xref: /optee_os/core/drivers/stm32_hpdma.c (revision 98dd4c70dbb586416a1515d1470f646ff9383929)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2022-2024, STMicroelectronics
4  */
5 
6 #include <arm.h>
7 #include <config.h>
8 #include <drivers/clk.h>
9 #include <drivers/clk_dt.h>
10 #include <drivers/stm32_gpio.h>
11 #include <drivers/stm32_rif.h>
12 #include <io.h>
13 #include <kernel/boot.h>
14 #include <kernel/delay.h>
15 #include <kernel/dt.h>
16 #include <kernel/dt_driver.h>
17 #include <kernel/panic.h>
18 #include <kernel/pm.h>
19 #include <libfdt.h>
20 #include <mm/core_memprot.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <stm32_util.h>
24 #include <trace.h>
25 
26 #define _HPDMA_SECCFGR			U(0x000)
27 #define _HPDMA_PRIVCFGR			U(0x004)
28 #define _HPDMA_RCFGLOCKR		U(0x008)
29 #define _HPDMA_CIDCFGR(x)		(U(0x054) + U(0x080) * (x))
30 #define _HPDMA_SEMCR(x)			(U(0x058) + U(0x080) * (x))
31 
32 /*
33  * CFGR register bitfields
34  */
35 #define _HPDMA_CFGR_ENABLE		BIT(31)
36 
37 /*
38  * CIDCFGR register bitfields
39  */
40 #define _HPDMA_CIDCFGR_SEMWL_MASK	GENMASK_32(23, 16)
41 #define _HPDMA_CIDCFGR_SEMWL_SHIFT	U(16)
42 #define _HPDMA_CIDCFGR_SCID_MASK	GENMASK_32(5, 4)
43 #define _HPDMA_CIDCFGR_SCID_SHIFT	U(4)
44 #define _HPDMA_CIDCFGR_CONF_MASK	(_CIDCFGR_CFEN |	 \
45 					 _CIDCFGR_SEMEN |	 \
46 					 _HPDMA_CIDCFGR_SCID_MASK |\
47 					 _HPDMA_CIDCFGR_SEMWL_MASK)
48 
49 /*
50  * PRIVCFGR register bitfields
51  */
52 #define _HPDMA_PRIVCFGR_MASK		GENMASK_32(15, 0)
53 
54 /*
55  * RCFGLOCKR register bitfields
56  */
57 #define _HPDMA_RCFGLOCKR_MASK		GENMASK_32(15, 0)
58 
59 /*
60  * SECCFGR register bitfields
61  */
62 #define _HPDMA_SECCFGR_EN		BIT(0)
63 #define _HPDMA_SECCFGR_MASK		GENMASK_32(15, 0)
64 
65 /*
66  * SEMCR register bitfields
67  */
68 #define _HPDMA_SEMCR_SCID_MASK		GENMASK_32(5, 4)
69 #define _HPDMA_SEMCR_SCID_SHIFT		U(4)
70 
71 /*
72  * Miscellaneous
73  */
74 
75 #define HPDMA_RIF_CHANNELS		U(16)
76 
77 #define HPDMA_NB_MAX_CID_SUPPORTED	U(3)
78 
79 struct hpdma_pdata {
80 	struct clk *hpdma_clock;
81 	struct rif_conf_data *conf_data;
82 	unsigned int nb_channels;
83 	vaddr_t base;
84 	bool errata_ahbrisab;
85 
86 	SLIST_ENTRY(hpdma_pdata) link;
87 };
88 
89 static SLIST_HEAD(, hpdma_pdata) hpdma_list =
90 		SLIST_HEAD_INITIALIZER(hpdma_list);
91 
92 static TEE_Result handle_available_semaphores(struct hpdma_pdata *hpdma_d)
93 {
94 	TEE_Result res = TEE_ERROR_GENERIC;
95 	uint32_t cidcfgr = 0;
96 	unsigned int i = 0;
97 
98 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
99 		if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
100 			continue;
101 
102 		cidcfgr = io_read32(hpdma_d->base + _HPDMA_CIDCFGR(i));
103 
104 		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
105 			continue;
106 
107 		if (!(io_read32(hpdma_d->base + _HPDMA_SECCFGR) & BIT(i))) {
108 			res =
109 			stm32_rif_release_semaphore(hpdma_d->base +
110 						    _HPDMA_SEMCR(i),
111 						    HPDMA_NB_MAX_CID_SUPPORTED);
112 			if (res) {
113 				EMSG("Cannot release semaphore for resource %u",
114 				     i);
115 				return res;
116 			}
117 		} else {
118 			res =
119 			stm32_rif_acquire_semaphore(hpdma_d->base +
120 						    _HPDMA_SEMCR(i),
121 						    HPDMA_NB_MAX_CID_SUPPORTED);
122 			if (res) {
123 				EMSG("Cannot acquire semaphore for resource %u",
124 				     i);
125 				return res;
126 			}
127 		}
128 	}
129 
130 	return TEE_SUCCESS;
131 }
132 
133 /* This function expects HPDMA bus clock is enabled */
134 static TEE_Result apply_rif_config(struct hpdma_pdata *hpdma_d, bool is_tdcid)
135 {
136 	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
137 	unsigned int i = 0;
138 
139 	if (!hpdma_d->conf_data)
140 		return TEE_SUCCESS;
141 
142 	if (is_tdcid) {
143 		for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
144 			if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
145 				continue;
146 			/*
147 			 * When TDCID, OP-TEE should be the one to set the CID
148 			 * filtering configuration. Clearing previous
149 			 * configuration prevents undesired events during the
150 			 * only legitimate configuration.
151 			 */
152 			io_clrbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
153 				     _HPDMA_CIDCFGR_CONF_MASK);
154 		}
155 	} else {
156 		res = handle_available_semaphores(hpdma_d);
157 		if (res)
158 			panic();
159 	}
160 
161 	/* Security and privilege RIF configuration */
162 	io_clrsetbits32(hpdma_d->base + _HPDMA_PRIVCFGR, _HPDMA_PRIVCFGR_MASK &
163 			hpdma_d->conf_data->access_mask[0],
164 			hpdma_d->conf_data->priv_conf[0]);
165 	io_clrsetbits32(hpdma_d->base + _HPDMA_SECCFGR, _HPDMA_SECCFGR_MASK &
166 			hpdma_d->conf_data->access_mask[0],
167 			hpdma_d->conf_data->sec_conf[0]);
168 
169 	/* Skip CID/semaphore configuration if not in TDCID state. */
170 	if (!is_tdcid)
171 		goto end;
172 
173 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
174 		uint32_t cid_conf = hpdma_d->conf_data->cid_confs[i];
175 
176 		if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
177 			continue;
178 
179 		/*
180 		 * Errata: When CID filtering is enabled on one of RISAB 3/4/5
181 		 * instances, we forbid the use of CID0 for any initiator on the
182 		 * bus to handle transient CID0 transactions on these RAMs.
183 		 */
184 		if (hpdma_d->errata_ahbrisab &&
185 		    (!(cid_conf & _CIDCFGR_CFEN) ||
186 		     (!(cid_conf & _CIDCFGR_SEMEN) &&
187 		      ((cid_conf & _HPDMA_CIDCFGR_SCID_MASK) >>
188 		       _HPDMA_CIDCFGR_SCID_SHIFT) == RIF_CID0) ||
189 		     (cid_conf & _CIDCFGR_SEMEN &&
190 		      cid_conf & BIT(RIF_CID0 + _HPDMA_CIDCFGR_SEMWL_SHIFT)))) {
191 			EMSG("HPDMA channel cannot hold CID0 value");
192 			if (!IS_ENABLED(CFG_INSECURE))
193 				panic();
194 		}
195 
196 		io_clrsetbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
197 				_HPDMA_CIDCFGR_CONF_MASK, cid_conf);
198 	}
199 
200 	/*
201 	 * Lock RIF configuration if configured. This cannot be undone until
202 	 * next reset.
203 	 */
204 	io_setbits32(hpdma_d->base + _HPDMA_RCFGLOCKR,
205 		     hpdma_d->conf_data->lock_conf[0]);
206 
207 	res = handle_available_semaphores(hpdma_d);
208 	if (res)
209 		panic();
210 
211 end:
212 	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
213 		/* Check that RIF config are applied, panic otherwise */
214 		if ((io_read32(hpdma_d->base + _HPDMA_PRIVCFGR) &
215 		     hpdma_d->conf_data->access_mask[0]) !=
216 		    hpdma_d->conf_data->priv_conf[0])
217 			panic("HPDMA channel priv conf is incorrect");
218 
219 		if ((io_read32(hpdma_d->base + _HPDMA_SECCFGR) &
220 		     hpdma_d->conf_data->access_mask[0]) !=
221 		    hpdma_d->conf_data->sec_conf[0])
222 			panic("HPDMA channel sec conf is incorrect");
223 	}
224 
225 	return TEE_SUCCESS;
226 }
227 
228 static TEE_Result parse_dt(const void *fdt, int node,
229 			   struct hpdma_pdata *hpdma_d)
230 {
231 	TEE_Result res = TEE_ERROR_GENERIC;
232 	unsigned int i = 0;
233 	int lenp = 0;
234 	const fdt32_t *cuint = NULL;
235 	struct dt_node_info info = { };
236 	struct io_pa_va addr = { };
237 
238 	fdt_fill_device_info(fdt, &info, node);
239 	assert(info.reg != DT_INFO_INVALID_REG &&
240 	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
241 
242 	addr.pa = info.reg;
243 	hpdma_d->base = io_pa_or_va_secure(&addr, info.reg_size);
244 
245 	/* Gate the IP */
246 	res = clk_dt_get_by_index(fdt, node, 0, &hpdma_d->hpdma_clock);
247 	if (res)
248 		return res;
249 
250 	hpdma_d->errata_ahbrisab = fdt_getprop(fdt, node, "st,errata-ahbrisab",
251 					       NULL);
252 
253 	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
254 	if (!cuint) {
255 		DMSG("No RIF configuration available");
256 		return TEE_SUCCESS;
257 	}
258 
259 	hpdma_d->conf_data = calloc(1, sizeof(*hpdma_d->conf_data));
260 	if (!hpdma_d->conf_data)
261 		panic();
262 
263 	hpdma_d->nb_channels = (unsigned int)(lenp / sizeof(uint32_t));
264 	assert(hpdma_d->nb_channels <= HPDMA_RIF_CHANNELS);
265 
266 	hpdma_d->conf_data->cid_confs = calloc(HPDMA_RIF_CHANNELS,
267 					       sizeof(uint32_t));
268 	hpdma_d->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
269 	hpdma_d->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
270 	hpdma_d->conf_data->access_mask = calloc(1, sizeof(uint32_t));
271 	hpdma_d->conf_data->lock_conf = calloc(1, sizeof(uint32_t));
272 	if (!hpdma_d->conf_data->cid_confs || !hpdma_d->conf_data->sec_conf ||
273 	    !hpdma_d->conf_data->priv_conf ||
274 	    !hpdma_d->conf_data->access_mask || !hpdma_d->conf_data->lock_conf)
275 		panic("Missing memory capacity for HPDMA RIF configuration");
276 
277 	for (i = 0; i < hpdma_d->nb_channels; i++)
278 		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), hpdma_d->conf_data,
279 				    HPDMA_RIF_CHANNELS);
280 
281 	return TEE_SUCCESS;
282 }
283 
284 static void stm32_hpdma_pm_resume(struct hpdma_pdata *hpdma)
285 {
286 	if (apply_rif_config(hpdma, true))
287 		panic("Failed to resume HPDMA");
288 }
289 
290 static void stm32_hpdma_pm_suspend(struct hpdma_pdata *hpdma)
291 {
292 	size_t i = 0;
293 
294 	for (i = 0; i < HPDMA_RIF_CHANNELS; i++)
295 		hpdma->conf_data->cid_confs[i] = io_read32(hpdma->base +
296 							  _HPDMA_CIDCFGR(i)) &
297 						_HPDMA_CIDCFGR_CONF_MASK;
298 
299 	hpdma->conf_data->priv_conf[0] = io_read32(hpdma->base +
300 						  _HPDMA_PRIVCFGR) &
301 					_HPDMA_PRIVCFGR_MASK;
302 	hpdma->conf_data->sec_conf[0] = io_read32(hpdma->base +
303 						 _HPDMA_SECCFGR) &
304 				       _HPDMA_SECCFGR_MASK;
305 	hpdma->conf_data->lock_conf[0] = io_read32(hpdma->base +
306 						  _HPDMA_RCFGLOCKR) &
307 					_HPDMA_RCFGLOCKR_MASK;
308 
309 	/*
310 	 * The access mask is modified to restore the conf for all
311 	 * resources.
312 	 */
313 	hpdma->conf_data->access_mask[0] = GENMASK_32(HPDMA_RIF_CHANNELS - 1,
314 						      0);
315 }
316 
317 static TEE_Result
318 stm32_hpdma_pm(enum pm_op op, unsigned int pm_hint,
319 	       const struct pm_callback_handle *pm_handle)
320 {
321 	struct hpdma_pdata *hpdma = pm_handle->handle;
322 	TEE_Result res = TEE_ERROR_GENERIC;
323 	bool is_tdcid = false;
324 
325 	res = stm32_rifsc_check_tdcid(&is_tdcid);
326 	if (res)
327 		panic();
328 
329 	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid)
330 		return TEE_SUCCESS;
331 
332 	res = clk_enable(hpdma->hpdma_clock);
333 	if (res)
334 		return res;
335 
336 	if (op == PM_OP_RESUME)
337 		stm32_hpdma_pm_resume(hpdma);
338 	else
339 		stm32_hpdma_pm_suspend(hpdma);
340 
341 	clk_disable(hpdma->hpdma_clock);
342 
343 	return TEE_SUCCESS;
344 }
345 
346 static TEE_Result stm32_hpdma_probe(const void *fdt, int node,
347 				    const void *compat_data __unused)
348 {
349 	TEE_Result res = TEE_ERROR_GENERIC;
350 	struct hpdma_pdata *hpdma_d = NULL;
351 	bool is_tdcid = false;
352 
353 	res = stm32_rifsc_check_tdcid(&is_tdcid);
354 	if (res)
355 		return res;
356 
357 	hpdma_d = calloc(1, sizeof(*hpdma_d));
358 	if (!hpdma_d)
359 		return TEE_ERROR_OUT_OF_MEMORY;
360 
361 	res = parse_dt(fdt, node, hpdma_d);
362 	if (res) {
363 		free(hpdma_d);
364 		return res;
365 	}
366 
367 	if (clk_enable(hpdma_d->hpdma_clock))
368 		panic("Cannot access hpdma clock");
369 
370 	res = apply_rif_config(hpdma_d, is_tdcid);
371 	if (res)
372 		panic("Failed to apply RIF config");
373 
374 	clk_disable(hpdma_d->hpdma_clock);
375 
376 	SLIST_INSERT_HEAD(&hpdma_list, hpdma_d, link);
377 
378 	register_pm_core_service_cb(stm32_hpdma_pm, hpdma_d, "stm32-hpdma");
379 
380 	return TEE_SUCCESS;
381 }
382 
383 static const struct dt_device_match stm32_hpdma_match_table[] = {
384 	{ .compatible = "st,stm32-dma3" },
385 	{ }
386 };
387 
388 DEFINE_DT_DRIVER(stm32_hpdma_dt_driver) = {
389 	.name = "st,stm32-hpdma",
390 	.match_table = stm32_hpdma_match_table,
391 	.probe = stm32_hpdma_probe,
392 };
393