1 /*
2 * Copyright (c) 2025-2026, 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) != 0U) {
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 #if STM32MP21
199 (((value & DT_RISAF_ENC_MASK) >> DT_RISAF_ENC_SHIFT) <<
200 _RISAF_REG_CFGR_ENC_SHIFT) |
201 #else /* !STM32MP21 */
202 (((value & DT_RISAF_ENC_MASK) >> (DT_RISAF_ENC_SHIFT + 1)) <<
203 _RISAF_REG_CFGR_ENC_SHIFT) |
204 #endif /* STM32MP21 */
205 (((value & DT_RISAF_PRIV_MASK) >> DT_RISAF_PRIV_SHIFT) <<
206 _RISAF_REG_CFGR_PRIVC_SHIFT);
207
208 cid_cfg = (((value & DT_RISAF_WRITE_MASK) >> DT_RISAF_WRITE_SHIFT) <<
209 _RISAF_REG_CIDCFGR_WRENC_SHIFT) |
210 (((value & DT_RISAF_READ_MASK) >> DT_RISAF_READ_SHIFT) <<
211 _RISAF_REG_CIDCFGR_RDENC_SHIFT);
212
213 start_addr = pdata->region[n].addr;
214 end_addr = (start_addr - 1U) + pdata->region[n].len;
215
216 if (risaf_configure_region(idx, id, cfg, cid_cfg,
217 start_addr, end_addr) < 0) {
218 ERROR("%s: failed to configure region %u of RISAF@%lx\n",
219 __func__, id, pdata->base[idx]);
220 panic();
221 }
222 }
223
224 clk_disable(pdata->clock[idx]);
225 }
226 }
227
risaf_get_dt_node(struct dt_node_info * info,int offset)228 static int risaf_get_dt_node(struct dt_node_info *info, int offset)
229 {
230 return dt_get_node(info, offset, DT_RISAF_COMPAT);
231 }
232
risaf_get_instance_from_region(uintptr_t address,size_t length)233 static int risaf_get_instance_from_region(uintptr_t address, size_t length)
234 {
235 struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
236 unsigned int idx;
237 int instance = -1;
238
239 for (idx = 0U; idx < RISAF_MAX_INSTANCE; idx++) {
240 if (pdata->base[idx] == 0U) {
241 continue;
242 }
243
244 if (check_region_boundaries(idx, address, length) == 0) {
245 instance = idx;
246 }
247 }
248
249 return instance;
250 }
251
252 /*
253 * Register region in platfoirm data structure if parameters are valid.
254 * If instance is known, related entry parameter is filled, else it is equal to -1.
255 */
risaf_register_region(void * fdt,int node,int instance)256 static int risaf_register_region(void *fdt, int node, int instance)
257 {
258 struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
259 const fdt32_t *cuint;
260 int len = 0;
261 int inst;
262 uintptr_t address;
263 size_t length;
264 uint32_t protreg;
265
266 /* Get address and length */
267 cuint = fdt_getprop(fdt, node, "reg", &len);
268 if ((cuint == NULL) || (len != RISAF_REGION_REG_SIZE)) {
269 ERROR("RISAF: No or bad reg entry in DT\n");
270 return -EINVAL;
271 }
272
273 address = (uintptr_t)fdt32_to_cpu(cuint[0]) << 32;
274 address |= fdt32_to_cpu(cuint[1]);
275 length = (size_t)fdt32_to_cpu(cuint[2]) << 32;
276 length |= fdt32_to_cpu(cuint[3]);
277
278 /* Get instance */
279 inst = risaf_get_instance_from_region(address, length);
280 if (inst < 0) {
281 ERROR("RISAF: No instance found in DT\n");
282 return -EINVAL;
283 }
284
285 if ((instance != -1) && (inst != instance)) {
286 ERROR("RISAF%d: Region not located in expected address space\n", instance + 1);
287 return -EINVAL;
288 }
289
290 /* Get protreg configuration */
291 cuint = fdt_getprop(fdt, node, "st,protreg", &len);
292 if ((cuint == NULL) || (len != RISAF_REGION_PROTREG_SIZE)) {
293 ERROR("RISAF%d: No or bad st,protreg entry in DT\n", inst + 1);
294 return -EINVAL;
295 }
296
297 protreg = fdt32_to_cpu(*cuint);
298
299 /* Check if region max is reached for the current instance */
300 region_per_instance[inst]++;
301 if (region_per_instance[inst] > stm32_risaf_get_max_region(inst)) {
302 ERROR("RISAF%d: Too many entries in DT\n", inst + 1);
303 return -EINVAL;
304 }
305
306 if (check_region_boundaries(inst, address, length) != 0) {
307 ERROR("RISAF%d: Region %d exceeds limits\n", inst + 1, pdata->nregions);
308 return -EINVAL;
309 }
310
311 /* Register region configuration */
312 pdata->region[pdata->nregions].instance = inst;
313 pdata->region[pdata->nregions].cfg = protreg;
314 pdata->region[pdata->nregions].addr = address;
315 pdata->region[pdata->nregions].len = length;
316 pdata->nregions++;
317
318 if (check_region_overlap() != 0) {
319 return -EINVAL;
320 }
321
322 return 0;
323 }
324
325 /*
326 * From DT, retrieve base address, clock ID and all region information for each RISAF instance.
327 * Check boundaries for each region and overlap for each instance.
328 */
risaf_parse_fdt(void)329 static int risaf_parse_fdt(void)
330 {
331 struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
332 struct dt_node_info risaf_info;
333 int node = -1;
334 void *fdt;
335
336 if (fdt_get_address(&fdt) == 0) {
337 return -ENOENT;
338 }
339
340 for (node = risaf_get_dt_node(&risaf_info, node); node >= 0;
341 node = risaf_get_dt_node(&risaf_info, node)) {
342 int idx;
343 int nregions;
344 int inst_maxregions;
345 int i;
346 int len = 0;
347 const fdt32_t *conf_list;
348 uint32_t granularity;
349
350 idx = stm32_risaf_get_instance(risaf_info.base);
351 if ((idx < 0) || (risaf_info.clock < 0)) {
352 continue;
353 }
354
355 pdata->base[idx] = risaf_info.base;
356 pdata->clock[idx] = (unsigned long)risaf_info.clock;
357
358 /* Get IP region granularity */
359 if (clk_enable(pdata->clock[idx]) != 0) {
360 ERROR("%s: clock enable failed.\n", __func__);
361 panic();
362 }
363
364 granularity = mmio_read_32(pdata->base[idx] + _RISAF_HWCFGR);
365 clk_disable(pdata->clock[idx]);
366 granularity = BIT_32((granularity & _RISAF_HWCFGR_CFG3_MASK) >>
367 _RISAF_HWCFGR_CFG3_SHIFT);
368 pdata->granularity[idx] = granularity;
369
370 conf_list = fdt_getprop(fdt, node, "memory-region", &len);
371 if (conf_list == NULL) {
372 len = 0;
373 }
374
375 nregions = (unsigned int)len / sizeof(uint32_t);
376
377 inst_maxregions = stm32_risaf_get_max_region(idx);
378 if (inst_maxregions <= 0) {
379 continue;
380 }
381
382 if ((nregions > inst_maxregions) ||
383 ((pdata->nregions + nregions) > RISAF_MAX_REGION)) {
384 ERROR("RISAF%d: Too many entries in DT\n", idx + 1);
385 return -EINVAL;
386 }
387
388 for (i = 0; i < nregions; i++) {
389 int pnode = 0;
390
391 pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(conf_list[i]));
392 if (pnode < 0) {
393 continue;
394 }
395
396 if (risaf_register_region(fdt, pnode, idx) != 0) {
397 ERROR("RISAF%d: Region %d error\n", idx + 1, pdata->nregions);
398 return -EINVAL;
399 }
400 }
401 }
402
403 return 0;
404 }
405
406 static uintptr_t risaf_base[RISAF_MAX_INSTANCE];
407 static unsigned long risaf_clock[RISAF_MAX_INSTANCE];
408 static uint32_t risaf_granularity[RISAF_MAX_INSTANCE];
409 static struct stm32mp2_risaf_region risaf_region[RISAF_MAX_REGION];
410
411 /* Construct platform data structure */
risaf_get_platdata(struct stm32mp2_risaf_platdata * pdata)412 static int risaf_get_platdata(struct stm32mp2_risaf_platdata *pdata)
413 {
414 pdata->base = risaf_base;
415 pdata->clock = risaf_clock;
416 pdata->granularity = risaf_granularity;
417 pdata->region = risaf_region;
418
419 return 0;
420 }
421
422 /*
423 * @brief Write the encryption key for a given instance.
424 * @param instance: RISAF instance ID.
425 * key: Pointer to the encryption key buffer.
426 * @retval 0 if OK, negative value else.
427 */
stm32mp2_risaf_write_encryption_key(int instance,uint8_t * key)428 int stm32mp2_risaf_write_encryption_key(int instance, uint8_t *key)
429 {
430 uint64_t timeout_ref;
431 uint32_t i;
432 uintptr_t base = stm32mp2_risaf.base[instance];
433
434 assert(key != NULL);
435
436 if (base == 0U) {
437 return -EINVAL;
438 }
439
440 for (i = 0U; i < RISAF_ENCRYPTION_KEY_SIZE_IN_BYTES; i += sizeof(uint32_t)) {
441 uint32_t key_val = 0U;
442
443 memcpy(&key_val, key + i, sizeof(uint32_t));
444
445 mmio_write_32(base + _RISAF_KEYR + i, key_val);
446 }
447
448 timeout_ref = timeout_init_us(RISAF_TIMEOUT_1MS_IN_US);
449
450 while (((mmio_read_32(base + _RISAF_SR) & _RISAF_SR_KEYVALID) != _RISAF_SR_KEYVALID) ||
451 ((mmio_read_32(base + _RISAF_SR) & _RISAF_SR_KEYRDY) != _RISAF_SR_KEYRDY)) {
452 if (timeout_elapsed(timeout_ref)) {
453 return -EIO;
454 }
455 }
456
457 return 0;
458 }
459
460 #if STM32MP21
risaf_get_mce_key_size(int instance,uint32_t * size)461 static int risaf_get_mce_key_size(int instance, uint32_t *size)
462 {
463 struct dt_node_info risaf_info;
464 int node = -1;
465 void *fdt;
466
467 if (fdt_get_address(&fdt) == 0) {
468 return -ENOENT;
469 }
470
471 for (node = risaf_get_dt_node(&risaf_info, node); node >= 0;
472 node = risaf_get_dt_node(&risaf_info, node)) {
473 int idx;
474 const fdt32_t *cuint = NULL;
475
476 idx = stm32_risaf_get_instance(risaf_info.base);
477 if (idx != instance) {
478 continue;
479 }
480
481 cuint = fdt_getprop(fdt, node, "st,mce-keysize-bits", NULL);
482 if (cuint == NULL) {
483 /* Property not set, affect default value */
484 *size = RISAF_MCE_KEY_128BITS_SIZE_IN_BYTES;
485 } else {
486 *size = (uint32_t)fdt32_to_cpu(*cuint) / 8;
487 }
488
489 return 0;
490 }
491
492 return -ENODEV;
493 }
494
495 /*
496 * @brief Write the MCE key for a given instance.
497 * @param instance: RISAF instance ID.
498 * key: Pointer to the MCE key buffer.
499 * size: MCE key size in bytes.
500 * @retval 0 if OK, negative value else.
501 */
stm32mp2_risaf_write_mce_key(int instance,uint8_t * key)502 int stm32mp2_risaf_write_mce_key(int instance, uint8_t *key)
503 {
504 uint64_t timeout_ref;
505 uint32_t i;
506 uint32_t size;
507 uintptr_t base = stm32mp2_risaf.base[instance];
508
509 assert(key != NULL);
510
511 if (base == 0U) {
512 return -EINVAL;
513 }
514
515 if (risaf_get_mce_key_size(instance, &size) != 0) {
516 return -EINVAL;
517 }
518
519 if (size == RISAF_MCE_KEY_128BITS_SIZE_IN_BYTES) {
520 mmio_write_32(base + _RISAF_XCR,
521 _RISAF_XCR_CIPHERSEL_AES128 << _RISAF_XCR_CIPHERSEL_SHIFT);
522 } else if (size == RISAF_MCE_KEY_256BITS_SIZE_IN_BYTES) {
523 mmio_write_32(base + _RISAF_XCR,
524 _RISAF_XCR_CIPHERSEL_AES256 << _RISAF_XCR_CIPHERSEL_SHIFT);
525 } else {
526 return -EINVAL;
527 }
528
529 for (i = 0U; i < size; i += sizeof(uint32_t)) {
530 uint32_t key_val = 0U;
531
532 memcpy(&key_val, key + i, sizeof(uint32_t));
533
534 mmio_write_32(base + _RISAF_MKEYR + i, key_val);
535 }
536
537 timeout_ref = timeout_init_us(RISAF_TIMEOUT_1MS_IN_US);
538
539 while (((mmio_read_32(base + _RISAF_XSR) & _RISAF_XSR_MKVALID) != _RISAF_XSR_MKVALID)) {
540 if (timeout_elapsed(timeout_ref)) {
541 return -EIO;
542 }
543 }
544
545 return 0;
546 }
547 #endif /* STM32MP21 */
548
549 /*
550 * @brief Lock the RISAF IP registers for a given instance.
551 * @param instance: RISAF instance ID.
552 * @retval 0 if OK, negative value else.
553 */
stm32mp2_risaf_lock(int instance)554 int stm32mp2_risaf_lock(int instance)
555 {
556 uintptr_t base = stm32mp2_risaf.base[instance];
557
558 if (base == 0U) {
559 return -EINVAL;
560 }
561
562 mmio_setbits_32(base + _RISAF_CR, _RISAF_CR_GLOCK);
563
564 return 0;
565 }
566
567 /*
568 * @brief Get the RISAF lock state for a given instance.
569 * @param instance: RISAF instance ID.
570 * state: lock state, true if locked, false else.
571 * @retval 0 if OK, negative value else.
572 */
stm32mp2_risaf_is_locked(int instance,bool * state)573 int stm32mp2_risaf_is_locked(int instance, bool *state)
574 {
575 uintptr_t base = stm32mp2_risaf.base[instance];
576
577 if (base == 0U) {
578 return -EINVAL;
579 }
580
581 *state = (mmio_read_32(base + _RISAF_CR) & _RISAF_CR_GLOCK) == _RISAF_CR_GLOCK;
582
583 return 0;
584 }
585
stm32mp2_risaf_init(void)586 int stm32mp2_risaf_init(void)
587 {
588 int err;
589
590 err = risaf_get_platdata(&stm32mp2_risaf);
591 if (err != 0) {
592 return err;
593 }
594
595 err = risaf_parse_fdt();
596 if (err != 0) {
597 return err;
598 }
599
600 risaf_conf_protreg();
601
602 return err;
603 }
604
risaf_parse_fwconfig(uintptr_t config)605 static int risaf_parse_fwconfig(uintptr_t config)
606 {
607 struct stm32mp2_risaf_platdata *pdata = &stm32mp2_risaf;
608 unsigned int i;
609 int node;
610 int subnode;
611 const void *fdt = (const void *)config;
612 const char *compatible_str = "st,stm32mp2-mem-firewall";
613
614 node = fdt_node_offset_by_compatible(fdt, -1, compatible_str);
615 if (node < 0) {
616 ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
617 return node;
618 }
619
620 fdt_for_each_subnode(subnode, fdt, node) {
621 if (risaf_register_region((void *)fdt, subnode, -1) != 0) {
622 ERROR("RISAF: Region %d error\n", pdata->nregions);
623 return -EINVAL;
624 }
625 }
626
627 for (i = 0U; i < RISAF_MAX_INSTANCE; i++) {
628 if ((region_per_instance[i] == 0) && (stm32_risaf_get_max_region(i) != 0)) {
629 INFO("RISAF%u: No configuration in DT, use default\n", i + 1);
630 }
631 }
632
633 return 0;
634 }
635
fconf_populate_risaf(uintptr_t config)636 static int fconf_populate_risaf(uintptr_t config)
637 {
638 int err;
639
640 err = risaf_parse_fwconfig(config);
641 if (err != 0) {
642 return err;
643 }
644
645 risaf_conf_protreg();
646
647 return err;
648 }
649
650 FCONF_REGISTER_POPULATOR(FW_CONFIG, risaf_config, fconf_populate_risaf);
651