xref: /optee_os/core/drivers/stm32_iwdg.c (revision fc9063dd97be0dbe294fd6fc05db8a869959166c)
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
4  */
5 
6 #include <assert.h>
7 #include <drivers/clk.h>
8 #include <drivers/clk_dt.h>
9 #include <drivers/stm32_iwdg.h>
10 #include <drivers/wdt.h>
11 #include <io.h>
12 #include <keep.h>
13 #include <kernel/boot.h>
14 #include <kernel/delay.h>
15 #include <kernel/dt.h>
16 #include <kernel/dt_driver.h>
17 #include <kernel/interrupt.h>
18 #include <kernel/misc.h>
19 #include <kernel/panic.h>
20 #include <kernel/pm.h>
21 #include <kernel/spinlock.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(1000)
31 #define IWDG_CNT_MASK		GENMASK_32(11, 0)
32 
33 /* IWDG registers offsets */
34 #define IWDG_KR_OFFSET		U(0x00)
35 #define IWDG_PR_OFFSET		U(0x04)
36 #define IWDG_RLR_OFFSET		U(0x08)
37 #define IWDG_SR_OFFSET		U(0x0C)
38 #define IWDG_EWCR_OFFSET	U(0x14)
39 
40 #define IWDG_KR_ACCESS_KEY	U(0x5555)
41 #define IWDG_KR_RELOAD_KEY	U(0xAAAA)
42 #define IWDG_KR_START_KEY	U(0xCCCC)
43 
44 /* Use a fixed prescaler divider of 256 */
45 #define IWDG_PRESCALER_256	U(256)
46 #define IWDG_PR_DIV_256		U(0x06)
47 #define IWDG_PR_DIV_MASK	GENMASK_32(3, 0)
48 
49 #define IWDG_SR_PVU		BIT(0)
50 #define IWDG_SR_RVU		BIT(1)
51 #define IWDG_SR_WVU		BIT(2)
52 #define IWDG_SR_EWU		BIT(3)
53 #define IWDG_SR_UPDATE_MASK	(IWDG_SR_PVU | IWDG_SR_RVU | IWDG_SR_WVU | \
54 				 IWDG_SR_EWU)
55 
56 #define IWDG_EWCR_EWIE		BIT(15)
57 #define IWDG_EWCR_EWIC		BIT(14)
58 
59 /*
60  * Values for struct stm32_iwdg_device::flags
61  * IWDG_FLAGS_HW_ENABLED                Watchdog is enabled by BootROM
62  * IWDG_FLAGS_DISABLE_ON_STOP           Watchdog is freezed in SoC STOP mode
63  * IWDG_FLAGS_DISABLE_ON_STANDBY        Watchdog is freezed in SoC STANDBY mode
64  * IWDG_FLAGS_NON_SECURE                Instance is assigned to non-secure world
65  * IWDG_FLAGS_ENABLED			Watchdog has been enabled
66  */
67 #define IWDG_FLAGS_HW_ENABLED			BIT(0)
68 #define IWDG_FLAGS_DISABLE_ON_STOP		BIT(1)
69 #define IWDG_FLAGS_DISABLE_ON_STANDBY		BIT(2)
70 #define IWDG_FLAGS_NON_SECURE			BIT(3)
71 #define IWDG_FLAGS_ENABLED			BIT(4)
72 
73 /*
74  * IWDG watch instance data
75  * @base - IWDG interface IOMEM base address
76  * @clock - Bus clock
77  * @clk_lsi - IWDG source clock
78  * @flags - Property flags for the IWDG instance
79  * @timeout - Watchdog elaspure timeout
80  * @wdt_chip - Wathcdog chip instance
81  * @link - Link in registered watchdog instance list
82  */
83 struct stm32_iwdg_device {
84 	struct io_pa_va base;
85 	struct clk *clock;
86 	struct clk *clk_lsi;
87 	uint32_t flags;
88 	unsigned long timeout;
89 	struct wdt_chip wdt_chip;
90 	SLIST_ENTRY(stm32_iwdg_device) link;
91 };
92 
93 static unsigned int iwdg_lock = SPINLOCK_UNLOCK;
94 
95 static SLIST_HEAD(iwdg_dev_list_head, stm32_iwdg_device) iwdg_dev_list =
96 	SLIST_HEAD_INITIALIZER(iwdg_dev_list_head);
97 
98 static vaddr_t get_base(struct stm32_iwdg_device *iwdg)
99 {
100 	return io_pa_or_va(&iwdg->base, 1);
101 }
102 
103 static bool is_assigned_to_nsec(struct stm32_iwdg_device *iwdg)
104 {
105 	return iwdg->flags & IWDG_FLAGS_NON_SECURE;
106 }
107 
108 static bool is_enable(struct stm32_iwdg_device *iwdg)
109 {
110 	return iwdg->flags & IWDG_FLAGS_ENABLED;
111 }
112 
113 /* Return counter value to related to input timeout in seconds, or 0 on error */
114 static uint32_t iwdg_timeout_cnt(struct stm32_iwdg_device *iwdg,
115 				 unsigned long to_sec)
116 {
117 	uint64_t reload = (uint64_t)to_sec * clk_get_rate(iwdg->clk_lsi);
118 	uint64_t cnt = (reload / IWDG_PRESCALER_256) - 1;
119 
120 	/* Be safe and expect any counter to be above 2 */
121 	if (cnt > IWDG_CNT_MASK || cnt < 3)
122 		return 0;
123 
124 	return cnt;
125 }
126 
127 /* Wait IWDG programming completes */
128 static TEE_Result iwdg_wait_sync(struct stm32_iwdg_device *iwdg)
129 {
130 	uint64_t timeout_ref = timeout_init_us(IWDG_TIMEOUT_US);
131 	vaddr_t iwdg_base = get_base(iwdg);
132 
133 	while (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK)
134 		if (timeout_elapsed(timeout_ref))
135 			break;
136 
137 	if (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK)
138 		return TEE_ERROR_GENERIC;
139 
140 	return TEE_SUCCESS;
141 }
142 
143 static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg)
144 {
145 	TEE_Result res = TEE_ERROR_GENERIC;
146 	vaddr_t iwdg_base = get_base(iwdg);
147 	uint32_t rlr_value = 0;
148 
149 	assert(is_enable(iwdg));
150 
151 	rlr_value = iwdg_timeout_cnt(iwdg, iwdg->timeout);
152 	if (!rlr_value)
153 		return TEE_ERROR_GENERIC;
154 
155 	clk_enable(iwdg->clock);
156 
157 	io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY);
158 	io_write32(iwdg_base + IWDG_PR_OFFSET, IWDG_PR_DIV_256);
159 	io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value);
160 	io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY);
161 
162 	res = iwdg_wait_sync(iwdg);
163 
164 	clk_disable(iwdg->clock);
165 
166 	return res;
167 }
168 
169 static void iwdg_start(struct stm32_iwdg_device *iwdg)
170 {
171 	clk_enable(iwdg->clock);
172 	io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_START_KEY);
173 	clk_disable(iwdg->clock);
174 
175 	iwdg->flags |= IWDG_FLAGS_ENABLED;
176 }
177 
178 static void iwdg_refresh(struct stm32_iwdg_device *iwdg)
179 {
180 	clk_enable(iwdg->clock);
181 	io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY);
182 	clk_disable(iwdg->clock);
183 }
184 
185 /* Operators for watchdog OP-TEE interface */
186 static struct stm32_iwdg_device *wdt_chip_to_iwdg(struct wdt_chip *chip)
187 {
188 	return container_of(chip, struct stm32_iwdg_device, wdt_chip);
189 }
190 
191 static TEE_Result iwdg_wdt_init(struct wdt_chip *chip,
192 				unsigned long *min_timeout,
193 				unsigned long *max_timeout)
194 {
195 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
196 	unsigned long rate = clk_get_rate(iwdg->clk_lsi);
197 
198 	if (!rate)
199 		return TEE_ERROR_GENERIC;
200 
201 	/* Be safe and expect any counter to be above 2 */
202 	*min_timeout = 3 * IWDG_PRESCALER_256 / rate;
203 	*max_timeout = (IWDG_CNT_MASK + 1) * IWDG_PRESCALER_256 / rate;
204 
205 	return TEE_SUCCESS;
206 }
207 
208 static void iwdg_wdt_start(struct wdt_chip *chip)
209 {
210 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
211 
212 	iwdg_start(iwdg);
213 
214 	if (configure_timeout(iwdg))
215 		panic();
216 }
217 
218 static void iwdg_wdt_refresh(struct wdt_chip *chip)
219 {
220 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
221 
222 	iwdg_refresh(iwdg);
223 }
224 
225 static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip,
226 				       unsigned long timeout)
227 {
228 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
229 
230 	if (!iwdg_timeout_cnt(iwdg, timeout))
231 		return TEE_ERROR_BAD_PARAMETERS;
232 
233 	iwdg->timeout = timeout;
234 
235 	if (is_enable(iwdg)) {
236 		TEE_Result res = TEE_ERROR_GENERIC;
237 
238 		res = configure_timeout(iwdg);
239 		if (res)
240 			return res;
241 	}
242 
243 	return TEE_SUCCESS;
244 }
245 
246 static const struct wdt_ops stm32_iwdg_ops = {
247 	.init = iwdg_wdt_init,
248 	.start = iwdg_wdt_start,
249 	.ping = iwdg_wdt_refresh,
250 	.set_timeout = iwdg_wdt_set_timeout,
251 };
252 DECLARE_KEEP_PAGER(stm32_iwdg_ops);
253 
254 /* Refresh all registered watchdogs */
255 void stm32_iwdg_refresh(void)
256 {
257 	struct stm32_iwdg_device *iwdg = NULL;
258 	uint32_t exceptions = cpu_spin_lock_xsave(&iwdg_lock);
259 
260 	SLIST_FOREACH(iwdg, &iwdg_dev_list, link)
261 		iwdg_refresh(iwdg);
262 
263 	cpu_spin_unlock_xrestore(&iwdg_lock, exceptions);
264 }
265 
266 /* Driver initialization */
267 static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg,
268 				       const void *fdt, int node)
269 {
270 	TEE_Result res = TEE_ERROR_GENERIC;
271 	struct dt_node_info dt_info = { };
272 	const fdt32_t *cuint = NULL;
273 
274 	fdt_fill_device_info(fdt, &dt_info, node);
275 
276 	if (dt_info.reg == DT_INFO_INVALID_REG ||
277 	    dt_info.reg_size == DT_INFO_INVALID_REG_SIZE)
278 		panic();
279 
280 	res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clock);
281 	if (res)
282 		return res;
283 
284 	res = clk_dt_get_by_name(fdt, node, "lsi", &iwdg->clk_lsi);
285 	if (res)
286 		return res;
287 
288 	if (dt_info.status == DT_STATUS_OK_NSEC)
289 		iwdg->flags |= IWDG_FLAGS_NON_SECURE;
290 
291 	/* Get IOMEM address */
292 	iwdg->base.pa = dt_info.reg;
293 
294 	if (iwdg->flags & IWDG_FLAGS_NON_SECURE)
295 		io_pa_or_va_nsec(&iwdg->base, dt_info.reg_size);
296 	else
297 		io_pa_or_va_secure(&iwdg->base, dt_info.reg_size);
298 
299 	assert(iwdg->base.va);
300 
301 	/* Get and check timeout value */
302 	cuint = fdt_getprop(fdt, node, "timeout-sec", NULL);
303 	if (!cuint)
304 		return TEE_ERROR_BAD_PARAMETERS;
305 
306 	iwdg->timeout = (int)fdt32_to_cpu(*cuint);
307 	if (!iwdg->timeout)
308 		return TEE_ERROR_BAD_PARAMETERS;
309 
310 	if (!iwdg_timeout_cnt(iwdg, iwdg->timeout)) {
311 		EMSG("Timeout %lu not applicable", iwdg->timeout);
312 		return TEE_ERROR_BAD_PARAMETERS;
313 	}
314 
315 	/* DT can specify low power cases */
316 	if (!fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL))
317 		iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STOP;
318 
319 	if (!fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL))
320 		iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY;
321 
322 	return TEE_SUCCESS;
323 }
324 
325 /* Platform should override this function to provide IWDG fuses configuration */
326 TEE_Result __weak stm32_get_iwdg_otp_config(paddr_t pbase __unused,
327 					    struct stm32_iwdg_otp_data *otp_d)
328 {
329 	otp_d->hw_enabled = false;
330 	otp_d->disable_on_stop = false;
331 	otp_d->disable_on_standby = false;
332 
333 	return TEE_SUCCESS;
334 }
335 
336 static TEE_Result stm32_iwdg_setup(struct stm32_iwdg_device *iwdg,
337 				   const void *fdt, int node)
338 {
339 	struct stm32_iwdg_otp_data otp_data = { };
340 	TEE_Result res = TEE_SUCCESS;
341 
342 	res = stm32_iwdg_parse_fdt(iwdg, fdt, node);
343 	if (res)
344 		return res;
345 
346 	res = stm32_get_iwdg_otp_config(iwdg->base.pa, &otp_data);
347 	if (res)
348 		return res;
349 
350 	if (otp_data.hw_enabled)
351 		iwdg->flags |= IWDG_FLAGS_HW_ENABLED;
352 	if (otp_data.disable_on_stop)
353 		iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STOP;
354 	if (otp_data.disable_on_standby)
355 		iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY;
356 
357 	/* Enable watchdog source clock once for all */
358 	clk_enable(iwdg->clk_lsi);
359 
360 	if (otp_data.hw_enabled) {
361 		iwdg->flags |= IWDG_FLAGS_ENABLED;
362 
363 		/* Configure timeout if watchdog is already enabled */
364 		res = configure_timeout(iwdg);
365 		if (res)
366 			return res;
367 
368 		iwdg_refresh(iwdg);
369 	}
370 
371 	return TEE_SUCCESS;
372 }
373 
374 static TEE_Result stm32_iwdg_register(struct stm32_iwdg_device *iwdg)
375 {
376 	TEE_Result res = TEE_ERROR_GENERIC;
377 
378 	if (is_assigned_to_nsec(iwdg)) {
379 		stm32mp_register_non_secure_periph_iomem(iwdg->base.pa);
380 	} else {
381 		stm32mp_register_secure_periph_iomem(iwdg->base.pa);
382 
383 		/* Expose watchdog runtime service only to secure IWDG */
384 		iwdg->wdt_chip.ops = &stm32_iwdg_ops;
385 
386 		res = watchdog_register(&iwdg->wdt_chip);
387 		if (res)
388 			return res;
389 	}
390 
391 	SLIST_INSERT_HEAD(&iwdg_dev_list, iwdg, link);
392 
393 	return TEE_SUCCESS;
394 }
395 
396 static TEE_Result stm32_iwdg_probe(const void *fdt, int node,
397 				   const void *compat_data __unused)
398 {
399 	struct stm32_iwdg_device *iwdg = NULL;
400 	TEE_Result res = TEE_SUCCESS;
401 
402 	iwdg = calloc(1, sizeof(*iwdg));
403 	if (!iwdg)
404 		return TEE_ERROR_OUT_OF_MEMORY;
405 
406 	res = stm32_iwdg_setup(iwdg, fdt, node);
407 	if (res)
408 		goto err;
409 
410 	res = stm32_iwdg_register(iwdg);
411 	if (res)
412 		goto err;
413 
414 	return TEE_SUCCESS;
415 
416 err:
417 	free(iwdg);
418 	return res;
419 }
420 
421 static const struct dt_device_match stm32_iwdg_match_table[] = {
422 	{ .compatible = "st,stm32mp1-iwdg" },
423 	{ }
424 };
425 
426 DEFINE_DT_DRIVER(stm32_iwdg_dt_driver) = {
427 	.name = "stm32-iwdg",
428 	.match_table = stm32_iwdg_match_table,
429 	.probe = stm32_iwdg_probe,
430 };
431