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> 8461e8793SGatien Chevallier #include <drivers/stm32_rif.h> 969b8b983SEtienne Carriere #include <io.h> 1069b8b983SEtienne Carriere #include <kernel/dt.h> 119e3c57c8SEtienne Carriere #include <kernel/dt_driver.h> 1269b8b983SEtienne Carriere #include <kernel/interrupt.h> 1369b8b983SEtienne Carriere #include <libfdt.h> 1469b8b983SEtienne Carriere #include <mm/core_memprot.h> 1569b8b983SEtienne Carriere #include <stdbool.h> 1669b8b983SEtienne Carriere 1769b8b983SEtienne Carriere /* STM32 Registers */ 1869b8b983SEtienne Carriere #define _TAMP_CR1 0x00U 1969b8b983SEtienne Carriere #define _TAMP_CR2 0x04U 2069b8b983SEtienne Carriere #define _TAMP_CR3 0x08U 2169b8b983SEtienne Carriere #define _TAMP_FLTCR 0x0CU 2269b8b983SEtienne Carriere #define _TAMP_ATCR1 0x10U 2369b8b983SEtienne Carriere #define _TAMP_ATSEEDR 0x14U 2469b8b983SEtienne Carriere #define _TAMP_ATOR 0x18U 2569b8b983SEtienne Carriere #define _TAMP_ATCR2 0x1CU 2669b8b983SEtienne Carriere #define _TAMP_SECCFGR 0x20U 2769b8b983SEtienne Carriere #define _TAMP_SMCR 0x20U 2869b8b983SEtienne Carriere #define _TAMP_PRIVCFGR 0x24U 2969b8b983SEtienne Carriere #define _TAMP_IER 0x2CU 3069b8b983SEtienne Carriere #define _TAMP_SR 0x30U 3169b8b983SEtienne Carriere #define _TAMP_MISR 0x34U 3269b8b983SEtienne Carriere #define _TAMP_SMISR 0x38U 3369b8b983SEtienne Carriere #define _TAMP_SCR 0x3CU 3469b8b983SEtienne Carriere #define _TAMP_COUNTR 0x40U 3569b8b983SEtienne Carriere #define _TAMP_COUNT2R 0x44U 3669b8b983SEtienne Carriere #define _TAMP_OR 0x50U 3769b8b983SEtienne Carriere #define _TAMP_ERCFGR 0X54U 38461e8793SGatien Chevallier #define _TAMP_BKPRIFR(x) (0x70U + 0x4U * ((x) - 1U)) 39461e8793SGatien Chevallier #define _TAMP_CIDCFGR(x) (0x80U + 0x4U * (x)) 40461e8793SGatien Chevallier #define _TAMP_BKPxR(x) (0x100U + 0x4U * ((x) - 1U)) 4169b8b983SEtienne Carriere #define _TAMP_HWCFGR2 0x3ECU 4269b8b983SEtienne Carriere #define _TAMP_HWCFGR1 0x3F0U 4369b8b983SEtienne Carriere #define _TAMP_VERR 0x3F4U 4469b8b983SEtienne Carriere #define _TAMP_IPIDR 0x3F8U 4569b8b983SEtienne Carriere #define _TAMP_SIDR 0x3FCU 4669b8b983SEtienne Carriere 4769b8b983SEtienne Carriere /* _TAMP_SECCFGR bit fields */ 4869b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_MASK GENMASK_32(7, 0) 4969b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_SHIFT 0U 5069b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT2SEC BIT(14) 51461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT2SEC_SHIFT 14U 5269b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT1SEC BIT(15) 53461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT1SEC_SHIFT 15U 5469b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_MASK GENMASK_32(23, 16) 5569b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_SHIFT 16U 5669b8b983SEtienne Carriere #define _TAMP_SECCFGR_BHKLOCK BIT(30) 5769b8b983SEtienne Carriere #define _TAMP_SECCFGR_TAMPSEC BIT(31) 58461e8793SGatien Chevallier #define _TAMP_SECCFGR_TAMPSEC_SHIFT 31U 5969b8b983SEtienne Carriere #define _TAMP_SECCFGR_BUT_BKP_MASK (GENMASK_32(31, 30) | \ 6069b8b983SEtienne Carriere GENMASK_32(15, 14)) 61461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_TAMP_SEC BIT(0) 62461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_1 BIT(1) 63461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_2 BIT(2) 6469b8b983SEtienne Carriere 6569b8b983SEtienne Carriere /* _TAMP_SMCR bit fields */ 6669b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK_32(7, 0) 6769b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_SHIFT 0U 6869b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_MASK GENMASK_32(23, 16) 6969b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_SHIFT 16U 7069b8b983SEtienne Carriere #define _TAMP_SMCR_DPROT BIT(31) 7169b8b983SEtienne Carriere /* 7269b8b983SEtienne Carriere * _TAMP_PRIVCFGR bit fields 7369b8b983SEtienne Carriere */ 7469b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV BIT(14) 7569b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV BIT(15) 7669b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) 7769b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV BIT(30) 7869b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV BIT(31) 7969b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ 8069b8b983SEtienne Carriere GENMASK_32(15, 14)) 81461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_TAMP_PRIV BIT(0) 82461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R1 BIT(1) 83461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R2 BIT(2) 8469b8b983SEtienne Carriere 8569b8b983SEtienne Carriere /* 8669b8b983SEtienne Carriere * _TAMP_PRIVCFGR bit fields 8769b8b983SEtienne Carriere */ 8869b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV BIT(14) 8969b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV BIT(15) 9069b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) 9169b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV BIT(30) 9269b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV BIT(31) 9369b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ 9469b8b983SEtienne Carriere GENMASK_32(15, 14)) 9569b8b983SEtienne Carriere 9669b8b983SEtienne Carriere /* _TAMP_HWCFGR2 bit fields */ 9769b8b983SEtienne Carriere #define _TAMP_HWCFGR2_TZ GENMASK_32(11, 8) 9869b8b983SEtienne Carriere #define _TAMP_HWCFGR2_OR GENMASK_32(7, 0) 9969b8b983SEtienne Carriere 10069b8b983SEtienne Carriere /* _TAMP_HWCFGR1 bit fields */ 10169b8b983SEtienne Carriere #define _TAMP_HWCFGR1_BKPREG GENMASK_32(7, 0) 10269b8b983SEtienne Carriere #define _TAMP_HWCFGR1_TAMPER GENMASK_32(11, 8) 10369b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ACTIVE GENMASK_32(15, 12) 10469b8b983SEtienne Carriere #define _TAMP_HWCFGR1_INTERN GENMASK_32(31, 16) 10569b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U 10669b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP(id) BIT((id) - INT_TAMP1 + 16U) 10769b8b983SEtienne Carriere 10869b8b983SEtienne Carriere /* _TAMP_VERR bit fields */ 10969b8b983SEtienne Carriere #define _TAMP_VERR_MINREV GENMASK_32(3, 0) 11069b8b983SEtienne Carriere #define _TAMP_VERR_MAJREV GENMASK_32(7, 4) 11169b8b983SEtienne Carriere 11269b8b983SEtienne Carriere /* 113461e8793SGatien Chevallier * CIDCFGR register bitfields 11469b8b983SEtienne Carriere */ 115461e8793SGatien Chevallier #define _TAMP_CIDCFGR_SCID_MASK GENMASK_32(6, 4) 116461e8793SGatien Chevallier #define _TAMP_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ 117461e8793SGatien Chevallier _CIDCFGR_SEMEN | \ 118461e8793SGatien Chevallier _TAMP_CIDCFGR_SCID_MASK) 119461e8793SGatien Chevallier 120461e8793SGatien Chevallier /* _TAMP_BKPRIFR */ 121461e8793SGatien Chevallier #define _TAMP_BKPRIFR_1_MASK GENMASK_32(7, 0) 122461e8793SGatien Chevallier #define _TAMP_BKPRIFR_2_MASK GENMASK_32(7, 0) 123461e8793SGatien Chevallier #define _TAMP_BKPRIFR_3_MASK (GENMASK_32(23, 16) | GENMASK_32(7, 0)) 124461e8793SGatien Chevallier #define _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT 16U 125461e8793SGatien Chevallier 126461e8793SGatien Chevallier /* 127461e8793SGatien Chevallier * RIF miscellaneous 128461e8793SGatien Chevallier */ 129461e8793SGatien Chevallier #define TAMP_NB_BKPR_ZONES 3U 130461e8793SGatien Chevallier #define TAMP_RIF_RESOURCES 3U 131461e8793SGatien Chevallier #define TAMP_RIF_OFFSET_CNT 4U 13269b8b983SEtienne Carriere 13369b8b983SEtienne Carriere /* 13469b8b983SEtienne Carriere * Compatibility capabilities 135461e8793SGatien Chevallier * TAMP_HAS_REGISTER_SECCFGR - Supports SECCFGR, otherwise supports SMCR 136461e8793SGatien Chevallier * register 13769b8b983SEtienne Carriere * TAMP_HAS_REGISTER_PRIVCFG - Supports PRIVCFGR configuration register 138461e8793SGatien Chevallier * TAMP_HAS_RIF_SUPPORT - Supports RIF 13969b8b983SEtienne Carriere */ 140461e8793SGatien Chevallier #define TAMP_HAS_REGISTER_SECCFGR BIT(0) 14169b8b983SEtienne Carriere #define TAMP_HAS_REGISTER_PRIVCFGR BIT(1) 142461e8793SGatien Chevallier #define TAMP_HAS_RIF_SUPPORT BIT(31) 14369b8b983SEtienne Carriere 144461e8793SGatien Chevallier /** 145461e8793SGatien Chevallier * struct stm32_tamp_compat - TAMP compatible data 146461e8793SGatien Chevallier * @nb_monotonic_counter: Number of monotic counter supported 147461e8793SGatien Chevallier * @tags: Bit flags TAMP_HAS_* for compatibility management 14869b8b983SEtienne Carriere */ 14969b8b983SEtienne Carriere struct stm32_tamp_compat { 15069b8b983SEtienne Carriere int nb_monotonic_counter; 15169b8b983SEtienne Carriere uint32_t tags; 15269b8b983SEtienne Carriere }; 15369b8b983SEtienne Carriere 154461e8793SGatien Chevallier /* 155*92ab6535SGatien Chevallier * struct stm32_bkpregs_conf - Backup registers zone bounds 156461e8793SGatien Chevallier * @zone1_end - Number of backup registers in zone 1 157461e8793SGatien Chevallier * @zone2_end - Number of backup registers in zone 2 + zone 1 158461e8793SGatien Chevallier * @rif_offsets - RIF offsets used for CID compartments 159461e8793SGatien Chevallier * 160461e8793SGatien Chevallier * TAMP backup registers access permissions 161461e8793SGatien Chevallier * 162461e8793SGatien Chevallier * Zone 1: read/write in secure state, no access in non-secure state 163461e8793SGatien Chevallier * Zone 2: read/write in secure state, read-only in non-secure state 164461e8793SGatien Chevallier * Zone 3: read/write in secure state, read/write in non-secure state 165461e8793SGatien Chevallier * 166461e8793SGatien Chevallier * Protection zone 1 167461e8793SGatien Chevallier * If zone1_end == 0 no backup register are in zone 1. 168461e8793SGatien Chevallier * Otherwise backup registers from TAMP_BKP0R to TAMP_BKP<x>R are in zone 1, 169461e8793SGatien Chevallier * with <x> = (@zone1_end - 1). 170461e8793SGatien Chevallier * 171461e8793SGatien Chevallier * Protection zone 2 172461e8793SGatien Chevallier * If zone2_end == 0 no backup register are in zone 2 and zone 1. 173461e8793SGatien Chevallier * Otherwise backup registers from TAMP_BKP<y>R to TAMP_BKP<z>R are in zone 2, 174461e8793SGatien Chevallier * with <y> = @zone1_end and <z> = (@zone2_end - 1). 175461e8793SGatien Chevallier * 176461e8793SGatien Chevallier * Protection zone 3 177461e8793SGatien Chevallier * Backup registers from TAMP_BKP<t>R to last backup register are in zone 3, 178461e8793SGatien Chevallier * with <t> = (@zone2_end - 1). 179461e8793SGatien Chevallier * 180461e8793SGatien Chevallier * When RIF is supported, each zone can be subdivided to restrain accesses to 181461e8793SGatien Chevallier * some CIDs. 182461e8793SGatien Chevallier */ 183*92ab6535SGatien Chevallier struct stm32_bkpregs_conf { 184461e8793SGatien Chevallier uint32_t zone1_end; 185461e8793SGatien Chevallier uint32_t zone2_end; 186461e8793SGatien Chevallier uint32_t *rif_offsets; 187461e8793SGatien Chevallier }; 188461e8793SGatien Chevallier 189461e8793SGatien Chevallier /** 190461e8793SGatien Chevallier * struct stm32_tamp_platdata - TAMP platform data 191461e8793SGatien Chevallier * @base: IOMEM base address 192461e8793SGatien Chevallier * @bkpregs_conf: TAMP backup register configuration reference 193461e8793SGatien Chevallier * @compat: Reference to compat data passed at driver initialization 194461e8793SGatien Chevallier * @conf_data: RIF configuration data 195461e8793SGatien Chevallier * @clock: TAMP clock 196461e8793SGatien Chevallier * @nb_rif_resources: Number of RIF resources 197461e8793SGatien Chevallier * @it: TAMP interrupt number 198461e8793SGatien Chevallier * @is_tdcid: True if current processor is TDCID 199461e8793SGatien Chevallier */ 200461e8793SGatien Chevallier struct stm32_tamp_platdata { 201461e8793SGatien Chevallier struct io_pa_va base; 202*92ab6535SGatien Chevallier struct stm32_bkpregs_conf bkpregs_conf; 203461e8793SGatien Chevallier struct stm32_tamp_compat *compat; 204461e8793SGatien Chevallier struct rif_conf_data *conf_data; 205461e8793SGatien Chevallier struct clk *clock; 206461e8793SGatien Chevallier unsigned int nb_rif_resources; 207461e8793SGatien Chevallier int it; 208461e8793SGatien Chevallier bool is_tdcid; 209461e8793SGatien Chevallier }; 210461e8793SGatien Chevallier 211461e8793SGatien Chevallier /** 212461e8793SGatien Chevallier * struct stm32_tamp_instance - TAMP instance data 213461e8793SGatien Chevallier * @pdata: TAMP platform data 214461e8793SGatien Chevallier * @hwconf1: Copy of TAMP HWCONF1 register content 215461e8793SGatien Chevallier * @hwconf2: Copy of TAMP HWCONF2 register content 216461e8793SGatien Chevallier */ 217461e8793SGatien Chevallier struct stm32_tamp_instance { 218461e8793SGatien Chevallier struct stm32_tamp_platdata pdata; 219461e8793SGatien Chevallier uint32_t hwconf1; 220461e8793SGatien Chevallier uint32_t hwconf2; 221461e8793SGatien Chevallier }; 222461e8793SGatien Chevallier 22369b8b983SEtienne Carriere /* Expects at most a single instance */ 224461e8793SGatien Chevallier static struct stm32_tamp_instance *stm32_tamp_dev; 225461e8793SGatien Chevallier 226461e8793SGatien Chevallier static void apply_rif_config(void) 227461e8793SGatien Chevallier { 228461e8793SGatien Chevallier struct rif_conf_data *rif_conf = stm32_tamp_dev->pdata.conf_data; 229461e8793SGatien Chevallier vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 230461e8793SGatien Chevallier uint32_t access_mask_priv_reg = 0; 231461e8793SGatien Chevallier uint32_t access_mask_sec_reg = 0; 232461e8793SGatien Chevallier uint32_t privcfgr = 0; 233461e8793SGatien Chevallier uint32_t seccfgr = 0; 234461e8793SGatien Chevallier unsigned int i = 0; 235461e8793SGatien Chevallier 236461e8793SGatien Chevallier if (!stm32_tamp_dev->pdata.conf_data) 237461e8793SGatien Chevallier return; 238461e8793SGatien Chevallier 239461e8793SGatien Chevallier /* Build access masks for _TAMP_PRIVCFGR and _TAMP_SECCFGR */ 240461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) { 241461e8793SGatien Chevallier if (BIT(i) & rif_conf->access_mask[0]) { 242461e8793SGatien Chevallier switch (i) { 243461e8793SGatien Chevallier case 0: 244461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_TAMPSEC; 245461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_TAMPPRIV; 246461e8793SGatien Chevallier break; 247461e8793SGatien Chevallier case 1: 248461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_CNT1SEC; 249461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_CNT1PRIV; 250461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_BKPRWPRIV; 251461e8793SGatien Chevallier break; 252461e8793SGatien Chevallier case 2: 253461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_CNT2SEC; 254461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_CNT2PRIV; 255461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_BKPWPRIV; 256461e8793SGatien Chevallier break; 257461e8793SGatien Chevallier default: 258461e8793SGatien Chevallier panic(); 259461e8793SGatien Chevallier } 260461e8793SGatien Chevallier } 261461e8793SGatien Chevallier } 262461e8793SGatien Chevallier 263461e8793SGatien Chevallier /* 264461e8793SGatien Chevallier * When TDCID, OP-TEE should be the one to set the CID filtering 265461e8793SGatien Chevallier * configuration. Clearing previous configuration prevents 266461e8793SGatien Chevallier * undesired events during the only legitimate configuration. 267461e8793SGatien Chevallier */ 268461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.is_tdcid) { 269461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) 270461e8793SGatien Chevallier if (BIT(i) & rif_conf->access_mask[0]) 271461e8793SGatien Chevallier io_clrbits32(base + _TAMP_CIDCFGR(i), 272461e8793SGatien Chevallier _TAMP_CIDCFGR_CONF_MASK); 273461e8793SGatien Chevallier } 274461e8793SGatien Chevallier 275461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_TAMP_SEC) 276461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_TAMPSEC; 277461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_1) 278461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_CNT1SEC; 279461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_2) 280461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_CNT2SEC; 281461e8793SGatien Chevallier 282461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_TAMP_PRIV) 283461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_TAMPPRIV; 284461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R1) 285461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_CNT1PRIV | _TAMP_PRIVCFG_BKPRWPRIV; 286461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R2) 287461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_CNT2PRIV | _TAMP_PRIVCFG_BKPWPRIV; 288461e8793SGatien Chevallier 289461e8793SGatien Chevallier /* Security and privilege RIF configuration */ 290461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_PRIVCFGR, access_mask_priv_reg, privcfgr); 291461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_SECCFGR, access_mask_sec_reg, seccfgr); 292461e8793SGatien Chevallier 293461e8793SGatien Chevallier if (!stm32_tamp_dev->pdata.is_tdcid) 294461e8793SGatien Chevallier return; 295461e8793SGatien Chevallier 296461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) { 297461e8793SGatien Chevallier if (!(BIT(i) & rif_conf->access_mask[0])) 298461e8793SGatien Chevallier continue; 299461e8793SGatien Chevallier 300461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_CIDCFGR(i), 301461e8793SGatien Chevallier _TAMP_CIDCFGR_CONF_MASK, 302461e8793SGatien Chevallier rif_conf->cid_confs[i]); 303461e8793SGatien Chevallier } 304461e8793SGatien Chevallier } 305461e8793SGatien Chevallier 306461e8793SGatien Chevallier static TEE_Result stm32_tamp_apply_bkpr_rif_conf(void) 307461e8793SGatien Chevallier { 308*92ab6535SGatien Chevallier struct stm32_bkpregs_conf *bkpregs_conf = 309461e8793SGatien Chevallier &stm32_tamp_dev->pdata.bkpregs_conf; 310461e8793SGatien Chevallier vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 311461e8793SGatien Chevallier unsigned int i = 0; 312461e8793SGatien Chevallier 313461e8793SGatien Chevallier if (!bkpregs_conf->rif_offsets) 314461e8793SGatien Chevallier panic("No backup register configuration"); 315461e8793SGatien Chevallier 316461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_OFFSET_CNT; i++) { 317461e8793SGatien Chevallier if (bkpregs_conf->rif_offsets[i] > 318461e8793SGatien Chevallier (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) 319461e8793SGatien Chevallier return TEE_ERROR_NOT_SUPPORTED; 320461e8793SGatien Chevallier } 321461e8793SGatien Chevallier 322461e8793SGatien Chevallier /* Fill the 3 TAMP_BKPRIFRx registers */ 323461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(1), _TAMP_BKPRIFR_1_MASK, 324461e8793SGatien Chevallier bkpregs_conf->rif_offsets[0]); 325461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(2), _TAMP_BKPRIFR_2_MASK, 326461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1]); 327461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(3), _TAMP_BKPRIFR_3_MASK, 328461e8793SGatien Chevallier bkpregs_conf->rif_offsets[2] | 329461e8793SGatien Chevallier SHIFT_U32(bkpregs_conf->rif_offsets[3], 330461e8793SGatien Chevallier _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT)); 331461e8793SGatien Chevallier 332461e8793SGatien Chevallier DMSG("Backup registers mapping :"); 333461e8793SGatien Chevallier DMSG("********START of zone 1********"); 334461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF1 begins at register: 0"); 335461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF2 begins at register: %"PRIu32, 336461e8793SGatien Chevallier bkpregs_conf->rif_offsets[0]); 337461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF2 ends at register: %"PRIu32, 338461e8793SGatien Chevallier bkpregs_conf->zone1_end ? bkpregs_conf->zone1_end - 1 : 0); 339461e8793SGatien Chevallier DMSG("********END of zone 1********"); 340461e8793SGatien Chevallier DMSG("********START of zone 2********"); 341461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF1 begins at register: %"PRIu32, 342461e8793SGatien Chevallier bkpregs_conf->zone1_end); 343461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF2 begins at register: %"PRIu32, 344461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1]); 345461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF2 ends at register: %"PRIu32, 346461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1] > bkpregs_conf->zone1_end ? 347461e8793SGatien Chevallier bkpregs_conf->zone2_end - 1 : 0); 348461e8793SGatien Chevallier DMSG("********END of zone 2********"); 349461e8793SGatien Chevallier DMSG("********START of zone 3********"); 350461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF1 begins at register: %"PRIu32, 351461e8793SGatien Chevallier bkpregs_conf->zone2_end); 352461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF0 begins at register: %"PRIu32, 353461e8793SGatien Chevallier bkpregs_conf->rif_offsets[2]); 354461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF2 begins at register: %"PRIu32, 355461e8793SGatien Chevallier bkpregs_conf->rif_offsets[3]); 356461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF2 ends at the last register: %"PRIu32, 357461e8793SGatien Chevallier stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG); 358461e8793SGatien Chevallier DMSG("********END of zone 3********"); 359461e8793SGatien Chevallier 360461e8793SGatien Chevallier return TEE_SUCCESS; 361461e8793SGatien Chevallier } 36269b8b983SEtienne Carriere 363*92ab6535SGatien Chevallier static TEE_Result stm32_tamp_set_secure_bkpregs(void) 36469b8b983SEtienne Carriere { 365*92ab6535SGatien Chevallier struct stm32_bkpregs_conf *bkpregs_conf = 366*92ab6535SGatien Chevallier &stm32_tamp_dev->pdata.bkpregs_conf; 36769b8b983SEtienne Carriere vaddr_t base = 0; 36869b8b983SEtienne Carriere uint32_t first_z2 = 0; 36969b8b983SEtienne Carriere uint32_t first_z3 = 0; 37069b8b983SEtienne Carriere 371461e8793SGatien Chevallier base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 37269b8b983SEtienne Carriere 373*92ab6535SGatien Chevallier first_z2 = bkpregs_conf->zone1_end; 374*92ab6535SGatien Chevallier first_z3 = bkpregs_conf->zone2_end; 37569b8b983SEtienne Carriere 376461e8793SGatien Chevallier if ((first_z2 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) || 377461e8793SGatien Chevallier (first_z3 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG))) 37869b8b983SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 37969b8b983SEtienne Carriere 380461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 381461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) { 38269b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 38369b8b983SEtienne Carriere _TAMP_SECCFGR_BKPRWSEC_MASK, 38469b8b983SEtienne Carriere (first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) & 38569b8b983SEtienne Carriere _TAMP_SECCFGR_BKPRWSEC_MASK); 38669b8b983SEtienne Carriere 38769b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 38869b8b983SEtienne Carriere _TAMP_SECCFGR_BKPWSEC_MASK, 38969b8b983SEtienne Carriere (first_z3 << _TAMP_SECCFGR_BKPWSEC_SHIFT) & 39069b8b983SEtienne Carriere _TAMP_SECCFGR_BKPWSEC_MASK); 39169b8b983SEtienne Carriere } else { 39269b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SMCR, 39369b8b983SEtienne Carriere _TAMP_SMCR_BKPRWDPROT_MASK, 39469b8b983SEtienne Carriere (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) & 39569b8b983SEtienne Carriere _TAMP_SMCR_BKPRWDPROT_MASK); 39669b8b983SEtienne Carriere 39769b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SMCR, 39869b8b983SEtienne Carriere _TAMP_SMCR_BKPWDPROT_MASK, 39969b8b983SEtienne Carriere (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) & 40069b8b983SEtienne Carriere _TAMP_SMCR_BKPWDPROT_MASK); 40169b8b983SEtienne Carriere } 40269b8b983SEtienne Carriere 40369b8b983SEtienne Carriere return TEE_SUCCESS; 40469b8b983SEtienne Carriere } 40569b8b983SEtienne Carriere 406461e8793SGatien Chevallier static void stm32_tamp_set_secure(uint32_t mode) 40769b8b983SEtienne Carriere { 408461e8793SGatien Chevallier vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 40969b8b983SEtienne Carriere 410461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 411461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) { 41269b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 41369b8b983SEtienne Carriere _TAMP_SECCFGR_BUT_BKP_MASK, 41469b8b983SEtienne Carriere mode & _TAMP_SECCFGR_BUT_BKP_MASK); 41569b8b983SEtienne Carriere } else { 41669b8b983SEtienne Carriere /* 41769b8b983SEtienne Carriere * Note: MP15 doesn't use SECCFG register and 41869b8b983SEtienne Carriere * inverts the secure bit. 41969b8b983SEtienne Carriere */ 42069b8b983SEtienne Carriere if (mode & _TAMP_SECCFGR_TAMPSEC) 42169b8b983SEtienne Carriere io_clrbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); 42269b8b983SEtienne Carriere else 42369b8b983SEtienne Carriere io_setbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); 42469b8b983SEtienne Carriere } 42569b8b983SEtienne Carriere } 42669b8b983SEtienne Carriere 427461e8793SGatien Chevallier static void stm32_tamp_set_privilege(uint32_t mode) 42869b8b983SEtienne Carriere { 429461e8793SGatien Chevallier vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 43069b8b983SEtienne Carriere 431461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 432461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_PRIVCFGR)) 43369b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK, 43469b8b983SEtienne Carriere mode & _TAMP_PRIVCFGR_MASK); 43569b8b983SEtienne Carriere } 43669b8b983SEtienne Carriere 437*92ab6535SGatien Chevallier static void parse_bkpregs_dt_conf(const void *fdt, int node) 438461e8793SGatien Chevallier { 439*92ab6535SGatien Chevallier struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata; 440461e8793SGatien Chevallier unsigned int bkpregs_count = 0; 441*92ab6535SGatien Chevallier const fdt32_t *cuint = NULL; 442461e8793SGatien Chevallier int lenp = 0; 443461e8793SGatien Chevallier 444461e8793SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,backup-zones", &lenp); 445461e8793SGatien Chevallier if (!cuint) 446461e8793SGatien Chevallier panic("Missing backup registers configuration"); 447461e8793SGatien Chevallier 448461e8793SGatien Chevallier /* 449461e8793SGatien Chevallier * When TAMP does not support RIF, the backup registers can 450461e8793SGatien Chevallier * be splited in 3 zones. These zones have specific read/write 451461e8793SGatien Chevallier * access permissions based on the secure status of the accesser. 452461e8793SGatien Chevallier * When RIF is supported, these zones can additionally be splited 453461e8793SGatien Chevallier * in subzones that have CID filtering. Zones/Subzones can be empty and 454461e8793SGatien Chevallier * are contiguous. 455461e8793SGatien Chevallier */ 456*92ab6535SGatien Chevallier if (!(pdata->compat->tags & TAMP_HAS_RIF_SUPPORT)) { 457461e8793SGatien Chevallier /* 3 zones, 2 offsets to apply */ 458461e8793SGatien Chevallier if (lenp != sizeof(uint32_t) * TAMP_NB_BKPR_ZONES) 459461e8793SGatien Chevallier panic("Incorrect bkpregs configuration"); 460461e8793SGatien Chevallier 461461e8793SGatien Chevallier pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]); 462461e8793SGatien Chevallier bkpregs_count = fdt32_to_cpu(cuint[0]); 463461e8793SGatien Chevallier 464461e8793SGatien Chevallier pdata->bkpregs_conf.zone2_end = bkpregs_count + 465461e8793SGatien Chevallier fdt32_to_cpu(cuint[1]); 466461e8793SGatien Chevallier } else { 467461e8793SGatien Chevallier /* 468461e8793SGatien Chevallier * Zone 3 469461e8793SGatien Chevallier * ----------------------| 470461e8793SGatien Chevallier * Protection Zone 3-RIF2|Read non- 471461e8793SGatien Chevallier * ----------------------|secure 472461e8793SGatien Chevallier * Protection Zone 3-RIF0|Write non- 473461e8793SGatien Chevallier * ----------------------|secure 474461e8793SGatien Chevallier * Protection Zone 3-RIF1| 475461e8793SGatien Chevallier * ----------------------| 476461e8793SGatien Chevallier * 477461e8793SGatien Chevallier * Zone 2 478461e8793SGatien Chevallier * ----------------------| 479461e8793SGatien Chevallier * Protection Zone 2-RIF2|Read non- 480461e8793SGatien Chevallier * ----------------------|secure 481461e8793SGatien Chevallier * Protection Zone 2-RIF1|Write secure 482461e8793SGatien Chevallier * ----------------------| 483461e8793SGatien Chevallier * 484461e8793SGatien Chevallier * Zone 1 485461e8793SGatien Chevallier * ----------------------| 486461e8793SGatien Chevallier * Protection Zone 1-RIF2|Read secure 487461e8793SGatien Chevallier * ----------------------|Write secure 488461e8793SGatien Chevallier * Protection Zone 1-RIF1| 489461e8793SGatien Chevallier * ----------------------| 490461e8793SGatien Chevallier * 491461e8793SGatien Chevallier * (BHK => First 8 registers) 492461e8793SGatien Chevallier */ 493461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets = calloc(TAMP_RIF_OFFSET_CNT, 494461e8793SGatien Chevallier sizeof(uint32_t)); 495461e8793SGatien Chevallier if (!pdata->bkpregs_conf.rif_offsets) 496461e8793SGatien Chevallier panic(); 497461e8793SGatien Chevallier 498461e8793SGatien Chevallier /* 499461e8793SGatien Chevallier * 3 zones with 7 subzones in total(6 offsets): 500461e8793SGatien Chevallier * - 2 zone offsets 501461e8793SGatien Chevallier * - 4 subzones offsets 502461e8793SGatien Chevallier */ 503461e8793SGatien Chevallier if (lenp != sizeof(uint32_t) * 504461e8793SGatien Chevallier (TAMP_RIF_OFFSET_CNT + TAMP_NB_BKPR_ZONES)) 505461e8793SGatien Chevallier panic("Incorrect bkpregs configuration"); 506461e8793SGatien Chevallier 507461e8793SGatien Chevallier /* Backup registers zone 1 */ 508461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[0] = fdt32_to_cpu(cuint[0]); 509461e8793SGatien Chevallier pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]) + 510461e8793SGatien Chevallier fdt32_to_cpu(cuint[1]); 511461e8793SGatien Chevallier 512461e8793SGatien Chevallier bkpregs_count = pdata->bkpregs_conf.zone1_end; 513461e8793SGatien Chevallier 514461e8793SGatien Chevallier /* Backup registers zone 2 */ 515461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[1] = bkpregs_count + 516461e8793SGatien Chevallier fdt32_to_cpu(cuint[2]); 517461e8793SGatien Chevallier pdata->bkpregs_conf.zone2_end = bkpregs_count + 518461e8793SGatien Chevallier fdt32_to_cpu(cuint[2]) + 519461e8793SGatien Chevallier fdt32_to_cpu(cuint[3]); 520461e8793SGatien Chevallier 521461e8793SGatien Chevallier bkpregs_count = pdata->bkpregs_conf.zone2_end; 522461e8793SGatien Chevallier 523461e8793SGatien Chevallier /* Backup registers zone 3 */ 524461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[2] = bkpregs_count + 525461e8793SGatien Chevallier fdt32_to_cpu(cuint[4]); 526461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[3] = bkpregs_count + 527461e8793SGatien Chevallier fdt32_to_cpu(cuint[4]) + 528461e8793SGatien Chevallier fdt32_to_cpu(cuint[5]); 529461e8793SGatien Chevallier } 530461e8793SGatien Chevallier } 531461e8793SGatien Chevallier 532461e8793SGatien Chevallier static TEE_Result stm32_tamp_parse_fdt(const void *fdt, int node, 53369b8b983SEtienne Carriere const void *compat) 53469b8b983SEtienne Carriere { 535461e8793SGatien Chevallier struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata; 536461e8793SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 53769b8b983SEtienne Carriere struct dt_node_info dt_tamp = { }; 53869b8b983SEtienne Carriere 539f354a5d8SGatien Chevallier fdt_fill_device_info(fdt, &dt_tamp, node); 54069b8b983SEtienne Carriere 54169b8b983SEtienne Carriere if (dt_tamp.reg == DT_INFO_INVALID_REG || 54269b8b983SEtienne Carriere dt_tamp.reg_size == DT_INFO_INVALID_REG_SIZE) 54369b8b983SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 54469b8b983SEtienne Carriere 545461e8793SGatien Chevallier pdata->compat = (struct stm32_tamp_compat *)compat; 546461e8793SGatien Chevallier pdata->it = dt_tamp.interrupt; 547461e8793SGatien Chevallier pdata->base.pa = dt_tamp.reg; 548461e8793SGatien Chevallier io_pa_or_va_secure(&pdata->base, dt_tamp.reg_size); 54969b8b983SEtienne Carriere 550461e8793SGatien Chevallier res = clk_dt_get_by_index(fdt, node, 0, &pdata->clock); 551461e8793SGatien Chevallier if (res) 552461e8793SGatien Chevallier return res; 553461e8793SGatien Chevallier 554*92ab6535SGatien Chevallier parse_bkpregs_dt_conf(fdt, node); 555461e8793SGatien Chevallier 556461e8793SGatien Chevallier if (pdata->compat->tags & TAMP_HAS_RIF_SUPPORT) { 557461e8793SGatien Chevallier const fdt32_t *cuint = NULL; 558461e8793SGatien Chevallier unsigned int i = 0; 559461e8793SGatien Chevallier int lenp = 0; 560461e8793SGatien Chevallier 561461e8793SGatien Chevallier res = stm32_rifsc_check_tdcid(&pdata->is_tdcid); 562461e8793SGatien Chevallier if (res) 563461e8793SGatien Chevallier return res; 564461e8793SGatien Chevallier 565461e8793SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); 566461e8793SGatien Chevallier if (!cuint) { 567461e8793SGatien Chevallier DMSG("No RIF configuration available"); 568461e8793SGatien Chevallier return TEE_SUCCESS; 569461e8793SGatien Chevallier } 570461e8793SGatien Chevallier 571461e8793SGatien Chevallier pdata->conf_data = calloc(1, sizeof(*pdata->conf_data)); 572461e8793SGatien Chevallier if (!pdata->conf_data) 573461e8793SGatien Chevallier panic(); 574461e8793SGatien Chevallier 575461e8793SGatien Chevallier pdata->nb_rif_resources = (unsigned int)(lenp / 576461e8793SGatien Chevallier sizeof(uint32_t)); 577461e8793SGatien Chevallier assert(pdata->nb_rif_resources <= TAMP_RIF_RESOURCES); 578461e8793SGatien Chevallier 579461e8793SGatien Chevallier pdata->conf_data->cid_confs = calloc(TAMP_RIF_RESOURCES, 580461e8793SGatien Chevallier sizeof(uint32_t)); 581461e8793SGatien Chevallier pdata->conf_data->sec_conf = calloc(1, sizeof(uint32_t)); 582461e8793SGatien Chevallier pdata->conf_data->priv_conf = calloc(1, sizeof(uint32_t)); 583461e8793SGatien Chevallier pdata->conf_data->access_mask = calloc(1, sizeof(uint32_t)); 584461e8793SGatien Chevallier if (!pdata->conf_data->cid_confs || 585461e8793SGatien Chevallier !pdata->conf_data->sec_conf || 586461e8793SGatien Chevallier !pdata->conf_data->priv_conf || 587461e8793SGatien Chevallier !pdata->conf_data->access_mask) 588461e8793SGatien Chevallier panic("Not enough memory capacity for TAMP RIF config"); 589461e8793SGatien Chevallier 590461e8793SGatien Chevallier for (i = 0; i < pdata->nb_rif_resources; i++) 591461e8793SGatien Chevallier stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), 592461e8793SGatien Chevallier pdata->conf_data, 593461e8793SGatien Chevallier TAMP_RIF_RESOURCES); 594461e8793SGatien Chevallier } 595461e8793SGatien Chevallier 596461e8793SGatien Chevallier return TEE_SUCCESS; 59769b8b983SEtienne Carriere } 59869b8b983SEtienne Carriere 59969b8b983SEtienne Carriere static TEE_Result stm32_tamp_probe(const void *fdt, int node, 60069b8b983SEtienne Carriere const void *compat_data) 60169b8b983SEtienne Carriere { 60269b8b983SEtienne Carriere uint32_t __maybe_unused revision = 0; 60369b8b983SEtienne Carriere TEE_Result res = TEE_SUCCESS; 60469b8b983SEtienne Carriere vaddr_t base = 0; 60569b8b983SEtienne Carriere 606461e8793SGatien Chevallier stm32_tamp_dev = calloc(1, sizeof(*stm32_tamp_dev)); 607461e8793SGatien Chevallier if (!stm32_tamp_dev) 60869b8b983SEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY; 60969b8b983SEtienne Carriere 610461e8793SGatien Chevallier res = stm32_tamp_parse_fdt(fdt, node, compat_data); 61169b8b983SEtienne Carriere if (res) 61269b8b983SEtienne Carriere goto err; 61369b8b983SEtienne Carriere 614461e8793SGatien Chevallier if (clk_enable(stm32_tamp_dev->pdata.clock)) 615461e8793SGatien Chevallier panic(); 61669b8b983SEtienne Carriere 617461e8793SGatien Chevallier base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1); 61869b8b983SEtienne Carriere 619461e8793SGatien Chevallier stm32_tamp_dev->hwconf1 = io_read32(base + _TAMP_HWCFGR1); 620461e8793SGatien Chevallier stm32_tamp_dev->hwconf2 = io_read32(base + _TAMP_HWCFGR2); 62169b8b983SEtienne Carriere 62269b8b983SEtienne Carriere revision = io_read32(base + _TAMP_VERR); 62369b8b983SEtienne Carriere FMSG("STM32 TAMPER V%"PRIx32".%"PRIu32, 62469b8b983SEtienne Carriere (revision & _TAMP_VERR_MAJREV) >> 4, revision & _TAMP_VERR_MINREV); 62569b8b983SEtienne Carriere 626461e8793SGatien Chevallier if (!(stm32_tamp_dev->hwconf2 & _TAMP_HWCFGR2_TZ)) { 62769b8b983SEtienne Carriere EMSG("TAMP doesn't support TrustZone"); 62869b8b983SEtienne Carriere res = TEE_ERROR_NOT_SUPPORTED; 62969b8b983SEtienne Carriere goto err_clk; 63069b8b983SEtienne Carriere } 63169b8b983SEtienne Carriere 632461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) { 633461e8793SGatien Chevallier apply_rif_config(); 634461e8793SGatien Chevallier 635461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.is_tdcid) { 636461e8793SGatien Chevallier res = stm32_tamp_apply_bkpr_rif_conf(); 637461e8793SGatien Chevallier if (res) 638461e8793SGatien Chevallier goto err_clk; 639461e8793SGatien Chevallier } 640461e8793SGatien Chevallier } else { 64169b8b983SEtienne Carriere /* 64269b8b983SEtienne Carriere * Enforce secure only access to protected TAMP registers. 64369b8b983SEtienne Carriere * Allow non-secure access to monotonic counter. 64469b8b983SEtienne Carriere */ 645461e8793SGatien Chevallier stm32_tamp_set_secure(_TAMP_SECCFGR_TAMPSEC); 64669b8b983SEtienne Carriere 64769b8b983SEtienne Carriere /* 64869b8b983SEtienne Carriere * Enforce privilege only access to TAMP registers, backup 64969b8b983SEtienne Carriere * registers and monotonic counter. 65069b8b983SEtienne Carriere */ 651461e8793SGatien Chevallier stm32_tamp_set_privilege(_TAMP_PRIVCFG_TAMPPRIV | 65269b8b983SEtienne Carriere _TAMP_PRIVCFG_BKPRWPRIV | 65369b8b983SEtienne Carriere _TAMP_PRIVCFG_BKPWPRIV); 654461e8793SGatien Chevallier } 65569b8b983SEtienne Carriere 656*92ab6535SGatien Chevallier if (!(stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) || 657*92ab6535SGatien Chevallier stm32_tamp_dev->pdata.is_tdcid) { 658*92ab6535SGatien Chevallier res = stm32_tamp_set_secure_bkpregs(); 659*92ab6535SGatien Chevallier if (res) 660*92ab6535SGatien Chevallier goto err_clk; 661*92ab6535SGatien Chevallier } 662*92ab6535SGatien Chevallier 66369b8b983SEtienne Carriere return TEE_SUCCESS; 66469b8b983SEtienne Carriere 66569b8b983SEtienne Carriere err_clk: 666461e8793SGatien Chevallier clk_disable(stm32_tamp_dev->pdata.clock); 66769b8b983SEtienne Carriere err: 668461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.conf_data) { 669461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->cid_confs); 670461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->sec_conf); 671461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->priv_conf); 672461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->access_mask); 673461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data); 674461e8793SGatien Chevallier } 675461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.bkpregs_conf.rif_offsets); 676461e8793SGatien Chevallier free(stm32_tamp_dev); 677461e8793SGatien Chevallier 67869b8b983SEtienne Carriere return res; 67969b8b983SEtienne Carriere } 68069b8b983SEtienne Carriere 68169b8b983SEtienne Carriere static const struct stm32_tamp_compat mp13_compat = { 68269b8b983SEtienne Carriere .nb_monotonic_counter = 2, 683461e8793SGatien Chevallier .tags = TAMP_HAS_REGISTER_SECCFGR | TAMP_HAS_REGISTER_PRIVCFGR, 68469b8b983SEtienne Carriere }; 68569b8b983SEtienne Carriere 68669b8b983SEtienne Carriere static const struct stm32_tamp_compat mp15_compat = { 68769b8b983SEtienne Carriere .nb_monotonic_counter = 1, 68869b8b983SEtienne Carriere .tags = 0, 68969b8b983SEtienne Carriere }; 69069b8b983SEtienne Carriere 691461e8793SGatien Chevallier static const struct stm32_tamp_compat mp25_compat = { 692461e8793SGatien Chevallier .nb_monotonic_counter = 2, 693461e8793SGatien Chevallier .tags = TAMP_HAS_REGISTER_SECCFGR | 694461e8793SGatien Chevallier TAMP_HAS_REGISTER_PRIVCFGR | 695461e8793SGatien Chevallier TAMP_HAS_RIF_SUPPORT, 696461e8793SGatien Chevallier }; 697461e8793SGatien Chevallier 69869b8b983SEtienne Carriere static const struct dt_device_match stm32_tamp_match_table[] = { 699461e8793SGatien Chevallier { .compatible = "st,stm32mp25-tamp", .compat_data = &mp25_compat }, 70069b8b983SEtienne Carriere { .compatible = "st,stm32mp13-tamp", .compat_data = &mp13_compat }, 70169b8b983SEtienne Carriere { .compatible = "st,stm32-tamp", .compat_data = &mp15_compat }, 70269b8b983SEtienne Carriere { } 70369b8b983SEtienne Carriere }; 70469b8b983SEtienne Carriere 70569b8b983SEtienne Carriere DEFINE_DT_DRIVER(stm32_tamp_dt_driver) = { 70669b8b983SEtienne Carriere .name = "stm32-tamp", 70769b8b983SEtienne Carriere .match_table = stm32_tamp_match_table, 70869b8b983SEtienne Carriere .probe = stm32_tamp_probe, 70969b8b983SEtienne Carriere }; 710