xref: /optee_os/core/drivers/stm32_fmc.c (revision 778a36bf91d2271146e6ed57c0cfe925872b2ab6)
1*778a36bfSGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause
2*778a36bfSGatien Chevallier /*
3*778a36bfSGatien Chevallier  * Copyright (c) 2021-2024, STMicroelectronics
4*778a36bfSGatien Chevallier  */
5*778a36bfSGatien Chevallier 
6*778a36bfSGatien Chevallier #include <arm.h>
7*778a36bfSGatien Chevallier #include <config.h>
8*778a36bfSGatien Chevallier #include <drivers/clk.h>
9*778a36bfSGatien Chevallier #include <drivers/clk_dt.h>
10*778a36bfSGatien Chevallier #include <drivers/stm32_gpio.h>
11*778a36bfSGatien Chevallier #include <drivers/stm32_rif.h>
12*778a36bfSGatien Chevallier #include <io.h>
13*778a36bfSGatien Chevallier #include <kernel/boot.h>
14*778a36bfSGatien Chevallier #include <kernel/delay.h>
15*778a36bfSGatien Chevallier #include <kernel/dt.h>
16*778a36bfSGatien Chevallier #include <kernel/dt_driver.h>
17*778a36bfSGatien Chevallier #include <kernel/panic.h>
18*778a36bfSGatien Chevallier #include <kernel/pm.h>
19*778a36bfSGatien Chevallier #include <libfdt.h>
20*778a36bfSGatien Chevallier #include <mm/core_memprot.h>
21*778a36bfSGatien Chevallier #include <stdbool.h>
22*778a36bfSGatien Chevallier #include <stdlib.h>
23*778a36bfSGatien Chevallier #include <stm32_util.h>
24*778a36bfSGatien Chevallier #include <trace.h>
25*778a36bfSGatien Chevallier 
26*778a36bfSGatien Chevallier #define _FMC_CFGR			U(0x020)
27*778a36bfSGatien Chevallier #define _FMC_SECCFGR			U(0x300)
28*778a36bfSGatien Chevallier #define _FMC_PRIVCFGR			U(0x304)
29*778a36bfSGatien Chevallier #define _FMC_RCFGLOCKR			U(0x308)
30*778a36bfSGatien Chevallier #define _FMC_CIDCFGR(x)			(U(0x30C) + U(0x8) * (x))
31*778a36bfSGatien Chevallier #define _FMC_SEMCR(x)			(U(0x310) + U(0x8) * (x))
32*778a36bfSGatien Chevallier /*
33*778a36bfSGatien Chevallier  * CFGR register bitfields
34*778a36bfSGatien Chevallier  */
35*778a36bfSGatien Chevallier #define _FMC_CFGR_CLKDIV_MASK		GENMASK_32(19, 16)
36*778a36bfSGatien Chevallier #define _FMC_CFGR_CLKDIV_SHIFT		U(16)
37*778a36bfSGatien Chevallier #define _FMC_CFGR_CCLKEN		BIT(20)
38*778a36bfSGatien Chevallier #define _FMC_CFGR_ENABLE		BIT(31)
39*778a36bfSGatien Chevallier 
40*778a36bfSGatien Chevallier /*
41*778a36bfSGatien Chevallier  * CIDCFGR register bitfields
42*778a36bfSGatien Chevallier  */
43*778a36bfSGatien Chevallier #define _FMC_CIDCFGR_SEMWL_MASK		GENMASK_32(23, 16)
44*778a36bfSGatien Chevallier #define _FMC_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
45*778a36bfSGatien Chevallier #define _FMC_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	 \
46*778a36bfSGatien Chevallier 					 _CIDCFGR_SEMEN |	 \
47*778a36bfSGatien Chevallier 					 _FMC_CIDCFGR_SCID_MASK |\
48*778a36bfSGatien Chevallier 					 _FMC_CIDCFGR_SEMWL_MASK)
49*778a36bfSGatien Chevallier 
50*778a36bfSGatien Chevallier /*
51*778a36bfSGatien Chevallier  * PRIVCFGR register bitfields
52*778a36bfSGatien Chevallier  */
53*778a36bfSGatien Chevallier #define _FMC_PRIVCFGR_MASK		GENMASK_32(5, 0)
54*778a36bfSGatien Chevallier 
55*778a36bfSGatien Chevallier /*
56*778a36bfSGatien Chevallier  * RCFGLOCKR register bitfields
57*778a36bfSGatien Chevallier  */
58*778a36bfSGatien Chevallier #define _FMC_RCFGLOCKR_MASK		GENMASK_32(5, 0)
59*778a36bfSGatien Chevallier 
60*778a36bfSGatien Chevallier /*
61*778a36bfSGatien Chevallier  * SECCFGR register bitfields
62*778a36bfSGatien Chevallier  */
63*778a36bfSGatien Chevallier #define _FMC_SECCFGR_EN			BIT(0)
64*778a36bfSGatien Chevallier #define _FMC_SECCFGR_MASK		GENMASK_32(5, 0)
65*778a36bfSGatien Chevallier 
66*778a36bfSGatien Chevallier /*
67*778a36bfSGatien Chevallier  * SEMCR register bitfields
68*778a36bfSGatien Chevallier  */
69*778a36bfSGatien Chevallier #define _FMC_SEMCR_SCID_MASK		GENMASK_32(7, 5)
70*778a36bfSGatien Chevallier #define _FMC_SEMCR_SCID_SHIFT		U(5)
71*778a36bfSGatien Chevallier 
72*778a36bfSGatien Chevallier /*
73*778a36bfSGatien Chevallier  * Miscellaneous
74*778a36bfSGatien Chevallier  */
75*778a36bfSGatien Chevallier 
76*778a36bfSGatien Chevallier #define FMC_RIF_CONTROLLERS		U(6)
77*778a36bfSGatien Chevallier 
78*778a36bfSGatien Chevallier #define FMC_NB_MAX_CID_SUPPORTED	U(7)
79*778a36bfSGatien Chevallier 
80*778a36bfSGatien Chevallier #define FMC_NSEC_PER_SEC		UL(1000000000)
81*778a36bfSGatien Chevallier 
82*778a36bfSGatien Chevallier struct fmc_pdata {
83*778a36bfSGatien Chevallier 	struct clk *fmc_clock;
84*778a36bfSGatien Chevallier 	struct pinctrl_state *pinctrl_d;
85*778a36bfSGatien Chevallier 	struct pinctrl_state *pinctrl_s;
86*778a36bfSGatien Chevallier 	struct rif_conf_data conf_data;
87*778a36bfSGatien Chevallier 	unsigned int nb_controller;
88*778a36bfSGatien Chevallier 	vaddr_t base;
89*778a36bfSGatien Chevallier 	uint32_t clk_period_ns;
90*778a36bfSGatien Chevallier 	bool cclken;
91*778a36bfSGatien Chevallier };
92*778a36bfSGatien Chevallier 
93*778a36bfSGatien Chevallier static struct fmc_pdata *fmc_d;
94*778a36bfSGatien Chevallier 
95*778a36bfSGatien Chevallier static bool fmc_controller_is_secure(uint8_t controller)
96*778a36bfSGatien Chevallier {
97*778a36bfSGatien Chevallier 	return io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(controller);
98*778a36bfSGatien Chevallier }
99*778a36bfSGatien Chevallier 
100*778a36bfSGatien Chevallier static TEE_Result apply_rif_config(void)
101*778a36bfSGatien Chevallier {
102*778a36bfSGatien Chevallier 	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
103*778a36bfSGatien Chevallier 	uint32_t cidcfgr = 0;
104*778a36bfSGatien Chevallier 	unsigned int i = 0;
105*778a36bfSGatien Chevallier 
106*778a36bfSGatien Chevallier 	res = clk_enable(fmc_d->fmc_clock);
107*778a36bfSGatien Chevallier 	if (res)
108*778a36bfSGatien Chevallier 		panic("Cannot access FMC clock");
109*778a36bfSGatien Chevallier 
110*778a36bfSGatien Chevallier 	for (i = 0; i < FMC_RIF_CONTROLLERS; i++) {
111*778a36bfSGatien Chevallier 		if (!(BIT(i) & fmc_d->conf_data.access_mask[0]))
112*778a36bfSGatien Chevallier 			continue;
113*778a36bfSGatien Chevallier 
114*778a36bfSGatien Chevallier 		/*
115*778a36bfSGatien Chevallier 		 * Whatever the TDCID state, try to clear the configurable part
116*778a36bfSGatien Chevallier 		 * of the CIDCFGR register.
117*778a36bfSGatien Chevallier 		 * If TDCID, register will be cleared, if not, the clear will
118*778a36bfSGatien Chevallier 		 * be ignored.
119*778a36bfSGatien Chevallier 		 * When TDCID, OP-TEE should be the one to set the CID filtering
120*778a36bfSGatien Chevallier 		 * configuration. Clearing previous configuration prevents
121*778a36bfSGatien Chevallier 		 * undesired events during the only legitimate configuration.
122*778a36bfSGatien Chevallier 		 */
123*778a36bfSGatien Chevallier 		io_clrbits32(fmc_d->base + _FMC_CIDCFGR(i),
124*778a36bfSGatien Chevallier 			     _FMC_CIDCFGR_CONF_MASK);
125*778a36bfSGatien Chevallier 
126*778a36bfSGatien Chevallier 		cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i));
127*778a36bfSGatien Chevallier 
128*778a36bfSGatien Chevallier 		/* Check if the controller is in semaphore mode */
129*778a36bfSGatien Chevallier 		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
130*778a36bfSGatien Chevallier 			continue;
131*778a36bfSGatien Chevallier 
132*778a36bfSGatien Chevallier 		/* If not TDCID, we want to acquire semaphores assigned to us */
133*778a36bfSGatien Chevallier 		res = stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(i),
134*778a36bfSGatien Chevallier 						  FMC_NB_MAX_CID_SUPPORTED);
135*778a36bfSGatien Chevallier 		if (res) {
136*778a36bfSGatien Chevallier 			EMSG("Couldn't acquire semaphore for controller %u", i);
137*778a36bfSGatien Chevallier 			clk_disable(fmc_d->fmc_clock);
138*778a36bfSGatien Chevallier 			return res;
139*778a36bfSGatien Chevallier 		}
140*778a36bfSGatien Chevallier 	}
141*778a36bfSGatien Chevallier 
142*778a36bfSGatien Chevallier 	/* Security and privilege RIF configuration */
143*778a36bfSGatien Chevallier 	io_clrsetbits32(fmc_d->base + _FMC_PRIVCFGR, _FMC_PRIVCFGR_MASK,
144*778a36bfSGatien Chevallier 			fmc_d->conf_data.priv_conf[0]);
145*778a36bfSGatien Chevallier 	io_clrsetbits32(fmc_d->base + _FMC_SECCFGR, _FMC_SECCFGR_MASK,
146*778a36bfSGatien Chevallier 			fmc_d->conf_data.sec_conf[0]);
147*778a36bfSGatien Chevallier 
148*778a36bfSGatien Chevallier 	for (i = 0; i < FMC_RIF_CONTROLLERS; i++) {
149*778a36bfSGatien Chevallier 		if (!(BIT(i) & fmc_d->conf_data.access_mask[0]))
150*778a36bfSGatien Chevallier 			continue;
151*778a36bfSGatien Chevallier 
152*778a36bfSGatien Chevallier 		io_clrsetbits32(fmc_d->base + _FMC_CIDCFGR(i),
153*778a36bfSGatien Chevallier 				_FMC_CIDCFGR_CONF_MASK,
154*778a36bfSGatien Chevallier 				fmc_d->conf_data.cid_confs[i]);
155*778a36bfSGatien Chevallier 
156*778a36bfSGatien Chevallier 		cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i));
157*778a36bfSGatien Chevallier 
158*778a36bfSGatien Chevallier 		/*
159*778a36bfSGatien Chevallier 		 * Take semaphore if the resource is in semaphore mode
160*778a36bfSGatien Chevallier 		 * and secured
161*778a36bfSGatien Chevallier 		 */
162*778a36bfSGatien Chevallier 		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1) ||
163*778a36bfSGatien Chevallier 		    !(io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(i))) {
164*778a36bfSGatien Chevallier 			res =
165*778a36bfSGatien Chevallier 			stm32_rif_release_semaphore(fmc_d->base + _FMC_SEMCR(i),
166*778a36bfSGatien Chevallier 						    FMC_NB_MAX_CID_SUPPORTED);
167*778a36bfSGatien Chevallier 			if (res) {
168*778a36bfSGatien Chevallier 				EMSG("Couldn't release semaphore for res%u", i);
169*778a36bfSGatien Chevallier 				clk_disable(fmc_d->fmc_clock);
170*778a36bfSGatien Chevallier 				return res;
171*778a36bfSGatien Chevallier 			}
172*778a36bfSGatien Chevallier 		} else {
173*778a36bfSGatien Chevallier 			res =
174*778a36bfSGatien Chevallier 			stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(i),
175*778a36bfSGatien Chevallier 						    FMC_NB_MAX_CID_SUPPORTED);
176*778a36bfSGatien Chevallier 			if (res) {
177*778a36bfSGatien Chevallier 				EMSG("Couldn't acquire semaphore for res%u", i);
178*778a36bfSGatien Chevallier 				clk_disable(fmc_d->fmc_clock);
179*778a36bfSGatien Chevallier 				return res;
180*778a36bfSGatien Chevallier 			}
181*778a36bfSGatien Chevallier 		}
182*778a36bfSGatien Chevallier 	}
183*778a36bfSGatien Chevallier 
184*778a36bfSGatien Chevallier 	/*
185*778a36bfSGatien Chevallier 	 * Lock RIF configuration if configured. This cannot be undone until
186*778a36bfSGatien Chevallier 	 * next reset.
187*778a36bfSGatien Chevallier 	 */
188*778a36bfSGatien Chevallier 	io_clrsetbits32(fmc_d->base + _FMC_RCFGLOCKR, _FMC_RCFGLOCKR_MASK,
189*778a36bfSGatien Chevallier 			fmc_d->conf_data.lock_conf[0]);
190*778a36bfSGatien Chevallier 
191*778a36bfSGatien Chevallier 	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
192*778a36bfSGatien Chevallier 		/* Check that RIF config are applied, panic otherwise */
193*778a36bfSGatien Chevallier 		if ((io_read32(fmc_d->base + _FMC_PRIVCFGR) &
194*778a36bfSGatien Chevallier 		     fmc_d->conf_data.access_mask[0]) !=
195*778a36bfSGatien Chevallier 		    fmc_d->conf_data.priv_conf[0]) {
196*778a36bfSGatien Chevallier 			EMSG("FMC controller priv conf is incorrect");
197*778a36bfSGatien Chevallier 			panic();
198*778a36bfSGatien Chevallier 		}
199*778a36bfSGatien Chevallier 
200*778a36bfSGatien Chevallier 		if ((io_read32(fmc_d->base + _FMC_SECCFGR) &
201*778a36bfSGatien Chevallier 		     fmc_d->conf_data.access_mask[0]) !=
202*778a36bfSGatien Chevallier 		    fmc_d->conf_data.sec_conf[0]) {
203*778a36bfSGatien Chevallier 			EMSG("FMC controller sec conf is incorrect");
204*778a36bfSGatien Chevallier 			panic();
205*778a36bfSGatien Chevallier 		}
206*778a36bfSGatien Chevallier 	}
207*778a36bfSGatien Chevallier 
208*778a36bfSGatien Chevallier 	/* Disable the clock to allow RCC RIF re-configuration on this clock */
209*778a36bfSGatien Chevallier 	clk_disable(fmc_d->fmc_clock);
210*778a36bfSGatien Chevallier 
211*778a36bfSGatien Chevallier 	return TEE_SUCCESS;
212*778a36bfSGatien Chevallier }
213*778a36bfSGatien Chevallier 
214*778a36bfSGatien Chevallier static TEE_Result parse_dt(const void *fdt, int node)
215*778a36bfSGatien Chevallier {
216*778a36bfSGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
217*778a36bfSGatien Chevallier 	uint32_t rif_conf = 0;
218*778a36bfSGatien Chevallier 	unsigned int i = 0;
219*778a36bfSGatien Chevallier 	int lenp = 0;
220*778a36bfSGatien Chevallier 	const fdt32_t *cuint = NULL;
221*778a36bfSGatien Chevallier 	struct dt_node_info info = { };
222*778a36bfSGatien Chevallier 	struct io_pa_va addr = { };
223*778a36bfSGatien Chevallier 	int ctrl_node = 0;
224*778a36bfSGatien Chevallier 
225*778a36bfSGatien Chevallier 	fdt_fill_device_info(fdt, &info, node);
226*778a36bfSGatien Chevallier 	assert(info.reg != DT_INFO_INVALID_REG &&
227*778a36bfSGatien Chevallier 	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
228*778a36bfSGatien Chevallier 
229*778a36bfSGatien Chevallier 	addr.pa = info.reg;
230*778a36bfSGatien Chevallier 	fmc_d->base = io_pa_or_va(&addr, info.reg_size);
231*778a36bfSGatien Chevallier 
232*778a36bfSGatien Chevallier 	res = clk_dt_get_by_index(fdt, node, 0, &fmc_d->fmc_clock);
233*778a36bfSGatien Chevallier 	if (res)
234*778a36bfSGatien Chevallier 		return res;
235*778a36bfSGatien Chevallier 
236*778a36bfSGatien Chevallier 	res = pinctrl_get_state_by_name(fdt, node, "default",
237*778a36bfSGatien Chevallier 					&fmc_d->pinctrl_d);
238*778a36bfSGatien Chevallier 	if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
239*778a36bfSGatien Chevallier 		return res;
240*778a36bfSGatien Chevallier 
241*778a36bfSGatien Chevallier 	res = pinctrl_get_state_by_name(fdt, node, "sleep",
242*778a36bfSGatien Chevallier 					&fmc_d->pinctrl_s);
243*778a36bfSGatien Chevallier 	if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
244*778a36bfSGatien Chevallier 		return res;
245*778a36bfSGatien Chevallier 
246*778a36bfSGatien Chevallier 	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
247*778a36bfSGatien Chevallier 	if (!cuint)
248*778a36bfSGatien Chevallier 		panic("No RIF configuration available");
249*778a36bfSGatien Chevallier 
250*778a36bfSGatien Chevallier 	fmc_d->nb_controller = (unsigned int)(lenp / sizeof(uint32_t));
251*778a36bfSGatien Chevallier 	assert(fmc_d->nb_controller <= FMC_RIF_CONTROLLERS);
252*778a36bfSGatien Chevallier 
253*778a36bfSGatien Chevallier 	fmc_d->conf_data.cid_confs = calloc(FMC_RIF_CONTROLLERS,
254*778a36bfSGatien Chevallier 					    sizeof(uint32_t));
255*778a36bfSGatien Chevallier 	fmc_d->conf_data.sec_conf = calloc(1, sizeof(uint32_t));
256*778a36bfSGatien Chevallier 	fmc_d->conf_data.priv_conf = calloc(1, sizeof(uint32_t));
257*778a36bfSGatien Chevallier 	fmc_d->conf_data.lock_conf = calloc(1, sizeof(uint32_t));
258*778a36bfSGatien Chevallier 	fmc_d->conf_data.access_mask = calloc(1, sizeof(uint32_t));
259*778a36bfSGatien Chevallier 	assert(fmc_d->conf_data.cid_confs && fmc_d->conf_data.sec_conf &&
260*778a36bfSGatien Chevallier 	       fmc_d->conf_data.priv_conf && fmc_d->conf_data.access_mask);
261*778a36bfSGatien Chevallier 
262*778a36bfSGatien Chevallier 	for (i = 0; i < fmc_d->nb_controller; i++) {
263*778a36bfSGatien Chevallier 		rif_conf = fdt32_to_cpu(cuint[i]);
264*778a36bfSGatien Chevallier 
265*778a36bfSGatien Chevallier 		stm32_rif_parse_cfg(rif_conf, &fmc_d->conf_data,
266*778a36bfSGatien Chevallier 				    FMC_NB_MAX_CID_SUPPORTED,
267*778a36bfSGatien Chevallier 				    FMC_RIF_CONTROLLERS);
268*778a36bfSGatien Chevallier 	}
269*778a36bfSGatien Chevallier 
270*778a36bfSGatien Chevallier 	fdt_for_each_subnode(ctrl_node, fdt, node) {
271*778a36bfSGatien Chevallier 		int status = fdt_get_status(fdt, ctrl_node);
272*778a36bfSGatien Chevallier 		uint32_t bank = 0;
273*778a36bfSGatien Chevallier 
274*778a36bfSGatien Chevallier 		if (status == DT_STATUS_DISABLED)
275*778a36bfSGatien Chevallier 			continue;
276*778a36bfSGatien Chevallier 
277*778a36bfSGatien Chevallier 		if (fdt_read_uint32(fdt, ctrl_node, "reg", &bank) < 0)
278*778a36bfSGatien Chevallier 			return TEE_ERROR_BAD_PARAMETERS;
279*778a36bfSGatien Chevallier 
280*778a36bfSGatien Chevallier 		if (bank != 0)
281*778a36bfSGatien Chevallier 			continue;
282*778a36bfSGatien Chevallier 
283*778a36bfSGatien Chevallier 		if (fdt_getprop(fdt, ctrl_node,
284*778a36bfSGatien Chevallier 				"st,fmc2-ebi-cs-cclk-enable", NULL))
285*778a36bfSGatien Chevallier 			fmc_d->cclken = true;
286*778a36bfSGatien Chevallier 
287*778a36bfSGatien Chevallier 		if (!fmc_d->cclken)
288*778a36bfSGatien Chevallier 			continue;
289*778a36bfSGatien Chevallier 
290*778a36bfSGatien Chevallier 		if (fdt_read_uint32(fdt, ctrl_node,
291*778a36bfSGatien Chevallier 				    "st,fmc2-ebi-cs-clk-period-ns",
292*778a36bfSGatien Chevallier 				    &fmc_d->clk_period_ns) < 0)
293*778a36bfSGatien Chevallier 			return TEE_ERROR_BAD_PARAMETERS;
294*778a36bfSGatien Chevallier 	}
295*778a36bfSGatien Chevallier 
296*778a36bfSGatien Chevallier 	return TEE_SUCCESS;
297*778a36bfSGatien Chevallier }
298*778a36bfSGatien Chevallier 
299*778a36bfSGatien Chevallier static TEE_Result __maybe_unused check_fmc_rif_conf(void)
300*778a36bfSGatien Chevallier {
301*778a36bfSGatien Chevallier 	unsigned int i = 0;
302*778a36bfSGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
303*778a36bfSGatien Chevallier 
304*778a36bfSGatien Chevallier 	res = clk_enable(fmc_d->fmc_clock);
305*778a36bfSGatien Chevallier 	if (res)
306*778a36bfSGatien Chevallier 		panic("Cannot access FMC clock");
307*778a36bfSGatien Chevallier 
308*778a36bfSGatien Chevallier 	if (fmc_controller_is_secure(0))
309*778a36bfSGatien Chevallier 		goto end;
310*778a36bfSGatien Chevallier 
311*778a36bfSGatien Chevallier 	for (i = 1; i < fmc_d->nb_controller; i++) {
312*778a36bfSGatien Chevallier 		uint32_t cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i));
313*778a36bfSGatien Chevallier 		uint32_t semcr = io_read32(fmc_d->base + _FMC_SEMCR(i));
314*778a36bfSGatien Chevallier 
315*778a36bfSGatien Chevallier 		/* Check if a controller is secure */
316*778a36bfSGatien Chevallier 		if (fmc_controller_is_secure(i)) {
317*778a36bfSGatien Chevallier 			res = TEE_ERROR_BAD_STATE;
318*778a36bfSGatien Chevallier 			goto end;
319*778a36bfSGatien Chevallier 		}
320*778a36bfSGatien Chevallier 
321*778a36bfSGatien Chevallier 		/*
322*778a36bfSGatien Chevallier 		 * Check if a controller is shared with incorrect CID
323*778a36bfSGatien Chevallier 		 * (!= RIF_CID1)
324*778a36bfSGatien Chevallier 		 */
325*778a36bfSGatien Chevallier 		res = stm32_rif_check_access(cidcfgr, semcr,
326*778a36bfSGatien Chevallier 					     FMC_NB_MAX_CID_SUPPORTED,
327*778a36bfSGatien Chevallier 					     RIF_CID1);
328*778a36bfSGatien Chevallier 		if (res)
329*778a36bfSGatien Chevallier 			break;
330*778a36bfSGatien Chevallier 	}
331*778a36bfSGatien Chevallier 
332*778a36bfSGatien Chevallier end:
333*778a36bfSGatien Chevallier 	clk_disable(fmc_d->fmc_clock);
334*778a36bfSGatien Chevallier 
335*778a36bfSGatien Chevallier 	return res;
336*778a36bfSGatien Chevallier }
337*778a36bfSGatien Chevallier 
338*778a36bfSGatien Chevallier static void configure_fmc(void)
339*778a36bfSGatien Chevallier {
340*778a36bfSGatien Chevallier 	uint32_t cidcfgr = 0;
341*778a36bfSGatien Chevallier 	uint32_t semcr = 0;
342*778a36bfSGatien Chevallier 
343*778a36bfSGatien Chevallier 	if (clk_enable(fmc_d->fmc_clock))
344*778a36bfSGatien Chevallier 		panic("Cannot access FMC clock");
345*778a36bfSGatien Chevallier 
346*778a36bfSGatien Chevallier 	semcr = io_read32(fmc_d->base + _FMC_SEMCR(0));
347*778a36bfSGatien Chevallier 	cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(0));
348*778a36bfSGatien Chevallier 
349*778a36bfSGatien Chevallier 	/*
350*778a36bfSGatien Chevallier 	 * If OP-TEE doesn't have access to the controller 0,
351*778a36bfSGatien Chevallier 	 * then we don't want to try to enable the FMC.
352*778a36bfSGatien Chevallier 	 */
353*778a36bfSGatien Chevallier 	if (stm32_rif_check_access(cidcfgr, semcr,
354*778a36bfSGatien Chevallier 				   FMC_NB_MAX_CID_SUPPORTED, RIF_CID1))
355*778a36bfSGatien Chevallier 		goto end;
356*778a36bfSGatien Chevallier 
357*778a36bfSGatien Chevallier 	/* Check controller 0 access */
358*778a36bfSGatien Chevallier 	if (!fmc_controller_is_secure(0)) {
359*778a36bfSGatien Chevallier 		DMSG("Controller 0 non-secure, FMC not enabled");
360*778a36bfSGatien Chevallier 		goto end;
361*778a36bfSGatien Chevallier 	}
362*778a36bfSGatien Chevallier 
363*778a36bfSGatien Chevallier 	if (cidcfgr & _CIDCFGR_SEMEN &&
364*778a36bfSGatien Chevallier 	    stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(0),
365*778a36bfSGatien Chevallier 					FMC_NB_MAX_CID_SUPPORTED))
366*778a36bfSGatien Chevallier 		panic("Couldn't acquire controller 0 semaphore");
367*778a36bfSGatien Chevallier 
368*778a36bfSGatien Chevallier 	if (fmc_d->pinctrl_d && pinctrl_apply_state(fmc_d->pinctrl_d))
369*778a36bfSGatien Chevallier 		panic("Could not apply FMC pinctrl");
370*778a36bfSGatien Chevallier 
371*778a36bfSGatien Chevallier 	if (fmc_d->cclken) {
372*778a36bfSGatien Chevallier 		unsigned long hclk = clk_get_rate(fmc_d->fmc_clock);
373*778a36bfSGatien Chevallier 		unsigned long hclkp = FMC_NSEC_PER_SEC / (hclk / 1000);
374*778a36bfSGatien Chevallier 		unsigned long timing = DIV_ROUND_UP(fmc_d->clk_period_ns * 1000,
375*778a36bfSGatien Chevallier 						    hclkp);
376*778a36bfSGatien Chevallier 		uint32_t clk_div = SHIFT_U32(1, _FMC_CFGR_CLKDIV_SHIFT);
377*778a36bfSGatien Chevallier 
378*778a36bfSGatien Chevallier 		if (timing > 1) {
379*778a36bfSGatien Chevallier 			timing--;
380*778a36bfSGatien Chevallier 			if (timing >
381*778a36bfSGatien Chevallier 			    _FMC_CFGR_CLKDIV_MASK >> _FMC_CFGR_CLKDIV_SHIFT)
382*778a36bfSGatien Chevallier 				clk_div = _FMC_CFGR_CLKDIV_MASK;
383*778a36bfSGatien Chevallier 			else
384*778a36bfSGatien Chevallier 				clk_div = SHIFT_U32(timing,
385*778a36bfSGatien Chevallier 						    _FMC_CFGR_CLKDIV_SHIFT);
386*778a36bfSGatien Chevallier 		}
387*778a36bfSGatien Chevallier 
388*778a36bfSGatien Chevallier 		io_clrsetbits32(fmc_d->base + _FMC_CFGR,
389*778a36bfSGatien Chevallier 				_FMC_CFGR_CLKDIV_MASK | _FMC_CFGR_CCLKEN,
390*778a36bfSGatien Chevallier 				clk_div | _FMC_CFGR_CCLKEN);
391*778a36bfSGatien Chevallier 	}
392*778a36bfSGatien Chevallier 
393*778a36bfSGatien Chevallier 	/* Set the FMC enable BIT */
394*778a36bfSGatien Chevallier 	io_setbits32(fmc_d->base + _FMC_CFGR, _FMC_CFGR_ENABLE);
395*778a36bfSGatien Chevallier 
396*778a36bfSGatien Chevallier end:
397*778a36bfSGatien Chevallier 	clk_disable(fmc_d->fmc_clock);
398*778a36bfSGatien Chevallier }
399*778a36bfSGatien Chevallier 
400*778a36bfSGatien Chevallier static void fmc_setup(void)
401*778a36bfSGatien Chevallier {
402*778a36bfSGatien Chevallier 	if (apply_rif_config())
403*778a36bfSGatien Chevallier 		panic("Failed to apply rif_config");
404*778a36bfSGatien Chevallier 
405*778a36bfSGatien Chevallier 	/* Sanity check for FMC RIF config */
406*778a36bfSGatien Chevallier 	assert(check_fmc_rif_conf());
407*778a36bfSGatien Chevallier 
408*778a36bfSGatien Chevallier 	configure_fmc();
409*778a36bfSGatien Chevallier }
410*778a36bfSGatien Chevallier 
411*778a36bfSGatien Chevallier static void fmc_suspend(void)
412*778a36bfSGatien Chevallier {
413*778a36bfSGatien Chevallier 	unsigned int i = 0;
414*778a36bfSGatien Chevallier 
415*778a36bfSGatien Chevallier 	if (clk_enable(fmc_d->fmc_clock))
416*778a36bfSGatien Chevallier 		panic("Cannot access FMC clock");
417*778a36bfSGatien Chevallier 
418*778a36bfSGatien Chevallier 	if (fmc_controller_is_secure(0) && fmc_d->pinctrl_s &&
419*778a36bfSGatien Chevallier 	    pinctrl_apply_state(fmc_d->pinctrl_s))
420*778a36bfSGatien Chevallier 		panic();
421*778a36bfSGatien Chevallier 
422*778a36bfSGatien Chevallier 	for (i = 0; i < FMC_RIF_CONTROLLERS; i++)
423*778a36bfSGatien Chevallier 		fmc_d->conf_data.cid_confs[i] =
424*778a36bfSGatien Chevallier 			io_read32(fmc_d->base + _FMC_CIDCFGR(i)) &
425*778a36bfSGatien Chevallier 			_FMC_CIDCFGR_CONF_MASK;
426*778a36bfSGatien Chevallier 
427*778a36bfSGatien Chevallier 	fmc_d->conf_data.priv_conf[0] =
428*778a36bfSGatien Chevallier 		io_read32(fmc_d->base + _FMC_PRIVCFGR) & _FMC_PRIVCFGR_MASK;
429*778a36bfSGatien Chevallier 	fmc_d->conf_data.sec_conf[0] =
430*778a36bfSGatien Chevallier 		io_read32(fmc_d->base + _FMC_SECCFGR) & _FMC_SECCFGR_MASK;
431*778a36bfSGatien Chevallier 	fmc_d->conf_data.lock_conf[0] =
432*778a36bfSGatien Chevallier 		io_read32(fmc_d->base + _FMC_RCFGLOCKR) & _FMC_RCFGLOCKR_MASK;
433*778a36bfSGatien Chevallier 	fmc_d->conf_data.access_mask[0] =
434*778a36bfSGatien Chevallier 		GENMASK_32(FMC_RIF_CONTROLLERS - 1, 0);
435*778a36bfSGatien Chevallier 
436*778a36bfSGatien Chevallier 	clk_disable(fmc_d->fmc_clock);
437*778a36bfSGatien Chevallier }
438*778a36bfSGatien Chevallier 
439*778a36bfSGatien Chevallier static TEE_Result fmc_pm(enum pm_op op, unsigned int pm_hint,
440*778a36bfSGatien Chevallier 			 const struct pm_callback_handle *pm_handle __unused)
441*778a36bfSGatien Chevallier {
442*778a36bfSGatien Chevallier 	if (pm_hint != PM_HINT_CONTEXT_STATE)
443*778a36bfSGatien Chevallier 		return TEE_SUCCESS;
444*778a36bfSGatien Chevallier 
445*778a36bfSGatien Chevallier 	if (op == PM_OP_RESUME)
446*778a36bfSGatien Chevallier 		fmc_setup();
447*778a36bfSGatien Chevallier 	else
448*778a36bfSGatien Chevallier 		fmc_suspend();
449*778a36bfSGatien Chevallier 
450*778a36bfSGatien Chevallier 	return TEE_SUCCESS;
451*778a36bfSGatien Chevallier }
452*778a36bfSGatien Chevallier 
453*778a36bfSGatien Chevallier static TEE_Result fmc_probe(const void *fdt, int node,
454*778a36bfSGatien Chevallier 			    const void *compat_data __unused)
455*778a36bfSGatien Chevallier {
456*778a36bfSGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
457*778a36bfSGatien Chevallier 
458*778a36bfSGatien Chevallier 	fmc_d = calloc(1, sizeof(*fmc_d));
459*778a36bfSGatien Chevallier 	if (!fmc_d)
460*778a36bfSGatien Chevallier 		return TEE_ERROR_OUT_OF_MEMORY;
461*778a36bfSGatien Chevallier 
462*778a36bfSGatien Chevallier 	res = parse_dt(fdt, node);
463*778a36bfSGatien Chevallier 	if (res)
464*778a36bfSGatien Chevallier 		goto err;
465*778a36bfSGatien Chevallier 
466*778a36bfSGatien Chevallier 	fmc_setup();
467*778a36bfSGatien Chevallier 
468*778a36bfSGatien Chevallier 	register_pm_core_service_cb(fmc_pm, NULL, "stm32-fmc");
469*778a36bfSGatien Chevallier 
470*778a36bfSGatien Chevallier 	return TEE_SUCCESS;
471*778a36bfSGatien Chevallier err:
472*778a36bfSGatien Chevallier 	/* Free all allocated resources */
473*778a36bfSGatien Chevallier 	free(fmc_d->conf_data.cid_confs);
474*778a36bfSGatien Chevallier 	free(fmc_d->conf_data.sec_conf);
475*778a36bfSGatien Chevallier 	free(fmc_d->conf_data.priv_conf);
476*778a36bfSGatien Chevallier 	free(fmc_d->conf_data.access_mask);
477*778a36bfSGatien Chevallier 	free(fmc_d);
478*778a36bfSGatien Chevallier 
479*778a36bfSGatien Chevallier 	return res;
480*778a36bfSGatien Chevallier }
481*778a36bfSGatien Chevallier 
482*778a36bfSGatien Chevallier static const struct dt_device_match stm32_fmc_match_table[] = {
483*778a36bfSGatien Chevallier 	{ .compatible = "st,stm32mp25-fmc2-ebi" },
484*778a36bfSGatien Chevallier 	{ }
485*778a36bfSGatien Chevallier };
486*778a36bfSGatien Chevallier 
487*778a36bfSGatien Chevallier DEFINE_DT_DRIVER(stm32_fmc_dt_driver) = {
488*778a36bfSGatien Chevallier 	.name = "stm32_fmc",
489*778a36bfSGatien Chevallier 	.match_table = stm32_fmc_match_table,
490*778a36bfSGatien Chevallier 	.probe = fmc_probe,
491*778a36bfSGatien Chevallier };
492