xref: /optee_os/core/drivers/stm32_iwdg.c (revision e4b8d29a42c5973337c9b41191817ac140497084)
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 2017-2025, STMicroelectronics - All Rights Reserved
4  */
5 
6 #include <assert.h>
7 #include <drivers/clk.h>
8 #include <drivers/clk_dt.h>
9 #include <drivers/wdt.h>
10 #include <io.h>
11 #include <keep.h>
12 #include <kernel/boot.h>
13 #include <kernel/delay.h>
14 #include <kernel/dt.h>
15 #include <kernel/dt_driver.h>
16 #include <kernel/interrupt.h>
17 #include <kernel/misc.h>
18 #include <kernel/panic.h>
19 #include <kernel/pm.h>
20 #include <kernel/spinlock.h>
21 #include <kernel/tee_time.h>
22 #include <libfdt.h>
23 #include <mm/core_memprot.h>
24 #include <sm/sm.h>
25 #include <stm32_util.h>
26 #include <string.h>
27 #include <trace.h>
28 
29 /* IWDG Compatibility */
30 #define IWDG_TIMEOUT_US		U(10000)
31 #define IWDG_CNT_MASK		GENMASK_32(11, 0)
32 #define IWDG_ONF_MIN_VER	U(0x31)
33 #define IWDG_ICR_MIN_VER	U(0x40)
34 
35 /* IWDG registers offsets */
36 #define IWDG_KR_OFFSET		U(0x00)
37 #define IWDG_PR_OFFSET		U(0x04)
38 #define IWDG_RLR_OFFSET		U(0x08)
39 #define IWDG_SR_OFFSET		U(0x0C)
40 #define IWDG_EWCR_OFFSET	U(0x14)
41 #define IWDG_ICR_OFFSET		U(0x18)
42 #define IWDG_VERR_OFFSET	U(0x3F4)
43 
44 #define IWDG_KR_WPROT_KEY	U(0x0000)
45 #define IWDG_KR_ACCESS_KEY	U(0x5555)
46 #define IWDG_KR_RELOAD_KEY	U(0xAAAA)
47 #define IWDG_KR_START_KEY	U(0xCCCC)
48 
49 /* Use a fixed prescaler divider of 256 */
50 #define IWDG_PRESCALER_256	U(256)
51 #define IWDG_PR_DIV_256		U(0x06)
52 #define IWDG_PR_DIV_MASK	GENMASK_32(3, 0)
53 
54 #define IWDG_SR_PVU		BIT(0)
55 #define IWDG_SR_RVU		BIT(1)
56 #define IWDG_SR_WVU		BIT(2)
57 #define IWDG_SR_EWU		BIT(3)
58 #define IWDG_SR_UPDATE_MASK	(IWDG_SR_PVU | IWDG_SR_RVU | IWDG_SR_WVU | \
59 				 IWDG_SR_EWU)
60 #define IWDG_SR_ONF		BIT(8)
61 #define IWDG_SR_EWIF		BIT(14)
62 #define IWDG_SR_EWIF_V40	BIT(15)
63 
64 #define IWDG_EWCR_EWIE		BIT(15)
65 #define IWDG_EWCR_EWIC		BIT(14)
66 
67 #define IWDG_ICR_EWIC		BIT(15)
68 
69 #define IWDG_VERR_REV_MASK	GENMASK_32(7, 0)
70 
71 /* Define default early timeout delay to 5 sec before timeout */
72 #define IWDG_ETIMEOUT_SEC	U(5)
73 
74 /*
75  * Values for struct stm32_iwdg_device::flags
76  * IWDG_FLAGS_ENABLED			Watchdog has been enabled
77  */
78 #define IWDG_FLAGS_ENABLED			BIT(0)
79 
80 /*
81  * IWDG watch instance data
82  * @base - IWDG interface IOMEM base address
83  * @clk_pclk - Bus clock
84  * @clk_lsi - IWDG source clock
85  * @itr_chip - Interrupt chip device
86  * @itr_num - Interrupt number for the IWDG instance
87  * @itr_handler - Interrupt handler
88  * @flags - Property flags for the IWDG instance
89  * @timeout - Watchdog elaspure timeout
90  * @hw_version - Watchdog HW version
91  * @last_refresh - Time of last watchdog refresh
92  * @wdt_chip - Wathcdog chip instance
93  */
94 struct stm32_iwdg_device {
95 	struct io_pa_va base;
96 	struct clk *clk_pclk;
97 	struct clk *clk_lsi;
98 	struct itr_chip *itr_chip;
99 	size_t itr_num;
100 	struct itr_handler *itr_handler;
101 	uint32_t flags;
102 	unsigned long timeout;
103 	unsigned int hw_version;
104 	TEE_Time last_refresh;
105 	struct wdt_chip wdt_chip;
106 };
107 
108 static uint32_t sr_ewif_mask(struct stm32_iwdg_device *iwdg)
109 {
110 	if (iwdg->hw_version >= IWDG_ICR_MIN_VER)
111 		return IWDG_SR_EWIF_V40;
112 	else
113 		return IWDG_SR_EWIF;
114 }
115 
116 static vaddr_t get_base(struct stm32_iwdg_device *iwdg)
117 {
118 	return io_pa_or_va(&iwdg->base, 1);
119 }
120 
121 static void iwdg_wdt_set_enabled(struct stm32_iwdg_device *iwdg)
122 {
123 	iwdg->flags |= IWDG_FLAGS_ENABLED;
124 }
125 
126 static bool iwdg_wdt_is_enabled(struct stm32_iwdg_device *iwdg)
127 {
128 	return iwdg->flags & IWDG_FLAGS_ENABLED;
129 }
130 
131 /* Return counter value to related to input timeout in seconds, or 0 on error */
132 static uint32_t iwdg_timeout_cnt(struct stm32_iwdg_device *iwdg,
133 				 unsigned long to_sec)
134 {
135 	uint64_t reload = (uint64_t)to_sec * clk_get_rate(iwdg->clk_lsi);
136 	uint64_t cnt = (reload / IWDG_PRESCALER_256) - 1;
137 
138 	/* Be safe and expect any counter to be above 2 */
139 	if (cnt > IWDG_CNT_MASK || cnt < 3)
140 		return 0;
141 
142 	return cnt;
143 }
144 
145 /* Wait IWDG programming completes */
146 static TEE_Result iwdg_wait_sync(struct stm32_iwdg_device *iwdg)
147 {
148 	uint64_t timeout_ref = timeout_init_us(IWDG_TIMEOUT_US);
149 	vaddr_t iwdg_base = get_base(iwdg);
150 
151 	while (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK)
152 		if (timeout_elapsed(timeout_ref))
153 			break;
154 
155 	if (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK)
156 		return TEE_ERROR_GENERIC;
157 
158 	return TEE_SUCCESS;
159 }
160 
161 static enum itr_return stm32_iwdg_it_handler(struct itr_handler *h)
162 {
163 	unsigned int __maybe_unused cpu = get_core_pos();
164 	struct stm32_iwdg_device *iwdg = h->data;
165 	vaddr_t iwdg_base = get_base(iwdg);
166 
167 	DMSG("CPU %u IT Watchdog %#"PRIxPA, cpu, iwdg->base.pa);
168 
169 	/* Check for spurious interrupt */
170 	if (!(io_read32(iwdg_base + IWDG_SR_OFFSET) & sr_ewif_mask(iwdg)))
171 		return ITRR_NONE;
172 
173 	/*
174 	 * Writing IWDG_EWCR_EWIT triggers a watchdog refresh.
175 	 * To prevent the watchdog refresh, write-protect all the registers;
176 	 * this makes read-only all IWDG_EWCR fields except IWDG_EWCR_EWIC.
177 	 */
178 	io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_WPROT_KEY);
179 
180 	/* Disable early interrupt */
181 	if (iwdg->hw_version >= IWDG_ICR_MIN_VER)
182 		io_setbits32(iwdg_base + IWDG_ICR_OFFSET, IWDG_ICR_EWIC);
183 	else
184 		io_setbits32(iwdg_base + IWDG_EWCR_OFFSET, IWDG_EWCR_EWIC);
185 
186 	panic("Watchdog");
187 
188 	return ITRR_HANDLED;
189 }
190 DECLARE_KEEP_PAGER(stm32_iwdg_it_handler);
191 
192 static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg)
193 {
194 	TEE_Result res = TEE_ERROR_GENERIC;
195 	vaddr_t iwdg_base = get_base(iwdg);
196 	uint32_t rlr_value = 0;
197 	uint32_t ewie_value = 0;
198 	uint32_t early_timeout = 0;
199 
200 	assert(iwdg_wdt_is_enabled(iwdg));
201 
202 	rlr_value = iwdg_timeout_cnt(iwdg, iwdg->timeout);
203 	if (!rlr_value)
204 		return TEE_ERROR_GENERIC;
205 
206 	if (iwdg->itr_handler) {
207 		if (iwdg->timeout >= 2 * IWDG_ETIMEOUT_SEC)
208 			early_timeout = IWDG_ETIMEOUT_SEC;
209 		else
210 			early_timeout = iwdg->timeout / 4;
211 		ewie_value = iwdg_timeout_cnt(iwdg, early_timeout);
212 		interrupt_enable(iwdg->itr_chip, iwdg->itr_num);
213 	}
214 
215 	io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY);
216 	io_write32(iwdg_base + IWDG_PR_OFFSET, IWDG_PR_DIV_256);
217 	io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value);
218 	if (ewie_value &&
219 	    !(io_read32(iwdg_base + IWDG_EWCR_OFFSET) & IWDG_EWCR_EWIE))
220 		io_write32(iwdg_base + IWDG_EWCR_OFFSET,
221 			   ewie_value | IWDG_EWCR_EWIE);
222 
223 	res = iwdg_wait_sync(iwdg);
224 
225 	io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY);
226 
227 	return res;
228 }
229 
230 static void iwdg_start(struct stm32_iwdg_device *iwdg)
231 {
232 	TEE_Result res = TEE_ERROR_GENERIC;
233 
234 	res = tee_time_get_sys_time(&iwdg->last_refresh);
235 	if (res)
236 		panic();
237 
238 	io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_START_KEY);
239 
240 	iwdg_wdt_set_enabled(iwdg);
241 }
242 
243 static void iwdg_refresh(struct stm32_iwdg_device *iwdg)
244 {
245 	TEE_Result res = TEE_ERROR_GENERIC;
246 
247 	res = tee_time_get_sys_time(&iwdg->last_refresh);
248 	if (res)
249 		panic();
250 
251 	io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY);
252 }
253 
254 /* Operators for watchdog OP-TEE interface */
255 static struct stm32_iwdg_device *wdt_chip_to_iwdg(struct wdt_chip *chip)
256 {
257 	return container_of(chip, struct stm32_iwdg_device, wdt_chip);
258 }
259 
260 static TEE_Result iwdg_wdt_init(struct wdt_chip *chip,
261 				unsigned long *min_timeout,
262 				unsigned long *max_timeout)
263 {
264 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
265 	unsigned long rate = clk_get_rate(iwdg->clk_lsi);
266 
267 	if (!rate)
268 		return TEE_ERROR_GENERIC;
269 
270 	/* Be safe and expect any counter to be above 2 */
271 	*min_timeout = 3 * IWDG_PRESCALER_256 / rate;
272 	*max_timeout = (IWDG_CNT_MASK + 1) * IWDG_PRESCALER_256 / rate;
273 
274 	return TEE_SUCCESS;
275 }
276 
277 static void iwdg_wdt_start(struct wdt_chip *chip)
278 {
279 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
280 
281 	iwdg_start(iwdg);
282 
283 	if (configure_timeout(iwdg))
284 		panic();
285 }
286 
287 static void iwdg_wdt_refresh(struct wdt_chip *chip)
288 {
289 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
290 
291 	iwdg_refresh(iwdg);
292 }
293 
294 static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip,
295 				       unsigned long timeout)
296 {
297 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
298 
299 	if (!iwdg_timeout_cnt(iwdg, timeout))
300 		return TEE_ERROR_BAD_PARAMETERS;
301 
302 	iwdg->timeout = timeout;
303 
304 	if (iwdg_wdt_is_enabled(iwdg)) {
305 		TEE_Result res = TEE_ERROR_GENERIC;
306 
307 		res = configure_timeout(iwdg);
308 		if (res)
309 			return res;
310 	}
311 
312 	return TEE_SUCCESS;
313 }
314 
315 static TEE_Result iwdg_wdt_get_timeleft(struct wdt_chip *chip, bool *is_started,
316 					unsigned long *timeleft)
317 {
318 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
319 	TEE_Result res = TEE_ERROR_GENERIC;
320 	TEE_Time time = { };
321 	TEE_Time now = { };
322 
323 	*is_started = iwdg_wdt_is_enabled(iwdg);
324 
325 	if (!*is_started)
326 		return TEE_SUCCESS;
327 
328 	res = tee_time_get_sys_time(&now);
329 	if (res)
330 		panic();
331 
332 	time.seconds = iwdg->timeout;
333 	TEE_TIME_ADD(iwdg->last_refresh, time, time);
334 	if (TEE_TIME_LE(time, now)) {
335 		*timeleft = 0;
336 	} else {
337 		TEE_TIME_SUB(time, now, time);
338 		*timeleft = time.seconds;
339 	}
340 
341 	return TEE_SUCCESS;
342 }
343 
344 static const struct wdt_ops stm32_iwdg_ops = {
345 	.init = iwdg_wdt_init,
346 	.start = iwdg_wdt_start,
347 	.ping = iwdg_wdt_refresh,
348 	.set_timeout = iwdg_wdt_set_timeout,
349 	.get_timeleft = iwdg_wdt_get_timeleft,
350 };
351 DECLARE_KEEP_PAGER(stm32_iwdg_ops);
352 
353 /* Driver initialization */
354 static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg,
355 				       const void *fdt, int node)
356 {
357 	TEE_Result res = TEE_ERROR_GENERIC;
358 	struct dt_node_info dt_info = { };
359 	const fdt32_t *cuint = NULL;
360 
361 	fdt_fill_device_info(fdt, &dt_info, node);
362 
363 	if (dt_info.reg == DT_INFO_INVALID_REG ||
364 	    dt_info.reg_size == DT_INFO_INVALID_REG_SIZE)
365 		panic();
366 
367 	res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clk_pclk);
368 	if (res)
369 		return res;
370 
371 	res = clk_dt_get_by_name(fdt, node, "lsi", &iwdg->clk_lsi);
372 	if (res)
373 		return res;
374 
375 	res = interrupt_dt_get(fdt, node, &iwdg->itr_chip, &iwdg->itr_num);
376 	if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
377 		return res;
378 	if (!res) {
379 		res = interrupt_create_handler(iwdg->itr_chip, iwdg->itr_num,
380 					       stm32_iwdg_it_handler, iwdg, 0,
381 					       &iwdg->itr_handler);
382 		if (res)
383 			return res;
384 	}
385 
386 	/* Get IOMEM address */
387 	iwdg->base.pa = dt_info.reg;
388 	io_pa_or_va_secure(&iwdg->base, dt_info.reg_size);
389 	assert(iwdg->base.va);
390 
391 	/* Get and check timeout value */
392 	cuint = fdt_getprop(fdt, node, "timeout-sec", NULL);
393 	if (!cuint) {
394 		res = TEE_ERROR_BAD_PARAMETERS;
395 		goto err_itr;
396 	}
397 
398 	iwdg->timeout = (int)fdt32_to_cpu(*cuint);
399 	if (!iwdg->timeout) {
400 		res = TEE_ERROR_BAD_PARAMETERS;
401 		goto err_itr;
402 	}
403 
404 	if (!iwdg_timeout_cnt(iwdg, iwdg->timeout)) {
405 		EMSG("Timeout %lu not applicable", iwdg->timeout);
406 		res = TEE_ERROR_BAD_PARAMETERS;
407 		goto err_itr;
408 	}
409 
410 	return TEE_SUCCESS;
411 
412 err_itr:
413 	interrupt_remove_free_handler(iwdg->itr_handler);
414 
415 	return res;
416 }
417 
418 static void iwdg_wdt_get_version_and_status(struct stm32_iwdg_device *iwdg)
419 {
420 	vaddr_t iwdg_base = get_base(iwdg);
421 	uint32_t rlr_value = 0;
422 
423 	iwdg->hw_version = io_read32(iwdg_base + IWDG_VERR_OFFSET) &
424 			   IWDG_VERR_REV_MASK;
425 
426 	/* Test if watchdog is already running */
427 	if (iwdg->hw_version >= IWDG_ONF_MIN_VER) {
428 		if (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_ONF)
429 			iwdg_wdt_set_enabled(iwdg);
430 	} else {
431 		/*
432 		 * Workaround for old versions without IWDG_SR_ONF bit:
433 		 * - write in IWDG_RLR_OFFSET
434 		 * - wait for sync
435 		 * - if sync succeeds, then iwdg is running
436 		 */
437 		io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY);
438 
439 		rlr_value = io_read32(iwdg_base + IWDG_RLR_OFFSET);
440 		io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value);
441 
442 		if (!iwdg_wait_sync(iwdg))
443 			iwdg_wdt_set_enabled(iwdg);
444 
445 		io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_WPROT_KEY);
446 	}
447 
448 	DMSG("Watchdog is %sabled", iwdg_wdt_is_enabled(iwdg) ? "en" : "dis");
449 }
450 
451 static TEE_Result stm32_iwdg_setup(struct stm32_iwdg_device *iwdg,
452 				   const void *fdt, int node)
453 {
454 	TEE_Result res = TEE_SUCCESS;
455 
456 	res = stm32_iwdg_parse_fdt(iwdg, fdt, node);
457 	if (res)
458 		return res;
459 
460 	/* Enable watchdog source and bus clocks once for all */
461 	if (clk_enable(iwdg->clk_lsi))
462 		panic();
463 
464 	if (clk_enable(iwdg->clk_pclk))
465 		panic();
466 
467 	iwdg_wdt_get_version_and_status(iwdg);
468 
469 	if (iwdg_wdt_is_enabled(iwdg)) {
470 		/* Configure timeout if watchdog is already enabled */
471 		res = configure_timeout(iwdg);
472 		if (res)
473 			panic();
474 
475 		iwdg_refresh(iwdg);
476 	}
477 
478 	return TEE_SUCCESS;
479 }
480 
481 static TEE_Result stm32_iwdg_probe(const void *fdt, int node,
482 				   const void *compat_data __unused)
483 {
484 	struct stm32_iwdg_device *iwdg = NULL;
485 	TEE_Result res = TEE_SUCCESS;
486 
487 	iwdg = calloc(1, sizeof(*iwdg));
488 	if (!iwdg)
489 		return TEE_ERROR_OUT_OF_MEMORY;
490 
491 	res = stm32_iwdg_setup(iwdg, fdt, node);
492 	if (res)
493 		goto out;
494 
495 	iwdg->wdt_chip.ops = &stm32_iwdg_ops;
496 
497 	res = watchdog_register(&iwdg->wdt_chip);
498 
499 out:
500 	if (res)
501 		free(iwdg);
502 
503 	return res;
504 }
505 
506 static const struct dt_device_match stm32_iwdg_match_table[] = {
507 	{ .compatible = "st,stm32mp1-iwdg" },
508 	{ }
509 };
510 
511 DEFINE_DT_DRIVER(stm32_iwdg_dt_driver) = {
512 	.name = "stm32-iwdg",
513 	.match_table = stm32_iwdg_match_table,
514 	.probe = stm32_iwdg_probe,
515 };
516