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