1 /*
2  * Copyright (c) 2024 Aurelien Jarno
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT st_stm32_digi_temp
8 
9 #include <zephyr/device.h>
10 #include <zephyr/pm/device.h>
11 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
12 #include <zephyr/drivers/sensor.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/logging/log.h>
15 
16 LOG_MODULE_REGISTER(stm32_digi_temp, CONFIG_SENSOR_LOG_LEVEL);
17 
18 /* Constants */
19 #define ONE_MHZ			1000000 /* Hz */
20 #define TS1_T0_VAL0		30	/* °C */
21 #define TS1_T0_VAL1		130	/* °C */
22 #define SAMPLING_TIME		15	/* best precision */
23 
24 struct stm32_digi_temp_data {
25 	struct k_sem sem_isr;
26 	struct k_mutex mutex;
27 
28 	/* Peripheral clock frequency */
29 	uint32_t pclk_freq;
30 	/* Engineering value of the frequency measured at T0 in Hz */
31 	uint32_t t0_freq;
32 	/* Engineering value of the T0 temperature in °C */
33 	uint16_t t0;
34 	/* Engineering value of the ramp coefficient in Hz / °C */
35 	uint16_t ramp_coeff;
36 
37 	/* Raw sensor value */
38 	uint16_t raw;
39 };
40 
41 struct stm32_digi_temp_config {
42 	/* DTS instance. */
43 	DTS_TypeDef *base;
44 	/* Clock configuration. */
45 	struct stm32_pclken pclken;
46 	/* Interrupt configuration. */
47 	void (*irq_config)(const struct device *dev);
48 };
49 
stm32_digi_temp_isr(const struct device * dev)50 static void stm32_digi_temp_isr(const struct device *dev)
51 {
52 	struct stm32_digi_temp_data *data = dev->data;
53 	const struct stm32_digi_temp_config *cfg = dev->config;
54 	DTS_TypeDef *dts = cfg->base;
55 
56 	/* Clear interrupt */
57 	SET_BIT(dts->ICIFR, DTS_ICIFR_TS1_CITEF);
58 
59 	/* Give semaphore */
60 	k_sem_give(&data->sem_isr);
61 }
62 
stm32_digi_temp_sample_fetch(const struct device * dev,enum sensor_channel chan)63 static int stm32_digi_temp_sample_fetch(const struct device *dev, enum sensor_channel chan)
64 {
65 	const struct stm32_digi_temp_config *cfg = dev->config;
66 	struct stm32_digi_temp_data *data = dev->data;
67 	DTS_TypeDef *dts = cfg->base;
68 
69 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
70 		return -ENOTSUP;
71 	}
72 
73 	k_mutex_lock(&data->mutex, K_FOREVER);
74 
75 	/* Wait for the sensor to be ready (~40µS delay after enabling it) */
76 	while (READ_BIT(dts->SR, DTS_SR_TS1_RDY) == 0) {
77 		k_yield();
78 	}
79 
80 	/* Trigger a measurement */
81 	SET_BIT(dts->CFGR1, DTS_CFGR1_TS1_START);
82 	CLEAR_BIT(dts->CFGR1, DTS_CFGR1_TS1_START);
83 
84 	/* Wait for interrupt */
85 	k_sem_take(&data->sem_isr, K_FOREVER);
86 
87 	/* Read value */
88 	data->raw = READ_REG(dts->DR);
89 
90 	k_mutex_unlock(&data->mutex);
91 
92 	return 0;
93 }
94 
stm32_digi_temp_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)95 static int stm32_digi_temp_channel_get(const struct device *dev, enum sensor_channel chan,
96 				  struct sensor_value *val)
97 {
98 	struct stm32_digi_temp_data *data = dev->data;
99 	float meas_freq, temp;
100 
101 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
102 		return -ENOTSUP;
103 	}
104 
105 	meas_freq = ((float)data->pclk_freq * SAMPLING_TIME) / data->raw;
106 	temp = data->t0 + (meas_freq - data->t0_freq) / data->ramp_coeff;
107 
108 	return sensor_value_from_float(val, temp);
109 }
110 
stm32_digi_temp_configure(const struct device * dev)111 static void stm32_digi_temp_configure(const struct device *dev)
112 {
113 	const struct stm32_digi_temp_config *cfg = dev->config;
114 	struct stm32_digi_temp_data *data = dev->data;
115 	DTS_TypeDef *dts = cfg->base;
116 	int clk_div;
117 
118 	/* Use the prescaler to obtain an internal frequency lower than 1 MHz.
119 	 * Allowed values are between 0 and 127.
120 	 */
121 	clk_div = MIN(DIV_ROUND_UP(data->pclk_freq, ONE_MHZ), 127);
122 	MODIFY_REG(dts->CFGR1, DTS_CFGR1_HSREF_CLK_DIV_Msk,
123 		   clk_div << DTS_CFGR1_HSREF_CLK_DIV_Pos);
124 
125 	/* Select PCLK as reference clock */
126 	MODIFY_REG(dts->CFGR1, DTS_CFGR1_REFCLK_SEL_Msk,
127 		   0 << DTS_CFGR1_REFCLK_SEL_Pos);
128 
129 	/* Select trigger */
130 	MODIFY_REG(dts->CFGR1, DTS_CFGR1_TS1_INTRIG_SEL_Msk,
131 		   0 << DTS_CFGR1_TS1_INTRIG_SEL_Pos);
132 
133 	/* Set sampling time */
134 	MODIFY_REG(dts->CFGR1, DTS_CFGR1_TS1_SMP_TIME_Msk,
135 		   SAMPLING_TIME << DTS_CFGR1_TS1_SMP_TIME_Pos);
136 }
137 
stm32_digi_temp_enable(const struct device * dev)138 static void stm32_digi_temp_enable(const struct device *dev)
139 {
140 	const struct stm32_digi_temp_config *cfg = dev->config;
141 	DTS_TypeDef *dts = cfg->base;
142 
143 	/* Enable the sensor */
144 	SET_BIT(dts->CFGR1, DTS_CFGR1_TS1_EN);
145 
146 	/* Enable interrupt */
147 	SET_BIT(dts->ITENR, DTS_ITENR_TS1_ITEEN);
148 }
149 
150 #ifdef CONFIG_PM_DEVICE
stm32_digi_temp_disable(const struct device * dev)151 static void stm32_digi_temp_disable(const struct device *dev)
152 {
153 	const struct stm32_digi_temp_config *cfg = dev->config;
154 	DTS_TypeDef *dts = cfg->base;
155 
156 	/* Disable interrupt */
157 	CLEAR_BIT(dts->ITENR, DTS_ITENR_TS1_ITEEN);
158 
159 	/* Disable the sensor */
160 	CLEAR_BIT(dts->CFGR1, DTS_CFGR1_TS1_EN);
161 }
162 #endif
163 
stm32_digi_temp_init(const struct device * dev)164 static int stm32_digi_temp_init(const struct device *dev)
165 {
166 	const struct stm32_digi_temp_config *cfg = dev->config;
167 	struct stm32_digi_temp_data *data = dev->data;
168 	DTS_TypeDef *dts = cfg->base;
169 
170 	/* enable clock for subsystem */
171 	const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
172 
173 	if (!device_is_ready(clk)) {
174 		LOG_ERR("Clock control device not ready");
175 		return -ENODEV;
176 	}
177 
178 	if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken) != 0) {
179 		LOG_ERR("Could not enable DTS clock");
180 		return -EIO;
181 	}
182 
183 	/* Save the peripheral clock frequency in the data structure to avoid
184 	 * querying it for each call to the channel_get method.
185 	 */
186 	if (clock_control_get_rate(clk, (clock_control_subsys_t) &cfg->pclken,
187 				   &data->pclk_freq) < 0) {
188 		LOG_ERR("Failed call clock_control_get_rate(pclken)");
189 		return -EIO;
190 	}
191 
192 	/* Save the calibration data in the data structure to avoid reading
193 	 * them for each call to the channel_get method, as this requires
194 	 * enabling the peripheral clock.
195 	 */
196 	data->ramp_coeff = dts->RAMPVALR & DTS_RAMPVALR_TS1_RAMP_COEFF;
197 	data->t0_freq = (dts->T0VALR1 & DTS_T0VALR1_TS1_FMT0) * 100; /* 0.1 kHz -> Hz */
198 
199 	/* T0 temperature from the datasheet */
200 	switch (dts->T0VALR1 >> DTS_T0VALR1_TS1_T0_Pos) {
201 	case 0:
202 		data->t0 = TS1_T0_VAL0;
203 		break;
204 	case 1:
205 		data->t0 = TS1_T0_VAL1;
206 		break;
207 	default:
208 		LOG_ERR("Unknown T0 temperature value");
209 		return -EIO;
210 	}
211 
212 	/* Init mutex and semaphore */
213 	k_mutex_init(&data->mutex);
214 	k_sem_init(&data->sem_isr, 0, 1);
215 
216 	/* Configure and enable the sensor */
217 	cfg->irq_config(dev);
218 	stm32_digi_temp_configure(dev);
219 	stm32_digi_temp_enable(dev);
220 
221 	return 0;
222 }
223 
224 #ifdef CONFIG_PM_DEVICE
stm32_digi_temp_pm_action(const struct device * dev,enum pm_device_action action)225 static int stm32_digi_temp_pm_action(const struct device *dev, enum pm_device_action action)
226 {
227 	const struct stm32_digi_temp_config *cfg = dev->config;
228 	const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
229 	int err;
230 
231 	switch (action) {
232 	case PM_DEVICE_ACTION_RESUME:
233 		/* enable clock */
234 		err = clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken);
235 		if (err != 0) {
236 			LOG_ERR("Could not enable DTS clock");
237 			return err;
238 		}
239 		/* Enable sensor */
240 		stm32_digi_temp_enable(dev);
241 		break;
242 	case PM_DEVICE_ACTION_SUSPEND:
243 		/* Disable sensor */
244 		stm32_digi_temp_disable(dev);
245 		/* Stop device clock */
246 		err = clock_control_off(clk, (clock_control_subsys_t)&cfg->pclken);
247 		if (err != 0) {
248 			LOG_ERR("Could not disable DTS clock");
249 			return err;
250 		}
251 		break;
252 	default:
253 		return -ENOTSUP;
254 	}
255 
256 	return 0;
257 }
258 #endif /* CONFIG_PM_DEVICE */
259 
260 static DEVICE_API(sensor, stm32_digi_temp_driver_api) = {
261 	.sample_fetch = stm32_digi_temp_sample_fetch,
262 	.channel_get = stm32_digi_temp_channel_get,
263 };
264 
265 #define STM32_DIGI_TEMP_INIT(index)							\
266 static void stm32_digi_temp_irq_config_func_##index(const struct device *dev)		\
267 {											\
268 	IRQ_CONNECT(DT_INST_IRQN(index),						\
269 		    DT_INST_IRQ(index, priority),					\
270 		    stm32_digi_temp_isr, DEVICE_DT_INST_GET(index), 0);			\
271 	irq_enable(DT_INST_IRQN(index));						\
272 }											\
273 											\
274 static struct stm32_digi_temp_data stm32_digi_temp_dev_data_##index;			\
275 											\
276 static const struct stm32_digi_temp_config stm32_digi_temp_dev_config_##index = {	\
277 	.base = (DTS_TypeDef *)DT_INST_REG_ADDR(index),					\
278 	.pclken = {									\
279 		.enr = DT_INST_CLOCKS_CELL(index, bits),				\
280 		.bus = DT_INST_CLOCKS_CELL(index, bus)					\
281 	},										\
282 	.irq_config = stm32_digi_temp_irq_config_func_##index,				\
283 };											\
284 											\
285 PM_DEVICE_DT_INST_DEFINE(index, stm32_digi_temp_pm_action);				\
286 											\
287 SENSOR_DEVICE_DT_INST_DEFINE(index, stm32_digi_temp_init,				\
288 			     PM_DEVICE_DT_INST_GET(index),				\
289 			     &stm32_digi_temp_dev_data_##index,				\
290 			     &stm32_digi_temp_dev_config_##index,			\
291 			     POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,			\
292 			     &stm32_digi_temp_driver_api);				\
293 
294 DT_INST_FOREACH_STATUS_OKAY(STM32_DIGI_TEMP_INIT)
295