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