1 /*
2  * Copyright (c) 2023 Andriy Gelman <andriy.gelman@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT infineon_xmc4xxx_temp
8 
9 #include <xmc_scu.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/devicetree.h>
14 #include <zephyr/drivers/sensor.h>
15 
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(xmc4xxx_temp, CONFIG_SENSOR_LOG_LEVEL);
18 
19 struct xmc4xxx_temp_data {
20 	float temp_out;
21 };
22 
xmc4xxx_temp_sample_fetch(const struct device * dev,enum sensor_channel chan)23 static int xmc4xxx_temp_sample_fetch(const struct device *dev, enum sensor_channel chan)
24 {
25 	struct xmc4xxx_temp_data *data = dev->data;
26 	int32_t val;
27 	int ret;
28 
29 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
30 		return -ENOTSUP;
31 	}
32 
33 	ret = XMC_SCU_StartTemperatureMeasurement();
34 	if (ret != 0) {
35 		return -EBUSY;
36 	}
37 
38 	while (XMC_SCU_IsTemperatureSensorBusy()) {
39 	};
40 
41 	val = XMC_SCU_GetTemperatureMeasurement();
42 	/* See Infineon XMC4500 Reference Manual Section 11.2.5.1 */
43 	data->temp_out = (val - 605) / 2.05f;
44 
45 	return ret;
46 }
47 
xmc4xxx_temp_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)48 static int xmc4xxx_temp_channel_get(const struct device *dev, enum sensor_channel chan,
49 				    struct sensor_value *val)
50 {
51 	struct xmc4xxx_temp_data *data = dev->data;
52 
53 	if (chan != SENSOR_CHAN_DIE_TEMP) {
54 		return -ENOTSUP;
55 	}
56 
57 	return sensor_value_from_double(val, data->temp_out);
58 }
59 
60 static DEVICE_API(sensor, xmc4xxx_temp_driver_api) = {
61 	.sample_fetch = xmc4xxx_temp_sample_fetch,
62 	.channel_get = xmc4xxx_temp_channel_get,
63 };
64 
xmc4xxx_temp_init(const struct device * dev)65 static int xmc4xxx_temp_init(const struct device *dev)
66 {
67 	ARG_UNUSED(dev);
68 	XMC_SCU_EnableTemperatureSensor();
69 
70 	BUILD_ASSERT(CONFIG_XMC4XXX_TEMP_CALIBRATE_OFFSET >= -64 &&
71 		     CONFIG_XMC4XXX_TEMP_CALIBRATE_OFFSET <= 63);
72 
73 	BUILD_ASSERT(CONFIG_XMC4XXX_TEMP_CALIBRATE_GAIN >= 0 &&
74 		     CONFIG_XMC4XXX_TEMP_CALIBRATE_OFFSET <= 63);
75 
76 	XMC_SCU_CalibrateTemperatureSensor(CONFIG_XMC4XXX_TEMP_CALIBRATE_OFFSET & 0x7f,
77 					   CONFIG_XMC4XXX_TEMP_CALIBRATE_GAIN);
78 	return 0;
79 }
80 
81 #define XMC4XXX_TEMP_DEFINE(inst)								\
82 	static struct xmc4xxx_temp_data xmc4xxx_temp_dev_data_##inst;				\
83 												\
84 	SENSOR_DEVICE_DT_INST_DEFINE(inst, xmc4xxx_temp_init, NULL,				\
85 			      &xmc4xxx_temp_dev_data_##inst, NULL,				\
86 			      POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,				\
87 			      &xmc4xxx_temp_driver_api);					\
88 
89 DT_INST_FOREACH_STATUS_OKAY(XMC4XXX_TEMP_DEFINE)
90