1 /*
2  * Copyright (c) 2024 TDK Invensense
3  * Copyright (c) 2022 Esco Medical ApS
4  * Copyright (c) 2020 TDK Invensense
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #ifndef ZEPHYR_DRIVERS_SENSOR_ICM42X70_H_
10 #define ZEPHYR_DRIVERS_SENSOR_ICM42X70_H_
11 
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/drivers/sensor.h>
14 #include <zephyr/drivers/spi.h>
15 #include <zephyr/drivers/i2c.h>
16 #include <zephyr/kernel.h>
17 
18 #include "imu/inv_imu_driver.h"
19 #ifdef CONFIG_TDK_APEX
20 #include "imu/inv_imu_apex.h"
21 #endif
22 
23 union icm42x70_bus {
24 #if CONFIG_SPI
25 	struct spi_dt_spec spi;
26 #endif
27 #if CONFIG_I2C
28 	struct i2c_dt_spec i2c;
29 #endif
30 };
31 
32 typedef int (*icm42x70_bus_check_fn)(const union icm42x70_bus *bus);
33 typedef int (*icm42x70_reg_read_fn)(const union icm42x70_bus *bus, uint8_t reg, uint8_t *buf,
34 				    uint32_t size);
35 typedef int (*icm42x70_reg_write_fn)(const union icm42x70_bus *bus, uint8_t reg, uint8_t *buf,
36 				     uint32_t size);
37 
38 struct icm42x70_bus_io {
39 	icm42x70_bus_check_fn check;
40 	icm42x70_reg_read_fn read;
41 	icm42x70_reg_write_fn write;
42 };
43 
44 #if CONFIG_SPI
45 extern const struct icm42x70_bus_io icm42x70_bus_io_spi;
46 #endif
47 
48 #if CONFIG_I2C
49 extern const struct icm42x70_bus_io icm42x70_bus_io_i2c;
50 #endif
51 
52 struct icm42x70_data {
53 	struct inv_imu_serif serif;
54 	struct inv_imu_device driver;
55 	uint8_t imu_whoami;
56 	char *imu_name;
57 	uint8_t chip_id;
58 	int32_t accel_x;
59 	int32_t accel_y;
60 	int32_t accel_z;
61 	uint16_t accel_hz;
62 	uint8_t accel_fs;
63 	uint8_t accel_pwr_mode;
64 #if CONFIG_USE_EMD_ICM42670
65 	int32_t gyro_x;
66 	int32_t gyro_y;
67 	int32_t gyro_z;
68 	uint16_t gyro_hz;
69 	uint16_t gyro_fs;
70 #endif
71 	int32_t temp;
72 #ifdef CONFIG_TDK_APEX
73 	uint8_t dmp_odr_hz;
74 	uint64_t pedometer_cnt;
75 	uint8_t pedometer_activity;
76 	uint8_t pedometer_cadence;
77 	uint8_t apex_status;
78 #endif
79 
80 #ifdef CONFIG_ICM42X70_TRIGGER
81 	const struct device *dev;
82 	struct gpio_callback gpio_cb;
83 	sensor_trigger_handler_t data_ready_handler;
84 	const struct sensor_trigger *data_ready_trigger;
85 	struct k_mutex mutex;
86 #endif
87 #ifdef CONFIG_ICM42X70_TRIGGER_OWN_THREAD
88 	K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ICM42X70_THREAD_STACK_SIZE);
89 	struct k_thread thread;
90 	struct k_sem gpio_sem;
91 #endif
92 #ifdef CONFIG_ICM42X70_TRIGGER_GLOBAL_THREAD
93 	struct k_work work;
94 #endif
95 };
96 
97 struct icm42x70_config {
98 	union icm42x70_bus bus;
99 	const struct icm42x70_bus_io *bus_io;
100 	uint32_t serif_type;
101 	struct gpio_dt_spec gpio_int;
102 	uint8_t accel_fs;
103 	uint16_t accel_hz;
104 	uint16_t accel_avg;
105 	uint16_t accel_filt_bw;
106 #if CONFIG_USE_EMD_ICM42670
107 	uint16_t gyro_fs;
108 	uint16_t gyro_hz;
109 	uint16_t gyro_filt_bw;
110 #endif
111 	uint8_t accel_pwr_mode;
112 	uint8_t apex;
113 };
114 
115 uint32_t convert_freq_to_bitfield(uint32_t val, uint16_t *freq);
116 uint32_t convert_ln_bw_to_bitfield(uint32_t val);
117 
118 #ifdef CONFIG_TDK_APEX
119 
120 #define ICM42X70_APEX_STATUS_MASK_TILT  BIT(0)
121 #define ICM42X70_APEX_STATUS_MASK_SMD   BIT(1)
122 #define ICM42X70_APEX_STATUS_MASK_WOM_X BIT(2)
123 #define ICM42X70_APEX_STATUS_MASK_WOM_Y BIT(3)
124 #define ICM42X70_APEX_STATUS_MASK_WOM_Z BIT(4)
125 
126 int icm42x70_apex_enable(inv_imu_device_t *s);
127 int icm42x70_apex_fetch_from_dmp(const struct device *dev);
128 void icm42x70_apex_pedometer_cadence_convert(struct sensor_value *val, uint8_t raw_val,
129 					     uint8_t dmp_odr_hz);
130 int icm42x70_apex_enable_pedometer(const struct device *dev, inv_imu_device_t *s);
131 int icm42x70_apex_enable_tilt(inv_imu_device_t *s);
132 int icm42x70_apex_enable_smd(inv_imu_device_t *s);
133 int icm42x70_apex_enable_wom(inv_imu_device_t *s);
134 #endif
135 
136 #endif /* ZEPHYR_DRIVERS_SENSOR_ICM42X70_H_ */
137