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