1*778a36bfSGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause 2*778a36bfSGatien Chevallier /* 3*778a36bfSGatien Chevallier * Copyright (c) 2021-2024, STMicroelectronics 4*778a36bfSGatien Chevallier */ 5*778a36bfSGatien Chevallier 6*778a36bfSGatien Chevallier #include <arm.h> 7*778a36bfSGatien Chevallier #include <config.h> 8*778a36bfSGatien Chevallier #include <drivers/clk.h> 9*778a36bfSGatien Chevallier #include <drivers/clk_dt.h> 10*778a36bfSGatien Chevallier #include <drivers/stm32_gpio.h> 11*778a36bfSGatien Chevallier #include <drivers/stm32_rif.h> 12*778a36bfSGatien Chevallier #include <io.h> 13*778a36bfSGatien Chevallier #include <kernel/boot.h> 14*778a36bfSGatien Chevallier #include <kernel/delay.h> 15*778a36bfSGatien Chevallier #include <kernel/dt.h> 16*778a36bfSGatien Chevallier #include <kernel/dt_driver.h> 17*778a36bfSGatien Chevallier #include <kernel/panic.h> 18*778a36bfSGatien Chevallier #include <kernel/pm.h> 19*778a36bfSGatien Chevallier #include <libfdt.h> 20*778a36bfSGatien Chevallier #include <mm/core_memprot.h> 21*778a36bfSGatien Chevallier #include <stdbool.h> 22*778a36bfSGatien Chevallier #include <stdlib.h> 23*778a36bfSGatien Chevallier #include <stm32_util.h> 24*778a36bfSGatien Chevallier #include <trace.h> 25*778a36bfSGatien Chevallier 26*778a36bfSGatien Chevallier #define _FMC_CFGR U(0x020) 27*778a36bfSGatien Chevallier #define _FMC_SECCFGR U(0x300) 28*778a36bfSGatien Chevallier #define _FMC_PRIVCFGR U(0x304) 29*778a36bfSGatien Chevallier #define _FMC_RCFGLOCKR U(0x308) 30*778a36bfSGatien Chevallier #define _FMC_CIDCFGR(x) (U(0x30C) + U(0x8) * (x)) 31*778a36bfSGatien Chevallier #define _FMC_SEMCR(x) (U(0x310) + U(0x8) * (x)) 32*778a36bfSGatien Chevallier /* 33*778a36bfSGatien Chevallier * CFGR register bitfields 34*778a36bfSGatien Chevallier */ 35*778a36bfSGatien Chevallier #define _FMC_CFGR_CLKDIV_MASK GENMASK_32(19, 16) 36*778a36bfSGatien Chevallier #define _FMC_CFGR_CLKDIV_SHIFT U(16) 37*778a36bfSGatien Chevallier #define _FMC_CFGR_CCLKEN BIT(20) 38*778a36bfSGatien Chevallier #define _FMC_CFGR_ENABLE BIT(31) 39*778a36bfSGatien Chevallier 40*778a36bfSGatien Chevallier /* 41*778a36bfSGatien Chevallier * CIDCFGR register bitfields 42*778a36bfSGatien Chevallier */ 43*778a36bfSGatien Chevallier #define _FMC_CIDCFGR_SEMWL_MASK GENMASK_32(23, 16) 44*778a36bfSGatien Chevallier #define _FMC_CIDCFGR_SCID_MASK GENMASK_32(6, 4) 45*778a36bfSGatien Chevallier #define _FMC_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ 46*778a36bfSGatien Chevallier _CIDCFGR_SEMEN | \ 47*778a36bfSGatien Chevallier _FMC_CIDCFGR_SCID_MASK |\ 48*778a36bfSGatien Chevallier _FMC_CIDCFGR_SEMWL_MASK) 49*778a36bfSGatien Chevallier 50*778a36bfSGatien Chevallier /* 51*778a36bfSGatien Chevallier * PRIVCFGR register bitfields 52*778a36bfSGatien Chevallier */ 53*778a36bfSGatien Chevallier #define _FMC_PRIVCFGR_MASK GENMASK_32(5, 0) 54*778a36bfSGatien Chevallier 55*778a36bfSGatien Chevallier /* 56*778a36bfSGatien Chevallier * RCFGLOCKR register bitfields 57*778a36bfSGatien Chevallier */ 58*778a36bfSGatien Chevallier #define _FMC_RCFGLOCKR_MASK GENMASK_32(5, 0) 59*778a36bfSGatien Chevallier 60*778a36bfSGatien Chevallier /* 61*778a36bfSGatien Chevallier * SECCFGR register bitfields 62*778a36bfSGatien Chevallier */ 63*778a36bfSGatien Chevallier #define _FMC_SECCFGR_EN BIT(0) 64*778a36bfSGatien Chevallier #define _FMC_SECCFGR_MASK GENMASK_32(5, 0) 65*778a36bfSGatien Chevallier 66*778a36bfSGatien Chevallier /* 67*778a36bfSGatien Chevallier * SEMCR register bitfields 68*778a36bfSGatien Chevallier */ 69*778a36bfSGatien Chevallier #define _FMC_SEMCR_SCID_MASK GENMASK_32(7, 5) 70*778a36bfSGatien Chevallier #define _FMC_SEMCR_SCID_SHIFT U(5) 71*778a36bfSGatien Chevallier 72*778a36bfSGatien Chevallier /* 73*778a36bfSGatien Chevallier * Miscellaneous 74*778a36bfSGatien Chevallier */ 75*778a36bfSGatien Chevallier 76*778a36bfSGatien Chevallier #define FMC_RIF_CONTROLLERS U(6) 77*778a36bfSGatien Chevallier 78*778a36bfSGatien Chevallier #define FMC_NB_MAX_CID_SUPPORTED U(7) 79*778a36bfSGatien Chevallier 80*778a36bfSGatien Chevallier #define FMC_NSEC_PER_SEC UL(1000000000) 81*778a36bfSGatien Chevallier 82*778a36bfSGatien Chevallier struct fmc_pdata { 83*778a36bfSGatien Chevallier struct clk *fmc_clock; 84*778a36bfSGatien Chevallier struct pinctrl_state *pinctrl_d; 85*778a36bfSGatien Chevallier struct pinctrl_state *pinctrl_s; 86*778a36bfSGatien Chevallier struct rif_conf_data conf_data; 87*778a36bfSGatien Chevallier unsigned int nb_controller; 88*778a36bfSGatien Chevallier vaddr_t base; 89*778a36bfSGatien Chevallier uint32_t clk_period_ns; 90*778a36bfSGatien Chevallier bool cclken; 91*778a36bfSGatien Chevallier }; 92*778a36bfSGatien Chevallier 93*778a36bfSGatien Chevallier static struct fmc_pdata *fmc_d; 94*778a36bfSGatien Chevallier 95*778a36bfSGatien Chevallier static bool fmc_controller_is_secure(uint8_t controller) 96*778a36bfSGatien Chevallier { 97*778a36bfSGatien Chevallier return io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(controller); 98*778a36bfSGatien Chevallier } 99*778a36bfSGatien Chevallier 100*778a36bfSGatien Chevallier static TEE_Result apply_rif_config(void) 101*778a36bfSGatien Chevallier { 102*778a36bfSGatien Chevallier TEE_Result res = TEE_ERROR_ACCESS_DENIED; 103*778a36bfSGatien Chevallier uint32_t cidcfgr = 0; 104*778a36bfSGatien Chevallier unsigned int i = 0; 105*778a36bfSGatien Chevallier 106*778a36bfSGatien Chevallier res = clk_enable(fmc_d->fmc_clock); 107*778a36bfSGatien Chevallier if (res) 108*778a36bfSGatien Chevallier panic("Cannot access FMC clock"); 109*778a36bfSGatien Chevallier 110*778a36bfSGatien Chevallier for (i = 0; i < FMC_RIF_CONTROLLERS; i++) { 111*778a36bfSGatien Chevallier if (!(BIT(i) & fmc_d->conf_data.access_mask[0])) 112*778a36bfSGatien Chevallier continue; 113*778a36bfSGatien Chevallier 114*778a36bfSGatien Chevallier /* 115*778a36bfSGatien Chevallier * Whatever the TDCID state, try to clear the configurable part 116*778a36bfSGatien Chevallier * of the CIDCFGR register. 117*778a36bfSGatien Chevallier * If TDCID, register will be cleared, if not, the clear will 118*778a36bfSGatien Chevallier * be ignored. 119*778a36bfSGatien Chevallier * When TDCID, OP-TEE should be the one to set the CID filtering 120*778a36bfSGatien Chevallier * configuration. Clearing previous configuration prevents 121*778a36bfSGatien Chevallier * undesired events during the only legitimate configuration. 122*778a36bfSGatien Chevallier */ 123*778a36bfSGatien Chevallier io_clrbits32(fmc_d->base + _FMC_CIDCFGR(i), 124*778a36bfSGatien Chevallier _FMC_CIDCFGR_CONF_MASK); 125*778a36bfSGatien Chevallier 126*778a36bfSGatien Chevallier cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i)); 127*778a36bfSGatien Chevallier 128*778a36bfSGatien Chevallier /* Check if the controller is in semaphore mode */ 129*778a36bfSGatien Chevallier if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1)) 130*778a36bfSGatien Chevallier continue; 131*778a36bfSGatien Chevallier 132*778a36bfSGatien Chevallier /* If not TDCID, we want to acquire semaphores assigned to us */ 133*778a36bfSGatien Chevallier res = stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(i), 134*778a36bfSGatien Chevallier FMC_NB_MAX_CID_SUPPORTED); 135*778a36bfSGatien Chevallier if (res) { 136*778a36bfSGatien Chevallier EMSG("Couldn't acquire semaphore for controller %u", i); 137*778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 138*778a36bfSGatien Chevallier return res; 139*778a36bfSGatien Chevallier } 140*778a36bfSGatien Chevallier } 141*778a36bfSGatien Chevallier 142*778a36bfSGatien Chevallier /* Security and privilege RIF configuration */ 143*778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_PRIVCFGR, _FMC_PRIVCFGR_MASK, 144*778a36bfSGatien Chevallier fmc_d->conf_data.priv_conf[0]); 145*778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_SECCFGR, _FMC_SECCFGR_MASK, 146*778a36bfSGatien Chevallier fmc_d->conf_data.sec_conf[0]); 147*778a36bfSGatien Chevallier 148*778a36bfSGatien Chevallier for (i = 0; i < FMC_RIF_CONTROLLERS; i++) { 149*778a36bfSGatien Chevallier if (!(BIT(i) & fmc_d->conf_data.access_mask[0])) 150*778a36bfSGatien Chevallier continue; 151*778a36bfSGatien Chevallier 152*778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_CIDCFGR(i), 153*778a36bfSGatien Chevallier _FMC_CIDCFGR_CONF_MASK, 154*778a36bfSGatien Chevallier fmc_d->conf_data.cid_confs[i]); 155*778a36bfSGatien Chevallier 156*778a36bfSGatien Chevallier cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i)); 157*778a36bfSGatien Chevallier 158*778a36bfSGatien Chevallier /* 159*778a36bfSGatien Chevallier * Take semaphore if the resource is in semaphore mode 160*778a36bfSGatien Chevallier * and secured 161*778a36bfSGatien Chevallier */ 162*778a36bfSGatien Chevallier if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1) || 163*778a36bfSGatien Chevallier !(io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(i))) { 164*778a36bfSGatien Chevallier res = 165*778a36bfSGatien Chevallier stm32_rif_release_semaphore(fmc_d->base + _FMC_SEMCR(i), 166*778a36bfSGatien Chevallier FMC_NB_MAX_CID_SUPPORTED); 167*778a36bfSGatien Chevallier if (res) { 168*778a36bfSGatien Chevallier EMSG("Couldn't release semaphore for res%u", i); 169*778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 170*778a36bfSGatien Chevallier return res; 171*778a36bfSGatien Chevallier } 172*778a36bfSGatien Chevallier } else { 173*778a36bfSGatien Chevallier res = 174*778a36bfSGatien Chevallier stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(i), 175*778a36bfSGatien Chevallier FMC_NB_MAX_CID_SUPPORTED); 176*778a36bfSGatien Chevallier if (res) { 177*778a36bfSGatien Chevallier EMSG("Couldn't acquire semaphore for res%u", i); 178*778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 179*778a36bfSGatien Chevallier return res; 180*778a36bfSGatien Chevallier } 181*778a36bfSGatien Chevallier } 182*778a36bfSGatien Chevallier } 183*778a36bfSGatien Chevallier 184*778a36bfSGatien Chevallier /* 185*778a36bfSGatien Chevallier * Lock RIF configuration if configured. This cannot be undone until 186*778a36bfSGatien Chevallier * next reset. 187*778a36bfSGatien Chevallier */ 188*778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_RCFGLOCKR, _FMC_RCFGLOCKR_MASK, 189*778a36bfSGatien Chevallier fmc_d->conf_data.lock_conf[0]); 190*778a36bfSGatien Chevallier 191*778a36bfSGatien Chevallier if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) { 192*778a36bfSGatien Chevallier /* Check that RIF config are applied, panic otherwise */ 193*778a36bfSGatien Chevallier if ((io_read32(fmc_d->base + _FMC_PRIVCFGR) & 194*778a36bfSGatien Chevallier fmc_d->conf_data.access_mask[0]) != 195*778a36bfSGatien Chevallier fmc_d->conf_data.priv_conf[0]) { 196*778a36bfSGatien Chevallier EMSG("FMC controller priv conf is incorrect"); 197*778a36bfSGatien Chevallier panic(); 198*778a36bfSGatien Chevallier } 199*778a36bfSGatien Chevallier 200*778a36bfSGatien Chevallier if ((io_read32(fmc_d->base + _FMC_SECCFGR) & 201*778a36bfSGatien Chevallier fmc_d->conf_data.access_mask[0]) != 202*778a36bfSGatien Chevallier fmc_d->conf_data.sec_conf[0]) { 203*778a36bfSGatien Chevallier EMSG("FMC controller sec conf is incorrect"); 204*778a36bfSGatien Chevallier panic(); 205*778a36bfSGatien Chevallier } 206*778a36bfSGatien Chevallier } 207*778a36bfSGatien Chevallier 208*778a36bfSGatien Chevallier /* Disable the clock to allow RCC RIF re-configuration on this clock */ 209*778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 210*778a36bfSGatien Chevallier 211*778a36bfSGatien Chevallier return TEE_SUCCESS; 212*778a36bfSGatien Chevallier } 213*778a36bfSGatien Chevallier 214*778a36bfSGatien Chevallier static TEE_Result parse_dt(const void *fdt, int node) 215*778a36bfSGatien Chevallier { 216*778a36bfSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 217*778a36bfSGatien Chevallier uint32_t rif_conf = 0; 218*778a36bfSGatien Chevallier unsigned int i = 0; 219*778a36bfSGatien Chevallier int lenp = 0; 220*778a36bfSGatien Chevallier const fdt32_t *cuint = NULL; 221*778a36bfSGatien Chevallier struct dt_node_info info = { }; 222*778a36bfSGatien Chevallier struct io_pa_va addr = { }; 223*778a36bfSGatien Chevallier int ctrl_node = 0; 224*778a36bfSGatien Chevallier 225*778a36bfSGatien Chevallier fdt_fill_device_info(fdt, &info, node); 226*778a36bfSGatien Chevallier assert(info.reg != DT_INFO_INVALID_REG && 227*778a36bfSGatien Chevallier info.reg_size != DT_INFO_INVALID_REG_SIZE); 228*778a36bfSGatien Chevallier 229*778a36bfSGatien Chevallier addr.pa = info.reg; 230*778a36bfSGatien Chevallier fmc_d->base = io_pa_or_va(&addr, info.reg_size); 231*778a36bfSGatien Chevallier 232*778a36bfSGatien Chevallier res = clk_dt_get_by_index(fdt, node, 0, &fmc_d->fmc_clock); 233*778a36bfSGatien Chevallier if (res) 234*778a36bfSGatien Chevallier return res; 235*778a36bfSGatien Chevallier 236*778a36bfSGatien Chevallier res = pinctrl_get_state_by_name(fdt, node, "default", 237*778a36bfSGatien Chevallier &fmc_d->pinctrl_d); 238*778a36bfSGatien Chevallier if (res && res != TEE_ERROR_ITEM_NOT_FOUND) 239*778a36bfSGatien Chevallier return res; 240*778a36bfSGatien Chevallier 241*778a36bfSGatien Chevallier res = pinctrl_get_state_by_name(fdt, node, "sleep", 242*778a36bfSGatien Chevallier &fmc_d->pinctrl_s); 243*778a36bfSGatien Chevallier if (res && res != TEE_ERROR_ITEM_NOT_FOUND) 244*778a36bfSGatien Chevallier return res; 245*778a36bfSGatien Chevallier 246*778a36bfSGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); 247*778a36bfSGatien Chevallier if (!cuint) 248*778a36bfSGatien Chevallier panic("No RIF configuration available"); 249*778a36bfSGatien Chevallier 250*778a36bfSGatien Chevallier fmc_d->nb_controller = (unsigned int)(lenp / sizeof(uint32_t)); 251*778a36bfSGatien Chevallier assert(fmc_d->nb_controller <= FMC_RIF_CONTROLLERS); 252*778a36bfSGatien Chevallier 253*778a36bfSGatien Chevallier fmc_d->conf_data.cid_confs = calloc(FMC_RIF_CONTROLLERS, 254*778a36bfSGatien Chevallier sizeof(uint32_t)); 255*778a36bfSGatien Chevallier fmc_d->conf_data.sec_conf = calloc(1, sizeof(uint32_t)); 256*778a36bfSGatien Chevallier fmc_d->conf_data.priv_conf = calloc(1, sizeof(uint32_t)); 257*778a36bfSGatien Chevallier fmc_d->conf_data.lock_conf = calloc(1, sizeof(uint32_t)); 258*778a36bfSGatien Chevallier fmc_d->conf_data.access_mask = calloc(1, sizeof(uint32_t)); 259*778a36bfSGatien Chevallier assert(fmc_d->conf_data.cid_confs && fmc_d->conf_data.sec_conf && 260*778a36bfSGatien Chevallier fmc_d->conf_data.priv_conf && fmc_d->conf_data.access_mask); 261*778a36bfSGatien Chevallier 262*778a36bfSGatien Chevallier for (i = 0; i < fmc_d->nb_controller; i++) { 263*778a36bfSGatien Chevallier rif_conf = fdt32_to_cpu(cuint[i]); 264*778a36bfSGatien Chevallier 265*778a36bfSGatien Chevallier stm32_rif_parse_cfg(rif_conf, &fmc_d->conf_data, 266*778a36bfSGatien Chevallier FMC_NB_MAX_CID_SUPPORTED, 267*778a36bfSGatien Chevallier FMC_RIF_CONTROLLERS); 268*778a36bfSGatien Chevallier } 269*778a36bfSGatien Chevallier 270*778a36bfSGatien Chevallier fdt_for_each_subnode(ctrl_node, fdt, node) { 271*778a36bfSGatien Chevallier int status = fdt_get_status(fdt, ctrl_node); 272*778a36bfSGatien Chevallier uint32_t bank = 0; 273*778a36bfSGatien Chevallier 274*778a36bfSGatien Chevallier if (status == DT_STATUS_DISABLED) 275*778a36bfSGatien Chevallier continue; 276*778a36bfSGatien Chevallier 277*778a36bfSGatien Chevallier if (fdt_read_uint32(fdt, ctrl_node, "reg", &bank) < 0) 278*778a36bfSGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 279*778a36bfSGatien Chevallier 280*778a36bfSGatien Chevallier if (bank != 0) 281*778a36bfSGatien Chevallier continue; 282*778a36bfSGatien Chevallier 283*778a36bfSGatien Chevallier if (fdt_getprop(fdt, ctrl_node, 284*778a36bfSGatien Chevallier "st,fmc2-ebi-cs-cclk-enable", NULL)) 285*778a36bfSGatien Chevallier fmc_d->cclken = true; 286*778a36bfSGatien Chevallier 287*778a36bfSGatien Chevallier if (!fmc_d->cclken) 288*778a36bfSGatien Chevallier continue; 289*778a36bfSGatien Chevallier 290*778a36bfSGatien Chevallier if (fdt_read_uint32(fdt, ctrl_node, 291*778a36bfSGatien Chevallier "st,fmc2-ebi-cs-clk-period-ns", 292*778a36bfSGatien Chevallier &fmc_d->clk_period_ns) < 0) 293*778a36bfSGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 294*778a36bfSGatien Chevallier } 295*778a36bfSGatien Chevallier 296*778a36bfSGatien Chevallier return TEE_SUCCESS; 297*778a36bfSGatien Chevallier } 298*778a36bfSGatien Chevallier 299*778a36bfSGatien Chevallier static TEE_Result __maybe_unused check_fmc_rif_conf(void) 300*778a36bfSGatien Chevallier { 301*778a36bfSGatien Chevallier unsigned int i = 0; 302*778a36bfSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 303*778a36bfSGatien Chevallier 304*778a36bfSGatien Chevallier res = clk_enable(fmc_d->fmc_clock); 305*778a36bfSGatien Chevallier if (res) 306*778a36bfSGatien Chevallier panic("Cannot access FMC clock"); 307*778a36bfSGatien Chevallier 308*778a36bfSGatien Chevallier if (fmc_controller_is_secure(0)) 309*778a36bfSGatien Chevallier goto end; 310*778a36bfSGatien Chevallier 311*778a36bfSGatien Chevallier for (i = 1; i < fmc_d->nb_controller; i++) { 312*778a36bfSGatien Chevallier uint32_t cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i)); 313*778a36bfSGatien Chevallier uint32_t semcr = io_read32(fmc_d->base + _FMC_SEMCR(i)); 314*778a36bfSGatien Chevallier 315*778a36bfSGatien Chevallier /* Check if a controller is secure */ 316*778a36bfSGatien Chevallier if (fmc_controller_is_secure(i)) { 317*778a36bfSGatien Chevallier res = TEE_ERROR_BAD_STATE; 318*778a36bfSGatien Chevallier goto end; 319*778a36bfSGatien Chevallier } 320*778a36bfSGatien Chevallier 321*778a36bfSGatien Chevallier /* 322*778a36bfSGatien Chevallier * Check if a controller is shared with incorrect CID 323*778a36bfSGatien Chevallier * (!= RIF_CID1) 324*778a36bfSGatien Chevallier */ 325*778a36bfSGatien Chevallier res = stm32_rif_check_access(cidcfgr, semcr, 326*778a36bfSGatien Chevallier FMC_NB_MAX_CID_SUPPORTED, 327*778a36bfSGatien Chevallier RIF_CID1); 328*778a36bfSGatien Chevallier if (res) 329*778a36bfSGatien Chevallier break; 330*778a36bfSGatien Chevallier } 331*778a36bfSGatien Chevallier 332*778a36bfSGatien Chevallier end: 333*778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 334*778a36bfSGatien Chevallier 335*778a36bfSGatien Chevallier return res; 336*778a36bfSGatien Chevallier } 337*778a36bfSGatien Chevallier 338*778a36bfSGatien Chevallier static void configure_fmc(void) 339*778a36bfSGatien Chevallier { 340*778a36bfSGatien Chevallier uint32_t cidcfgr = 0; 341*778a36bfSGatien Chevallier uint32_t semcr = 0; 342*778a36bfSGatien Chevallier 343*778a36bfSGatien Chevallier if (clk_enable(fmc_d->fmc_clock)) 344*778a36bfSGatien Chevallier panic("Cannot access FMC clock"); 345*778a36bfSGatien Chevallier 346*778a36bfSGatien Chevallier semcr = io_read32(fmc_d->base + _FMC_SEMCR(0)); 347*778a36bfSGatien Chevallier cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(0)); 348*778a36bfSGatien Chevallier 349*778a36bfSGatien Chevallier /* 350*778a36bfSGatien Chevallier * If OP-TEE doesn't have access to the controller 0, 351*778a36bfSGatien Chevallier * then we don't want to try to enable the FMC. 352*778a36bfSGatien Chevallier */ 353*778a36bfSGatien Chevallier if (stm32_rif_check_access(cidcfgr, semcr, 354*778a36bfSGatien Chevallier FMC_NB_MAX_CID_SUPPORTED, RIF_CID1)) 355*778a36bfSGatien Chevallier goto end; 356*778a36bfSGatien Chevallier 357*778a36bfSGatien Chevallier /* Check controller 0 access */ 358*778a36bfSGatien Chevallier if (!fmc_controller_is_secure(0)) { 359*778a36bfSGatien Chevallier DMSG("Controller 0 non-secure, FMC not enabled"); 360*778a36bfSGatien Chevallier goto end; 361*778a36bfSGatien Chevallier } 362*778a36bfSGatien Chevallier 363*778a36bfSGatien Chevallier if (cidcfgr & _CIDCFGR_SEMEN && 364*778a36bfSGatien Chevallier stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(0), 365*778a36bfSGatien Chevallier FMC_NB_MAX_CID_SUPPORTED)) 366*778a36bfSGatien Chevallier panic("Couldn't acquire controller 0 semaphore"); 367*778a36bfSGatien Chevallier 368*778a36bfSGatien Chevallier if (fmc_d->pinctrl_d && pinctrl_apply_state(fmc_d->pinctrl_d)) 369*778a36bfSGatien Chevallier panic("Could not apply FMC pinctrl"); 370*778a36bfSGatien Chevallier 371*778a36bfSGatien Chevallier if (fmc_d->cclken) { 372*778a36bfSGatien Chevallier unsigned long hclk = clk_get_rate(fmc_d->fmc_clock); 373*778a36bfSGatien Chevallier unsigned long hclkp = FMC_NSEC_PER_SEC / (hclk / 1000); 374*778a36bfSGatien Chevallier unsigned long timing = DIV_ROUND_UP(fmc_d->clk_period_ns * 1000, 375*778a36bfSGatien Chevallier hclkp); 376*778a36bfSGatien Chevallier uint32_t clk_div = SHIFT_U32(1, _FMC_CFGR_CLKDIV_SHIFT); 377*778a36bfSGatien Chevallier 378*778a36bfSGatien Chevallier if (timing > 1) { 379*778a36bfSGatien Chevallier timing--; 380*778a36bfSGatien Chevallier if (timing > 381*778a36bfSGatien Chevallier _FMC_CFGR_CLKDIV_MASK >> _FMC_CFGR_CLKDIV_SHIFT) 382*778a36bfSGatien Chevallier clk_div = _FMC_CFGR_CLKDIV_MASK; 383*778a36bfSGatien Chevallier else 384*778a36bfSGatien Chevallier clk_div = SHIFT_U32(timing, 385*778a36bfSGatien Chevallier _FMC_CFGR_CLKDIV_SHIFT); 386*778a36bfSGatien Chevallier } 387*778a36bfSGatien Chevallier 388*778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_CFGR, 389*778a36bfSGatien Chevallier _FMC_CFGR_CLKDIV_MASK | _FMC_CFGR_CCLKEN, 390*778a36bfSGatien Chevallier clk_div | _FMC_CFGR_CCLKEN); 391*778a36bfSGatien Chevallier } 392*778a36bfSGatien Chevallier 393*778a36bfSGatien Chevallier /* Set the FMC enable BIT */ 394*778a36bfSGatien Chevallier io_setbits32(fmc_d->base + _FMC_CFGR, _FMC_CFGR_ENABLE); 395*778a36bfSGatien Chevallier 396*778a36bfSGatien Chevallier end: 397*778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 398*778a36bfSGatien Chevallier } 399*778a36bfSGatien Chevallier 400*778a36bfSGatien Chevallier static void fmc_setup(void) 401*778a36bfSGatien Chevallier { 402*778a36bfSGatien Chevallier if (apply_rif_config()) 403*778a36bfSGatien Chevallier panic("Failed to apply rif_config"); 404*778a36bfSGatien Chevallier 405*778a36bfSGatien Chevallier /* Sanity check for FMC RIF config */ 406*778a36bfSGatien Chevallier assert(check_fmc_rif_conf()); 407*778a36bfSGatien Chevallier 408*778a36bfSGatien Chevallier configure_fmc(); 409*778a36bfSGatien Chevallier } 410*778a36bfSGatien Chevallier 411*778a36bfSGatien Chevallier static void fmc_suspend(void) 412*778a36bfSGatien Chevallier { 413*778a36bfSGatien Chevallier unsigned int i = 0; 414*778a36bfSGatien Chevallier 415*778a36bfSGatien Chevallier if (clk_enable(fmc_d->fmc_clock)) 416*778a36bfSGatien Chevallier panic("Cannot access FMC clock"); 417*778a36bfSGatien Chevallier 418*778a36bfSGatien Chevallier if (fmc_controller_is_secure(0) && fmc_d->pinctrl_s && 419*778a36bfSGatien Chevallier pinctrl_apply_state(fmc_d->pinctrl_s)) 420*778a36bfSGatien Chevallier panic(); 421*778a36bfSGatien Chevallier 422*778a36bfSGatien Chevallier for (i = 0; i < FMC_RIF_CONTROLLERS; i++) 423*778a36bfSGatien Chevallier fmc_d->conf_data.cid_confs[i] = 424*778a36bfSGatien Chevallier io_read32(fmc_d->base + _FMC_CIDCFGR(i)) & 425*778a36bfSGatien Chevallier _FMC_CIDCFGR_CONF_MASK; 426*778a36bfSGatien Chevallier 427*778a36bfSGatien Chevallier fmc_d->conf_data.priv_conf[0] = 428*778a36bfSGatien Chevallier io_read32(fmc_d->base + _FMC_PRIVCFGR) & _FMC_PRIVCFGR_MASK; 429*778a36bfSGatien Chevallier fmc_d->conf_data.sec_conf[0] = 430*778a36bfSGatien Chevallier io_read32(fmc_d->base + _FMC_SECCFGR) & _FMC_SECCFGR_MASK; 431*778a36bfSGatien Chevallier fmc_d->conf_data.lock_conf[0] = 432*778a36bfSGatien Chevallier io_read32(fmc_d->base + _FMC_RCFGLOCKR) & _FMC_RCFGLOCKR_MASK; 433*778a36bfSGatien Chevallier fmc_d->conf_data.access_mask[0] = 434*778a36bfSGatien Chevallier GENMASK_32(FMC_RIF_CONTROLLERS - 1, 0); 435*778a36bfSGatien Chevallier 436*778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 437*778a36bfSGatien Chevallier } 438*778a36bfSGatien Chevallier 439*778a36bfSGatien Chevallier static TEE_Result fmc_pm(enum pm_op op, unsigned int pm_hint, 440*778a36bfSGatien Chevallier const struct pm_callback_handle *pm_handle __unused) 441*778a36bfSGatien Chevallier { 442*778a36bfSGatien Chevallier if (pm_hint != PM_HINT_CONTEXT_STATE) 443*778a36bfSGatien Chevallier return TEE_SUCCESS; 444*778a36bfSGatien Chevallier 445*778a36bfSGatien Chevallier if (op == PM_OP_RESUME) 446*778a36bfSGatien Chevallier fmc_setup(); 447*778a36bfSGatien Chevallier else 448*778a36bfSGatien Chevallier fmc_suspend(); 449*778a36bfSGatien Chevallier 450*778a36bfSGatien Chevallier return TEE_SUCCESS; 451*778a36bfSGatien Chevallier } 452*778a36bfSGatien Chevallier 453*778a36bfSGatien Chevallier static TEE_Result fmc_probe(const void *fdt, int node, 454*778a36bfSGatien Chevallier const void *compat_data __unused) 455*778a36bfSGatien Chevallier { 456*778a36bfSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 457*778a36bfSGatien Chevallier 458*778a36bfSGatien Chevallier fmc_d = calloc(1, sizeof(*fmc_d)); 459*778a36bfSGatien Chevallier if (!fmc_d) 460*778a36bfSGatien Chevallier return TEE_ERROR_OUT_OF_MEMORY; 461*778a36bfSGatien Chevallier 462*778a36bfSGatien Chevallier res = parse_dt(fdt, node); 463*778a36bfSGatien Chevallier if (res) 464*778a36bfSGatien Chevallier goto err; 465*778a36bfSGatien Chevallier 466*778a36bfSGatien Chevallier fmc_setup(); 467*778a36bfSGatien Chevallier 468*778a36bfSGatien Chevallier register_pm_core_service_cb(fmc_pm, NULL, "stm32-fmc"); 469*778a36bfSGatien Chevallier 470*778a36bfSGatien Chevallier return TEE_SUCCESS; 471*778a36bfSGatien Chevallier err: 472*778a36bfSGatien Chevallier /* Free all allocated resources */ 473*778a36bfSGatien Chevallier free(fmc_d->conf_data.cid_confs); 474*778a36bfSGatien Chevallier free(fmc_d->conf_data.sec_conf); 475*778a36bfSGatien Chevallier free(fmc_d->conf_data.priv_conf); 476*778a36bfSGatien Chevallier free(fmc_d->conf_data.access_mask); 477*778a36bfSGatien Chevallier free(fmc_d); 478*778a36bfSGatien Chevallier 479*778a36bfSGatien Chevallier return res; 480*778a36bfSGatien Chevallier } 481*778a36bfSGatien Chevallier 482*778a36bfSGatien Chevallier static const struct dt_device_match stm32_fmc_match_table[] = { 483*778a36bfSGatien Chevallier { .compatible = "st,stm32mp25-fmc2-ebi" }, 484*778a36bfSGatien Chevallier { } 485*778a36bfSGatien Chevallier }; 486*778a36bfSGatien Chevallier 487*778a36bfSGatien Chevallier DEFINE_DT_DRIVER(stm32_fmc_dt_driver) = { 488*778a36bfSGatien Chevallier .name = "stm32_fmc", 489*778a36bfSGatien Chevallier .match_table = stm32_fmc_match_table, 490*778a36bfSGatien Chevallier .probe = fmc_probe, 491*778a36bfSGatien Chevallier }; 492