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