1778a36bfSGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause 2778a36bfSGatien Chevallier /* 3778a36bfSGatien Chevallier * Copyright (c) 2021-2024, STMicroelectronics 4778a36bfSGatien Chevallier */ 5778a36bfSGatien Chevallier 6778a36bfSGatien Chevallier #include <arm.h> 7778a36bfSGatien Chevallier #include <config.h> 8778a36bfSGatien Chevallier #include <drivers/clk.h> 9778a36bfSGatien Chevallier #include <drivers/clk_dt.h> 10778a36bfSGatien Chevallier #include <drivers/stm32_gpio.h> 11778a36bfSGatien Chevallier #include <drivers/stm32_rif.h> 12778a36bfSGatien Chevallier #include <io.h> 13778a36bfSGatien Chevallier #include <kernel/boot.h> 14778a36bfSGatien Chevallier #include <kernel/delay.h> 15778a36bfSGatien Chevallier #include <kernel/dt.h> 16778a36bfSGatien Chevallier #include <kernel/dt_driver.h> 17778a36bfSGatien Chevallier #include <kernel/panic.h> 18778a36bfSGatien Chevallier #include <kernel/pm.h> 19778a36bfSGatien Chevallier #include <libfdt.h> 20778a36bfSGatien Chevallier #include <mm/core_memprot.h> 21778a36bfSGatien Chevallier #include <stdbool.h> 22778a36bfSGatien Chevallier #include <stdlib.h> 23778a36bfSGatien Chevallier #include <stm32_util.h> 24778a36bfSGatien Chevallier #include <trace.h> 25778a36bfSGatien Chevallier 26778a36bfSGatien Chevallier #define _FMC_CFGR U(0x020) 27778a36bfSGatien Chevallier #define _FMC_SECCFGR U(0x300) 28778a36bfSGatien Chevallier #define _FMC_PRIVCFGR U(0x304) 29778a36bfSGatien Chevallier #define _FMC_RCFGLOCKR U(0x308) 30778a36bfSGatien Chevallier #define _FMC_CIDCFGR(x) (U(0x30C) + U(0x8) * (x)) 31778a36bfSGatien Chevallier #define _FMC_SEMCR(x) (U(0x310) + U(0x8) * (x)) 32778a36bfSGatien Chevallier /* 33778a36bfSGatien Chevallier * CFGR register bitfields 34778a36bfSGatien Chevallier */ 35778a36bfSGatien Chevallier #define _FMC_CFGR_CLKDIV_MASK GENMASK_32(19, 16) 36778a36bfSGatien Chevallier #define _FMC_CFGR_CLKDIV_SHIFT U(16) 37778a36bfSGatien Chevallier #define _FMC_CFGR_CCLKEN BIT(20) 38778a36bfSGatien Chevallier #define _FMC_CFGR_ENABLE BIT(31) 39778a36bfSGatien Chevallier 40778a36bfSGatien Chevallier /* 41778a36bfSGatien Chevallier * CIDCFGR register bitfields 42778a36bfSGatien Chevallier */ 43778a36bfSGatien Chevallier #define _FMC_CIDCFGR_SEMWL_MASK GENMASK_32(23, 16) 44778a36bfSGatien Chevallier #define _FMC_CIDCFGR_SCID_MASK GENMASK_32(6, 4) 45778a36bfSGatien Chevallier #define _FMC_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ 46778a36bfSGatien Chevallier _CIDCFGR_SEMEN | \ 47778a36bfSGatien Chevallier _FMC_CIDCFGR_SCID_MASK |\ 48778a36bfSGatien Chevallier _FMC_CIDCFGR_SEMWL_MASK) 49778a36bfSGatien Chevallier 50778a36bfSGatien Chevallier /* 51778a36bfSGatien Chevallier * PRIVCFGR register bitfields 52778a36bfSGatien Chevallier */ 53778a36bfSGatien Chevallier #define _FMC_PRIVCFGR_MASK GENMASK_32(5, 0) 54778a36bfSGatien Chevallier 55778a36bfSGatien Chevallier /* 56778a36bfSGatien Chevallier * RCFGLOCKR register bitfields 57778a36bfSGatien Chevallier */ 58778a36bfSGatien Chevallier #define _FMC_RCFGLOCKR_MASK GENMASK_32(5, 0) 59778a36bfSGatien Chevallier 60778a36bfSGatien Chevallier /* 61778a36bfSGatien Chevallier * SECCFGR register bitfields 62778a36bfSGatien Chevallier */ 63778a36bfSGatien Chevallier #define _FMC_SECCFGR_EN BIT(0) 64778a36bfSGatien Chevallier #define _FMC_SECCFGR_MASK GENMASK_32(5, 0) 65778a36bfSGatien Chevallier 66778a36bfSGatien Chevallier /* 67778a36bfSGatien Chevallier * SEMCR register bitfields 68778a36bfSGatien Chevallier */ 69778a36bfSGatien Chevallier #define _FMC_SEMCR_SCID_MASK GENMASK_32(7, 5) 70778a36bfSGatien Chevallier #define _FMC_SEMCR_SCID_SHIFT U(5) 71778a36bfSGatien Chevallier 72778a36bfSGatien Chevallier /* 73778a36bfSGatien Chevallier * Miscellaneous 74778a36bfSGatien Chevallier */ 75778a36bfSGatien Chevallier 76778a36bfSGatien Chevallier #define FMC_RIF_CONTROLLERS U(6) 77778a36bfSGatien Chevallier 78778a36bfSGatien Chevallier #define FMC_NSEC_PER_SEC UL(1000000000) 79778a36bfSGatien Chevallier 80778a36bfSGatien Chevallier struct fmc_pdata { 81778a36bfSGatien Chevallier struct clk *fmc_clock; 82778a36bfSGatien Chevallier struct pinctrl_state *pinctrl_d; 83778a36bfSGatien Chevallier struct pinctrl_state *pinctrl_s; 84b573873cSGatien Chevallier struct rif_conf_data *conf_data; 85778a36bfSGatien Chevallier unsigned int nb_controller; 86778a36bfSGatien Chevallier vaddr_t base; 87778a36bfSGatien Chevallier uint32_t clk_period_ns; 88*5da989f3SGatien Chevallier bool is_tdcid; 89778a36bfSGatien Chevallier bool cclken; 90778a36bfSGatien Chevallier }; 91778a36bfSGatien Chevallier 92778a36bfSGatien Chevallier static struct fmc_pdata *fmc_d; 93778a36bfSGatien Chevallier 94778a36bfSGatien Chevallier static bool fmc_controller_is_secure(uint8_t controller) 95778a36bfSGatien Chevallier { 96778a36bfSGatien Chevallier return io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(controller); 97778a36bfSGatien Chevallier } 98778a36bfSGatien Chevallier 99*5da989f3SGatien Chevallier static TEE_Result handle_available_semaphores(void) 100*5da989f3SGatien Chevallier { 101*5da989f3SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 102*5da989f3SGatien Chevallier uint32_t cidcfgr = 0; 103*5da989f3SGatien Chevallier unsigned int i = 0; 104*5da989f3SGatien Chevallier 105*5da989f3SGatien Chevallier for (i = 0; i < FMC_RIF_CONTROLLERS; i++) { 106*5da989f3SGatien Chevallier if (!(BIT(i) & fmc_d->conf_data->access_mask[0])) 107*5da989f3SGatien Chevallier continue; 108*5da989f3SGatien Chevallier 109*5da989f3SGatien Chevallier cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i)); 110*5da989f3SGatien Chevallier 111*5da989f3SGatien Chevallier if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1)) 112*5da989f3SGatien Chevallier continue; 113*5da989f3SGatien Chevallier 114*5da989f3SGatien Chevallier if (!(io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(i))) { 115*5da989f3SGatien Chevallier res = stm32_rif_release_semaphore(fmc_d->base + 116*5da989f3SGatien Chevallier _FMC_SEMCR(i), 117*5da989f3SGatien Chevallier MAX_CID_SUPPORTED); 118*5da989f3SGatien Chevallier if (res) { 119*5da989f3SGatien Chevallier EMSG("Cannot release semaphore for resource %u", 120*5da989f3SGatien Chevallier i); 121*5da989f3SGatien Chevallier return res; 122*5da989f3SGatien Chevallier } 123*5da989f3SGatien Chevallier } else { 124*5da989f3SGatien Chevallier res = stm32_rif_acquire_semaphore(fmc_d->base + 125*5da989f3SGatien Chevallier _FMC_SEMCR(i), 126*5da989f3SGatien Chevallier MAX_CID_SUPPORTED); 127*5da989f3SGatien Chevallier if (res) { 128*5da989f3SGatien Chevallier EMSG("Cannot acquire semaphore for resource %u", 129*5da989f3SGatien Chevallier i); 130*5da989f3SGatien Chevallier return res; 131*5da989f3SGatien Chevallier } 132*5da989f3SGatien Chevallier } 133*5da989f3SGatien Chevallier } 134*5da989f3SGatien Chevallier 135*5da989f3SGatien Chevallier return TEE_SUCCESS; 136*5da989f3SGatien Chevallier } 137*5da989f3SGatien Chevallier 138778a36bfSGatien Chevallier static TEE_Result apply_rif_config(void) 139778a36bfSGatien Chevallier { 140778a36bfSGatien Chevallier TEE_Result res = TEE_ERROR_ACCESS_DENIED; 141778a36bfSGatien Chevallier unsigned int i = 0; 142778a36bfSGatien Chevallier 143b573873cSGatien Chevallier if (!fmc_d->conf_data) 144b573873cSGatien Chevallier return TEE_SUCCESS; 145b573873cSGatien Chevallier 146778a36bfSGatien Chevallier res = clk_enable(fmc_d->fmc_clock); 147778a36bfSGatien Chevallier if (res) 148778a36bfSGatien Chevallier panic("Cannot access FMC clock"); 149778a36bfSGatien Chevallier 150*5da989f3SGatien Chevallier if (fmc_d->is_tdcid) { 151778a36bfSGatien Chevallier for (i = 0; i < FMC_RIF_CONTROLLERS; i++) { 152b573873cSGatien Chevallier if (!(BIT(i) & fmc_d->conf_data->access_mask[0])) 153778a36bfSGatien Chevallier continue; 154778a36bfSGatien Chevallier /* 155*5da989f3SGatien Chevallier * When TDCID, OP-TEE should be the one to set the CID 156*5da989f3SGatien Chevallier * filtering configuration. Clearing previous 157*5da989f3SGatien Chevallier * configuration prevents undesired events during the 158*5da989f3SGatien Chevallier * only legitimate configuration. 159778a36bfSGatien Chevallier */ 160778a36bfSGatien Chevallier io_clrbits32(fmc_d->base + _FMC_CIDCFGR(i), 161778a36bfSGatien Chevallier _FMC_CIDCFGR_CONF_MASK); 162778a36bfSGatien Chevallier } 163*5da989f3SGatien Chevallier } else { 164*5da989f3SGatien Chevallier res = handle_available_semaphores(); 165*5da989f3SGatien Chevallier if (res) 166*5da989f3SGatien Chevallier panic(); 167778a36bfSGatien Chevallier } 168778a36bfSGatien Chevallier 169778a36bfSGatien Chevallier /* Security and privilege RIF configuration */ 170778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_PRIVCFGR, _FMC_PRIVCFGR_MASK, 171b573873cSGatien Chevallier fmc_d->conf_data->priv_conf[0]); 172778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_SECCFGR, _FMC_SECCFGR_MASK, 173b573873cSGatien Chevallier fmc_d->conf_data->sec_conf[0]); 174778a36bfSGatien Chevallier 175*5da989f3SGatien Chevallier if (!fmc_d->is_tdcid) 176*5da989f3SGatien Chevallier goto out; 177*5da989f3SGatien Chevallier 178778a36bfSGatien Chevallier for (i = 0; i < FMC_RIF_CONTROLLERS; i++) { 179b573873cSGatien Chevallier if (!(BIT(i) & fmc_d->conf_data->access_mask[0])) 180778a36bfSGatien Chevallier continue; 181778a36bfSGatien Chevallier 182778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_CIDCFGR(i), 183778a36bfSGatien Chevallier _FMC_CIDCFGR_CONF_MASK, 184b573873cSGatien Chevallier fmc_d->conf_data->cid_confs[i]); 185778a36bfSGatien Chevallier } 186778a36bfSGatien Chevallier 187778a36bfSGatien Chevallier /* 188778a36bfSGatien Chevallier * Lock RIF configuration if configured. This cannot be undone until 189778a36bfSGatien Chevallier * next reset. 190778a36bfSGatien Chevallier */ 191*5da989f3SGatien Chevallier io_setbits32(fmc_d->base + _FMC_RCFGLOCKR, 192b573873cSGatien Chevallier fmc_d->conf_data->lock_conf[0]); 193778a36bfSGatien Chevallier 194*5da989f3SGatien Chevallier res = handle_available_semaphores(); 195*5da989f3SGatien Chevallier if (res) 196*5da989f3SGatien Chevallier panic(); 197*5da989f3SGatien Chevallier out: 198778a36bfSGatien Chevallier if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) { 199778a36bfSGatien Chevallier /* Check that RIF config are applied, panic otherwise */ 200778a36bfSGatien Chevallier if ((io_read32(fmc_d->base + _FMC_PRIVCFGR) & 201b573873cSGatien Chevallier fmc_d->conf_data->access_mask[0]) != 202b573873cSGatien Chevallier fmc_d->conf_data->priv_conf[0]) { 203778a36bfSGatien Chevallier EMSG("FMC controller priv conf is incorrect"); 204778a36bfSGatien Chevallier panic(); 205778a36bfSGatien Chevallier } 206778a36bfSGatien Chevallier 207778a36bfSGatien Chevallier if ((io_read32(fmc_d->base + _FMC_SECCFGR) & 208b573873cSGatien Chevallier fmc_d->conf_data->access_mask[0]) != 209b573873cSGatien Chevallier fmc_d->conf_data->sec_conf[0]) { 210778a36bfSGatien Chevallier EMSG("FMC controller sec conf is incorrect"); 211778a36bfSGatien Chevallier panic(); 212778a36bfSGatien Chevallier } 213778a36bfSGatien Chevallier } 214778a36bfSGatien Chevallier 215778a36bfSGatien Chevallier /* Disable the clock to allow RCC RIF re-configuration on this clock */ 216778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 217778a36bfSGatien Chevallier 218778a36bfSGatien Chevallier return TEE_SUCCESS; 219778a36bfSGatien Chevallier } 220778a36bfSGatien Chevallier 221778a36bfSGatien Chevallier static TEE_Result parse_dt(const void *fdt, int node) 222778a36bfSGatien Chevallier { 223778a36bfSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 224778a36bfSGatien Chevallier struct dt_node_info info = { }; 225b573873cSGatien Chevallier const fdt32_t *cuint = NULL; 226778a36bfSGatien Chevallier struct io_pa_va addr = { }; 227b573873cSGatien Chevallier unsigned int i = 0; 228778a36bfSGatien Chevallier int ctrl_node = 0; 229b573873cSGatien Chevallier int lenp = 0; 230778a36bfSGatien Chevallier 231778a36bfSGatien Chevallier fdt_fill_device_info(fdt, &info, node); 232778a36bfSGatien Chevallier assert(info.reg != DT_INFO_INVALID_REG && 233778a36bfSGatien Chevallier info.reg_size != DT_INFO_INVALID_REG_SIZE); 234778a36bfSGatien Chevallier 235778a36bfSGatien Chevallier addr.pa = info.reg; 236778a36bfSGatien Chevallier fmc_d->base = io_pa_or_va(&addr, info.reg_size); 237778a36bfSGatien Chevallier 238778a36bfSGatien Chevallier res = clk_dt_get_by_index(fdt, node, 0, &fmc_d->fmc_clock); 239778a36bfSGatien Chevallier if (res) 240778a36bfSGatien Chevallier return res; 241778a36bfSGatien Chevallier 242778a36bfSGatien Chevallier res = pinctrl_get_state_by_name(fdt, node, "default", 243778a36bfSGatien Chevallier &fmc_d->pinctrl_d); 244778a36bfSGatien Chevallier if (res && res != TEE_ERROR_ITEM_NOT_FOUND) 245778a36bfSGatien Chevallier return res; 246778a36bfSGatien Chevallier 247778a36bfSGatien Chevallier res = pinctrl_get_state_by_name(fdt, node, "sleep", 248778a36bfSGatien Chevallier &fmc_d->pinctrl_s); 249778a36bfSGatien Chevallier if (res && res != TEE_ERROR_ITEM_NOT_FOUND) 250778a36bfSGatien Chevallier return res; 251778a36bfSGatien Chevallier 252778a36bfSGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); 253b573873cSGatien Chevallier if (!cuint) { 254b573873cSGatien Chevallier DMSG("No RIF configuration available"); 255b573873cSGatien Chevallier goto skip_rif; 256b573873cSGatien Chevallier } 257b573873cSGatien Chevallier 258b573873cSGatien Chevallier fmc_d->conf_data = calloc(1, sizeof(*fmc_d->conf_data)); 259b573873cSGatien Chevallier if (!fmc_d->conf_data) 260b573873cSGatien Chevallier panic(); 261778a36bfSGatien Chevallier 262778a36bfSGatien Chevallier fmc_d->nb_controller = (unsigned int)(lenp / sizeof(uint32_t)); 263778a36bfSGatien Chevallier assert(fmc_d->nb_controller <= FMC_RIF_CONTROLLERS); 264778a36bfSGatien Chevallier 265b573873cSGatien Chevallier fmc_d->conf_data->cid_confs = calloc(FMC_RIF_CONTROLLERS, 266778a36bfSGatien Chevallier sizeof(uint32_t)); 267b573873cSGatien Chevallier fmc_d->conf_data->sec_conf = calloc(1, sizeof(uint32_t)); 268b573873cSGatien Chevallier fmc_d->conf_data->priv_conf = calloc(1, sizeof(uint32_t)); 269b573873cSGatien Chevallier fmc_d->conf_data->lock_conf = calloc(1, sizeof(uint32_t)); 270b573873cSGatien Chevallier fmc_d->conf_data->access_mask = calloc(1, sizeof(uint32_t)); 271b573873cSGatien Chevallier if (!fmc_d->conf_data->cid_confs || !fmc_d->conf_data->sec_conf || 272b573873cSGatien Chevallier !fmc_d->conf_data->priv_conf || !fmc_d->conf_data->access_mask) 273b573873cSGatien Chevallier panic("Missing memory capacity for FMC RIF configuration"); 274778a36bfSGatien Chevallier 275b573873cSGatien Chevallier for (i = 0; i < fmc_d->nb_controller; i++) 276b573873cSGatien Chevallier stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), fmc_d->conf_data, 277778a36bfSGatien Chevallier FMC_RIF_CONTROLLERS); 278778a36bfSGatien Chevallier 279b573873cSGatien Chevallier skip_rif: 280778a36bfSGatien Chevallier fdt_for_each_subnode(ctrl_node, fdt, node) { 281778a36bfSGatien Chevallier int status = fdt_get_status(fdt, ctrl_node); 282778a36bfSGatien Chevallier uint32_t bank = 0; 283778a36bfSGatien Chevallier 284778a36bfSGatien Chevallier if (status == DT_STATUS_DISABLED) 285778a36bfSGatien Chevallier continue; 286778a36bfSGatien Chevallier 287778a36bfSGatien Chevallier if (fdt_read_uint32(fdt, ctrl_node, "reg", &bank) < 0) 288778a36bfSGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 289778a36bfSGatien Chevallier 290778a36bfSGatien Chevallier if (bank != 0) 291778a36bfSGatien Chevallier continue; 292778a36bfSGatien Chevallier 293778a36bfSGatien Chevallier if (fdt_getprop(fdt, ctrl_node, 294778a36bfSGatien Chevallier "st,fmc2-ebi-cs-cclk-enable", NULL)) 295778a36bfSGatien Chevallier fmc_d->cclken = true; 296778a36bfSGatien Chevallier 297778a36bfSGatien Chevallier if (!fmc_d->cclken) 298778a36bfSGatien Chevallier continue; 299778a36bfSGatien Chevallier 300778a36bfSGatien Chevallier if (fdt_read_uint32(fdt, ctrl_node, 301778a36bfSGatien Chevallier "st,fmc2-ebi-cs-clk-period-ns", 302778a36bfSGatien Chevallier &fmc_d->clk_period_ns) < 0) 303778a36bfSGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 304778a36bfSGatien Chevallier } 305778a36bfSGatien Chevallier 306778a36bfSGatien Chevallier return TEE_SUCCESS; 307778a36bfSGatien Chevallier } 308778a36bfSGatien Chevallier 309778a36bfSGatien Chevallier static TEE_Result __maybe_unused check_fmc_rif_conf(void) 310778a36bfSGatien Chevallier { 311778a36bfSGatien Chevallier unsigned int i = 0; 312778a36bfSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 313778a36bfSGatien Chevallier 314778a36bfSGatien Chevallier res = clk_enable(fmc_d->fmc_clock); 315778a36bfSGatien Chevallier if (res) 316778a36bfSGatien Chevallier panic("Cannot access FMC clock"); 317778a36bfSGatien Chevallier 318778a36bfSGatien Chevallier if (fmc_controller_is_secure(0)) 319778a36bfSGatien Chevallier goto end; 320778a36bfSGatien Chevallier 321778a36bfSGatien Chevallier for (i = 1; i < fmc_d->nb_controller; i++) { 322778a36bfSGatien Chevallier uint32_t cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i)); 323778a36bfSGatien Chevallier uint32_t semcr = io_read32(fmc_d->base + _FMC_SEMCR(i)); 324778a36bfSGatien Chevallier 325778a36bfSGatien Chevallier /* Check if a controller is secure */ 326778a36bfSGatien Chevallier if (fmc_controller_is_secure(i)) { 327778a36bfSGatien Chevallier res = TEE_ERROR_BAD_STATE; 328778a36bfSGatien Chevallier goto end; 329778a36bfSGatien Chevallier } 330778a36bfSGatien Chevallier 331778a36bfSGatien Chevallier /* 332778a36bfSGatien Chevallier * Check if a controller is shared with incorrect CID 333778a36bfSGatien Chevallier * (!= RIF_CID1) 334778a36bfSGatien Chevallier */ 335*5da989f3SGatien Chevallier res = stm32_rif_check_access(cidcfgr, semcr, MAX_CID_SUPPORTED, 336778a36bfSGatien Chevallier RIF_CID1); 337778a36bfSGatien Chevallier if (res) 338778a36bfSGatien Chevallier break; 339778a36bfSGatien Chevallier } 340778a36bfSGatien Chevallier 341778a36bfSGatien Chevallier end: 342778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 343778a36bfSGatien Chevallier 344778a36bfSGatien Chevallier return res; 345778a36bfSGatien Chevallier } 346778a36bfSGatien Chevallier 347778a36bfSGatien Chevallier static void configure_fmc(void) 348778a36bfSGatien Chevallier { 349778a36bfSGatien Chevallier uint32_t cidcfgr = 0; 350778a36bfSGatien Chevallier uint32_t semcr = 0; 351778a36bfSGatien Chevallier 352778a36bfSGatien Chevallier if (clk_enable(fmc_d->fmc_clock)) 353778a36bfSGatien Chevallier panic("Cannot access FMC clock"); 354778a36bfSGatien Chevallier 355778a36bfSGatien Chevallier semcr = io_read32(fmc_d->base + _FMC_SEMCR(0)); 356778a36bfSGatien Chevallier cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(0)); 357778a36bfSGatien Chevallier 358778a36bfSGatien Chevallier /* 359778a36bfSGatien Chevallier * If OP-TEE doesn't have access to the controller 0, 360778a36bfSGatien Chevallier * then we don't want to try to enable the FMC. 361778a36bfSGatien Chevallier */ 362*5da989f3SGatien Chevallier if (stm32_rif_check_access(cidcfgr, semcr, MAX_CID_SUPPORTED, RIF_CID1)) 363778a36bfSGatien Chevallier goto end; 364778a36bfSGatien Chevallier 365778a36bfSGatien Chevallier /* Check controller 0 access */ 366778a36bfSGatien Chevallier if (!fmc_controller_is_secure(0)) { 367778a36bfSGatien Chevallier DMSG("Controller 0 non-secure, FMC not enabled"); 368778a36bfSGatien Chevallier goto end; 369778a36bfSGatien Chevallier } 370778a36bfSGatien Chevallier 371778a36bfSGatien Chevallier if (cidcfgr & _CIDCFGR_SEMEN && 372778a36bfSGatien Chevallier stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(0), 373*5da989f3SGatien Chevallier MAX_CID_SUPPORTED)) 374778a36bfSGatien Chevallier panic("Couldn't acquire controller 0 semaphore"); 375778a36bfSGatien Chevallier 376778a36bfSGatien Chevallier if (fmc_d->pinctrl_d && pinctrl_apply_state(fmc_d->pinctrl_d)) 377778a36bfSGatien Chevallier panic("Could not apply FMC pinctrl"); 378778a36bfSGatien Chevallier 379778a36bfSGatien Chevallier if (fmc_d->cclken) { 380778a36bfSGatien Chevallier unsigned long hclk = clk_get_rate(fmc_d->fmc_clock); 381778a36bfSGatien Chevallier unsigned long hclkp = FMC_NSEC_PER_SEC / (hclk / 1000); 382778a36bfSGatien Chevallier unsigned long timing = DIV_ROUND_UP(fmc_d->clk_period_ns * 1000, 383778a36bfSGatien Chevallier hclkp); 384778a36bfSGatien Chevallier uint32_t clk_div = SHIFT_U32(1, _FMC_CFGR_CLKDIV_SHIFT); 385778a36bfSGatien Chevallier 386778a36bfSGatien Chevallier if (timing > 1) { 387778a36bfSGatien Chevallier timing--; 388778a36bfSGatien Chevallier if (timing > 389778a36bfSGatien Chevallier _FMC_CFGR_CLKDIV_MASK >> _FMC_CFGR_CLKDIV_SHIFT) 390778a36bfSGatien Chevallier clk_div = _FMC_CFGR_CLKDIV_MASK; 391778a36bfSGatien Chevallier else 392778a36bfSGatien Chevallier clk_div = SHIFT_U32(timing, 393778a36bfSGatien Chevallier _FMC_CFGR_CLKDIV_SHIFT); 394778a36bfSGatien Chevallier } 395778a36bfSGatien Chevallier 396778a36bfSGatien Chevallier io_clrsetbits32(fmc_d->base + _FMC_CFGR, 397778a36bfSGatien Chevallier _FMC_CFGR_CLKDIV_MASK | _FMC_CFGR_CCLKEN, 398778a36bfSGatien Chevallier clk_div | _FMC_CFGR_CCLKEN); 399778a36bfSGatien Chevallier } 400778a36bfSGatien Chevallier 401778a36bfSGatien Chevallier /* Set the FMC enable BIT */ 402778a36bfSGatien Chevallier io_setbits32(fmc_d->base + _FMC_CFGR, _FMC_CFGR_ENABLE); 403778a36bfSGatien Chevallier 404778a36bfSGatien Chevallier end: 405778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 406778a36bfSGatien Chevallier } 407778a36bfSGatien Chevallier 408778a36bfSGatien Chevallier static void fmc_setup(void) 409778a36bfSGatien Chevallier { 410778a36bfSGatien Chevallier if (apply_rif_config()) 411778a36bfSGatien Chevallier panic("Failed to apply rif_config"); 412778a36bfSGatien Chevallier 413778a36bfSGatien Chevallier /* Sanity check for FMC RIF config */ 414778a36bfSGatien Chevallier assert(check_fmc_rif_conf()); 415778a36bfSGatien Chevallier 416778a36bfSGatien Chevallier configure_fmc(); 417778a36bfSGatien Chevallier } 418778a36bfSGatien Chevallier 419778a36bfSGatien Chevallier static void fmc_suspend(void) 420778a36bfSGatien Chevallier { 421778a36bfSGatien Chevallier unsigned int i = 0; 422778a36bfSGatien Chevallier 423778a36bfSGatien Chevallier if (clk_enable(fmc_d->fmc_clock)) 424778a36bfSGatien Chevallier panic("Cannot access FMC clock"); 425778a36bfSGatien Chevallier 426778a36bfSGatien Chevallier if (fmc_controller_is_secure(0) && fmc_d->pinctrl_s && 427778a36bfSGatien Chevallier pinctrl_apply_state(fmc_d->pinctrl_s)) 428778a36bfSGatien Chevallier panic(); 429778a36bfSGatien Chevallier 430778a36bfSGatien Chevallier for (i = 0; i < FMC_RIF_CONTROLLERS; i++) 431b573873cSGatien Chevallier fmc_d->conf_data->cid_confs[i] = 432778a36bfSGatien Chevallier io_read32(fmc_d->base + _FMC_CIDCFGR(i)) & 433778a36bfSGatien Chevallier _FMC_CIDCFGR_CONF_MASK; 434778a36bfSGatien Chevallier 435b573873cSGatien Chevallier fmc_d->conf_data->priv_conf[0] = 436778a36bfSGatien Chevallier io_read32(fmc_d->base + _FMC_PRIVCFGR) & _FMC_PRIVCFGR_MASK; 437b573873cSGatien Chevallier fmc_d->conf_data->sec_conf[0] = 438778a36bfSGatien Chevallier io_read32(fmc_d->base + _FMC_SECCFGR) & _FMC_SECCFGR_MASK; 439b573873cSGatien Chevallier fmc_d->conf_data->lock_conf[0] = 440778a36bfSGatien Chevallier io_read32(fmc_d->base + _FMC_RCFGLOCKR) & _FMC_RCFGLOCKR_MASK; 441b573873cSGatien Chevallier fmc_d->conf_data->access_mask[0] = 442778a36bfSGatien Chevallier GENMASK_32(FMC_RIF_CONTROLLERS - 1, 0); 443778a36bfSGatien Chevallier 444778a36bfSGatien Chevallier clk_disable(fmc_d->fmc_clock); 445778a36bfSGatien Chevallier } 446778a36bfSGatien Chevallier 447778a36bfSGatien Chevallier static TEE_Result fmc_pm(enum pm_op op, unsigned int pm_hint, 448778a36bfSGatien Chevallier const struct pm_callback_handle *pm_handle __unused) 449778a36bfSGatien Chevallier { 450778a36bfSGatien Chevallier if (pm_hint != PM_HINT_CONTEXT_STATE) 451778a36bfSGatien Chevallier return TEE_SUCCESS; 452778a36bfSGatien Chevallier 453778a36bfSGatien Chevallier if (op == PM_OP_RESUME) 454778a36bfSGatien Chevallier fmc_setup(); 455778a36bfSGatien Chevallier else 456778a36bfSGatien Chevallier fmc_suspend(); 457778a36bfSGatien Chevallier 458778a36bfSGatien Chevallier return TEE_SUCCESS; 459778a36bfSGatien Chevallier } 460778a36bfSGatien Chevallier 461778a36bfSGatien Chevallier static TEE_Result fmc_probe(const void *fdt, int node, 462778a36bfSGatien Chevallier const void *compat_data __unused) 463778a36bfSGatien Chevallier { 464778a36bfSGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 465778a36bfSGatien Chevallier 466778a36bfSGatien Chevallier fmc_d = calloc(1, sizeof(*fmc_d)); 467778a36bfSGatien Chevallier if (!fmc_d) 468778a36bfSGatien Chevallier return TEE_ERROR_OUT_OF_MEMORY; 469778a36bfSGatien Chevallier 470*5da989f3SGatien Chevallier res = stm32_rifsc_check_tdcid(&fmc_d->is_tdcid); 471*5da989f3SGatien Chevallier if (res) { 472*5da989f3SGatien Chevallier free(fmc_d); 473*5da989f3SGatien Chevallier return res; 474*5da989f3SGatien Chevallier } 475*5da989f3SGatien Chevallier 476778a36bfSGatien Chevallier res = parse_dt(fdt, node); 477778a36bfSGatien Chevallier if (res) 478778a36bfSGatien Chevallier goto err; 479778a36bfSGatien Chevallier 480778a36bfSGatien Chevallier fmc_setup(); 481778a36bfSGatien Chevallier 482778a36bfSGatien Chevallier register_pm_core_service_cb(fmc_pm, NULL, "stm32-fmc"); 483778a36bfSGatien Chevallier 484778a36bfSGatien Chevallier return TEE_SUCCESS; 485778a36bfSGatien Chevallier err: 486778a36bfSGatien Chevallier /* Free all allocated resources */ 487b573873cSGatien Chevallier if (fmc_d->conf_data) { 488b573873cSGatien Chevallier free(fmc_d->conf_data->access_mask); 489b573873cSGatien Chevallier free(fmc_d->conf_data->cid_confs); 490b573873cSGatien Chevallier free(fmc_d->conf_data->priv_conf); 491b573873cSGatien Chevallier free(fmc_d->conf_data->sec_conf); 492b573873cSGatien Chevallier } 493b573873cSGatien Chevallier free(fmc_d->conf_data); 494778a36bfSGatien Chevallier free(fmc_d); 495778a36bfSGatien Chevallier 496778a36bfSGatien Chevallier return res; 497778a36bfSGatien Chevallier } 498778a36bfSGatien Chevallier 499778a36bfSGatien Chevallier static const struct dt_device_match stm32_fmc_match_table[] = { 500778a36bfSGatien Chevallier { .compatible = "st,stm32mp25-fmc2-ebi" }, 501778a36bfSGatien Chevallier { } 502778a36bfSGatien Chevallier }; 503778a36bfSGatien Chevallier 504778a36bfSGatien Chevallier DEFINE_DT_DRIVER(stm32_fmc_dt_driver) = { 505778a36bfSGatien Chevallier .name = "stm32_fmc", 506778a36bfSGatien Chevallier .match_table = stm32_fmc_match_table, 507778a36bfSGatien Chevallier .probe = fmc_probe, 508778a36bfSGatien Chevallier }; 509