1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "accel_bmi160.h"
10 #include <securec.h>
11 #include "osal_mem.h"
12 #include "osal_time.h"
13 #include "sensor_accel_driver.h"
14 #include "sensor_config_controller.h"
15 #include "sensor_device_manager.h"
16
17 #define HDF_LOG_TAG khdf_sensor_accel_driver
18
19 static struct Bmi160DrvData *g_bmi160DrvData = NULL;
20
21 /* IO config for int-pin and I2C-pin */
22 #define SENSOR_I2C6_DATA_REG_ADDR 0x114f004c
23 #define SENSOR_I2C6_CLK_REG_ADDR 0x114f0048
24 #define SENSOR_I2C_REG_CFG 0x403
25
ReadBmi160RawData(struct SensorCfgData * data,struct AccelData * rawData,uint64_t * timestamp)26 static int32_t ReadBmi160RawData(struct SensorCfgData *data, struct AccelData *rawData, uint64_t *timestamp)
27 {
28 uint8_t status = 0;
29 uint8_t reg[ACCEL_AXIS_BUTT];
30 OsalTimespec time;
31
32 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
33 (void)memset_s(reg, sizeof(reg), 0, sizeof(reg));
34
35 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
36
37 if (OsalGetTime(&time) != HDF_SUCCESS) {
38 HDF_LOGE("%s: Get time failed", __func__);
39 return HDF_FAILURE;
40 }
41 *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */
42
43 int32_t ret = ReadSensor(&data->busCfg, BMI160_STATUS_ADDR, &status, sizeof(uint8_t));
44 if (!(status & BMI160_ACCEL_DATA_READY_MASK) || (ret != HDF_SUCCESS)) {
45 HDF_LOGE("%s: data status [%hhu] ret [%d]", __func__, status, ret);
46 return HDF_FAILURE;
47 }
48
49 ret = ReadSensor(&data->busCfg, BMI160_ACCEL_X_LSB_ADDR, ®[ACCEL_X_AXIS_LSB], sizeof(uint8_t));
50 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
51
52 ret = ReadSensor(&data->busCfg, BMI160_ACCEL_X_MSB_ADDR, ®[ACCEL_X_AXIS_MSB], sizeof(uint8_t));
53 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
54
55 ret = ReadSensor(&data->busCfg, BMI160_ACCEL_Y_LSB_ADDR, ®[ACCEL_Y_AXIS_LSB], sizeof(uint8_t));
56 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
57
58 ret = ReadSensor(&data->busCfg, BMI160_ACCEL_Y_MSB_ADDR, ®[ACCEL_Y_AXIS_MSB], sizeof(uint8_t));
59 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
60
61 ret = ReadSensor(&data->busCfg, BMI160_ACCEL_Z_LSB_ADDR, ®[ACCEL_Z_AXIS_LSB], sizeof(uint8_t));
62 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
63
64 ret = ReadSensor(&data->busCfg, BMI160_ACCEL_Z_MSB_ADDR, ®[ACCEL_Z_AXIS_MSB], sizeof(uint8_t));
65 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
66
67 rawData->x = (int16_t)(SENSOR_DATA_SHIFT_LEFT(reg[ACCEL_X_AXIS_MSB], SENSOR_DATA_WIDTH_8_BIT) |
68 reg[ACCEL_X_AXIS_LSB]);
69 rawData->y = (int16_t)(SENSOR_DATA_SHIFT_LEFT(reg[ACCEL_Y_AXIS_MSB], SENSOR_DATA_WIDTH_8_BIT) |
70 reg[ACCEL_Y_AXIS_LSB]);
71 rawData->z = (int16_t)(SENSOR_DATA_SHIFT_LEFT(reg[ACCEL_Z_AXIS_MSB], SENSOR_DATA_WIDTH_8_BIT) |
72 reg[ACCEL_Z_AXIS_LSB]);
73
74 return HDF_SUCCESS;
75 }
76
ReadBmi160Data(struct SensorCfgData * cfg,struct SensorReportEvent * event)77 static int32_t ReadBmi160Data(struct SensorCfgData *cfg, struct SensorReportEvent *event)
78 {
79 int32_t ret;
80 struct AccelData rawData = { 0, 0, 0 };
81 static int32_t tmp[ACCEL_AXIS_NUM];
82
83 CHECK_NULL_PTR_RETURN_VALUE(cfg, HDF_ERR_INVALID_PARAM);
84 CHECK_NULL_PTR_RETURN_VALUE(event, HDF_ERR_INVALID_PARAM);
85
86 ret = ReadBmi160RawData(cfg, &rawData, &event->timestamp);
87 if (ret != HDF_SUCCESS) {
88 HDF_LOGE("%s: BMI160 read raw data failed", __func__);
89 return HDF_FAILURE;
90 }
91
92 event->sensorId = SENSOR_TAG_ACCELEROMETER;
93 event->option = 0;
94 event->mode = SENSOR_WORK_MODE_REALTIME;
95
96 rawData.x = rawData.x * BMI160_ACC_SENSITIVITY_2G;
97 rawData.y = rawData.y * BMI160_ACC_SENSITIVITY_2G;
98 rawData.z = rawData.z * BMI160_ACC_SENSITIVITY_2G;
99
100 tmp[ACCEL_X_AXIS] = (rawData.x * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
101 tmp[ACCEL_Y_AXIS] = (rawData.y * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
102 tmp[ACCEL_Z_AXIS] = (rawData.z * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
103
104 ret = SensorRawDataToRemapData(cfg->direction, tmp, sizeof(tmp) / sizeof(tmp[0]));
105 if (ret != HDF_SUCCESS) {
106 HDF_LOGE("%s: BMI160 convert raw data failed", __func__);
107 return HDF_FAILURE;
108 }
109
110 event->dataLen = sizeof(tmp);
111 event->data = (uint8_t *)&tmp;
112
113 return ret;
114 }
115
InitBmi160(struct SensorCfgData * data)116 static int32_t InitBmi160(struct SensorCfgData *data)
117 {
118 int32_t ret;
119
120 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
121 ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);
122 if (ret != HDF_SUCCESS) {
123 HDF_LOGE("%s: BMI160 sensor init config failed", __func__);
124 return HDF_FAILURE;
125 }
126 return HDF_SUCCESS;
127 }
128
InitAccelPreConfig(void)129 static int32_t InitAccelPreConfig(void)
130 {
131 if (SetSensorPinMux(SENSOR_I2C6_DATA_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) {
132 HDF_LOGE("%s: Data write mux pin failed", __func__);
133 return HDF_FAILURE;
134 }
135 if (SetSensorPinMux(SENSOR_I2C6_CLK_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) {
136 HDF_LOGE("%s: Clk write mux pin failed", __func__);
137 return HDF_FAILURE;
138 }
139
140 return HDF_SUCCESS;
141 }
142
DispatchBMI160(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)143 static int32_t DispatchBMI160(struct HdfDeviceIoClient *client,
144 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
145 {
146 (void)client;
147 (void)cmd;
148 (void)data;
149 (void)reply;
150
151 return HDF_SUCCESS;
152 }
153
Bmi160BindDriver(struct HdfDeviceObject * device)154 static int32_t Bmi160BindDriver(struct HdfDeviceObject *device)
155 {
156 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
157
158 struct Bmi160DrvData *drvData = (struct Bmi160DrvData *)OsalMemCalloc(sizeof(*drvData));
159 if (drvData == NULL) {
160 HDF_LOGE("%s: Malloc Bmi160 drv data fail", __func__);
161 return HDF_ERR_MALLOC_FAIL;
162 }
163
164 drvData->ioService.Dispatch = DispatchBMI160;
165 drvData->device = device;
166 device->service = &drvData->ioService;
167 g_bmi160DrvData = drvData;
168
169 return HDF_SUCCESS;
170 }
171
Bmi160InitDriver(struct HdfDeviceObject * device)172 static int32_t Bmi160InitDriver(struct HdfDeviceObject *device)
173 {
174 int32_t ret;
175 struct AccelOpsCall ops;
176
177 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
178 struct Bmi160DrvData *drvData = (struct Bmi160DrvData *)device->service;
179 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
180
181 ret = InitAccelPreConfig();
182 if (ret != HDF_SUCCESS) {
183 HDF_LOGE("%s: Init BMI160 bus mux config", __func__);
184 return HDF_FAILURE;
185 }
186
187 drvData->sensorCfg = AccelCreateCfgData(device->property);
188 if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
189 HDF_LOGD("%s: Creating accelcfg failed because detection failed", __func__);
190 return HDF_ERR_NOT_SUPPORT;
191 }
192
193 ops.Init = NULL;
194 ops.ReadData = ReadBmi160Data;
195 ret = AccelRegisterChipOps(&ops);
196 if (ret != HDF_SUCCESS) {
197 HDF_LOGE("%s: Register BMI160 accel failed", __func__);
198 return HDF_FAILURE;
199 }
200
201 ret = InitBmi160(drvData->sensorCfg);
202 if (ret != HDF_SUCCESS) {
203 HDF_LOGE("%s: Init BMI160 accel failed", __func__);
204 return HDF_FAILURE;
205 }
206
207 return HDF_SUCCESS;
208 }
209
Bmi160ReleaseDriver(struct HdfDeviceObject * device)210 static void Bmi160ReleaseDriver(struct HdfDeviceObject *device)
211 {
212 CHECK_NULL_PTR_RETURN(device);
213
214 struct Bmi160DrvData *drvData = (struct Bmi160DrvData *)device->service;
215 CHECK_NULL_PTR_RETURN(drvData);
216
217 if (drvData->sensorCfg != NULL) {
218 AccelReleaseCfgData(drvData->sensorCfg);
219 drvData->sensorCfg = NULL;
220 }
221 OsalMemFree(drvData);
222 }
223
224 struct HdfDriverEntry g_accelBmi160DevEntry = {
225 .moduleVersion = 1,
226 .moduleName = "HDF_SENSOR_ACCEL_BMI160",
227 .Bind = Bmi160BindDriver,
228 .Init = Bmi160InitDriver,
229 .Release = Bmi160ReleaseDriver,
230 };
231
232 HDF_INIT(g_accelBmi160DevEntry);
233