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