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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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