xref: /optee_os/core/drivers/stm32_ipcc.c (revision ce5fe0417a740964a2f3ebf6478ac780d9c58cae)
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_rif.h>
11 #include <io.h>
12 #include <kernel/boot.h>
13 #include <kernel/delay.h>
14 #include <kernel/dt.h>
15 #include <kernel/dt_driver.h>
16 #include <kernel/panic.h>
17 #include <kernel/pm.h>
18 #include <libfdt.h>
19 #include <mm/core_memprot.h>
20 #include <stdbool.h>
21 #include <stdlib.h>
22 #include <stm32_util.h>
23 #include <trace.h>
24 
25 #define IPCC_C1SECCFGR			U(0x80)
26 #define IPCC_C1PRIVCFGR			U(0x84)
27 #define IPCC_C1CIDCFGR			U(0x88)
28 #define IPCC_C2SECCFGR			U(0x90)
29 #define IPCC_C2PRIVCFGR			U(0x94)
30 #define IPCC_C2CIDCFGR			U(0x98)
31 #define IPCC_HWCFGR			U(0x3F0)
32 
33 /*
34  * CIDCFGR register bitfields
35  */
36 #define IPCC_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
37 #define IPCC_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	 \
38 					 IPCC_CIDCFGR_SCID_MASK)
39 
40 /*
41  * PRIVCFGR register bitfields
42  */
43 #define IPCC_PRIVCFGR_MASK		GENMASK_32(15, 0)
44 
45 /*
46  * SECCFGR register bitfields
47  */
48 #define IPCC_SECCFGR_MASK		GENMASK_32(15, 0)
49 
50 /*
51  * IPCC_HWCFGR register bitfields
52  */
53 #define IPCC_HWCFGR_CHAN_MASK		GENMASK_32(7, 0)
54 
55 /*
56  * Miscellaneous
57  */
58 #define IPCC_NB_MAX_RIF_CHAN		U(16)
59 
60 #define IPCC_NB_MAX_CID_SUPPORTED	U(7)
61 
62 struct ipcc_pdata {
63 	/*
64 	 * An IPCC has nb_channels_cfg channel configuration for its
65 	 * (nb_channels_cfg / 2) bi-directionnal channels
66 	 */
67 	unsigned int nb_channels_cfg;
68 	struct clk *ipcc_clock;
69 	vaddr_t base;
70 	struct rif_conf_data *conf_data;
71 
72 	STAILQ_ENTRY(ipcc_pdata) link;
73 };
74 
75 static STAILQ_HEAD(, ipcc_pdata) ipcc_list =
76 		STAILQ_HEAD_INITIALIZER(ipcc_list);
77 
78 /* This function expects IPCC bus clock is enabled */
79 static void apply_rif_config(struct ipcc_pdata *ipcc_d, bool is_tdcid)
80 {
81 	uint32_t priv_proc_1 = 0;
82 	uint32_t priv_proc_2 = 0;
83 	uint32_t sec_proc_1 = 0;
84 	uint32_t sec_proc_2 = 0;
85 	unsigned int i = 0;
86 	bool is_cid_configured = false;
87 
88 	if (!ipcc_d->conf_data)
89 		return;
90 
91 	/*
92 	 * Check that the number of channel supported by hardware
93 	 * is coherent with the config
94 	 */
95 	assert((io_read32(ipcc_d->base + IPCC_HWCFGR) &
96 			  IPCC_HWCFGR_CHAN_MASK) >=
97 	       ipcc_d->nb_channels_cfg / 2);
98 
99 	/*
100 	 * When TDCID, OP-TEE should be the one to set the CID filtering
101 	 * configuration. Clearing previous configuration prevents
102 	 * undesired events during the only legitimate configuration.
103 	 */
104 	if (is_tdcid) {
105 		/* IPCC Processor 1 */
106 		io_clrbits32(ipcc_d->base + IPCC_C1CIDCFGR,
107 			     IPCC_CIDCFGR_CONF_MASK);
108 
109 		/* IPCC Processor 2 */
110 		io_clrbits32(ipcc_d->base + IPCC_C2CIDCFGR,
111 			     IPCC_CIDCFGR_CONF_MASK);
112 	}
113 
114 	/* Split the sec and priv configuration for IPCC processor 1 and 2 */
115 	sec_proc_1 = ipcc_d->conf_data->sec_conf[0] &
116 		     GENMASK_32(IPCC_NB_MAX_RIF_CHAN - 1, 0);
117 	priv_proc_1 = ipcc_d->conf_data->priv_conf[0] &
118 		     GENMASK_32(IPCC_NB_MAX_RIF_CHAN - 1, 0);
119 
120 	sec_proc_2 = (ipcc_d->conf_data->sec_conf[0] &
121 		      GENMASK_32((IPCC_NB_MAX_RIF_CHAN * 2) - 1,
122 				 IPCC_NB_MAX_RIF_CHAN)) >>
123 		     IPCC_NB_MAX_RIF_CHAN;
124 	priv_proc_2 = (ipcc_d->conf_data->priv_conf[0] &
125 		       GENMASK_32((IPCC_NB_MAX_RIF_CHAN * 2) - 1,
126 				  IPCC_NB_MAX_RIF_CHAN)) >>
127 		      IPCC_NB_MAX_RIF_CHAN;
128 
129 	/* Security and privilege RIF configuration */
130 	io_clrsetbits32(ipcc_d->base + IPCC_C1PRIVCFGR, IPCC_PRIVCFGR_MASK,
131 			priv_proc_1);
132 	io_clrsetbits32(ipcc_d->base + IPCC_C2PRIVCFGR, IPCC_PRIVCFGR_MASK,
133 			priv_proc_2);
134 	io_clrsetbits32(ipcc_d->base + IPCC_C1SECCFGR, IPCC_SECCFGR_MASK,
135 			sec_proc_1);
136 	io_clrsetbits32(ipcc_d->base + IPCC_C2SECCFGR, IPCC_SECCFGR_MASK,
137 			sec_proc_2);
138 
139 	/*
140 	 * Evaluate RIF CID filtering configuration before setting it.
141 	 * Parsed configuration must have consistency. If CID filtering
142 	 * is enabled for an IPCC channel, then it must be the case for all
143 	 * channels of this processor. This is a configuration check.
144 	 */
145 	for (i = 0; i < IPCC_NB_MAX_RIF_CHAN; i++) {
146 		if (!(BIT(i) & ipcc_d->conf_data->access_mask[0]))
147 			continue;
148 
149 		if (!is_cid_configured &&
150 		    (BIT(0) & ipcc_d->conf_data->cid_confs[i])) {
151 			is_cid_configured = true;
152 			if (i == IPCC_NB_MAX_RIF_CHAN - 1)
153 				panic("Inconsistent IPCC CID filtering RIF configuration");
154 		}
155 
156 		if (is_cid_configured &&
157 		    !(BIT(0) & ipcc_d->conf_data->cid_confs[i]))
158 			panic("Inconsistent IPCC CID filtering RIF configuration");
159 	}
160 
161 	/* IPCC processor 1 CID filtering configuration */
162 	if (!is_tdcid)
163 		return;
164 
165 	io_clrsetbits32(ipcc_d->base + IPCC_C1CIDCFGR,
166 			IPCC_CIDCFGR_CONF_MASK,
167 			ipcc_d->conf_data->cid_confs[0]);
168 
169 	/*
170 	 * Reset this field to evaluate CID filtering configuration
171 	 * for processor 2
172 	 */
173 	is_cid_configured = false;
174 
175 	for (i = IPCC_NB_MAX_RIF_CHAN; i < IPCC_NB_MAX_RIF_CHAN * 2; i++) {
176 		if (!(BIT(i) & ipcc_d->conf_data->access_mask[0]))
177 			continue;
178 
179 		if (!is_cid_configured &&
180 		    (BIT(0) & ipcc_d->conf_data->cid_confs[i])) {
181 			is_cid_configured = true;
182 			if (i == (IPCC_NB_MAX_RIF_CHAN * 2) - 1)
183 				panic("Inconsistent IPCC CID filtering RIF configuration");
184 		}
185 
186 		if (is_cid_configured &&
187 		    !(BIT(0) & ipcc_d->conf_data->cid_confs[i]))
188 			panic("Inconsistent IPCC CID filtering RIF configuration");
189 	}
190 
191 	/* IPCC Processor 2 CID filtering configuration */
192 	io_clrsetbits32(ipcc_d->base + IPCC_C2CIDCFGR,
193 			IPCC_CIDCFGR_CONF_MASK,
194 			ipcc_d->conf_data->cid_confs[IPCC_NB_MAX_RIF_CHAN]);
195 }
196 
197 static void stm32_ipcc_pm_resume(struct ipcc_pdata *ipcc)
198 {
199 	apply_rif_config(ipcc, true);
200 }
201 
202 static void stm32_ipcc_pm_suspend(struct ipcc_pdata *ipcc __unused)
203 {
204 	/*
205 	 * Do nothing because IPCC forbids RIF configuration read if CID
206 	 * filtering is enabled. We'll simply restore the device tree RIF
207 	 * configuration.
208 	 */
209 }
210 
211 static TEE_Result
212 stm32_ipcc_pm(enum pm_op op, unsigned int pm_hint,
213 	      const struct pm_callback_handle *pm_handle)
214 {
215 	struct ipcc_pdata *ipcc = pm_handle->handle;
216 	TEE_Result res = TEE_ERROR_GENERIC;
217 	bool is_tdcid = false;
218 
219 	if (stm32_rifsc_check_tdcid(&is_tdcid))
220 		panic();
221 
222 	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid)
223 		return TEE_SUCCESS;
224 
225 	res = clk_enable(ipcc->ipcc_clock);
226 	if (res)
227 		return res;
228 
229 	if (op == PM_OP_RESUME)
230 		stm32_ipcc_pm_resume(ipcc);
231 	else
232 		stm32_ipcc_pm_suspend(ipcc);
233 
234 	clk_disable(ipcc->ipcc_clock);
235 
236 	return TEE_SUCCESS;
237 }
238 
239 static TEE_Result parse_dt(const void *fdt, int node, struct ipcc_pdata *ipcc_d)
240 {
241 	TEE_Result res = TEE_ERROR_GENERIC;
242 	struct dt_node_info info = { };
243 	const fdt32_t *cuint = NULL;
244 	struct io_pa_va addr = { };
245 	unsigned int i = 0;
246 	int lenp = 0;
247 
248 	fdt_fill_device_info(fdt, &info, node);
249 	assert(info.reg != DT_INFO_INVALID_REG &&
250 	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
251 
252 	addr.pa = info.reg;
253 	ipcc_d->base = io_pa_or_va_secure(&addr, info.reg_size);
254 	assert(ipcc_d->base);
255 
256 	/* Gate the IP */
257 	res = clk_dt_get_by_index(fdt, node, 0, &ipcc_d->ipcc_clock);
258 	if (res)
259 		return res;
260 
261 	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
262 	if (!cuint) {
263 		DMSG("No RIF configuration available");
264 		return TEE_SUCCESS;
265 	}
266 
267 	ipcc_d->conf_data = calloc(1, sizeof(*ipcc_d->conf_data));
268 	if (!ipcc_d->conf_data)
269 		panic();
270 
271 	ipcc_d->nb_channels_cfg = (unsigned int)(lenp / sizeof(uint32_t));
272 	assert(ipcc_d->nb_channels_cfg <= (IPCC_NB_MAX_RIF_CHAN * 2));
273 
274 	ipcc_d->conf_data->cid_confs = calloc(IPCC_NB_MAX_RIF_CHAN * 2,
275 					      sizeof(uint32_t));
276 	ipcc_d->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
277 	ipcc_d->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
278 	ipcc_d->conf_data->access_mask = calloc(1, sizeof(uint32_t));
279 	if (!ipcc_d->conf_data->cid_confs || !ipcc_d->conf_data->sec_conf ||
280 	    !ipcc_d->conf_data->priv_conf || !ipcc_d->conf_data->access_mask)
281 		panic("Missing memory capacity for ipcc RIF configuration");
282 
283 	for (i = 0; i < ipcc_d->nb_channels_cfg; i++)
284 		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), ipcc_d->conf_data,
285 				    IPCC_NB_MAX_RIF_CHAN * 2);
286 
287 	return TEE_SUCCESS;
288 }
289 
290 static TEE_Result stm32_ipcc_probe(const void *fdt, int node,
291 				   const void *compat_data __unused)
292 {
293 	TEE_Result res = TEE_ERROR_GENERIC;
294 	struct ipcc_pdata *ipcc_d = NULL;
295 	bool is_tdcid = false;
296 
297 	res = stm32_rifsc_check_tdcid(&is_tdcid);
298 	if (res)
299 		return res;
300 
301 	ipcc_d = calloc(1, sizeof(*ipcc_d));
302 	if (!ipcc_d)
303 		return TEE_ERROR_OUT_OF_MEMORY;
304 
305 	res = parse_dt(fdt, node, ipcc_d);
306 	if (res)
307 		goto err;
308 
309 	res = clk_enable(ipcc_d->ipcc_clock);
310 	if (res)
311 		panic("Cannot access IPCC clock");
312 
313 	apply_rif_config(ipcc_d, is_tdcid);
314 
315 	clk_disable(ipcc_d->ipcc_clock);
316 
317 	STAILQ_INSERT_TAIL(&ipcc_list, ipcc_d, link);
318 
319 	register_pm_core_service_cb(stm32_ipcc_pm, ipcc_d, "stm32-ipcc");
320 
321 	return res;
322 
323 err:
324 	/* Free all allocated resources */
325 	if (ipcc_d->conf_data) {
326 		free(ipcc_d->conf_data->access_mask);
327 		free(ipcc_d->conf_data->cid_confs);
328 		free(ipcc_d->conf_data->priv_conf);
329 		free(ipcc_d->conf_data->sec_conf);
330 	}
331 	free(ipcc_d->conf_data);
332 	free(ipcc_d);
333 
334 	return res;
335 }
336 
337 static const struct dt_device_match stm32_ipcc_match_table[] = {
338 	{ .compatible = "st,stm32mp25-ipcc" },
339 	{ }
340 };
341 
342 DEFINE_DT_DRIVER(stm32_ipcc_dt_driver) = {
343 	.name = "st,stm32mp-ipcc",
344 	.match_table = stm32_ipcc_match_table,
345 	.probe = stm32_ipcc_probe,
346 };
347