1 /*
2 * Copyright (c) 2020 TDK Invensense
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/sys/byteorder.h>
8 #include <zephyr/drivers/sensor.h>
9 #include <zephyr/logging/log.h>
10
11 #include "icm42605.h"
12 #include "icm42605_reg.h"
13 #include "icm42605_spi.h"
14
15 LOG_MODULE_DECLARE(ICM42605, CONFIG_SENSOR_LOG_LEVEL);
16
icm42605_set_fs(const struct device * dev,uint16_t a_sf,uint16_t g_sf)17 int icm42605_set_fs(const struct device *dev, uint16_t a_sf, uint16_t g_sf)
18 {
19 const struct icm42605_config *cfg = dev->config;
20 uint8_t databuf;
21 int result;
22
23 result = inv_spi_read(&cfg->spi, REG_ACCEL_CONFIG0, &databuf, 1);
24 if (result) {
25 return result;
26 }
27 databuf &= ~BIT_ACCEL_FSR;
28
29 databuf |= a_sf;
30
31 result = inv_spi_single_write(&cfg->spi, REG_ACCEL_CONFIG0, &databuf);
32
33 result = inv_spi_read(&cfg->spi, REG_GYRO_CONFIG0, &databuf, 1);
34
35 if (result) {
36 return result;
37 }
38
39 databuf &= ~BIT_GYRO_FSR;
40 databuf |= g_sf;
41
42 result = inv_spi_single_write(&cfg->spi, REG_GYRO_CONFIG0, &databuf);
43
44 if (result) {
45 return result;
46 }
47
48 return 0;
49 }
50
icm42605_set_odr(const struct device * dev,uint16_t a_rate,uint16_t g_rate)51 int icm42605_set_odr(const struct device *dev, uint16_t a_rate, uint16_t g_rate)
52 {
53 const struct icm42605_config *cfg = dev->config;
54 uint8_t databuf;
55 int result;
56
57 if (a_rate > 8000 || g_rate > 8000 ||
58 a_rate < 1 || g_rate < 12) {
59 LOG_ERR("Not supported frequency");
60 return -ENOTSUP;
61 }
62
63 result = inv_spi_read(&cfg->spi, REG_ACCEL_CONFIG0, &databuf, 1);
64
65 if (result) {
66 return result;
67 }
68
69 databuf &= ~BIT_ACCEL_ODR;
70
71 if (a_rate > 4000) {
72 databuf |= BIT_ACCEL_ODR_8000;
73 } else if (a_rate > 2000) {
74 databuf |= BIT_ACCEL_ODR_4000;
75 } else if (a_rate > 1000) {
76 databuf |= BIT_ACCEL_ODR_2000;
77 } else if (a_rate > 500) {
78 databuf |= BIT_ACCEL_ODR_1000;
79 } else if (a_rate > 200) {
80 databuf |= BIT_ACCEL_ODR_500;
81 } else if (a_rate > 100) {
82 databuf |= BIT_ACCEL_ODR_200;
83 } else if (a_rate > 50) {
84 databuf |= BIT_ACCEL_ODR_100;
85 } else if (a_rate > 25) {
86 databuf |= BIT_ACCEL_ODR_50;
87 } else if (a_rate > 12) {
88 databuf |= BIT_ACCEL_ODR_25;
89 } else if (a_rate > 6) {
90 databuf |= BIT_ACCEL_ODR_12;
91 } else if (a_rate > 3) {
92 databuf |= BIT_ACCEL_ODR_6;
93 } else if (a_rate > 1) {
94 databuf |= BIT_ACCEL_ODR_3;
95 } else {
96 databuf |= BIT_ACCEL_ODR_1;
97 }
98
99 result = inv_spi_single_write(&cfg->spi, REG_ACCEL_CONFIG0, &databuf);
100
101 if (result) {
102 return result;
103 }
104
105 LOG_DBG("Write Accel ODR 0x%X", databuf);
106
107 result = inv_spi_read(&cfg->spi, REG_GYRO_CONFIG0, &databuf, 1);
108
109 if (result) {
110 return result;
111 }
112
113 databuf &= ~BIT_GYRO_ODR;
114
115 if (g_rate > 4000) {
116 databuf |= BIT_GYRO_ODR_8000;
117 } else if (g_rate > 2000) {
118 databuf |= BIT_GYRO_ODR_4000;
119 } else if (g_rate > 1000) {
120 databuf |= BIT_GYRO_ODR_2000;
121 } else if (g_rate > 500) {
122 databuf |= BIT_GYRO_ODR_1000;
123 } else if (g_rate > 200) {
124 databuf |= BIT_GYRO_ODR_500;
125 } else if (g_rate > 100) {
126 databuf |= BIT_GYRO_ODR_200;
127 } else if (g_rate > 50) {
128 databuf |= BIT_GYRO_ODR_100;
129 } else if (g_rate > 25) {
130 databuf |= BIT_GYRO_ODR_50;
131 } else if (g_rate > 12) {
132 databuf |= BIT_GYRO_ODR_25;
133 } else {
134 databuf |= BIT_GYRO_ODR_12;
135 }
136
137 LOG_DBG("Write GYRO ODR 0x%X", databuf);
138
139 result = inv_spi_single_write(&cfg->spi, REG_GYRO_CONFIG0, &databuf);
140 if (result) {
141 return result;
142 }
143
144 return result;
145 }
146
icm42605_sensor_init(const struct device * dev)147 int icm42605_sensor_init(const struct device *dev)
148 {
149 const struct icm42605_config *cfg = dev->config;
150 int result = 0;
151 uint8_t v;
152
153 result = inv_spi_read(&cfg->spi, REG_WHO_AM_I, &v, 1);
154
155 if (result) {
156 return result;
157 }
158
159 LOG_DBG("WHO AM I : 0x%X", v);
160
161 result = inv_spi_read(&cfg->spi, REG_DEVICE_CONFIG, &v, 1);
162
163 if (result) {
164 LOG_DBG("read REG_DEVICE_CONFIG_REG failed");
165 return result;
166 }
167
168 v |= BIT_SOFT_RESET;
169
170 result = inv_spi_single_write(&cfg->spi, REG_DEVICE_CONFIG, &v);
171
172 if (result) {
173 LOG_ERR("write REG_DEVICE_CONFIG failed");
174 return result;
175 }
176
177 /* Need at least 10ms after soft reset */
178 k_msleep(10);
179
180 v = BIT_GYRO_AFSR_MODE_HFS | BIT_ACCEL_AFSR_MODE_HFS | BIT_CLK_SEL_PLL;
181
182 result = inv_spi_single_write(&cfg->spi, REG_INTF_CONFIG1, &v);
183
184 if (result) {
185 LOG_ERR("write REG_INTF_CONFIG1 failed");
186 return result;
187 }
188
189 v = BIT_EN_DREG_FIFO_D2A |
190 BIT_TMST_TO_REGS_EN |
191 BIT_TMST_EN;
192
193 result = inv_spi_single_write(&cfg->spi, REG_TMST_CONFIG, &v);
194
195 if (result) {
196 LOG_ERR("Write REG_TMST_CONFIG failed");
197 return result;
198 }
199
200 result = inv_spi_read(&cfg->spi, REG_INTF_CONFIG0, &v, 1);
201
202 if (result) {
203 LOG_ERR("Read REG_INTF_CONFIG0 failed");
204 return result;
205 }
206
207 LOG_DBG("Read REG_INTF_CONFIG0 0x%X", v);
208
209 v |= BIT_UI_SIFS_DISABLE_I2C;
210
211 result = inv_spi_single_write(&cfg->spi, REG_INTF_CONFIG0, &v);
212
213 if (result) {
214 LOG_ERR("Write REG_INTF_CONFIG failed");
215 return result;
216 }
217
218 v = 0;
219 result = inv_spi_single_write(&cfg->spi, REG_INT_CONFIG1, &v);
220
221 if (result) {
222 return result;
223 }
224
225 result = inv_spi_single_write(&cfg->spi, REG_PWR_MGMT0, &v);
226
227 if (result) {
228 return result;
229 }
230
231 return 0;
232 }
233
icm42605_turn_on_fifo(const struct device * dev)234 int icm42605_turn_on_fifo(const struct device *dev)
235 {
236 const struct icm42605_data *drv_data = dev->data;
237 const struct icm42605_config *cfg = dev->config;
238
239 uint8_t int0_en = BIT_INT_UI_DRDY_INT1_EN;
240 uint8_t fifo_en = BIT_FIFO_ACCEL_EN | BIT_FIFO_GYRO_EN | BIT_FIFO_WM_TH;
241 uint8_t burst_read[3];
242 int result;
243 uint8_t v = 0;
244
245 v = BIT_FIFO_MODE_BYPASS;
246 result = inv_spi_single_write(&cfg->spi, REG_FIFO_CONFIG, &v);
247 if (result) {
248 return result;
249 }
250
251 v = 0;
252 result = inv_spi_single_write(&cfg->spi, REG_FIFO_CONFIG1, &v);
253 if (result) {
254 return result;
255 }
256
257 result = inv_spi_read(&cfg->spi, REG_FIFO_COUNTH, burst_read, 2);
258 if (result) {
259 return result;
260 }
261
262 result = inv_spi_read(&cfg->spi, REG_FIFO_DATA, burst_read, 3);
263 if (result) {
264 return result;
265 }
266
267 v = BIT_FIFO_MODE_STREAM;
268 result = inv_spi_single_write(&cfg->spi, REG_FIFO_CONFIG, &v);
269 if (result) {
270 return result;
271 }
272
273 result = inv_spi_single_write(&cfg->spi, REG_FIFO_CONFIG1, &fifo_en);
274 if (result) {
275 return result;
276 }
277
278 result = inv_spi_single_write(&cfg->spi, REG_INT_SOURCE0, &int0_en);
279 if (result) {
280 return result;
281 }
282
283 if (drv_data->tap_en) {
284 v = BIT_TAP_ENABLE;
285 result = inv_spi_single_write(&cfg->spi, REG_APEX_CONFIG0, &v);
286 if (result) {
287 return result;
288 }
289
290 v = BIT_DMP_INIT_EN;
291 result = inv_spi_single_write(&cfg->spi, REG_SIGNAL_PATH_RESET, &v);
292 if (result) {
293 return result;
294 }
295
296 v = BIT_BANK_SEL_4;
297 result = inv_spi_single_write(&cfg->spi, REG_BANK_SEL, &v);
298 if (result) {
299 return result;
300 }
301
302 v = BIT_INT_STATUS_TAP_DET;
303 result = inv_spi_single_write(&cfg->spi, REG_INT_SOURCE6, &v);
304 if (result) {
305 return result;
306 }
307
308 v = BIT_BANK_SEL_0;
309 result = inv_spi_single_write(&cfg->spi, REG_BANK_SEL, &v);
310 if (result) {
311 return result;
312 }
313 }
314
315 LOG_DBG("turn on fifo done");
316 return 0;
317 }
318
icm42605_turn_off_fifo(const struct device * dev)319 int icm42605_turn_off_fifo(const struct device *dev)
320 {
321 const struct icm42605_data *drv_data = dev->data;
322 const struct icm42605_config *cfg = dev->config;
323 uint8_t int0_en = 0;
324 uint8_t burst_read[3];
325 int result;
326 uint8_t v = 0;
327
328 v = BIT_FIFO_MODE_BYPASS;
329 result = inv_spi_single_write(&cfg->spi, REG_FIFO_CONFIG, &v);
330 if (result) {
331 return result;
332 }
333
334 v = 0;
335 result = inv_spi_single_write(&cfg->spi, REG_FIFO_CONFIG1, &v);
336 if (result) {
337 return result;
338 }
339
340 result = inv_spi_read(&cfg->spi, REG_FIFO_COUNTH, burst_read, 2);
341 if (result) {
342 return result;
343 }
344
345 result = inv_spi_read(&cfg->spi, REG_FIFO_DATA, burst_read, 3);
346 if (result) {
347 return result;
348 }
349
350 result = inv_spi_single_write(&cfg->spi, REG_INT_SOURCE0, &int0_en);
351 if (result) {
352 return result;
353 }
354
355 if (drv_data->tap_en) {
356 v = 0;
357 result = inv_spi_single_write(&cfg->spi, REG_APEX_CONFIG0, &v);
358 if (result) {
359 return result;
360 }
361
362 result = inv_spi_single_write(&cfg->spi, REG_SIGNAL_PATH_RESET, &v);
363 if (result) {
364 return result;
365 }
366
367 v = BIT_BANK_SEL_4;
368 result = inv_spi_single_write(&cfg->spi, REG_BANK_SEL, &v);
369 if (result) {
370 return result;
371 }
372
373 v = 0;
374 result = inv_spi_single_write(&cfg->spi, REG_INT_SOURCE6, &v);
375 if (result) {
376 return result;
377 }
378
379 v = BIT_BANK_SEL_0;
380 result = inv_spi_single_write(&cfg->spi, REG_BANK_SEL, &v);
381 if (result) {
382 return result;
383 }
384 }
385
386 return 0;
387 }
388
icm42605_turn_on_sensor(const struct device * dev)389 int icm42605_turn_on_sensor(const struct device *dev)
390 {
391 struct icm42605_data *drv_data = dev->data;
392 const struct icm42605_config *cfg = dev->config;
393 uint8_t v = 0;
394 int result = 0;
395
396
397 if (drv_data->sensor_started) {
398 LOG_ERR("Sensor already started");
399 return -EALREADY;
400 }
401
402 icm42605_set_fs(dev, drv_data->accel_sf, drv_data->gyro_sf);
403
404 icm42605_set_odr(dev, drv_data->accel_hz, drv_data->gyro_hz);
405
406 v |= BIT_ACCEL_MODE_LNM;
407 v |= BIT_GYRO_MODE_LNM;
408
409 result = inv_spi_single_write(&cfg->spi, REG_PWR_MGMT0, &v);
410 if (result) {
411 return result;
412 }
413
414 /* Accelerometer sensor need at least 10ms startup time
415 * Gyroscope sensor need at least 30ms startup time
416 */
417 k_msleep(100);
418
419 icm42605_turn_on_fifo(dev);
420
421 drv_data->sensor_started = true;
422
423 return 0;
424 }
425
icm42605_turn_off_sensor(const struct device * dev)426 int icm42605_turn_off_sensor(const struct device *dev)
427 {
428 const struct icm42605_config *cfg = dev->config;
429 uint8_t v = 0;
430 int result = 0;
431
432 result = inv_spi_read(&cfg->spi, REG_PWR_MGMT0, &v, 1);
433
434 v ^= BIT_ACCEL_MODE_LNM;
435 v ^= BIT_GYRO_MODE_LNM;
436
437 result = inv_spi_single_write(&cfg->spi, REG_PWR_MGMT0, &v);
438 if (result) {
439 return result;
440 }
441
442 /* Accelerometer sensor need at least 10ms startup time
443 * Gyroscope sensor need at least 30ms startup time
444 */
445 k_msleep(100);
446
447 icm42605_turn_off_fifo(dev);
448
449 return 0;
450 }
451