xref: /optee_os/core/drivers/stm32_tamp.c (revision ca530bf3ae2d1c5a400e9e7a4eaa2d03971b3300)
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, &reg_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