169b8b983SEtienne Carriere // SPDX-License-Identifier: BSD-3-Clause 269b8b983SEtienne Carriere /* 369b8b983SEtienne Carriere * Copyright (c) 2021-2022, STMicroelectronics 469b8b983SEtienne Carriere */ 569b8b983SEtienne Carriere 669b8b983SEtienne Carriere #include <drivers/clk.h> 769b8b983SEtienne Carriere #include <drivers/clk_dt.h> 8*461e8793SGatien Chevallier #include <drivers/stm32_rif.h> 969b8b983SEtienne Carriere #include <drivers/stm32_tamp.h> 1069b8b983SEtienne Carriere #include <io.h> 1169b8b983SEtienne Carriere #include <kernel/dt.h> 129e3c57c8SEtienne Carriere #include <kernel/dt_driver.h> 1369b8b983SEtienne Carriere #include <kernel/interrupt.h> 1469b8b983SEtienne Carriere #include <libfdt.h> 1569b8b983SEtienne Carriere #include <mm/core_memprot.h> 1669b8b983SEtienne Carriere #include <stdbool.h> 1769b8b983SEtienne Carriere 1869b8b983SEtienne Carriere /* STM32 Registers */ 1969b8b983SEtienne Carriere #define _TAMP_CR1 0x00U 2069b8b983SEtienne Carriere #define _TAMP_CR2 0x04U 2169b8b983SEtienne Carriere #define _TAMP_CR3 0x08U 2269b8b983SEtienne Carriere #define _TAMP_FLTCR 0x0CU 2369b8b983SEtienne Carriere #define _TAMP_ATCR1 0x10U 2469b8b983SEtienne Carriere #define _TAMP_ATSEEDR 0x14U 2569b8b983SEtienne Carriere #define _TAMP_ATOR 0x18U 2669b8b983SEtienne Carriere #define _TAMP_ATCR2 0x1CU 2769b8b983SEtienne Carriere #define _TAMP_SECCFGR 0x20U 2869b8b983SEtienne Carriere #define _TAMP_SMCR 0x20U 2969b8b983SEtienne Carriere #define _TAMP_PRIVCFGR 0x24U 3069b8b983SEtienne Carriere #define _TAMP_IER 0x2CU 3169b8b983SEtienne Carriere #define _TAMP_SR 0x30U 3269b8b983SEtienne Carriere #define _TAMP_MISR 0x34U 3369b8b983SEtienne Carriere #define _TAMP_SMISR 0x38U 3469b8b983SEtienne Carriere #define _TAMP_SCR 0x3CU 3569b8b983SEtienne Carriere #define _TAMP_COUNTR 0x40U 3669b8b983SEtienne Carriere #define _TAMP_COUNT2R 0x44U 3769b8b983SEtienne Carriere #define _TAMP_OR 0x50U 3869b8b983SEtienne Carriere #define _TAMP_ERCFGR 0X54U 39*461e8793SGatien Chevallier #define _TAMP_BKPRIFR(x) (0x70U + 0x4U * ((x) - 1U)) 40*461e8793SGatien Chevallier #define _TAMP_CIDCFGR(x) (0x80U + 0x4U * (x)) 41*461e8793SGatien Chevallier #define _TAMP_BKPxR(x) (0x100U + 0x4U * ((x) - 1U)) 4269b8b983SEtienne Carriere #define _TAMP_HWCFGR2 0x3ECU 4369b8b983SEtienne Carriere #define _TAMP_HWCFGR1 0x3F0U 4469b8b983SEtienne Carriere #define _TAMP_VERR 0x3F4U 4569b8b983SEtienne Carriere #define _TAMP_IPIDR 0x3F8U 4669b8b983SEtienne Carriere #define _TAMP_SIDR 0x3FCU 4769b8b983SEtienne Carriere 4869b8b983SEtienne Carriere /* _TAMP_SECCFGR bit fields */ 4969b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_MASK GENMASK_32(7, 0) 5069b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_SHIFT 0U 5169b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT2SEC BIT(14) 52*461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT2SEC_SHIFT 14U 5369b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT1SEC BIT(15) 54*461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT1SEC_SHIFT 15U 5569b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_MASK GENMASK_32(23, 16) 5669b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_SHIFT 16U 5769b8b983SEtienne Carriere #define _TAMP_SECCFGR_BHKLOCK BIT(30) 5869b8b983SEtienne Carriere #define _TAMP_SECCFGR_TAMPSEC BIT(31) 59*461e8793SGatien Chevallier #define _TAMP_SECCFGR_TAMPSEC_SHIFT 31U 6069b8b983SEtienne Carriere #define _TAMP_SECCFGR_BUT_BKP_MASK (GENMASK_32(31, 30) | \ 6169b8b983SEtienne Carriere GENMASK_32(15, 14)) 62*461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_TAMP_SEC BIT(0) 63*461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_1 BIT(1) 64*461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_2 BIT(2) 6569b8b983SEtienne Carriere 6669b8b983SEtienne Carriere /* _TAMP_SMCR bit fields */ 6769b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK_32(7, 0) 6869b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_SHIFT 0U 6969b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_MASK GENMASK_32(23, 16) 7069b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_SHIFT 16U 7169b8b983SEtienne Carriere #define _TAMP_SMCR_DPROT BIT(31) 7269b8b983SEtienne Carriere /* 7369b8b983SEtienne Carriere * _TAMP_PRIVCFGR bit fields 7469b8b983SEtienne Carriere */ 7569b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV BIT(14) 7669b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV BIT(15) 7769b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) 7869b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV BIT(30) 7969b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV BIT(31) 8069b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ 8169b8b983SEtienne Carriere GENMASK_32(15, 14)) 82*461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_TAMP_PRIV BIT(0) 83*461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R1 BIT(1) 84*461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R2 BIT(2) 8569b8b983SEtienne Carriere 8669b8b983SEtienne Carriere /* 8769b8b983SEtienne Carriere * _TAMP_PRIVCFGR bit fields 8869b8b983SEtienne Carriere */ 8969b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV BIT(14) 9069b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV BIT(15) 9169b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) 9269b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV BIT(30) 9369b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV BIT(31) 9469b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ 9569b8b983SEtienne Carriere GENMASK_32(15, 14)) 9669b8b983SEtienne Carriere 9769b8b983SEtienne Carriere /* _TAMP_HWCFGR2 bit fields */ 9869b8b983SEtienne Carriere #define _TAMP_HWCFGR2_TZ GENMASK_32(11, 8) 9969b8b983SEtienne Carriere #define _TAMP_HWCFGR2_OR GENMASK_32(7, 0) 10069b8b983SEtienne Carriere 10169b8b983SEtienne Carriere /* _TAMP_HWCFGR1 bit fields */ 10269b8b983SEtienne Carriere #define _TAMP_HWCFGR1_BKPREG GENMASK_32(7, 0) 10369b8b983SEtienne Carriere #define _TAMP_HWCFGR1_TAMPER GENMASK_32(11, 8) 10469b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ACTIVE GENMASK_32(15, 12) 10569b8b983SEtienne Carriere #define _TAMP_HWCFGR1_INTERN GENMASK_32(31, 16) 10669b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U 10769b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP(id) BIT((id) - INT_TAMP1 + 16U) 10869b8b983SEtienne Carriere 10969b8b983SEtienne Carriere /* _TAMP_VERR bit fields */ 11069b8b983SEtienne Carriere #define _TAMP_VERR_MINREV GENMASK_32(3, 0) 11169b8b983SEtienne Carriere #define _TAMP_VERR_MAJREV GENMASK_32(7, 4) 11269b8b983SEtienne Carriere 11369b8b983SEtienne Carriere /* 114*461e8793SGatien Chevallier * CIDCFGR register bitfields 11569b8b983SEtienne Carriere */ 116*461e8793SGatien Chevallier #define _TAMP_CIDCFGR_SCID_MASK GENMASK_32(6, 4) 117*461e8793SGatien Chevallier #define _TAMP_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ 118*461e8793SGatien Chevallier _CIDCFGR_SEMEN | \ 119*461e8793SGatien Chevallier _TAMP_CIDCFGR_SCID_MASK) 120*461e8793SGatien Chevallier 121*461e8793SGatien Chevallier /* _TAMP_BKPRIFR */ 122*461e8793SGatien Chevallier #define _TAMP_BKPRIFR_1_MASK GENMASK_32(7, 0) 123*461e8793SGatien Chevallier #define _TAMP_BKPRIFR_2_MASK GENMASK_32(7, 0) 124*461e8793SGatien Chevallier #define _TAMP_BKPRIFR_3_MASK (GENMASK_32(23, 16) | GENMASK_32(7, 0)) 125*461e8793SGatien Chevallier #define _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT 16U 126*461e8793SGatien Chevallier 127*461e8793SGatien Chevallier /* 128*461e8793SGatien Chevallier * RIF miscellaneous 129*461e8793SGatien Chevallier */ 130*461e8793SGatien Chevallier #define TAMP_NB_BKPR_ZONES 3U 131*461e8793SGatien Chevallier #define TAMP_RIF_RESOURCES 3U 132*461e8793SGatien Chevallier #define TAMP_RIF_OFFSET_CNT 4U 13369b8b983SEtienne Carriere 13469b8b983SEtienne Carriere /* 13569b8b983SEtienne Carriere * Compatibility capabilities 136*461e8793SGatien Chevallier * TAMP_HAS_REGISTER_SECCFGR - Supports SECCFGR, otherwise supports SMCR 137*461e8793SGatien Chevallier * register 13869b8b983SEtienne Carriere * TAMP_HAS_REGISTER_PRIVCFG - Supports PRIVCFGR configuration register 139*461e8793SGatien Chevallier * TAMP_HAS_RIF_SUPPORT - Supports RIF 14069b8b983SEtienne Carriere */ 141*461e8793SGatien Chevallier #define TAMP_HAS_REGISTER_SECCFGR BIT(0) 14269b8b983SEtienne Carriere #define TAMP_HAS_REGISTER_PRIVCFGR BIT(1) 143*461e8793SGatien Chevallier #define TAMP_HAS_RIF_SUPPORT BIT(31) 14469b8b983SEtienne Carriere 145*461e8793SGatien Chevallier /** 146*461e8793SGatien Chevallier * struct stm32_tamp_compat - TAMP compatible data 147*461e8793SGatien Chevallier * @nb_monotonic_counter: Number of monotic counter supported 148*461e8793SGatien Chevallier * @tags: Bit flags TAMP_HAS_* for compatibility management 14969b8b983SEtienne Carriere */ 15069b8b983SEtienne Carriere struct stm32_tamp_compat { 15169b8b983SEtienne Carriere int nb_monotonic_counter; 15269b8b983SEtienne Carriere uint32_t tags; 15369b8b983SEtienne Carriere }; 15469b8b983SEtienne Carriere 155*461e8793SGatien Chevallier /* 156*461e8793SGatien Chevallier * struct stm32_bkpregs_conf_new - Backup registers zone bounds 157*461e8793SGatien Chevallier * @zone1_end - Number of backup registers in zone 1 158*461e8793SGatien Chevallier * @zone2_end - Number of backup registers in zone 2 + zone 1 159*461e8793SGatien Chevallier * @rif_offsets - RIF offsets used for CID compartments 160*461e8793SGatien Chevallier * 161*461e8793SGatien Chevallier * TAMP backup registers access permissions 162*461e8793SGatien Chevallier * 163*461e8793SGatien Chevallier * Zone 1: read/write in secure state, no access in non-secure state 164*461e8793SGatien Chevallier * Zone 2: read/write in secure state, read-only in non-secure state 165*461e8793SGatien Chevallier * Zone 3: read/write in secure state, read/write in non-secure state 166*461e8793SGatien Chevallier * 167*461e8793SGatien Chevallier * Protection zone 1 168*461e8793SGatien Chevallier * If zone1_end == 0 no backup register are in zone 1. 169*461e8793SGatien Chevallier * Otherwise backup registers from TAMP_BKP0R to TAMP_BKP<x>R are in zone 1, 170*461e8793SGatien Chevallier * with <x> = (@zone1_end - 1). 171*461e8793SGatien Chevallier * 172*461e8793SGatien Chevallier * Protection zone 2 173*461e8793SGatien Chevallier * If zone2_end == 0 no backup register are in zone 2 and zone 1. 174*461e8793SGatien Chevallier * Otherwise backup registers from TAMP_BKP<y>R to TAMP_BKP<z>R are in zone 2, 175*461e8793SGatien Chevallier * with <y> = @zone1_end and <z> = (@zone2_end - 1). 176*461e8793SGatien Chevallier * 177*461e8793SGatien Chevallier * Protection zone 3 178*461e8793SGatien Chevallier * Backup registers from TAMP_BKP<t>R to last backup register are in zone 3, 179*461e8793SGatien Chevallier * with <t> = (@zone2_end - 1). 180*461e8793SGatien Chevallier * 181*461e8793SGatien Chevallier * When RIF is supported, each zone can be subdivided to restrain accesses to 182*461e8793SGatien Chevallier * some CIDs. 183*461e8793SGatien Chevallier */ 184*461e8793SGatien Chevallier struct stm32_bkpregs_conf_new { 185*461e8793SGatien Chevallier uint32_t zone1_end; 186*461e8793SGatien Chevallier uint32_t zone2_end; 187*461e8793SGatien Chevallier uint32_t *rif_offsets; 188*461e8793SGatien Chevallier }; 189*461e8793SGatien Chevallier 190*461e8793SGatien Chevallier /** 191*461e8793SGatien Chevallier * struct stm32_tamp_platdata - TAMP platform data 192*461e8793SGatien Chevallier * @base: IOMEM base address 193*461e8793SGatien Chevallier * @bkpregs_conf: TAMP backup register configuration reference 194*461e8793SGatien Chevallier * @compat: Reference to compat data passed at driver initialization 195*461e8793SGatien Chevallier * @conf_data: RIF configuration data 196*461e8793SGatien Chevallier * @clock: TAMP clock 197*461e8793SGatien Chevallier * @nb_rif_resources: Number of RIF resources 198*461e8793SGatien Chevallier * @it: TAMP interrupt number 199*461e8793SGatien Chevallier * @is_tdcid: True if current processor is TDCID 200*461e8793SGatien Chevallier */ 201*461e8793SGatien Chevallier struct stm32_tamp_platdata { 202*461e8793SGatien Chevallier struct io_pa_va base; 203*461e8793SGatien Chevallier struct stm32_bkpregs_conf_new bkpregs_conf; 204*461e8793SGatien Chevallier struct stm32_tamp_compat *compat; 205*461e8793SGatien Chevallier struct rif_conf_data *conf_data; 206*461e8793SGatien Chevallier struct clk *clock; 207*461e8793SGatien Chevallier unsigned int nb_rif_resources; 208*461e8793SGatien Chevallier int it; 209*461e8793SGatien Chevallier bool is_tdcid; 210*461e8793SGatien Chevallier }; 211*461e8793SGatien Chevallier 212*461e8793SGatien Chevallier /** 213*461e8793SGatien Chevallier * struct stm32_tamp_instance - TAMP instance data 214*461e8793SGatien Chevallier * @pdata: TAMP platform data 215*461e8793SGatien Chevallier * @hwconf1: Copy of TAMP HWCONF1 register content 216*461e8793SGatien Chevallier * @hwconf2: Copy of TAMP HWCONF2 register content 217*461e8793SGatien Chevallier */ 218*461e8793SGatien Chevallier struct stm32_tamp_instance { 219*461e8793SGatien Chevallier struct stm32_tamp_platdata pdata; 220*461e8793SGatien Chevallier uint32_t hwconf1; 221*461e8793SGatien Chevallier uint32_t hwconf2; 222*461e8793SGatien Chevallier }; 223*461e8793SGatien Chevallier 22469b8b983SEtienne Carriere /* Expects at most a single instance */ 225*461e8793SGatien Chevallier static struct stm32_tamp_instance *stm32_tamp_dev; 226*461e8793SGatien Chevallier 227*461e8793SGatien Chevallier static void apply_rif_config(void) 228*461e8793SGatien Chevallier { 229*461e8793SGatien Chevallier struct rif_conf_data *rif_conf = stm32_tamp_dev->pdata.conf_data; 230*461e8793SGatien Chevallier vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 231*461e8793SGatien Chevallier uint32_t access_mask_priv_reg = 0; 232*461e8793SGatien Chevallier uint32_t access_mask_sec_reg = 0; 233*461e8793SGatien Chevallier uint32_t privcfgr = 0; 234*461e8793SGatien Chevallier uint32_t seccfgr = 0; 235*461e8793SGatien Chevallier unsigned int i = 0; 236*461e8793SGatien Chevallier 237*461e8793SGatien Chevallier if (!stm32_tamp_dev->pdata.conf_data) 238*461e8793SGatien Chevallier return; 239*461e8793SGatien Chevallier 240*461e8793SGatien Chevallier /* Build access masks for _TAMP_PRIVCFGR and _TAMP_SECCFGR */ 241*461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) { 242*461e8793SGatien Chevallier if (BIT(i) & rif_conf->access_mask[0]) { 243*461e8793SGatien Chevallier switch (i) { 244*461e8793SGatien Chevallier case 0: 245*461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_TAMPSEC; 246*461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_TAMPPRIV; 247*461e8793SGatien Chevallier break; 248*461e8793SGatien Chevallier case 1: 249*461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_CNT1SEC; 250*461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_CNT1PRIV; 251*461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_BKPRWPRIV; 252*461e8793SGatien Chevallier break; 253*461e8793SGatien Chevallier case 2: 254*461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_CNT2SEC; 255*461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_CNT2PRIV; 256*461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_BKPWPRIV; 257*461e8793SGatien Chevallier break; 258*461e8793SGatien Chevallier default: 259*461e8793SGatien Chevallier panic(); 260*461e8793SGatien Chevallier } 261*461e8793SGatien Chevallier } 262*461e8793SGatien Chevallier } 263*461e8793SGatien Chevallier 264*461e8793SGatien Chevallier /* 265*461e8793SGatien Chevallier * When TDCID, OP-TEE should be the one to set the CID filtering 266*461e8793SGatien Chevallier * configuration. Clearing previous configuration prevents 267*461e8793SGatien Chevallier * undesired events during the only legitimate configuration. 268*461e8793SGatien Chevallier */ 269*461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.is_tdcid) { 270*461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) 271*461e8793SGatien Chevallier if (BIT(i) & rif_conf->access_mask[0]) 272*461e8793SGatien Chevallier io_clrbits32(base + _TAMP_CIDCFGR(i), 273*461e8793SGatien Chevallier _TAMP_CIDCFGR_CONF_MASK); 274*461e8793SGatien Chevallier } 275*461e8793SGatien Chevallier 276*461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_TAMP_SEC) 277*461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_TAMPSEC; 278*461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_1) 279*461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_CNT1SEC; 280*461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_2) 281*461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_CNT2SEC; 282*461e8793SGatien Chevallier 283*461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_TAMP_PRIV) 284*461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_TAMPPRIV; 285*461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R1) 286*461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_CNT1PRIV | _TAMP_PRIVCFG_BKPRWPRIV; 287*461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R2) 288*461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_CNT2PRIV | _TAMP_PRIVCFG_BKPWPRIV; 289*461e8793SGatien Chevallier 290*461e8793SGatien Chevallier /* Security and privilege RIF configuration */ 291*461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_PRIVCFGR, access_mask_priv_reg, privcfgr); 292*461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_SECCFGR, access_mask_sec_reg, seccfgr); 293*461e8793SGatien Chevallier 294*461e8793SGatien Chevallier if (!stm32_tamp_dev->pdata.is_tdcid) 295*461e8793SGatien Chevallier return; 296*461e8793SGatien Chevallier 297*461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) { 298*461e8793SGatien Chevallier if (!(BIT(i) & rif_conf->access_mask[0])) 299*461e8793SGatien Chevallier continue; 300*461e8793SGatien Chevallier 301*461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_CIDCFGR(i), 302*461e8793SGatien Chevallier _TAMP_CIDCFGR_CONF_MASK, 303*461e8793SGatien Chevallier rif_conf->cid_confs[i]); 304*461e8793SGatien Chevallier } 305*461e8793SGatien Chevallier } 306*461e8793SGatien Chevallier 307*461e8793SGatien Chevallier static TEE_Result stm32_tamp_apply_bkpr_rif_conf(void) 308*461e8793SGatien Chevallier { 309*461e8793SGatien Chevallier struct stm32_bkpregs_conf_new *bkpregs_conf = 310*461e8793SGatien Chevallier &stm32_tamp_dev->pdata.bkpregs_conf; 311*461e8793SGatien Chevallier vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 312*461e8793SGatien Chevallier unsigned int i = 0; 313*461e8793SGatien Chevallier 314*461e8793SGatien Chevallier if (!bkpregs_conf->rif_offsets) 315*461e8793SGatien Chevallier panic("No backup register configuration"); 316*461e8793SGatien Chevallier 317*461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_OFFSET_CNT; i++) { 318*461e8793SGatien Chevallier if (bkpregs_conf->rif_offsets[i] > 319*461e8793SGatien Chevallier (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) 320*461e8793SGatien Chevallier return TEE_ERROR_NOT_SUPPORTED; 321*461e8793SGatien Chevallier } 322*461e8793SGatien Chevallier 323*461e8793SGatien Chevallier /* Fill the 3 TAMP_BKPRIFRx registers */ 324*461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(1), _TAMP_BKPRIFR_1_MASK, 325*461e8793SGatien Chevallier bkpregs_conf->rif_offsets[0]); 326*461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(2), _TAMP_BKPRIFR_2_MASK, 327*461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1]); 328*461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(3), _TAMP_BKPRIFR_3_MASK, 329*461e8793SGatien Chevallier bkpregs_conf->rif_offsets[2] | 330*461e8793SGatien Chevallier SHIFT_U32(bkpregs_conf->rif_offsets[3], 331*461e8793SGatien Chevallier _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT)); 332*461e8793SGatien Chevallier 333*461e8793SGatien Chevallier DMSG("Backup registers mapping :"); 334*461e8793SGatien Chevallier DMSG("********START of zone 1********"); 335*461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF1 begins at register: 0"); 336*461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF2 begins at register: %"PRIu32, 337*461e8793SGatien Chevallier bkpregs_conf->rif_offsets[0]); 338*461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF2 ends at register: %"PRIu32, 339*461e8793SGatien Chevallier bkpregs_conf->zone1_end ? bkpregs_conf->zone1_end - 1 : 0); 340*461e8793SGatien Chevallier DMSG("********END of zone 1********"); 341*461e8793SGatien Chevallier DMSG("********START of zone 2********"); 342*461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF1 begins at register: %"PRIu32, 343*461e8793SGatien Chevallier bkpregs_conf->zone1_end); 344*461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF2 begins at register: %"PRIu32, 345*461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1]); 346*461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF2 ends at register: %"PRIu32, 347*461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1] > bkpregs_conf->zone1_end ? 348*461e8793SGatien Chevallier bkpregs_conf->zone2_end - 1 : 0); 349*461e8793SGatien Chevallier DMSG("********END of zone 2********"); 350*461e8793SGatien Chevallier DMSG("********START of zone 3********"); 351*461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF1 begins at register: %"PRIu32, 352*461e8793SGatien Chevallier bkpregs_conf->zone2_end); 353*461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF0 begins at register: %"PRIu32, 354*461e8793SGatien Chevallier bkpregs_conf->rif_offsets[2]); 355*461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF2 begins at register: %"PRIu32, 356*461e8793SGatien Chevallier bkpregs_conf->rif_offsets[3]); 357*461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF2 ends at the last register: %"PRIu32, 358*461e8793SGatien Chevallier stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG); 359*461e8793SGatien Chevallier DMSG("********END of zone 3********"); 360*461e8793SGatien Chevallier 361*461e8793SGatien Chevallier return TEE_SUCCESS; 362*461e8793SGatien Chevallier } 36369b8b983SEtienne Carriere 36469b8b983SEtienne Carriere TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *bkr_conf) 36569b8b983SEtienne Carriere { 366*461e8793SGatien Chevallier struct stm32_tamp_instance *tamp = stm32_tamp_dev; 36769b8b983SEtienne Carriere vaddr_t base = 0; 36869b8b983SEtienne Carriere uint32_t first_z2 = 0; 36969b8b983SEtienne Carriere uint32_t first_z3 = 0; 37069b8b983SEtienne Carriere 37169b8b983SEtienne Carriere if (!tamp) 37269b8b983SEtienne Carriere return TEE_ERROR_DEFER_DRIVER_INIT; 37369b8b983SEtienne Carriere 37469b8b983SEtienne Carriere if (!bkr_conf) 37569b8b983SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 37669b8b983SEtienne Carriere 377*461e8793SGatien Chevallier base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 37869b8b983SEtienne Carriere 37969b8b983SEtienne Carriere first_z2 = bkr_conf->nb_zone1_regs; 38069b8b983SEtienne Carriere first_z3 = bkr_conf->nb_zone1_regs + bkr_conf->nb_zone2_regs; 38169b8b983SEtienne Carriere 382*461e8793SGatien Chevallier if ((first_z2 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) || 383*461e8793SGatien Chevallier (first_z3 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG))) 38469b8b983SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 38569b8b983SEtienne Carriere 386*461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 387*461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) { 38869b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 38969b8b983SEtienne Carriere _TAMP_SECCFGR_BKPRWSEC_MASK, 39069b8b983SEtienne Carriere (first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) & 39169b8b983SEtienne Carriere _TAMP_SECCFGR_BKPRWSEC_MASK); 39269b8b983SEtienne Carriere 39369b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 39469b8b983SEtienne Carriere _TAMP_SECCFGR_BKPWSEC_MASK, 39569b8b983SEtienne Carriere (first_z3 << _TAMP_SECCFGR_BKPWSEC_SHIFT) & 39669b8b983SEtienne Carriere _TAMP_SECCFGR_BKPWSEC_MASK); 39769b8b983SEtienne Carriere } else { 39869b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SMCR, 39969b8b983SEtienne Carriere _TAMP_SMCR_BKPRWDPROT_MASK, 40069b8b983SEtienne Carriere (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) & 40169b8b983SEtienne Carriere _TAMP_SMCR_BKPRWDPROT_MASK); 40269b8b983SEtienne Carriere 40369b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SMCR, 40469b8b983SEtienne Carriere _TAMP_SMCR_BKPWDPROT_MASK, 40569b8b983SEtienne Carriere (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) & 40669b8b983SEtienne Carriere _TAMP_SMCR_BKPWDPROT_MASK); 40769b8b983SEtienne Carriere } 40869b8b983SEtienne Carriere 40969b8b983SEtienne Carriere return TEE_SUCCESS; 41069b8b983SEtienne Carriere } 41169b8b983SEtienne Carriere 412*461e8793SGatien Chevallier static void stm32_tamp_set_secure(uint32_t mode) 41369b8b983SEtienne Carriere { 414*461e8793SGatien Chevallier vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 41569b8b983SEtienne Carriere 416*461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 417*461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) { 41869b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 41969b8b983SEtienne Carriere _TAMP_SECCFGR_BUT_BKP_MASK, 42069b8b983SEtienne Carriere mode & _TAMP_SECCFGR_BUT_BKP_MASK); 42169b8b983SEtienne Carriere } else { 42269b8b983SEtienne Carriere /* 42369b8b983SEtienne Carriere * Note: MP15 doesn't use SECCFG register and 42469b8b983SEtienne Carriere * inverts the secure bit. 42569b8b983SEtienne Carriere */ 42669b8b983SEtienne Carriere if (mode & _TAMP_SECCFGR_TAMPSEC) 42769b8b983SEtienne Carriere io_clrbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); 42869b8b983SEtienne Carriere else 42969b8b983SEtienne Carriere io_setbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); 43069b8b983SEtienne Carriere } 43169b8b983SEtienne Carriere } 43269b8b983SEtienne Carriere 433*461e8793SGatien Chevallier static void stm32_tamp_set_privilege(uint32_t mode) 43469b8b983SEtienne Carriere { 435*461e8793SGatien Chevallier vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 43669b8b983SEtienne Carriere 437*461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 438*461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_PRIVCFGR)) 43969b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK, 44069b8b983SEtienne Carriere mode & _TAMP_PRIVCFGR_MASK); 44169b8b983SEtienne Carriere } 44269b8b983SEtienne Carriere 443*461e8793SGatien Chevallier static void parse_bkpregs_dt_conf(const void *fdt, int node, 444*461e8793SGatien Chevallier struct stm32_tamp_platdata *pdata) 445*461e8793SGatien Chevallier { 446*461e8793SGatien Chevallier const fdt32_t *cuint = NULL; 447*461e8793SGatien Chevallier unsigned int bkpregs_count = 0; 448*461e8793SGatien Chevallier int lenp = 0; 449*461e8793SGatien Chevallier 450*461e8793SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,backup-zones", &lenp); 451*461e8793SGatien Chevallier if (!cuint) 452*461e8793SGatien Chevallier panic("Missing backup registers configuration"); 453*461e8793SGatien Chevallier 454*461e8793SGatien Chevallier /* 455*461e8793SGatien Chevallier * When TAMP does not support RIF, the backup registers can 456*461e8793SGatien Chevallier * be splited in 3 zones. These zones have specific read/write 457*461e8793SGatien Chevallier * access permissions based on the secure status of the accesser. 458*461e8793SGatien Chevallier * When RIF is supported, these zones can additionally be splited 459*461e8793SGatien Chevallier * in subzones that have CID filtering. Zones/Subzones can be empty and 460*461e8793SGatien Chevallier * are contiguous. 461*461e8793SGatien Chevallier */ 462*461e8793SGatien Chevallier if (!(stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT)) { 463*461e8793SGatien Chevallier /* 3 zones, 2 offsets to apply */ 464*461e8793SGatien Chevallier if (lenp != sizeof(uint32_t) * TAMP_NB_BKPR_ZONES) 465*461e8793SGatien Chevallier panic("Incorrect bkpregs configuration"); 466*461e8793SGatien Chevallier 467*461e8793SGatien Chevallier pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]); 468*461e8793SGatien Chevallier bkpregs_count = fdt32_to_cpu(cuint[0]); 469*461e8793SGatien Chevallier 470*461e8793SGatien Chevallier pdata->bkpregs_conf.zone2_end = bkpregs_count + 471*461e8793SGatien Chevallier fdt32_to_cpu(cuint[1]); 472*461e8793SGatien Chevallier } else { 473*461e8793SGatien Chevallier /* 474*461e8793SGatien Chevallier * Zone 3 475*461e8793SGatien Chevallier * ----------------------| 476*461e8793SGatien Chevallier * Protection Zone 3-RIF2|Read non- 477*461e8793SGatien Chevallier * ----------------------|secure 478*461e8793SGatien Chevallier * Protection Zone 3-RIF0|Write non- 479*461e8793SGatien Chevallier * ----------------------|secure 480*461e8793SGatien Chevallier * Protection Zone 3-RIF1| 481*461e8793SGatien Chevallier * ----------------------| 482*461e8793SGatien Chevallier * 483*461e8793SGatien Chevallier * Zone 2 484*461e8793SGatien Chevallier * ----------------------| 485*461e8793SGatien Chevallier * Protection Zone 2-RIF2|Read non- 486*461e8793SGatien Chevallier * ----------------------|secure 487*461e8793SGatien Chevallier * Protection Zone 2-RIF1|Write secure 488*461e8793SGatien Chevallier * ----------------------| 489*461e8793SGatien Chevallier * 490*461e8793SGatien Chevallier * Zone 1 491*461e8793SGatien Chevallier * ----------------------| 492*461e8793SGatien Chevallier * Protection Zone 1-RIF2|Read secure 493*461e8793SGatien Chevallier * ----------------------|Write secure 494*461e8793SGatien Chevallier * Protection Zone 1-RIF1| 495*461e8793SGatien Chevallier * ----------------------| 496*461e8793SGatien Chevallier * 497*461e8793SGatien Chevallier * (BHK => First 8 registers) 498*461e8793SGatien Chevallier */ 499*461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets = calloc(TAMP_RIF_OFFSET_CNT, 500*461e8793SGatien Chevallier sizeof(uint32_t)); 501*461e8793SGatien Chevallier if (!pdata->bkpregs_conf.rif_offsets) 502*461e8793SGatien Chevallier panic(); 503*461e8793SGatien Chevallier 504*461e8793SGatien Chevallier /* 505*461e8793SGatien Chevallier * 3 zones with 7 subzones in total(6 offsets): 506*461e8793SGatien Chevallier * - 2 zone offsets 507*461e8793SGatien Chevallier * - 4 subzones offsets 508*461e8793SGatien Chevallier */ 509*461e8793SGatien Chevallier if (lenp != sizeof(uint32_t) * 510*461e8793SGatien Chevallier (TAMP_RIF_OFFSET_CNT + TAMP_NB_BKPR_ZONES)) 511*461e8793SGatien Chevallier panic("Incorrect bkpregs configuration"); 512*461e8793SGatien Chevallier 513*461e8793SGatien Chevallier /* Backup registers zone 1 */ 514*461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[0] = fdt32_to_cpu(cuint[0]); 515*461e8793SGatien Chevallier pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]) + 516*461e8793SGatien Chevallier fdt32_to_cpu(cuint[1]); 517*461e8793SGatien Chevallier 518*461e8793SGatien Chevallier bkpregs_count = pdata->bkpregs_conf.zone1_end; 519*461e8793SGatien Chevallier 520*461e8793SGatien Chevallier /* Backup registers zone 2 */ 521*461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[1] = bkpregs_count + 522*461e8793SGatien Chevallier fdt32_to_cpu(cuint[2]); 523*461e8793SGatien Chevallier pdata->bkpregs_conf.zone2_end = bkpregs_count + 524*461e8793SGatien Chevallier fdt32_to_cpu(cuint[2]) + 525*461e8793SGatien Chevallier fdt32_to_cpu(cuint[3]); 526*461e8793SGatien Chevallier 527*461e8793SGatien Chevallier bkpregs_count = pdata->bkpregs_conf.zone2_end; 528*461e8793SGatien Chevallier 529*461e8793SGatien Chevallier /* Backup registers zone 3 */ 530*461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[2] = bkpregs_count + 531*461e8793SGatien Chevallier fdt32_to_cpu(cuint[4]); 532*461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[3] = bkpregs_count + 533*461e8793SGatien Chevallier fdt32_to_cpu(cuint[4]) + 534*461e8793SGatien Chevallier fdt32_to_cpu(cuint[5]); 535*461e8793SGatien Chevallier } 536*461e8793SGatien Chevallier } 537*461e8793SGatien Chevallier 538*461e8793SGatien Chevallier static TEE_Result stm32_tamp_parse_fdt(const void *fdt, int node, 53969b8b983SEtienne Carriere const void *compat) 54069b8b983SEtienne Carriere { 541*461e8793SGatien Chevallier struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata; 542*461e8793SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 54369b8b983SEtienne Carriere struct dt_node_info dt_tamp = { }; 54469b8b983SEtienne Carriere 545f354a5d8SGatien Chevallier fdt_fill_device_info(fdt, &dt_tamp, node); 54669b8b983SEtienne Carriere 54769b8b983SEtienne Carriere if (dt_tamp.reg == DT_INFO_INVALID_REG || 54869b8b983SEtienne Carriere dt_tamp.reg_size == DT_INFO_INVALID_REG_SIZE) 54969b8b983SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 55069b8b983SEtienne Carriere 551*461e8793SGatien Chevallier pdata->compat = (struct stm32_tamp_compat *)compat; 552*461e8793SGatien Chevallier pdata->it = dt_tamp.interrupt; 553*461e8793SGatien Chevallier pdata->base.pa = dt_tamp.reg; 554*461e8793SGatien Chevallier io_pa_or_va_secure(&pdata->base, dt_tamp.reg_size); 55569b8b983SEtienne Carriere 556*461e8793SGatien Chevallier res = clk_dt_get_by_index(fdt, node, 0, &pdata->clock); 557*461e8793SGatien Chevallier if (res) 558*461e8793SGatien Chevallier return res; 559*461e8793SGatien Chevallier 560*461e8793SGatien Chevallier parse_bkpregs_dt_conf(fdt, node, pdata); 561*461e8793SGatien Chevallier 562*461e8793SGatien Chevallier if (pdata->compat->tags & TAMP_HAS_RIF_SUPPORT) { 563*461e8793SGatien Chevallier const fdt32_t *cuint = NULL; 564*461e8793SGatien Chevallier unsigned int i = 0; 565*461e8793SGatien Chevallier int lenp = 0; 566*461e8793SGatien Chevallier 567*461e8793SGatien Chevallier res = stm32_rifsc_check_tdcid(&pdata->is_tdcid); 568*461e8793SGatien Chevallier if (res) 569*461e8793SGatien Chevallier return res; 570*461e8793SGatien Chevallier 571*461e8793SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); 572*461e8793SGatien Chevallier if (!cuint) { 573*461e8793SGatien Chevallier DMSG("No RIF configuration available"); 574*461e8793SGatien Chevallier return TEE_SUCCESS; 575*461e8793SGatien Chevallier } 576*461e8793SGatien Chevallier 577*461e8793SGatien Chevallier pdata->conf_data = calloc(1, sizeof(*pdata->conf_data)); 578*461e8793SGatien Chevallier if (!pdata->conf_data) 579*461e8793SGatien Chevallier panic(); 580*461e8793SGatien Chevallier 581*461e8793SGatien Chevallier pdata->nb_rif_resources = (unsigned int)(lenp / 582*461e8793SGatien Chevallier sizeof(uint32_t)); 583*461e8793SGatien Chevallier assert(pdata->nb_rif_resources <= TAMP_RIF_RESOURCES); 584*461e8793SGatien Chevallier 585*461e8793SGatien Chevallier pdata->conf_data->cid_confs = calloc(TAMP_RIF_RESOURCES, 586*461e8793SGatien Chevallier sizeof(uint32_t)); 587*461e8793SGatien Chevallier pdata->conf_data->sec_conf = calloc(1, sizeof(uint32_t)); 588*461e8793SGatien Chevallier pdata->conf_data->priv_conf = calloc(1, sizeof(uint32_t)); 589*461e8793SGatien Chevallier pdata->conf_data->access_mask = calloc(1, sizeof(uint32_t)); 590*461e8793SGatien Chevallier if (!pdata->conf_data->cid_confs || 591*461e8793SGatien Chevallier !pdata->conf_data->sec_conf || 592*461e8793SGatien Chevallier !pdata->conf_data->priv_conf || 593*461e8793SGatien Chevallier !pdata->conf_data->access_mask) 594*461e8793SGatien Chevallier panic("Not enough memory capacity for TAMP RIF config"); 595*461e8793SGatien Chevallier 596*461e8793SGatien Chevallier for (i = 0; i < pdata->nb_rif_resources; i++) 597*461e8793SGatien Chevallier stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), 598*461e8793SGatien Chevallier pdata->conf_data, 599*461e8793SGatien Chevallier TAMP_RIF_RESOURCES); 600*461e8793SGatien Chevallier } 601*461e8793SGatien Chevallier 602*461e8793SGatien Chevallier return TEE_SUCCESS; 60369b8b983SEtienne Carriere } 60469b8b983SEtienne Carriere 60569b8b983SEtienne Carriere static TEE_Result stm32_tamp_probe(const void *fdt, int node, 60669b8b983SEtienne Carriere const void *compat_data) 60769b8b983SEtienne Carriere { 60869b8b983SEtienne Carriere uint32_t __maybe_unused revision = 0; 60969b8b983SEtienne Carriere TEE_Result res = TEE_SUCCESS; 61069b8b983SEtienne Carriere vaddr_t base = 0; 61169b8b983SEtienne Carriere 612*461e8793SGatien Chevallier stm32_tamp_dev = calloc(1, sizeof(*stm32_tamp_dev)); 613*461e8793SGatien Chevallier if (!stm32_tamp_dev) 61469b8b983SEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY; 61569b8b983SEtienne Carriere 616*461e8793SGatien Chevallier res = stm32_tamp_parse_fdt(fdt, node, compat_data); 61769b8b983SEtienne Carriere if (res) 61869b8b983SEtienne Carriere goto err; 61969b8b983SEtienne Carriere 620*461e8793SGatien Chevallier if (clk_enable(stm32_tamp_dev->pdata.clock)) 621*461e8793SGatien Chevallier panic(); 62269b8b983SEtienne Carriere 623*461e8793SGatien Chevallier base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 62469b8b983SEtienne Carriere 625*461e8793SGatien Chevallier stm32_tamp_dev->hwconf1 = io_read32(base + _TAMP_HWCFGR1); 626*461e8793SGatien Chevallier stm32_tamp_dev->hwconf2 = io_read32(base + _TAMP_HWCFGR2); 62769b8b983SEtienne Carriere 62869b8b983SEtienne Carriere revision = io_read32(base + _TAMP_VERR); 62969b8b983SEtienne Carriere FMSG("STM32 TAMPER V%"PRIx32".%"PRIu32, 63069b8b983SEtienne Carriere (revision & _TAMP_VERR_MAJREV) >> 4, revision & _TAMP_VERR_MINREV); 63169b8b983SEtienne Carriere 632*461e8793SGatien Chevallier if (!(stm32_tamp_dev->hwconf2 & _TAMP_HWCFGR2_TZ)) { 63369b8b983SEtienne Carriere EMSG("TAMP doesn't support TrustZone"); 63469b8b983SEtienne Carriere res = TEE_ERROR_NOT_SUPPORTED; 63569b8b983SEtienne Carriere goto err_clk; 63669b8b983SEtienne Carriere } 63769b8b983SEtienne Carriere 638*461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) { 639*461e8793SGatien Chevallier apply_rif_config(); 640*461e8793SGatien Chevallier 641*461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.is_tdcid) { 642*461e8793SGatien Chevallier res = stm32_tamp_apply_bkpr_rif_conf(); 643*461e8793SGatien Chevallier if (res) 644*461e8793SGatien Chevallier goto err_clk; 645*461e8793SGatien Chevallier } 646*461e8793SGatien Chevallier } else { 64769b8b983SEtienne Carriere /* 64869b8b983SEtienne Carriere * Enforce secure only access to protected TAMP registers. 64969b8b983SEtienne Carriere * Allow non-secure access to monotonic counter. 65069b8b983SEtienne Carriere */ 651*461e8793SGatien Chevallier stm32_tamp_set_secure(_TAMP_SECCFGR_TAMPSEC); 65269b8b983SEtienne Carriere 65369b8b983SEtienne Carriere /* 65469b8b983SEtienne Carriere * Enforce privilege only access to TAMP registers, backup 65569b8b983SEtienne Carriere * registers and monotonic counter. 65669b8b983SEtienne Carriere */ 657*461e8793SGatien Chevallier stm32_tamp_set_privilege(_TAMP_PRIVCFG_TAMPPRIV | 65869b8b983SEtienne Carriere _TAMP_PRIVCFG_BKPRWPRIV | 65969b8b983SEtienne Carriere _TAMP_PRIVCFG_BKPWPRIV); 660*461e8793SGatien Chevallier } 66169b8b983SEtienne Carriere 66269b8b983SEtienne Carriere return TEE_SUCCESS; 66369b8b983SEtienne Carriere 66469b8b983SEtienne Carriere err_clk: 665*461e8793SGatien Chevallier clk_disable(stm32_tamp_dev->pdata.clock); 66669b8b983SEtienne Carriere err: 667*461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.conf_data) { 668*461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->cid_confs); 669*461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->sec_conf); 670*461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->priv_conf); 671*461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->access_mask); 672*461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data); 673*461e8793SGatien Chevallier } 674*461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.bkpregs_conf.rif_offsets); 675*461e8793SGatien Chevallier free(stm32_tamp_dev); 676*461e8793SGatien Chevallier 67769b8b983SEtienne Carriere return res; 67869b8b983SEtienne Carriere } 67969b8b983SEtienne Carriere 68069b8b983SEtienne Carriere static const struct stm32_tamp_compat mp13_compat = { 68169b8b983SEtienne Carriere .nb_monotonic_counter = 2, 682*461e8793SGatien Chevallier .tags = TAMP_HAS_REGISTER_SECCFGR | TAMP_HAS_REGISTER_PRIVCFGR, 68369b8b983SEtienne Carriere }; 68469b8b983SEtienne Carriere 68569b8b983SEtienne Carriere static const struct stm32_tamp_compat mp15_compat = { 68669b8b983SEtienne Carriere .nb_monotonic_counter = 1, 68769b8b983SEtienne Carriere .tags = 0, 68869b8b983SEtienne Carriere }; 68969b8b983SEtienne Carriere 690*461e8793SGatien Chevallier static const struct stm32_tamp_compat mp25_compat = { 691*461e8793SGatien Chevallier .nb_monotonic_counter = 2, 692*461e8793SGatien Chevallier .tags = TAMP_HAS_REGISTER_SECCFGR | 693*461e8793SGatien Chevallier TAMP_HAS_REGISTER_PRIVCFGR | 694*461e8793SGatien Chevallier TAMP_HAS_RIF_SUPPORT, 695*461e8793SGatien Chevallier }; 696*461e8793SGatien Chevallier 69769b8b983SEtienne Carriere static const struct dt_device_match stm32_tamp_match_table[] = { 698*461e8793SGatien Chevallier { .compatible = "st,stm32mp25-tamp", .compat_data = &mp25_compat }, 69969b8b983SEtienne Carriere { .compatible = "st,stm32mp13-tamp", .compat_data = &mp13_compat }, 70069b8b983SEtienne Carriere { .compatible = "st,stm32-tamp", .compat_data = &mp15_compat }, 70169b8b983SEtienne Carriere { } 70269b8b983SEtienne Carriere }; 70369b8b983SEtienne Carriere 70469b8b983SEtienne Carriere DEFINE_DT_DRIVER(stm32_tamp_dt_driver) = { 70569b8b983SEtienne Carriere .name = "stm32-tamp", 70669b8b983SEtienne Carriere .match_table = stm32_tamp_match_table, 70769b8b983SEtienne Carriere .probe = stm32_tamp_probe, 70869b8b983SEtienne Carriere }; 709