xref: /optee_os/core/drivers/firewall/stm32_serc.c (revision 612f3e4f430ffd58091335f9df6e815be3ae9c65)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2022-2024, STMicroelectronics
4  */
5 #include <drivers/clk.h>
6 #include <drivers/clk_dt.h>
7 #include <drivers/stm32_rif.h>
8 #include <io.h>
9 #include <kernel/boot.h>
10 #include <kernel/dt.h>
11 #include <kernel/interrupt.h>
12 #include <kernel/panic.h>
13 #include <kernel/pm.h>
14 #include <libfdt.h>
15 #include <mm/core_memprot.h>
16 #include <tee_api_defines.h>
17 #include <trace.h>
18 #include <util.h>
19 
20 /* SERC offset register */
21 #define _SERC_IER0		U(0x000)
22 #define _SERC_ISR0		U(0x040)
23 #define _SERC_ICR0		U(0x080)
24 #define _SERC_ENABLE		U(0x100)
25 
26 #define _SERC_HWCFGR		U(0x3F0)
27 #define _SERC_VERR		U(0x3F4)
28 
29 /* SERC_ENABLE register fields */
30 #define _SERC_ENABLE_SERFEN	BIT(0)
31 
32 /* SERC_HWCFGR register fields */
33 #define _SERC_HWCFGR_CFG1_MASK	GENMASK_32(7, 0)
34 #define _SERC_HWCFGR_CFG1_SHIFT	U(0)
35 #define _SERC_HWCFGR_CFG2_MASK	GENMASK_32(18, 16)
36 #define _SERC_HWCFGR_CFG2_SHIFT	U(16)
37 
38 /* SERC_VERR register fields */
39 #define _SERC_VERR_MINREV_MASK	GENMASK_32(3, 0)
40 #define _SERC_VERR_MINREV_SHIFT	U(0)
41 #define _SERC_VERR_MAJREV_MASK	GENMASK_32(7, 4)
42 #define _SERC_VERR_MAJREV_SHIFT	U(4)
43 
44 /* Periph id per register */
45 #define _PERIPH_IDS_PER_REG	U(32)
46 
47 #define _SERC_FLD_PREP(field, value)	(SHIFT_U32((value), \
48 						   (field ## _SHIFT)) & \
49 					 (field ## _MASK))
50 #define _SERC_FLD_GET(field, value)	(((uint32_t)(value) & \
51 					  (field ## _MASK)) >> \
52 					 (field ## _SHIFT))
53 
54 #define SERC_EXCEPT_MSB_BIT(x) ((x) * _PERIPH_IDS_PER_REG + \
55 				_PERIPH_IDS_PER_REG - 1)
56 #define SERC_EXCEPT_LSB_BIT(x) ((x) * _PERIPH_IDS_PER_REG)
57 
58 /**
59  * struct serc_driver_data - Hardware information on the SERC peripheral
60  *
61  * @version: Peripheral version number
62  * @num_ilac: Number of SERC lines
63  */
64 struct serc_driver_data {
65 	uint32_t version;
66 	uint8_t num_ilac;
67 };
68 
69 /**
70  * struct stm32_serc_platdata - Platform data for the SERC driver
71  *
72  * @irq_chip: Reference to the SERC's IRQ chip
73  * @clock: Reference on the SERC clock
74  * @base: Base address of the SERC peripheral
75  * @irq: ID of the SERC interrupt
76  */
77 struct stm32_serc_platdata {
78 	struct itr_chip *irq_chip;
79 	struct clk *clock;
80 	vaddr_t base;
81 	size_t irq;
82 };
83 
84 /**
85  * struct serc_device - SERC device private data
86  * @pdata: Platform data read from the DT
87  * @ddata: Device data read from the hardware
88  * @itr: Interrupt handler reference
89  */
90 struct serc_device {
91 	struct stm32_serc_platdata pdata;
92 	struct serc_driver_data *ddata;
93 	struct itr_handler *itr;
94 };
95 
96 static struct serc_device serc_dev;
97 
98 static __noreturn void access_violation_action(void)
99 {
100 	DMSG("Ooops...");
101 	panic();
102 }
103 
104 static void stm32_serc_get_hwdata(void)
105 {
106 	struct stm32_serc_platdata *pdata = &serc_dev.pdata;
107 	struct serc_driver_data *ddata = serc_dev.ddata;
108 	vaddr_t base = pdata->base;
109 	uint32_t regval = 0;
110 
111 	regval = io_read32(base + _SERC_HWCFGR);
112 
113 	ddata->num_ilac = _SERC_FLD_GET(_SERC_HWCFGR_CFG1, regval);
114 
115 	ddata->version = io_read32(base + _SERC_VERR);
116 
117 	DMSG("SERC version %"PRIu32".%"PRIu32,
118 	     _SERC_FLD_GET(_SERC_VERR_MAJREV, ddata->version),
119 	     _SERC_FLD_GET(_SERC_VERR_MINREV, ddata->version));
120 
121 	DMSG("HW cap: num ilac:[%"PRIu8"]", ddata->num_ilac);
122 }
123 
124 static TEE_Result stm32_serc_parse_fdt(const void *fdt, int node)
125 {
126 	struct stm32_serc_platdata *pdata = &serc_dev.pdata;
127 	TEE_Result res = TEE_ERROR_GENERIC;
128 	struct dt_node_info dt_info = { };
129 	struct io_pa_va base = { };
130 
131 	fdt_fill_device_info(fdt, &dt_info, node);
132 	if (dt_info.reg == DT_INFO_INVALID_REG)
133 		return TEE_ERROR_BAD_PARAMETERS;
134 
135 	res = interrupt_dt_get(fdt, node, &pdata->irq_chip, &pdata->irq);
136 	if (res)
137 		return res;
138 
139 	base.pa = dt_info.reg;
140 	pdata->base = io_pa_or_va_secure(&base, dt_info.reg_size);
141 
142 	return clk_dt_get_by_index(fdt, node, 0, &pdata->clock);
143 }
144 
145 static void stm32_serc_handle_ilac(void)
146 {
147 	struct stm32_serc_platdata *pdata = &serc_dev.pdata;
148 	struct serc_driver_data *ddata = serc_dev.ddata;
149 	unsigned int nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG);
150 	vaddr_t base = pdata->base;
151 	unsigned int i = 0;
152 	uint32_t isr = 0;
153 
154 	for (i = 0; i < nreg; i++) {
155 		uint32_t offset = sizeof(uint32_t) * i;
156 		unsigned int j = 0;
157 
158 		isr = io_read32(base + _SERC_ISR0 + offset);
159 		isr &= io_read32(base + _SERC_IER0 + offset);
160 
161 		if (!isr)
162 			continue;
163 
164 		EMSG("SERC exceptions [%d:%d]: %#"PRIx32,
165 		     SERC_EXCEPT_MSB_BIT(i), SERC_EXCEPT_LSB_BIT(i), isr);
166 
167 		for (j = 0; j < _PERIPH_IDS_PER_REG; j++) {
168 			EMSG("SERC exception ID: %d",
169 			     SERC_EXCEPT_LSB_BIT(i) + __builtin_ffs(isr) - 1);
170 
171 			io_write32(base + _SERC_ICR0 + offset,
172 				   BIT(__builtin_ffs(isr) - 1));
173 
174 			isr = io_read32(base + _SERC_ISR0 + offset);
175 			isr &= io_read32(base + _SERC_IER0 + offset);
176 
177 			if (!isr)
178 				break;
179 		}
180 	}
181 
182 	access_violation_action();
183 }
184 
185 static enum itr_return stm32_serc_itr(struct itr_handler *h __unused)
186 {
187 	stm32_serc_handle_ilac();
188 
189 	return ITRR_HANDLED;
190 }
191 
192 static void stm32_serc_setup(void)
193 {
194 	struct stm32_serc_platdata *pdata = &serc_dev.pdata;
195 	struct serc_driver_data *ddata = serc_dev.ddata;
196 	vaddr_t base = serc_dev.pdata.base;
197 	uint32_t nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG);
198 	uint32_t i = 0;
199 
200 	io_setbits32(pdata->base + _SERC_ENABLE, _SERC_ENABLE_SERFEN);
201 
202 	for (i = 0; i < nreg; i++) {
203 		vaddr_t reg_ofst = base + sizeof(uint32_t) * i;
204 
205 		/* Clear status flags */
206 		io_write32(reg_ofst + _SERC_ICR0, ~0x0);
207 		/* Enable all peripherals of nreg */
208 		io_write32(reg_ofst + _SERC_IER0, ~0x0);
209 	}
210 }
211 
212 static TEE_Result probe_serc_device(const void *fdt, int node)
213 {
214 	TEE_Result res = TEE_ERROR_GENERIC;
215 
216 	res = stm32_serc_parse_fdt(fdt, node);
217 	if (res)
218 		return res;
219 
220 	/* Unbalanced clock enable to have the SERC running */
221 	if (clk_enable(serc_dev.pdata.clock))
222 		panic();
223 
224 	stm32_serc_get_hwdata();
225 	stm32_serc_setup();
226 
227 	res = interrupt_alloc_add_handler(serc_dev.pdata.irq_chip,
228 					  serc_dev.pdata.irq, stm32_serc_itr,
229 					  ITRF_TRIGGER_LEVEL, NULL,
230 					  &serc_dev.itr);
231 	if (res)
232 		panic();
233 
234 	interrupt_enable(serc_dev.pdata.irq_chip, serc_dev.itr->it);
235 
236 	return TEE_SUCCESS;
237 }
238 
239 static TEE_Result stm32_serc_pm(enum pm_op op, unsigned int pm_hint,
240 				const struct pm_callback_handle *hdl __unused)
241 {
242 	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
243 		return TEE_SUCCESS;
244 
245 	if (op == PM_OP_RESUME) {
246 		if (clk_enable(serc_dev.pdata.clock))
247 			panic();
248 		stm32_serc_setup();
249 	} else {
250 		clk_disable(serc_dev.pdata.clock);
251 	}
252 
253 	return TEE_SUCCESS;
254 }
255 
256 static TEE_Result stm32_serc_probe(const void *fdt, int node,
257 				   const void *compat_data __unused)
258 {
259 	TEE_Result res = TEE_ERROR_GENERIC;
260 
261 	serc_dev.ddata = calloc(1, sizeof(*serc_dev.ddata));
262 	if (!serc_dev.ddata)
263 		return TEE_ERROR_OUT_OF_MEMORY;
264 
265 	res = probe_serc_device(fdt, node);
266 	if (res) {
267 		free(serc_dev.ddata);
268 		return res;
269 	}
270 
271 	register_pm_core_service_cb(stm32_serc_pm, NULL, "stm32-serc");
272 
273 	return TEE_SUCCESS;
274 }
275 
276 static const struct dt_device_match stm32_serc_match_table[] = {
277 	{ .compatible = "st,stm32mp25-serc" },
278 	{ }
279 };
280 
281 DEFINE_DT_DRIVER(stm32_serc_dt_driver) = {
282 	.name = "stm32-serc",
283 	.match_table = stm32_serc_match_table,
284 	.probe = stm32_serc_probe,
285 };
286