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