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