1 /* ST Microelectronics LIS2DE12 3-axis accelerometer sensor driver
2 *
3 * Copyright (c) 2024 STMicroelectronics
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Datasheet:
8 * https://www.st.com/resource/en/datasheet/lis2de12.pdf
9 */
10
11 #define DT_DRV_COMPAT st_lis2de12
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 "lis2de12.h"
23
24 LOG_MODULE_REGISTER(LIS2DE12, CONFIG_SENSOR_LOG_LEVEL);
25
26 static const uint16_t lis2de12_odr_map[10] = { 0, 1, 10, 25, 50, 100, 200, 400, 1620, 5376};
27
lis2de12_freq_to_odr_val(const struct device * dev,uint16_t freq)28 static int lis2de12_freq_to_odr_val(const struct device *dev, uint16_t freq)
29 {
30 size_t i;
31
32 for (i = 0; i < ARRAY_SIZE(lis2de12_odr_map); i++) {
33 if (freq <= lis2de12_odr_map[i]) {
34 return i;
35 }
36 }
37
38 return -EINVAL;
39 }
40
41 typedef struct {
42 uint16_t fs;
43 uint32_t gain; /* Accel sensor sensitivity in ug/LSB */
44 } fs_map;
45
46 static const fs_map lis2de12_accel_fs_map[] = {
47 {2, 15600},
48 {4, 31200},
49 {8, 62500},
50 {16, 187500},
51 };
52
lis2de12_accel_range_to_fs_val(int32_t range)53 static int lis2de12_accel_range_to_fs_val(int32_t range)
54 {
55 size_t i;
56
57 for (i = 0; i < ARRAY_SIZE(lis2de12_accel_fs_map); i++) {
58 if (range == lis2de12_accel_fs_map[i].fs) {
59 return i;
60 }
61 }
62
63 return -EINVAL;
64 }
65
lis2de12_accel_set_fs_raw(const struct device * dev,uint8_t fs)66 static int lis2de12_accel_set_fs_raw(const struct device *dev, uint8_t fs)
67 {
68 const struct lis2de12_config *cfg = dev->config;
69 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
70 struct lis2de12_data *data = dev->data;
71
72 if (lis2de12_full_scale_set(ctx, fs) < 0) {
73 return -EIO;
74 }
75
76 data->accel_fs = fs;
77
78 return 0;
79 }
80
lis2de12_accel_set_odr_raw(const struct device * dev,uint8_t odr)81 static int lis2de12_accel_set_odr_raw(const struct device *dev, uint8_t odr)
82 {
83 const struct lis2de12_config *cfg = dev->config;
84 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
85 struct lis2de12_data *data = dev->data;
86
87 if (lis2de12_data_rate_set(ctx, odr) < 0) {
88 return -EIO;
89 }
90
91 data->accel_freq = odr;
92
93 return 0;
94 }
95
lis2de12_accel_odr_set(const struct device * dev,uint16_t freq)96 static int lis2de12_accel_odr_set(const struct device *dev, uint16_t freq)
97 {
98 int odr;
99
100 odr = lis2de12_freq_to_odr_val(dev, freq);
101 if (odr < 0) {
102 return odr;
103 }
104
105 if (lis2de12_accel_set_odr_raw(dev, odr) < 0) {
106 LOG_ERR("failed to set accelerometer sampling rate");
107 return -EIO;
108 }
109
110 return 0;
111 }
112
lis2de12_accel_range_set(const struct device * dev,int32_t range)113 static int lis2de12_accel_range_set(const struct device *dev, int32_t range)
114 {
115 int fs;
116 struct lis2de12_data *data = dev->data;
117
118 fs = lis2de12_accel_range_to_fs_val(range);
119 if (fs < 0) {
120 return fs;
121 }
122
123 if (lis2de12_accel_set_fs_raw(dev, fs) < 0) {
124 LOG_ERR("failed to set accelerometer full-scale");
125 return -EIO;
126 }
127
128 data->acc_gain = lis2de12_accel_fs_map[fs].gain;
129 return 0;
130 }
131
lis2de12_accel_config(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)132 static int lis2de12_accel_config(const struct device *dev,
133 enum sensor_channel chan,
134 enum sensor_attribute attr,
135 const struct sensor_value *val)
136 {
137 switch (attr) {
138 case SENSOR_ATTR_FULL_SCALE:
139 return lis2de12_accel_range_set(dev, sensor_ms2_to_g(val));
140 case SENSOR_ATTR_SAMPLING_FREQUENCY:
141 return lis2de12_accel_odr_set(dev, val->val1);
142 default:
143 LOG_WRN("Accel attribute %d not supported.", attr);
144 return -ENOTSUP;
145 }
146 }
147
lis2de12_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)148 static int lis2de12_attr_set(const struct device *dev,
149 enum sensor_channel chan,
150 enum sensor_attribute attr,
151 const struct sensor_value *val)
152 {
153 switch (chan) {
154 case SENSOR_CHAN_ACCEL_XYZ:
155 return lis2de12_accel_config(dev, chan, attr, val);
156 default:
157 LOG_WRN("attribute %d not supported on this channel.", chan);
158 return -ENOTSUP;
159 }
160 }
161
lis2de12_sample_fetch_accel(const struct device * dev)162 static int lis2de12_sample_fetch_accel(const struct device *dev)
163 {
164 const struct lis2de12_config *cfg = dev->config;
165 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
166 struct lis2de12_data *data = dev->data;
167
168 if (lis2de12_acceleration_raw_get(ctx, data->acc) < 0) {
169 LOG_ERR("Failed to read sample");
170 return -EIO;
171 }
172
173 return 0;
174 }
175
176 #if defined(CONFIG_LIS2DE12_ENABLE_TEMP)
lis2de12_sample_fetch_temp(const struct device * dev)177 static int lis2de12_sample_fetch_temp(const struct device *dev)
178 {
179 const struct lis2de12_config *cfg = dev->config;
180 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
181 struct lis2de12_data *data = dev->data;
182
183 if (lis2de12_temperature_raw_get(ctx, &data->temp_sample) < 0) {
184 LOG_DBG("Failed to read sample");
185 return -EIO;
186 }
187
188 return 0;
189 }
190 #endif
191
lis2de12_sample_fetch(const struct device * dev,enum sensor_channel chan)192 static int lis2de12_sample_fetch(const struct device *dev,
193 enum sensor_channel chan)
194 {
195 switch (chan) {
196 case SENSOR_CHAN_ACCEL_XYZ:
197 lis2de12_sample_fetch_accel(dev);
198 break;
199 #if defined(CONFIG_LIS2DE12_ENABLE_TEMP)
200 case SENSOR_CHAN_DIE_TEMP:
201 lis2de12_sample_fetch_temp(dev);
202 break;
203 #endif
204 case SENSOR_CHAN_ALL:
205 lis2de12_sample_fetch_accel(dev);
206 #if defined(CONFIG_LIS2DE12_ENABLE_TEMP)
207 lis2de12_sample_fetch_temp(dev);
208 #endif
209 break;
210 default:
211 return -ENOTSUP;
212 }
213
214 return 0;
215 }
216
lis2de12_accel_convert(struct sensor_value * val,int raw_val,uint32_t sensitivity)217 static inline void lis2de12_accel_convert(struct sensor_value *val, int raw_val,
218 uint32_t sensitivity)
219 {
220 int64_t dval;
221
222 /* Sensitivity is exposed in ug/LSB */
223 /* Convert to m/s^2 */
224 dval = (int64_t)(raw_val / 256) * sensitivity * SENSOR_G_DOUBLE;
225 val->val1 = (int32_t)(dval / 1000000);
226 val->val2 = (int32_t)(dval % 1000000);
227
228 }
229
lis2de12_accel_get_channel(enum sensor_channel chan,struct sensor_value * val,struct lis2de12_data * data,uint32_t sensitivity)230 static inline int lis2de12_accel_get_channel(enum sensor_channel chan,
231 struct sensor_value *val,
232 struct lis2de12_data *data,
233 uint32_t sensitivity)
234 {
235 uint8_t i;
236
237 switch (chan) {
238 case SENSOR_CHAN_ACCEL_X:
239 lis2de12_accel_convert(val, data->acc[0], sensitivity);
240 break;
241 case SENSOR_CHAN_ACCEL_Y:
242 lis2de12_accel_convert(val, data->acc[1], sensitivity);
243 break;
244 case SENSOR_CHAN_ACCEL_Z:
245 lis2de12_accel_convert(val, data->acc[2], sensitivity);
246 break;
247 case SENSOR_CHAN_ACCEL_XYZ:
248 for (i = 0; i < 3; i++) {
249 lis2de12_accel_convert(val++, data->acc[i], sensitivity);
250 }
251 break;
252 default:
253 return -ENOTSUP;
254 }
255
256 return 0;
257 }
258
lis2de12_accel_channel_get(enum sensor_channel chan,struct sensor_value * val,struct lis2de12_data * data)259 static int lis2de12_accel_channel_get(enum sensor_channel chan,
260 struct sensor_value *val,
261 struct lis2de12_data *data)
262 {
263 return lis2de12_accel_get_channel(chan, val, data, data->acc_gain);
264 }
265
266 #if defined(CONFIG_LIS2DE12_ENABLE_TEMP)
lis2de12_temp_channel_get(struct sensor_value * val,struct lis2de12_data * data)267 static void lis2de12_temp_channel_get(struct sensor_value *val, struct lis2de12_data *data)
268 {
269 int64_t micro_c;
270
271 /* convert units to micro Celsius. Raw temperature samples are
272 * expressed in 256 LSB/deg_C units. And LSB output is 0 at 25 C.
273 */
274 micro_c = ((int64_t)data->temp_sample * 1000000) / 256;
275
276 val->val1 = micro_c / 1000000 + 25;
277 val->val2 = micro_c % 1000000;
278 }
279 #endif
280
lis2de12_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)281 static int lis2de12_channel_get(const struct device *dev,
282 enum sensor_channel chan,
283 struct sensor_value *val)
284 {
285 struct lis2de12_data *data = dev->data;
286
287 switch (chan) {
288 case SENSOR_CHAN_ACCEL_X:
289 case SENSOR_CHAN_ACCEL_Y:
290 case SENSOR_CHAN_ACCEL_Z:
291 case SENSOR_CHAN_ACCEL_XYZ:
292 lis2de12_accel_channel_get(chan, val, data);
293 break;
294 #if defined(CONFIG_LIS2DE12_ENABLE_TEMP)
295 case SENSOR_CHAN_DIE_TEMP:
296 lis2de12_temp_channel_get(val, data);
297 break;
298 #endif
299 default:
300 return -ENOTSUP;
301 }
302
303 return 0;
304 }
305
306 static const struct sensor_driver_api lis2de12_driver_api = {
307 .attr_set = lis2de12_attr_set,
308 #if CONFIG_LIS2DE12_TRIGGER
309 .trigger_set = lis2de12_trigger_set,
310 #endif
311 .sample_fetch = lis2de12_sample_fetch,
312 .channel_get = lis2de12_channel_get,
313 };
314
lis2de12_init_chip(const struct device * dev)315 static int lis2de12_init_chip(const struct device *dev)
316 {
317 const struct lis2de12_config *cfg = dev->config;
318 stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
319 struct lis2de12_data *lis2de12 = dev->data;
320 uint8_t chip_id;
321 uint8_t odr, fs;
322
323 if (lis2de12_device_id_get(ctx, &chip_id) < 0) {
324 LOG_ERR("Failed reading chip id");
325 return -EIO;
326 }
327
328 if (chip_id != LIS2DE12_ID) {
329 LOG_ERR("Invalid chip id 0x%x", chip_id);
330 return -EIO;
331 }
332
333 LOG_INF("chip id 0x%x", chip_id);
334
335 if (lis2de12_block_data_update_set(ctx, 1) < 0) {
336 LOG_ERR("failed to set BDU");
337 return -EIO;
338 }
339
340 /* set FS from DT */
341 fs = cfg->accel_range;
342 LOG_DBG("accel range is %d", fs);
343 if (lis2de12_accel_set_fs_raw(dev, fs) < 0) {
344 LOG_ERR("failed to set accelerometer range %d", fs);
345 return -EIO;
346 }
347 lis2de12->acc_gain = lis2de12_accel_fs_map[fs].gain;
348
349 /* set odr from DT (the only way to go in high performance) */
350 odr = cfg->accel_odr;
351 LOG_DBG("accel odr is %d", odr);
352 if (lis2de12_accel_set_odr_raw(dev, odr) < 0) {
353 LOG_ERR("failed to set accelerometer odr %d", odr);
354 return -EIO;
355 }
356
357 #if defined(CONFIG_LIS2DE12_ENABLE_TEMP)
358 lis2de12_temperature_meas_set(ctx, LIS2DE12_TEMP_ENABLE);
359 #endif
360
361 return 0;
362 }
363
lis2de12_init(const struct device * dev)364 static int lis2de12_init(const struct device *dev)
365 {
366 #ifdef CONFIG_LIS2DE12_TRIGGER
367 const struct lis2de12_config *cfg = dev->config;
368 #endif
369 struct lis2de12_data *data = dev->data;
370
371 LOG_INF("Initialize device %s", dev->name);
372 data->dev = dev;
373
374 if (lis2de12_init_chip(dev) < 0) {
375 LOG_ERR("failed to initialize chip");
376 return -EIO;
377 }
378
379 #ifdef CONFIG_LIS2DE12_TRIGGER
380 if (cfg->trig_enabled) {
381 if (lis2de12_init_interrupt(dev) < 0) {
382 LOG_ERR("Failed to initialize interrupt.");
383 return -EIO;
384 }
385 }
386 #endif
387
388 return 0;
389 }
390
391 /*
392 * Device creation macro, shared by LIS2DE12_DEFINE_SPI() and
393 * LIS2DE12_DEFINE_I2C().
394 */
395
396 #define LIS2DE12_DEVICE_INIT(inst) \
397 SENSOR_DEVICE_DT_INST_DEFINE(inst, \
398 lis2de12_init, \
399 NULL, \
400 &lis2de12_data_##inst, \
401 &lis2de12_config_##inst, \
402 POST_KERNEL, \
403 CONFIG_SENSOR_INIT_PRIORITY, \
404 &lis2de12_driver_api);
405
406 /*
407 * Instantiation macros used when a device is on a SPI bus.
408 */
409
410 #ifdef CONFIG_LIS2DE12_TRIGGER
411 #define LIS2DE12_CFG_IRQ(inst) \
412 .trig_enabled = true, \
413 .int1_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, { 0 }), \
414 .int2_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int2_gpios, { 0 }), \
415 .drdy_pulsed = DT_INST_PROP(inst, drdy_pulsed)
416 #else
417 #define LIS2DE12_CFG_IRQ(inst)
418 #endif /* CONFIG_LIS2DE12_TRIGGER */
419
420 #define LIS2DE12_SPI_OP (SPI_WORD_SET(8) | \
421 SPI_OP_MODE_MASTER | \
422 SPI_MODE_CPOL | \
423 SPI_MODE_CPHA) \
424
425 #define LIS2DE12_CONFIG_COMMON(inst) \
426 .accel_odr = DT_INST_PROP(inst, accel_odr), \
427 .accel_range = DT_INST_PROP(inst, accel_range), \
428 IF_ENABLED(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \
429 DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \
430 (LIS2DE12_CFG_IRQ(inst)))
431
432 /*
433 * Instantiation macros used when a device is on a SPI bus.
434 */
435
436 #define LIS2DE12_CONFIG_SPI(inst) \
437 { \
438 STMEMSC_CTX_SPI(&lis2de12_config_##inst.stmemsc_cfg), \
439 .stmemsc_cfg = { \
440 .spi = SPI_DT_SPEC_INST_GET(inst, LIS2DE12_SPI_OP, 0), \
441 }, \
442 LIS2DE12_CONFIG_COMMON(inst) \
443 }
444
445 /*
446 * Instantiation macros used when a device is on an I2C bus.
447 */
448
449 #define LIS2DE12_CONFIG_I2C(inst) \
450 { \
451 STMEMSC_CTX_I2C_INCR(&lis2de12_config_##inst.stmemsc_cfg), \
452 .stmemsc_cfg = { \
453 .i2c = I2C_DT_SPEC_INST_GET(inst), \
454 }, \
455 LIS2DE12_CONFIG_COMMON(inst) \
456 }
457
458 /*
459 * Main instantiation macro. Use of COND_CODE_1() selects the right
460 * bus-specific macro at preprocessor time.
461 */
462
463 #define LIS2DE12_DEFINE(inst) \
464 static struct lis2de12_data lis2de12_data_##inst; \
465 static const struct lis2de12_config lis2de12_config_##inst = \
466 COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
467 (LIS2DE12_CONFIG_SPI(inst)), \
468 (LIS2DE12_CONFIG_I2C(inst))); \
469 LIS2DE12_DEVICE_INIT(inst)
470
471 DT_INST_FOREACH_STATUS_OKAY(LIS2DE12_DEFINE)
472