1 /* ST Microelectronics LIS2DS12 3-axis accelerometer driver
2 *
3 * Copyright (c) 2019 STMicroelectronics
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Datasheet:
8 * https://www.st.com/resource/en/datasheet/lis2ds12.pdf
9 */
10
11 #define DT_DRV_COMPAT st_lis2ds12
12
13 #include <zephyr/drivers/sensor.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/device.h>
16 #include <zephyr/init.h>
17 #include <string.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/sys/__assert.h>
20 #include <zephyr/logging/log.h>
21
22 #include "lis2ds12.h"
23
24 LOG_MODULE_REGISTER(LIS2DS12, CONFIG_SENSOR_LOG_LEVEL);
25
lis2ds12_set_odr(const struct device * dev,uint8_t odr)26 static int lis2ds12_set_odr(const struct device *dev, uint8_t odr)
27 {
28 const struct lis2ds12_config *cfg = dev->config;
29 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
30 lis2ds12_odr_t val;
31
32 /* check if power off */
33 if (odr == 0U) {
34 LOG_DBG("%s: set power-down", dev->name);
35 return lis2ds12_xl_data_rate_set(ctx, LIS2DS12_XL_ODR_OFF);
36 }
37
38 /*
39 * odr >= 1600Hz are available in HF mode only
40 * 12,5Hz <= odr <= 800Hz are available in LP and HR mode only
41 * odr == 1Hz is available in LP mode only
42 */
43 if ((odr >= 9 && cfg->pm != 3) || (odr < 9 && cfg->pm == 3) ||
44 (odr == 1 && cfg->pm != 1)) {
45 LOG_ERR("%s: bad odr and pm combination", dev->name);
46 return -ENOTSUP;
47 }
48
49 switch (odr) {
50 case 1:
51 val = LIS2DS12_XL_ODR_1Hz_LP;
52 break;
53 case 2:
54 val = (cfg->pm == 1) ? LIS2DS12_XL_ODR_12Hz5_LP :
55 LIS2DS12_XL_ODR_12Hz5_HR;
56 break;
57 case 3:
58 val = (cfg->pm == 1) ? LIS2DS12_XL_ODR_25Hz_LP :
59 LIS2DS12_XL_ODR_25Hz_HR;
60 break;
61 case 4:
62 val = (cfg->pm == 1) ? LIS2DS12_XL_ODR_50Hz_LP :
63 LIS2DS12_XL_ODR_50Hz_HR;
64 break;
65 case 5:
66 val = (cfg->pm == 1) ? LIS2DS12_XL_ODR_100Hz_LP :
67 LIS2DS12_XL_ODR_100Hz_HR;
68 break;
69 case 6:
70 val = (cfg->pm == 1) ? LIS2DS12_XL_ODR_200Hz_LP :
71 LIS2DS12_XL_ODR_200Hz_HR;
72 break;
73 case 7:
74 val = (cfg->pm == 1) ? LIS2DS12_XL_ODR_400Hz_LP :
75 LIS2DS12_XL_ODR_400Hz_HR;
76 break;
77 case 8:
78 val = (cfg->pm == 1) ? LIS2DS12_XL_ODR_800Hz_LP :
79 LIS2DS12_XL_ODR_800Hz_HR;
80 break;
81 case 9:
82 val = LIS2DS12_XL_ODR_1k6Hz_HF;
83 break;
84 case 10:
85 val = LIS2DS12_XL_ODR_3k2Hz_HF;
86 break;
87 case 11:
88 val = LIS2DS12_XL_ODR_6k4Hz_HF;
89 break;
90 default:
91 LOG_ERR("%s: bad odr %d", dev->name, odr);
92 return -ENOTSUP;
93 }
94
95 return lis2ds12_xl_data_rate_set(ctx, val);
96 }
97
lis2ds12_set_range(const struct device * dev,uint8_t range)98 static int lis2ds12_set_range(const struct device *dev, uint8_t range)
99 {
100 int err;
101 struct lis2ds12_data *data = dev->data;
102 const struct lis2ds12_config *cfg = dev->config;
103 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
104
105 switch (range) {
106 default:
107 case 2U:
108 err = lis2ds12_xl_full_scale_set(ctx, LIS2DS12_2g);
109 data->gain = lis2ds12_from_fs2g_to_mg(1);
110 break;
111 case 4U:
112 err = lis2ds12_xl_full_scale_set(ctx, LIS2DS12_4g);
113 data->gain = lis2ds12_from_fs4g_to_mg(1);
114 break;
115 case 8U:
116 err = lis2ds12_xl_full_scale_set(ctx, LIS2DS12_8g);
117 data->gain = lis2ds12_from_fs8g_to_mg(1);
118 break;
119 case 16U:
120 err = lis2ds12_xl_full_scale_set(ctx, LIS2DS12_16g);
121 data->gain = lis2ds12_from_fs16g_to_mg(1);
122 break;
123 }
124
125 return err;
126 }
127
lis2ds12_accel_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)128 static int lis2ds12_accel_config(const struct device *dev,
129 enum sensor_channel chan,
130 enum sensor_attribute attr,
131 const struct sensor_value *val)
132 {
133 switch (attr) {
134 case SENSOR_ATTR_FULL_SCALE:
135 return lis2ds12_set_range(dev, sensor_ms2_to_g(val));
136 case SENSOR_ATTR_SAMPLING_FREQUENCY:
137 LOG_DBG("%s: set odr to %d Hz", dev->name, val->val1);
138 return lis2ds12_set_odr(dev, LIS2DS12_ODR_TO_REG(val->val1));
139 default:
140 LOG_DBG("Accel attribute not supported.");
141 return -ENOTSUP;
142 }
143
144 return 0;
145 }
146
lis2ds12_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)147 static int lis2ds12_attr_set(const struct device *dev,
148 enum sensor_channel chan,
149 enum sensor_attribute attr,
150 const struct sensor_value *val)
151 {
152 switch (chan) {
153 case SENSOR_CHAN_ACCEL_XYZ:
154 return lis2ds12_accel_config(dev, chan, attr, val);
155 default:
156 LOG_WRN("attr_set() not supported on this channel.");
157 return -ENOTSUP;
158 }
159
160 return 0;
161 }
162
lis2ds12_sample_fetch_accel(const struct device * dev)163 static int lis2ds12_sample_fetch_accel(const struct device *dev)
164 {
165 struct lis2ds12_data *data = dev->data;
166 const struct lis2ds12_config *cfg = dev->config;
167 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
168 int16_t buf[3];
169
170 /* fetch raw data sample */
171 if (lis2ds12_acceleration_raw_get(ctx, buf) < 0) {
172 LOG_ERR("Failed to fetch raw data sample");
173 return -EIO;
174 }
175
176 data->sample_x = sys_le16_to_cpu(buf[0]);
177 data->sample_y = sys_le16_to_cpu(buf[1]);
178 data->sample_z = sys_le16_to_cpu(buf[2]);
179
180 return 0;
181 }
182
lis2ds12_sample_fetch(const struct device * dev,enum sensor_channel chan)183 static int lis2ds12_sample_fetch(const struct device *dev,
184 enum sensor_channel chan)
185 {
186 switch (chan) {
187 case SENSOR_CHAN_ACCEL_XYZ:
188 lis2ds12_sample_fetch_accel(dev);
189 break;
190 #if defined(CONFIG_LIS2DS12_ENABLE_TEMP)
191 case SENSOR_CHAN_DIE_TEMP:
192 /* ToDo:
193 lis2ds12_sample_fetch_temp(dev)
194 */
195 break;
196 #endif
197 case SENSOR_CHAN_ALL:
198 lis2ds12_sample_fetch_accel(dev);
199 #if defined(CONFIG_LIS2DS12_ENABLE_TEMP)
200 /* ToDo:
201 lis2ds12_sample_fetch_temp(dev)
202 */
203 #endif
204 break;
205 default:
206 return -ENOTSUP;
207 }
208
209 return 0;
210 }
211
lis2ds12_convert(struct sensor_value * val,int raw_val,float gain)212 static inline void lis2ds12_convert(struct sensor_value *val, int raw_val,
213 float gain)
214 {
215 int64_t dval;
216
217 /* Gain is in mg/LSB */
218 /* Convert to m/s^2 */
219 dval = ((int64_t)raw_val * gain * SENSOR_G) / 1000;
220 val->val1 = dval / 1000000LL;
221 val->val2 = dval % 1000000LL;
222 }
223
lis2ds12_get_channel(enum sensor_channel chan,struct sensor_value * val,struct lis2ds12_data * data,float gain)224 static inline int lis2ds12_get_channel(enum sensor_channel chan,
225 struct sensor_value *val,
226 struct lis2ds12_data *data,
227 float gain)
228 {
229 switch (chan) {
230 case SENSOR_CHAN_ACCEL_X:
231 lis2ds12_convert(val, data->sample_x, gain);
232 break;
233 case SENSOR_CHAN_ACCEL_Y:
234 lis2ds12_convert(val, data->sample_y, gain);
235 break;
236 case SENSOR_CHAN_ACCEL_Z:
237 lis2ds12_convert(val, data->sample_z, gain);
238 break;
239 case SENSOR_CHAN_ACCEL_XYZ:
240 lis2ds12_convert(val, data->sample_x, gain);
241 lis2ds12_convert(val + 1, data->sample_y, gain);
242 lis2ds12_convert(val + 2, data->sample_z, gain);
243 break;
244 default:
245 return -ENOTSUP;
246 }
247
248 return 0;
249 }
250
lis2ds12_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)251 static int lis2ds12_channel_get(const struct device *dev,
252 enum sensor_channel chan,
253 struct sensor_value *val)
254 {
255 struct lis2ds12_data *data = dev->data;
256
257 return lis2ds12_get_channel(chan, val, data, data->gain);
258 }
259
260 static const struct sensor_driver_api lis2ds12_driver_api = {
261 .attr_set = lis2ds12_attr_set,
262 #if defined(CONFIG_LIS2DS12_TRIGGER)
263 .trigger_set = lis2ds12_trigger_set,
264 #endif
265 .sample_fetch = lis2ds12_sample_fetch,
266 .channel_get = lis2ds12_channel_get,
267 };
268
lis2ds12_init(const struct device * dev)269 static int lis2ds12_init(const struct device *dev)
270 {
271 const struct lis2ds12_config * const cfg = dev->config;
272 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
273 uint8_t chip_id;
274 int ret;
275
276 /* check chip ID */
277 ret = lis2ds12_device_id_get(ctx, &chip_id);
278 if (ret < 0) {
279 LOG_ERR("%s: Not able to read dev id", dev->name);
280 return ret;
281 }
282
283 if (chip_id != LIS2DS12_ID) {
284 LOG_ERR("%s: Invalid chip ID 0x%02x", dev->name, chip_id);
285 return -EINVAL;
286 }
287
288 /* reset device */
289 ret = lis2ds12_reset_set(ctx, PROPERTY_ENABLE);
290 if (ret < 0) {
291 return ret;
292 }
293
294 k_busy_wait(100);
295
296 LOG_DBG("%s: chip id 0x%x", dev->name, chip_id);
297
298 #ifdef CONFIG_LIS2DS12_TRIGGER
299 ret = lis2ds12_trigger_init(dev);
300 if (ret < 0) {
301 LOG_ERR("%s: Failed to initialize triggers", dev->name);
302 return ret;
303 }
304 #endif
305
306 /* set sensor default pm and odr */
307 LOG_DBG("%s: pm: %d, odr: %d", dev->name, cfg->pm, cfg->odr);
308 ret = lis2ds12_set_odr(dev, (cfg->pm == 0) ? 0 : cfg->odr);
309 if (ret < 0) {
310 LOG_ERR("%s: odr init error (12.5 Hz)", dev->name);
311 return ret;
312 }
313
314 /* set sensor default scale */
315 LOG_DBG("%s: range is %d", dev->name, cfg->range);
316 ret = lis2ds12_set_range(dev, cfg->range);
317 if (ret < 0) {
318 LOG_ERR("%s: range init error %d", dev->name, cfg->range);
319 return ret;
320 }
321
322 return 0;
323 }
324
325 #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
326 #warning "LIS2DS12 driver enabled without any devices"
327 #endif
328
329 /*
330 * Device creation macro, shared by LIS2DS12_DEFINE_SPI() and
331 * LIS2DS12_DEFINE_I2C().
332 */
333
334 #define LIS2DS12_DEVICE_INIT(inst) \
335 SENSOR_DEVICE_DT_INST_DEFINE(inst, \
336 lis2ds12_init, \
337 NULL, \
338 &lis2ds12_data_##inst, \
339 &lis2ds12_config_##inst, \
340 POST_KERNEL, \
341 CONFIG_SENSOR_INIT_PRIORITY, \
342 &lis2ds12_driver_api);
343
344 /*
345 * Instantiation macros used when a device is on a SPI bus.
346 */
347
348 #ifdef CONFIG_LIS2DS12_TRIGGER
349 #define LIS2DS12_CFG_IRQ(inst) \
350 .gpio_int = GPIO_DT_SPEC_INST_GET(inst, irq_gpios),
351 #else
352 #define LIS2DS12_CFG_IRQ(inst)
353 #endif /* CONFIG_LIS2DS12_TRIGGER */
354
355 #define LIS2DS12_CONFIG_COMMON(inst) \
356 .range = DT_INST_PROP(inst, range), \
357 .pm = DT_INST_PROP(inst, power_mode), \
358 .odr = DT_INST_PROP(inst, odr), \
359 COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios), \
360 (LIS2DS12_CFG_IRQ(inst)), ())
361
362 #define LIS2DS12_SPI_OPERATION (SPI_WORD_SET(8) | \
363 SPI_OP_MODE_MASTER | \
364 SPI_MODE_CPOL | \
365 SPI_MODE_CPHA) \
366
367 #define LIS2DS12_CONFIG_SPI(inst) \
368 { \
369 STMEMSC_CTX_SPI(&lis2ds12_config_##inst.stmemsc_cfg), \
370 .stmemsc_cfg = { \
371 .spi = SPI_DT_SPEC_INST_GET(inst, \
372 LIS2DS12_SPI_OPERATION, \
373 0), \
374 }, \
375 LIS2DS12_CONFIG_COMMON(inst) \
376 }
377
378 /*
379 * Instantiation macros used when a device is on an I2C bus.
380 */
381
382 #define LIS2DS12_CONFIG_I2C(inst) \
383 { \
384 STMEMSC_CTX_I2C(&lis2ds12_config_##inst.stmemsc_cfg), \
385 .stmemsc_cfg = { \
386 .i2c = I2C_DT_SPEC_INST_GET(inst), \
387 }, \
388 LIS2DS12_CONFIG_COMMON(inst) \
389 }
390
391 /*
392 * Main instantiation macro. Use of COND_CODE_1() selects the right
393 * bus-specific macro at preprocessor time.
394 */
395
396 #define LIS2DS12_DEFINE(inst) \
397 static struct lis2ds12_data lis2ds12_data_##inst; \
398 static const struct lis2ds12_config lis2ds12_config_##inst = \
399 COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
400 (LIS2DS12_CONFIG_SPI(inst)), \
401 (LIS2DS12_CONFIG_I2C(inst))); \
402 LIS2DS12_DEVICE_INIT(inst)
403
404 DT_INST_FOREACH_STATUS_OKAY(LIS2DS12_DEFINE)
405