1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  * Würth Elektronic WSEN-ITDS 3-axis accel sensor driver
5  *
6  * Copyright (c) 2020 Linumiz
7  * Author: Saravanan Sekar <saravanan@linumiz.com>
8  */
9 
10 #include <zephyr/init.h>
11 #include <zephyr/drivers/sensor.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/sys/__assert.h>
15 #include <zephyr/logging/log.h>
16 #include "itds.h"
17 
18 #define DT_DRV_COMPAT we_wsen_itds
19 #define ITDS_TEMP_CONST 62500
20 
21 LOG_MODULE_REGISTER(ITDS, CONFIG_SENSOR_LOG_LEVEL);
22 
23 static const struct itds_odr itds_odr_map[ITDS_ODR_MAX] = {
24 	{0}, {1, 600}, {12, 500}, {25}, {50}, {100}, {200},
25 	{400}, {800}, {1600}
26 };
27 
28 static const int16_t itds_sensitivity_scale[][ITDS_ACCL_RANGE_END] = {
29 	{976, 1952, 3904, 7808},
30 
31 	/* high performance mode */
32 	{244, 488, 976, 1952}
33 };
34 
itds_get_odr_for_index(const struct device * dev,enum itds_odr_const idx,uint16_t * freq,uint16_t * mfreq)35 static int itds_get_odr_for_index(const struct device *dev,
36 				  enum itds_odr_const idx,
37 				  uint16_t *freq, uint16_t *mfreq)
38 {
39 	struct itds_device_data *ddata = dev->data;
40 	int start, end;
41 	bool hp_mode;
42 
43 	hp_mode = !!(ddata->op_mode & ITDS_OP_MODE_HIGH_PERF);
44 	if (hp_mode) {
45 		start = ITDS_ODR_12_5;
46 		end = ITDS_ODR_1600;
47 	} else {
48 		start = ITDS_ODR_1_6;
49 		end = ITDS_ODR_200;
50 	}
51 
52 	if (idx < start || idx > end) {
53 		LOG_ERR("invalid odr for the operating mode");
54 		return -EINVAL;
55 	}
56 
57 	*freq = itds_odr_map[idx].freq;
58 	*mfreq = itds_odr_map[idx].mfreq;
59 
60 	return 0;
61 }
62 
itds_accl_odr_set(const struct device * dev,uint16_t freq,uint16_t mfreq)63 static int itds_accl_odr_set(const struct device *dev, uint16_t freq,
64 			     uint16_t mfreq)
65 {
66 	struct itds_device_data *ddata = dev->data;
67 	const struct itds_device_config *cfg = dev->config;
68 	int start, end, i;
69 	bool hp_mode;
70 
71 	hp_mode = !!(ddata->op_mode & ITDS_OP_MODE_HIGH_PERF);
72 	if (hp_mode) {
73 		start = ITDS_ODR_12_5;
74 		end = ITDS_ODR_1600;
75 	} else {
76 		start = ITDS_ODR_1_6;
77 		end = ITDS_ODR_200;
78 	}
79 
80 	for (i = start; i <= end; i++) {
81 		if ((freq == itds_odr_map[i].freq) &&
82 		    (mfreq == itds_odr_map[i].mfreq)) {
83 
84 			return i2c_reg_update_byte_dt(&cfg->i2c,
85 					 ITDS_REG_CTRL1, ITDS_MASK_ODR, i << 4);
86 		}
87 	}
88 
89 	LOG_ERR("invalid odr, not in range");
90 	return -EINVAL;
91 }
92 
itds_accl_range_set(const struct device * dev,int32_t range)93 static int itds_accl_range_set(const struct device *dev, int32_t range)
94 {
95 	struct itds_device_data *ddata = dev->data;
96 	const struct itds_device_config *cfg = dev->config;
97 	int i, ret;
98 	bool hp_mode;
99 
100 	for (i = 0; i < ITDS_ACCL_RANGE_END; i++) {
101 		if (range <= (2 << i)) {
102 			break;
103 		}
104 	}
105 
106 	if (i == ITDS_ACCL_RANGE_END) {
107 		LOG_ERR("Accl out of range");
108 		return -EINVAL;
109 	}
110 
111 	ret = i2c_reg_update_byte_dt(&cfg->i2c, ITDS_REG_CTRL6,
112 				  ITDS_MASK_SCALE, i << 4);
113 	if (ret) {
114 		LOG_ERR("Accl set full scale failed %d", ret);
115 		return ret;
116 	}
117 
118 	hp_mode = !!(ddata->op_mode & ITDS_OP_MODE_HIGH_PERF);
119 	ddata->scale = itds_sensitivity_scale[hp_mode][i];
120 
121 	return 0;
122 }
123 
itds_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)124 static int itds_attr_set(const struct device *dev, enum sensor_channel chan,
125 			 enum sensor_attribute attr,
126 			 const struct sensor_value *val)
127 {
128 	if (chan != SENSOR_CHAN_ACCEL_X &&
129 	    chan != SENSOR_CHAN_ACCEL_Y &&
130 	    chan != SENSOR_CHAN_ACCEL_Z &&
131 	    chan != SENSOR_CHAN_ACCEL_XYZ) {
132 		LOG_ERR("attr_set() not supported on this channel.");
133 		return -ENOTSUP;
134 	}
135 
136 	switch (attr) {
137 	case SENSOR_ATTR_FULL_SCALE:
138 		return itds_accl_range_set(dev, sensor_ms2_to_g(val));
139 
140 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
141 		return itds_accl_odr_set(dev, val->val1, val->val2 / 1000);
142 
143 	default:
144 		LOG_ERR("Accel attribute not supported.");
145 		return -ENOTSUP;
146 	}
147 }
148 
itds_fetch_temperature(struct itds_device_data * ddata,const struct itds_device_config * cfg)149 static int itds_fetch_temperature(struct itds_device_data *ddata,
150 				 const struct itds_device_config *cfg)
151 {
152 	uint8_t rval;
153 	int16_t temp_raw = 0;
154 	int ret;
155 
156 	ret = i2c_reg_read_byte_dt(&cfg->i2c,
157 				ITDS_REG_STATUS_DETECT, &rval);
158 	if (ret) {
159 		return ret;
160 	}
161 
162 	if (!(rval & ITDS_EVENT_DRDY_T)) {
163 		return -EAGAIN;
164 	}
165 
166 	ret = i2c_burst_read_dt(&cfg->i2c, ITDS_REG_TEMP_L,
167 			     (uint8_t *)&temp_raw, sizeof(uint16_t));
168 	if (ret) {
169 		return ret;
170 	}
171 
172 	ddata->temperature = sys_le16_to_cpu(temp_raw);
173 
174 	return 0;
175 }
176 
itds_fetch_accel(struct itds_device_data * ddata,const struct itds_device_config * cfg)177 static int itds_fetch_accel(struct itds_device_data *ddata,
178 			    const struct itds_device_config *cfg)
179 {
180 	size_t i, ret;
181 	uint8_t rval;
182 
183 	ret = i2c_reg_read_byte_dt(&cfg->i2c,
184 				ITDS_REG_STATUS, &rval);
185 	if (ret) {
186 		return ret;
187 	}
188 
189 	if (!(rval & ITDS_EVENT_DRDY)) {
190 		return -EAGAIN;
191 	}
192 
193 	ret = i2c_burst_read_dt(&cfg->i2c, ITDS_REG_X_OUT_L,
194 			     (uint8_t *)ddata->samples,
195 			     sizeof(uint16_t) * ITDS_SAMPLE_SIZE);
196 	if (ret) {
197 		return ret;
198 	}
199 
200 	/* convert samples to cpu endianness */
201 	for (i = 0; i < ITDS_SAMPLE_SIZE; i += 2) {
202 		int16_t *sample =	(int16_t *) &ddata->samples[i];
203 
204 		*sample = sys_le16_to_cpu(*sample);
205 		if (ddata->op_mode & ITDS_OP_MODE_NORMAL ||
206 		    ddata->op_mode & ITDS_OP_MODE_HIGH_PERF) {
207 			*sample = *sample >> 2;
208 		} else {
209 			*sample = *sample >> 4;
210 		}
211 		LOG_DBG("itds sample %d %X\n", i, *sample);
212 	}
213 
214 	return 0;
215 }
216 
itds_sample_fetch(const struct device * dev,enum sensor_channel chan)217 static int itds_sample_fetch(const struct device *dev,
218 			     enum sensor_channel chan)
219 {
220 	struct itds_device_data *ddata = dev->data;
221 	const struct itds_device_config *cfg = dev->config;
222 
223 	switch (chan) {
224 	case SENSOR_CHAN_ACCEL_XYZ:
225 	case SENSOR_CHAN_ACCEL_X:
226 	case SENSOR_CHAN_ACCEL_Y:
227 	case SENSOR_CHAN_ACCEL_Z:
228 		return itds_fetch_accel(ddata, cfg);
229 
230 	case SENSOR_CHAN_DIE_TEMP:
231 		return itds_fetch_temperature(ddata, cfg);
232 
233 	case SENSOR_CHAN_ALL:
234 		return itds_fetch_accel(ddata, cfg) ||
235 		       itds_fetch_temperature(ddata, cfg);
236 
237 	default:
238 		return -EINVAL;
239 	}
240 }
241 
itds_accl_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)242 static inline void itds_accl_channel_get(const struct device *dev,
243 					 enum sensor_channel chan,
244 					 struct sensor_value *val)
245 {
246 	int i;
247 	struct itds_device_data *ddata = dev->data;
248 	uint8_t ofs_start, ofs_stop;
249 
250 	switch (chan) {
251 	case SENSOR_CHAN_ACCEL_X:
252 		ofs_start = ofs_stop = 0U;
253 		break;
254 	case SENSOR_CHAN_ACCEL_Y:
255 		ofs_start = ofs_stop = 1U;
256 		break;
257 	case SENSOR_CHAN_ACCEL_Z:
258 		ofs_start = ofs_stop = 2U;
259 		break;
260 	default:
261 		ofs_start = 0U; ofs_stop = 2U;
262 		break;
263 	}
264 
265 	for (i = ofs_start; i <= ofs_stop ; i++, val++) {
266 		int64_t dval;
267 
268 		/* Sensitivity is exposed in ug/LSB */
269 		/* Convert to m/s^2 */
270 		dval = (int64_t)((ddata->samples[i] * ddata->scale * SENSOR_G) /
271 				1000000LL);
272 		val->val1 = (int32_t)(dval / 1000000);
273 		val->val2 = (int32_t)(dval % 1000000);
274 	}
275 }
276 
itds_temp_channel_get(const struct device * dev,struct sensor_value * val)277 static int itds_temp_channel_get(const struct device *dev,
278 				 struct sensor_value *val)
279 {
280 	int32_t temp_processed;
281 	struct itds_device_data *ddata = dev->data;
282 
283 	temp_processed = (ddata->temperature >> 4) * ITDS_TEMP_CONST;
284 
285 	val->val1 = ITDS_TEMP_OFFSET;
286 	val->val2 = temp_processed;
287 
288 	return 0;
289 }
290 
itds_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)291 static int itds_channel_get(const struct device *dev,
292 			    enum sensor_channel chan,
293 			    struct sensor_value *val)
294 {
295 	switch (chan) {
296 	case SENSOR_CHAN_ACCEL_X:
297 	case SENSOR_CHAN_ACCEL_Y:
298 	case SENSOR_CHAN_ACCEL_Z:
299 	case SENSOR_CHAN_ACCEL_XYZ:
300 		itds_accl_channel_get(dev, chan, val);
301 		return 0;
302 
303 	case SENSOR_CHAN_DIE_TEMP:
304 		return itds_temp_channel_get(dev, val);
305 
306 	default:
307 		LOG_ERR("Channel not supported.");
308 		return -ENOTSUP;
309 	}
310 
311 	return 0;
312 }
313 
itds_init(const struct device * dev)314 static int itds_init(const struct device *dev)
315 {
316 	struct itds_device_data *ddata = dev->data;
317 	const struct itds_device_config *cfg = dev->config;
318 	int ret;
319 	uint16_t freq, mfreq;
320 	uint8_t rval;
321 
322 	if (!device_is_ready(cfg->i2c.bus)) {
323 		LOG_ERR("Bus device is not ready");
324 		return -ENODEV;
325 	}
326 
327 	ret = i2c_reg_read_byte_dt(&cfg->i2c,
328 				ITDS_REG_DEV_ID, &rval);
329 	if (ret) {
330 		LOG_ERR("device init fail: %d", ret);
331 		return ret;
332 	}
333 
334 	if (rval != ITDS_DEVICE_ID) {
335 		LOG_ERR("device ID mismatch: %x", rval);
336 		return ret;
337 	}
338 
339 	ret = i2c_reg_update_byte_dt(&cfg->i2c, ITDS_REG_CTRL2,
340 				  ITDS_MASK_BDU_INC_ADD, ITDS_MASK_BDU_INC_ADD);
341 	if (ret) {
342 		LOG_ERR("unable to set block data update %d", ret);
343 		return ret;
344 	}
345 
346 	ret = i2c_reg_write_byte_dt(&cfg->i2c, ITDS_REG_WAKEUP_EVENT, 0);
347 	if (ret) {
348 		LOG_ERR("disable wakeup event fail %d", ret);
349 		return ret;
350 	}
351 
352 	ret = i2c_reg_update_byte_dt(&cfg->i2c, ITDS_REG_CTRL1,
353 				     ITDS_MASK_MODE, 1 << cfg->def_op_mode);
354 	if (ret) {
355 		LOG_ERR("set operating mode fail %d", ret);
356 		return ret;
357 	}
358 
359 	ddata->op_mode = 1 << cfg->def_op_mode;
360 
361 	ret = itds_get_odr_for_index(dev, cfg->def_odr, &freq, &mfreq);
362 	if (ret) {
363 		LOG_ERR("odr not in range for operating mode %d", ret);
364 		return ret;
365 	}
366 
367 	ret = itds_accl_odr_set(dev, freq, mfreq);
368 	if (ret) {
369 		LOG_ERR("odr not in range for operating mode %d", ret);
370 		return ret;
371 	}
372 
373 #ifdef CONFIG_ITDS_TRIGGER
374 	ret = itds_trigger_mode_init(dev);
375 	if (ret) {
376 		LOG_ERR("trigger mode init failed %d", ret);
377 		return ret;
378 	}
379 #endif
380 	return 0;
381 }
382 
383 static const struct sensor_driver_api itds_api = {
384 	.attr_set = itds_attr_set,
385 #ifdef CONFIG_ITDS_TRIGGER
386 	.trigger_set = itds_trigger_set,
387 #endif
388 	.sample_fetch = itds_sample_fetch,
389 	.channel_get = itds_channel_get,
390 };
391 
392 #ifdef CONFIG_ITDS_TRIGGER
393 #define WSEN_ITDS_CFG_IRQ(inst)						\
394 	.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }),
395 #else
396 #define WSEN_ITDS_CFG_IRQ(inst)
397 #endif
398 
399 #define WSEN_ITDS_INIT(idx)						\
400 									\
401 static struct itds_device_data itds_data_##idx;				\
402 									\
403 static const struct itds_device_config itds_config_##idx = {		\
404 	.i2c = I2C_DT_SPEC_INST_GET(idx),				\
405 	.def_odr = DT_INST_ENUM_IDX(idx, odr),				\
406 	.def_op_mode = DT_INST_ENUM_IDX(idx, op_mode),			\
407 	WSEN_ITDS_CFG_IRQ(idx)						\
408 };									\
409 									\
410 SENSOR_DEVICE_DT_INST_DEFINE(idx, itds_init, NULL,			\
411 		    &itds_data_##idx, &itds_config_##idx,		\
412 		    POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,		\
413 		    &itds_api);						\
414 
415 DT_INST_FOREACH_STATUS_OKAY(WSEN_ITDS_INIT)
416