1*399cfdd4SNicolas Le Bayon /*
2*399cfdd4SNicolas Le Bayon * Copyright (c) 2025, STMicroelectronics - All Rights Reserved
3*399cfdd4SNicolas Le Bayon *
4*399cfdd4SNicolas Le Bayon * SPDX-License-Identifier: BSD-3-Clause
5*399cfdd4SNicolas Le Bayon */
6*399cfdd4SNicolas Le Bayon
7*399cfdd4SNicolas Le Bayon #include <assert.h>
8*399cfdd4SNicolas Le Bayon #include <errno.h>
9*399cfdd4SNicolas Le Bayon
10*399cfdd4SNicolas Le Bayon #include <arch_helpers.h>
11*399cfdd4SNicolas Le Bayon #include <common/debug.h>
12*399cfdd4SNicolas Le Bayon #include <drivers/clk.h>
13*399cfdd4SNicolas Le Bayon #include <drivers/delay_timer.h>
14*399cfdd4SNicolas Le Bayon #include <drivers/st/stm32mp2_risaf.h>
15*399cfdd4SNicolas Le Bayon #include <dt-bindings/soc/rif.h>
16*399cfdd4SNicolas Le Bayon #include <lib/mmio.h>
17*399cfdd4SNicolas Le Bayon #include <libfdt.h>
18*399cfdd4SNicolas Le Bayon #include <plat/common/platform.h>
19*399cfdd4SNicolas Le Bayon
20*399cfdd4SNicolas Le Bayon #include <platform_def.h>
21*399cfdd4SNicolas Le Bayon #include <stm32mp_fconf_getter.h>
22*399cfdd4SNicolas Le Bayon
23*399cfdd4SNicolas Le Bayon static struct stm32mp2_risaf_platdata stm32mp2_risaf;
24*399cfdd4SNicolas Le Bayon static int region_per_instance[RISAF_MAX_INSTANCE];
25*399cfdd4SNicolas Le Bayon
26*399cfdd4SNicolas Le Bayon #if ENABLE_ASSERTIONS
valid_protreg_id(int instance,uint32_t id)27*399cfdd4SNicolas Le Bayon static bool valid_protreg_id(int instance, uint32_t id)
28*399cfdd4SNicolas Le Bayon {
29*399cfdd4SNicolas Le Bayon uint32_t max_id;
30*399cfdd4SNicolas Le Bayon
31*399cfdd4SNicolas Le Bayon max_id = mmio_read_32(stm32mp2_risaf.base[instance] + _RISAF_HWCFGR);
32*399cfdd4SNicolas Le Bayon max_id = (max_id & _RISAF_HWCFGR_CFG1_MASK) >> _RISAF_HWCFGR_CFG1_SHIFT;
33*399cfdd4SNicolas Le Bayon
34*399cfdd4SNicolas Le Bayon return id < max_id;
35*399cfdd4SNicolas Le Bayon }
36*399cfdd4SNicolas Le Bayon
valid_instance(int instance)37*399cfdd4SNicolas Le Bayon static bool valid_instance(int instance)
38*399cfdd4SNicolas Le Bayon {
39*399cfdd4SNicolas Le Bayon return (instance < RISAF_MAX_INSTANCE) && (stm32mp2_risaf.base[instance] != 0U);
40*399cfdd4SNicolas Le Bayon }
41*399cfdd4SNicolas Le Bayon #endif
42*399cfdd4SNicolas Le Bayon
risaf_is_hw_encryption_functional(int instance)43*399cfdd4SNicolas Le Bayon static bool risaf_is_hw_encryption_functional(int instance)
44*399cfdd4SNicolas Le Bayon {
45*399cfdd4SNicolas Le Bayon return (mmio_read_32(stm32mp2_risaf.base[instance] + _RISAF_SR) & _RISAF_SR_ENCDIS) !=
46*399cfdd4SNicolas Le Bayon _RISAF_SR_ENCDIS;
47*399cfdd4SNicolas Le Bayon }
48*399cfdd4SNicolas Le Bayon
check_region_boundaries(int instance,uintptr_t addr,size_t len)49*399cfdd4SNicolas Le Bayon static int check_region_boundaries(int instance, uintptr_t addr, size_t len)
50*399cfdd4SNicolas Le Bayon {
51*399cfdd4SNicolas Le Bayon uintptr_t end_address;
52*399cfdd4SNicolas Le Bayon uintptr_t mem_base = stm32_risaf_get_memory_base(instance);
53*399cfdd4SNicolas Le Bayon
54*399cfdd4SNicolas Le Bayon if ((addr < mem_base) || (len == 0U)) {
55*399cfdd4SNicolas Le Bayon return -EINVAL;
56*399cfdd4SNicolas Le Bayon }
57*399cfdd4SNicolas Le Bayon
58*399cfdd4SNicolas Le Bayon /* Get physical end address */
59*399cfdd4SNicolas Le Bayon end_address = mem_base + stm32_risaf_get_memory_size(instance) - 1U;
60*399cfdd4SNicolas Le Bayon if ((addr > end_address) || ((addr - 1U + len) > end_address)) {
61*399cfdd4SNicolas Le Bayon return -EINVAL;
62*399cfdd4SNicolas Le Bayon }
63*399cfdd4SNicolas Le Bayon
64*399cfdd4SNicolas Le Bayon if ((stm32mp2_risaf.granularity[instance] == 0U) ||
65*399cfdd4SNicolas Le Bayon ((addr % stm32mp2_risaf.granularity[instance]) != 0U) ||
66*399cfdd4SNicolas Le Bayon ((len % stm32mp2_risaf.granularity[instance]) != 0U)) {
67*399cfdd4SNicolas Le Bayon return -EINVAL;
68*399cfdd4SNicolas Le Bayon }
69*399cfdd4SNicolas Le Bayon
70*399cfdd4SNicolas Le Bayon return 0;
71*399cfdd4SNicolas Le Bayon }
72*399cfdd4SNicolas Le Bayon
do_regions_overlap(uintptr_t addr1,size_t len1,uintptr_t addr2,size_t len2)73*399cfdd4SNicolas Le Bayon static bool do_regions_overlap(uintptr_t addr1, size_t len1, uintptr_t addr2, size_t len2)
74*399cfdd4SNicolas Le Bayon {
75*399cfdd4SNicolas Le Bayon return !((addr1 >= (addr2 + len2)) || (addr2 >= (addr1 + len1)));
76*399cfdd4SNicolas Le Bayon }
77*399cfdd4SNicolas Le Bayon
check_region_overlap(void)78*399cfdd4SNicolas Le Bayon static int check_region_overlap(void)
79*399cfdd4SNicolas Le Bayon {
80*399cfdd4SNicolas Le Bayon struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
81*399cfdd4SNicolas Le Bayon int i;
82*399cfdd4SNicolas Le Bayon uintptr_t addr;
83*399cfdd4SNicolas Le Bayon size_t length;
84*399cfdd4SNicolas Le Bayon int instance;
85*399cfdd4SNicolas Le Bayon int region_id;
86*399cfdd4SNicolas Le Bayon
87*399cfdd4SNicolas Le Bayon if (pdata->nregions <= 1) {
88*399cfdd4SNicolas Le Bayon /*
89*399cfdd4SNicolas Le Bayon * No region found, or first region found.
90*399cfdd4SNicolas Le Bayon * No need to check overlap with previous ones.
91*399cfdd4SNicolas Le Bayon */
92*399cfdd4SNicolas Le Bayon return 0;
93*399cfdd4SNicolas Le Bayon }
94*399cfdd4SNicolas Le Bayon
95*399cfdd4SNicolas Le Bayon region_id = pdata->nregions - 1;
96*399cfdd4SNicolas Le Bayon addr = pdata->region[region_id].addr;
97*399cfdd4SNicolas Le Bayon length = pdata->region[region_id].len;
98*399cfdd4SNicolas Le Bayon instance = pdata->region[region_id].instance;
99*399cfdd4SNicolas Le Bayon
100*399cfdd4SNicolas Le Bayon for (i = 0; i < region_id; i++) {
101*399cfdd4SNicolas Le Bayon if (pdata->region[i].instance != instance) {
102*399cfdd4SNicolas Le Bayon continue;
103*399cfdd4SNicolas Le Bayon }
104*399cfdd4SNicolas Le Bayon
105*399cfdd4SNicolas Le Bayon if (do_regions_overlap(addr, length,
106*399cfdd4SNicolas Le Bayon pdata->region[i].addr, pdata->region[i].len)) {
107*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: Regions %d and %d overlap\n", instance + 1, region_id, i);
108*399cfdd4SNicolas Le Bayon return -EINVAL;
109*399cfdd4SNicolas Le Bayon }
110*399cfdd4SNicolas Le Bayon }
111*399cfdd4SNicolas Le Bayon
112*399cfdd4SNicolas Le Bayon return 0;
113*399cfdd4SNicolas Le Bayon }
114*399cfdd4SNicolas Le Bayon
risaf_configure_region(int instance,uint32_t region_id,uint32_t cfg,uint32_t cid_cfg,uintptr_t saddr,uintptr_t eaddr)115*399cfdd4SNicolas Le Bayon static int risaf_configure_region(int instance, uint32_t region_id, uint32_t cfg,
116*399cfdd4SNicolas Le Bayon uint32_t cid_cfg, uintptr_t saddr, uintptr_t eaddr)
117*399cfdd4SNicolas Le Bayon {
118*399cfdd4SNicolas Le Bayon uintptr_t base = stm32mp2_risaf.base[instance];
119*399cfdd4SNicolas Le Bayon uint32_t hwcfgr;
120*399cfdd4SNicolas Le Bayon uint32_t mask_lsb;
121*399cfdd4SNicolas Le Bayon uint32_t mask_msb;
122*399cfdd4SNicolas Le Bayon uint32_t mask;
123*399cfdd4SNicolas Le Bayon
124*399cfdd4SNicolas Le Bayon assert(valid_instance(instance));
125*399cfdd4SNicolas Le Bayon assert(valid_protreg_id(instance, region_id));
126*399cfdd4SNicolas Le Bayon
127*399cfdd4SNicolas Le Bayon mmio_clrbits_32(base + _RISAF_REG_CFGR(region_id), _RISAF_REG_CFGR_BREN);
128*399cfdd4SNicolas Le Bayon
129*399cfdd4SNicolas Le Bayon /* Get address mask depending on RISAF instance HW configuration */
130*399cfdd4SNicolas Le Bayon hwcfgr = mmio_read_32(base + _RISAF_HWCFGR);
131*399cfdd4SNicolas Le Bayon mask_lsb = (hwcfgr & _RISAF_HWCFGR_CFG3_MASK) >> _RISAF_HWCFGR_CFG3_SHIFT;
132*399cfdd4SNicolas Le Bayon mask_msb = mask_lsb + ((hwcfgr & _RISAF_HWCFGR_CFG4_MASK) >> _RISAF_HWCFGR_CFG4_SHIFT) - 1U;
133*399cfdd4SNicolas Le Bayon mask = GENMASK_32(mask_msb, mask_lsb);
134*399cfdd4SNicolas Le Bayon
135*399cfdd4SNicolas Le Bayon mmio_clrsetbits_32(base + _RISAF_REG_STARTR(region_id), mask,
136*399cfdd4SNicolas Le Bayon (saddr - stm32_risaf_get_memory_base(instance)) & mask);
137*399cfdd4SNicolas Le Bayon mmio_clrsetbits_32(base + _RISAF_REG_ENDR(region_id), mask,
138*399cfdd4SNicolas Le Bayon (eaddr - stm32_risaf_get_memory_base(instance)) & mask);
139*399cfdd4SNicolas Le Bayon
140*399cfdd4SNicolas Le Bayon mmio_clrsetbits_32(base + _RISAF_REG_CIDCFGR(region_id), _RISAF_REG_CIDCFGR_ALL_MASK,
141*399cfdd4SNicolas Le Bayon cid_cfg & _RISAF_REG_CIDCFGR_ALL_MASK);
142*399cfdd4SNicolas Le Bayon
143*399cfdd4SNicolas Le Bayon mmio_clrsetbits_32(base + _RISAF_REG_CFGR(region_id),
144*399cfdd4SNicolas Le Bayon _RISAF_REG_CFGR_ALL_MASK, cfg & _RISAF_REG_CFGR_ALL_MASK);
145*399cfdd4SNicolas Le Bayon
146*399cfdd4SNicolas Le Bayon if ((cfg & _RISAF_REG_CFGR_ENC) == _RISAF_REG_CFGR_ENC) {
147*399cfdd4SNicolas Le Bayon if (!risaf_is_hw_encryption_functional(instance)) {
148*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: encryption disabled\n", instance + 1);
149*399cfdd4SNicolas Le Bayon return -EIO;
150*399cfdd4SNicolas Le Bayon }
151*399cfdd4SNicolas Le Bayon
152*399cfdd4SNicolas Le Bayon if ((cfg & _RISAF_REG_CFGR_SEC) != _RISAF_REG_CFGR_SEC) {
153*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: encryption on non secure area\n", instance + 1);
154*399cfdd4SNicolas Le Bayon return -EIO;
155*399cfdd4SNicolas Le Bayon }
156*399cfdd4SNicolas Le Bayon }
157*399cfdd4SNicolas Le Bayon
158*399cfdd4SNicolas Le Bayon return 0;
159*399cfdd4SNicolas Le Bayon }
160*399cfdd4SNicolas Le Bayon
risaf_conf_protreg(void)161*399cfdd4SNicolas Le Bayon static void risaf_conf_protreg(void)
162*399cfdd4SNicolas Le Bayon {
163*399cfdd4SNicolas Le Bayon struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
164*399cfdd4SNicolas Le Bayon int idx;
165*399cfdd4SNicolas Le Bayon
166*399cfdd4SNicolas Le Bayon for (idx = 0; idx < RISAF_MAX_INSTANCE; idx++) {
167*399cfdd4SNicolas Le Bayon int n;
168*399cfdd4SNicolas Le Bayon
169*399cfdd4SNicolas Le Bayon if (pdata->base[idx] == 0) {
170*399cfdd4SNicolas Le Bayon continue;
171*399cfdd4SNicolas Le Bayon }
172*399cfdd4SNicolas Le Bayon
173*399cfdd4SNicolas Le Bayon if (clk_enable(pdata->clock[idx]) != 0) {
174*399cfdd4SNicolas Le Bayon ERROR("%s: RISAF@%lx clock failed\n", __func__, pdata->base[idx]);
175*399cfdd4SNicolas Le Bayon panic();
176*399cfdd4SNicolas Le Bayon }
177*399cfdd4SNicolas Le Bayon
178*399cfdd4SNicolas Le Bayon for (n = 0; n < pdata->nregions; n++) {
179*399cfdd4SNicolas Le Bayon uint32_t id;
180*399cfdd4SNicolas Le Bayon uint32_t value;
181*399cfdd4SNicolas Le Bayon uint32_t cfg;
182*399cfdd4SNicolas Le Bayon uint32_t cid_cfg;
183*399cfdd4SNicolas Le Bayon uintptr_t start_addr;
184*399cfdd4SNicolas Le Bayon uintptr_t end_addr;
185*399cfdd4SNicolas Le Bayon
186*399cfdd4SNicolas Le Bayon if (pdata->region[n].instance != idx) {
187*399cfdd4SNicolas Le Bayon continue;
188*399cfdd4SNicolas Le Bayon }
189*399cfdd4SNicolas Le Bayon
190*399cfdd4SNicolas Le Bayon value = pdata->region[n].cfg;
191*399cfdd4SNicolas Le Bayon id = (value & DT_RISAF_REG_ID_MASK);
192*399cfdd4SNicolas Le Bayon assert(valid_protreg_id(idx, id));
193*399cfdd4SNicolas Le Bayon
194*399cfdd4SNicolas Le Bayon cfg = (((value & DT_RISAF_EN_MASK) >> DT_RISAF_EN_SHIFT) <<
195*399cfdd4SNicolas Le Bayon _RISAF_REG_CFGR_BREN_SHIFT) |
196*399cfdd4SNicolas Le Bayon (((value & DT_RISAF_SEC_MASK) >> DT_RISAF_SEC_SHIFT) <<
197*399cfdd4SNicolas Le Bayon _RISAF_REG_CFGR_SEC_SHIFT) |
198*399cfdd4SNicolas Le Bayon (((value & DT_RISAF_ENC_MASK) >> DT_RISAF_ENC_SHIFT) <<
199*399cfdd4SNicolas Le Bayon _RISAF_REG_CFGR_ENC_SHIFT) |
200*399cfdd4SNicolas Le Bayon (((value & DT_RISAF_PRIV_MASK) >> DT_RISAF_PRIV_SHIFT) <<
201*399cfdd4SNicolas Le Bayon _RISAF_REG_CFGR_PRIVC_SHIFT);
202*399cfdd4SNicolas Le Bayon
203*399cfdd4SNicolas Le Bayon cid_cfg = (((value & DT_RISAF_WRITE_MASK) >> DT_RISAF_WRITE_SHIFT) <<
204*399cfdd4SNicolas Le Bayon _RISAF_REG_CIDCFGR_WRENC_SHIFT) |
205*399cfdd4SNicolas Le Bayon (((value & DT_RISAF_READ_MASK) >> DT_RISAF_READ_SHIFT) <<
206*399cfdd4SNicolas Le Bayon _RISAF_REG_CIDCFGR_RDENC_SHIFT);
207*399cfdd4SNicolas Le Bayon
208*399cfdd4SNicolas Le Bayon start_addr = pdata->region[n].addr;
209*399cfdd4SNicolas Le Bayon end_addr = (start_addr - 1U) + pdata->region[n].len;
210*399cfdd4SNicolas Le Bayon
211*399cfdd4SNicolas Le Bayon if (risaf_configure_region(idx, id, cfg, cid_cfg,
212*399cfdd4SNicolas Le Bayon start_addr, end_addr) < 0) {
213*399cfdd4SNicolas Le Bayon ERROR("%s: failed to configure region %u of RISAF@%lx\n",
214*399cfdd4SNicolas Le Bayon __func__, id, pdata->base[idx]);
215*399cfdd4SNicolas Le Bayon panic();
216*399cfdd4SNicolas Le Bayon }
217*399cfdd4SNicolas Le Bayon }
218*399cfdd4SNicolas Le Bayon
219*399cfdd4SNicolas Le Bayon clk_disable(pdata->clock[idx]);
220*399cfdd4SNicolas Le Bayon }
221*399cfdd4SNicolas Le Bayon }
222*399cfdd4SNicolas Le Bayon
risaf_get_dt_node(struct dt_node_info * info,int offset)223*399cfdd4SNicolas Le Bayon static int risaf_get_dt_node(struct dt_node_info *info, int offset)
224*399cfdd4SNicolas Le Bayon {
225*399cfdd4SNicolas Le Bayon return dt_get_node(info, offset, DT_RISAF_COMPAT);
226*399cfdd4SNicolas Le Bayon }
227*399cfdd4SNicolas Le Bayon
risaf_get_instance_from_region(uintptr_t address,size_t length)228*399cfdd4SNicolas Le Bayon static int risaf_get_instance_from_region(uintptr_t address, size_t length)
229*399cfdd4SNicolas Le Bayon {
230*399cfdd4SNicolas Le Bayon struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
231*399cfdd4SNicolas Le Bayon unsigned int idx;
232*399cfdd4SNicolas Le Bayon int instance = -1;
233*399cfdd4SNicolas Le Bayon
234*399cfdd4SNicolas Le Bayon for (idx = 0U; idx < RISAF_MAX_INSTANCE; idx++) {
235*399cfdd4SNicolas Le Bayon if (pdata->base[idx] == 0U) {
236*399cfdd4SNicolas Le Bayon continue;
237*399cfdd4SNicolas Le Bayon }
238*399cfdd4SNicolas Le Bayon
239*399cfdd4SNicolas Le Bayon if (check_region_boundaries(idx, address, length) == 0) {
240*399cfdd4SNicolas Le Bayon instance = idx;
241*399cfdd4SNicolas Le Bayon }
242*399cfdd4SNicolas Le Bayon }
243*399cfdd4SNicolas Le Bayon
244*399cfdd4SNicolas Le Bayon return instance;
245*399cfdd4SNicolas Le Bayon }
246*399cfdd4SNicolas Le Bayon
247*399cfdd4SNicolas Le Bayon /*
248*399cfdd4SNicolas Le Bayon * Register region in platfoirm data structure if parameters are valid.
249*399cfdd4SNicolas Le Bayon * If instance is known, related entry parameter is filled, else it is equal to -1.
250*399cfdd4SNicolas Le Bayon */
risaf_register_region(void * fdt,int node,int instance)251*399cfdd4SNicolas Le Bayon static int risaf_register_region(void *fdt, int node, int instance)
252*399cfdd4SNicolas Le Bayon {
253*399cfdd4SNicolas Le Bayon struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
254*399cfdd4SNicolas Le Bayon const fdt32_t *cuint;
255*399cfdd4SNicolas Le Bayon int len = 0;
256*399cfdd4SNicolas Le Bayon int inst;
257*399cfdd4SNicolas Le Bayon uintptr_t address;
258*399cfdd4SNicolas Le Bayon size_t length;
259*399cfdd4SNicolas Le Bayon uint32_t protreg;
260*399cfdd4SNicolas Le Bayon
261*399cfdd4SNicolas Le Bayon /* Get address and length */
262*399cfdd4SNicolas Le Bayon cuint = fdt_getprop(fdt, node, "reg", &len);
263*399cfdd4SNicolas Le Bayon if ((cuint == NULL) || (len != RISAF_REGION_REG_SIZE)) {
264*399cfdd4SNicolas Le Bayon ERROR("RISAF: No or bad reg entry in DT\n");
265*399cfdd4SNicolas Le Bayon return -EINVAL;
266*399cfdd4SNicolas Le Bayon }
267*399cfdd4SNicolas Le Bayon
268*399cfdd4SNicolas Le Bayon address = (uintptr_t)fdt32_to_cpu(cuint[0]) << 32;
269*399cfdd4SNicolas Le Bayon address |= fdt32_to_cpu(cuint[1]);
270*399cfdd4SNicolas Le Bayon length = (size_t)fdt32_to_cpu(cuint[2]) << 32;
271*399cfdd4SNicolas Le Bayon length |= fdt32_to_cpu(cuint[3]);
272*399cfdd4SNicolas Le Bayon
273*399cfdd4SNicolas Le Bayon /* Get instance */
274*399cfdd4SNicolas Le Bayon inst = risaf_get_instance_from_region(address, length);
275*399cfdd4SNicolas Le Bayon if (inst < 0) {
276*399cfdd4SNicolas Le Bayon ERROR("RISAF: No instance found in DT\n");
277*399cfdd4SNicolas Le Bayon return -EINVAL;
278*399cfdd4SNicolas Le Bayon }
279*399cfdd4SNicolas Le Bayon
280*399cfdd4SNicolas Le Bayon if ((instance != -1) && (inst != instance)) {
281*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: Region not located in expected address space\n", instance + 1);
282*399cfdd4SNicolas Le Bayon return -EINVAL;
283*399cfdd4SNicolas Le Bayon }
284*399cfdd4SNicolas Le Bayon
285*399cfdd4SNicolas Le Bayon /* Get protreg configuration */
286*399cfdd4SNicolas Le Bayon cuint = fdt_getprop(fdt, node, "st,protreg", &len);
287*399cfdd4SNicolas Le Bayon if ((cuint == NULL) || (len != RISAF_REGION_PROTREG_SIZE)) {
288*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: No or bad st,protreg entry in DT\n", inst + 1);
289*399cfdd4SNicolas Le Bayon return -EINVAL;
290*399cfdd4SNicolas Le Bayon }
291*399cfdd4SNicolas Le Bayon
292*399cfdd4SNicolas Le Bayon protreg = fdt32_to_cpu(*cuint);
293*399cfdd4SNicolas Le Bayon
294*399cfdd4SNicolas Le Bayon /* Check if region max is reached for the current instance */
295*399cfdd4SNicolas Le Bayon region_per_instance[inst]++;
296*399cfdd4SNicolas Le Bayon if (region_per_instance[inst] > stm32_risaf_get_max_region(inst)) {
297*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: Too many entries in DT\n", inst + 1);
298*399cfdd4SNicolas Le Bayon return -EINVAL;
299*399cfdd4SNicolas Le Bayon }
300*399cfdd4SNicolas Le Bayon
301*399cfdd4SNicolas Le Bayon if (check_region_boundaries(inst, address, length) != 0) {
302*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: Region %d exceeds limits\n", inst + 1, pdata->nregions);
303*399cfdd4SNicolas Le Bayon return -EINVAL;
304*399cfdd4SNicolas Le Bayon }
305*399cfdd4SNicolas Le Bayon
306*399cfdd4SNicolas Le Bayon /* Register region configuration */
307*399cfdd4SNicolas Le Bayon pdata->region[pdata->nregions].instance = inst;
308*399cfdd4SNicolas Le Bayon pdata->region[pdata->nregions].cfg = protreg;
309*399cfdd4SNicolas Le Bayon pdata->region[pdata->nregions].addr = address;
310*399cfdd4SNicolas Le Bayon pdata->region[pdata->nregions].len = length;
311*399cfdd4SNicolas Le Bayon pdata->nregions++;
312*399cfdd4SNicolas Le Bayon
313*399cfdd4SNicolas Le Bayon if (check_region_overlap() != 0) {
314*399cfdd4SNicolas Le Bayon return -EINVAL;
315*399cfdd4SNicolas Le Bayon }
316*399cfdd4SNicolas Le Bayon
317*399cfdd4SNicolas Le Bayon return 0;
318*399cfdd4SNicolas Le Bayon }
319*399cfdd4SNicolas Le Bayon
320*399cfdd4SNicolas Le Bayon /*
321*399cfdd4SNicolas Le Bayon * From DT, retrieve base address, clock ID and all region information for each RISAF instance.
322*399cfdd4SNicolas Le Bayon * Check boundaries for each region and overlap for each instance.
323*399cfdd4SNicolas Le Bayon */
risaf_parse_fdt(void)324*399cfdd4SNicolas Le Bayon static int risaf_parse_fdt(void)
325*399cfdd4SNicolas Le Bayon {
326*399cfdd4SNicolas Le Bayon struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
327*399cfdd4SNicolas Le Bayon struct dt_node_info risaf_info;
328*399cfdd4SNicolas Le Bayon int node = -1;
329*399cfdd4SNicolas Le Bayon void *fdt;
330*399cfdd4SNicolas Le Bayon
331*399cfdd4SNicolas Le Bayon if (fdt_get_address(&fdt) == 0) {
332*399cfdd4SNicolas Le Bayon return -ENOENT;
333*399cfdd4SNicolas Le Bayon }
334*399cfdd4SNicolas Le Bayon
335*399cfdd4SNicolas Le Bayon for (node = risaf_get_dt_node(&risaf_info, node); node >= 0;
336*399cfdd4SNicolas Le Bayon node = risaf_get_dt_node(&risaf_info, node)) {
337*399cfdd4SNicolas Le Bayon int idx;
338*399cfdd4SNicolas Le Bayon int nregions;
339*399cfdd4SNicolas Le Bayon int inst_maxregions;
340*399cfdd4SNicolas Le Bayon int i;
341*399cfdd4SNicolas Le Bayon int len = 0;
342*399cfdd4SNicolas Le Bayon const fdt32_t *conf_list;
343*399cfdd4SNicolas Le Bayon uint32_t granularity;
344*399cfdd4SNicolas Le Bayon
345*399cfdd4SNicolas Le Bayon idx = stm32_risaf_get_instance(risaf_info.base);
346*399cfdd4SNicolas Le Bayon if ((idx < 0) || (risaf_info.clock < 0)) {
347*399cfdd4SNicolas Le Bayon continue;
348*399cfdd4SNicolas Le Bayon }
349*399cfdd4SNicolas Le Bayon
350*399cfdd4SNicolas Le Bayon pdata->base[idx] = risaf_info.base;
351*399cfdd4SNicolas Le Bayon pdata->clock[idx] = (unsigned long)risaf_info.clock;
352*399cfdd4SNicolas Le Bayon
353*399cfdd4SNicolas Le Bayon /* Get IP region granularity */
354*399cfdd4SNicolas Le Bayon if (clk_enable(pdata->clock[idx]) != 0) {
355*399cfdd4SNicolas Le Bayon ERROR("%s: clock enable failed.\n", __func__);
356*399cfdd4SNicolas Le Bayon panic();
357*399cfdd4SNicolas Le Bayon }
358*399cfdd4SNicolas Le Bayon
359*399cfdd4SNicolas Le Bayon granularity = mmio_read_32(pdata->base[idx] + _RISAF_HWCFGR);
360*399cfdd4SNicolas Le Bayon clk_disable(pdata->clock[idx]);
361*399cfdd4SNicolas Le Bayon granularity = BIT_32((granularity & _RISAF_HWCFGR_CFG3_MASK) >>
362*399cfdd4SNicolas Le Bayon _RISAF_HWCFGR_CFG3_SHIFT);
363*399cfdd4SNicolas Le Bayon pdata->granularity[idx] = granularity;
364*399cfdd4SNicolas Le Bayon
365*399cfdd4SNicolas Le Bayon conf_list = fdt_getprop(fdt, node, "memory-region", &len);
366*399cfdd4SNicolas Le Bayon if (conf_list == NULL) {
367*399cfdd4SNicolas Le Bayon len = 0;
368*399cfdd4SNicolas Le Bayon }
369*399cfdd4SNicolas Le Bayon
370*399cfdd4SNicolas Le Bayon nregions = (unsigned int)len / sizeof(uint32_t);
371*399cfdd4SNicolas Le Bayon
372*399cfdd4SNicolas Le Bayon inst_maxregions = stm32_risaf_get_max_region(idx);
373*399cfdd4SNicolas Le Bayon if (inst_maxregions <= 0) {
374*399cfdd4SNicolas Le Bayon continue;
375*399cfdd4SNicolas Le Bayon }
376*399cfdd4SNicolas Le Bayon
377*399cfdd4SNicolas Le Bayon if ((nregions > inst_maxregions) ||
378*399cfdd4SNicolas Le Bayon ((pdata->nregions + nregions) > RISAF_MAX_REGION)) {
379*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: Too many entries in DT\n", idx + 1);
380*399cfdd4SNicolas Le Bayon return -EINVAL;
381*399cfdd4SNicolas Le Bayon }
382*399cfdd4SNicolas Le Bayon
383*399cfdd4SNicolas Le Bayon for (i = 0; i < nregions; i++) {
384*399cfdd4SNicolas Le Bayon int pnode = 0;
385*399cfdd4SNicolas Le Bayon
386*399cfdd4SNicolas Le Bayon pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(conf_list[i]));
387*399cfdd4SNicolas Le Bayon if (pnode < 0) {
388*399cfdd4SNicolas Le Bayon continue;
389*399cfdd4SNicolas Le Bayon }
390*399cfdd4SNicolas Le Bayon
391*399cfdd4SNicolas Le Bayon if (risaf_register_region(fdt, pnode, idx) != 0) {
392*399cfdd4SNicolas Le Bayon ERROR("RISAF%d: Region %d error\n", idx + 1, pdata->nregions);
393*399cfdd4SNicolas Le Bayon return -EINVAL;
394*399cfdd4SNicolas Le Bayon }
395*399cfdd4SNicolas Le Bayon }
396*399cfdd4SNicolas Le Bayon }
397*399cfdd4SNicolas Le Bayon
398*399cfdd4SNicolas Le Bayon return 0;
399*399cfdd4SNicolas Le Bayon }
400*399cfdd4SNicolas Le Bayon
401*399cfdd4SNicolas Le Bayon static uintptr_t risaf_base[RISAF_MAX_INSTANCE];
402*399cfdd4SNicolas Le Bayon static unsigned long risaf_clock[RISAF_MAX_INSTANCE];
403*399cfdd4SNicolas Le Bayon static uint32_t risaf_granularity[RISAF_MAX_INSTANCE];
404*399cfdd4SNicolas Le Bayon static struct stm32mp2_risaf_region risaf_region[RISAF_MAX_REGION];
405*399cfdd4SNicolas Le Bayon
406*399cfdd4SNicolas Le Bayon /* Construct platform data structure */
risaf_get_platdata(struct stm32mp2_risaf_platdata * pdata)407*399cfdd4SNicolas Le Bayon static int risaf_get_platdata(struct stm32mp2_risaf_platdata *pdata)
408*399cfdd4SNicolas Le Bayon {
409*399cfdd4SNicolas Le Bayon pdata->base = risaf_base;
410*399cfdd4SNicolas Le Bayon pdata->clock = risaf_clock;
411*399cfdd4SNicolas Le Bayon pdata->granularity = risaf_granularity;
412*399cfdd4SNicolas Le Bayon pdata->region = risaf_region;
413*399cfdd4SNicolas Le Bayon
414*399cfdd4SNicolas Le Bayon return 0;
415*399cfdd4SNicolas Le Bayon }
416*399cfdd4SNicolas Le Bayon
417*399cfdd4SNicolas Le Bayon /*
418*399cfdd4SNicolas Le Bayon * @brief Write the encryption key for a given instance.
419*399cfdd4SNicolas Le Bayon * @param instance: RISAF instance ID.
420*399cfdd4SNicolas Le Bayon * key: Pointer to the encryption key buffer.
421*399cfdd4SNicolas Le Bayon * @retval 0 if OK, negative value else.
422*399cfdd4SNicolas Le Bayon */
stm32mp2_risaf_write_encryption_key(int instance,uint8_t * key)423*399cfdd4SNicolas Le Bayon int stm32mp2_risaf_write_encryption_key(int instance, uint8_t *key)
424*399cfdd4SNicolas Le Bayon {
425*399cfdd4SNicolas Le Bayon uint64_t timeout_ref;
426*399cfdd4SNicolas Le Bayon uint32_t i;
427*399cfdd4SNicolas Le Bayon uintptr_t base = stm32mp2_risaf.base[instance];
428*399cfdd4SNicolas Le Bayon
429*399cfdd4SNicolas Le Bayon if (base == 0U) {
430*399cfdd4SNicolas Le Bayon return -EINVAL;
431*399cfdd4SNicolas Le Bayon }
432*399cfdd4SNicolas Le Bayon
433*399cfdd4SNicolas Le Bayon if (key == NULL) {
434*399cfdd4SNicolas Le Bayon return -EINVAL;
435*399cfdd4SNicolas Le Bayon }
436*399cfdd4SNicolas Le Bayon
437*399cfdd4SNicolas Le Bayon for (i = 0U; i < RISAF_ENCRYPTION_KEY_SIZE_IN_BYTES; i += sizeof(uint32_t)) {
438*399cfdd4SNicolas Le Bayon uint32_t key_val = 0U;
439*399cfdd4SNicolas Le Bayon
440*399cfdd4SNicolas Le Bayon memcpy(&key_val, key + i, sizeof(uint32_t));
441*399cfdd4SNicolas Le Bayon
442*399cfdd4SNicolas Le Bayon mmio_write_32(base + _RISAF_KEYR + i, key_val);
443*399cfdd4SNicolas Le Bayon }
444*399cfdd4SNicolas Le Bayon
445*399cfdd4SNicolas Le Bayon timeout_ref = timeout_init_us(RISAF_TIMEOUT_1MS_IN_US);
446*399cfdd4SNicolas Le Bayon
447*399cfdd4SNicolas Le Bayon while (((mmio_read_32(base + _RISAF_SR) & _RISAF_SR_KEYVALID) != _RISAF_SR_KEYVALID) ||
448*399cfdd4SNicolas Le Bayon ((mmio_read_32(base + _RISAF_SR) & _RISAF_SR_KEYRDY) != _RISAF_SR_KEYRDY)) {
449*399cfdd4SNicolas Le Bayon if (timeout_elapsed(timeout_ref)) {
450*399cfdd4SNicolas Le Bayon return -EIO;
451*399cfdd4SNicolas Le Bayon }
452*399cfdd4SNicolas Le Bayon }
453*399cfdd4SNicolas Le Bayon
454*399cfdd4SNicolas Le Bayon return 0;
455*399cfdd4SNicolas Le Bayon }
456*399cfdd4SNicolas Le Bayon
457*399cfdd4SNicolas Le Bayon /*
458*399cfdd4SNicolas Le Bayon * @brief Lock the RISAF IP registers for a given instance.
459*399cfdd4SNicolas Le Bayon * @param instance: RISAF instance ID.
460*399cfdd4SNicolas Le Bayon * @retval 0 if OK, negative value else.
461*399cfdd4SNicolas Le Bayon */
stm32mp2_risaf_lock(int instance)462*399cfdd4SNicolas Le Bayon int stm32mp2_risaf_lock(int instance)
463*399cfdd4SNicolas Le Bayon {
464*399cfdd4SNicolas Le Bayon uintptr_t base = stm32mp2_risaf.base[instance];
465*399cfdd4SNicolas Le Bayon
466*399cfdd4SNicolas Le Bayon if (base == 0U) {
467*399cfdd4SNicolas Le Bayon return -EINVAL;
468*399cfdd4SNicolas Le Bayon }
469*399cfdd4SNicolas Le Bayon
470*399cfdd4SNicolas Le Bayon mmio_setbits_32(base + _RISAF_CR, _RISAF_CR_GLOCK);
471*399cfdd4SNicolas Le Bayon
472*399cfdd4SNicolas Le Bayon return 0;
473*399cfdd4SNicolas Le Bayon }
474*399cfdd4SNicolas Le Bayon
475*399cfdd4SNicolas Le Bayon /*
476*399cfdd4SNicolas Le Bayon * @brief Get the RISAF lock state for a given instance.
477*399cfdd4SNicolas Le Bayon * @param instance: RISAF instance ID.
478*399cfdd4SNicolas Le Bayon * state: lock state, true if locked, false else.
479*399cfdd4SNicolas Le Bayon * @retval 0 if OK, negative value else.
480*399cfdd4SNicolas Le Bayon */
stm32mp2_risaf_is_locked(int instance,bool * state)481*399cfdd4SNicolas Le Bayon int stm32mp2_risaf_is_locked(int instance, bool *state)
482*399cfdd4SNicolas Le Bayon {
483*399cfdd4SNicolas Le Bayon uintptr_t base = stm32mp2_risaf.base[instance];
484*399cfdd4SNicolas Le Bayon
485*399cfdd4SNicolas Le Bayon if (base == 0U) {
486*399cfdd4SNicolas Le Bayon return -EINVAL;
487*399cfdd4SNicolas Le Bayon }
488*399cfdd4SNicolas Le Bayon
489*399cfdd4SNicolas Le Bayon *state = (mmio_read_32(base + _RISAF_CR) & _RISAF_CR_GLOCK) == _RISAF_CR_GLOCK;
490*399cfdd4SNicolas Le Bayon
491*399cfdd4SNicolas Le Bayon return 0;
492*399cfdd4SNicolas Le Bayon }
493*399cfdd4SNicolas Le Bayon
stm32mp2_risaf_init(void)494*399cfdd4SNicolas Le Bayon int stm32mp2_risaf_init(void)
495*399cfdd4SNicolas Le Bayon {
496*399cfdd4SNicolas Le Bayon int err;
497*399cfdd4SNicolas Le Bayon
498*399cfdd4SNicolas Le Bayon err = risaf_get_platdata(&stm32mp2_risaf);
499*399cfdd4SNicolas Le Bayon if (err != 0) {
500*399cfdd4SNicolas Le Bayon return err;
501*399cfdd4SNicolas Le Bayon }
502*399cfdd4SNicolas Le Bayon
503*399cfdd4SNicolas Le Bayon err = risaf_parse_fdt();
504*399cfdd4SNicolas Le Bayon if (err != 0) {
505*399cfdd4SNicolas Le Bayon return err;
506*399cfdd4SNicolas Le Bayon }
507*399cfdd4SNicolas Le Bayon
508*399cfdd4SNicolas Le Bayon risaf_conf_protreg();
509*399cfdd4SNicolas Le Bayon
510*399cfdd4SNicolas Le Bayon return err;
511*399cfdd4SNicolas Le Bayon }
512*399cfdd4SNicolas Le Bayon
risaf_parse_fwconfig(uintptr_t config)513*399cfdd4SNicolas Le Bayon static int risaf_parse_fwconfig(uintptr_t config)
514*399cfdd4SNicolas Le Bayon {
515*399cfdd4SNicolas Le Bayon struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
516*399cfdd4SNicolas Le Bayon unsigned int i;
517*399cfdd4SNicolas Le Bayon int node = -1;
518*399cfdd4SNicolas Le Bayon int subnode;
519*399cfdd4SNicolas Le Bayon const void *fdt = (const void *)config;
520*399cfdd4SNicolas Le Bayon const char *compatible_str = "st,stm32mp2-mem-firewall";
521*399cfdd4SNicolas Le Bayon
522*399cfdd4SNicolas Le Bayon node = fdt_node_offset_by_compatible(fdt, -1, compatible_str);
523*399cfdd4SNicolas Le Bayon if (node < 0) {
524*399cfdd4SNicolas Le Bayon ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
525*399cfdd4SNicolas Le Bayon return node;
526*399cfdd4SNicolas Le Bayon }
527*399cfdd4SNicolas Le Bayon
528*399cfdd4SNicolas Le Bayon fdt_for_each_subnode(subnode, fdt, node) {
529*399cfdd4SNicolas Le Bayon if (risaf_register_region((void *)fdt, subnode, -1) != 0) {
530*399cfdd4SNicolas Le Bayon ERROR("RISAF: Region %d error\n", pdata->nregions);
531*399cfdd4SNicolas Le Bayon return -EINVAL;
532*399cfdd4SNicolas Le Bayon }
533*399cfdd4SNicolas Le Bayon }
534*399cfdd4SNicolas Le Bayon
535*399cfdd4SNicolas Le Bayon for (i = 0U; i < RISAF_MAX_INSTANCE; i++) {
536*399cfdd4SNicolas Le Bayon if ((region_per_instance[i] == 0) && (stm32_risaf_get_max_region(i) != 0)) {
537*399cfdd4SNicolas Le Bayon INFO("RISAF%u: No configuration in DT, use default\n", i + 1);
538*399cfdd4SNicolas Le Bayon }
539*399cfdd4SNicolas Le Bayon }
540*399cfdd4SNicolas Le Bayon
541*399cfdd4SNicolas Le Bayon return 0;
542*399cfdd4SNicolas Le Bayon }
543*399cfdd4SNicolas Le Bayon
fconf_populate_risaf(uintptr_t config)544*399cfdd4SNicolas Le Bayon static int fconf_populate_risaf(uintptr_t config)
545*399cfdd4SNicolas Le Bayon {
546*399cfdd4SNicolas Le Bayon int err;
547*399cfdd4SNicolas Le Bayon
548*399cfdd4SNicolas Le Bayon err = risaf_parse_fwconfig(config);
549*399cfdd4SNicolas Le Bayon if (err != 0) {
550*399cfdd4SNicolas Le Bayon return err;
551*399cfdd4SNicolas Le Bayon }
552*399cfdd4SNicolas Le Bayon
553*399cfdd4SNicolas Le Bayon risaf_conf_protreg();
554*399cfdd4SNicolas Le Bayon
555*399cfdd4SNicolas Le Bayon return err;
556*399cfdd4SNicolas Le Bayon }
557*399cfdd4SNicolas Le Bayon
558*399cfdd4SNicolas Le Bayon FCONF_REGISTER_POPULATOR(FW_CONFIG, risaf_config, fconf_populate_risaf);
559