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, &regv, 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, &regv, 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, &regv, 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, &regv, 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, &regv, 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, &regv, 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, &regv, 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, &regv, 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, &regv, 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