xref: /optee_os/core/drivers/rstctrl/stm32_rstctrl.c (revision 19a31ec40245ae01a9adcd206eec2a4bb4479fc9)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021-2022, Linaro Limited
4  * Copyright (c) 2018-2022, STMicroelectronics
5  */
6 
7 #include <drivers/rstctrl.h>
8 #include <drivers/stm32mp_dt_bindings.h>
9 #include <drivers/stm32mp1_rcc.h>
10 #include <io.h>
11 #include <kernel/delay.h>
12 #include <kernel/dt.h>
13 #include <kernel/dt_driver.h>
14 #include <kernel/panic.h>
15 #include <mm/core_memprot.h>
16 #include <stm32_util.h>
17 
18 #define RESET_ID_MASK		GENMASK_32(31, 5)
19 #define RESET_ID_SHIFT		5
20 #define RESET_BIT_POS_MASK	GENMASK_32(4, 0)
21 #define RESET_OFFSET_MAX	1024
22 
23 /* Exposed rstctrl instance */
24 struct stm32_rstline {
25 	unsigned int id;
26 	struct rstctrl rstctrl;
27 	SLIST_ENTRY(stm32_rstline) link;
28 };
29 
30 static SLIST_HEAD(, stm32_rstline) stm32_rst_list =
31 	SLIST_HEAD_INITIALIZER(stm32_rst_list);
32 
33 static size_t reset_id2reg_offset(unsigned int id)
34 {
35 	size_t offset = (id & RESET_ID_MASK) >> RESET_ID_SHIFT;
36 
37 	assert(offset < RESET_OFFSET_MAX);
38 	return offset * sizeof(uint32_t);
39 }
40 
41 static uint8_t reset_id2reg_bit_pos(unsigned int reset_id)
42 {
43 	uint8_t pos = reset_id & RESET_BIT_POS_MASK;
44 
45 	assert(pos < 32);
46 	return pos;
47 }
48 
49 static struct stm32_rstline *to_rstline(struct rstctrl *rstctrl)
50 {
51 	assert(rstctrl);
52 
53 	return container_of(rstctrl, struct stm32_rstline, rstctrl);
54 }
55 
56 static TEE_Result reset_assert(struct rstctrl *rstctrl, unsigned int to_us)
57 {
58 	unsigned int id = to_rstline(rstctrl)->id;
59 	vaddr_t rcc_base = stm32_rcc_base();
60 	uint32_t bit_mask = 0;
61 	size_t offset = 0;
62 
63 #ifdef CFG_STM32MP15
64 	switch (id) {
65 	case MCU_HOLD_BOOT_R:
66 		/*
67 		 * The RCC_MP_GCR is a read/write register.
68 		 * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit
69 		 */
70 		io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
71 
72 		return TEE_SUCCESS;
73 	case MCU_R:
74 		/* MCU reset can only be written */
75 		to_us = 0;
76 		break;
77 	default:
78 		break;
79 	}
80 #endif
81 
82 	offset = reset_id2reg_offset(id);
83 	bit_mask = BIT(reset_id2reg_bit_pos(id));
84 
85 	io_write32(rcc_base + offset, bit_mask);
86 
87 	if (to_us) {
88 		uint64_t timeout_ref = timeout_init_us(to_us);
89 
90 		while (!(io_read32(rcc_base + offset) & bit_mask))
91 			if (timeout_elapsed(timeout_ref))
92 				break;
93 
94 		if (!(io_read32(rcc_base + offset) & bit_mask))
95 			return TEE_ERROR_SECURITY;
96 	}
97 
98 	return TEE_SUCCESS;
99 }
100 
101 static TEE_Result reset_deassert(struct rstctrl *rstctrl, unsigned int to_us)
102 {
103 	unsigned int id = to_rstline(rstctrl)->id;
104 	vaddr_t rcc_base = stm32_rcc_base();
105 	uint32_t bit_mask = 0;
106 	size_t offset = 0;
107 
108 #ifdef CFG_STM32MP15
109 	switch (id) {
110 	case MCU_HOLD_BOOT_R:
111 		/*
112 		 * The RCC_MP_GCR is a read/write register.
113 		 * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit
114 		 */
115 		io_setbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
116 
117 		return TEE_SUCCESS;
118 	case MCU_R:
119 		/* MCU reset deasserts by its own */
120 		return TEE_SUCCESS;
121 	default:
122 		break;
123 	}
124 #endif
125 
126 	offset = reset_id2reg_offset(id) + RCC_MP_RSTCLRR_OFFSET;
127 	bit_mask = BIT(reset_id2reg_bit_pos(id));
128 
129 	io_write32(rcc_base + offset, bit_mask);
130 
131 	if (to_us) {
132 		uint64_t timeout_ref = timeout_init_us(to_us);
133 
134 		while ((io_read32(rcc_base + offset) & bit_mask))
135 			if (timeout_elapsed(timeout_ref))
136 				break;
137 
138 		if (io_read32(rcc_base + offset) & bit_mask)
139 			return TEE_ERROR_SECURITY;
140 	}
141 
142 	return TEE_SUCCESS;
143 }
144 
145 static struct rstctrl_ops stm32_rstctrl_ops = {
146 	.assert_level = reset_assert,
147 	.deassert_level = reset_deassert,
148 };
149 
150 static struct stm32_rstline *find_rstctrl_device(unsigned int control_id)
151 {
152 	struct stm32_rstline *stm32_rstline = NULL;
153 
154 	SLIST_FOREACH(stm32_rstline, &stm32_rst_list, link)
155 		if (stm32_rstline->id == control_id)
156 			break;
157 
158 	return stm32_rstline;
159 }
160 
161 static struct stm32_rstline *find_or_allocate_rstline(unsigned int binding_id)
162 {
163 	struct stm32_rstline *stm32_rstline = find_rstctrl_device(binding_id);
164 
165 	if (stm32_rstline)
166 		return stm32_rstline;
167 
168 	stm32_rstline = calloc(1, sizeof(*stm32_rstline));
169 	if (stm32_rstline) {
170 		stm32_rstline->rstctrl.ops = &stm32_rstctrl_ops;
171 		stm32_rstline->id = binding_id;
172 		SLIST_INSERT_HEAD(&stm32_rst_list, stm32_rstline, link);
173 	}
174 
175 	return stm32_rstline;
176 }
177 
178 struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id)
179 {
180 	struct stm32_rstline *rstline = find_or_allocate_rstline(binding_id);
181 
182 	assert(rstline);
183 	return &rstline->rstctrl;
184 }
185 
186 static TEE_Result stm32_rstctrl_get_dev(struct dt_pargs *arg,
187 					void *priv_data __unused,
188 					struct rstctrl **out_device)
189 {
190 	struct stm32_rstline *stm32_rstline = NULL;
191 	uintptr_t control_id = 0;
192 
193 	if (arg->args_count != 1)
194 		return TEE_ERROR_BAD_PARAMETERS;
195 
196 	control_id = arg->args[0];
197 
198 	stm32_rstline = find_or_allocate_rstline(control_id);
199 	if (!stm32_rstline)
200 		return TEE_ERROR_OUT_OF_MEMORY;
201 
202 	*out_device = &stm32_rstline->rstctrl;
203 
204 	return TEE_SUCCESS;
205 }
206 
207 static TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs,
208 					       const void *compat_data __unused)
209 {
210 	struct dt_node_info info = { };
211 
212 	assert(rstctrl_ops_is_valid(&stm32_rstctrl_ops));
213 
214 	fdt_fill_device_info(fdt, &info, offs);
215 
216 	assert(info.reg == RCC_BASE &&
217 	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
218 
219 	return rstctrl_register_provider(fdt, offs, stm32_rstctrl_get_dev,
220 					 NULL);
221 }
222 
223 static const struct dt_device_match stm32_rstctrl_match_table[] = {
224 	{ .compatible = "st,stm32mp1-rcc" },
225 	{ .compatible = "st,stm32mp1-rcc-secure" },
226 	{ .compatible = "st,stm32mp13-rcc" },
227 	{ }
228 };
229 
230 DEFINE_DT_DRIVER(stm32_rstctrl_dt_driver) = {
231 	.name = "stm32_rstctrl",
232 	.type = DT_DRIVER_RSTCTRL,
233 	.match_table = stm32_rstctrl_match_table,
234 	.probe = stm32_rstctrl_provider_probe,
235 };
236