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