xref: /optee_os/core/drivers/firewall/stm32_etzpc.c (revision 2462f4e0f4dfb511acbf1ff7b90dfb0712e91aea)
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
4  * Copyright (c) 2017-2024, STMicroelectronics
5  */
6 
7 /*
8  * STM32 ETPZC acts as a firewall on stm32mp SoC peripheral interfaces and
9  * internal memories. The driver expects a single instance of the controller
10  * in the platform.
11  */
12 
13 #include <assert.h>
14 #include <drivers/clk_dt.h>
15 #include <drivers/stm32_etzpc.h>
16 #include <drivers/stm32mp_dt_bindings.h>
17 #include <initcall.h>
18 #include <io.h>
19 #include <keep.h>
20 #include <kernel/boot.h>
21 #include <kernel/dt.h>
22 #include <kernel/panic.h>
23 #include <kernel/pm.h>
24 #include <kernel/spinlock.h>
25 #include <libfdt.h>
26 #include <mm/core_memprot.h>
27 #include <stm32_util.h>
28 #include <util.h>
29 
30 /* ID Registers */
31 #define ETZPC_TZMA0_SIZE		U(0x000)
32 #define ETZPC_DECPROT0			U(0x010)
33 #define ETZPC_DECPROT_LOCK0		U(0x030)
34 #define ETZPC_HWCFGR			U(0x3F0)
35 #define ETZPC_VERR			U(0x3F4)
36 
37 /* ID Registers fields */
38 #define ETZPC_TZMA0_SIZE_LOCK		BIT(31)
39 #define ETZPC_DECPROT0_MASK		GENMASK_32(1, 0)
40 #define ETZPC_HWCFGR_NUM_TZMA_MASK	GENMASK_32(7, 0)
41 #define ETZPC_HWCFGR_NUM_TZMA_SHIFT	0
42 #define ETZPC_HWCFGR_NUM_PER_SEC_MASK	GENMASK_32(15, 8)
43 #define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT	8
44 #define ETZPC_HWCFGR_NUM_AHB_SEC_MASK	GENMASK_32(23, 16)
45 #define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT	16
46 #define ETZPC_HWCFGR_CHUNKS1N4_MASK	GENMASK_32(31, 24)
47 #define ETZPC_HWCFGR_CHUNKS1N4_SHIFT	24
48 
49 #define DECPROT_SHIFT			1
50 #define IDS_PER_DECPROT_REGS		U(16)
51 #define IDS_PER_DECPROT_LOCK_REGS	U(32)
52 
53 /*
54  * Implementation uses uint8_t to store each securable DECPROT configuration
55  * and uint16_t to store each securable TZMA configuration. When resuming
56  * from deep suspend, the DECPROT configurations are restored.
57  */
58 #define PERIPH_PM_LOCK_BIT		BIT(7)
59 #define PERIPH_PM_ATTR_MASK		GENMASK_32(2, 0)
60 #define TZMA_PM_LOCK_BIT		BIT(15)
61 #define TZMA_PM_VALUE_MASK		GENMASK_32(9, 0)
62 
63 /*
64  * struct stm32_etzpc_platdata - Driver data set at initialization
65  *
66  * @name:	Name of the peripheral
67  * @clk:	ETZPC clock
68  * @periph_cfg:	Peripheral DECPROT configuration
69  * @tzma_cfg:	TZMA configuration
70  * @base:	ETZPC IOMEM base address
71  */
72 struct stm32_etzpc_platdata {
73 	char *name;
74 	struct clk *clk;
75 	uint8_t *periph_cfg;
76 	uint16_t *tzma_cfg;
77 	struct io_pa_va base;
78 };
79 
80 /*
81  * struct stm32_etzpc_driver_data - configuration data from the hardware
82  *
83  * @num_tzma:	 Number of TZMA zones, read from the hardware
84  * @num_per_sec: Number of securable AHB & APB periphs, read from the hardware
85  * @num_ahb_sec: Number of securable AHB master zones, read from the hardware
86  */
87 struct stm32_etzpc_driver_data {
88 	unsigned int num_tzma;
89 	unsigned int num_per_sec;
90 	unsigned int num_ahb_sec;
91 };
92 
93 /*
94  * struct etzpc_device - ETZPC device driver instance
95  * @pdata:	Platform data set during initialization
96  * @ddata:	Device configuration data from the hardware
97  * @lock:	Access contention
98  */
99 struct etzpc_device {
100 	struct stm32_etzpc_platdata pdata;
101 	struct stm32_etzpc_driver_data ddata;
102 	unsigned int lock;
103 };
104 
105 static struct etzpc_device *etzpc_device;
106 
107 static uint32_t etzpc_lock(void)
108 {
109 	return cpu_spin_lock_xsave(&etzpc_device->lock);
110 }
111 
112 static void etzpc_unlock(uint32_t exceptions)
113 {
114 	cpu_spin_unlock_xrestore(&etzpc_device->lock, exceptions);
115 }
116 
117 static bool valid_decprot_id(unsigned int id)
118 {
119 	return id < etzpc_device->ddata.num_per_sec;
120 }
121 
122 static bool __maybe_unused valid_tzma_id(unsigned int id)
123 {
124 	return id < etzpc_device->ddata.num_tzma;
125 }
126 
127 static enum etzpc_decprot_attributes etzpc_binding2decprot(uint32_t mode)
128 {
129 	switch (mode) {
130 	case DECPROT_S_RW:
131 		return ETZPC_DECPROT_S_RW;
132 	case DECPROT_NS_R_S_W:
133 		return ETZPC_DECPROT_NS_R_S_W;
134 #ifdef CFG_STM32MP15
135 	case DECPROT_MCU_ISOLATION:
136 		return ETZPC_DECPROT_MCU_ISOLATION;
137 #endif
138 	case DECPROT_NS_RW:
139 		return ETZPC_DECPROT_NS_RW;
140 	default:
141 		panic();
142 	}
143 }
144 
145 static void etzpc_configure_decprot(uint32_t decprot_id,
146 				    enum etzpc_decprot_attributes attr)
147 {
148 	size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_REGS);
149 	uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
150 	uint32_t masked_decprot = (uint32_t)attr & ETZPC_DECPROT0_MASK;
151 	vaddr_t base = etzpc_device->pdata.base.va;
152 	unsigned int exceptions = 0;
153 
154 	assert(valid_decprot_id(decprot_id));
155 
156 	DMSG("ID : %"PRIu32", CONF %d", decprot_id, attr);
157 
158 	exceptions = etzpc_lock();
159 
160 	io_clrsetbits32(base + ETZPC_DECPROT0 + offset,
161 			ETZPC_DECPROT0_MASK << shift,
162 			masked_decprot << shift);
163 
164 	etzpc_unlock(exceptions);
165 }
166 
167 enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id)
168 {
169 	size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_REGS);
170 	uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
171 	vaddr_t base = etzpc_device->pdata.base.va;
172 	uint32_t value = 0;
173 
174 	assert(valid_decprot_id(decprot_id));
175 
176 	value = (io_read32(base + ETZPC_DECPROT0 + offset) >> shift) &
177 		ETZPC_DECPROT0_MASK;
178 
179 	return (enum etzpc_decprot_attributes)value;
180 }
181 
182 static void etzpc_lock_decprot(uint32_t decprot_id)
183 {
184 	size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
185 	uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
186 	vaddr_t base = etzpc_device->pdata.base.va;
187 	uint32_t exceptions = 0;
188 
189 	assert(valid_decprot_id(decprot_id));
190 
191 	exceptions = etzpc_lock();
192 
193 	io_write32(base + offset + ETZPC_DECPROT_LOCK0, mask);
194 
195 	etzpc_unlock(exceptions);
196 }
197 
198 static bool decprot_is_locked(uint32_t decprot_id)
199 {
200 	size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
201 	uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
202 	vaddr_t base = etzpc_device->pdata.base.va;
203 
204 	assert(valid_decprot_id(decprot_id));
205 
206 	return io_read32(base + offset + ETZPC_DECPROT_LOCK0) & mask;
207 }
208 
209 void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value)
210 {
211 	size_t offset = sizeof(uint32_t) * tzma_id;
212 	vaddr_t base = etzpc_device->pdata.base.va;
213 	uint32_t exceptions = 0;
214 
215 	assert(valid_tzma_id(tzma_id));
216 
217 	exceptions = etzpc_lock();
218 
219 	io_write32(base + ETZPC_TZMA0_SIZE + offset, tzma_value);
220 
221 	etzpc_unlock(exceptions);
222 }
223 
224 static uint16_t etzpc_get_tzma(uint32_t tzma_id)
225 {
226 	size_t offset = sizeof(uint32_t) * tzma_id;
227 	vaddr_t base = etzpc_device->pdata.base.va;
228 
229 	assert(valid_tzma_id(tzma_id));
230 
231 	return io_read32(base + ETZPC_TZMA0_SIZE + offset);
232 }
233 
234 static void etzpc_lock_tzma(uint32_t tzma_id)
235 {
236 	size_t offset = sizeof(uint32_t) * tzma_id;
237 	vaddr_t base = etzpc_device->pdata.base.va;
238 	uint32_t exceptions = 0;
239 
240 	assert(valid_tzma_id(tzma_id));
241 
242 	exceptions = etzpc_lock();
243 
244 	io_setbits32(base + ETZPC_TZMA0_SIZE + offset, ETZPC_TZMA0_SIZE_LOCK);
245 
246 	etzpc_unlock(exceptions);
247 }
248 
249 static bool tzma_is_locked(uint32_t tzma_id)
250 {
251 	size_t offset = sizeof(uint32_t) * tzma_id;
252 	vaddr_t base = etzpc_device->pdata.base.va;
253 
254 	assert(valid_tzma_id(tzma_id));
255 
256 	return io_read32(base + ETZPC_TZMA0_SIZE + offset) &
257 	       ETZPC_TZMA0_SIZE_LOCK;
258 }
259 
260 static TEE_Result etzpc_pm(enum pm_op op, unsigned int pm_hint __unused,
261 			   const struct pm_callback_handle *pm_handle __unused)
262 {
263 	struct stm32_etzpc_driver_data *ddata = &etzpc_device->ddata;
264 	struct stm32_etzpc_platdata *pdata = &etzpc_device->pdata;
265 	unsigned int n = 0;
266 
267 	if (op == PM_OP_SUSPEND) {
268 		for (n = 0; n < ddata->num_per_sec; n++) {
269 			pdata->periph_cfg[n] =
270 				(uint8_t)etzpc_get_decprot(n);
271 			if (decprot_is_locked(n))
272 				pdata->periph_cfg[n] |= PERIPH_PM_LOCK_BIT;
273 		}
274 
275 		for (n = 0; n < ddata->num_tzma; n++) {
276 			pdata->tzma_cfg[n] =
277 				(uint8_t)etzpc_get_tzma(n);
278 			if (tzma_is_locked(n))
279 				pdata->tzma_cfg[n] |= TZMA_PM_LOCK_BIT;
280 		}
281 
282 		return TEE_SUCCESS;
283 	}
284 
285 	/* PM_OP_RESUME */
286 	for (n = 0; n < ddata->num_per_sec; n++) {
287 		unsigned int attr = pdata->periph_cfg[n] & PERIPH_PM_ATTR_MASK;
288 
289 		etzpc_configure_decprot(n, (enum etzpc_decprot_attributes)attr);
290 
291 		if (pdata->periph_cfg[n] & PERIPH_PM_LOCK_BIT)
292 			etzpc_lock_decprot(n);
293 	}
294 
295 	for (n = 0; n < ddata->num_tzma; n++) {
296 		uint16_t value = pdata->tzma_cfg[n] & TZMA_PM_VALUE_MASK;
297 
298 		etzpc_configure_tzma(n, value);
299 
300 		if (pdata->tzma_cfg[n] & TZMA_PM_LOCK_BIT)
301 			etzpc_lock_tzma(n);
302 	}
303 
304 	return TEE_SUCCESS;
305 }
306 DECLARE_KEEP_PAGER(etzpc_pm);
307 
308 static void stm32_etzpc_set_driverdata(void)
309 {
310 	struct stm32_etzpc_driver_data *ddata = &etzpc_device->ddata;
311 	vaddr_t base = etzpc_device->pdata.base.va;
312 	uint32_t reg = io_read32(base + ETZPC_HWCFGR);
313 
314 	ddata->num_tzma = (reg & ETZPC_HWCFGR_NUM_TZMA_MASK) >>
315 			   ETZPC_HWCFGR_NUM_TZMA_SHIFT;
316 	ddata->num_per_sec = (reg & ETZPC_HWCFGR_NUM_PER_SEC_MASK) >>
317 			      ETZPC_HWCFGR_NUM_PER_SEC_SHIFT;
318 	ddata->num_ahb_sec = (reg & ETZPC_HWCFGR_NUM_AHB_SEC_MASK) >>
319 			      ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT;
320 
321 	DMSG("ETZPC revision 0x%02"PRIx8", per_sec %u, ahb_sec %u, tzma %u",
322 	     io_read8(base + ETZPC_VERR),
323 	     ddata->num_per_sec, ddata->num_ahb_sec, ddata->num_tzma);
324 }
325 
326 static void fdt_etzpc_conf_decprot(const void *fdt, int node)
327 {
328 	const fdt32_t *cuint = NULL;
329 	size_t i = 0;
330 	int len = 0;
331 
332 	cuint = fdt_getprop(fdt, node, "st,decprot", &len);
333 	if (!cuint) {
334 		DMSG("No ETZPC DECPROT configuration in DT");
335 		return;
336 	}
337 
338 	clk_enable(etzpc_device->pdata.clk);
339 
340 	for (i = 0; i < len / sizeof(uint32_t); i++) {
341 		uint32_t value = fdt32_to_cpu(cuint[i]);
342 		uint32_t id = value & ETZPC_ID_MASK;
343 		uint32_t mode = (value & ETZPC_MODE_MASK) >> ETZPC_MODE_SHIFT;
344 		bool lock = value & ETZPC_LOCK_MASK;
345 		enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX;
346 
347 		if (!valid_decprot_id(id)) {
348 			DMSG("Invalid DECPROT %"PRIu32, id);
349 			panic();
350 		}
351 
352 		attr = etzpc_binding2decprot(mode);
353 		etzpc_configure_decprot(id, attr);
354 
355 		if (lock)
356 			etzpc_lock_decprot(id);
357 	}
358 
359 	clk_disable(etzpc_device->pdata.clk);
360 }
361 
362 static TEE_Result init_etzpc_from_dt(const void *fdt, int node)
363 {
364 	TEE_Result res = TEE_ERROR_GENERIC;
365 	struct dt_node_info etzpc_info = { };
366 	int len = 0;
367 
368 	fdt_fill_device_info(fdt, &etzpc_info, node);
369 	if (etzpc_info.reg == DT_INFO_INVALID_REG ||
370 	    etzpc_info.reg_size == DT_INFO_INVALID_REG_SIZE)
371 		return TEE_ERROR_ITEM_NOT_FOUND;
372 
373 	etzpc_device->pdata.base.pa = etzpc_info.reg;
374 	etzpc_device->pdata.name = strdup(fdt_get_name(fdt, node, &len));
375 	io_pa_or_va_secure(&etzpc_device->pdata.base, etzpc_info.reg_size);
376 	res = clk_dt_get_by_index(fdt, node, 0, &etzpc_device->pdata.clk);
377 	if (res)
378 		return res;
379 
380 	stm32_etzpc_set_driverdata();
381 
382 	etzpc_device->pdata.periph_cfg =
383 		calloc(etzpc_device->ddata.num_per_sec,
384 		       sizeof(*etzpc_device->pdata.periph_cfg));
385 
386 	etzpc_device->pdata.tzma_cfg =
387 		calloc(etzpc_device->ddata.num_tzma,
388 		       sizeof(*etzpc_device->pdata.tzma_cfg));
389 	if (!etzpc_device->pdata.periph_cfg || !etzpc_device->pdata.tzma_cfg)
390 		return TEE_ERROR_OUT_OF_MEMORY;
391 
392 	fdt_etzpc_conf_decprot(fdt, node);
393 
394 	return TEE_SUCCESS;
395 }
396 
397 static TEE_Result stm32_etzpc_probe(const void *fdt, int node,
398 				    const void *compat_data __unused)
399 {
400 	TEE_Result res = TEE_ERROR_GENERIC;
401 	int subnode = 0;
402 
403 	etzpc_device = calloc(1, sizeof(*etzpc_device));
404 	if (!etzpc_device)
405 		panic("ETZPC probe failed");
406 
407 	res = init_etzpc_from_dt(fdt, node);
408 	if (res) {
409 		free(etzpc_device->pdata.periph_cfg);
410 		free(etzpc_device->pdata.tzma_cfg);
411 		free(etzpc_device->pdata.name);
412 		free(etzpc_device);
413 		return res;
414 	}
415 
416 	fdt_for_each_subnode(subnode, fdt, node) {
417 		res = dt_driver_maybe_add_probe_node(fdt, subnode);
418 		if (res) {
419 			EMSG("Failed to add node %s to probe list: %#"PRIx32,
420 			     fdt_get_name(fdt, subnode, NULL), res);
421 			panic();
422 		}
423 	}
424 
425 	register_pm_core_service_cb(etzpc_pm, NULL, "stm32-etzpc");
426 
427 	return TEE_SUCCESS;
428 }
429 
430 static const struct dt_device_match etzpc_match_table[] = {
431 	{ .compatible = "st,stm32-etzpc" },
432 	{ }
433 };
434 
435 DEFINE_DT_DRIVER(etzpc_dt_driver) = {
436 	.name = "stm32-etzpc",
437 	.match_table = etzpc_match_table,
438 	.probe = stm32_etzpc_probe,
439 };
440