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