1 /*
2  * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10 
11 #include <libfdt.h>
12 
13 #include <platform_def.h>
14 
15 #include <arch_helpers.h>
16 #include <common/debug.h>
17 #include <drivers/arm/gicv2.h>
18 #include <drivers/clk.h>
19 #include <drivers/delay_timer.h>
20 #include <drivers/st/stm32_iwdg.h>
21 #include <drivers/st/stm32mp_clkfunc.h>
22 #include <lib/mmio.h>
23 #include <lib/utils.h>
24 #include <plat/common/platform.h>
25 
26 /* IWDG registers offsets */
27 #define IWDG_KR_OFFSET		0x00U
28 
29 /* Registers values */
30 #define IWDG_KR_RELOAD_KEY	0xAAAA
31 
32 struct stm32_iwdg_instance {
33 	uintptr_t base;
34 	unsigned long clock;
35 	uint8_t flags;
36 	int num_irq;
37 };
38 
39 static struct stm32_iwdg_instance stm32_iwdg[IWDG_MAX_INSTANCE];
40 
stm32_iwdg_get_dt_node(struct dt_node_info * info,int offset)41 static int stm32_iwdg_get_dt_node(struct dt_node_info *info, int offset)
42 {
43 	int node;
44 
45 	node = dt_get_node(info, offset, DT_IWDG_COMPAT);
46 	if (node < 0) {
47 		if (offset == -1) {
48 			VERBOSE("%s: No IDWG found\n", __func__);
49 		}
50 		return -FDT_ERR_NOTFOUND;
51 	}
52 
53 	return node;
54 }
55 
stm32_iwdg_refresh(void)56 void stm32_iwdg_refresh(void)
57 {
58 	uint8_t i;
59 
60 	for (i = 0U; i < IWDG_MAX_INSTANCE; i++) {
61 		struct stm32_iwdg_instance *iwdg = &stm32_iwdg[i];
62 
63 		/* 0x00000000 is not a valid address for IWDG peripherals */
64 		if (iwdg->base != 0U) {
65 			clk_enable(iwdg->clock);
66 
67 			mmio_write_32(iwdg->base + IWDG_KR_OFFSET,
68 				      IWDG_KR_RELOAD_KEY);
69 
70 			clk_disable(iwdg->clock);
71 		}
72 	}
73 }
74 
stm32_iwdg_init(void)75 int stm32_iwdg_init(void)
76 {
77 	int node = -1;
78 	struct dt_node_info dt_info;
79 	void *fdt;
80 	uint32_t __unused count = 0;
81 
82 	if (fdt_get_address(&fdt) == 0) {
83 		panic();
84 	}
85 
86 	for (node = stm32_iwdg_get_dt_node(&dt_info, node);
87 	     node != -FDT_ERR_NOTFOUND;
88 	     node = stm32_iwdg_get_dt_node(&dt_info, node)) {
89 		struct stm32_iwdg_instance *iwdg;
90 		uint32_t hw_init;
91 		uint32_t idx;
92 
93 		count++;
94 
95 		idx = stm32_iwdg_get_instance(dt_info.base);
96 		iwdg = &stm32_iwdg[idx];
97 		iwdg->base = dt_info.base;
98 		iwdg->clock = (unsigned long)dt_info.clock;
99 
100 		/* DT can specify low power cases */
101 		if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) ==
102 		    NULL) {
103 			iwdg->flags |= IWDG_DISABLE_ON_STOP;
104 		}
105 
106 		if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) ==
107 		    NULL) {
108 			iwdg->flags |= IWDG_DISABLE_ON_STANDBY;
109 		}
110 
111 		/* Explicit list of supported bit flags */
112 		hw_init = stm32_iwdg_get_otp_config(idx);
113 
114 		if ((hw_init & IWDG_HW_ENABLED) != 0) {
115 			if (dt_info.status == DT_DISABLED) {
116 				ERROR("OTP enabled but iwdg%u DT-disabled\n",
117 				      idx + 1U);
118 				panic();
119 			}
120 			iwdg->flags |= IWDG_HW_ENABLED;
121 		}
122 
123 		if (dt_info.status == DT_DISABLED) {
124 			zeromem((void *)iwdg,
125 				sizeof(struct stm32_iwdg_instance));
126 			continue;
127 		}
128 
129 		if ((hw_init & IWDG_DISABLE_ON_STOP) != 0) {
130 			iwdg->flags |= IWDG_DISABLE_ON_STOP;
131 		}
132 
133 		if ((hw_init & IWDG_DISABLE_ON_STANDBY) != 0) {
134 			iwdg->flags |= IWDG_DISABLE_ON_STANDBY;
135 		}
136 
137 		VERBOSE("IWDG%u found, %ssecure\n", idx + 1U,
138 			((dt_info.status & DT_NON_SECURE) != 0) ?
139 			"non-" : "");
140 
141 		if ((dt_info.status & DT_NON_SECURE) != 0) {
142 			stm32mp_register_non_secure_periph_iomem(iwdg->base);
143 		} else {
144 			stm32mp_register_secure_periph_iomem(iwdg->base);
145 		}
146 
147 #if defined(IMAGE_BL2)
148 		if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) {
149 			return -1;
150 		}
151 #endif
152 	}
153 
154 	VERBOSE("%u IWDG instance%s found\n", count, (count > 1U) ? "s" : "");
155 
156 	return 0;
157 }
158