// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* RISAF general registers (base relative) */ #define _RISAF_CR U(0x00) #define _RISAF_SR U(0x04) #define _RISAF_IASR U(0x08) #define _RISAF_IACR U(0xC) #define _RISAF_IAESR0 U(0x20) #define _RISAF_IADDR0 U(0x24) #define _RISAF_IAESR1 U(0x28) #define _RISAF_IADDR1 U(0x2C) #define _RISAF_KEYR U(0x30) #define _RISAF_HWCFGR U(0xFF0) #define _RISAF_VERR U(0xFF4) #define _RISAF_IPIDR U(0xFF8) #define _RISAF_SIDR U(0xFFC) /* RISAF general register field description */ /* _RISAF_CR register fields */ #define _RISAF_CR_GLOCK BIT(0) /* _RISAF_SR register fields */ #define _RISAF_SR_KEYVALID BIT(0) #define _RISAF_SR_KEYRDY BIT(1) #define _RISAF_SR_ENCDIS BIT(2) /* _RISAF_IACR register fields */ #define _RISAF_IACR_CAEF BIT(0) #define _RISAF_IACR_IAEF0 BIT(1) #define _RISAF_IACR_IAEF1 BIT(2) /* _RISAF_HWCFGR register fields */ #define _RISAF_HWCFGR_CFG1_SHIFT U(0) #define _RISAF_HWCFGR_CFG1_MASK GENMASK_32(7, 0) #define _RISAF_HWCFGR_CFG2_SHIFT U(8) #define _RISAF_HWCFGR_CFG2_MASK GENMASK_32(15, 8) #define _RISAF_HWCFGR_CFG3_SHIFT U(16) #define _RISAF_HWCFGR_CFG3_MASK GENMASK_32(23, 16) #define _RISAF_HWCFGR_CFG4_SHIFT U(24) #define _RISAF_HWCFGR_CFG4_MASK GENMASK_32(31, 24) /* _RISAF_VERR register fields */ #define _RISAF_VERR_MINREV_SHIFT U(0) #define _RISAF_VERR_MINREV_MASK GENMASK_32(3, 0) #define _RISAF_VERR_MAJREV_SHIFT U(4) #define _RISAF_VERR_MAJREV_MASK GENMASK_32(7, 4) /* RISAF region registers (base relative) */ #define _RISAF_REG_BASE U(0x40) #define _RISAF_REG_SIZE U(0x40) #define _RISAF_REG(n) (_RISAF_REG_BASE + \ (((n) - 1) * _RISAF_REG_SIZE)) #define _RISAF_REG_CFGR_OFFSET U(0x0) #define _RISAF_REG_CFGR(n) (_RISAF_REG(n) + _RISAF_REG_CFGR_OFFSET) #define _RISAF_REG_STARTR_OFFSET U(0x4) #define _RISAF_REG_STARTR(n) (_RISAF_REG(n) + \ _RISAF_REG_STARTR_OFFSET) #define _RISAF_REG_ENDR_OFFSET U(0x8) #define _RISAF_REG_ENDR(n) (_RISAF_REG(n) + _RISAF_REG_ENDR_OFFSET) #define _RISAF_REG_CIDCFGR_OFFSET U(0xC) #define _RISAF_REG_CIDCFGR(n) (_RISAF_REG(n) + \ _RISAF_REG_CIDCFGR_OFFSET) /* RISAF region register field description */ /* _RISAF_REG_CFGR(n) register fields */ #define _RISAF_REG_CFGR_BREN_SHIFT U(0) #define _RISAF_REG_CFGR_BREN BIT(_RISAF_REG_CFGR_BREN_SHIFT) #define _RISAF_REG_CFGR_SEC_SHIFT U(8) #define _RISAF_REG_CFGR_SEC BIT(_RISAF_REG_CFGR_SEC_SHIFT) #define _RISAF_REG_CFGR_ENC_SHIFT U(15) #define _RISAF_REG_CFGR_ENC BIT(_RISAF_REG_CFGR_ENC_SHIFT) #define _RISAF_REG_CFGR_PRIVC_SHIFT U(16) #define _RISAF_REG_CFGR_PRIVC_MASK GENMASK_32(23, 16) #define _RISAF_REG_CFGR_ALL_MASK (_RISAF_REG_CFGR_BREN | \ _RISAF_REG_CFGR_SEC | \ _RISAF_REG_CFGR_ENC | \ _RISAF_REG_CFGR_PRIVC_MASK) /* _RISAF_REG_CIDCFGR(n) register fields */ #define _RISAF_REG_CIDCFGR_RDENC_SHIFT U(0) #define _RISAF_REG_CIDCFGR_RDENC_MASK GENMASK_32(7, 0) #define _RISAF_REG_CIDCFGR_WRENC_SHIFT U(16) #define _RISAF_REG_CIDCFGR_WRENC_MASK GENMASK_32(23, 16) #define _RISAF_REG_CIDCFGR_ALL_MASK (_RISAF_REG_CIDCFGR_RDENC_MASK | \ _RISAF_REG_CIDCFGR_WRENC_MASK) #define _RISAF_REG_READ_OK(reg, cid) \ ((reg) & BIT((cid) + _RISAF_REG_CIDCFGR_RDENC_SHIFT)) #define _RISAF_REG_WRITE_OK(reg, cid) \ ((reg) & BIT((cid) + _RISAF_REG_CIDCFGR_WRENC_SHIFT)) #define _RISAF_GET_REGION_ID(cfg) ((cfg) & DT_RISAF_REG_ID_MASK) #define _RISAF_NB_CID_SUPPORTED U(8) /** * struct stm32_risaf_region - RISAF memory region * * @addr: Region base address. * @len: Length of the memory region. * @cfg: Region configuration. */ struct stm32_risaf_region { paddr_t addr; size_t len; uint32_t cfg; }; /** * struct stm32_risaf_pdata - RISAF platform data * * @base: Base address of the RISAF instance. * @clock: Clock of the RISAF. * @regions: Number of memory regions, defined by the device tree configuration. * @risaf_name: Name of the RISAF instance * @nregions: Number of memory regions found in the device tree. * @conf_lock: State whether the RISAF configuration is locked. * @mem_base: Base address of the memory range covered by the RISAF instance. * @mem_size: Size of the memory range covered by the RISAF instance. * @enc_supported: If true, the RISAF instance supports encryption of the memory * regions. */ struct stm32_risaf_pdata { struct io_pa_va base; struct clk *clock; struct stm32_risaf_region *regions; char risaf_name[20]; unsigned int nregions; unsigned int conf_lock; paddr_t mem_base; size_t mem_size; bool enc_supported; }; /** * struct stm32_risaf_ddata - RISAF driver data * * @mask_regions: Number of address bits to match when determining access to a * base region or subregion (WIDTH). * @max_base_regions: Number of subdivision of the memory range (A.K.A memory * regions) supported by the RISAF instance. * @granularity: Length of the smallest possible region size. */ struct stm32_risaf_ddata { uint32_t mask_regions; uint32_t max_base_regions; uint32_t granularity; }; struct stm32_risaf_instance { struct stm32_risaf_pdata pdata; struct stm32_risaf_ddata *ddata; SLIST_ENTRY(stm32_risaf_instance) link; }; struct stm32_risaf_version { uint32_t major; uint32_t minor; uint32_t ip_id; uint32_t size_id; }; /** * struct stm32_risaf_compat_data - Describes RISAF associated data * for compatible list. * * @supported_encryption: identify RISAF encryption capabilities. */ struct stm32_risaf_compat_data { bool supported_encryption; }; static bool is_tdcid; static const struct stm32_risaf_compat_data stm32_risaf_compat = { .supported_encryption = false, }; static const struct stm32_risaf_compat_data stm32_risaf_enc_compat = { .supported_encryption = true, }; static SLIST_HEAD(, stm32_risaf_instance) risaf_list = SLIST_HEAD_INITIALIZER(risaf_list); static vaddr_t risaf_base(struct stm32_risaf_instance *risaf) { return io_pa_or_va_secure(&risaf->pdata.base, 1); } static uint32_t stm32_risaf_get_region_config(uint32_t cfg) { return SHIFT_U32((cfg & DT_RISAF_EN_MASK) >> DT_RISAF_EN_SHIFT, _RISAF_REG_CFGR_BREN_SHIFT) | SHIFT_U32((cfg & DT_RISAF_SEC_MASK) >> DT_RISAF_SEC_SHIFT, _RISAF_REG_CFGR_SEC_SHIFT) | SHIFT_U32((cfg & DT_RISAF_ENC_MASK) >> (DT_RISAF_ENC_SHIFT + 1), _RISAF_REG_CFGR_ENC_SHIFT) | SHIFT_U32((cfg & DT_RISAF_PRIV_MASK) >> DT_RISAF_PRIV_SHIFT, _RISAF_REG_CFGR_PRIVC_SHIFT); } static uint32_t stm32_risaf_get_region_cid_config(uint32_t cfg) { return SHIFT_U32((cfg & DT_RISAF_WRITE_MASK) >> DT_RISAF_WRITE_SHIFT, _RISAF_REG_CIDCFGR_WRENC_SHIFT) | SHIFT_U32((cfg & DT_RISAF_READ_MASK) >> DT_RISAF_READ_SHIFT, _RISAF_REG_CIDCFGR_RDENC_SHIFT); } void stm32_risaf_clear_illegal_access_flags(void) { struct stm32_risaf_instance *risaf = NULL; SLIST_FOREACH(risaf, &risaf_list, link) { vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1); if (!io_read32(base + _RISAF_IASR)) continue; io_write32(base + _RISAF_IACR, _RISAF_IACR_CAEF | _RISAF_IACR_IAEF0 | _RISAF_IACR_IAEF1); } } void stm32_risaf_print_erroneous_data(void) { struct stm32_risaf_instance *risaf = NULL; if (!IS_ENABLED(CFG_TEE_CORE_DEBUG)) return; SLIST_FOREACH(risaf, &risaf_list, link) { vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1); /* Check if faulty address on this RISAF */ if (!io_read32(base + _RISAF_IASR)) continue; IMSG("\n\nDUMPING DATA FOR %s\n\n", risaf->pdata.risaf_name); IMSG("====================================================="); IMSG("Status register (IAESR0): %#"PRIx32, io_read32(base + _RISAF_IAESR0)); /* Reserved if dual port feature not available */ if (io_read32(base + _RISAF_IAESR1)) IMSG("Status register Dual Port (IAESR1) %#"PRIx32, io_read32(base + _RISAF_IAESR1)); IMSG("-----------------------------------------------------"); if (virt_to_phys((void *)base) == RISAF4_BASE) { IMSG("Faulty address (IADDR0): %#"PRIxPA, risaf->pdata.mem_base + io_read32(base + _RISAF_IADDR0)); /* Reserved if dual port feature not available */ if (io_read32(base + _RISAF_IADDR1)) IMSG("Dual port faulty address (IADDR1): %#"PRIxPA, risaf->pdata.mem_base + io_read32(base + _RISAF_IADDR1)); } else { IMSG("Faulty address (IADDR0): %#"PRIx32, io_read32(base + _RISAF_IADDR0)); /* Reserved if dual port feature not available */ if (io_read32(base + _RISAF_IADDR1)) IMSG("Dual port faulty address (IADDR1): %#"PRIx32, io_read32(base + _RISAF_IADDR1)); } IMSG("=====================================================\n"); }; } static __maybe_unused bool risaf_is_hw_encryption_enabled(struct stm32_risaf_instance *risaf) { return (io_read32(risaf_base(risaf) + _RISAF_SR) & _RISAF_SR_ENCDIS) != _RISAF_SR_ENCDIS; } static TEE_Result risaf_check_region_boundaries(struct stm32_risaf_instance *risaf, struct stm32_risaf_region *region) { if (!core_is_buffer_inside(region->addr, region->len, risaf->pdata.mem_base, risaf->pdata.mem_size)) { EMSG("Region %#"PRIxPA"..%#"PRIxPA" outside RISAF area %#"PRIxPA"...%#"PRIxPA, region->addr, region->addr + region->len - 1, risaf->pdata.mem_base, risaf->pdata.mem_base + risaf->pdata.mem_size - 1); return TEE_ERROR_BAD_PARAMETERS; } if (!risaf->ddata->granularity || (region->addr % risaf->ddata->granularity) || (region->len % risaf->ddata->granularity)) { EMSG("RISAF %#"PRIxPA": start/end address granularity not respected", risaf->pdata.base.pa); return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result risaf_check_overlap(struct stm32_risaf_instance *risaf __maybe_unused, struct stm32_risaf_region *region, unsigned int index) { unsigned int i = 0; for (i = 0; i < index; i++) { /* Skip region if there's no configuration */ if (!region[i].cfg) continue; if (core_is_buffer_intersect(region[index].addr, region[index].len, region[i].addr, region[i].len)) { EMSG("RISAF %#"PRIxPA": Regions %u and %u overlap", risaf->pdata.base.pa, index, i); return TEE_ERROR_GENERIC; } } return TEE_SUCCESS; } static TEE_Result risaf_configure_region(struct stm32_risaf_instance *risaf, uint32_t region_id, uint32_t cfg, uint32_t cid_cfg, paddr_t saddr, paddr_t eaddr) { uint32_t mask = risaf->ddata->mask_regions; vaddr_t base = risaf_base(risaf); if (cfg & _RISAF_REG_CFGR_ENC) { if (!risaf->pdata.enc_supported) { EMSG("RISAF %#"PRIxPA": encryption feature error", risaf->pdata.base.pa); return TEE_ERROR_GENERIC; } if ((cfg & _RISAF_REG_CFGR_SEC) != _RISAF_REG_CFGR_SEC) { EMSG("RISAF %#"PRIxPA": encryption on non-secure area", risaf->pdata.base.pa); return TEE_ERROR_GENERIC; } } io_clrbits32(base + _RISAF_REG_CFGR(region_id), _RISAF_REG_CFGR_BREN); io_clrsetbits32(base + _RISAF_REG_STARTR(region_id), mask, (saddr - risaf->pdata.mem_base) & mask); io_clrsetbits32(base + _RISAF_REG_ENDR(region_id), mask, (eaddr - risaf->pdata.mem_base) & mask); io_clrsetbits32(base + _RISAF_REG_CIDCFGR(region_id), _RISAF_REG_CIDCFGR_ALL_MASK, cid_cfg & _RISAF_REG_CIDCFGR_ALL_MASK); io_clrsetbits32(base + _RISAF_REG_CFGR(region_id), _RISAF_REG_CFGR_ALL_MASK, cfg & _RISAF_REG_CFGR_ALL_MASK); DMSG("RISAF %#"PRIxPA": region %02"PRIu32" - start %#"PRIxPA "- end %#"PRIxPA" - cfg %#08"PRIx32" - cidcfg %#08"PRIx32, risaf->pdata.base.pa, region_id, risaf->pdata.mem_base + io_read32(base + _RISAF_REG_STARTR(region_id)), risaf->pdata.mem_base + io_read32(base + _RISAF_REG_ENDR(region_id)), io_read32(base + _RISAF_REG_CFGR(region_id)), io_read32(base + _RISAF_REG_CIDCFGR(region_id))); return TEE_SUCCESS; } static void risaf_print_version(struct stm32_risaf_instance *risaf) { vaddr_t base = risaf_base(risaf); struct stm32_risaf_version __maybe_unused version = { .major = (io_read32(base + _RISAF_VERR) & _RISAF_VERR_MAJREV_MASK) >> _RISAF_VERR_MAJREV_SHIFT, .minor = (io_read32(base + _RISAF_VERR) & _RISAF_VERR_MINREV_MASK) >> _RISAF_VERR_MINREV_SHIFT, .ip_id = io_read32(base + _RISAF_IPIDR), .size_id = io_read32(base + _RISAF_SIDR) }; DMSG("RISAF %#"PRIxPA" version %"PRIu32".%"PRIu32", ip%#"PRIx32" size%#"PRIx32, risaf->pdata.base.pa, version.major, version.minor, version.ip_id, version.size_id); } static __maybe_unused void stm32_risaf_lock(struct stm32_risaf_instance *risaf) { assert(risaf); io_setbits32(risaf_base(risaf) + _RISAF_CR, _RISAF_CR_GLOCK); } static __maybe_unused void stm32_risaf_is_locked(struct stm32_risaf_instance *risaf, bool *state) { assert(risaf); *state = (io_read32(risaf_base(risaf) + _RISAF_CR) & _RISAF_CR_GLOCK) == _RISAF_CR_GLOCK; } static TEE_Result stm32_risaf_init_ddata(struct stm32_risaf_instance *risaf) { vaddr_t base = risaf_base(risaf); uint32_t granularity = 0; uint32_t mask_lsb = 0; uint32_t mask_msb = 0; uint32_t hwcfgr = 0; risaf->ddata = calloc(1, sizeof(*risaf->ddata)); if (!risaf->ddata) return TEE_ERROR_OUT_OF_MEMORY; /* Get address mask depending on RISAF instance HW configuration */ hwcfgr = io_read32(base + _RISAF_HWCFGR); mask_lsb = (hwcfgr & _RISAF_HWCFGR_CFG3_MASK) >> _RISAF_HWCFGR_CFG3_SHIFT; mask_msb = mask_lsb + ((hwcfgr & _RISAF_HWCFGR_CFG4_MASK) >> _RISAF_HWCFGR_CFG4_SHIFT) - 1U; risaf->ddata->mask_regions = GENMASK_32(mask_msb, mask_lsb); risaf->ddata->max_base_regions = (hwcfgr & _RISAF_HWCFGR_CFG1_MASK) >> _RISAF_HWCFGR_CFG1_SHIFT; /* Get IP region granularity */ granularity = io_read32(risaf_base(risaf) + _RISAF_HWCFGR); granularity = BIT((granularity & _RISAF_HWCFGR_CFG3_MASK) >> _RISAF_HWCFGR_CFG3_SHIFT); risaf->ddata->granularity = granularity; return TEE_SUCCESS; } static TEE_Result stm32_risaf_pm_resume(struct stm32_risaf_instance *risaf) { struct stm32_risaf_region *regions = risaf->pdata.regions; size_t i = 0; for (i = 0; i < risaf->pdata.nregions; i++) { uint32_t id = _RISAF_GET_REGION_ID(regions[i].cfg); paddr_t start_addr = 0; paddr_t end_addr = 0; uint32_t cid_cfg = 0; uint32_t cfg = 0; if (!id) continue; cfg = stm32_risaf_get_region_config(regions[i].cfg); cid_cfg = stm32_risaf_get_region_cid_config(regions[i].cfg); start_addr = regions[i].addr; end_addr = start_addr + regions[i].len - 1U; if (risaf_configure_region(risaf, id, cfg, cid_cfg, start_addr, end_addr)) panic(); } return TEE_SUCCESS; } static TEE_Result stm32_risaf_pm_suspend(struct stm32_risaf_instance *risaf) { vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1); size_t i = 0; for (i = 0; i < risaf->pdata.nregions; i++) { uint32_t id = _RISAF_GET_REGION_ID(risaf->pdata.regions[i].cfg); struct stm32_risaf_region *region = risaf->pdata.regions + i; paddr_t start_addr = 0; paddr_t end_addr = 0; uint32_t cid_cfg = 0; uint32_t priv = 0; uint32_t rden = 0; uint32_t wren = 0; uint32_t cfg = 0; uint32_t enc = 0; uint32_t sec = 0; uint32_t en = 0; /* Skip region not defined in DT, not configured in probe */ if (!id) continue; cfg = io_read32(base + _RISAF_REG_CFGR(id)); en = cfg & _RISAF_REG_CFGR_BREN; sec = (cfg & _RISAF_REG_CFGR_SEC) >> _RISAF_REG_CFGR_SEC_SHIFT; enc = (cfg & _RISAF_REG_CFGR_ENC) >> _RISAF_REG_CFGR_ENC_SHIFT; priv = (cfg & _RISAF_REG_CFGR_PRIVC_MASK) >> _RISAF_REG_CFGR_PRIVC_SHIFT; cid_cfg = io_read32(base + _RISAF_REG_CIDCFGR(id)); rden = cid_cfg & _RISAF_REG_CIDCFGR_RDENC_MASK; wren = (cid_cfg & _RISAF_REG_CIDCFGR_WRENC_MASK) >> _RISAF_REG_CIDCFGR_WRENC_SHIFT; region->cfg = id | SHIFT_U32(en, DT_RISAF_EN_SHIFT) | SHIFT_U32(sec, DT_RISAF_SEC_SHIFT) | SHIFT_U32(enc, DT_RISAF_ENC_SHIFT + 1) | SHIFT_U32(priv, DT_RISAF_PRIV_SHIFT) | SHIFT_U32(rden, DT_RISAF_READ_SHIFT) | SHIFT_U32(wren, DT_RISAF_WRITE_SHIFT); start_addr = io_read32(base + _RISAF_REG_STARTR(id)); end_addr = io_read32(base + _RISAF_REG_ENDR(id)); region->addr = start_addr + risaf->pdata.mem_base; region->len = end_addr - start_addr + 1; } return TEE_SUCCESS; } static TEE_Result stm32_risaf_pm(enum pm_op op, unsigned int pm_hint, const struct pm_callback_handle *pm_handle) { struct stm32_risaf_instance *risaf = pm_handle->handle; TEE_Result res = TEE_ERROR_GENERIC; assert(risaf); if (!PM_HINT_IS_STATE(pm_hint, CONTEXT)) return TEE_SUCCESS; if (op == PM_OP_RESUME) res = stm32_risaf_pm_resume(risaf); else res = stm32_risaf_pm_suspend(risaf); return res; } static TEE_Result stm32_risaf_probe(const void *fdt, int node, const void *compat_data) { const struct stm32_risaf_compat_data *compat = compat_data; struct stm32_risaf_instance *risaf = NULL; struct stm32_risaf_region *regions = NULL; TEE_Result res = TEE_ERROR_GENERIC; struct dt_node_info dt_info = { }; const fdt32_t *conf_list = NULL; const fdt64_t *cuint = NULL; unsigned int nregions = 0; unsigned int i = 0; int len = 0; res = stm32_rifsc_check_tdcid(&is_tdcid); if (res) return res; if (!is_tdcid) return TEE_SUCCESS; risaf = calloc(1, sizeof(*risaf)); if (!risaf) return TEE_ERROR_OUT_OF_MEMORY; fdt_fill_device_info(fdt, &dt_info, node); if (dt_info.reg == DT_INFO_INVALID_REG || dt_info.reg_size == DT_INFO_INVALID_REG_SIZE) { free(risaf); return TEE_ERROR_BAD_PARAMETERS; } risaf->pdata.base.pa = dt_info.reg; io_pa_or_va_secure(&risaf->pdata.base, dt_info.reg_size); risaf->pdata.enc_supported = compat->supported_encryption; res = clk_dt_get_by_index(fdt, node, 0, &risaf->pdata.clock); if (!risaf->pdata.clock) goto err; conf_list = fdt_getprop(fdt, node, "memory-region", &len); if (!conf_list) { DMSG("RISAF %#"PRIxPA": No configuration in DT, use default", risaf->pdata.base.pa); free(risaf); return TEE_SUCCESS; } nregions = (unsigned int)len / sizeof(uint32_t); /* Silently allow unexpected truncated names */ strncpy(risaf->pdata.risaf_name, fdt_get_name(fdt, node, NULL), sizeof(risaf->pdata.risaf_name) - 1); res = clk_enable(risaf->pdata.clock); if (res) goto err; res = stm32_risaf_init_ddata(risaf); if (res) goto err_clk; risaf_print_version(risaf); cuint = fdt_getprop(fdt, node, "st,mem-map", &len); if (!cuint || (size_t)len != sizeof(*cuint) * 2) panic(); risaf->pdata.mem_base = (paddr_t)fdt64_to_cpu(*cuint); risaf->pdata.mem_size = (size_t)fdt64_to_cpu(*(cuint + 1)); regions = calloc(nregions, sizeof(*regions)); if (nregions && !regions) { res = TEE_ERROR_OUT_OF_MEMORY; goto err_ddata; } DMSG("RISAF %#"PRIxPA" memory range: %#"PRIxPA" - %#"PRIxPA, risaf->pdata.base.pa, risaf->pdata.mem_base, risaf->pdata.mem_base + risaf->pdata.mem_size - 1); for (i = 0; i < nregions; i++) { const fdt32_t *prop = NULL; paddr_t start_addr = 0; paddr_t end_addr = 0; uint32_t cid_cfg = 0; uint32_t phandle = 0; uint32_t cfg = 0; uint32_t id = 0; int pnode = 0; phandle = fdt32_to_cpu(*(conf_list + i)); pnode = fdt_node_offset_by_phandle(fdt, phandle); if (pnode < 0) continue; regions[i].addr = fdt_reg_base_address(fdt, pnode); regions[i].len = fdt_reg_size(fdt, pnode); if (!regions[i].len) continue; /* * The secure bootloader is in charge of configuring RISAF * related to OP-TEE secure memory. Therefore, skip OP-TEE * region so that RISAF configuration cannot interfere with * OP-TEE execution flow. */ if (regions[i].addr == TZDRAM_BASE && regions[i].len == TZDRAM_SIZE) { continue; } prop = fdt_getprop(fdt, pnode, "st,protreg", NULL); if (!prop) continue; regions[i].cfg = fdt32_to_cpu(*prop); if (risaf_check_region_boundaries(risaf, ®ions[i]) || risaf_check_overlap(risaf, regions, i)) panic(); id = _RISAF_GET_REGION_ID(regions[i].cfg); assert(id < risaf->ddata->max_base_regions); cfg = stm32_risaf_get_region_config(regions[i].cfg); cid_cfg = stm32_risaf_get_region_cid_config(regions[i].cfg); start_addr = regions[i].addr; end_addr = start_addr + regions[i].len - 1U; if (risaf_configure_region(risaf, id, cfg, cid_cfg, start_addr, end_addr)) panic(); } risaf->pdata.regions = regions; risaf->pdata.nregions = nregions; SLIST_INSERT_HEAD(&risaf_list, risaf, link); register_pm_core_service_cb(stm32_risaf_pm, risaf, "stm32-risaf"); return TEE_SUCCESS; err_ddata: free(risaf->ddata); err_clk: clk_disable(risaf->pdata.clock); err: free(risaf); return res; } static const struct dt_device_match risaf_match_table[] = { { .compatible = "st,stm32mp25-risaf", .compat_data = &stm32_risaf_compat, }, { .compatible = "st,stm32mp25-risaf-enc", .compat_data = &stm32_risaf_enc_compat, }, { } }; DEFINE_DT_DRIVER(risaf_dt_driver) = { .name = "stm32-risaf", .match_table = risaf_match_table, .probe = stm32_risaf_probe, };