1 /*
2  * Copyright (c) 2025 Würth Elektronik eiSos GmbH & Co. KG
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT we_wsen_tids_2521020222501
8 
9 #include <stdlib.h>
10 
11 #include <zephyr/sys/__assert.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/logging/log.h>
14 
15 #include "wsen_tids_2521020222501.h"
16 
17 LOG_MODULE_REGISTER(WSEN_TIDS_2521020222501, CONFIG_SENSOR_LOG_LEVEL);
18 
19 static const struct sensor_value tids_2521020222501_odr_list[] = {{.val1 = 0, .val2 = 0},
20 								  {.val1 = 25, .val2 = 0},
21 								  {.val1 = 50, .val2 = 0},
22 								  {.val1 = 100, .val2 = 0},
23 								  {.val1 = 200, .val2 = 0}};
24 
tids_2521020222501_sample_fetch(const struct device * dev,enum sensor_channel chan)25 static int tids_2521020222501_sample_fetch(const struct device *dev, enum sensor_channel chan)
26 {
27 	struct tids_2521020222501_data *data = dev->data;
28 	int16_t raw_temperature;
29 
30 	switch (chan) {
31 	case SENSOR_CHAN_ALL:
32 	case SENSOR_CHAN_AMBIENT_TEMP:
33 		break;
34 	default:
35 		LOG_ERR("Fetching is not supported on channel %d.", chan);
36 		return -ENOTSUP;
37 	}
38 	if (data->sensor_odr == ((uint8_t)tids_2521020222501_odr_list[0].val1)) {
39 
40 		TIDS_softReset(&data->sensor_interface, TIDS_enable);
41 
42 		k_sleep(K_USEC(5));
43 
44 		TIDS_softReset(&data->sensor_interface, TIDS_disable);
45 
46 		if (TIDS_enableOneShot(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) {
47 			LOG_ERR("Failed to enable one shot");
48 			return -EIO;
49 		}
50 
51 		TIDS_state_t busy = TIDS_enable;
52 
53 		do {
54 			if (TIDS_isBusy(&data->sensor_interface, &busy) != WE_SUCCESS) {
55 				LOG_ERR("Failed to check for data ready");
56 				return -EIO;
57 			}
58 		} while (TIDS_enable == busy);
59 	}
60 
61 	if (TIDS_getRawTemperature(&data->sensor_interface, &raw_temperature) != WE_SUCCESS) {
62 		LOG_ERR("Failed to fetch data sample");
63 		return -EIO;
64 	}
65 
66 	data->temperature = raw_temperature;
67 
68 	return 0;
69 }
70 
tids_2521020222501_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)71 static int tids_2521020222501_channel_get(const struct device *dev, enum sensor_channel chan,
72 					  struct sensor_value *val)
73 {
74 	struct tids_2521020222501_data *data = dev->data;
75 
76 	switch (chan) {
77 	case SENSOR_CHAN_AMBIENT_TEMP:
78 		/* Convert temperature from 0.01 degrees Celsius to degrees Celsius */
79 		val->val1 = data->temperature / 100;
80 		val->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100);
81 		break;
82 	default:
83 		LOG_ERR("Channel not supported %d", chan);
84 		return -ENOTSUP;
85 	}
86 
87 	return 0;
88 }
89 
90 /* Set output data rate. See tids_2521020222501_odr_list for allowed values. */
tids_2521020222501_odr_set(const struct device * dev,const struct sensor_value * odr)91 static int tids_2521020222501_odr_set(const struct device *dev, const struct sensor_value *odr)
92 {
93 	struct tids_2521020222501_data *data = dev->data;
94 
95 	int odr_index;
96 
97 	for (odr_index = 0; odr_index < ARRAY_SIZE(tids_2521020222501_odr_list); odr_index++) {
98 		if (odr->val1 == tids_2521020222501_odr_list[odr_index].val1 &&
99 		    odr->val2 == tids_2521020222501_odr_list[odr_index].val2) {
100 			break;
101 		}
102 	}
103 
104 	if (odr_index == ARRAY_SIZE(tids_2521020222501_odr_list)) {
105 		/* ODR not allowed (was not found in tids_2521020222501_odr_list) */
106 		LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2);
107 		return -EINVAL;
108 	}
109 
110 	if (odr->val1 == tids_2521020222501_odr_list[0].val1) {
111 		if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_disable) !=
112 		    WE_SUCCESS) {
113 			LOG_ERR("Failed to enable block data update.");
114 			return -EIO;
115 		}
116 
117 		if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_disable) !=
118 		    WE_SUCCESS) {
119 			LOG_ERR("Failed to enable continuous mode.");
120 			return -EIO;
121 		}
122 	} else {
123 		if (TIDS_setOutputDataRate(&data->sensor_interface,
124 					   (TIDS_outputDataRate_t)(odr->val1 - 1)) != WE_SUCCESS) {
125 			LOG_ERR("Failed to set output data rate");
126 			return -EIO;
127 		}
128 
129 		if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_enable) !=
130 		    WE_SUCCESS) {
131 			LOG_ERR("Failed to enable block data update.");
132 			return -EIO;
133 		}
134 
135 		if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) {
136 			LOG_ERR("Failed to enable continuous mode.");
137 			return -EIO;
138 		}
139 	}
140 
141 	data->sensor_odr = (uint8_t)odr->val1;
142 
143 	return 0;
144 }
145 
146 /* Get output data rate. */
tids_2521020222501_odr_get(const struct device * dev,struct sensor_value * odr)147 static int tids_2521020222501_odr_get(const struct device *dev, struct sensor_value *odr)
148 {
149 
150 	struct tids_2521020222501_data *data = dev->data;
151 
152 	TIDS_state_t continuous_mode_state;
153 
154 	if (TIDS_isContinuousModeEnabled(&data->sensor_interface, &continuous_mode_state) !=
155 	    WE_SUCCESS) {
156 		LOG_ERR("Failed to get continuous mode.");
157 		return -EIO;
158 	}
159 
160 	if (continuous_mode_state == TIDS_disable) {
161 		odr->val1 = tids_2521020222501_odr_list[0].val1;
162 	} else {
163 		TIDS_outputDataRate_t odrIndex;
164 
165 		if (TIDS_getOutputDataRate(&data->sensor_interface, &odrIndex) != WE_SUCCESS) {
166 			LOG_ERR("Failed to get output data rate");
167 			return -EIO;
168 		}
169 
170 		odr->val1 = tids_2521020222501_odr_list[odrIndex + 1].val1;
171 	}
172 
173 	data->sensor_odr = (uint8_t)odr->val1;
174 
175 	odr->val2 = 0;
176 
177 	return 0;
178 }
179 
tids_2521020222501_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)180 static int tids_2521020222501_attr_set(const struct device *dev, enum sensor_channel chan,
181 				       enum sensor_attribute attr, const struct sensor_value *val)
182 {
183 
184 	switch (chan) {
185 	case SENSOR_CHAN_ALL:
186 	case SENSOR_CHAN_AMBIENT_TEMP:
187 		break;
188 	default:
189 		LOG_ERR("attr_set() is not supported on channel %d.", chan);
190 		return -ENOTSUP;
191 	}
192 
193 	switch (attr) {
194 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
195 		return tids_2521020222501_odr_set(dev, val);
196 #ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER
197 	case SENSOR_ATTR_LOWER_THRESH:
198 		return tids_2521020222501_threshold_lower_set(dev, val);
199 	case SENSOR_ATTR_UPPER_THRESH:
200 		return tids_2521020222501_threshold_upper_set(dev, val);
201 #endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */
202 
203 	default:
204 		LOG_ERR("Operation not supported.");
205 		return -ENOTSUP;
206 	}
207 }
208 
tids_2521020222501_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)209 static int tids_2521020222501_attr_get(const struct device *dev, enum sensor_channel chan,
210 				       enum sensor_attribute attr, struct sensor_value *val)
211 {
212 
213 	if (val == NULL) {
214 		LOG_WRN("address of passed value is NULL.");
215 		return -EFAULT;
216 	}
217 
218 	switch (chan) {
219 	case SENSOR_CHAN_ALL:
220 	case SENSOR_CHAN_AMBIENT_TEMP:
221 		break;
222 	default:
223 		LOG_ERR("attr_get() is not supported on channel %d.", chan);
224 		return -ENOTSUP;
225 	}
226 
227 	switch (attr) {
228 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
229 		return tids_2521020222501_odr_get(dev, val);
230 #ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER
231 	case SENSOR_ATTR_LOWER_THRESH:
232 		return tids_2521020222501_threshold_lower_get(dev, val);
233 	case SENSOR_ATTR_UPPER_THRESH:
234 		return tids_2521020222501_threshold_upper_get(dev, val);
235 #endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */
236 	default:
237 		LOG_ERR("Operation not supported.");
238 		return -ENOTSUP;
239 	}
240 
241 	return 0;
242 }
243 
244 static DEVICE_API(sensor, tids_2521020222501_driver_api) = {
245 	.attr_set = tids_2521020222501_attr_set,
246 #if CONFIG_WSEN_TIDS_2521020222501_TRIGGER
247 	.trigger_set = tids_2521020222501_trigger_set,
248 #endif
249 	.attr_get = tids_2521020222501_attr_get,
250 	.sample_fetch = tids_2521020222501_sample_fetch,
251 	.channel_get = tids_2521020222501_channel_get,
252 };
253 
tids_2521020222501_init(const struct device * dev)254 static int tids_2521020222501_init(const struct device *dev)
255 {
256 	const struct tids_2521020222501_config *const config = dev->config;
257 	struct tids_2521020222501_data *data = dev->data;
258 	uint8_t device_id;
259 
260 	/* Initialize WE sensor interface */
261 	TIDS_getDefaultInterface(&data->sensor_interface);
262 	data->sensor_interface.interfaceType = WE_i2c;
263 	if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) {
264 		LOG_ERR("I2C bus device not ready");
265 		return -ENODEV;
266 	}
267 	data->sensor_interface.handle = (void *)&config->bus_cfg.i2c;
268 
269 	/* Needed after power up */
270 	k_sleep(K_MSEC(12));
271 
272 	/* First communication test - check device ID */
273 	if (TIDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) {
274 		LOG_ERR("Failed to read device ID.");
275 		return -EIO;
276 	}
277 
278 	if (device_id != TIDS_DEVICE_ID_VALUE) {
279 		LOG_ERR("Invalid device ID 0x%x.", device_id);
280 		return -EIO;
281 	}
282 
283 	/* Reset the sensor with an arbitrary off time of 5 us */
284 	TIDS_softReset(&data->sensor_interface, TIDS_enable);
285 	k_sleep(K_USEC(5));
286 	TIDS_softReset(&data->sensor_interface, TIDS_disable);
287 
288 	if (tids_2521020222501_odr_set(dev, &tids_2521020222501_odr_list[config->odr]) < 0) {
289 		LOG_ERR("Failed to set output data rate.");
290 		return -EIO;
291 	}
292 
293 #ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER
294 	if (tids_2521020222501_init_interrupt(dev) < 0) {
295 		LOG_ERR("Failed to initialize interrupt.");
296 		return -EIO;
297 	}
298 #endif
299 
300 	return 0;
301 }
302 
303 #ifdef CONFIG_WSEN_TIDS_2521020222501_TRIGGER
304 #define TIDS_2521020222501_CFG_IRQ(inst)                                                           \
305 	.interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, interrupt_gpios),                            \
306 	.high_threshold = DT_INST_PROP(inst, temp_high_threshold),                                 \
307 	.low_threshold = DT_INST_PROP(inst, temp_low_threshold)
308 #else
309 #define TIDS_2521020222501_CFG_IRQ(inst)
310 #endif /* CONFIG_WSEN_TIDS_2521020222501_TRIGGER */
311 
312 /*
313  * Main instantiation macro.
314  */
315 #define TIDS_2521020222501_DEFINE(inst)                                                            \
316 	static struct tids_2521020222501_data tids_2521020222501_data_##inst;                      \
317 	static const struct tids_2521020222501_config tids_2521020222501_config_##inst = {         \
318 		.bus_cfg =                                                                         \
319 			{                                                                          \
320 				.i2c = I2C_DT_SPEC_INST_GET(inst),                                 \
321 			},                                                                         \
322 		.odr = (uint8_t)(DT_INST_ENUM_IDX(inst, odr)),                                     \
323 		COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, interrupt_gpios),                          \
324 			    (TIDS_2521020222501_CFG_IRQ(inst)), ())};         \
325 	SENSOR_DEVICE_DT_INST_DEFINE(inst, tids_2521020222501_init, NULL,                          \
326 				     &tids_2521020222501_data_##inst,                              \
327 				     &tids_2521020222501_config_##inst, POST_KERNEL,               \
328 				     CONFIG_SENSOR_INIT_PRIORITY, &tids_2521020222501_driver_api);
329 
330 DT_INST_FOREACH_STATUS_OKAY(TIDS_2521020222501_DEFINE)
331