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_pads_2511020213301
8 
9 #include <string.h>
10 
11 #include <zephyr/sys/__assert.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/logging/log.h>
14 
15 #include "wsen_pads_2511020213301.h"
16 
17 LOG_MODULE_REGISTER(WSEN_PADS_2511020213301, CONFIG_SENSOR_LOG_LEVEL);
18 
19 /*
20  * List of supported output data rates. Index into this list is used as
21  * argument for PADS_setOutputDataRate()
22  */
23 static const int32_t pads_2511020213301_odr_list[] = {
24 	0, 1, 10, 25, 50, 75, 100, 200,
25 };
26 
27 #define SAMPLES_TO_DISCARD (uint8_t)2
28 
29 #define MAX_POLL_STEP_COUNT 10
30 
pads_2511020213301_sample_fetch(const struct device * dev,enum sensor_channel channel)31 static int pads_2511020213301_sample_fetch(const struct device *dev, enum sensor_channel channel)
32 {
33 	struct pads_2511020213301_data *data = dev->data;
34 	const struct pads_2511020213301_config *cfg = dev->config;
35 
36 	switch (channel) {
37 	case SENSOR_CHAN_ALL:
38 	case SENSOR_CHAN_AMBIENT_TEMP:
39 	case SENSOR_CHAN_PRESS:
40 		break;
41 	default:
42 		LOG_ERR("Fetching is not supported on channel %d.", channel);
43 		return -ENOTSUP;
44 	}
45 
46 	if (data->sensor_odr == PADS_outputDataRatePowerDown) {
47 		if (PADS_enableOneShot(&data->sensor_interface, PADS_enable) != WE_SUCCESS) {
48 			LOG_ERR("Failed to fetch %s sample.", "pressure");
49 			return -EIO;
50 		}
51 
52 		switch (cfg->configuration) {
53 		case PADS_lowPower:
54 			k_sleep(K_USEC(4700));
55 			break;
56 		case PADS_lowNoise:
57 			k_sleep(K_USEC(13200));
58 			break;
59 		default:
60 			LOG_ERR("Invalid sensor configuration");
61 			return -EIO;
62 		}
63 
64 		PADS_state_t one_shot_state;
65 
66 		do {
67 			if (PADS_isOneShotEnabled(&data->sensor_interface, &one_shot_state) !=
68 			    WE_SUCCESS) {
69 				LOG_ERR("Failed to check for data ready");
70 				return -EIO;
71 			}
72 		} while (PADS_enable == one_shot_state);
73 	} else {
74 
75 		bool data_ready = false;
76 		int step_count = 0;
77 		uint32_t step_sleep_duration =
78 			((uint32_t)1000000000 /
79 			 (pads_2511020213301_odr_list[data->sensor_odr] * 1000)) /
80 			MAX_POLL_STEP_COUNT;
81 
82 		while (1) {
83 			PADS_state_t pressure_state, temp_state;
84 
85 			pressure_state = temp_state = PADS_disable;
86 
87 			if (PADS_isDataAvailable(&data->sensor_interface, &temp_state,
88 						 &pressure_state) != WE_SUCCESS) {
89 				LOG_ERR("Failed to check for data available");
90 				return -EIO;
91 			}
92 
93 			switch (channel) {
94 			case SENSOR_CHAN_ALL:
95 				data_ready = (pressure_state == PADS_enable &&
96 					      temp_state == PADS_enable);
97 				break;
98 			case SENSOR_CHAN_AMBIENT_TEMP:
99 				data_ready = (temp_state == PADS_enable);
100 				break;
101 			case SENSOR_CHAN_PRESS:
102 				data_ready = (pressure_state == PADS_enable);
103 				break;
104 			default:
105 				break;
106 			}
107 
108 			if (data_ready) {
109 				break;
110 			} else if (step_count >= MAX_POLL_STEP_COUNT) {
111 				return -EIO;
112 			}
113 
114 			step_count++;
115 			k_sleep(K_USEC(step_sleep_duration));
116 		}
117 	}
118 
119 	switch (channel) {
120 	case SENSOR_CHAN_ALL: {
121 
122 		if (PADS_getPressure_int(&data->sensor_interface, &data->pressure) != WE_SUCCESS) {
123 			LOG_ERR("Failed to fetch %s sample.", "pressure");
124 			return -EIO;
125 		}
126 
127 		if (PADS_getTemperature_int(&data->sensor_interface, &data->temperature) !=
128 		    WE_SUCCESS) {
129 			LOG_ERR("Failed to fetch %s sample.", "temperature");
130 			return -EIO;
131 		}
132 
133 		break;
134 	}
135 	case SENSOR_CHAN_AMBIENT_TEMP: {
136 
137 		if (PADS_getTemperature_int(&data->sensor_interface, &data->temperature) !=
138 		    WE_SUCCESS) {
139 			LOG_ERR("Failed to fetch %s sample.", "temperature");
140 			return -EIO;
141 		}
142 
143 		break;
144 	}
145 	case SENSOR_CHAN_PRESS: {
146 
147 		if (PADS_getPressure_int(&data->sensor_interface, &data->pressure) != WE_SUCCESS) {
148 			LOG_ERR("Failed to fetch %s sample.", "pressure");
149 			return -EIO;
150 		}
151 
152 		break;
153 	}
154 	default:
155 		break;
156 	}
157 
158 	return 0;
159 }
160 
pads_2511020213301_channel_get(const struct device * dev,enum sensor_channel channel,struct sensor_value * value)161 static int pads_2511020213301_channel_get(const struct device *dev, enum sensor_channel channel,
162 					  struct sensor_value *value)
163 {
164 	struct pads_2511020213301_data *data = dev->data;
165 
166 	switch (channel) {
167 	case SENSOR_CHAN_AMBIENT_TEMP:
168 		/* Convert temperature from 0.01 degrees Celsius to degrees Celsius */
169 		value->val1 = data->temperature / 100;
170 		value->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100);
171 		break;
172 	case SENSOR_CHAN_PRESS:
173 		/* Convert pressure from Pa to kPa */
174 		value->val1 = data->pressure / 1000;
175 		value->val2 = ((int32_t)data->pressure % 1000) * (1000000 / 1000);
176 		break;
177 	default:
178 		LOG_ERR("Channel not supported %d", channel);
179 		return -ENOTSUP;
180 	}
181 
182 	return 0;
183 }
184 
185 /* Set output data rate. See pads_2511020213301_odr_list for allowed values. */
pads_2511020213301_odr_set(const struct device * dev,const struct sensor_value * odr)186 static int pads_2511020213301_odr_set(const struct device *dev, const struct sensor_value *odr)
187 {
188 	struct pads_2511020213301_data *data = dev->data;
189 	const struct pads_2511020213301_config *cfg = dev->config;
190 	int odr_index;
191 
192 	for (odr_index = 0; odr_index < ARRAY_SIZE(pads_2511020213301_odr_list); odr_index++) {
193 		if (odr->val1 == pads_2511020213301_odr_list[odr_index] && odr->val2 == 0) {
194 			break;
195 		}
196 	}
197 
198 	if (odr_index == ARRAY_SIZE(pads_2511020213301_odr_list)) {
199 		/* ODR not allowed (was not found in pads_2511020213301_odr_list) */
200 		LOG_ERR("Bad sampling frequency %d.%d", odr->val1, odr->val2);
201 		return -EINVAL;
202 	}
203 
204 	if (cfg->configuration == PADS_lowNoise &&
205 	    (PADS_outputDataRate_t)odr_index > PADS_outputDataRate75Hz) {
206 		LOG_ERR("Failed to set ODR > 75Hz is not possible with low noise sensor "
207 			"configuration.");
208 		return -EIO;
209 	}
210 
211 	if (PADS_setOutputDataRate(&data->sensor_interface, (PADS_outputDataRate_t)odr_index) !=
212 	    WE_SUCCESS) {
213 		LOG_ERR("Failed to set output data rate");
214 		return -EIO;
215 	}
216 
217 	if (PADS_enableBlockDataUpdate(&data->sensor_interface,
218 				       (PADS_outputDataRate_t)odr_index !=
219 						       PADS_outputDataRatePowerDown
220 					       ? PADS_enable
221 					       : PADS_disable) != WE_SUCCESS) {
222 		LOG_ERR("Failed to enable block data update.");
223 		return -EIO;
224 	}
225 
226 	data->sensor_odr = (PADS_outputDataRate_t)odr_index;
227 
228 	return 0;
229 }
230 
231 /* Get output data rate. */
pads_2511020213301_odr_get(const struct device * dev,struct sensor_value * odr)232 static int pads_2511020213301_odr_get(const struct device *dev, struct sensor_value *odr)
233 {
234 
235 	struct pads_2511020213301_data *data = dev->data;
236 
237 	PADS_outputDataRate_t odr_index;
238 
239 	if (PADS_getOutputDataRate(&data->sensor_interface, &odr_index) != WE_SUCCESS) {
240 		LOG_ERR("Failed to get output data rate");
241 		return -EIO;
242 	}
243 
244 	data->sensor_odr = odr_index;
245 
246 	odr->val1 = pads_2511020213301_odr_list[odr_index];
247 	odr->val2 = 0;
248 
249 	return 0;
250 }
251 
pads_2511020213301_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)252 static int pads_2511020213301_attr_get(const struct device *dev, enum sensor_channel chan,
253 				       enum sensor_attribute attr, struct sensor_value *val)
254 {
255 
256 	if (val == NULL) {
257 		LOG_WRN("address of passed value is NULL.");
258 		return -EFAULT;
259 	}
260 
261 	switch ((int)attr) {
262 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
263 		if (chan != SENSOR_CHAN_ALL) {
264 			LOG_ERR("attr_get() is not supported on channel %d.", chan);
265 			return -ENOTSUP;
266 		}
267 		return pads_2511020213301_odr_get(dev, val);
268 #ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD
269 	case SENSOR_ATTR_WSEN_PADS_2511020213301_REFERENCE_POINT:
270 		if (chan != SENSOR_CHAN_PRESS) {
271 			LOG_ERR("attr_get() is not supported on channel %d.", chan);
272 			return -ENOTSUP;
273 		}
274 		return pads_2511020213301_reference_point_get(dev, val);
275 	case SENSOR_ATTR_UPPER_THRESH:
276 	case SENSOR_ATTR_LOWER_THRESH:
277 		if (chan != SENSOR_CHAN_PRESS) {
278 			LOG_ERR("attr_get() is not supported on channel %d.", chan);
279 			return -ENOTSUP;
280 		}
281 		return pads_2511020213301_threshold_get(dev, val);
282 #endif
283 	default:
284 		LOG_ERR("Operation not supported.");
285 		return -ENOTSUP;
286 	}
287 
288 	return 0;
289 }
290 
pads_2511020213301_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)291 static int pads_2511020213301_attr_set(const struct device *dev, enum sensor_channel chan,
292 				       enum sensor_attribute attr, const struct sensor_value *val)
293 {
294 	switch ((int)attr) {
295 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
296 		if (chan != SENSOR_CHAN_ALL) {
297 			LOG_ERR("attr_set() is not supported on channel %d.", chan);
298 			return -ENOTSUP;
299 		}
300 		return pads_2511020213301_odr_set(dev, val);
301 #ifdef CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD
302 	case SENSOR_ATTR_WSEN_PADS_2511020213301_REFERENCE_POINT:
303 		if (chan != SENSOR_CHAN_PRESS) {
304 			LOG_ERR("attr_set() is not supported on channel %d.", chan);
305 			return -ENOTSUP;
306 		}
307 		return pads_2511020213301_reference_point_set(dev, val);
308 	case SENSOR_ATTR_UPPER_THRESH:
309 	case SENSOR_ATTR_LOWER_THRESH:
310 		if (chan != SENSOR_CHAN_PRESS) {
311 			LOG_ERR("attr_set() is not supported on channel %d.", chan);
312 			return -ENOTSUP;
313 		}
314 		return pads_2511020213301_threshold_set(dev, val);
315 #endif
316 	default:
317 		LOG_ERR("Operation not supported.");
318 		return -ENOTSUP;
319 	}
320 }
321 
322 static DEVICE_API(sensor, pads_2511020213301_driver_api) = {
323 	.attr_set = pads_2511020213301_attr_set,
324 #if CONFIG_WSEN_PADS_2511020213301_TRIGGER
325 	.trigger_set = pads_2511020213301_trigger_set,
326 #endif
327 	.attr_get = pads_2511020213301_attr_get,
328 	.sample_fetch = pads_2511020213301_sample_fetch,
329 	.channel_get = pads_2511020213301_channel_get,
330 };
331 
pads_2511020213301_init(const struct device * dev)332 static int pads_2511020213301_init(const struct device *dev)
333 {
334 	const struct pads_2511020213301_config *config = dev->config;
335 	struct pads_2511020213301_data *data = dev->data;
336 	struct sensor_value odr;
337 	uint8_t device_id;
338 
339 	/* Initialize WE sensor interface */
340 	WE_sensorInterfaceType_t interface_type = data->sensor_interface.interfaceType;
341 
342 	PADS_getDefaultInterface(&data->sensor_interface);
343 	data->sensor_interface.interfaceType = interface_type;
344 
345 	switch (data->sensor_interface.interfaceType) {
346 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
347 	case WE_i2c:
348 		if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) {
349 			LOG_ERR("I2C bus device not ready");
350 			return -ENODEV;
351 		}
352 		data->sensor_interface.handle = (void *)&config->bus_cfg.i2c;
353 		break;
354 #endif
355 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
356 	case WE_spi:
357 		if (!spi_is_ready_dt(&config->bus_cfg.spi)) {
358 			LOG_ERR("SPI bus device not ready");
359 			return -ENODEV;
360 		}
361 		data->sensor_interface.handle = (void *)&config->bus_cfg.spi;
362 		break;
363 #endif
364 	default:
365 		LOG_ERR("Invalid interface type");
366 		return -EINVAL;
367 	}
368 
369 	/* needed after power up */
370 	k_sleep(K_USEC(4500));
371 
372 	PADS_state_t boot_state = PADS_enable;
373 
374 	do {
375 		if (PADS_getBootStatus(&data->sensor_interface, &boot_state) != WE_SUCCESS) {
376 			LOG_ERR("Failed to get sensor reset state.");
377 			return -EIO;
378 		}
379 	} while (PADS_enable == boot_state);
380 
381 	/* First communication test - check device ID */
382 	if (PADS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) {
383 		LOG_ERR("Failed to read device ID.");
384 		return -EIO;
385 	}
386 
387 	if (device_id != PADS_DEVICE_ID_VALUE) {
388 		LOG_ERR("Invalid device ID 0x%x.", device_id);
389 		return -EINVAL;
390 	}
391 
392 	/* Reset sensor */
393 	PADS_softReset(&data->sensor_interface, PADS_enable);
394 	k_sleep(K_USEC(50));
395 
396 	PADS_state_t sw_reset;
397 
398 	do {
399 		if (PADS_getSoftResetState(&data->sensor_interface, &sw_reset) != WE_SUCCESS) {
400 			LOG_ERR("Failed to get sensor reset state.");
401 			return -EIO;
402 		}
403 	} while (PADS_enable == sw_reset);
404 
405 	if (PADS_setPowerMode(&data->sensor_interface, config->configuration) != WE_SUCCESS) {
406 		LOG_ERR("Failed to set sensor configuration.");
407 		return -EIO;
408 	}
409 
410 	odr.val1 = pads_2511020213301_odr_list[config->odr];
411 	odr.val2 = 0;
412 
413 	if (pads_2511020213301_odr_set(dev, &odr) < 0) {
414 		LOG_ERR("Failed to set output data rate.");
415 		return -EIO;
416 	}
417 
418 	if (PADS_enableLowPassFilter(&data->sensor_interface, config->alpf) != WE_SUCCESS) {
419 		LOG_ERR("Failed to set additional low pass filter.");
420 		return -EIO;
421 	}
422 
423 	if (config->alpf == PADS_enable) {
424 		if (PADS_setLowPassFilterConfig(&data->sensor_interface,
425 						config->alpf_configuration) != WE_SUCCESS) {
426 			LOG_ERR("Failed to set additional low pass filter configuration.");
427 			return -EIO;
428 		}
429 
430 		for (uint8_t i = 0; i < SAMPLES_TO_DISCARD; i++) {
431 			pads_2511020213301_sample_fetch(dev, SENSOR_CHAN_ALL);
432 		}
433 
434 		data->pressure = 0;
435 		data->temperature = 0;
436 	}
437 
438 #if CONFIG_WSEN_PADS_2511020213301_TRIGGER
439 	if (pads_2511020213301_init_interrupt(dev) < 0) {
440 		LOG_ERR("Failed to initialize interrupt.");
441 		return -EIO;
442 	}
443 #endif
444 
445 	return 0;
446 }
447 
448 #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
449 #warning "PADS driver enabled without any devices"
450 #endif
451 
452 #ifdef CONFIG_WSEN_PADS_2511020213301_TRIGGER
453 #define PADS_2511020213301_CFG_IRQ(inst)                                                           \
454 	.interrupt_gpio = GPIO_DT_SPEC_INST_GET(inst, interrupt_gpios)
455 #else
456 #define PADS_2511020213301_CFG_IRQ(inst)
457 #endif /* CONFIG_WSEN_PADS_2511020213301_TRIGGER */
458 
459 #define PADS_2511020213301_CFG_ALPF(inst)                                                          \
460 	.alpf = COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, additional_low_pass_filter),            \
461 		(PADS_enable), (PADS_disable))
462 
463 #define PADS_2511020213301_CONFIG_COMMON(inst)                                                     \
464 	.odr = (PADS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr)),                               \
465 	.configuration = (PADS_powerMode_t)(DT_INST_ENUM_IDX(inst, configuration)),                \
466 	.alpf_configuration =                                                                      \
467 		(PADS_filterConf_t)DT_INST_PROP(inst, additional_low_pass_filter_configuration),   \
468 	PADS_2511020213301_CFG_ALPF(inst),                                                         \
469 	IF_ENABLED(CONFIG_WSEN_PADS_2511020213301_PRESSURE_THRESHOLD, \
470 	(.threshold = (uint16_t)DT_INST_PROP_OR(inst, threshold, 0),))                            \
471 			    COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, interrupt_gpios),		\
472 	(PADS_2511020213301_CFG_IRQ(inst)), ())
473 
474 /*
475  * Instantiation macros used when device is on SPI bus.
476  */
477 
478 #define PADS_2511020213301_SPI_OPERATION                                                           \
479 	(SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA)
480 
481 #define PADS_2511020213301_CONFIG_SPI(inst)                                                        \
482 	{.bus_cfg =                                                                                \
483 		 {                                                                                 \
484 			 .spi = SPI_DT_SPEC_INST_GET(inst, PADS_2511020213301_SPI_OPERATION, 0),   \
485 		 },                                                                                \
486 	 PADS_2511020213301_CONFIG_COMMON(inst)}
487 
488 /*
489  * Instantiation macros used when device is on I2C bus.
490  */
491 
492 #define PADS_2511020213301_CONFIG_I2C(inst)                                                        \
493 	{.bus_cfg =                                                                                \
494 		 {                                                                                 \
495 			 .i2c = I2C_DT_SPEC_INST_GET(inst),                                        \
496 		 },                                                                                \
497 	 PADS_2511020213301_CONFIG_COMMON(inst)}
498 
499 #define PADS_2511020213301_CONFIG_WE_INTERFACE(inst)                                               \
500 	{COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \
501 		(.sensor_interface = {.interfaceType = WE_i2c}), \
502 		()) COND_CODE_1(DT_INST_ON_BUS(inst, spi),  \
503 		(.sensor_interface = {.interfaceType = WE_spi}), \
504 		()) }
505 
506 /*
507  * Main instantiation macro. Use of COND_CODE_1() selects the right
508  * bus-specific macro at preprocessor time.
509  */
510 #define PADS_2511020213301_DEFINE(inst)                                                            \
511 	static struct pads_2511020213301_data pads_2511020213301_data_##inst =                     \
512 		PADS_2511020213301_CONFIG_WE_INTERFACE(inst);                                      \
513 	static const struct pads_2511020213301_config pads_2511020213301_config_##inst =           \
514 		COND_CODE_1(DT_INST_ON_BUS(inst, i2c),\
515 		(PADS_2511020213301_CONFIG_I2C(inst)), \
516 		())                                            \
517 				COND_CODE_1(DT_INST_ON_BUS(inst, spi),  \
518 		(PADS_2511020213301_CONFIG_SPI(inst)),\
519 		());       \
520 	SENSOR_DEVICE_DT_INST_DEFINE(inst, pads_2511020213301_init, NULL,                          \
521 				     &pads_2511020213301_data_##inst,                              \
522 				     &pads_2511020213301_config_##inst, POST_KERNEL,               \
523 				     CONFIG_SENSOR_INIT_PRIORITY, &pads_2511020213301_driver_api);
524 
525 DT_INST_FOREACH_STATUS_OKAY(PADS_2511020213301_DEFINE)
526