1ca530bf3SGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause 269b8b983SEtienne Carriere /* 3ca530bf3SGatien Chevallier * Copyright (c) 2021-2025, STMicroelectronics 469b8b983SEtienne Carriere */ 569b8b983SEtienne Carriere 6ca530bf3SGatien Chevallier #include <crypto/crypto.h> 769b8b983SEtienne Carriere #include <drivers/clk.h> 869b8b983SEtienne Carriere #include <drivers/clk_dt.h> 9ca530bf3SGatien Chevallier #include <drivers/gpio.h> 10ca530bf3SGatien Chevallier #include <drivers/stm32_gpio.h> 11461e8793SGatien Chevallier #include <drivers/stm32_rif.h> 12ca530bf3SGatien Chevallier #include <drivers/stm32_rtc.h> 13ca530bf3SGatien Chevallier #include <drivers/stm32mp_dt_bindings.h> 1469b8b983SEtienne Carriere #include <io.h> 1569b8b983SEtienne Carriere #include <kernel/dt.h> 169e3c57c8SEtienne Carriere #include <kernel/dt_driver.h> 1769b8b983SEtienne Carriere #include <kernel/interrupt.h> 1869b8b983SEtienne Carriere #include <libfdt.h> 1969b8b983SEtienne Carriere #include <mm/core_memprot.h> 2069b8b983SEtienne Carriere #include <stdbool.h> 21*112396a5SGatien Chevallier #include <stm32_util.h> 2269b8b983SEtienne Carriere 2369b8b983SEtienne Carriere /* STM32 Registers */ 2469b8b983SEtienne Carriere #define _TAMP_CR1 0x00U 2569b8b983SEtienne Carriere #define _TAMP_CR2 0x04U 2669b8b983SEtienne Carriere #define _TAMP_CR3 0x08U 2769b8b983SEtienne Carriere #define _TAMP_FLTCR 0x0CU 2869b8b983SEtienne Carriere #define _TAMP_ATCR1 0x10U 2969b8b983SEtienne Carriere #define _TAMP_ATSEEDR 0x14U 3069b8b983SEtienne Carriere #define _TAMP_ATOR 0x18U 3169b8b983SEtienne Carriere #define _TAMP_ATCR2 0x1CU 3269b8b983SEtienne Carriere #define _TAMP_SECCFGR 0x20U 3369b8b983SEtienne Carriere #define _TAMP_SMCR 0x20U 3469b8b983SEtienne Carriere #define _TAMP_PRIVCFGR 0x24U 3569b8b983SEtienne Carriere #define _TAMP_IER 0x2CU 3669b8b983SEtienne Carriere #define _TAMP_SR 0x30U 3769b8b983SEtienne Carriere #define _TAMP_MISR 0x34U 3869b8b983SEtienne Carriere #define _TAMP_SMISR 0x38U 3969b8b983SEtienne Carriere #define _TAMP_SCR 0x3CU 4069b8b983SEtienne Carriere #define _TAMP_COUNTR 0x40U 4169b8b983SEtienne Carriere #define _TAMP_COUNT2R 0x44U 4269b8b983SEtienne Carriere #define _TAMP_OR 0x50U 4369b8b983SEtienne Carriere #define _TAMP_ERCFGR 0X54U 44461e8793SGatien Chevallier #define _TAMP_BKPRIFR(x) (0x70U + 0x4U * ((x) - 1U)) 45461e8793SGatien Chevallier #define _TAMP_CIDCFGR(x) (0x80U + 0x4U * (x)) 46461e8793SGatien Chevallier #define _TAMP_BKPxR(x) (0x100U + 0x4U * ((x) - 1U)) 4769b8b983SEtienne Carriere #define _TAMP_HWCFGR2 0x3ECU 4869b8b983SEtienne Carriere #define _TAMP_HWCFGR1 0x3F0U 4969b8b983SEtienne Carriere #define _TAMP_VERR 0x3F4U 5069b8b983SEtienne Carriere #define _TAMP_IPIDR 0x3F8U 5169b8b983SEtienne Carriere #define _TAMP_SIDR 0x3FCU 5269b8b983SEtienne Carriere 5369b8b983SEtienne Carriere /* _TAMP_SECCFGR bit fields */ 5469b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_MASK GENMASK_32(7, 0) 5569b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_SHIFT 0U 5669b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT2SEC BIT(14) 57461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT2SEC_SHIFT 14U 5869b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT1SEC BIT(15) 59461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT1SEC_SHIFT 15U 6069b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_MASK GENMASK_32(23, 16) 6169b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_SHIFT 16U 6269b8b983SEtienne Carriere #define _TAMP_SECCFGR_BHKLOCK BIT(30) 6369b8b983SEtienne Carriere #define _TAMP_SECCFGR_TAMPSEC BIT(31) 64461e8793SGatien Chevallier #define _TAMP_SECCFGR_TAMPSEC_SHIFT 31U 6569b8b983SEtienne Carriere #define _TAMP_SECCFGR_BUT_BKP_MASK (GENMASK_32(31, 30) | \ 6669b8b983SEtienne Carriere GENMASK_32(15, 14)) 67461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_TAMP_SEC BIT(0) 68461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_1 BIT(1) 69461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_2 BIT(2) 7069b8b983SEtienne Carriere 7169b8b983SEtienne Carriere /* _TAMP_SMCR bit fields */ 7269b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK_32(7, 0) 7369b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_SHIFT 0U 7469b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_MASK GENMASK_32(23, 16) 7569b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_SHIFT 16U 7669b8b983SEtienne Carriere #define _TAMP_SMCR_DPROT BIT(31) 7769b8b983SEtienne Carriere /* 7869b8b983SEtienne Carriere * _TAMP_PRIVCFGR bit fields 7969b8b983SEtienne Carriere */ 8069b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV BIT(14) 8169b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV BIT(15) 8269b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) 8369b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV BIT(30) 8469b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV BIT(31) 8569b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ 8669b8b983SEtienne Carriere GENMASK_32(15, 14)) 87461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_TAMP_PRIV BIT(0) 88461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R1 BIT(1) 89461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R2 BIT(2) 9069b8b983SEtienne Carriere 91ca530bf3SGatien Chevallier /* _TAMP_PRIVCFGR bit fields */ 9269b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV BIT(14) 9369b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV BIT(15) 9469b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) 9569b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV BIT(30) 9669b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV BIT(31) 9769b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ 9869b8b983SEtienne Carriere GENMASK_32(15, 14)) 9969b8b983SEtienne Carriere 100ca530bf3SGatien Chevallier /*_TAMP_CR1 bit fields */ 101ca530bf3SGatien Chevallier #define _TAMP_CR1_ITAMP(id) BIT((id) - INT_TAMP1 + U(16)) 102ca530bf3SGatien Chevallier #define _TAMP_CR1_ETAMP(id) BIT((id) - EXT_TAMP1) 103ca530bf3SGatien Chevallier 104ca530bf3SGatien Chevallier /* _TAMP_CR2 bit fields */ 105ca530bf3SGatien Chevallier #define _TAMP_CR2_ETAMPTRG(id) BIT((id) - EXT_TAMP1 + U(24)) 106ca530bf3SGatien Chevallier #define _TAMP_CR2_BKERASE BIT(23) 107ca530bf3SGatien Chevallier #define _TAMP_CR2_BKBLOCK BIT(22) 108ca530bf3SGatien Chevallier #define _TAMP_CR2_ETAMPMSK_MAX_ID 3U 109ca530bf3SGatien Chevallier #define _TAMP_CR2_ETAMPMSK(id) BIT((id) - EXT_TAMP1 + U(16)) 110ca530bf3SGatien Chevallier #define _TAMP_CR2_ETAMPNOER(id) BIT((id) - EXT_TAMP1) 111ca530bf3SGatien Chevallier 112ca530bf3SGatien Chevallier /* _TAMP_CR3 bit fields */ 113ca530bf3SGatien Chevallier #define _TAMP_CR3_ITAMPNOER_ALL GENMASK_32(12, 0) 114ca530bf3SGatien Chevallier #define _TAMP_CR3_ITAMPNOER(id) BIT((id) - INT_TAMP1) 115ca530bf3SGatien Chevallier 116ca530bf3SGatien Chevallier /* _TAMP_FLTCR bit fields */ 117ca530bf3SGatien Chevallier #define _TAMP_FLTCR_TAMPFREQ_MASK GENMASK_32(2, 0) 118ca530bf3SGatien Chevallier #define _TAMP_FLTCR_TAMPFREQ_SHIFT 0U 119ca530bf3SGatien Chevallier #define _TAMP_FLTCR_TAMPFLT_MASK GENMASK_32(4, 3) 120ca530bf3SGatien Chevallier #define _TAMP_FLTCR_TAMPFLT_SHIFT U(3) 121ca530bf3SGatien Chevallier #define _TAMP_FLTCR_TAMPPRCH_MASK GENMASK_32(6, 5) 122ca530bf3SGatien Chevallier #define _TAMP_FLTCR_TAMPPRCH_SHIFT 5U 123ca530bf3SGatien Chevallier #define _TAMP_FLTCR_TAMPPUDIS BIT(7) 124ca530bf3SGatien Chevallier 125ca530bf3SGatien Chevallier /* _TAMP_ATCR bit fields */ 126ca530bf3SGatien Chevallier #define _TAMP_ATCR1_ATCKSEL_MASK GENMASK_32(19, 16) 127ca530bf3SGatien Chevallier #define _TAMP_ATCR1_ATCKSEL_SHIFT 16U 128ca530bf3SGatien Chevallier #define _TAMP_ATCR1_ATPER_MASK GENMASK_32(26, 24) 129ca530bf3SGatien Chevallier #define _TAMP_ATCR1_ATPER_SHIFT 24U 130ca530bf3SGatien Chevallier #define _TAMP_ATCR1_ATOSHARE BIT(30) 131ca530bf3SGatien Chevallier #define _TAMP_ATCR1_FLTEN BIT(31) 132ca530bf3SGatien Chevallier #define _TAMP_ATCR1_COMMON_MASK GENMASK_32(31, 16) 133ca530bf3SGatien Chevallier #define _TAMP_ATCR1_ETAMPAM(id) BIT((id) - EXT_TAMP1) 134ca530bf3SGatien Chevallier #define _TAMP_ATCR1_ATOSEL_MASK(id) \ 135ca530bf3SGatien Chevallier ({ \ 136ca530bf3SGatien Chevallier typeof(id) _id = (id); \ 137ca530bf3SGatien Chevallier GENMASK_32(((_id) - EXT_TAMP1 + 1) * 2 + 7, \ 138ca530bf3SGatien Chevallier ((_id) - EXT_TAMP1) * 2 + 8); \ 139ca530bf3SGatien Chevallier }) 140ca530bf3SGatien Chevallier 141ca530bf3SGatien Chevallier #define _TAMP_ATCR1_ATOSEL(id, od) \ 142ca530bf3SGatien Chevallier SHIFT_U32((od) - OUT_TAMP1, ((id) - EXT_TAMP1) * 2 + 8) 143ca530bf3SGatien Chevallier 144ca530bf3SGatien Chevallier /* _TAMP_ATCR2 bit fields */ 145ca530bf3SGatien Chevallier #define _TAMP_ATCR2_ATOSEL_MASK(id) \ 146ca530bf3SGatien Chevallier ({ \ 147ca530bf3SGatien Chevallier typeof(id) _id = (id); \ 148ca530bf3SGatien Chevallier GENMASK_32(((_id) - EXT_TAMP1 + 1) * 3 + 7, \ 149ca530bf3SGatien Chevallier ((_id) - EXT_TAMP1) * 3 + 8); \ 150ca530bf3SGatien Chevallier }) 151ca530bf3SGatien Chevallier 152ca530bf3SGatien Chevallier #define _TAMP_ATCR2_ATOSEL(id, od) \ 153ca530bf3SGatien Chevallier SHIFT_U32((od) - OUT_TAMP1, ((id) - EXT_TAMP1) * 3 + 8) 154ca530bf3SGatien Chevallier 155ca530bf3SGatien Chevallier /* _TAMP_ATOR bit fields */ 156ca530bf3SGatien Chevallier #define _TAMP_PRNG GENMASK_32(7, 0) 157ca530bf3SGatien Chevallier #define _TAMP_SEEDF BIT(14) 158ca530bf3SGatien Chevallier #define _TAMP_INITS BIT(15) 159ca530bf3SGatien Chevallier 160ca530bf3SGatien Chevallier /* _TAMP_IER bit fields */ 161ca530bf3SGatien Chevallier #define _TAMP_IER_ITAMP(id) BIT((id) - INT_TAMP1 + U(16)) 162ca530bf3SGatien Chevallier #define _TAMP_IER_ETAMP(id) BIT((id) - EXT_TAMP1) 163ca530bf3SGatien Chevallier 164ca530bf3SGatien Chevallier /* _TAMP_SR bit fields */ 165ca530bf3SGatien Chevallier #define _TAMP_SR_ETAMPXF_MASK GENMASK_32(7, 0) 166ca530bf3SGatien Chevallier #define _TAMP_SR_ITAMPXF_MASK GENMASK_32(31, 16) 167ca530bf3SGatien Chevallier #define _TAMP_SR_ITAMP(id) BIT((id) - INT_TAMP1 + U(16)) 168ca530bf3SGatien Chevallier #define _TAMP_SR_ETAMP(id) BIT((id) - EXT_TAMP1) 169ca530bf3SGatien Chevallier 170ca530bf3SGatien Chevallier /* _TAMP_SCR bit fields */ 171ca530bf3SGatien Chevallier #define _TAMP_SCR_ITAMP(id) BIT((id) - INT_TAMP1 + U(16)) 172ca530bf3SGatien Chevallier #define _TAMP_SCR_ETAMP(id) BIT((id) - EXT_TAMP1) 173ca530bf3SGatien Chevallier 174ca530bf3SGatien Chevallier /* _TAMP_OR bit fields */ 175ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP13_IN1RMP_PF10 0U 176ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP13_IN1RMP_PC13 BIT(0) 177ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP13_IN2RMP_PA6 0U 178ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP13_IN2RMP_PI1 BIT(1) 179ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP13_IN3RMP_PC0 0U 180ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP13_IN3RMP_PI2 BIT(2) 181ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP13_IN4RMP_PG8 0U 182ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP13_IN4RMP_PI3 BIT(3) 183ca530bf3SGatien Chevallier 184ca530bf3SGatien Chevallier /* For STM32MP15x, _TAMP_CFGR is _TAMP_OR */ 185ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP15_OUT3RMP_PI8 0U 186ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP15_OUT3RMP_PC13 BIT(0) 187ca530bf3SGatien Chevallier 188ca530bf3SGatien Chevallier #define _TAMP_STM32MP21_OR_IN1RMP_PC4 0U 189ca530bf3SGatien Chevallier #define _TAMP_STM32MP21_OR_IN1RMP_PI8 BIT(0) 190ca530bf3SGatien Chevallier 191ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP25_IN1RMP_PC4 0U 192ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP25_IN1RMP_PI8 BIT(0) 193ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP25_IN3RMP_PC3 0U 194ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP25_IN3RMP_PZ2 BIT(1) 195ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP25_IN5RMP_PF6 0U 196ca530bf3SGatien Chevallier #define _TAMP_OR_STM32MP25_IN5RMP_PZ4 BIT(2) 197ca530bf3SGatien Chevallier 19869b8b983SEtienne Carriere /* _TAMP_HWCFGR2 bit fields */ 19969b8b983SEtienne Carriere #define _TAMP_HWCFGR2_TZ GENMASK_32(11, 8) 20069b8b983SEtienne Carriere #define _TAMP_HWCFGR2_OR GENMASK_32(7, 0) 20169b8b983SEtienne Carriere 20269b8b983SEtienne Carriere /* _TAMP_HWCFGR1 bit fields */ 20369b8b983SEtienne Carriere #define _TAMP_HWCFGR1_BKPREG GENMASK_32(7, 0) 204ca530bf3SGatien Chevallier #define _TAMP_HWCFGR1_TAMPER_SHIFT 8U 20569b8b983SEtienne Carriere #define _TAMP_HWCFGR1_TAMPER GENMASK_32(11, 8) 20669b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ACTIVE GENMASK_32(15, 12) 20769b8b983SEtienne Carriere #define _TAMP_HWCFGR1_INTERN GENMASK_32(31, 16) 20869b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U 20969b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP(id) BIT((id) - INT_TAMP1 + 16U) 21069b8b983SEtienne Carriere 21169b8b983SEtienne Carriere /* _TAMP_VERR bit fields */ 21269b8b983SEtienne Carriere #define _TAMP_VERR_MINREV GENMASK_32(3, 0) 21369b8b983SEtienne Carriere #define _TAMP_VERR_MAJREV GENMASK_32(7, 4) 21469b8b983SEtienne Carriere 21569b8b983SEtienne Carriere /* 216461e8793SGatien Chevallier * CIDCFGR register bitfields 21769b8b983SEtienne Carriere */ 218461e8793SGatien Chevallier #define _TAMP_CIDCFGR_SCID_MASK GENMASK_32(6, 4) 219461e8793SGatien Chevallier #define _TAMP_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ 220461e8793SGatien Chevallier _CIDCFGR_SEMEN | \ 221461e8793SGatien Chevallier _TAMP_CIDCFGR_SCID_MASK) 222461e8793SGatien Chevallier 223461e8793SGatien Chevallier /* _TAMP_BKPRIFR */ 224461e8793SGatien Chevallier #define _TAMP_BKPRIFR_1_MASK GENMASK_32(7, 0) 225461e8793SGatien Chevallier #define _TAMP_BKPRIFR_2_MASK GENMASK_32(7, 0) 226461e8793SGatien Chevallier #define _TAMP_BKPRIFR_3_MASK (GENMASK_32(23, 16) | GENMASK_32(7, 0)) 227461e8793SGatien Chevallier #define _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT 16U 228461e8793SGatien Chevallier 229461e8793SGatien Chevallier /* 230461e8793SGatien Chevallier * RIF miscellaneous 231461e8793SGatien Chevallier */ 232461e8793SGatien Chevallier #define TAMP_NB_BKPR_ZONES 3U 233461e8793SGatien Chevallier #define TAMP_RIF_RESOURCES 3U 234461e8793SGatien Chevallier #define TAMP_RIF_OFFSET_CNT 4U 23569b8b983SEtienne Carriere 23669b8b983SEtienne Carriere /* 23769b8b983SEtienne Carriere * Compatibility capabilities 238461e8793SGatien Chevallier * TAMP_HAS_REGISTER_SECCFGR - Supports SECCFGR, otherwise supports SMCR 239461e8793SGatien Chevallier * register 24069b8b983SEtienne Carriere * TAMP_HAS_REGISTER_PRIVCFG - Supports PRIVCFGR configuration register 241461e8793SGatien Chevallier * TAMP_HAS_RIF_SUPPORT - Supports RIF 24269b8b983SEtienne Carriere */ 243461e8793SGatien Chevallier #define TAMP_HAS_REGISTER_SECCFGR BIT(0) 24469b8b983SEtienne Carriere #define TAMP_HAS_REGISTER_PRIVCFGR BIT(1) 245ca530bf3SGatien Chevallier #define TAMP_HAS_REGISTER_ERCFGR BIT(2) 246ca530bf3SGatien Chevallier #define TAMP_HAS_REGISTER_ATCR2 BIT(3) 247ca530bf3SGatien Chevallier #define TAMP_HAS_REGISTER_CR3 BIT(4) 248ca530bf3SGatien Chevallier #define TAMP_HAS_CR2_SECRET_STATUS BIT(5) 249ca530bf3SGatien Chevallier #define TAMP_SIZE_ATCR1_ATCKSEL_IS_4 BIT(7) 250461e8793SGatien Chevallier #define TAMP_HAS_RIF_SUPPORT BIT(31) 25169b8b983SEtienne Carriere 252ca530bf3SGatien Chevallier /* Tamper event modes */ 253ca530bf3SGatien Chevallier #define TAMP_ERASE 0x0U 254ca530bf3SGatien Chevallier #define TAMP_NOERASE BIT(1) 255ca530bf3SGatien Chevallier #define TAMP_NO_EVT_MASK 0x0U 256ca530bf3SGatien Chevallier #define TAMP_EVT_MASK BIT(2) 257ca530bf3SGatien Chevallier #define TAMP_MODE_MASK GENMASK_32(15, 0) 258ca530bf3SGatien Chevallier 259ca530bf3SGatien Chevallier /* Callback return bitmask values */ 260ca530bf3SGatien Chevallier #define TAMP_CB_ACK BIT(0) 261ca530bf3SGatien Chevallier #define TAMP_CB_RESET BIT(1) 262ca530bf3SGatien Chevallier #define TAMP_CB_ACK_AND_RESET (TAMP_CB_RESET | TAMP_CB_ACK) 263ca530bf3SGatien Chevallier 264ca530bf3SGatien Chevallier #define SEED_TIMEOUT_US 1000U 265ca530bf3SGatien Chevallier 266ca530bf3SGatien Chevallier /* Define TAMPER modes from DT */ 267ca530bf3SGatien Chevallier #define TAMP_TRIG_ON BIT(16) 268ca530bf3SGatien Chevallier #define TAMP_ACTIVE BIT(17) 269ca530bf3SGatien Chevallier #define TAMP_IN_DT BIT(18) 270ca530bf3SGatien Chevallier 271ca530bf3SGatien Chevallier enum stm32_tamp_id { 272ca530bf3SGatien Chevallier INT_TAMP1 = 0, 273ca530bf3SGatien Chevallier INT_TAMP2, 274ca530bf3SGatien Chevallier INT_TAMP3, 275ca530bf3SGatien Chevallier INT_TAMP4, 276ca530bf3SGatien Chevallier INT_TAMP5, 277ca530bf3SGatien Chevallier INT_TAMP6, 278ca530bf3SGatien Chevallier INT_TAMP7, 279ca530bf3SGatien Chevallier INT_TAMP8, 280ca530bf3SGatien Chevallier INT_TAMP9, 281ca530bf3SGatien Chevallier INT_TAMP10, 282ca530bf3SGatien Chevallier INT_TAMP11, 283ca530bf3SGatien Chevallier INT_TAMP12, 284ca530bf3SGatien Chevallier INT_TAMP13, 285ca530bf3SGatien Chevallier INT_TAMP14, 286ca530bf3SGatien Chevallier INT_TAMP15, 287ca530bf3SGatien Chevallier INT_TAMP16, 288ca530bf3SGatien Chevallier 289ca530bf3SGatien Chevallier EXT_TAMP1, 290ca530bf3SGatien Chevallier EXT_TAMP2, 291ca530bf3SGatien Chevallier EXT_TAMP3, 292ca530bf3SGatien Chevallier EXT_TAMP4, 293ca530bf3SGatien Chevallier EXT_TAMP5, 294ca530bf3SGatien Chevallier EXT_TAMP6, 295ca530bf3SGatien Chevallier EXT_TAMP7, 296ca530bf3SGatien Chevallier EXT_TAMP8, 297ca530bf3SGatien Chevallier 298ca530bf3SGatien Chevallier LAST_TAMP, 299ca530bf3SGatien Chevallier INVALID_TAMP = 0xFFFF, 300ca530bf3SGatien Chevallier }; 301ca530bf3SGatien Chevallier 302ca530bf3SGatien Chevallier enum stm32_tamp_out_id { 303ca530bf3SGatien Chevallier OUT_TAMP1 = LAST_TAMP, 304ca530bf3SGatien Chevallier OUT_TAMP2, 305ca530bf3SGatien Chevallier OUT_TAMP3, 306ca530bf3SGatien Chevallier OUT_TAMP4, 307ca530bf3SGatien Chevallier OUT_TAMP5, 308ca530bf3SGatien Chevallier OUT_TAMP6, 309ca530bf3SGatien Chevallier OUT_TAMP7, 310ca530bf3SGatien Chevallier OUT_TAMP8, 311ca530bf3SGatien Chevallier INVALID_OUT_TAMP = INVALID_TAMP 312ca530bf3SGatien Chevallier }; 313ca530bf3SGatien Chevallier 314ca530bf3SGatien Chevallier /** 315ca530bf3SGatien Chevallier * struct stm32_tamp_pin_map - Tamper pin map 316ca530bf3SGatien Chevallier * 317ca530bf3SGatien Chevallier * @id: Identifier of the tamper 318ca530bf3SGatien Chevallier * @conf: Internal mux configuration of the pin present in the TAMP block 319ca530bf3SGatien Chevallier * @bank: GPIO pin bank 320ca530bf3SGatien Chevallier * @pin: GPIO number in the bank 321ca530bf3SGatien Chevallier * @out: True if pin is used for tamper output 322ca530bf3SGatien Chevallier */ 323ca530bf3SGatien Chevallier struct stm32_tamp_pin_map { 324ca530bf3SGatien Chevallier uint32_t id; 325ca530bf3SGatien Chevallier uint32_t conf; 326ca530bf3SGatien Chevallier uint8_t bank; 327ca530bf3SGatien Chevallier uint8_t pin; 328ca530bf3SGatien Chevallier bool out; 329ca530bf3SGatien Chevallier }; 330ca530bf3SGatien Chevallier 331ca530bf3SGatien Chevallier /** 332ca530bf3SGatien Chevallier * struct stm32_tamp_tamper_data - Tamper data 333ca530bf3SGatien Chevallier * 334ca530bf3SGatien Chevallier * @id: Identifier of the tamper 335ca530bf3SGatien Chevallier * @out_id: Identifier of the output tamper, tamper in active mode 336ca530bf3SGatien Chevallier * @mode: Mode of the tamper 337ca530bf3SGatien Chevallier * @func: Tamper callback in case of tamper event 338ca530bf3SGatien Chevallier */ 339ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data { 340ca530bf3SGatien Chevallier uint32_t id; 341ca530bf3SGatien Chevallier uint32_t out_id; 342ca530bf3SGatien Chevallier uint32_t mode; 343ca530bf3SGatien Chevallier uint32_t (*func)(int id); 344ca530bf3SGatien Chevallier }; 345ca530bf3SGatien Chevallier 346461e8793SGatien Chevallier /** 347461e8793SGatien Chevallier * struct stm32_tamp_compat - TAMP compatible data 348ca530bf3SGatien Chevallier * 349ca530bf3SGatien Chevallier * @ext_tamp: List of available external tampers 350ca530bf3SGatien Chevallier * @int_tamp: List of available internal tampers 351ca530bf3SGatien Chevallier * @pin_map: List of hardware mapped of pins supporting tamper event detection 352461e8793SGatien Chevallier * @nb_monotonic_counter: Number of monotic counter supported 353ca530bf3SGatien Chevallier * @ext_tamp_size: Size of @ext_tamp 354ca530bf3SGatien Chevallier * @int_tamp_size: Size of @int_tamp 355ca530bf3SGatien Chevallier * @pin_map_size: Size of pin_map 356461e8793SGatien Chevallier * @tags: Bit flags TAMP_HAS_* for compatibility management 35769b8b983SEtienne Carriere */ 35869b8b983SEtienne Carriere struct stm32_tamp_compat { 359ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data *ext_tamp; 360ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data *int_tamp; 361ca530bf3SGatien Chevallier const struct stm32_tamp_pin_map *pin_map; 36269b8b983SEtienne Carriere int nb_monotonic_counter; 363ca530bf3SGatien Chevallier uint32_t ext_tamp_size; 364ca530bf3SGatien Chevallier uint32_t int_tamp_size; 365ca530bf3SGatien Chevallier uint32_t pin_map_size; 36669b8b983SEtienne Carriere uint32_t tags; 36769b8b983SEtienne Carriere }; 36869b8b983SEtienne Carriere 369461e8793SGatien Chevallier /* 37092ab6535SGatien Chevallier * struct stm32_bkpregs_conf - Backup registers zone bounds 371461e8793SGatien Chevallier * @zone1_end - Number of backup registers in zone 1 372461e8793SGatien Chevallier * @zone2_end - Number of backup registers in zone 2 + zone 1 373461e8793SGatien Chevallier * @rif_offsets - RIF offsets used for CID compartments 374461e8793SGatien Chevallier * 375461e8793SGatien Chevallier * TAMP backup registers access permissions 376461e8793SGatien Chevallier * 377461e8793SGatien Chevallier * Zone 1: read/write in secure state, no access in non-secure state 378461e8793SGatien Chevallier * Zone 2: read/write in secure state, read-only in non-secure state 379461e8793SGatien Chevallier * Zone 3: read/write in secure state, read/write in non-secure state 380461e8793SGatien Chevallier * 381461e8793SGatien Chevallier * Protection zone 1 382461e8793SGatien Chevallier * If zone1_end == 0 no backup register are in zone 1. 383461e8793SGatien Chevallier * Otherwise backup registers from TAMP_BKP0R to TAMP_BKP<x>R are in zone 1, 384461e8793SGatien Chevallier * with <x> = (@zone1_end - 1). 385461e8793SGatien Chevallier * 386461e8793SGatien Chevallier * Protection zone 2 387461e8793SGatien Chevallier * If zone2_end == 0 no backup register are in zone 2 and zone 1. 388461e8793SGatien Chevallier * Otherwise backup registers from TAMP_BKP<y>R to TAMP_BKP<z>R are in zone 2, 389461e8793SGatien Chevallier * with <y> = @zone1_end and <z> = (@zone2_end - 1). 390461e8793SGatien Chevallier * 391461e8793SGatien Chevallier * Protection zone 3 392461e8793SGatien Chevallier * Backup registers from TAMP_BKP<t>R to last backup register are in zone 3, 393461e8793SGatien Chevallier * with <t> = (@zone2_end - 1). 394461e8793SGatien Chevallier * 395461e8793SGatien Chevallier * When RIF is supported, each zone can be subdivided to restrain accesses to 396461e8793SGatien Chevallier * some CIDs. 397461e8793SGatien Chevallier */ 39892ab6535SGatien Chevallier struct stm32_bkpregs_conf { 399461e8793SGatien Chevallier uint32_t zone1_end; 400461e8793SGatien Chevallier uint32_t zone2_end; 401461e8793SGatien Chevallier uint32_t *rif_offsets; 402461e8793SGatien Chevallier }; 403461e8793SGatien Chevallier 404461e8793SGatien Chevallier /** 405461e8793SGatien Chevallier * struct stm32_tamp_platdata - TAMP platform data 406461e8793SGatien Chevallier * @base: IOMEM base address 407461e8793SGatien Chevallier * @bkpregs_conf: TAMP backup register configuration reference 408461e8793SGatien Chevallier * @compat: Reference to compat data passed at driver initialization 409461e8793SGatien Chevallier * @conf_data: RIF configuration data 410461e8793SGatien Chevallier * @clock: TAMP clock 411ca530bf3SGatien Chevallier * @itr: TAMP interrupt handler 412461e8793SGatien Chevallier * @nb_rif_resources: Number of RIF resources 413ca530bf3SGatien Chevallier * @passive_conf: Passive tampers configuration 414ca530bf3SGatien Chevallier * @active_conf: Active tampers configuration 415ca530bf3SGatien Chevallier * @pins_conf: Configuration of mapped pins for tampers 416ca530bf3SGatien Chevallier * @out_pins: Output pins for passive tampers 417ca530bf3SGatien Chevallier * @is_wakeup_source: True if a tamper event is a wakeup source 418461e8793SGatien Chevallier * @is_tdcid: True if current processor is TDCID 419461e8793SGatien Chevallier */ 420461e8793SGatien Chevallier struct stm32_tamp_platdata { 421461e8793SGatien Chevallier struct io_pa_va base; 42292ab6535SGatien Chevallier struct stm32_bkpregs_conf bkpregs_conf; 423461e8793SGatien Chevallier struct stm32_tamp_compat *compat; 424461e8793SGatien Chevallier struct rif_conf_data *conf_data; 425461e8793SGatien Chevallier struct clk *clock; 426ca530bf3SGatien Chevallier struct itr_handler *itr; 427461e8793SGatien Chevallier unsigned int nb_rif_resources; 428ca530bf3SGatien Chevallier uint32_t passive_conf; 429ca530bf3SGatien Chevallier uint32_t active_conf; 430ca530bf3SGatien Chevallier uint32_t pins_conf; 431ca530bf3SGatien Chevallier uint32_t out_pins; 432ca530bf3SGatien Chevallier bool is_wakeup_source; 433461e8793SGatien Chevallier bool is_tdcid; 434461e8793SGatien Chevallier }; 435461e8793SGatien Chevallier 436461e8793SGatien Chevallier /** 437461e8793SGatien Chevallier * struct stm32_tamp_instance - TAMP instance data 438461e8793SGatien Chevallier * @pdata: TAMP platform data 439461e8793SGatien Chevallier * @hwconf1: Copy of TAMP HWCONF1 register content 440461e8793SGatien Chevallier * @hwconf2: Copy of TAMP HWCONF2 register content 441461e8793SGatien Chevallier */ 442461e8793SGatien Chevallier struct stm32_tamp_instance { 443461e8793SGatien Chevallier struct stm32_tamp_platdata pdata; 444461e8793SGatien Chevallier uint32_t hwconf1; 445461e8793SGatien Chevallier uint32_t hwconf2; 446461e8793SGatien Chevallier }; 447461e8793SGatien Chevallier 448ca530bf3SGatien Chevallier #define GPIO_BANK(port) ((port) - 'A') 449ca530bf3SGatien Chevallier 450ca530bf3SGatien Chevallier #if defined(CFG_STM32MP13) 451ca530bf3SGatien Chevallier static const char * const itamper_name[] = { 452ca530bf3SGatien Chevallier [INT_TAMP1] = "Backup domain voltage threshold monitoring", 453ca530bf3SGatien Chevallier [INT_TAMP2] = "Temperature monitoring", 454ca530bf3SGatien Chevallier [INT_TAMP3] = "LSE monitoring", 455ca530bf3SGatien Chevallier [INT_TAMP4] = "HSE monitoring", 456ca530bf3SGatien Chevallier [INT_TAMP5] = "RTC Calendar overflow", 457ca530bf3SGatien Chevallier [INT_TAMP6] = "JTAG SWD access", 458ca530bf3SGatien Chevallier [INT_TAMP7] = "ADC2 analog watchdog monitoring 1", 459ca530bf3SGatien Chevallier [INT_TAMP8] = "Monotonic counter 1", 460ca530bf3SGatien Chevallier [INT_TAMP9] = "Cryptographic perpipheral fault", 461ca530bf3SGatien Chevallier [INT_TAMP10] = "Monotonic counter 2", 462ca530bf3SGatien Chevallier [INT_TAMP11] = "IWDG1 reset", 463ca530bf3SGatien Chevallier [INT_TAMP12] = "ADC2 analog watchdog monitoring 2", 464ca530bf3SGatien Chevallier [INT_TAMP13] = "ADC2 analog watchdog monitoring 3", 465ca530bf3SGatien Chevallier }; 466ca530bf3SGatien Chevallier 467ca530bf3SGatien Chevallier static struct stm32_tamp_tamper_data int_tamp_mp13[] = { 468ca530bf3SGatien Chevallier { .id = INT_TAMP1 }, { .id = INT_TAMP2 }, { .id = INT_TAMP3 }, 469ca530bf3SGatien Chevallier { .id = INT_TAMP4 }, { .id = INT_TAMP5 }, { .id = INT_TAMP6 }, 470ca530bf3SGatien Chevallier { .id = INT_TAMP7 }, { .id = INT_TAMP8 }, { .id = INT_TAMP9 }, 471ca530bf3SGatien Chevallier { .id = INT_TAMP10 }, { .id = INT_TAMP11 }, 472ca530bf3SGatien Chevallier { .id = INT_TAMP12 }, { .id = INT_TAMP13 }, 473ca530bf3SGatien Chevallier }; 474ca530bf3SGatien Chevallier 475ca530bf3SGatien Chevallier static struct stm32_tamp_tamper_data ext_tamp_mp13[] = { 476ca530bf3SGatien Chevallier { .id = EXT_TAMP1 }, { .id = EXT_TAMP2 }, { .id = EXT_TAMP3 }, 477ca530bf3SGatien Chevallier { .id = EXT_TAMP4 }, { .id = EXT_TAMP5 }, { .id = EXT_TAMP6 }, 478ca530bf3SGatien Chevallier { .id = EXT_TAMP7 }, { .id = EXT_TAMP8 }, 479ca530bf3SGatien Chevallier }; 480ca530bf3SGatien Chevallier 481ca530bf3SGatien Chevallier static const struct stm32_tamp_pin_map pin_map_mp13[] = { 482ca530bf3SGatien Chevallier { 483ca530bf3SGatien Chevallier .id = EXT_TAMP1, .bank = GPIO_BANK('C'), .pin = 13, 484ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP13_IN1RMP_PC13, 485ca530bf3SGatien Chevallier }, 486ca530bf3SGatien Chevallier { 487ca530bf3SGatien Chevallier .id = EXT_TAMP1, .bank = GPIO_BANK('F'), .pin = 10, 488ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP13_IN1RMP_PF10, 489ca530bf3SGatien Chevallier }, 490ca530bf3SGatien Chevallier { 491ca530bf3SGatien Chevallier .id = EXT_TAMP2, .bank = GPIO_BANK('A'), .pin = 6, 492ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP13_IN2RMP_PA6, 493ca530bf3SGatien Chevallier }, 494ca530bf3SGatien Chevallier { 495ca530bf3SGatien Chevallier .id = EXT_TAMP2, .bank = GPIO_BANK('I'), .pin = 1, 496ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP13_IN2RMP_PI1, 497ca530bf3SGatien Chevallier }, 498ca530bf3SGatien Chevallier { 499ca530bf3SGatien Chevallier .id = EXT_TAMP3, .bank = GPIO_BANK('C'), .pin = 0, 500ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP13_IN3RMP_PC0, 501ca530bf3SGatien Chevallier }, 502ca530bf3SGatien Chevallier { 503ca530bf3SGatien Chevallier .id = EXT_TAMP3, .bank = GPIO_BANK('I'), .pin = 2, 504ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP13_IN3RMP_PI2, 505ca530bf3SGatien Chevallier }, 506ca530bf3SGatien Chevallier { 507ca530bf3SGatien Chevallier .id = EXT_TAMP4, .bank = GPIO_BANK('G'), .pin = 8, 508ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP13_IN4RMP_PG8, 509ca530bf3SGatien Chevallier }, 510ca530bf3SGatien Chevallier { 511ca530bf3SGatien Chevallier .id = EXT_TAMP4, .bank = GPIO_BANK('I'), .pin = 3, 512ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP13_IN4RMP_PI3, 513ca530bf3SGatien Chevallier }, 514ca530bf3SGatien Chevallier }; 515ca530bf3SGatien Chevallier #endif 516ca530bf3SGatien Chevallier 517ca530bf3SGatien Chevallier #if defined(CFG_STM32MP15) 518ca530bf3SGatien Chevallier static const char * const itamper_name[] = { 519ca530bf3SGatien Chevallier [INT_TAMP1] = "RTC power domain", 520ca530bf3SGatien Chevallier [INT_TAMP2] = "Temperature monitoring", 521ca530bf3SGatien Chevallier [INT_TAMP3] = "LSE monitoring", 522ca530bf3SGatien Chevallier [INT_TAMP5] = "RTC Calendar overflow", 523ca530bf3SGatien Chevallier [INT_TAMP8] = "Monotonic counter", 524ca530bf3SGatien Chevallier }; 525ca530bf3SGatien Chevallier DECLARE_KEEP_PAGER(itamper_name); 526ca530bf3SGatien Chevallier 527ca530bf3SGatien Chevallier static struct stm32_tamp_tamper_data int_tamp_mp15[] = { 528ca530bf3SGatien Chevallier { .id = INT_TAMP1 }, { .id = INT_TAMP2 }, { .id = INT_TAMP3 }, 529ca530bf3SGatien Chevallier { .id = INT_TAMP4 }, { .id = INT_TAMP5 }, { .id = INT_TAMP8 }, 530ca530bf3SGatien Chevallier }; 531ca530bf3SGatien Chevallier 532ca530bf3SGatien Chevallier static struct stm32_tamp_tamper_data ext_tamp_mp15[] = { 533ca530bf3SGatien Chevallier { .id = EXT_TAMP1 }, { .id = EXT_TAMP2 }, { .id = EXT_TAMP3 }, 534ca530bf3SGatien Chevallier }; 535ca530bf3SGatien Chevallier 536ca530bf3SGatien Chevallier static const struct stm32_tamp_pin_map pin_map_mp15[] = { 537ca530bf3SGatien Chevallier { 538ca530bf3SGatien Chevallier .id = EXT_TAMP1, .bank = GPIO_BANK('C'), .pin = 13, 539ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP15_OUT3RMP_PI8, 540ca530bf3SGatien Chevallier }, 541ca530bf3SGatien Chevallier { 542ca530bf3SGatien Chevallier .id = EXT_TAMP2, .bank = GPIO_BANK('I'), .pin = 8, 543ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP15_OUT3RMP_PI8, 544ca530bf3SGatien Chevallier }, 545ca530bf3SGatien Chevallier { 546ca530bf3SGatien Chevallier .id = EXT_TAMP3, .bank = GPIO_BANK('C'), .pin = 1, 547ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP15_OUT3RMP_PI8, 548ca530bf3SGatien Chevallier }, 549ca530bf3SGatien Chevallier { 550ca530bf3SGatien Chevallier .id = OUT_TAMP2, .bank = GPIO_BANK('C'), .pin = 13, 551ca530bf3SGatien Chevallier .out = true, .conf = _TAMP_OR_STM32MP15_OUT3RMP_PI8, 552ca530bf3SGatien Chevallier }, 553ca530bf3SGatien Chevallier { 554ca530bf3SGatien Chevallier .id = OUT_TAMP3, .bank = GPIO_BANK('C'), .pin = 13, 555ca530bf3SGatien Chevallier .out = true, .conf = _TAMP_OR_STM32MP15_OUT3RMP_PC13, 556ca530bf3SGatien Chevallier }, 557ca530bf3SGatien Chevallier { 558ca530bf3SGatien Chevallier .id = OUT_TAMP3, .bank = GPIO_BANK('I'), .pin = 8, 559ca530bf3SGatien Chevallier .out = true, .conf = _TAMP_OR_STM32MP15_OUT3RMP_PI8, 560ca530bf3SGatien Chevallier }, 561ca530bf3SGatien Chevallier }; 562ca530bf3SGatien Chevallier #endif 563ca530bf3SGatien Chevallier 564ca530bf3SGatien Chevallier #if defined(CFG_STM32MP21) 565ca530bf3SGatien Chevallier static const char * const itamper_name[] = { 566ca530bf3SGatien Chevallier [INT_TAMP1] = "Backup domain voltage threshold monitoring", 567ca530bf3SGatien Chevallier [INT_TAMP2] = "Temperature monitoring", 568ca530bf3SGatien Chevallier [INT_TAMP3] = "LSE monitoring", 569ca530bf3SGatien Chevallier [INT_TAMP4] = "HSE monitoring", 570ca530bf3SGatien Chevallier [INT_TAMP5] = "RTC Calendar overflow", 571ca530bf3SGatien Chevallier [INT_TAMP6] = "JTAG TAP access in secured-closed", 572ca530bf3SGatien Chevallier [INT_TAMP7] = "ADC2 analog watchdog monitoring1", 573ca530bf3SGatien Chevallier [INT_TAMP8] = "Monotonic counter 1 overflow", 574ca530bf3SGatien Chevallier [INT_TAMP9] = "Cryptographic peripherals fault", 575ca530bf3SGatien Chevallier [INT_TAMP10] = "Monotonic counter 2 overflow", 576ca530bf3SGatien Chevallier [INT_TAMP11] = "IWDG3 reset", 577ca530bf3SGatien Chevallier [INT_TAMP12] = "ADC2 analog watchdog monitoring2", 578ca530bf3SGatien Chevallier [INT_TAMP13] = "ADC2 analog watchdog monitoring3", 579ca530bf3SGatien Chevallier [INT_TAMP14] = "RIFSC or BSEC or DBGMCU fault", 580ca530bf3SGatien Chevallier [INT_TAMP15] = "IWDG1_reset", 581ca530bf3SGatien Chevallier [INT_TAMP16] = "BOOTROM fault", 582ca530bf3SGatien Chevallier }; 583ca530bf3SGatien Chevallier 584ca530bf3SGatien Chevallier static struct stm32_tamp_tamper_data int_tamp_mp21[] = { 585ca530bf3SGatien Chevallier { .id = INT_TAMP1 }, { .id = INT_TAMP2 }, { .id = INT_TAMP3 }, 586ca530bf3SGatien Chevallier { .id = INT_TAMP4 }, { .id = INT_TAMP5 }, { .id = INT_TAMP6 }, 587ca530bf3SGatien Chevallier { .id = INT_TAMP7 }, { .id = INT_TAMP8 }, { .id = INT_TAMP9 }, 588ca530bf3SGatien Chevallier { .id = INT_TAMP10 }, { .id = INT_TAMP11 }, { .id = INT_TAMP12 }, 589ca530bf3SGatien Chevallier { .id = INT_TAMP13 }, { .id = INT_TAMP14 }, { .id = INT_TAMP15 }, 590ca530bf3SGatien Chevallier { .id = INT_TAMP16 }, 591ca530bf3SGatien Chevallier }; 592ca530bf3SGatien Chevallier 593ca530bf3SGatien Chevallier static struct stm32_tamp_tamper_data ext_tamp_mp21[] = { 594ca530bf3SGatien Chevallier { .id = EXT_TAMP1 }, { .id = EXT_TAMP2 }, { .id = EXT_TAMP3 }, 595ca530bf3SGatien Chevallier { .id = EXT_TAMP4 }, { .id = EXT_TAMP5 }, { .id = EXT_TAMP6 }, 596ca530bf3SGatien Chevallier { .id = EXT_TAMP7 }, 597ca530bf3SGatien Chevallier }; 598ca530bf3SGatien Chevallier 599ca530bf3SGatien Chevallier static const struct stm32_tamp_pin_map pin_map_mp21[] = { 600ca530bf3SGatien Chevallier { 601ca530bf3SGatien Chevallier .id = EXT_TAMP1, .bank = GPIO_BANK('I'), .pin = 8, 602ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_STM32MP21_OR_IN1RMP_PI8, 603ca530bf3SGatien Chevallier }, 604ca530bf3SGatien Chevallier { 605ca530bf3SGatien Chevallier .id = EXT_TAMP1, .bank = GPIO_BANK('C'), .pin = 4, 606ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_STM32MP21_OR_IN1RMP_PC4, 607ca530bf3SGatien Chevallier }, 608ca530bf3SGatien Chevallier }; 609ca530bf3SGatien Chevallier #endif 610ca530bf3SGatien Chevallier 611ca530bf3SGatien Chevallier #if defined(CFG_STM32MP25) 612ca530bf3SGatien Chevallier static const char * const itamper_name[] = { 613ca530bf3SGatien Chevallier [INT_TAMP1] = "Backup domain voltage threshold monitoring", 614ca530bf3SGatien Chevallier [INT_TAMP2] = "Temperature monitoring", 615ca530bf3SGatien Chevallier [INT_TAMP3] = "LSE monitoring", 616ca530bf3SGatien Chevallier [INT_TAMP4] = "HSE monitoring", 617ca530bf3SGatien Chevallier [INT_TAMP5] = "RTC Calendar overflow", 618ca530bf3SGatien Chevallier [INT_TAMP6] = "JTAG/SWD access", 619ca530bf3SGatien Chevallier [INT_TAMP7] = "VDDCORE monitoring under/over voltage", 620ca530bf3SGatien Chevallier [INT_TAMP8] = "Monotonic counter 1 overflow", 621ca530bf3SGatien Chevallier [INT_TAMP9] = "Cryptographic peripherals fault", 622ca530bf3SGatien Chevallier [INT_TAMP10] = "Monotonic counter 2 overflow", 623ca530bf3SGatien Chevallier [INT_TAMP11] = "IWDG3 reset", 624ca530bf3SGatien Chevallier [INT_TAMP12] = "VDDCPU monitoring under/over voltage", 625ca530bf3SGatien Chevallier [INT_TAMP14] = "IWDG5_reset", 626ca530bf3SGatien Chevallier [INT_TAMP15] = "IWDG1_reset", 627ca530bf3SGatien Chevallier }; 628ca530bf3SGatien Chevallier 629ca530bf3SGatien Chevallier static struct stm32_tamp_tamper_data int_tamp_mp25[] = { 630ca530bf3SGatien Chevallier { .id = INT_TAMP1 }, { .id = INT_TAMP2 }, { .id = INT_TAMP3 }, 631ca530bf3SGatien Chevallier { .id = INT_TAMP4 }, { .id = INT_TAMP5 }, { .id = INT_TAMP6 }, 632ca530bf3SGatien Chevallier { .id = INT_TAMP7 }, { .id = INT_TAMP8 }, { .id = INT_TAMP9 }, 633ca530bf3SGatien Chevallier { .id = INT_TAMP10 }, { .id = INT_TAMP11 }, 634ca530bf3SGatien Chevallier { .id = INT_TAMP12 }, { .id = INT_TAMP14 }, 635ca530bf3SGatien Chevallier { .id = INT_TAMP15 }, 636ca530bf3SGatien Chevallier }; 637ca530bf3SGatien Chevallier 638ca530bf3SGatien Chevallier static struct stm32_tamp_tamper_data ext_tamp_mp25[] = { 639ca530bf3SGatien Chevallier { .id = EXT_TAMP1 }, { .id = EXT_TAMP2 }, { .id = EXT_TAMP3 }, 640ca530bf3SGatien Chevallier { .id = EXT_TAMP4 }, { .id = EXT_TAMP5 }, { .id = EXT_TAMP6 }, 641ca530bf3SGatien Chevallier { .id = EXT_TAMP7 }, { .id = EXT_TAMP8 }, 642ca530bf3SGatien Chevallier }; 643ca530bf3SGatien Chevallier 644ca530bf3SGatien Chevallier static const struct stm32_tamp_pin_map pin_map_mp25[] = { 645ca530bf3SGatien Chevallier { 646ca530bf3SGatien Chevallier .id = EXT_TAMP1, .bank = GPIO_BANK('I'), .pin = 8, 647ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP25_IN1RMP_PI8, 648ca530bf3SGatien Chevallier }, 649ca530bf3SGatien Chevallier { 650ca530bf3SGatien Chevallier .id = EXT_TAMP1, .bank = GPIO_BANK('C'), .pin = 4, 651ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP25_IN1RMP_PC4, 652ca530bf3SGatien Chevallier }, 653ca530bf3SGatien Chevallier { 654ca530bf3SGatien Chevallier .id = EXT_TAMP3, .bank = GPIO_BANK('C'), .pin = 3, 655ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP25_IN3RMP_PC3, 656ca530bf3SGatien Chevallier }, 657ca530bf3SGatien Chevallier { 658ca530bf3SGatien Chevallier .id = EXT_TAMP3, .bank = GPIO_BANK('Z'), .pin = 2, 659ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP25_IN3RMP_PZ2, 660ca530bf3SGatien Chevallier }, 661ca530bf3SGatien Chevallier { 662ca530bf3SGatien Chevallier .id = EXT_TAMP5, .bank = GPIO_BANK('F'), .pin = 6, 663ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP25_IN5RMP_PF6, 664ca530bf3SGatien Chevallier }, 665ca530bf3SGatien Chevallier { 666ca530bf3SGatien Chevallier .id = EXT_TAMP5, .bank = GPIO_BANK('Z'), .pin = 4, 667ca530bf3SGatien Chevallier .out = false, .conf = _TAMP_OR_STM32MP25_IN5RMP_PZ4, 668ca530bf3SGatien Chevallier }, 669ca530bf3SGatien Chevallier }; 670ca530bf3SGatien Chevallier #endif 671ca530bf3SGatien Chevallier 67269b8b983SEtienne Carriere /* Expects at most a single instance */ 673461e8793SGatien Chevallier static struct stm32_tamp_instance *stm32_tamp_dev; 674461e8793SGatien Chevallier 675ca530bf3SGatien Chevallier static vaddr_t get_base(void) 676ca530bf3SGatien Chevallier { 677ca530bf3SGatien Chevallier assert(stm32_tamp_dev && stm32_tamp_dev->pdata.base.pa); 678ca530bf3SGatien Chevallier 679ca530bf3SGatien Chevallier return io_pa_or_va_secure(&stm32_tamp_dev->pdata.base, 1); 680ca530bf3SGatien Chevallier } 681ca530bf3SGatien Chevallier 682461e8793SGatien Chevallier static void apply_rif_config(void) 683461e8793SGatien Chevallier { 684461e8793SGatien Chevallier struct rif_conf_data *rif_conf = stm32_tamp_dev->pdata.conf_data; 685461e8793SGatien Chevallier uint32_t access_mask_priv_reg = 0; 686461e8793SGatien Chevallier uint32_t access_mask_sec_reg = 0; 687ca530bf3SGatien Chevallier vaddr_t base = get_base(); 688461e8793SGatien Chevallier uint32_t privcfgr = 0; 689461e8793SGatien Chevallier uint32_t seccfgr = 0; 690461e8793SGatien Chevallier unsigned int i = 0; 691461e8793SGatien Chevallier 692461e8793SGatien Chevallier if (!stm32_tamp_dev->pdata.conf_data) 693461e8793SGatien Chevallier return; 694461e8793SGatien Chevallier 695461e8793SGatien Chevallier /* Build access masks for _TAMP_PRIVCFGR and _TAMP_SECCFGR */ 696461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) { 697461e8793SGatien Chevallier if (BIT(i) & rif_conf->access_mask[0]) { 698461e8793SGatien Chevallier switch (i) { 699461e8793SGatien Chevallier case 0: 700461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_TAMPSEC; 701461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_TAMPPRIV; 702461e8793SGatien Chevallier break; 703461e8793SGatien Chevallier case 1: 704461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_CNT1SEC; 705461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_CNT1PRIV; 706461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_BKPRWPRIV; 707461e8793SGatien Chevallier break; 708461e8793SGatien Chevallier case 2: 709461e8793SGatien Chevallier access_mask_sec_reg |= _TAMP_SECCFGR_CNT2SEC; 710461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_CNT2PRIV; 711461e8793SGatien Chevallier access_mask_priv_reg |= _TAMP_PRIVCFG_BKPWPRIV; 712461e8793SGatien Chevallier break; 713461e8793SGatien Chevallier default: 714461e8793SGatien Chevallier panic(); 715461e8793SGatien Chevallier } 716461e8793SGatien Chevallier } 717461e8793SGatien Chevallier } 718461e8793SGatien Chevallier 719461e8793SGatien Chevallier /* 720461e8793SGatien Chevallier * When TDCID, OP-TEE should be the one to set the CID filtering 721461e8793SGatien Chevallier * configuration. Clearing previous configuration prevents 722461e8793SGatien Chevallier * undesired events during the only legitimate configuration. 723461e8793SGatien Chevallier */ 724461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.is_tdcid) { 725461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) 726461e8793SGatien Chevallier if (BIT(i) & rif_conf->access_mask[0]) 727461e8793SGatien Chevallier io_clrbits32(base + _TAMP_CIDCFGR(i), 728461e8793SGatien Chevallier _TAMP_CIDCFGR_CONF_MASK); 729461e8793SGatien Chevallier } 730461e8793SGatien Chevallier 731461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_TAMP_SEC) 732461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_TAMPSEC; 733461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_1) 734461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_CNT1SEC; 735461e8793SGatien Chevallier if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_2) 736461e8793SGatien Chevallier seccfgr |= _TAMP_SECCFGR_CNT2SEC; 737461e8793SGatien Chevallier 738461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_TAMP_PRIV) 739461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_TAMPPRIV; 740461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R1) 741461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_CNT1PRIV | _TAMP_PRIVCFG_BKPRWPRIV; 742461e8793SGatien Chevallier if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R2) 743461e8793SGatien Chevallier privcfgr |= _TAMP_PRIVCFG_CNT2PRIV | _TAMP_PRIVCFG_BKPWPRIV; 744461e8793SGatien Chevallier 745461e8793SGatien Chevallier /* Security and privilege RIF configuration */ 746461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_PRIVCFGR, access_mask_priv_reg, privcfgr); 747461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_SECCFGR, access_mask_sec_reg, seccfgr); 748461e8793SGatien Chevallier 749461e8793SGatien Chevallier if (!stm32_tamp_dev->pdata.is_tdcid) 750461e8793SGatien Chevallier return; 751461e8793SGatien Chevallier 752461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_RESOURCES; i++) { 753461e8793SGatien Chevallier if (!(BIT(i) & rif_conf->access_mask[0])) 754461e8793SGatien Chevallier continue; 755461e8793SGatien Chevallier 756461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_CIDCFGR(i), 757461e8793SGatien Chevallier _TAMP_CIDCFGR_CONF_MASK, 758461e8793SGatien Chevallier rif_conf->cid_confs[i]); 759461e8793SGatien Chevallier } 760461e8793SGatien Chevallier } 761461e8793SGatien Chevallier 762461e8793SGatien Chevallier static TEE_Result stm32_tamp_apply_bkpr_rif_conf(void) 763461e8793SGatien Chevallier { 76492ab6535SGatien Chevallier struct stm32_bkpregs_conf *bkpregs_conf = 765461e8793SGatien Chevallier &stm32_tamp_dev->pdata.bkpregs_conf; 766ca530bf3SGatien Chevallier vaddr_t base = get_base(); 767461e8793SGatien Chevallier unsigned int i = 0; 768461e8793SGatien Chevallier 769461e8793SGatien Chevallier if (!bkpregs_conf->rif_offsets) 770461e8793SGatien Chevallier panic("No backup register configuration"); 771461e8793SGatien Chevallier 772461e8793SGatien Chevallier for (i = 0; i < TAMP_RIF_OFFSET_CNT; i++) { 773461e8793SGatien Chevallier if (bkpregs_conf->rif_offsets[i] > 774461e8793SGatien Chevallier (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) 775461e8793SGatien Chevallier return TEE_ERROR_NOT_SUPPORTED; 776461e8793SGatien Chevallier } 777461e8793SGatien Chevallier 778461e8793SGatien Chevallier /* Fill the 3 TAMP_BKPRIFRx registers */ 779461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(1), _TAMP_BKPRIFR_1_MASK, 780461e8793SGatien Chevallier bkpregs_conf->rif_offsets[0]); 781461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(2), _TAMP_BKPRIFR_2_MASK, 782461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1]); 783461e8793SGatien Chevallier io_clrsetbits32(base + _TAMP_BKPRIFR(3), _TAMP_BKPRIFR_3_MASK, 784461e8793SGatien Chevallier bkpregs_conf->rif_offsets[2] | 785461e8793SGatien Chevallier SHIFT_U32(bkpregs_conf->rif_offsets[3], 786461e8793SGatien Chevallier _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT)); 787461e8793SGatien Chevallier 788461e8793SGatien Chevallier DMSG("Backup registers mapping :"); 789461e8793SGatien Chevallier DMSG("********START of zone 1********"); 790461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF1 begins at register: 0"); 791461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF2 begins at register: %"PRIu32, 792461e8793SGatien Chevallier bkpregs_conf->rif_offsets[0]); 793461e8793SGatien Chevallier DMSG("Protection Zone 1-RIF2 ends at register: %"PRIu32, 794461e8793SGatien Chevallier bkpregs_conf->zone1_end ? bkpregs_conf->zone1_end - 1 : 0); 795461e8793SGatien Chevallier DMSG("********END of zone 1********"); 796461e8793SGatien Chevallier DMSG("********START of zone 2********"); 797461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF1 begins at register: %"PRIu32, 798461e8793SGatien Chevallier bkpregs_conf->zone1_end); 799461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF2 begins at register: %"PRIu32, 800461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1]); 801461e8793SGatien Chevallier DMSG("Protection Zone 2-RIF2 ends at register: %"PRIu32, 802461e8793SGatien Chevallier bkpregs_conf->rif_offsets[1] > bkpregs_conf->zone1_end ? 803461e8793SGatien Chevallier bkpregs_conf->zone2_end - 1 : 0); 804461e8793SGatien Chevallier DMSG("********END of zone 2********"); 805461e8793SGatien Chevallier DMSG("********START of zone 3********"); 806461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF1 begins at register: %"PRIu32, 807461e8793SGatien Chevallier bkpregs_conf->zone2_end); 808461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF0 begins at register: %"PRIu32, 809461e8793SGatien Chevallier bkpregs_conf->rif_offsets[2]); 810461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF2 begins at register: %"PRIu32, 811461e8793SGatien Chevallier bkpregs_conf->rif_offsets[3]); 812461e8793SGatien Chevallier DMSG("Protection Zone 3-RIF2 ends at the last register: %"PRIu32, 813461e8793SGatien Chevallier stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG); 814461e8793SGatien Chevallier DMSG("********END of zone 3********"); 815461e8793SGatien Chevallier 816461e8793SGatien Chevallier return TEE_SUCCESS; 817461e8793SGatien Chevallier } 81869b8b983SEtienne Carriere 81992ab6535SGatien Chevallier static TEE_Result stm32_tamp_set_secure_bkpregs(void) 82069b8b983SEtienne Carriere { 82192ab6535SGatien Chevallier struct stm32_bkpregs_conf *bkpregs_conf = 82292ab6535SGatien Chevallier &stm32_tamp_dev->pdata.bkpregs_conf; 823ca530bf3SGatien Chevallier vaddr_t base = get_base(); 82469b8b983SEtienne Carriere uint32_t first_z2 = 0; 82569b8b983SEtienne Carriere uint32_t first_z3 = 0; 82669b8b983SEtienne Carriere 82792ab6535SGatien Chevallier first_z2 = bkpregs_conf->zone1_end; 82892ab6535SGatien Chevallier first_z3 = bkpregs_conf->zone2_end; 82969b8b983SEtienne Carriere 830461e8793SGatien Chevallier if ((first_z2 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) || 831461e8793SGatien Chevallier (first_z3 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG))) 83269b8b983SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 83369b8b983SEtienne Carriere 834461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 835461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) { 83669b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 83769b8b983SEtienne Carriere _TAMP_SECCFGR_BKPRWSEC_MASK, 83869b8b983SEtienne Carriere (first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) & 83969b8b983SEtienne Carriere _TAMP_SECCFGR_BKPRWSEC_MASK); 84069b8b983SEtienne Carriere 84169b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 84269b8b983SEtienne Carriere _TAMP_SECCFGR_BKPWSEC_MASK, 84369b8b983SEtienne Carriere (first_z3 << _TAMP_SECCFGR_BKPWSEC_SHIFT) & 84469b8b983SEtienne Carriere _TAMP_SECCFGR_BKPWSEC_MASK); 84569b8b983SEtienne Carriere } else { 84669b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SMCR, 84769b8b983SEtienne Carriere _TAMP_SMCR_BKPRWDPROT_MASK, 84869b8b983SEtienne Carriere (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) & 84969b8b983SEtienne Carriere _TAMP_SMCR_BKPRWDPROT_MASK); 85069b8b983SEtienne Carriere 85169b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SMCR, 85269b8b983SEtienne Carriere _TAMP_SMCR_BKPWDPROT_MASK, 85369b8b983SEtienne Carriere (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) & 85469b8b983SEtienne Carriere _TAMP_SMCR_BKPWDPROT_MASK); 85569b8b983SEtienne Carriere } 85669b8b983SEtienne Carriere 85769b8b983SEtienne Carriere return TEE_SUCCESS; 85869b8b983SEtienne Carriere } 85969b8b983SEtienne Carriere 860461e8793SGatien Chevallier static void stm32_tamp_set_secure(uint32_t mode) 86169b8b983SEtienne Carriere { 862ca530bf3SGatien Chevallier vaddr_t base = get_base(); 86369b8b983SEtienne Carriere 864461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 865461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) { 86669b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_SECCFGR, 86769b8b983SEtienne Carriere _TAMP_SECCFGR_BUT_BKP_MASK, 86869b8b983SEtienne Carriere mode & _TAMP_SECCFGR_BUT_BKP_MASK); 86969b8b983SEtienne Carriere } else { 87069b8b983SEtienne Carriere /* 87169b8b983SEtienne Carriere * Note: MP15 doesn't use SECCFG register and 87269b8b983SEtienne Carriere * inverts the secure bit. 87369b8b983SEtienne Carriere */ 87469b8b983SEtienne Carriere if (mode & _TAMP_SECCFGR_TAMPSEC) 87569b8b983SEtienne Carriere io_clrbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); 87669b8b983SEtienne Carriere else 87769b8b983SEtienne Carriere io_setbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); 87869b8b983SEtienne Carriere } 87969b8b983SEtienne Carriere } 88069b8b983SEtienne Carriere 881461e8793SGatien Chevallier static void stm32_tamp_set_privilege(uint32_t mode) 88269b8b983SEtienne Carriere { 883ca530bf3SGatien Chevallier vaddr_t base = get_base(); 88469b8b983SEtienne Carriere 885461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 886461e8793SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_PRIVCFGR)) 88769b8b983SEtienne Carriere io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK, 88869b8b983SEtienne Carriere mode & _TAMP_PRIVCFGR_MASK); 88969b8b983SEtienne Carriere } 89069b8b983SEtienne Carriere 89192ab6535SGatien Chevallier static void parse_bkpregs_dt_conf(const void *fdt, int node) 892461e8793SGatien Chevallier { 89392ab6535SGatien Chevallier struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata; 894461e8793SGatien Chevallier unsigned int bkpregs_count = 0; 89592ab6535SGatien Chevallier const fdt32_t *cuint = NULL; 896461e8793SGatien Chevallier int lenp = 0; 897461e8793SGatien Chevallier 898461e8793SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,backup-zones", &lenp); 899461e8793SGatien Chevallier if (!cuint) 900461e8793SGatien Chevallier panic("Missing backup registers configuration"); 901461e8793SGatien Chevallier 902461e8793SGatien Chevallier /* 903461e8793SGatien Chevallier * When TAMP does not support RIF, the backup registers can 904461e8793SGatien Chevallier * be splited in 3 zones. These zones have specific read/write 905461e8793SGatien Chevallier * access permissions based on the secure status of the accesser. 906461e8793SGatien Chevallier * When RIF is supported, these zones can additionally be splited 907461e8793SGatien Chevallier * in subzones that have CID filtering. Zones/Subzones can be empty and 908461e8793SGatien Chevallier * are contiguous. 909461e8793SGatien Chevallier */ 91092ab6535SGatien Chevallier if (!(pdata->compat->tags & TAMP_HAS_RIF_SUPPORT)) { 911461e8793SGatien Chevallier /* 3 zones, 2 offsets to apply */ 912461e8793SGatien Chevallier if (lenp != sizeof(uint32_t) * TAMP_NB_BKPR_ZONES) 913461e8793SGatien Chevallier panic("Incorrect bkpregs configuration"); 914461e8793SGatien Chevallier 915461e8793SGatien Chevallier pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]); 916461e8793SGatien Chevallier bkpregs_count = fdt32_to_cpu(cuint[0]); 917461e8793SGatien Chevallier 918461e8793SGatien Chevallier pdata->bkpregs_conf.zone2_end = bkpregs_count + 919461e8793SGatien Chevallier fdt32_to_cpu(cuint[1]); 920461e8793SGatien Chevallier } else { 921461e8793SGatien Chevallier /* 922461e8793SGatien Chevallier * Zone 3 923461e8793SGatien Chevallier * ----------------------| 924461e8793SGatien Chevallier * Protection Zone 3-RIF2|Read non- 925461e8793SGatien Chevallier * ----------------------|secure 926461e8793SGatien Chevallier * Protection Zone 3-RIF0|Write non- 927461e8793SGatien Chevallier * ----------------------|secure 928461e8793SGatien Chevallier * Protection Zone 3-RIF1| 929461e8793SGatien Chevallier * ----------------------| 930461e8793SGatien Chevallier * 931461e8793SGatien Chevallier * Zone 2 932461e8793SGatien Chevallier * ----------------------| 933461e8793SGatien Chevallier * Protection Zone 2-RIF2|Read non- 934461e8793SGatien Chevallier * ----------------------|secure 935461e8793SGatien Chevallier * Protection Zone 2-RIF1|Write secure 936461e8793SGatien Chevallier * ----------------------| 937461e8793SGatien Chevallier * 938461e8793SGatien Chevallier * Zone 1 939461e8793SGatien Chevallier * ----------------------| 940461e8793SGatien Chevallier * Protection Zone 1-RIF2|Read secure 941461e8793SGatien Chevallier * ----------------------|Write secure 942461e8793SGatien Chevallier * Protection Zone 1-RIF1| 943461e8793SGatien Chevallier * ----------------------| 944461e8793SGatien Chevallier * 945461e8793SGatien Chevallier * (BHK => First 8 registers) 946461e8793SGatien Chevallier */ 947461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets = calloc(TAMP_RIF_OFFSET_CNT, 948461e8793SGatien Chevallier sizeof(uint32_t)); 949461e8793SGatien Chevallier if (!pdata->bkpregs_conf.rif_offsets) 950461e8793SGatien Chevallier panic(); 951461e8793SGatien Chevallier 952461e8793SGatien Chevallier /* 953461e8793SGatien Chevallier * 3 zones with 7 subzones in total(6 offsets): 954461e8793SGatien Chevallier * - 2 zone offsets 955461e8793SGatien Chevallier * - 4 subzones offsets 956461e8793SGatien Chevallier */ 957461e8793SGatien Chevallier if (lenp != sizeof(uint32_t) * 958461e8793SGatien Chevallier (TAMP_RIF_OFFSET_CNT + TAMP_NB_BKPR_ZONES)) 959461e8793SGatien Chevallier panic("Incorrect bkpregs configuration"); 960461e8793SGatien Chevallier 961461e8793SGatien Chevallier /* Backup registers zone 1 */ 962461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[0] = fdt32_to_cpu(cuint[0]); 963461e8793SGatien Chevallier pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]) + 964461e8793SGatien Chevallier fdt32_to_cpu(cuint[1]); 965461e8793SGatien Chevallier 966461e8793SGatien Chevallier bkpregs_count = pdata->bkpregs_conf.zone1_end; 967461e8793SGatien Chevallier 968461e8793SGatien Chevallier /* Backup registers zone 2 */ 969461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[1] = bkpregs_count + 970461e8793SGatien Chevallier fdt32_to_cpu(cuint[2]); 971461e8793SGatien Chevallier pdata->bkpregs_conf.zone2_end = bkpregs_count + 972461e8793SGatien Chevallier fdt32_to_cpu(cuint[2]) + 973461e8793SGatien Chevallier fdt32_to_cpu(cuint[3]); 974461e8793SGatien Chevallier 975461e8793SGatien Chevallier bkpregs_count = pdata->bkpregs_conf.zone2_end; 976461e8793SGatien Chevallier 977461e8793SGatien Chevallier /* Backup registers zone 3 */ 978461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[2] = bkpregs_count + 979461e8793SGatien Chevallier fdt32_to_cpu(cuint[4]); 980461e8793SGatien Chevallier pdata->bkpregs_conf.rif_offsets[3] = bkpregs_count + 981461e8793SGatien Chevallier fdt32_to_cpu(cuint[4]) + 982461e8793SGatien Chevallier fdt32_to_cpu(cuint[5]); 983461e8793SGatien Chevallier } 984461e8793SGatien Chevallier } 985461e8793SGatien Chevallier 986ca530bf3SGatien Chevallier static void stm32_tamp_set_pins(vaddr_t base, uint32_t mode) 987ca530bf3SGatien Chevallier { 988ca530bf3SGatien Chevallier io_setbits32(base + _TAMP_OR, mode); 989ca530bf3SGatien Chevallier } 990ca530bf3SGatien Chevallier 991ca530bf3SGatien Chevallier static TEE_Result stm32_tamp_set_seed(vaddr_t base) 992ca530bf3SGatien Chevallier { 993ca530bf3SGatien Chevallier uint32_t value = 0; 994ca530bf3SGatien Chevallier int idx = 0; 995ca530bf3SGatien Chevallier 996ca530bf3SGatien Chevallier for (idx = 0; idx < 4; idx++) { 997ca530bf3SGatien Chevallier uint32_t rnd = 0; 998ca530bf3SGatien Chevallier 999ca530bf3SGatien Chevallier if (crypto_rng_read(&rnd, sizeof(uint32_t))) 1000ca530bf3SGatien Chevallier return TEE_ERROR_BAD_STATE; 1001ca530bf3SGatien Chevallier 1002ca530bf3SGatien Chevallier io_write32(base + _TAMP_ATSEEDR, rnd); 1003ca530bf3SGatien Chevallier } 1004ca530bf3SGatien Chevallier 1005ca530bf3SGatien Chevallier if (IO_READ32_POLL_TIMEOUT(base + _TAMP_ATOR, value, 1006ca530bf3SGatien Chevallier !(value & _TAMP_SEEDF), 0, SEED_TIMEOUT_US)) 1007ca530bf3SGatien Chevallier return TEE_ERROR_BAD_STATE; 1008ca530bf3SGatien Chevallier 1009ca530bf3SGatien Chevallier return TEE_SUCCESS; 1010ca530bf3SGatien Chevallier } 1011ca530bf3SGatien Chevallier 1012ca530bf3SGatien Chevallier static TEE_Result is_int_tamp_id_valid(enum stm32_tamp_id id) 1013ca530bf3SGatien Chevallier { 1014ca530bf3SGatien Chevallier if (id - INT_TAMP1 >= _TAMP_HWCFGR1_ITAMP_MAX_ID) 1015ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1016ca530bf3SGatien Chevallier 1017ca530bf3SGatien Chevallier if (!(stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_ITAMP(id))) 1018ca530bf3SGatien Chevallier return TEE_ERROR_ITEM_NOT_FOUND; 1019ca530bf3SGatien Chevallier 1020ca530bf3SGatien Chevallier return TEE_SUCCESS; 1021ca530bf3SGatien Chevallier } 1022ca530bf3SGatien Chevallier 1023ca530bf3SGatien Chevallier static bool is_ext_tamp_id_valid(enum stm32_tamp_id id) 1024ca530bf3SGatien Chevallier { 1025ca530bf3SGatien Chevallier return id - EXT_TAMP1 <= 1026ca530bf3SGatien Chevallier (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_TAMPER) >> 1027ca530bf3SGatien Chevallier _TAMP_HWCFGR1_TAMPER_SHIFT; 1028ca530bf3SGatien Chevallier } 1029ca530bf3SGatien Chevallier 1030ca530bf3SGatien Chevallier static enum itr_return stm32_tamp_it_handler(struct itr_handler *h __unused) 1031ca530bf3SGatien Chevallier { 1032ca530bf3SGatien Chevallier struct optee_rtc_time __maybe_unused tamp_ts = { }; 1033ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1034ca530bf3SGatien Chevallier uint32_t it = io_read32(base + _TAMP_SR); 1035ca530bf3SGatien Chevallier uint32_t int_it = it & _TAMP_SR_ITAMPXF_MASK; 1036ca530bf3SGatien Chevallier uint32_t ext_it = it & _TAMP_SR_ETAMPXF_MASK; 1037ca530bf3SGatien Chevallier bool ts_enabled = false; 1038ca530bf3SGatien Chevallier size_t i = 0; 1039ca530bf3SGatien Chevallier 1040ca530bf3SGatien Chevallier if (stm32_rtc_is_timestamp_enabled(&ts_enabled)) 1041ca530bf3SGatien Chevallier panic(); 1042ca530bf3SGatien Chevallier 1043ca530bf3SGatien Chevallier if (ts_enabled && it) { 1044ca530bf3SGatien Chevallier TEE_Result res = stm32_rtc_get_timestamp(&tamp_ts); 1045ca530bf3SGatien Chevallier 1046ca530bf3SGatien Chevallier if (res) 1047ca530bf3SGatien Chevallier EMSG("Failed to get RTC timestamp: %"PRIx32, res); 1048ca530bf3SGatien Chevallier FMSG("Tamper event occurred at:"); 1049ca530bf3SGatien Chevallier FMSG("\n \t Date: %"PRIu32"/%"PRIu32"\n \t Time: %"PRIu32":%"PRIu32":%"PRIu32, 1050ca530bf3SGatien Chevallier tamp_ts.tm_mday, tamp_ts.tm_mon, tamp_ts.tm_hour, 1051ca530bf3SGatien Chevallier tamp_ts.tm_min, tamp_ts.tm_sec); 1052ca530bf3SGatien Chevallier } 1053ca530bf3SGatien Chevallier 1054ca530bf3SGatien Chevallier while (int_it && i < stm32_tamp_dev->pdata.compat->int_tamp_size) { 1055ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data int_tamp = 1056ca530bf3SGatien Chevallier stm32_tamp_dev->pdata.compat->int_tamp[i]; 1057ca530bf3SGatien Chevallier int id = int_tamp.id; 1058ca530bf3SGatien Chevallier 1059ca530bf3SGatien Chevallier if (int_it & _TAMP_SR_ITAMP(id)) { 1060ca530bf3SGatien Chevallier uint32_t ret = 0; 1061ca530bf3SGatien Chevallier 1062ca530bf3SGatien Chevallier int_it &= ~_TAMP_SR_ITAMP(id); 1063ca530bf3SGatien Chevallier 1064ca530bf3SGatien Chevallier if (int_tamp.func) 1065ca530bf3SGatien Chevallier ret = int_tamp.func(id); 1066ca530bf3SGatien Chevallier 1067ca530bf3SGatien Chevallier if (ret & TAMP_CB_ACK) 1068ca530bf3SGatien Chevallier io_setbits32(base + _TAMP_SCR, 1069ca530bf3SGatien Chevallier _TAMP_SCR_ITAMP(id)); 1070ca530bf3SGatien Chevallier 1071ca530bf3SGatien Chevallier if (ret & TAMP_CB_RESET) 1072*112396a5SGatien Chevallier do_reset("Internal tamper event detected"); 1073ca530bf3SGatien Chevallier } 1074ca530bf3SGatien Chevallier i++; 1075ca530bf3SGatien Chevallier } 1076ca530bf3SGatien Chevallier 1077ca530bf3SGatien Chevallier i = 0; 1078ca530bf3SGatien Chevallier /* External tamper interrupt */ 1079ca530bf3SGatien Chevallier while (ext_it && i < stm32_tamp_dev->pdata.compat->ext_tamp_size) { 1080ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data ext_tamp = 1081ca530bf3SGatien Chevallier stm32_tamp_dev->pdata.compat->ext_tamp[i]; 1082ca530bf3SGatien Chevallier int id = ext_tamp.id; 1083ca530bf3SGatien Chevallier 1084ca530bf3SGatien Chevallier if (ext_it & _TAMP_SR_ETAMP(id)) { 1085ca530bf3SGatien Chevallier uint32_t ret = 0; 1086ca530bf3SGatien Chevallier 1087ca530bf3SGatien Chevallier ext_it &= ~_TAMP_SR_ETAMP(id); 1088ca530bf3SGatien Chevallier 1089ca530bf3SGatien Chevallier if (ext_tamp.func) 1090ca530bf3SGatien Chevallier ret = ext_tamp.func(id); 1091ca530bf3SGatien Chevallier 1092ca530bf3SGatien Chevallier if (ret & TAMP_CB_ACK) 1093ca530bf3SGatien Chevallier io_setbits32(base + _TAMP_SCR, 1094ca530bf3SGatien Chevallier _TAMP_SCR_ETAMP(id)); 1095ca530bf3SGatien Chevallier 1096ca530bf3SGatien Chevallier if (ret & TAMP_CB_RESET) 1097*112396a5SGatien Chevallier do_reset("External tamper event detected"); 1098ca530bf3SGatien Chevallier } 1099ca530bf3SGatien Chevallier i++; 1100ca530bf3SGatien Chevallier } 1101ca530bf3SGatien Chevallier 1102ca530bf3SGatien Chevallier return ITRR_HANDLED; 1103ca530bf3SGatien Chevallier } 1104ca530bf3SGatien Chevallier DECLARE_KEEP_PAGER(stm32_tamp_it_handler); 1105ca530bf3SGatien Chevallier 1106ca530bf3SGatien Chevallier static TEE_Result stm32_tamp_set_int_config(struct stm32_tamp_compat *tcompat, 1107ca530bf3SGatien Chevallier uint32_t itamp_index, uint32_t *cr1, 1108ca530bf3SGatien Chevallier uint32_t *cr3, uint32_t *ier) 1109ca530bf3SGatien Chevallier { 1110ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data *tamp_int = NULL; 1111ca530bf3SGatien Chevallier enum stm32_tamp_id id = INVALID_TAMP; 1112ca530bf3SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 1113ca530bf3SGatien Chevallier 1114ca530bf3SGatien Chevallier if (!tcompat) 1115ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1116ca530bf3SGatien Chevallier 1117ca530bf3SGatien Chevallier tamp_int = &tcompat->int_tamp[itamp_index]; 1118ca530bf3SGatien Chevallier id = tamp_int->id; 1119ca530bf3SGatien Chevallier 1120ca530bf3SGatien Chevallier res = is_int_tamp_id_valid(id); 1121ca530bf3SGatien Chevallier if (res == TEE_ERROR_ITEM_NOT_FOUND) 1122ca530bf3SGatien Chevallier return TEE_SUCCESS; 1123ca530bf3SGatien Chevallier else if (res) 1124ca530bf3SGatien Chevallier return res; 1125ca530bf3SGatien Chevallier 1126ca530bf3SGatien Chevallier /* 1127ca530bf3SGatien Chevallier * If there is no callback 1128ca530bf3SGatien Chevallier * this tamper is disabled, we reset its configuration. 1129ca530bf3SGatien Chevallier */ 1130ca530bf3SGatien Chevallier if (!tamp_int->func) { 1131ca530bf3SGatien Chevallier *cr1 &= ~_TAMP_CR1_ITAMP(id); 1132ca530bf3SGatien Chevallier *ier &= ~_TAMP_IER_ITAMP(id); 1133ca530bf3SGatien Chevallier if (tcompat->tags & TAMP_HAS_REGISTER_CR3) 1134ca530bf3SGatien Chevallier *cr3 &= ~_TAMP_CR3_ITAMPNOER(id); 1135ca530bf3SGatien Chevallier 1136ca530bf3SGatien Chevallier FMSG("INT_TAMP%d disabled", id - INT_TAMP1 + 1); 1137ca530bf3SGatien Chevallier return TEE_SUCCESS; 1138ca530bf3SGatien Chevallier } 1139ca530bf3SGatien Chevallier 1140ca530bf3SGatien Chevallier *cr1 |= _TAMP_CR1_ITAMP(id); 1141ca530bf3SGatien Chevallier *ier |= _TAMP_IER_ITAMP(id); 1142ca530bf3SGatien Chevallier 1143ca530bf3SGatien Chevallier if (tcompat->tags & TAMP_HAS_REGISTER_CR3) { 1144ca530bf3SGatien Chevallier if (tamp_int->mode & TAMP_NOERASE) 1145ca530bf3SGatien Chevallier *cr3 |= _TAMP_CR3_ITAMPNOER(id); 1146ca530bf3SGatien Chevallier else 1147ca530bf3SGatien Chevallier *cr3 &= ~_TAMP_CR3_ITAMPNOER(id); 1148ca530bf3SGatien Chevallier } 1149ca530bf3SGatien Chevallier 1150ca530bf3SGatien Chevallier DMSG("'%s' internal tamper enabled in %s mode", 1151ca530bf3SGatien Chevallier itamper_name[id - INT_TAMP1], 1152ca530bf3SGatien Chevallier (tamp_int->mode & TAMP_NOERASE) ? "potential" : "confirmed"); 1153ca530bf3SGatien Chevallier 1154ca530bf3SGatien Chevallier return TEE_SUCCESS; 1155ca530bf3SGatien Chevallier } 1156ca530bf3SGatien Chevallier 1157ca530bf3SGatien Chevallier static TEE_Result stm32_tamp_set_ext_config(struct stm32_tamp_compat *tcompat, 1158ca530bf3SGatien Chevallier uint32_t etamp_index, uint32_t *cr1, 1159ca530bf3SGatien Chevallier uint32_t *cr2, uint32_t *atcr1, 1160ca530bf3SGatien Chevallier uint32_t *atcr2, uint32_t *ier) 1161ca530bf3SGatien Chevallier { 1162ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data *tamp_ext = NULL; 1163ca530bf3SGatien Chevallier enum stm32_tamp_id id = INVALID_TAMP; 1164ca530bf3SGatien Chevallier 1165ca530bf3SGatien Chevallier if (!tcompat) 1166ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1167ca530bf3SGatien Chevallier 1168ca530bf3SGatien Chevallier tamp_ext = &tcompat->ext_tamp[etamp_index]; 1169ca530bf3SGatien Chevallier id = tamp_ext->id; 1170ca530bf3SGatien Chevallier 1171ca530bf3SGatien Chevallier /* Exit if not a valid TAMP_ID */ 1172ca530bf3SGatien Chevallier if (!is_ext_tamp_id_valid(id)) 1173ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1174ca530bf3SGatien Chevallier 1175ca530bf3SGatien Chevallier /* 1176ca530bf3SGatien Chevallier * If there is no callback or this TAMPER wasn't defined in DT, 1177ca530bf3SGatien Chevallier * this tamper is disabled, we reset its configuration. 1178ca530bf3SGatien Chevallier */ 1179ca530bf3SGatien Chevallier if (!tamp_ext->func || !(tamp_ext->mode & TAMP_IN_DT)) { 1180ca530bf3SGatien Chevallier *cr1 &= ~_TAMP_CR1_ETAMP(id); 1181ca530bf3SGatien Chevallier *cr2 &= ~_TAMP_CR2_ETAMPMSK(id); 1182ca530bf3SGatien Chevallier *cr2 &= ~_TAMP_CR2_ETAMPTRG(id); 1183ca530bf3SGatien Chevallier *cr2 &= ~_TAMP_CR2_ETAMPNOER(id); 1184ca530bf3SGatien Chevallier *ier &= ~_TAMP_IER_ETAMP(id); 1185ca530bf3SGatien Chevallier 1186ca530bf3SGatien Chevallier FMSG("EXT_TAMP%d disabled", id - EXT_TAMP1 + 1); 1187ca530bf3SGatien Chevallier return TEE_SUCCESS; 1188ca530bf3SGatien Chevallier } 1189ca530bf3SGatien Chevallier 1190ca530bf3SGatien Chevallier *cr1 |= _TAMP_CR1_ETAMP(id); 1191ca530bf3SGatien Chevallier 1192ca530bf3SGatien Chevallier if (tamp_ext->mode & TAMP_TRIG_ON) 1193ca530bf3SGatien Chevallier *cr2 |= _TAMP_CR2_ETAMPTRG(id); 1194ca530bf3SGatien Chevallier else 1195ca530bf3SGatien Chevallier *cr2 &= ~_TAMP_CR2_ETAMPTRG(id); 1196ca530bf3SGatien Chevallier 1197ca530bf3SGatien Chevallier if (tamp_ext->mode & TAMP_ACTIVE) { 1198ca530bf3SGatien Chevallier *atcr1 |= _TAMP_ATCR1_ETAMPAM(id); 1199ca530bf3SGatien Chevallier 1200ca530bf3SGatien Chevallier /* Configure output pin if ATOSHARE is selected */ 1201ca530bf3SGatien Chevallier if (*atcr1 & _TAMP_ATCR1_ATOSHARE) { 1202ca530bf3SGatien Chevallier if (tcompat->tags & TAMP_HAS_REGISTER_ATCR2) 1203ca530bf3SGatien Chevallier *atcr2 = (*atcr2 & 1204ca530bf3SGatien Chevallier ~_TAMP_ATCR2_ATOSEL_MASK(id)) | 1205ca530bf3SGatien Chevallier _TAMP_ATCR2_ATOSEL(id, 1206ca530bf3SGatien Chevallier tamp_ext->out_id); 1207ca530bf3SGatien Chevallier else 1208ca530bf3SGatien Chevallier *atcr1 = (*atcr1 & 1209ca530bf3SGatien Chevallier ~_TAMP_ATCR1_ATOSEL_MASK(id)) | 1210ca530bf3SGatien Chevallier _TAMP_ATCR1_ATOSEL(id, 1211ca530bf3SGatien Chevallier tamp_ext->out_id); 1212ca530bf3SGatien Chevallier } 1213ca530bf3SGatien Chevallier } else { 1214ca530bf3SGatien Chevallier *atcr1 &= ~_TAMP_ATCR1_ETAMPAM(id); 1215ca530bf3SGatien Chevallier } 1216ca530bf3SGatien Chevallier 1217ca530bf3SGatien Chevallier if (tamp_ext->mode & TAMP_NOERASE) 1218ca530bf3SGatien Chevallier *cr2 |= _TAMP_CR2_ETAMPNOER(id); 1219ca530bf3SGatien Chevallier else 1220ca530bf3SGatien Chevallier *cr2 &= ~_TAMP_CR2_ETAMPNOER(id); 1221ca530bf3SGatien Chevallier 1222ca530bf3SGatien Chevallier if (id < _TAMP_CR2_ETAMPMSK_MAX_ID) { 1223ca530bf3SGatien Chevallier /* 1224ca530bf3SGatien Chevallier * Only external TAMP 1, 2 and 3 can be masked 1225ca530bf3SGatien Chevallier * and we may want them masked at startup. 1226ca530bf3SGatien Chevallier */ 1227ca530bf3SGatien Chevallier if (tamp_ext->mode & TAMP_EVT_MASK) { 1228ca530bf3SGatien Chevallier /* 1229ca530bf3SGatien Chevallier * ETAMP(id) event generates a trigger event. This 1230ca530bf3SGatien Chevallier * ETAMP(id) is masked and internally cleared by 1231ca530bf3SGatien Chevallier * hardware. 1232ca530bf3SGatien Chevallier * The secrets are not erased. 1233ca530bf3SGatien Chevallier */ 1234ca530bf3SGatien Chevallier *ier &= ~_TAMP_IER_ETAMP(id); 1235ca530bf3SGatien Chevallier *cr2 |= _TAMP_CR2_ETAMPMSK(id); 1236ca530bf3SGatien Chevallier } else { 1237ca530bf3SGatien Chevallier /* 1238ca530bf3SGatien Chevallier * normal ETAMP interrupt: 1239ca530bf3SGatien Chevallier * ETAMP(id) event generates a trigger event and 1240ca530bf3SGatien Chevallier * TAMP(id) must be cleared by software to allow 1241ca530bf3SGatien Chevallier * next tamper event detection. 1242ca530bf3SGatien Chevallier */ 1243ca530bf3SGatien Chevallier *ier |= _TAMP_IER_ETAMP(id); 1244ca530bf3SGatien Chevallier *cr2 &= ~_TAMP_CR2_ETAMPMSK(id); 1245ca530bf3SGatien Chevallier } 1246ca530bf3SGatien Chevallier } else { 1247ca530bf3SGatien Chevallier /* Other than 1,2,3 external TAMP, we want its interrupt */ 1248ca530bf3SGatien Chevallier *ier |= _TAMP_IER_ETAMP(id); 1249ca530bf3SGatien Chevallier } 1250ca530bf3SGatien Chevallier 1251ca530bf3SGatien Chevallier DMSG("EXT_TAMP%d enabled as a %s tamper in %s mode, trig_%s %s", 1252ca530bf3SGatien Chevallier id - EXT_TAMP1 + 1, 1253ca530bf3SGatien Chevallier (tamp_ext->mode & TAMP_ACTIVE) ? "active" : "passive", 1254ca530bf3SGatien Chevallier (tamp_ext->mode & TAMP_NOERASE) ? "potential" : "confirmed", 1255ca530bf3SGatien Chevallier (tamp_ext->mode & TAMP_TRIG_ON) ? "on" : "off", 1256ca530bf3SGatien Chevallier (tamp_ext->mode & TAMP_EVT_MASK) ? " (masked)" : ""); 1257ca530bf3SGatien Chevallier 1258ca530bf3SGatien Chevallier if (tamp_ext->mode & TAMP_ACTIVE) 1259ca530bf3SGatien Chevallier DMSG(" linked with OUT_TAMP%"PRIu32, 1260ca530bf3SGatien Chevallier tamp_ext->out_id - OUT_TAMP1 + 1); 1261ca530bf3SGatien Chevallier 1262ca530bf3SGatien Chevallier return TEE_SUCCESS; 1263ca530bf3SGatien Chevallier } 1264ca530bf3SGatien Chevallier 1265ca530bf3SGatien Chevallier /* 1266ca530bf3SGatien Chevallier * Count number of 1 in bitmask 1267ca530bf3SGatien Chevallier * Cannot use __builtin_popcount(): libgcc.a for ARMV7 use hardfloat ABI, 1268ca530bf3SGatien Chevallier * but OP-TEE core is compiled with softfloat ABI. 1269ca530bf3SGatien Chevallier */ 1270ca530bf3SGatien Chevallier static int popcount(uint32_t bitmask) 1271ca530bf3SGatien Chevallier { 1272ca530bf3SGatien Chevallier int nb = 0; 1273ca530bf3SGatien Chevallier 1274ca530bf3SGatien Chevallier while (bitmask) { 1275ca530bf3SGatien Chevallier if (bitmask & 1) 1276ca530bf3SGatien Chevallier nb++; 1277ca530bf3SGatien Chevallier bitmask >>= 1; 1278ca530bf3SGatien Chevallier } 1279ca530bf3SGatien Chevallier 1280ca530bf3SGatien Chevallier return nb; 1281ca530bf3SGatien Chevallier } 1282ca530bf3SGatien Chevallier 1283ca530bf3SGatien Chevallier static void stm32_tamp_set_atper(uint32_t pins_out_bits, uint32_t *atcr1) 1284ca530bf3SGatien Chevallier { 1285ca530bf3SGatien Chevallier uint32_t conf = 0; 1286ca530bf3SGatien Chevallier 1287ca530bf3SGatien Chevallier switch (popcount(pins_out_bits)) { 1288ca530bf3SGatien Chevallier case 0: 1289ca530bf3SGatien Chevallier case 1: 1290ca530bf3SGatien Chevallier conf = 0; 1291ca530bf3SGatien Chevallier break; 1292ca530bf3SGatien Chevallier case 2: 1293ca530bf3SGatien Chevallier conf = 1; 1294ca530bf3SGatien Chevallier break; 1295ca530bf3SGatien Chevallier case 3: 1296ca530bf3SGatien Chevallier case 4: 1297ca530bf3SGatien Chevallier conf = 2; 1298ca530bf3SGatien Chevallier break; 1299ca530bf3SGatien Chevallier default: 1300ca530bf3SGatien Chevallier conf = 3; 1301ca530bf3SGatien Chevallier break; 1302ca530bf3SGatien Chevallier } 1303ca530bf3SGatien Chevallier 1304ca530bf3SGatien Chevallier *atcr1 |= SHIFT_U32(conf, _TAMP_ATCR1_ATPER_SHIFT) & 1305ca530bf3SGatien Chevallier _TAMP_ATCR1_ATPER_MASK; 1306ca530bf3SGatien Chevallier } 1307ca530bf3SGatien Chevallier 1308ca530bf3SGatien Chevallier static TEE_Result stm32_tamp_set_config(void) 1309ca530bf3SGatien Chevallier { 1310ca530bf3SGatien Chevallier TEE_Result ret = TEE_SUCCESS; 1311ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1312ca530bf3SGatien Chevallier uint32_t atcr1 = 0; 1313ca530bf3SGatien Chevallier uint32_t atcr2 = 0; 1314ca530bf3SGatien Chevallier uint32_t fltcr = 0; 1315ca530bf3SGatien Chevallier uint32_t cr1 = 0; 1316ca530bf3SGatien Chevallier uint32_t cr2 = 0; 1317ca530bf3SGatien Chevallier uint32_t cr3 = 0; 1318ca530bf3SGatien Chevallier uint32_t ier = 0; 1319ca530bf3SGatien Chevallier size_t i = 0; 1320ca530bf3SGatien Chevallier 1321ca530bf3SGatien Chevallier if (!stm32_tamp_dev->pdata.compat || 1322ca530bf3SGatien Chevallier !stm32_tamp_dev->pdata.compat->int_tamp || 1323ca530bf3SGatien Chevallier !stm32_tamp_dev->pdata.compat->ext_tamp) 1324ca530bf3SGatien Chevallier return TEE_ERROR_BAD_STATE; 1325ca530bf3SGatien Chevallier 1326ca530bf3SGatien Chevallier /* Set passive filter configuration */ 1327ca530bf3SGatien Chevallier fltcr = stm32_tamp_dev->pdata.passive_conf; 1328ca530bf3SGatien Chevallier 1329ca530bf3SGatien Chevallier /* Set active mode configuration */ 1330ca530bf3SGatien Chevallier atcr1 = stm32_tamp_dev->pdata.active_conf & _TAMP_ATCR1_COMMON_MASK; 1331ca530bf3SGatien Chevallier stm32_tamp_set_atper(stm32_tamp_dev->pdata.out_pins, &atcr1); 1332ca530bf3SGatien Chevallier 1333ca530bf3SGatien Chevallier for (i = 0; i < stm32_tamp_dev->pdata.compat->int_tamp_size; i++) { 1334ca530bf3SGatien Chevallier ret = stm32_tamp_set_int_config(stm32_tamp_dev->pdata.compat, i, 1335ca530bf3SGatien Chevallier &cr1, &cr3, &ier); 1336ca530bf3SGatien Chevallier if (ret) 1337ca530bf3SGatien Chevallier return ret; 1338ca530bf3SGatien Chevallier } 1339ca530bf3SGatien Chevallier 1340ca530bf3SGatien Chevallier for (i = 0; i < stm32_tamp_dev->pdata.compat->ext_tamp_size; i++) { 1341ca530bf3SGatien Chevallier ret = stm32_tamp_set_ext_config(stm32_tamp_dev->pdata.compat, i, 1342ca530bf3SGatien Chevallier &cr1, &cr2, &atcr1, &atcr2, 1343ca530bf3SGatien Chevallier &ier); 1344ca530bf3SGatien Chevallier if (ret) 1345ca530bf3SGatien Chevallier return ret; 1346ca530bf3SGatien Chevallier } 1347ca530bf3SGatien Chevallier 1348ca530bf3SGatien Chevallier /* 1349ca530bf3SGatien Chevallier * We apply configuration all in a row: 1350ca530bf3SGatien Chevallier * As for active ext tamper "all the needed tampers must be enabled in 1351ca530bf3SGatien Chevallier * the same write access". 1352ca530bf3SGatien Chevallier */ 1353ca530bf3SGatien Chevallier io_write32(base + _TAMP_FLTCR, fltcr); 1354ca530bf3SGatien Chevallier FMSG("Set passive conf %08"PRIx32, fltcr); 1355ca530bf3SGatien Chevallier 1356ca530bf3SGatien Chevallier /* Active configuration applied only if not already done. */ 1357ca530bf3SGatien Chevallier if (((io_read32(base + _TAMP_ATOR) & _TAMP_INITS) != _TAMP_INITS)) { 1358ca530bf3SGatien Chevallier io_write32(base + _TAMP_ATCR1, atcr1); 1359ca530bf3SGatien Chevallier FMSG("Set active conf1 %08"PRIx32, atcr1); 1360ca530bf3SGatien Chevallier 1361ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat->tags & 1362ca530bf3SGatien Chevallier TAMP_HAS_REGISTER_ATCR2) { 1363ca530bf3SGatien Chevallier io_write32(base + _TAMP_ATCR2, atcr2); 1364ca530bf3SGatien Chevallier FMSG("Set active conf2 %08"PRIx32, atcr2); 1365ca530bf3SGatien Chevallier } 1366ca530bf3SGatien Chevallier } 1367ca530bf3SGatien Chevallier 1368ca530bf3SGatien Chevallier io_write32(base + _TAMP_CR1, cr1); 1369ca530bf3SGatien Chevallier io_write32(base + _TAMP_CR2, cr2); 1370ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_CR3) 1371ca530bf3SGatien Chevallier io_write32(base + _TAMP_CR3, cr3); 1372ca530bf3SGatien Chevallier 1373ca530bf3SGatien Chevallier /* If active tamper we reinit the seed. */ 1374ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.active_conf) { 1375ca530bf3SGatien Chevallier if (stm32_tamp_set_seed(base) != TEE_SUCCESS) { 1376ca530bf3SGatien Chevallier EMSG("Active tamper: SEED not initialized"); 1377ca530bf3SGatien Chevallier return TEE_ERROR_BAD_STATE; 1378ca530bf3SGatien Chevallier } 1379ca530bf3SGatien Chevallier } 1380ca530bf3SGatien Chevallier 1381ca530bf3SGatien Chevallier /* Enable interrupts. */ 1382ca530bf3SGatien Chevallier io_write32(base + _TAMP_IER, ier); 1383ca530bf3SGatien Chevallier 1384ca530bf3SGatien Chevallier return TEE_SUCCESS; 1385ca530bf3SGatien Chevallier } 1386ca530bf3SGatien Chevallier 1387ca530bf3SGatien Chevallier /* 1388ca530bf3SGatien Chevallier * Mask a tamper event detection for a given @id 1389ca530bf3SGatien Chevallier * If ETAMP(id) event generates a trigger event, this ETAMP(id) is masked and 1390ca530bf3SGatien Chevallier * internally cleared by hardware. The secrets are not erased. 1391ca530bf3SGatien Chevallier */ 1392ca530bf3SGatien Chevallier static TEE_Result __maybe_unused stm32_tamp_set_mask(enum stm32_tamp_id id) 1393ca530bf3SGatien Chevallier { 1394ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1395ca530bf3SGatien Chevallier 1396ca530bf3SGatien Chevallier /* Only EXT_TAMP1, EXT_TAMP2, EXT_TAMP3 can be masked. */ 1397ca530bf3SGatien Chevallier if (id < EXT_TAMP1 || id > (EXT_TAMP1 + _TAMP_CR2_ETAMPMSK_MAX_ID)) 1398ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1399ca530bf3SGatien Chevallier 1400ca530bf3SGatien Chevallier /* We cannot mask the event if pending. */ 1401ca530bf3SGatien Chevallier if (io_read32(base + _TAMP_SR) & _TAMP_SR_ETAMP(id)) 1402ca530bf3SGatien Chevallier return TEE_ERROR_BAD_STATE; 1403ca530bf3SGatien Chevallier 1404ca530bf3SGatien Chevallier /* We disable the IT */ 1405ca530bf3SGatien Chevallier io_clrbits32(base + _TAMP_IER, _TAMP_IER_ETAMP(id)); 1406ca530bf3SGatien Chevallier /* We mask the event */ 1407ca530bf3SGatien Chevallier io_setbits32(base + _TAMP_CR2, _TAMP_CR2_ETAMPMSK(id)); 1408ca530bf3SGatien Chevallier 1409ca530bf3SGatien Chevallier return TEE_SUCCESS; 1410ca530bf3SGatien Chevallier } 1411ca530bf3SGatien Chevallier 1412ca530bf3SGatien Chevallier /* 1413ca530bf3SGatien Chevallier * Unmask a tamper event detection for a given @id 1414ca530bf3SGatien Chevallier * ETAMP(id) event now generates a trigger event and ETAMP(id) must be cleared 1415ca530bf3SGatien Chevallier * by software to allow next tamper event detection. 1416ca530bf3SGatien Chevallier */ 1417ca530bf3SGatien Chevallier static TEE_Result __maybe_unused stm32_tamp_unset_mask(enum stm32_tamp_id id) 1418ca530bf3SGatien Chevallier { 1419ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1420ca530bf3SGatien Chevallier 1421ca530bf3SGatien Chevallier /* Only EXT_TAMP1, EXT_TAMP2, EXT_TAMP3 can be masked. */ 1422ca530bf3SGatien Chevallier if (id < EXT_TAMP1 || id > (EXT_TAMP1 + _TAMP_CR2_ETAMPMSK_MAX_ID)) 1423ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1424ca530bf3SGatien Chevallier 1425ca530bf3SGatien Chevallier /* We unmask the event */ 1426ca530bf3SGatien Chevallier io_clrbits32(base + _TAMP_CR2, _TAMP_CR2_ETAMPMSK(id)); 1427ca530bf3SGatien Chevallier /* We enable the IT */ 1428ca530bf3SGatien Chevallier io_setbits32(base + _TAMP_IER, _TAMP_IER_ETAMP(id)); 1429ca530bf3SGatien Chevallier 1430ca530bf3SGatien Chevallier return TEE_SUCCESS; 1431ca530bf3SGatien Chevallier } 1432ca530bf3SGatien Chevallier 1433ca530bf3SGatien Chevallier /* This will increment the monotonic counter by 1. It cannot roll-over */ 1434ca530bf3SGatien Chevallier static TEE_Result __maybe_unused stm32_tamp_write_mcounter(int cnt_idx) 1435ca530bf3SGatien Chevallier { 1436ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1437ca530bf3SGatien Chevallier 1438ca530bf3SGatien Chevallier if (cnt_idx < 0 || !stm32_tamp_dev->pdata.compat || 1439ca530bf3SGatien Chevallier cnt_idx >= stm32_tamp_dev->pdata.compat->nb_monotonic_counter) 1440ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1441ca530bf3SGatien Chevallier 1442ca530bf3SGatien Chevallier io_write32(base + _TAMP_COUNTR + cnt_idx * sizeof(uint32_t), 1); 1443ca530bf3SGatien Chevallier 1444ca530bf3SGatien Chevallier return TEE_SUCCESS; 1445ca530bf3SGatien Chevallier } 1446ca530bf3SGatien Chevallier 1447ca530bf3SGatien Chevallier static uint32_t __maybe_unused stm32_tamp_read_mcounter(int cnt_idx) 1448ca530bf3SGatien Chevallier { 1449ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1450ca530bf3SGatien Chevallier 1451ca530bf3SGatien Chevallier if (cnt_idx < 0 || !stm32_tamp_dev->pdata.compat || 1452ca530bf3SGatien Chevallier cnt_idx >= stm32_tamp_dev->pdata.compat->nb_monotonic_counter) 1453ca530bf3SGatien Chevallier return 0U; 1454ca530bf3SGatien Chevallier 1455ca530bf3SGatien Chevallier return io_read32(base + _TAMP_COUNTR + cnt_idx * sizeof(uint32_t)); 1456ca530bf3SGatien Chevallier } 1457ca530bf3SGatien Chevallier 1458ca530bf3SGatien Chevallier static TEE_Result stm32_tamp_configure_int(struct stm32_tamp_tamper_data *tamp, 1459ca530bf3SGatien Chevallier uint32_t mode, 1460ca530bf3SGatien Chevallier uint32_t (*cb)(int id)) 1461ca530bf3SGatien Chevallier { 1462ca530bf3SGatien Chevallier if (mode & TAMP_EVT_MASK) 1463ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1464ca530bf3SGatien Chevallier 1465ca530bf3SGatien Chevallier tamp->mode |= (mode & TAMP_MODE_MASK); 1466ca530bf3SGatien Chevallier tamp->func = cb; 1467ca530bf3SGatien Chevallier 1468ca530bf3SGatien Chevallier return TEE_SUCCESS; 1469ca530bf3SGatien Chevallier } 1470ca530bf3SGatien Chevallier 1471ca530bf3SGatien Chevallier static TEE_Result stm32_tamp_configure_ext(struct stm32_tamp_tamper_data *tamp, 1472ca530bf3SGatien Chevallier uint32_t mode, 1473ca530bf3SGatien Chevallier uint32_t (*cb)(int id)) 1474ca530bf3SGatien Chevallier { 1475ca530bf3SGatien Chevallier enum stm32_tamp_id id = tamp->id; 1476ca530bf3SGatien Chevallier 1477ca530bf3SGatien Chevallier if (mode & TAMP_EVT_MASK && !is_ext_tamp_id_valid(id)) 1478ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1479ca530bf3SGatien Chevallier 1480ca530bf3SGatien Chevallier if (!(tamp->mode & TAMP_IN_DT)) 1481ca530bf3SGatien Chevallier return TEE_ERROR_ITEM_NOT_FOUND; 1482ca530bf3SGatien Chevallier 1483ca530bf3SGatien Chevallier tamp->mode |= (mode & TAMP_MODE_MASK); 1484ca530bf3SGatien Chevallier tamp->func = cb; 1485ca530bf3SGatien Chevallier 1486ca530bf3SGatien Chevallier return TEE_SUCCESS; 1487ca530bf3SGatien Chevallier } 1488ca530bf3SGatien Chevallier 1489ca530bf3SGatien Chevallier /* 1490ca530bf3SGatien Chevallier * stm32_tamp_activate_tamp: Configure and activate one tamper (internal or 1491ca530bf3SGatien Chevallier * external). 1492ca530bf3SGatien Chevallier * 1493ca530bf3SGatien Chevallier * @id: tamper ID 1494ca530bf3SGatien Chevallier * @mode: bitmask from TAMPER modes define: 1495ca530bf3SGatien Chevallier * TAMP_ERASE/TAMP_NOERASE: 1496ca530bf3SGatien Chevallier * TAMP_ERASE: when this tamper event is triggered; secrets are 1497ca530bf3SGatien Chevallier * erased. 1498ca530bf3SGatien Chevallier * TAMP_NOERASE: when this event is triggered; cryptographic 1499ca530bf3SGatien Chevallier * and some secure peripherals are locked until the event is 1500ca530bf3SGatien Chevallier * acknowledged. If the callback confirms the TAMPER, it 1501ca530bf3SGatien Chevallier * can manually erase secrets with stm32_tamp_erase_secrets(). 1502ca530bf3SGatien Chevallier * TAMP_NO_EVT_MASK/TAMP_EVT_MASK: 1503ca530bf3SGatien Chevallier * TAMP_NO_EVT_MASK: normal behavior. 1504ca530bf3SGatien Chevallier * TAMP_EVT_MASK: if the event is triggered, the event is masked and 1505ca530bf3SGatien Chevallier * internally cleared by hardware. Secrets are not erased. Only 1506ca530bf3SGatien Chevallier * applicable for some external tampers. This defines only the status 1507ca530bf3SGatien Chevallier * at boot. To change mask while runtime: stm32_tamp_set_mask() and 1508ca530bf3SGatien Chevallier * stm32_tamp_unset_mask() can be used. 1509ca530bf3SGatien Chevallier * @cb: function to call when a tamper event is raised (cannot be NULL). 1510ca530bf3SGatien Chevallier * It is called in interrupt context and returns a bitmask defining 1511ca530bf3SGatien Chevallier * the action to take by the driver: 1512ca530bf3SGatien Chevallier * TAMP_CB_RESET: will reset the board. 1513ca530bf3SGatien Chevallier * TAMP_CB_ACK: this specific tamper is acknowledged (in case 1514ca530bf3SGatien Chevallier * of no-erase tamper, blocked secret are unblocked). 1515ca530bf3SGatien Chevallier * 1516ca530bf3SGatien Chevallier * return: TEE_ERROR_BAD_PARAMETERS: 1517ca530bf3SGatien Chevallier * if @id is not a valid tamper ID, 1518ca530bf3SGatien Chevallier * if @cb is NULL, 1519ca530bf3SGatien Chevallier * if TAMP_EVT_MASK @mode is set for an unsupported @id. 1520ca530bf3SGatien Chevallier * TEE_ERROR_BAD_STATE 1521ca530bf3SGatien Chevallier * if driver was not previously initialized. 1522ca530bf3SGatien Chevallier * TEE_ERROR_ITEM_NOT_FOUND 1523ca530bf3SGatien Chevallier * if the activated external tamper was not previously 1524ca530bf3SGatien Chevallier * defined in the device tree. 1525ca530bf3SGatien Chevallier * else TEE_SUCCESS. 1526ca530bf3SGatien Chevallier */ 1527ca530bf3SGatien Chevallier static TEE_Result stm32_tamp_activate_tamp(enum stm32_tamp_id id, uint32_t mode, 1528ca530bf3SGatien Chevallier uint32_t (*cb)(int id)) 1529ca530bf3SGatien Chevallier { 1530ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data *tamp_conf = NULL; 1531ca530bf3SGatien Chevallier size_t i = 0; 1532ca530bf3SGatien Chevallier 1533ca530bf3SGatien Chevallier if (!stm32_tamp_dev->pdata.compat) 1534ca530bf3SGatien Chevallier return TEE_ERROR_BAD_STATE; 1535ca530bf3SGatien Chevallier 1536ca530bf3SGatien Chevallier assert(is_unpaged(cb)); 1537ca530bf3SGatien Chevallier 1538ca530bf3SGatien Chevallier if (!cb) 1539ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1540ca530bf3SGatien Chevallier 1541ca530bf3SGatien Chevallier /* Find internal Tamp struct */ 1542ca530bf3SGatien Chevallier for (i = 0; i < stm32_tamp_dev->pdata.compat->int_tamp_size; i++) { 1543ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat->int_tamp[i].id == id) { 1544ca530bf3SGatien Chevallier tamp_conf = &stm32_tamp_dev->pdata.compat->int_tamp[i]; 1545ca530bf3SGatien Chevallier return stm32_tamp_configure_int(tamp_conf, mode, cb); 1546ca530bf3SGatien Chevallier } 1547ca530bf3SGatien Chevallier } 1548ca530bf3SGatien Chevallier 1549ca530bf3SGatien Chevallier /* Find external Tamp struct */ 1550ca530bf3SGatien Chevallier for (i = 0; i < stm32_tamp_dev->pdata.compat->ext_tamp_size; i++) { 1551ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat->ext_tamp[i].id == id) { 1552ca530bf3SGatien Chevallier tamp_conf = &stm32_tamp_dev->pdata.compat->ext_tamp[i]; 1553ca530bf3SGatien Chevallier return stm32_tamp_configure_ext(tamp_conf, mode, cb); 1554ca530bf3SGatien Chevallier } 1555ca530bf3SGatien Chevallier } 1556ca530bf3SGatien Chevallier 1557ca530bf3SGatien Chevallier EMSG("Did not find existing tamper for ID:%d", id); 1558ca530bf3SGatien Chevallier 1559ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1560ca530bf3SGatien Chevallier } 1561ca530bf3SGatien Chevallier 1562ca530bf3SGatien Chevallier static bool __maybe_unused stm32_tamp_are_secrets_blocked(void) 1563ca530bf3SGatien Chevallier { 1564ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 1565ca530bf3SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_CR2_SECRET_STATUS)) { 1566ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1567ca530bf3SGatien Chevallier 1568ca530bf3SGatien Chevallier return ((io_read32(base + _TAMP_CR2) & _TAMP_CR2_BKBLOCK) || 1569ca530bf3SGatien Chevallier io_read32(base + _TAMP_SR)); 1570ca530bf3SGatien Chevallier } else { 1571ca530bf3SGatien Chevallier return false; 1572ca530bf3SGatien Chevallier } 1573ca530bf3SGatien Chevallier } 1574ca530bf3SGatien Chevallier 1575ca530bf3SGatien Chevallier static void __maybe_unused stm32_tamp_block_secrets(void) 1576ca530bf3SGatien Chevallier { 1577ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1578ca530bf3SGatien Chevallier 1579ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 1580ca530bf3SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_CR2_SECRET_STATUS)) 1581ca530bf3SGatien Chevallier io_setbits32(base + _TAMP_CR2, _TAMP_CR2_BKBLOCK); 1582ca530bf3SGatien Chevallier } 1583ca530bf3SGatien Chevallier 1584ca530bf3SGatien Chevallier static void __maybe_unused stm32_tamp_unblock_secrets(void) 1585ca530bf3SGatien Chevallier { 1586ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1587ca530bf3SGatien Chevallier 1588ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 1589ca530bf3SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_CR2_SECRET_STATUS)) 1590ca530bf3SGatien Chevallier io_clrbits32(base + _TAMP_CR2, _TAMP_CR2_BKBLOCK); 1591ca530bf3SGatien Chevallier } 1592ca530bf3SGatien Chevallier 1593ca530bf3SGatien Chevallier static void __maybe_unused stm32_tamp_erase_secrets(void) 1594ca530bf3SGatien Chevallier { 1595ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1596ca530bf3SGatien Chevallier 1597ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 1598ca530bf3SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_CR2_SECRET_STATUS)) 1599ca530bf3SGatien Chevallier io_setbits32(base + _TAMP_CR2, _TAMP_CR2_BKERASE); 1600ca530bf3SGatien Chevallier } 1601ca530bf3SGatien Chevallier 1602ca530bf3SGatien Chevallier static void __maybe_unused stm32_tamp_lock_boot_hardware_key(void) 1603ca530bf3SGatien Chevallier { 1604ca530bf3SGatien Chevallier vaddr_t base = get_base(); 1605ca530bf3SGatien Chevallier 1606ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat && 1607ca530bf3SGatien Chevallier (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) 1608ca530bf3SGatien Chevallier io_setbits32(base + _TAMP_SECCFGR, _TAMP_SECCFGR_BHKLOCK); 1609ca530bf3SGatien Chevallier } 1610ca530bf3SGatien Chevallier 1611ca530bf3SGatien Chevallier static void stm32_tamp_configure_pin(uint32_t id, struct gpio *gpio, bool out, 1612ca530bf3SGatien Chevallier struct stm32_tamp_platdata *pdata) 1613ca530bf3SGatien Chevallier { 1614ca530bf3SGatien Chevallier struct stm32_tamp_compat *compat = pdata->compat; 1615ca530bf3SGatien Chevallier unsigned int bank = stm32_gpio_chip_bank_id(gpio->chip); 1616ca530bf3SGatien Chevallier unsigned int pin = gpio->pin; 1617ca530bf3SGatien Chevallier size_t i = 0; 1618ca530bf3SGatien Chevallier 1619ca530bf3SGatien Chevallier if (!compat) 1620ca530bf3SGatien Chevallier return; 1621ca530bf3SGatien Chevallier 1622ca530bf3SGatien Chevallier /* Configure option registers */ 1623ca530bf3SGatien Chevallier for (i = 0; i < compat->pin_map_size; i++) { 1624ca530bf3SGatien Chevallier if (id == compat->pin_map[i].id && 1625ca530bf3SGatien Chevallier bank == compat->pin_map[i].bank && 1626ca530bf3SGatien Chevallier pin == compat->pin_map[i].pin && 1627ca530bf3SGatien Chevallier out == compat->pin_map[i].out) { 1628ca530bf3SGatien Chevallier pdata->pins_conf |= compat->pin_map[i].conf; 1629ca530bf3SGatien Chevallier break; 1630ca530bf3SGatien Chevallier } 1631ca530bf3SGatien Chevallier } 1632ca530bf3SGatien Chevallier } 1633ca530bf3SGatien Chevallier 1634ca530bf3SGatien Chevallier static TEE_Result 1635ca530bf3SGatien Chevallier stm32_tamp_configure_pin_from_dt(const void *fdt, int node, 1636ca530bf3SGatien Chevallier struct stm32_tamp_platdata *pdata, 1637ca530bf3SGatien Chevallier uint32_t ext_tamp_id, uint32_t out_tamp_id) 1638ca530bf3SGatien Chevallier { 1639ca530bf3SGatien Chevallier enum stm32_tamp_out_id out_id = INVALID_OUT_TAMP; 1640ca530bf3SGatien Chevallier struct stm32_tamp_tamper_data *tamp_ext = NULL; 1641ca530bf3SGatien Chevallier enum stm32_tamp_id id = INVALID_TAMP; 1642ca530bf3SGatien Chevallier TEE_Result res = TEE_SUCCESS; 1643ca530bf3SGatien Chevallier struct gpio *gpio_out = NULL; 1644ca530bf3SGatien Chevallier struct gpio *gpio_ext = NULL; 1645ca530bf3SGatien Chevallier bool active = false; 1646ca530bf3SGatien Chevallier unsigned int i = 0; 1647ca530bf3SGatien Chevallier 1648ca530bf3SGatien Chevallier /* 1649ca530bf3SGatien Chevallier * First GPIO in the tamper-gpios property is required and refers to the 1650ca530bf3SGatien Chevallier * EXT_TAMP control. Second GPIO in the tamper-gpios property is 1651ca530bf3SGatien Chevallier * optional and, if defined, refers to the OUT_TAMP control. 1652ca530bf3SGatien Chevallier * If only one GPIO is defined, the tamper control is a passive tamper. 1653ca530bf3SGatien Chevallier * Else, it is an active tamper. 1654ca530bf3SGatien Chevallier */ 1655ca530bf3SGatien Chevallier res = gpio_dt_get_by_index(fdt, node, 1, "tamper", &gpio_out); 1656ca530bf3SGatien Chevallier if (res && res != TEE_ERROR_ITEM_NOT_FOUND) 1657ca530bf3SGatien Chevallier return res; 1658ca530bf3SGatien Chevallier 1659ca530bf3SGatien Chevallier if (res != TEE_ERROR_ITEM_NOT_FOUND) { 1660ca530bf3SGatien Chevallier active = true; 1661ca530bf3SGatien Chevallier out_id = OUT_TAMP1 + out_tamp_id - 1; 1662ca530bf3SGatien Chevallier if (out_tamp_id > pdata->compat->ext_tamp_size) { 1663ca530bf3SGatien Chevallier gpio_put(gpio_out); 1664ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1665ca530bf3SGatien Chevallier } 1666ca530bf3SGatien Chevallier 1667ca530bf3SGatien Chevallier stm32_tamp_configure_pin(out_id, gpio_out, true, pdata); 1668ca530bf3SGatien Chevallier } 1669ca530bf3SGatien Chevallier 1670ca530bf3SGatien Chevallier res = gpio_dt_get_by_index(fdt, node, 0, "tamper", &gpio_ext); 1671ca530bf3SGatien Chevallier if (res) { 1672ca530bf3SGatien Chevallier gpio_put(gpio_out); 1673ca530bf3SGatien Chevallier return res; 1674ca530bf3SGatien Chevallier } 1675ca530bf3SGatien Chevallier 1676ca530bf3SGatien Chevallier /* We now configure first pin */ 1677ca530bf3SGatien Chevallier id = ext_tamp_id + EXT_TAMP1 - 1; 1678ca530bf3SGatien Chevallier 1679ca530bf3SGatien Chevallier /* Find external TAMP struct */ 1680ca530bf3SGatien Chevallier for (i = 0; i < pdata->compat->ext_tamp_size; i++) { 1681ca530bf3SGatien Chevallier if (pdata->compat->ext_tamp[i].id == id) { 1682ca530bf3SGatien Chevallier tamp_ext = &pdata->compat->ext_tamp[i]; 1683ca530bf3SGatien Chevallier break; 1684ca530bf3SGatien Chevallier } 1685ca530bf3SGatien Chevallier } 1686ca530bf3SGatien Chevallier 1687ca530bf3SGatien Chevallier if (!tamp_ext) { 1688ca530bf3SGatien Chevallier gpio_put(gpio_out); 1689ca530bf3SGatien Chevallier gpio_put(gpio_ext); 1690ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1691ca530bf3SGatien Chevallier } 1692ca530bf3SGatien Chevallier 1693ca530bf3SGatien Chevallier if (active) { 1694ca530bf3SGatien Chevallier tamp_ext->mode |= TAMP_ACTIVE; 1695ca530bf3SGatien Chevallier tamp_ext->out_id = out_id; 1696ca530bf3SGatien Chevallier pdata->out_pins |= BIT(tamp_ext->out_id - OUT_TAMP1); 1697ca530bf3SGatien Chevallier 1698ca530bf3SGatien Chevallier if (out_id - OUT_TAMP1 != id - EXT_TAMP1) 1699ca530bf3SGatien Chevallier pdata->active_conf |= _TAMP_ATCR1_ATOSHARE; 1700ca530bf3SGatien Chevallier } else { 1701ca530bf3SGatien Chevallier if (fdt_getprop(fdt, node, "st,trig-on", NULL)) 1702ca530bf3SGatien Chevallier tamp_ext->mode |= TAMP_TRIG_ON; 1703ca530bf3SGatien Chevallier } 1704ca530bf3SGatien Chevallier 1705ca530bf3SGatien Chevallier tamp_ext->mode |= TAMP_IN_DT; 1706ca530bf3SGatien Chevallier 1707ca530bf3SGatien Chevallier stm32_tamp_configure_pin(id, gpio_ext, false, pdata); 1708ca530bf3SGatien Chevallier 1709ca530bf3SGatien Chevallier return TEE_SUCCESS; 1710ca530bf3SGatien Chevallier } 1711ca530bf3SGatien Chevallier 1712ca530bf3SGatien Chevallier static TEE_Result 1713ca530bf3SGatien Chevallier stm32_tamp_parse_passive_conf(const void *fdt, int node, 1714ca530bf3SGatien Chevallier struct stm32_tamp_platdata *pdata) 1715ca530bf3SGatien Chevallier { 1716ca530bf3SGatien Chevallier const fdt32_t *cuint = NULL; 1717ca530bf3SGatien Chevallier uint32_t precharge = 0; 1718ca530bf3SGatien Chevallier uint32_t nb_sample = 0; 1719ca530bf3SGatien Chevallier uint32_t clk_div = 32768; 1720ca530bf3SGatien Chevallier uint32_t conf = 0; 1721ca530bf3SGatien Chevallier 1722ca530bf3SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,tamp-passive-precharge", NULL); 1723ca530bf3SGatien Chevallier if (cuint) 1724ca530bf3SGatien Chevallier precharge = fdt32_to_cpu(*cuint); 1725ca530bf3SGatien Chevallier 1726ca530bf3SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,tamp-passive-nb-sample", NULL); 1727ca530bf3SGatien Chevallier if (cuint) 1728ca530bf3SGatien Chevallier nb_sample = fdt32_to_cpu(*cuint); 1729ca530bf3SGatien Chevallier 1730ca530bf3SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,tamp-passive-sample-clk-div", NULL); 1731ca530bf3SGatien Chevallier if (cuint) 1732ca530bf3SGatien Chevallier clk_div = fdt32_to_cpu(*cuint); 1733ca530bf3SGatien Chevallier 1734ca530bf3SGatien Chevallier DMSG("Passive conf from dt: precharge=%"PRIu32", nb_sample=%"PRIu32 1735ca530bf3SGatien Chevallier ", clk_div=%"PRIu32, precharge, nb_sample, clk_div); 1736ca530bf3SGatien Chevallier 1737ca530bf3SGatien Chevallier switch (precharge) { 1738ca530bf3SGatien Chevallier case 0: 1739ca530bf3SGatien Chevallier /* No precharge, => we disable the pull-up */ 1740ca530bf3SGatien Chevallier conf |= _TAMP_FLTCR_TAMPPUDIS; 1741ca530bf3SGatien Chevallier break; 1742ca530bf3SGatien Chevallier case 1: 1743ca530bf3SGatien Chevallier /* Precharge for one cycle value stay 0 */ 1744ca530bf3SGatien Chevallier break; 1745ca530bf3SGatien Chevallier case 2: 1746ca530bf3SGatien Chevallier /* Precharge passive pin 2 cycles */ 1747ca530bf3SGatien Chevallier conf |= SHIFT_U32(1, _TAMP_FLTCR_TAMPPRCH_SHIFT); 1748ca530bf3SGatien Chevallier break; 1749ca530bf3SGatien Chevallier case 4: 1750ca530bf3SGatien Chevallier /* Precharge passive pin 4 cycles */ 1751ca530bf3SGatien Chevallier conf |= SHIFT_U32(2, _TAMP_FLTCR_TAMPPRCH_SHIFT); 1752ca530bf3SGatien Chevallier break; 1753ca530bf3SGatien Chevallier case 8: 1754ca530bf3SGatien Chevallier /* Precharge passive pin 8 cycles */ 1755ca530bf3SGatien Chevallier conf |= SHIFT_U32(3, _TAMP_FLTCR_TAMPPRCH_SHIFT); 1756ca530bf3SGatien Chevallier break; 1757ca530bf3SGatien Chevallier default: 1758ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1759ca530bf3SGatien Chevallier } 1760ca530bf3SGatien Chevallier 1761ca530bf3SGatien Chevallier switch (nb_sample) { 1762ca530bf3SGatien Chevallier case 0: 1763ca530bf3SGatien Chevallier /* Activation on edge, no pull-up: value stay 0 */ 1764ca530bf3SGatien Chevallier break; 1765ca530bf3SGatien Chevallier case 2: 1766ca530bf3SGatien Chevallier /* 1767ca530bf3SGatien Chevallier * Tamper event is activated after 2 consecutive samples at 1768ca530bf3SGatien Chevallier * active level. 1769ca530bf3SGatien Chevallier */ 1770ca530bf3SGatien Chevallier conf |= SHIFT_U32(1, _TAMP_FLTCR_TAMPFLT_SHIFT); 1771ca530bf3SGatien Chevallier break; 1772ca530bf3SGatien Chevallier case 4: 1773ca530bf3SGatien Chevallier /* 1774ca530bf3SGatien Chevallier * Tamper event is activated after 4 consecutive samples at 1775ca530bf3SGatien Chevallier * active level. 1776ca530bf3SGatien Chevallier */ 1777ca530bf3SGatien Chevallier conf |= SHIFT_U32(2, _TAMP_FLTCR_TAMPFLT_SHIFT); 1778ca530bf3SGatien Chevallier break; 1779ca530bf3SGatien Chevallier case 8: 1780ca530bf3SGatien Chevallier /* 1781ca530bf3SGatien Chevallier * Tamper event is activated after 8 consecutive samples at 1782ca530bf3SGatien Chevallier * active level. 1783ca530bf3SGatien Chevallier */ 1784ca530bf3SGatien Chevallier conf |= SHIFT_U32(3, _TAMP_FLTCR_TAMPFLT_SHIFT); 1785ca530bf3SGatien Chevallier break; 1786ca530bf3SGatien Chevallier default: 1787ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1788ca530bf3SGatien Chevallier } 1789ca530bf3SGatien Chevallier 1790ca530bf3SGatien Chevallier switch (clk_div) { 1791ca530bf3SGatien Chevallier case 32768: 1792ca530bf3SGatien Chevallier /* RTCCLK / 32768 (1 Hz when RTCCLK = 32768 Hz): stay 0 */ 1793ca530bf3SGatien Chevallier break; 1794ca530bf3SGatien Chevallier case 16384: 1795ca530bf3SGatien Chevallier /* RTCCLK / 16384 (2 Hz when RTCCLK = 32768 Hz) */ 1796ca530bf3SGatien Chevallier conf |= SHIFT_U32(1, _TAMP_FLTCR_TAMPFREQ_SHIFT); 1797ca530bf3SGatien Chevallier break; 1798ca530bf3SGatien Chevallier case 8192: 1799ca530bf3SGatien Chevallier /* RTCCLK / 8192 (4 Hz when RTCCLK = 32768 Hz) */ 1800ca530bf3SGatien Chevallier conf |= SHIFT_U32(2, _TAMP_FLTCR_TAMPFREQ_SHIFT); 1801ca530bf3SGatien Chevallier break; 1802ca530bf3SGatien Chevallier case 4096: 1803ca530bf3SGatien Chevallier /* RTCCLK / 4096 (8 Hz when RTCCLK = 32768 Hz) */ 1804ca530bf3SGatien Chevallier conf |= SHIFT_U32(3, _TAMP_FLTCR_TAMPFREQ_SHIFT); 1805ca530bf3SGatien Chevallier break; 1806ca530bf3SGatien Chevallier case 2048: 1807ca530bf3SGatien Chevallier /* RTCCLK / 2048 (16 Hz when RTCCLK = 32768 Hz) */ 1808ca530bf3SGatien Chevallier conf |= SHIFT_U32(4, _TAMP_FLTCR_TAMPFREQ_SHIFT); 1809ca530bf3SGatien Chevallier break; 1810ca530bf3SGatien Chevallier case 1024: 1811ca530bf3SGatien Chevallier /* RTCCLK / 1024 (32 Hz when RTCCLK = 32768 Hz) */ 1812ca530bf3SGatien Chevallier conf |= SHIFT_U32(5, _TAMP_FLTCR_TAMPFREQ_SHIFT); 1813ca530bf3SGatien Chevallier break; 1814ca530bf3SGatien Chevallier case 512: 1815ca530bf3SGatien Chevallier /* RTCCLK / 512 (64 Hz when RTCCLK = 32768 Hz) */ 1816ca530bf3SGatien Chevallier conf |= SHIFT_U32(6, _TAMP_FLTCR_TAMPFREQ_SHIFT); 1817ca530bf3SGatien Chevallier break; 1818ca530bf3SGatien Chevallier case 256: 1819ca530bf3SGatien Chevallier /* RTCCLK / 256 (128 Hz when RTCCLK = 32768 Hz) */ 1820ca530bf3SGatien Chevallier conf |= SHIFT_U32(7, _TAMP_FLTCR_TAMPFREQ_SHIFT); 1821ca530bf3SGatien Chevallier break; 1822ca530bf3SGatien Chevallier default: 1823ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1824ca530bf3SGatien Chevallier } 1825ca530bf3SGatien Chevallier 1826ca530bf3SGatien Chevallier pdata->passive_conf = conf; 1827ca530bf3SGatien Chevallier 1828ca530bf3SGatien Chevallier return TEE_SUCCESS; 1829ca530bf3SGatien Chevallier } 1830ca530bf3SGatien Chevallier 1831ca530bf3SGatien Chevallier static uint32_t stm32_tamp_itamper_action(int id) 1832ca530bf3SGatien Chevallier { 1833ca530bf3SGatien Chevallier const char __maybe_unused *tamp_name = NULL; 1834ca530bf3SGatien Chevallier 1835ca530bf3SGatien Chevallier if (id >= 0 && ((size_t)id < ARRAY_SIZE(itamper_name))) 1836ca530bf3SGatien Chevallier tamp_name = itamper_name[id]; 1837ca530bf3SGatien Chevallier 1838ca530bf3SGatien Chevallier MSG("Internal tamper event %u (%s) occurred", id - INT_TAMP1 + 1, 1839ca530bf3SGatien Chevallier tamp_name); 1840ca530bf3SGatien Chevallier 1841ca530bf3SGatien Chevallier return TAMP_CB_ACK_AND_RESET; 1842ca530bf3SGatien Chevallier } 1843ca530bf3SGatien Chevallier DECLARE_KEEP_PAGER(stm32_tamp_itamper_action); 1844ca530bf3SGatien Chevallier 1845ca530bf3SGatien Chevallier static uint32_t stm32_tamp_etamper_action(int id __maybe_unused) 1846ca530bf3SGatien Chevallier { 1847ca530bf3SGatien Chevallier MSG("External tamper %u occurs", id - EXT_TAMP1 + 1); 1848ca530bf3SGatien Chevallier 1849ca530bf3SGatien Chevallier return TAMP_CB_ACK_AND_RESET; 1850ca530bf3SGatien Chevallier } 1851ca530bf3SGatien Chevallier DECLARE_KEEP_PAGER(stm32_tamp_etamper_action); 1852ca530bf3SGatien Chevallier 1853ca530bf3SGatien Chevallier static TEE_Result stm32_configure_tamp(const void *fdt, int node) 1854ca530bf3SGatien Chevallier { 1855ca530bf3SGatien Chevallier const fdt32_t *internal_tampers = 0; 1856ca530bf3SGatien Chevallier uint32_t i_tampers[EXT_TAMP1 * 2] = { }; 1857ca530bf3SGatien Chevallier int subnode = -FDT_ERR_NOTFOUND; 1858ca530bf3SGatien Chevallier TEE_Result res = TEE_SUCCESS; 1859ca530bf3SGatien Chevallier int retval = 0; 1860ca530bf3SGatien Chevallier int len = 0; 1861ca530bf3SGatien Chevallier int i = 0; 1862ca530bf3SGatien Chevallier 1863ca530bf3SGatien Chevallier /* Internal tampers configuration */ 1864ca530bf3SGatien Chevallier internal_tampers = fdt_getprop(fdt, node, "st,tamp-internal-tampers", 1865ca530bf3SGatien Chevallier &len); 1866ca530bf3SGatien Chevallier if (len == -FDT_ERR_NOTFOUND) 1867ca530bf3SGatien Chevallier goto skip_int_tamp; 1868ca530bf3SGatien Chevallier 1869ca530bf3SGatien Chevallier if ((internal_tampers && len % (2 * sizeof(uint32_t))) || 1870ca530bf3SGatien Chevallier !internal_tampers || len / sizeof(uint32_t) > EXT_TAMP1 * 2) 1871ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1872ca530bf3SGatien Chevallier 1873ca530bf3SGatien Chevallier retval = fdt_read_uint32_array(fdt, node, "st,tamp-internal-tampers", 1874ca530bf3SGatien Chevallier i_tampers, len / sizeof(uint32_t)); 1875ca530bf3SGatien Chevallier if (retval && retval != -FDT_ERR_NOTFOUND) 1876ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1877ca530bf3SGatien Chevallier 1878ca530bf3SGatien Chevallier len = len / sizeof(uint32_t); 1879ca530bf3SGatien Chevallier for (i = 0; i < len; i += 2) { 1880ca530bf3SGatien Chevallier uint32_t i_tamper_id = i_tampers[i] - 1; 1881ca530bf3SGatien Chevallier uint32_t i_tamper_mode = i_tampers[i + 1]; 1882ca530bf3SGatien Chevallier 1883ca530bf3SGatien Chevallier res = stm32_tamp_activate_tamp(i_tamper_id, i_tamper_mode, 1884ca530bf3SGatien Chevallier stm32_tamp_itamper_action); 1885ca530bf3SGatien Chevallier if (res) 1886ca530bf3SGatien Chevallier return res; 1887ca530bf3SGatien Chevallier } 1888ca530bf3SGatien Chevallier 1889ca530bf3SGatien Chevallier skip_int_tamp: 1890ca530bf3SGatien Chevallier fdt_for_each_subnode(subnode, fdt, node) { 1891ca530bf3SGatien Chevallier unsigned int ext_tamp_id = 0; 1892ca530bf3SGatien Chevallier unsigned int out_tamp_id = 0; 1893ca530bf3SGatien Chevallier const fdt32_t *cuint = 0; 1894ca530bf3SGatien Chevallier unsigned int mode = 0; 1895ca530bf3SGatien Chevallier int lenp = 0; 1896ca530bf3SGatien Chevallier 1897ca530bf3SGatien Chevallier if (!fdt_getprop(fdt, subnode, "tamper-gpios", NULL) || 1898ca530bf3SGatien Chevallier fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) 1899ca530bf3SGatien Chevallier continue; 1900ca530bf3SGatien Chevallier 1901ca530bf3SGatien Chevallier cuint = fdt_getprop(fdt, subnode, "st,tamp-mode", NULL); 1902ca530bf3SGatien Chevallier if (!cuint) 1903ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1904ca530bf3SGatien Chevallier 1905ca530bf3SGatien Chevallier mode = fdt32_to_cpu(*cuint); 1906ca530bf3SGatien Chevallier 1907ca530bf3SGatien Chevallier cuint = fdt_getprop(fdt, subnode, "st,tamp-id", &lenp); 1908ca530bf3SGatien Chevallier if (!cuint) 1909ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 1910ca530bf3SGatien Chevallier 1911ca530bf3SGatien Chevallier ext_tamp_id = fdt32_to_cpu(*cuint); 1912ca530bf3SGatien Chevallier if (lenp > (int)sizeof(uint32_t)) 1913ca530bf3SGatien Chevallier out_tamp_id = fdt32_to_cpu(*(cuint + 1)); 1914ca530bf3SGatien Chevallier 1915ca530bf3SGatien Chevallier res = stm32_tamp_configure_pin_from_dt(fdt, subnode, 1916ca530bf3SGatien Chevallier &stm32_tamp_dev->pdata, 1917ca530bf3SGatien Chevallier ext_tamp_id, 1918ca530bf3SGatien Chevallier out_tamp_id); 1919ca530bf3SGatien Chevallier if (res) 1920ca530bf3SGatien Chevallier return res; 1921ca530bf3SGatien Chevallier 1922ca530bf3SGatien Chevallier res = stm32_tamp_activate_tamp(EXT_TAMP1 + ext_tamp_id - 1, 1923ca530bf3SGatien Chevallier mode, stm32_tamp_etamper_action); 1924ca530bf3SGatien Chevallier if (res) 1925ca530bf3SGatien Chevallier return res; 1926ca530bf3SGatien Chevallier } 1927ca530bf3SGatien Chevallier 1928ca530bf3SGatien Chevallier if (stm32_tamp_set_config()) 1929ca530bf3SGatien Chevallier panic(); 1930ca530bf3SGatien Chevallier 1931ca530bf3SGatien Chevallier /* Enable timestamp for tamper */ 1932ca530bf3SGatien Chevallier if (stm32_rtc_set_tamper_timestamp()) 1933ca530bf3SGatien Chevallier panic(); 1934ca530bf3SGatien Chevallier 1935ca530bf3SGatien Chevallier return TEE_SUCCESS; 1936ca530bf3SGatien Chevallier } 1937ca530bf3SGatien Chevallier 1938ca530bf3SGatien Chevallier static TEE_Result 1939ca530bf3SGatien Chevallier stm32_tamp_parse_active_conf(const void *fdt, int node, 1940ca530bf3SGatien Chevallier struct stm32_tamp_platdata *pdata) 1941ca530bf3SGatien Chevallier { 1942ca530bf3SGatien Chevallier const fdt32_t *cuint = NULL; 1943ca530bf3SGatien Chevallier uint32_t clk_div = 1; 1944ca530bf3SGatien Chevallier uint32_t conf = 0; 1945ca530bf3SGatien Chevallier 1946ca530bf3SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,tamp-active-filter", NULL); 1947ca530bf3SGatien Chevallier if (cuint) 1948ca530bf3SGatien Chevallier conf |= _TAMP_ATCR1_FLTEN; 1949ca530bf3SGatien Chevallier 1950ca530bf3SGatien Chevallier /* 1951ca530bf3SGatien Chevallier * Here we will select a divisor for the RTCCLK. 1952ca530bf3SGatien Chevallier * Note that RTCCLK is also divided by (RTC_PRER_PREDIV_A - 1). 1953ca530bf3SGatien Chevallier */ 1954ca530bf3SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,tamp-active-clk-div", NULL); 1955ca530bf3SGatien Chevallier if (cuint) 1956ca530bf3SGatien Chevallier clk_div = fdt32_to_cpu(*cuint); 1957ca530bf3SGatien Chevallier 1958ca530bf3SGatien Chevallier DMSG("Active conf from dt: %s clk_div=%"PRIu32, 1959ca530bf3SGatien Chevallier (conf & _TAMP_ATCR1_FLTEN) ? "filter" : "no filter", clk_div); 1960ca530bf3SGatien Chevallier 1961ca530bf3SGatien Chevallier switch (clk_div) { 1962ca530bf3SGatien Chevallier case 1: 1963ca530bf3SGatien Chevallier /* RTCCLK / 32768 (1 Hz when RTCCLK = 32768 Hz): stay 0 */ 1964ca530bf3SGatien Chevallier break; 1965ca530bf3SGatien Chevallier case 2: 1966ca530bf3SGatien Chevallier /* RTCCLK / 16384 (2 Hz when RTCCLK = 32768 Hz) */ 1967ca530bf3SGatien Chevallier conf |= SHIFT_U32(1, _TAMP_ATCR1_ATCKSEL_SHIFT); 1968ca530bf3SGatien Chevallier break; 1969ca530bf3SGatien Chevallier case 4: 1970ca530bf3SGatien Chevallier /* RTCCLK / 8192 (4 Hz when RTCCLK = 32768 Hz) */ 1971ca530bf3SGatien Chevallier conf |= SHIFT_U32(2, _TAMP_ATCR1_ATCKSEL_SHIFT); 1972ca530bf3SGatien Chevallier break; 1973ca530bf3SGatien Chevallier case 8: 1974ca530bf3SGatien Chevallier /* RTCCLK / 4096 (8 Hz when RTCCLK = 32768 Hz) */ 1975ca530bf3SGatien Chevallier conf |= SHIFT_U32(3, _TAMP_ATCR1_ATCKSEL_SHIFT); 1976ca530bf3SGatien Chevallier break; 1977ca530bf3SGatien Chevallier case 16: 1978ca530bf3SGatien Chevallier /* RTCCLK / 2048 (16 Hz when RTCCLK = 32768 Hz) */ 1979ca530bf3SGatien Chevallier conf |= SHIFT_U32(4, _TAMP_ATCR1_ATCKSEL_SHIFT); 1980ca530bf3SGatien Chevallier break; 1981ca530bf3SGatien Chevallier case 32: 1982ca530bf3SGatien Chevallier /* RTCCLK / 1024 (32 Hz when RTCCLK = 32768 Hz) */ 1983ca530bf3SGatien Chevallier conf |= SHIFT_U32(5, _TAMP_ATCR1_ATCKSEL_SHIFT); 1984ca530bf3SGatien Chevallier break; 1985ca530bf3SGatien Chevallier case 64: 1986ca530bf3SGatien Chevallier /* RTCCLK / 512 (64 Hz when RTCCLK = 32768 Hz) */ 1987ca530bf3SGatien Chevallier conf |= SHIFT_U32(6, _TAMP_ATCR1_ATCKSEL_SHIFT); 1988ca530bf3SGatien Chevallier break; 1989ca530bf3SGatien Chevallier case 128: 1990ca530bf3SGatien Chevallier /* RTCCLK / 256 (128 Hz when RTCCLK = 32768 Hz) */ 1991ca530bf3SGatien Chevallier conf |= SHIFT_U32(7, _TAMP_ATCR1_ATCKSEL_SHIFT); 1992ca530bf3SGatien Chevallier break; 1993ca530bf3SGatien Chevallier case 2048: 1994ca530bf3SGatien Chevallier if (pdata->compat && 1995ca530bf3SGatien Chevallier (pdata->compat->tags & TAMP_SIZE_ATCR1_ATCKSEL_IS_4)) { 1996ca530bf3SGatien Chevallier /* 1997ca530bf3SGatien Chevallier * RTCCLK/2048 when (PREDIV_A+1) = 128 and (PREDIV_S+1) 1998ca530bf3SGatien Chevallier * is a multiple of 16. 1999ca530bf3SGatien Chevallier */ 2000ca530bf3SGatien Chevallier conf |= SHIFT_U32(11, _TAMP_ATCR1_ATCKSEL_SHIFT); 2001ca530bf3SGatien Chevallier break; 2002ca530bf3SGatien Chevallier } 2003ca530bf3SGatien Chevallier 2004ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 2005ca530bf3SGatien Chevallier default: 2006ca530bf3SGatien Chevallier return TEE_ERROR_BAD_PARAMETERS; 2007ca530bf3SGatien Chevallier } 2008ca530bf3SGatien Chevallier 2009ca530bf3SGatien Chevallier pdata->active_conf = conf; 2010ca530bf3SGatien Chevallier 2011ca530bf3SGatien Chevallier return TEE_SUCCESS; 2012ca530bf3SGatien Chevallier } 2013ca530bf3SGatien Chevallier 2014461e8793SGatien Chevallier static TEE_Result stm32_tamp_parse_fdt(const void *fdt, int node, 201569b8b983SEtienne Carriere const void *compat) 201669b8b983SEtienne Carriere { 2017461e8793SGatien Chevallier struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata; 2018461e8793SGatien Chevallier TEE_Result res = TEE_ERROR_GENERIC; 2019ca530bf3SGatien Chevallier size_t reg_size = 0; 202069b8b983SEtienne Carriere 2021461e8793SGatien Chevallier pdata->compat = (struct stm32_tamp_compat *)compat; 2022ca530bf3SGatien Chevallier 2023ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) { 2024ca530bf3SGatien Chevallier res = stm32_rifsc_check_tdcid(&pdata->is_tdcid); 2025ca530bf3SGatien Chevallier if (res) 2026ca530bf3SGatien Chevallier return res; 2027ca530bf3SGatien Chevallier } 2028ca530bf3SGatien Chevallier 2029ca530bf3SGatien Chevallier if (fdt_reg_info(fdt, node, &pdata->base.pa, ®_size)) 2030ca530bf3SGatien Chevallier panic(); 2031ca530bf3SGatien Chevallier 2032ca530bf3SGatien Chevallier io_pa_or_va_secure(&pdata->base, reg_size); 2033ca530bf3SGatien Chevallier assert(pdata->base.va); 203469b8b983SEtienne Carriere 2035461e8793SGatien Chevallier res = clk_dt_get_by_index(fdt, node, 0, &pdata->clock); 2036461e8793SGatien Chevallier if (res) 2037461e8793SGatien Chevallier return res; 2038461e8793SGatien Chevallier 2039ca530bf3SGatien Chevallier res = stm32_tamp_parse_passive_conf(fdt, node, pdata); 2040ca530bf3SGatien Chevallier if (res) 2041ca530bf3SGatien Chevallier return res; 2042ca530bf3SGatien Chevallier 2043ca530bf3SGatien Chevallier res = stm32_tamp_parse_active_conf(fdt, node, pdata); 2044ca530bf3SGatien Chevallier if (res) 2045ca530bf3SGatien Chevallier return res; 2046ca530bf3SGatien Chevallier 2047ca530bf3SGatien Chevallier if (fdt_getprop(fdt, node, "wakeup-source", NULL)) 2048ca530bf3SGatien Chevallier pdata->is_wakeup_source = true; 2049ca530bf3SGatien Chevallier 205092ab6535SGatien Chevallier parse_bkpregs_dt_conf(fdt, node); 2051461e8793SGatien Chevallier 2052461e8793SGatien Chevallier if (pdata->compat->tags & TAMP_HAS_RIF_SUPPORT) { 2053461e8793SGatien Chevallier const fdt32_t *cuint = NULL; 2054461e8793SGatien Chevallier unsigned int i = 0; 2055461e8793SGatien Chevallier int lenp = 0; 2056461e8793SGatien Chevallier 2057461e8793SGatien Chevallier cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); 2058461e8793SGatien Chevallier if (!cuint) { 2059461e8793SGatien Chevallier DMSG("No RIF configuration available"); 2060461e8793SGatien Chevallier return TEE_SUCCESS; 2061461e8793SGatien Chevallier } 2062461e8793SGatien Chevallier 2063461e8793SGatien Chevallier pdata->conf_data = calloc(1, sizeof(*pdata->conf_data)); 2064461e8793SGatien Chevallier if (!pdata->conf_data) 2065461e8793SGatien Chevallier panic(); 2066461e8793SGatien Chevallier 2067461e8793SGatien Chevallier pdata->nb_rif_resources = (unsigned int)(lenp / 2068461e8793SGatien Chevallier sizeof(uint32_t)); 2069461e8793SGatien Chevallier assert(pdata->nb_rif_resources <= TAMP_RIF_RESOURCES); 2070461e8793SGatien Chevallier 2071461e8793SGatien Chevallier pdata->conf_data->cid_confs = calloc(TAMP_RIF_RESOURCES, 2072461e8793SGatien Chevallier sizeof(uint32_t)); 2073461e8793SGatien Chevallier pdata->conf_data->sec_conf = calloc(1, sizeof(uint32_t)); 2074461e8793SGatien Chevallier pdata->conf_data->priv_conf = calloc(1, sizeof(uint32_t)); 2075461e8793SGatien Chevallier pdata->conf_data->access_mask = calloc(1, sizeof(uint32_t)); 2076461e8793SGatien Chevallier if (!pdata->conf_data->cid_confs || 2077461e8793SGatien Chevallier !pdata->conf_data->sec_conf || 2078461e8793SGatien Chevallier !pdata->conf_data->priv_conf || 2079461e8793SGatien Chevallier !pdata->conf_data->access_mask) 2080461e8793SGatien Chevallier panic("Not enough memory capacity for TAMP RIF config"); 2081461e8793SGatien Chevallier 2082461e8793SGatien Chevallier for (i = 0; i < pdata->nb_rif_resources; i++) 2083461e8793SGatien Chevallier stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), 2084461e8793SGatien Chevallier pdata->conf_data, 2085461e8793SGatien Chevallier TAMP_RIF_RESOURCES); 2086461e8793SGatien Chevallier } 2087461e8793SGatien Chevallier 2088461e8793SGatien Chevallier return TEE_SUCCESS; 208969b8b983SEtienne Carriere } 209069b8b983SEtienne Carriere 209169b8b983SEtienne Carriere static TEE_Result stm32_tamp_probe(const void *fdt, int node, 209269b8b983SEtienne Carriere const void *compat_data) 209369b8b983SEtienne Carriere { 2094ca530bf3SGatien Chevallier size_t it_num = DT_INFO_INVALID_INTERRUPT; 209569b8b983SEtienne Carriere uint32_t __maybe_unused revision = 0; 2096ca530bf3SGatien Chevallier struct itr_chip *chip = NULL; 209769b8b983SEtienne Carriere TEE_Result res = TEE_SUCCESS; 209869b8b983SEtienne Carriere vaddr_t base = 0; 209969b8b983SEtienne Carriere 2100ca530bf3SGatien Chevallier /* Manage dependency on RNG driver */ 2101ca530bf3SGatien Chevallier res = dt_driver_get_crypto(); 2102ca530bf3SGatien Chevallier if (res) 2103ca530bf3SGatien Chevallier return res; 2104ca530bf3SGatien Chevallier 2105ca530bf3SGatien Chevallier /* Manage dependency on RTC driver */ 2106ca530bf3SGatien Chevallier res = stm32_rtc_driver_is_initialized(); 2107ca530bf3SGatien Chevallier if (res) 2108ca530bf3SGatien Chevallier return res; 2109ca530bf3SGatien Chevallier 2110ca530bf3SGatien Chevallier res = interrupt_dt_get_by_index(fdt, node, 0, &chip, &it_num); 2111ca530bf3SGatien Chevallier if (res) 2112ca530bf3SGatien Chevallier return res; 2113ca530bf3SGatien Chevallier 2114461e8793SGatien Chevallier stm32_tamp_dev = calloc(1, sizeof(*stm32_tamp_dev)); 2115461e8793SGatien Chevallier if (!stm32_tamp_dev) 211669b8b983SEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY; 211769b8b983SEtienne Carriere 2118461e8793SGatien Chevallier res = stm32_tamp_parse_fdt(fdt, node, compat_data); 211969b8b983SEtienne Carriere if (res) 212069b8b983SEtienne Carriere goto err; 212169b8b983SEtienne Carriere 2122461e8793SGatien Chevallier if (clk_enable(stm32_tamp_dev->pdata.clock)) 2123461e8793SGatien Chevallier panic(); 212469b8b983SEtienne Carriere 2125ca530bf3SGatien Chevallier base = get_base(); 212669b8b983SEtienne Carriere 2127461e8793SGatien Chevallier stm32_tamp_dev->hwconf1 = io_read32(base + _TAMP_HWCFGR1); 2128461e8793SGatien Chevallier stm32_tamp_dev->hwconf2 = io_read32(base + _TAMP_HWCFGR2); 212969b8b983SEtienne Carriere 213069b8b983SEtienne Carriere revision = io_read32(base + _TAMP_VERR); 213169b8b983SEtienne Carriere FMSG("STM32 TAMPER V%"PRIx32".%"PRIu32, 213269b8b983SEtienne Carriere (revision & _TAMP_VERR_MAJREV) >> 4, revision & _TAMP_VERR_MINREV); 213369b8b983SEtienne Carriere 2134461e8793SGatien Chevallier if (!(stm32_tamp_dev->hwconf2 & _TAMP_HWCFGR2_TZ)) { 213569b8b983SEtienne Carriere EMSG("TAMP doesn't support TrustZone"); 213669b8b983SEtienne Carriere res = TEE_ERROR_NOT_SUPPORTED; 213769b8b983SEtienne Carriere goto err_clk; 213869b8b983SEtienne Carriere } 213969b8b983SEtienne Carriere 2140461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) { 2141461e8793SGatien Chevallier apply_rif_config(); 2142461e8793SGatien Chevallier 2143461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.is_tdcid) { 2144461e8793SGatien Chevallier res = stm32_tamp_apply_bkpr_rif_conf(); 2145461e8793SGatien Chevallier if (res) 2146461e8793SGatien Chevallier goto err_clk; 2147461e8793SGatien Chevallier } 2148461e8793SGatien Chevallier } else { 214969b8b983SEtienne Carriere /* 215069b8b983SEtienne Carriere * Enforce secure only access to protected TAMP registers. 215169b8b983SEtienne Carriere * Allow non-secure access to monotonic counter. 215269b8b983SEtienne Carriere */ 2153461e8793SGatien Chevallier stm32_tamp_set_secure(_TAMP_SECCFGR_TAMPSEC); 215469b8b983SEtienne Carriere 215569b8b983SEtienne Carriere /* 215669b8b983SEtienne Carriere * Enforce privilege only access to TAMP registers, backup 215769b8b983SEtienne Carriere * registers and monotonic counter. 215869b8b983SEtienne Carriere */ 2159461e8793SGatien Chevallier stm32_tamp_set_privilege(_TAMP_PRIVCFG_TAMPPRIV | 216069b8b983SEtienne Carriere _TAMP_PRIVCFG_BKPRWPRIV | 216169b8b983SEtienne Carriere _TAMP_PRIVCFG_BKPWPRIV); 2162461e8793SGatien Chevallier } 216369b8b983SEtienne Carriere 216492ab6535SGatien Chevallier if (!(stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) || 216592ab6535SGatien Chevallier stm32_tamp_dev->pdata.is_tdcid) { 216692ab6535SGatien Chevallier res = stm32_tamp_set_secure_bkpregs(); 216792ab6535SGatien Chevallier if (res) 216892ab6535SGatien Chevallier goto err_clk; 216992ab6535SGatien Chevallier } 217092ab6535SGatien Chevallier 2171ca530bf3SGatien Chevallier res = interrupt_create_handler(chip, it_num, stm32_tamp_it_handler, 2172ca530bf3SGatien Chevallier NULL, ITRF_TRIGGER_LEVEL, 2173ca530bf3SGatien Chevallier &stm32_tamp_dev->pdata.itr); 2174ca530bf3SGatien Chevallier if (res) 2175ca530bf3SGatien Chevallier goto err_clk; 2176ca530bf3SGatien Chevallier 2177ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.is_wakeup_source && 2178ca530bf3SGatien Chevallier interrupt_can_set_wake(chip)) { 2179ca530bf3SGatien Chevallier interrupt_set_wake(chip, it_num, true); 2180ca530bf3SGatien Chevallier DMSG("Tamper event wakeup capability enabled"); 2181ca530bf3SGatien Chevallier } 2182ca530bf3SGatien Chevallier 2183ca530bf3SGatien Chevallier res = stm32_configure_tamp(fdt, node); 2184ca530bf3SGatien Chevallier if (res) 2185ca530bf3SGatien Chevallier goto err_clk; 2186ca530bf3SGatien Chevallier 2187ca530bf3SGatien Chevallier stm32_tamp_set_pins(base, stm32_tamp_dev->pdata.pins_conf); 2188ca530bf3SGatien Chevallier 2189ca530bf3SGatien Chevallier interrupt_enable(chip, it_num); 2190ca530bf3SGatien Chevallier 219169b8b983SEtienne Carriere return TEE_SUCCESS; 219269b8b983SEtienne Carriere 219369b8b983SEtienne Carriere err_clk: 2194461e8793SGatien Chevallier clk_disable(stm32_tamp_dev->pdata.clock); 219569b8b983SEtienne Carriere err: 2196461e8793SGatien Chevallier if (stm32_tamp_dev->pdata.conf_data) { 2197461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->cid_confs); 2198461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->sec_conf); 2199461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->priv_conf); 2200461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data->access_mask); 2201461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.conf_data); 2202461e8793SGatien Chevallier } 2203ca530bf3SGatien Chevallier 2204ca530bf3SGatien Chevallier if (stm32_tamp_dev->pdata.itr) { 2205ca530bf3SGatien Chevallier interrupt_disable(chip, it_num); 2206ca530bf3SGatien Chevallier interrupt_remove_free_handler(stm32_tamp_dev->pdata.itr); 2207ca530bf3SGatien Chevallier } 2208ca530bf3SGatien Chevallier 2209461e8793SGatien Chevallier free(stm32_tamp_dev->pdata.bkpregs_conf.rif_offsets); 2210461e8793SGatien Chevallier free(stm32_tamp_dev); 2211461e8793SGatien Chevallier 221269b8b983SEtienne Carriere return res; 221369b8b983SEtienne Carriere } 221469b8b983SEtienne Carriere 221569b8b983SEtienne Carriere static const struct stm32_tamp_compat mp13_compat = { 221669b8b983SEtienne Carriere .nb_monotonic_counter = 2, 2217ca530bf3SGatien Chevallier .tags = TAMP_HAS_REGISTER_SECCFGR | TAMP_HAS_REGISTER_PRIVCFGR | 2218ca530bf3SGatien Chevallier TAMP_HAS_REGISTER_ERCFGR | TAMP_HAS_REGISTER_CR3 | 2219ca530bf3SGatien Chevallier TAMP_HAS_REGISTER_ATCR2 | TAMP_HAS_CR2_SECRET_STATUS | 2220ca530bf3SGatien Chevallier TAMP_SIZE_ATCR1_ATCKSEL_IS_4, 2221ca530bf3SGatien Chevallier #if defined(CFG_STM32MP13) 2222ca530bf3SGatien Chevallier .int_tamp = int_tamp_mp13, 2223ca530bf3SGatien Chevallier .int_tamp_size = ARRAY_SIZE(int_tamp_mp13), 2224ca530bf3SGatien Chevallier .ext_tamp = ext_tamp_mp13, 2225ca530bf3SGatien Chevallier .ext_tamp_size = ARRAY_SIZE(ext_tamp_mp13), 2226ca530bf3SGatien Chevallier .pin_map = pin_map_mp13, 2227ca530bf3SGatien Chevallier .pin_map_size = ARRAY_SIZE(pin_map_mp13), 2228ca530bf3SGatien Chevallier #endif 222969b8b983SEtienne Carriere }; 223069b8b983SEtienne Carriere 223169b8b983SEtienne Carriere static const struct stm32_tamp_compat mp15_compat = { 223269b8b983SEtienne Carriere .nb_monotonic_counter = 1, 223369b8b983SEtienne Carriere .tags = 0, 2234ca530bf3SGatien Chevallier #if defined(CFG_STM32MP15) 2235ca530bf3SGatien Chevallier .int_tamp = int_tamp_mp15, 2236ca530bf3SGatien Chevallier .int_tamp_size = ARRAY_SIZE(int_tamp_mp15), 2237ca530bf3SGatien Chevallier .ext_tamp = ext_tamp_mp15, 2238ca530bf3SGatien Chevallier .ext_tamp_size = ARRAY_SIZE(ext_tamp_mp15), 2239ca530bf3SGatien Chevallier .pin_map = pin_map_mp15, 2240ca530bf3SGatien Chevallier .pin_map_size = ARRAY_SIZE(pin_map_mp15), 2241ca530bf3SGatien Chevallier #endif 2242ca530bf3SGatien Chevallier }; 2243ca530bf3SGatien Chevallier 2244ca530bf3SGatien Chevallier static const struct stm32_tamp_compat mp21_compat = { 2245ca530bf3SGatien Chevallier .nb_monotonic_counter = 2, 2246ca530bf3SGatien Chevallier .tags = TAMP_HAS_REGISTER_SECCFGR | 2247ca530bf3SGatien Chevallier TAMP_HAS_REGISTER_PRIVCFGR | 2248ca530bf3SGatien Chevallier TAMP_HAS_RIF_SUPPORT | 2249ca530bf3SGatien Chevallier TAMP_HAS_REGISTER_ERCFGR | 2250ca530bf3SGatien Chevallier TAMP_HAS_REGISTER_CR3 | 2251ca530bf3SGatien Chevallier TAMP_HAS_REGISTER_ATCR2 | 2252ca530bf3SGatien Chevallier TAMP_HAS_CR2_SECRET_STATUS | 2253ca530bf3SGatien Chevallier TAMP_SIZE_ATCR1_ATCKSEL_IS_4, 2254ca530bf3SGatien Chevallier #if defined(CFG_STM32MP21) 2255ca530bf3SGatien Chevallier .int_tamp = int_tamp_mp21, 2256ca530bf3SGatien Chevallier .int_tamp_size = ARRAY_SIZE(int_tamp_mp21), 2257ca530bf3SGatien Chevallier .ext_tamp = ext_tamp_mp21, 2258ca530bf3SGatien Chevallier .ext_tamp_size = ARRAY_SIZE(ext_tamp_mp21), 2259ca530bf3SGatien Chevallier .pin_map = pin_map_mp21, 2260ca530bf3SGatien Chevallier .pin_map_size = ARRAY_SIZE(pin_map_mp21), 2261ca530bf3SGatien Chevallier #endif 226269b8b983SEtienne Carriere }; 226369b8b983SEtienne Carriere 2264461e8793SGatien Chevallier static const struct stm32_tamp_compat mp25_compat = { 2265461e8793SGatien Chevallier .nb_monotonic_counter = 2, 2266ca530bf3SGatien Chevallier .tags = TAMP_HAS_REGISTER_SECCFGR | TAMP_HAS_REGISTER_PRIVCFGR | 2267ca530bf3SGatien Chevallier TAMP_HAS_RIF_SUPPORT | TAMP_HAS_REGISTER_ERCFGR | 2268ca530bf3SGatien Chevallier TAMP_HAS_REGISTER_CR3 | TAMP_HAS_REGISTER_ATCR2 | 2269ca530bf3SGatien Chevallier TAMP_HAS_CR2_SECRET_STATUS | TAMP_SIZE_ATCR1_ATCKSEL_IS_4, 2270ca530bf3SGatien Chevallier #if defined(CFG_STM32MP25) 2271ca530bf3SGatien Chevallier .int_tamp = int_tamp_mp25, 2272ca530bf3SGatien Chevallier .int_tamp_size = ARRAY_SIZE(int_tamp_mp25), 2273ca530bf3SGatien Chevallier .ext_tamp = ext_tamp_mp25, 2274ca530bf3SGatien Chevallier .ext_tamp_size = ARRAY_SIZE(ext_tamp_mp25), 2275ca530bf3SGatien Chevallier .pin_map = pin_map_mp25, 2276ca530bf3SGatien Chevallier .pin_map_size = ARRAY_SIZE(pin_map_mp25), 2277ca530bf3SGatien Chevallier #endif 2278461e8793SGatien Chevallier }; 2279461e8793SGatien Chevallier 228069b8b983SEtienne Carriere static const struct dt_device_match stm32_tamp_match_table[] = { 2281461e8793SGatien Chevallier { .compatible = "st,stm32mp25-tamp", .compat_data = &mp25_compat }, 2282ca530bf3SGatien Chevallier { .compatible = "st,stm32mp21-tamp", .compat_data = &mp21_compat }, 228369b8b983SEtienne Carriere { .compatible = "st,stm32mp13-tamp", .compat_data = &mp13_compat }, 228469b8b983SEtienne Carriere { .compatible = "st,stm32-tamp", .compat_data = &mp15_compat }, 228569b8b983SEtienne Carriere { } 228669b8b983SEtienne Carriere }; 228769b8b983SEtienne Carriere 228869b8b983SEtienne Carriere DEFINE_DT_DRIVER(stm32_tamp_dt_driver) = { 228969b8b983SEtienne Carriere .name = "stm32-tamp", 229069b8b983SEtienne Carriere .match_table = stm32_tamp_match_table, 229169b8b983SEtienne Carriere .probe = stm32_tamp_probe, 229269b8b983SEtienne Carriere }; 2293