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