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