1 /* ST Microelectronics LSM6DSV16X 6-axis IMU sensor driver
2  *
3  * Copyright (c) 2023 STMicroelectronics
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * Datasheet:
8  * https://www.st.com/resource/en/datasheet/lsm6dsv16x.pdf
9  */
10 
11 #ifndef ZEPHYR_DRIVERS_SENSOR_LSM6DSV16X_LSM6DSV16X_H_
12 #define ZEPHYR_DRIVERS_SENSOR_LSM6DSV16X_LSM6DSV16X_H_
13 
14 #include <zephyr/drivers/sensor.h>
15 #include <zephyr/types.h>
16 #include <zephyr/drivers/gpio.h>
17 #include <zephyr/sys/util.h>
18 #include <stmemsc.h>
19 #include "lsm6dsv16x_reg.h"
20 
21 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
22 #include <zephyr/drivers/spi.h>
23 #endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
24 
25 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
26 #include <zephyr/drivers/i2c.h>
27 #endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
28 
29 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
30 #include <zephyr/drivers/i3c.h>
31 #endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) */
32 
33 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
34 	#define ON_I3C_BUS(cfg)  (cfg->i3c.bus != NULL)
35 	#define I3C_INT_PIN(cfg) (cfg->int_en_i3c)
36 #else
37 	#define ON_I3C_BUS(cfg)  (false)
38 	#define I3C_INT_PIN(cfg) (false)
39 #endif
40 
41 #define LSM6DSV16X_EN_BIT					0x01
42 #define LSM6DSV16X_DIS_BIT					0x00
43 
44 /* Accel sensor sensitivity grain is 61 ug/LSB */
45 #define GAIN_UNIT_XL				(61LL)
46 
47 /* Gyro sensor sensitivity grain is 4.375 udps/LSB */
48 #define GAIN_UNIT_G				(4375LL)
49 
50 int lsm6dsv16x_calc_accel_gain(uint8_t fs);
51 int lsm6dsv16x_calc_gyro_gain(uint8_t fs);
52 
53 struct lsm6dsv16x_config {
54 	stmdev_ctx_t ctx;
55 	union {
56 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
57 		const struct i2c_dt_spec i2c;
58 #endif
59 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
60 		const struct spi_dt_spec spi;
61 #endif
62 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
63 		struct i3c_device_desc **i3c;
64 #endif
65 	} stmemsc_cfg;
66 	uint8_t accel_pm;
67 	uint8_t accel_odr;
68 	uint8_t accel_range;
69 	uint8_t gyro_pm;
70 	uint8_t gyro_odr;
71 	uint8_t gyro_range;
72 	uint8_t drdy_pulsed;
73 #ifdef CONFIG_LSM6DSV16X_STREAM
74 	uint8_t fifo_wtm;
75 	uint8_t accel_batch : 4;
76 	uint8_t gyro_batch : 4;
77 	uint8_t temp_batch : 2;
78 	uint8_t sflp_odr : 3;
79 	uint8_t sflp_fifo_en : 3;
80 #endif
81 #ifdef CONFIG_LSM6DSV16X_TRIGGER
82 	const struct gpio_dt_spec int1_gpio;
83 	const struct gpio_dt_spec int2_gpio;
84 	uint8_t drdy_pin;
85 	bool trig_enabled;
86 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
87 	bool int_en_i3c;
88 	lsm6dsv16x_i3c_ibi_time_t bus_act_sel;
89 #endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) */
90 #endif /* CONFIG_LSM6DSV16X_TRIGGER */
91 
92 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
93 	struct {
94 		const struct device *bus;
95 		const struct i3c_device_id dev_id;
96 	} i3c;
97 #endif
98 };
99 
100 union samples {
101 	uint8_t raw[6];
102 	struct {
103 		int16_t axis[3];
104 	};
105 } __aligned(2);
106 
107 #define LSM6DSV16X_SHUB_MAX_NUM_TARGETS			3
108 
109 struct lsm6dsv16x_ibi_payload {
110 	uint8_t mdb;
111 	uint8_t fifo_status1;
112 	uint8_t fifo_status2;
113 	uint8_t all_int_src;
114 	uint8_t status_reg;
115 	uint8_t status_reg_ois;
116 	uint8_t status_master_main;
117 	uint8_t emb_func_status;
118 	uint8_t fsm_status;
119 	uint8_t mlc_status;
120 } __packed;
121 
122 struct lsm6dsv16x_data {
123 	const struct device *dev;
124 	int16_t acc[3];
125 	uint32_t acc_gain;
126 	int16_t gyro[3];
127 	uint32_t gyro_gain;
128 #if defined(CONFIG_LSM6DSV16X_ENABLE_TEMP)
129 	int16_t temp_sample;
130 #endif
131 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
132 	uint8_t ext_data[LSM6DSV16X_SHUB_MAX_NUM_TARGETS][6];
133 	uint16_t magn_gain;
134 
135 	struct hts221_data {
136 		int16_t x0;
137 		int16_t x1;
138 		int16_t y0;
139 		int16_t y1;
140 	} hts221;
141 	bool shub_inited;
142 	uint8_t num_ext_dev;
143 	uint8_t shub_ext[LSM6DSV16X_SHUB_MAX_NUM_TARGETS];
144 #endif /* CONFIG_LSM6DSV16X_SENSORHUB */
145 
146 	uint8_t accel_freq;
147 	uint8_t accel_fs;
148 	uint8_t gyro_freq;
149 	uint8_t gyro_fs;
150 
151 #ifdef CONFIG_LSM6DSV16X_STREAM
152 	struct rtio_iodev_sqe *streaming_sqe;
153 	struct rtio *rtio_ctx;
154 	struct rtio_iodev *iodev;
155 	uint64_t fifo_timestamp;
156 	uint8_t fifo_status[2];
157 	uint16_t fifo_count;
158 	uint8_t fifo_irq;
159 	uint8_t accel_batch_odr : 4;
160 	uint8_t gyro_batch_odr : 4;
161 	uint8_t temp_batch_odr : 2;
162 	uint8_t bus_type : 2; /* I2C is 0, SPI is 1, I3C is 2 */
163 	uint8_t sflp_batch_odr : 3;
164 	uint8_t reserved : 1;
165 #endif
166 
167 #ifdef CONFIG_LSM6DSV16X_TRIGGER
168 	struct gpio_dt_spec *drdy_gpio;
169 
170 	struct gpio_callback gpio_cb;
171 	sensor_trigger_handler_t handler_drdy_acc;
172 	const struct sensor_trigger *trig_drdy_acc;
173 	sensor_trigger_handler_t handler_drdy_gyr;
174 	const struct sensor_trigger *trig_drdy_gyr;
175 	sensor_trigger_handler_t handler_drdy_temp;
176 	const struct sensor_trigger *trig_drdy_temp;
177 
178 #if defined(CONFIG_LSM6DSV16X_TRIGGER_OWN_THREAD)
179 	K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_LSM6DSV16X_THREAD_STACK_SIZE);
180 	struct k_thread thread;
181 	struct k_sem intr_sem;
182 #elif defined(CONFIG_LSM6DSV16X_TRIGGER_GLOBAL_THREAD)
183 	struct k_work work;
184 #endif
185 #endif /* CONFIG_LSM6DSV16X_TRIGGER */
186 
187 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
188 	struct i3c_device_desc *i3c_dev;
189 	struct lsm6dsv16x_ibi_payload ibi_payload;
190 #endif
191 };
192 
193 #ifdef CONFIG_LSM6DSV16X_STREAM
194 #define BUS_I2C 0
195 #define BUS_SPI 1
196 #define BUS_I3C 2
197 
lsm6dsv16x_bus_reg(struct lsm6dsv16x_data * data,uint8_t x)198 static inline uint8_t lsm6dsv16x_bus_reg(struct lsm6dsv16x_data *data, uint8_t x)
199 {
200 	return (data->bus_type == BUS_SPI) ? x | 0x80 : x;
201 }
202 
203 #define LSM6DSV16X_FIFO_ITEM_LEN 7
204 #define LSM6DSV16X_FIFO_SIZE(x) (x * LSM6DSV16X_FIFO_ITEM_LEN)
205 #endif
206 
207 #if defined(CONFIG_LSM6DSV16X_SENSORHUB)
208 int lsm6dsv16x_shub_init(const struct device *dev);
209 int lsm6dsv16x_shub_fetch_external_devs(const struct device *dev);
210 int lsm6dsv16x_shub_get_idx(const struct device *dev, enum sensor_channel type);
211 int lsm6dsv16x_shub_config(const struct device *dev, enum sensor_channel chan,
212 			enum sensor_attribute attr,
213 			const struct sensor_value *val);
214 #endif /* CONFIG_LSM6DSV16X_SENSORHUB */
215 
216 #ifdef CONFIG_LSM6DSV16X_TRIGGER
217 int lsm6dsv16x_trigger_set(const struct device *dev,
218 			const struct sensor_trigger *trig,
219 			sensor_trigger_handler_t handler);
220 
221 int lsm6dsv16x_init_interrupt(const struct device *dev);
222 #endif
223 
224 #endif /* ZEPHYR_DRIVERS_SENSOR_LSM6DSV16X_LSM6DSV16X_H_ */
225