1 /**
2 * Copyright (c) 2024 Bosch Sensortec GmbH. All rights reserved.
3 *
4 * accel_bmi270.c as part of the * /chipsets subdirectory
5 * is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option.
7 * See the LICENSE file in the root of this repository for complete details.
8 */
9
10 #include "accel_bmi270.h"
11 #include <securec.h>
12 #include "osal_mem.h"
13 #include "osal_time.h"
14 #include "sensor_accel_driver.h"
15 #include "sensor_config_controller.h"
16 #include "sensor_device_manager.h"
17
18 #define HDF_LOG_TAG khdf_sensor_accel_driver
19 static struct Bmi270DrvData *g_bmi270DrvData = NULL;
20 //328 bytes
21 static uint8_t g_regw_buffer[512];
22
23 /* IO config for int-pin and I2C-pin */
24 #define SENSOR_I2C6_DATA_REG_ADDR 0x114f004c
25 #define SENSOR_I2C6_CLK_REG_ADDR 0x114f0048
26 #define SENSOR_I2C_REG_CFG 0x403
27
28 static uint8_t bmi270_cfg_buffer[] = {
29 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x1a, 0x00, 0xc8, 0x2e, 0x00, 0x2e,
30 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e,
31 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0x90, 0x32, 0x21, 0x2e,
32 0x59, 0xf5, 0x10, 0x30, 0x21, 0x2e, 0x6a, 0xf5, 0x1a, 0x24, 0x22, 0x00,
33 0x80, 0x2e, 0x3b, 0x00, 0xc8, 0x2e, 0x44, 0x47, 0x22, 0x00, 0x37, 0x00,
34 0xa4, 0x00, 0xff, 0x0f, 0xd1, 0x00, 0x07, 0xad, 0x80, 0x2e, 0x00, 0xc1,
35 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
36 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
37 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
38 0x80, 0x2e, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x24,
39 0xfc, 0xf5, 0x80, 0x30, 0x40, 0x42, 0x50, 0x50, 0x00, 0x30, 0x12, 0x24,
40 0xeb, 0x00, 0x03, 0x30, 0x00, 0x2e, 0xc1, 0x86, 0x5a, 0x0e, 0xfb, 0x2f,
41 0x21, 0x2e, 0xfc, 0xf5, 0x13, 0x24, 0x63, 0xf5, 0xe0, 0x3c, 0x48, 0x00,
42 0x22, 0x30, 0xf7, 0x80, 0xc2, 0x42, 0xe1, 0x7f, 0x3a, 0x25, 0xfc, 0x86,
43 0xf0, 0x7f, 0x41, 0x33, 0x98, 0x2e, 0xc2, 0xc4, 0xd6, 0x6f, 0xf1, 0x30,
44 0xf1, 0x08, 0xc4, 0x6f, 0x11, 0x24, 0xff, 0x03, 0x12, 0x24, 0x00, 0xfc,
45 0x61, 0x09, 0xa2, 0x08, 0x36, 0xbe, 0x2a, 0xb9, 0x13, 0x24, 0x38, 0x00,
46 0x64, 0xbb, 0xd1, 0xbe, 0x94, 0x0a, 0x71, 0x08, 0xd5, 0x42, 0x21, 0xbd,
47 0x91, 0xbc, 0xd2, 0x42, 0xc1, 0x42, 0x00, 0xb2, 0xfe, 0x82, 0x05, 0x2f,
48 0x50, 0x30, 0x21, 0x2e, 0x21, 0xf2, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e,
49 0xf0, 0x6f, 0x02, 0x30, 0x02, 0x42, 0x20, 0x26, 0xe0, 0x6f, 0x02, 0x31,
50 0x03, 0x40, 0x9a, 0x0a, 0x02, 0x42, 0xf0, 0x37, 0x05, 0x2e, 0x5e, 0xf7,
51 0x10, 0x08, 0x12, 0x24, 0x1e, 0xf2, 0x80, 0x42, 0x83, 0x84, 0xf1, 0x7f,
52 0x0a, 0x25, 0x13, 0x30, 0x83, 0x42, 0x3b, 0x82, 0xf0, 0x6f, 0x00, 0x2e,
53 0x00, 0x2e, 0xd0, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40,
54 0x52, 0x42, 0x3e, 0x84, 0x00, 0x40, 0x40, 0x42, 0x7e, 0x82, 0xe1, 0x7f,
55 0xf2, 0x7f, 0x98, 0x2e, 0x6a, 0xd6, 0x21, 0x30, 0x23, 0x2e, 0x61, 0xf5,
56 0xeb, 0x2c, 0xe1, 0x6f
57 };
58 //328 bytes
59
Bmi270GetDrvData(void)60 static struct Bmi270DrvData *Bmi270GetDrvData(void)
61 {
62 return g_bmi270DrvData;
63 }
64
65 /// @brief basic register write function
66 /// @param data Sensor configuration data structre pointer
67 /// @param rega register address
68 /// @param buffer value to write
69 /// @param len write len
70 /// @return HDF_SUCCESS if success, failed any error
AccBmi270HalRegWrite(struct SensorCfgData *data, uint16_t rega, uint8_t* buffer, uint32_t len)71 static int32_t AccBmi270HalRegWrite(struct SensorCfgData *data, uint16_t rega, uint8_t* buffer, uint32_t len)
72 {
73 int32_t rc = HDF_SUCCESS;
74 uint32_t idx = 0;
75 (void)memset_s(g_regw_buffer, sizeof(g_regw_buffer), 0, sizeof(g_regw_buffer));
76
77 g_regw_buffer[0] = (rega & 0xFF);
78 do {
79 g_regw_buffer[idx + 1] = buffer[idx];
80 idx ++;
81 } while (idx < len);
82
83 rc = WriteSensor(&data->busCfg, g_regw_buffer, (len + 1));
84 OsalUDelay(BMI270_LP_MODE_WRITE_DELAY_IN_US);
85
86 if (rc != HDF_SUCCESS) {
87 HDF_LOGE("%s: [BMI270] w reg:%d err", __func__, rega);
88 }
89
90 return rc;
91 }
92
93 /// @brief basic register read function
94 /// @param data Sensor configuration data structre pointer
95 /// @param rega register address to read
96 /// @param buffer read data buffer
97 /// @param len read len
98 /// @return HDF_SUCCESS if success, failed any error
AccBmi270HalRegRead(struct SensorCfgData *data, uint16_t rega, uint8_t* buffer, uint32_t len)99 static int32_t AccBmi270HalRegRead(struct SensorCfgData *data, uint16_t rega, uint8_t* buffer, uint32_t len)
100 {
101 int32_t rc = HDF_SUCCESS;
102 rc = ReadSensor(&data->busCfg, rega, buffer, len);
103
104 OsalUDelay(BMI270_NORMAL_MODE_WRITE_DELAY_IN_US);
105 if (rc != HDF_SUCCESS) {
106 HDF_LOGE("%s: [BMI270] r reg:%d err", __func__, rega);
107 }
108
109 return rc;
110 }
111
AccReadBmi270RawData(struct SensorCfgData *data, struct AccelData *rawData, int64_t *timestamp)112 static int32_t AccReadBmi270RawData(struct SensorCfgData *data, struct AccelData *rawData, int64_t *timestamp)
113 {
114 OsalTimespec time;
115 uint8_t status = 0;
116 uint8_t regv[ACCEL_AXIS_BUTT] = {0};
117 int32_t ret = HDF_SUCCESS;
118
119 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
120 (void)memset_s(regv, sizeof(regv), 0, sizeof(regv));
121
122 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
123
124 if (OsalGetTime(&time) != HDF_SUCCESS) {
125 HDF_LOGE("%s: Get time failed", __func__);
126 return HDF_FAILURE;
127 }
128 *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */
129
130 ret = AccBmi270HalRegRead(data, BMI270_ACCEL_REGA_STATUS, &status, sizeof(uint8_t));
131 /* any new data? */
132 if (!(status & BMI270_ACCEL_DATA_READY_MASK) || (ret != HDF_SUCCESS)) {
133 HDF_LOGI("%s: data status [%hhu] ret [%d]", __func__, status, ret);
134 return HDF_FAILURE;
135 }
136
137 ret = AccBmi270HalRegRead(data, BMI270_ACCEL_REGA_X_LSB_ADDR, regv, BMI270_ACC_DATA_FRAME_SIZE);
138
139 rawData->x = (int16_t)(SENSOR_DATA_SHIFT_LEFT(regv[ACCEL_X_AXIS_MSB], SENSOR_DATA_WIDTH_8_BIT) |
140 regv[ACCEL_X_AXIS_LSB]);
141 rawData->y = (int16_t)(SENSOR_DATA_SHIFT_LEFT(regv[ACCEL_Y_AXIS_MSB], SENSOR_DATA_WIDTH_8_BIT) |
142 regv[ACCEL_Y_AXIS_LSB]);
143 rawData->z = (int16_t)(SENSOR_DATA_SHIFT_LEFT(regv[ACCEL_Z_AXIS_MSB], SENSOR_DATA_WIDTH_8_BIT) |
144 regv[ACCEL_Z_AXIS_LSB]);
145
146 return ret;
147 }
148
AccReadBmi270Data(struct SensorCfgData *cfg, struct SensorReportEvent *event)149 static int32_t AccReadBmi270Data(struct SensorCfgData *cfg, struct SensorReportEvent *event)
150 {
151 int32_t ret;
152 struct AccelData rawData = { 0, 0, 0 };
153 static int32_t tmp[ACCEL_AXIS_NUM];
154
155 CHECK_NULL_PTR_RETURN_VALUE(cfg, HDF_ERR_INVALID_PARAM);
156 CHECK_NULL_PTR_RETURN_VALUE(event, HDF_ERR_INVALID_PARAM);
157
158 ret = AccReadBmi270RawData(cfg, &rawData, (int64_t *)&event->timestamp);
159 if (ret != HDF_SUCCESS) {
160 HDF_LOGE("%s: BMI270 read raw data failed", __func__);
161 return HDF_FAILURE;
162 }
163 event->sensorId = SENSOR_TAG_ACCELEROMETER;
164 event->option = 0;
165 event->mode = SENSOR_WORK_MODE_REALTIME;
166
167 rawData.x = rawData.x * BMI270_ACC_SENSITIVITY_2G;
168 rawData.y = rawData.y * BMI270_ACC_SENSITIVITY_2G;
169 rawData.z = rawData.z * BMI270_ACC_SENSITIVITY_2G;
170
171 tmp[ACCEL_X_AXIS] = (rawData.x * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
172 tmp[ACCEL_Y_AXIS] = (rawData.y * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
173 tmp[ACCEL_Z_AXIS] = (rawData.z * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
174
175
176 ret = SensorRawDataToRemapData(cfg->direction, tmp, sizeof(tmp) / sizeof(tmp[0]));
177 if (ret != HDF_SUCCESS) {
178 HDF_LOGE("%s: BMI270 convert raw data failed", __func__);
179 return HDF_FAILURE;
180 }
181
182 event->dataLen = sizeof(tmp);
183 event->data = (uint8_t *)&tmp;
184
185 return ret;
186 }
187
188 // success
Bmi270IMUSwReset(struct SensorCfgData* data)189 static int32_t Bmi270IMUSwReset(struct SensorCfgData* data)
190 {
191 uint8_t regv = BMI26X_REGV_CMD_SOFT_RESET;
192 int32_t rc = AccBmi270HalRegWrite(data, BMI26X_REGA_USR_CMD, ®v, BMI270_ONE_BYTE);
193 OsalMDelay(BMI270_RESET_DELAY_IN_MS);
194
195 return rc;
196 }
197
Bmi270HalIMUInited(struct SensorCfgData *data)198 static bool Bmi270HalIMUInited(struct SensorCfgData *data)
199 {
200 bool rc = false;
201 uint8_t regv = 0;
202
203 rc = AccBmi270HalRegRead(data, BMI270_REGA_INTERNAL_STATUS, ®v, BMI270_ONE_BYTE);
204 if (BST_GET_VAL_BIT(regv, 0)) {
205 HDF_LOGI("[BMI270] %s, IMU inited", __LINE__);
206 rc = true;
207 }
208
209 return rc;
210 }
211
Bmi270CfgAccPwr(struct SensorCfgData *data, bool en)212 static int32_t Bmi270CfgAccPwr(struct SensorCfgData *data, bool en)
213 {
214 uint8_t regv = 0;
215 int32_t rc = HDF_SUCCESS;
216 rc = AccBmi270HalRegRead(data, BMI270_REGA_PWR_CTRL, ®v, BMI270_ONE_BYTE);
217
218 if (en) {
219 regv = BST_SET_VAL_BIT(regv, BMI270_ACC_POWER_BIT_POS_IN_PWR_CTRL_REG);
220 } else {
221 regv = BST_CLR_VAL_BIT(regv, BMI270_ACC_POWER_BIT_POS_IN_PWR_CTRL_REG);
222 }
223
224 rc = AccBmi270HalRegWrite(data, BMI270_REGA_PWR_CTRL, ®v, BMI270_ONE_BYTE);
225
226 return rc;
227 }
228
229 // @load configuration
Bmi270LoadCfg(struct SensorCfgData *data, uint8_t* cfg_data_buffer, uint32_t cfg_size, uint32_t in_burst_write_size)230 static int32_t Bmi270LoadCfg(struct SensorCfgData *data, uint8_t* cfg_data_buffer,
231 uint32_t cfg_size, uint32_t in_burst_write_size)
232 {
233 int32_t rc = HDF_SUCCESS;
234 uint8_t regv = 0;
235 /* Variable to update the configuration file index */
236 uint16_t index = 0;
237 /* Array to store address */
238 uint8_t addr_array[2] = {0};
239 uint32_t size_bw = in_burst_write_size; //burst write size in byte
240
241 /* Disable loading of the configuration */
242 rc = AccBmi270HalRegWrite(data, BMI26X_REGA_USR_TITAN_CTRL, ®v, BMI270_ONE_BYTE);
243
244 for (index = 0; index < cfg_size; index += size_bw) {
245 //1. len
246 if (index + in_burst_write_size > cfg_size) {
247 size_bw = cfg_size - index;
248 }
249
250 // index low in word
251 addr_array[0] = (uint8_t)((index / 2) & 0x0F);
252 // ndex high in word
253 addr_array[1] = (uint8_t)((index / 2) >> 4);
254 rc = AccBmi270HalRegWrite(data, BMI26X_REGA_USR_CONF_STREAM_IDX_LSB, addr_array, BMI270_TWO_BYTE);
255
256 //2. data
257 rc = AccBmi270HalRegWrite(data, BMI26X_REGA_USR_CONF_STREAM_IN,
258 cfg_data_buffer + index, size_bw);
259 }
260
261 return rc;
262 }
263
Bmi270HalLoadCfg(struct SensorCfgData *data)264 static int32_t Bmi270HalLoadCfg(struct SensorCfgData *data)
265 {
266 int32_t rc = HDF_SUCCESS;
267 uint8_t regv = 0;
268 uint8_t try_num_to_check_cfg = 0;
269 bool cfg_is_avaiblabe = Bmi270HalIMUInited(data);
270 if (cfg_is_avaiblabe) {
271 return HDF_SUCCESS;
272 }
273
274 rc = Bmi270IMUSwReset(data);
275 if (rc != HDF_SUCCESS) {
276 return rc;
277 }
278
279 //disable advance power saving
280 rc = AccBmi270HalRegWrite(data, BMI270_REGA_PWR_CFG, ®v, BMI270_ONE_BYTE);
281
282 // load configuration now
283 rc = Bmi270LoadCfg(data, bmi270_cfg_buffer,
284 HDF_ARRAY_SIZE(bmi270_cfg_buffer),
285 HDF_ARRAY_SIZE(bmi270_cfg_buffer));
286
287 regv = 0x01;
288 rc = AccBmi270HalRegWrite(data, BMI26X_REGA_USR_TITAN_CTRL, ®v, BMI270_ONE_BYTE);
289
290 cfg_is_avaiblabe = false;
291 rc = HDF_DEV_ERR_DEV_INIT_FAIL;
292 do {
293 OsalMDelay(BMI270_LOAD_RAM_PATCH_DELAY_IN_MS);
294 cfg_is_avaiblabe = Bmi270HalIMUInited(data);
295 try_num_to_check_cfg ++;
296 if (cfg_is_avaiblabe) {
297 rc = HDF_SUCCESS;
298 break;
299 }
300 } while ((try_num_to_check_cfg < BMI26X_CHECK_CONFIGURE_STATUS_TIMES) &&
301 (!cfg_is_avaiblabe));
302
303 return rc;
304 }
305
Bmi270GetWhoAmI(struct SensorCfgData *data)306 static int32_t Bmi270GetWhoAmI(struct SensorCfgData *data)
307 {
308 uint8_t regv = 0;
309 int32_t rc = HDF_SUCCESS;
310
311 rc = AccBmi270HalRegRead(data, 0x00, ®v, BMI270_ONE_BYTE);
312 if (rc != HDF_SUCCESS) {
313 HDF_LOGE("%s: [BMI270] WARN!!, NO Sensor", __func__);
314 return HDF_FAILURE;
315 }
316
317 if (regv != BMI26X_REGV_WHOAMI) {
318 rc = HDF_DEV_ERR_NO_DEVICE;
319 }
320
321 return rc;
322 }
323
InitBmi270(struct SensorCfgData *data)324 static int32_t InitBmi270(struct SensorCfgData *data)
325 {
326 int32_t ret = HDF_SUCCESS;
327 uint8_t regv = 0x00;
328
329 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
330 ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);
331 if (ret != HDF_SUCCESS) {
332 HDF_LOGE("%s: BMI270 sensor init config failed", __func__);
333 return HDF_FAILURE;
334 }
335
336 ret = Bmi270CfgAccPwr(data, true);
337 //defualt odr:100hz
338 // range:+/- 2G
339 regv = 0;
340 ret = AccBmi270HalRegWrite(data, BMI26X_REGA_ACC_RANGE, ®v, BMI270_ONE_BYTE);
341
342 return ret;
343 }
344
DispatchBmi270(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)345 static int32_t DispatchBmi270(struct HdfDeviceIoClient *client,
346 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
347 {
348 (void)client;
349 (void)cmd;
350 (void)data;
351 (void)reply;
352
353 return HDF_SUCCESS;
354 }
355
Bmi270BindDriver(struct HdfDeviceObject *device)356 static int32_t Bmi270BindDriver(struct HdfDeviceObject *device)
357 {
358 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
359
360 struct Bmi270DrvData *drvData = (struct Bmi270DrvData *)OsalMemCalloc(sizeof(*drvData));
361 if (drvData == NULL) {
362 HDF_LOGE("%s: Malloc Bmi270 drv data fail", __func__);
363 return HDF_ERR_MALLOC_FAIL;
364 }
365
366 drvData->ioService.Dispatch = DispatchBmi270;
367 drvData->device = device;
368 device->service = &drvData->ioService;
369 g_bmi270DrvData = drvData;
370
371 return HDF_SUCCESS;
372 }
373
Bmi270InitDriver(struct HdfDeviceObject *device)374 static int32_t Bmi270InitDriver(struct HdfDeviceObject *device)
375 {
376 int32_t ret;
377 struct AccelOpsCall ops;
378
379 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
380 struct Bmi270DrvData *drvData = (struct Bmi270DrvData *)device->service;
381 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
382
383 drvData->sensorCfg = AccelCreateCfgData(device->property);
384 if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
385 HDF_LOGD("%s: Creating accelcfg failed because detection failed", __func__);
386 return HDF_ERR_NOT_SUPPORT;
387 }
388
389 ops.Init = NULL;
390 ops.ReadData = AccReadBmi270Data;
391 ret = AccelRegisterChipOps(&ops);
392 if (ret != HDF_SUCCESS) {
393 HDF_LOGE("%s: Register BMI270 accel failed", __func__);
394 return HDF_FAILURE;
395 }
396
397 // check whoami
398 ret = Bmi270GetWhoAmI(drvData->sensorCfg);
399 if (ret != HDF_SUCCESS) {
400 return ret;
401 }
402
403 do {
404 ret = Bmi270HalLoadCfg(drvData->sensorCfg);
405 } while (0);
406
407 // init hw
408 ret = InitBmi270(drvData->sensorCfg);
409 if (ret != HDF_SUCCESS) {
410 HDF_LOGE("%s: Init BMI270 accel failed", __func__);
411 return HDF_FAILURE;
412 }
413
414 return HDF_SUCCESS;
415 }
416
Bmi270ReleaseDriver(struct HdfDeviceObject *device)417 static void Bmi270ReleaseDriver(struct HdfDeviceObject *device)
418 {
419 CHECK_NULL_PTR_RETURN(device);
420
421 struct Bmi270DrvData *drvData = (struct Bmi270DrvData *)device->service;
422 CHECK_NULL_PTR_RETURN(drvData);
423
424 if (drvData->sensorCfg != NULL) {
425 AccelReleaseCfgData(drvData->sensorCfg);
426 drvData->sensorCfg = NULL;
427 }
428 OsalMemFree(drvData);
429 }
430
431 struct HdfDriverEntry g_accelBmi270DevEntry = {
432 .moduleVersion = 1,
433 .moduleName = "HDF_SENSOR_ACCEL_BMI270",
434 .Bind = Bmi270BindDriver,
435 .Init = Bmi270InitDriver,
436 .Release = Bmi270ReleaseDriver,
437 };
438
439 HDF_INIT(g_accelBmi270DevEntry);
440