xref: /optee_os/core/drivers/stm32_tamp.c (revision 461e879370d2f82cd6fff838061e9a3013fd69e4)
169b8b983SEtienne Carriere // SPDX-License-Identifier: BSD-3-Clause
269b8b983SEtienne Carriere /*
369b8b983SEtienne Carriere  * Copyright (c) 2021-2022, STMicroelectronics
469b8b983SEtienne Carriere  */
569b8b983SEtienne Carriere 
669b8b983SEtienne Carriere #include <drivers/clk.h>
769b8b983SEtienne Carriere #include <drivers/clk_dt.h>
8*461e8793SGatien Chevallier #include <drivers/stm32_rif.h>
969b8b983SEtienne Carriere #include <drivers/stm32_tamp.h>
1069b8b983SEtienne Carriere #include <io.h>
1169b8b983SEtienne Carriere #include <kernel/dt.h>
129e3c57c8SEtienne Carriere #include <kernel/dt_driver.h>
1369b8b983SEtienne Carriere #include <kernel/interrupt.h>
1469b8b983SEtienne Carriere #include <libfdt.h>
1569b8b983SEtienne Carriere #include <mm/core_memprot.h>
1669b8b983SEtienne Carriere #include <stdbool.h>
1769b8b983SEtienne Carriere 
1869b8b983SEtienne Carriere /* STM32 Registers */
1969b8b983SEtienne Carriere #define _TAMP_CR1			0x00U
2069b8b983SEtienne Carriere #define _TAMP_CR2			0x04U
2169b8b983SEtienne Carriere #define _TAMP_CR3			0x08U
2269b8b983SEtienne Carriere #define _TAMP_FLTCR			0x0CU
2369b8b983SEtienne Carriere #define _TAMP_ATCR1			0x10U
2469b8b983SEtienne Carriere #define _TAMP_ATSEEDR			0x14U
2569b8b983SEtienne Carriere #define _TAMP_ATOR			0x18U
2669b8b983SEtienne Carriere #define _TAMP_ATCR2			0x1CU
2769b8b983SEtienne Carriere #define _TAMP_SECCFGR			0x20U
2869b8b983SEtienne Carriere #define _TAMP_SMCR			0x20U
2969b8b983SEtienne Carriere #define _TAMP_PRIVCFGR			0x24U
3069b8b983SEtienne Carriere #define _TAMP_IER			0x2CU
3169b8b983SEtienne Carriere #define _TAMP_SR			0x30U
3269b8b983SEtienne Carriere #define _TAMP_MISR			0x34U
3369b8b983SEtienne Carriere #define _TAMP_SMISR			0x38U
3469b8b983SEtienne Carriere #define _TAMP_SCR			0x3CU
3569b8b983SEtienne Carriere #define _TAMP_COUNTR			0x40U
3669b8b983SEtienne Carriere #define _TAMP_COUNT2R			0x44U
3769b8b983SEtienne Carriere #define _TAMP_OR			0x50U
3869b8b983SEtienne Carriere #define _TAMP_ERCFGR			0X54U
39*461e8793SGatien Chevallier #define _TAMP_BKPRIFR(x)		(0x70U + 0x4U * ((x) - 1U))
40*461e8793SGatien Chevallier #define _TAMP_CIDCFGR(x)		(0x80U + 0x4U * (x))
41*461e8793SGatien Chevallier #define _TAMP_BKPxR(x)			(0x100U + 0x4U * ((x) - 1U))
4269b8b983SEtienne Carriere #define _TAMP_HWCFGR2			0x3ECU
4369b8b983SEtienne Carriere #define _TAMP_HWCFGR1			0x3F0U
4469b8b983SEtienne Carriere #define _TAMP_VERR			0x3F4U
4569b8b983SEtienne Carriere #define _TAMP_IPIDR			0x3F8U
4669b8b983SEtienne Carriere #define _TAMP_SIDR			0x3FCU
4769b8b983SEtienne Carriere 
4869b8b983SEtienne Carriere /* _TAMP_SECCFGR bit fields */
4969b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_MASK	GENMASK_32(7, 0)
5069b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_SHIFT	0U
5169b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT2SEC		BIT(14)
52*461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT2SEC_SHIFT	14U
5369b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT1SEC		BIT(15)
54*461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT1SEC_SHIFT	15U
5569b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_MASK	GENMASK_32(23, 16)
5669b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_SHIFT	16U
5769b8b983SEtienne Carriere #define _TAMP_SECCFGR_BHKLOCK		BIT(30)
5869b8b983SEtienne Carriere #define _TAMP_SECCFGR_TAMPSEC		BIT(31)
59*461e8793SGatien Chevallier #define _TAMP_SECCFGR_TAMPSEC_SHIFT	31U
6069b8b983SEtienne Carriere #define _TAMP_SECCFGR_BUT_BKP_MASK	(GENMASK_32(31, 30) | \
6169b8b983SEtienne Carriere 					 GENMASK_32(15, 14))
62*461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_TAMP_SEC	BIT(0)
63*461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_1	BIT(1)
64*461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_2	BIT(2)
6569b8b983SEtienne Carriere 
6669b8b983SEtienne Carriere /* _TAMP_SMCR bit fields */
6769b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_MASK	GENMASK_32(7, 0)
6869b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_SHIFT	0U
6969b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_MASK	GENMASK_32(23, 16)
7069b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_SHIFT	16U
7169b8b983SEtienne Carriere #define _TAMP_SMCR_DPROT		BIT(31)
7269b8b983SEtienne Carriere /*
7369b8b983SEtienne Carriere  * _TAMP_PRIVCFGR bit fields
7469b8b983SEtienne Carriere  */
7569b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV		BIT(14)
7669b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV		BIT(15)
7769b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV		BIT(29)
7869b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV		BIT(30)
7969b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV		BIT(31)
8069b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK		(GENMASK_32(31, 29) | \
8169b8b983SEtienne Carriere 					 GENMASK_32(15, 14))
82*461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_TAMP_PRIV	BIT(0)
83*461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R1		BIT(1)
84*461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R2		BIT(2)
8569b8b983SEtienne Carriere 
8669b8b983SEtienne Carriere /*
8769b8b983SEtienne Carriere  * _TAMP_PRIVCFGR bit fields
8869b8b983SEtienne Carriere  */
8969b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV		BIT(14)
9069b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV		BIT(15)
9169b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV		BIT(29)
9269b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV		BIT(30)
9369b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV		BIT(31)
9469b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK		(GENMASK_32(31, 29) | \
9569b8b983SEtienne Carriere 					 GENMASK_32(15, 14))
9669b8b983SEtienne Carriere 
9769b8b983SEtienne Carriere /* _TAMP_HWCFGR2 bit fields */
9869b8b983SEtienne Carriere #define _TAMP_HWCFGR2_TZ		GENMASK_32(11, 8)
9969b8b983SEtienne Carriere #define _TAMP_HWCFGR2_OR		GENMASK_32(7, 0)
10069b8b983SEtienne Carriere 
10169b8b983SEtienne Carriere /* _TAMP_HWCFGR1 bit fields */
10269b8b983SEtienne Carriere #define _TAMP_HWCFGR1_BKPREG		GENMASK_32(7, 0)
10369b8b983SEtienne Carriere #define _TAMP_HWCFGR1_TAMPER		GENMASK_32(11, 8)
10469b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ACTIVE		GENMASK_32(15, 12)
10569b8b983SEtienne Carriere #define _TAMP_HWCFGR1_INTERN		GENMASK_32(31, 16)
10669b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP_MAX_ID	16U
10769b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP(id)		BIT((id) - INT_TAMP1 + 16U)
10869b8b983SEtienne Carriere 
10969b8b983SEtienne Carriere /* _TAMP_VERR bit fields */
11069b8b983SEtienne Carriere #define _TAMP_VERR_MINREV		GENMASK_32(3, 0)
11169b8b983SEtienne Carriere #define _TAMP_VERR_MAJREV		GENMASK_32(7, 4)
11269b8b983SEtienne Carriere 
11369b8b983SEtienne Carriere /*
114*461e8793SGatien Chevallier  * CIDCFGR register bitfields
11569b8b983SEtienne Carriere  */
116*461e8793SGatien Chevallier #define _TAMP_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
117*461e8793SGatien Chevallier #define _TAMP_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	 \
118*461e8793SGatien Chevallier 					 _CIDCFGR_SEMEN |	 \
119*461e8793SGatien Chevallier 					 _TAMP_CIDCFGR_SCID_MASK)
120*461e8793SGatien Chevallier 
121*461e8793SGatien Chevallier /* _TAMP_BKPRIFR */
122*461e8793SGatien Chevallier #define _TAMP_BKPRIFR_1_MASK		GENMASK_32(7, 0)
123*461e8793SGatien Chevallier #define _TAMP_BKPRIFR_2_MASK		GENMASK_32(7, 0)
124*461e8793SGatien Chevallier #define _TAMP_BKPRIFR_3_MASK		(GENMASK_32(23, 16) | GENMASK_32(7, 0))
125*461e8793SGatien Chevallier #define _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT	16U
126*461e8793SGatien Chevallier 
127*461e8793SGatien Chevallier /*
128*461e8793SGatien Chevallier  * RIF miscellaneous
129*461e8793SGatien Chevallier  */
130*461e8793SGatien Chevallier #define TAMP_NB_BKPR_ZONES		3U
131*461e8793SGatien Chevallier #define TAMP_RIF_RESOURCES		3U
132*461e8793SGatien Chevallier #define TAMP_RIF_OFFSET_CNT		4U
13369b8b983SEtienne Carriere 
13469b8b983SEtienne Carriere /*
13569b8b983SEtienne Carriere  * Compatibility capabilities
136*461e8793SGatien Chevallier  * TAMP_HAS_REGISTER_SECCFGR - Supports SECCFGR, otherwise supports SMCR
137*461e8793SGatien Chevallier  * register
13869b8b983SEtienne Carriere  * TAMP_HAS_REGISTER_PRIVCFG - Supports PRIVCFGR configuration register
139*461e8793SGatien Chevallier  * TAMP_HAS_RIF_SUPPORT - Supports RIF
14069b8b983SEtienne Carriere  */
141*461e8793SGatien Chevallier #define TAMP_HAS_REGISTER_SECCFGR	BIT(0)
14269b8b983SEtienne Carriere #define TAMP_HAS_REGISTER_PRIVCFGR	BIT(1)
143*461e8793SGatien Chevallier #define TAMP_HAS_RIF_SUPPORT		BIT(31)
14469b8b983SEtienne Carriere 
145*461e8793SGatien Chevallier /**
146*461e8793SGatien Chevallier  * struct stm32_tamp_compat - TAMP compatible data
147*461e8793SGatien Chevallier  * @nb_monotonic_counter: Number of monotic counter supported
148*461e8793SGatien Chevallier  * @tags: Bit flags TAMP_HAS_* for compatibility management
14969b8b983SEtienne Carriere  */
15069b8b983SEtienne Carriere struct stm32_tamp_compat {
15169b8b983SEtienne Carriere 	int nb_monotonic_counter;
15269b8b983SEtienne Carriere 	uint32_t tags;
15369b8b983SEtienne Carriere };
15469b8b983SEtienne Carriere 
155*461e8793SGatien Chevallier /*
156*461e8793SGatien Chevallier  * struct stm32_bkpregs_conf_new - Backup registers zone bounds
157*461e8793SGatien Chevallier  * @zone1_end - Number of backup registers in zone 1
158*461e8793SGatien Chevallier  * @zone2_end - Number of backup registers in zone 2 + zone 1
159*461e8793SGatien Chevallier  * @rif_offsets - RIF offsets used for CID compartments
160*461e8793SGatien Chevallier  *
161*461e8793SGatien Chevallier  * TAMP backup registers access permissions
162*461e8793SGatien Chevallier  *
163*461e8793SGatien Chevallier  * Zone 1: read/write in secure state, no access in non-secure state
164*461e8793SGatien Chevallier  * Zone 2: read/write in secure state, read-only in non-secure state
165*461e8793SGatien Chevallier  * Zone 3: read/write in secure state, read/write in non-secure state
166*461e8793SGatien Chevallier  *
167*461e8793SGatien Chevallier  * Protection zone 1
168*461e8793SGatien Chevallier  * If zone1_end == 0 no backup register are in zone 1.
169*461e8793SGatien Chevallier  * Otherwise backup registers from TAMP_BKP0R to TAMP_BKP<x>R are in zone 1,
170*461e8793SGatien Chevallier  * with <x> = (@zone1_end - 1).
171*461e8793SGatien Chevallier  *
172*461e8793SGatien Chevallier  * Protection zone 2
173*461e8793SGatien Chevallier  * If zone2_end == 0 no backup register are in zone 2 and zone 1.
174*461e8793SGatien Chevallier  * Otherwise backup registers from TAMP_BKP<y>R to TAMP_BKP<z>R are in zone 2,
175*461e8793SGatien Chevallier  * with <y> = @zone1_end and <z> = (@zone2_end - 1).
176*461e8793SGatien Chevallier  *
177*461e8793SGatien Chevallier  * Protection zone 3
178*461e8793SGatien Chevallier  * Backup registers from TAMP_BKP<t>R to last backup register are in zone 3,
179*461e8793SGatien Chevallier  * with <t> = (@zone2_end - 1).
180*461e8793SGatien Chevallier  *
181*461e8793SGatien Chevallier  * When RIF is supported, each zone can be subdivided to restrain accesses to
182*461e8793SGatien Chevallier  * some CIDs.
183*461e8793SGatien Chevallier  */
184*461e8793SGatien Chevallier struct stm32_bkpregs_conf_new {
185*461e8793SGatien Chevallier 	uint32_t zone1_end;
186*461e8793SGatien Chevallier 	uint32_t zone2_end;
187*461e8793SGatien Chevallier 	uint32_t *rif_offsets;
188*461e8793SGatien Chevallier };
189*461e8793SGatien Chevallier 
190*461e8793SGatien Chevallier /**
191*461e8793SGatien Chevallier  * struct stm32_tamp_platdata - TAMP platform data
192*461e8793SGatien Chevallier  * @base: IOMEM base address
193*461e8793SGatien Chevallier  * @bkpregs_conf: TAMP backup register configuration reference
194*461e8793SGatien Chevallier  * @compat: Reference to compat data passed at driver initialization
195*461e8793SGatien Chevallier  * @conf_data: RIF configuration data
196*461e8793SGatien Chevallier  * @clock: TAMP clock
197*461e8793SGatien Chevallier  * @nb_rif_resources: Number of RIF resources
198*461e8793SGatien Chevallier  * @it: TAMP interrupt number
199*461e8793SGatien Chevallier  * @is_tdcid: True if current processor is TDCID
200*461e8793SGatien Chevallier  */
201*461e8793SGatien Chevallier struct stm32_tamp_platdata {
202*461e8793SGatien Chevallier 	struct io_pa_va base;
203*461e8793SGatien Chevallier 	struct stm32_bkpregs_conf_new bkpregs_conf;
204*461e8793SGatien Chevallier 	struct stm32_tamp_compat *compat;
205*461e8793SGatien Chevallier 	struct rif_conf_data *conf_data;
206*461e8793SGatien Chevallier 	struct clk *clock;
207*461e8793SGatien Chevallier 	unsigned int nb_rif_resources;
208*461e8793SGatien Chevallier 	int it;
209*461e8793SGatien Chevallier 	bool is_tdcid;
210*461e8793SGatien Chevallier };
211*461e8793SGatien Chevallier 
212*461e8793SGatien Chevallier /**
213*461e8793SGatien Chevallier  * struct stm32_tamp_instance - TAMP instance data
214*461e8793SGatien Chevallier  * @pdata: TAMP platform data
215*461e8793SGatien Chevallier  * @hwconf1: Copy of TAMP HWCONF1 register content
216*461e8793SGatien Chevallier  * @hwconf2: Copy of TAMP HWCONF2 register content
217*461e8793SGatien Chevallier  */
218*461e8793SGatien Chevallier struct stm32_tamp_instance {
219*461e8793SGatien Chevallier 	struct stm32_tamp_platdata pdata;
220*461e8793SGatien Chevallier 	uint32_t hwconf1;
221*461e8793SGatien Chevallier 	uint32_t hwconf2;
222*461e8793SGatien Chevallier };
223*461e8793SGatien Chevallier 
22469b8b983SEtienne Carriere /* Expects at most a single instance */
225*461e8793SGatien Chevallier static struct stm32_tamp_instance *stm32_tamp_dev;
226*461e8793SGatien Chevallier 
227*461e8793SGatien Chevallier static void apply_rif_config(void)
228*461e8793SGatien Chevallier {
229*461e8793SGatien Chevallier 	struct rif_conf_data *rif_conf = stm32_tamp_dev->pdata.conf_data;
230*461e8793SGatien Chevallier 	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
231*461e8793SGatien Chevallier 	uint32_t access_mask_priv_reg = 0;
232*461e8793SGatien Chevallier 	uint32_t access_mask_sec_reg = 0;
233*461e8793SGatien Chevallier 	uint32_t privcfgr = 0;
234*461e8793SGatien Chevallier 	uint32_t seccfgr = 0;
235*461e8793SGatien Chevallier 	unsigned int i = 0;
236*461e8793SGatien Chevallier 
237*461e8793SGatien Chevallier 	if (!stm32_tamp_dev->pdata.conf_data)
238*461e8793SGatien Chevallier 		return;
239*461e8793SGatien Chevallier 
240*461e8793SGatien Chevallier 	/* Build access masks for _TAMP_PRIVCFGR and _TAMP_SECCFGR */
241*461e8793SGatien Chevallier 	for (i = 0; i < TAMP_RIF_RESOURCES; i++) {
242*461e8793SGatien Chevallier 		if (BIT(i) & rif_conf->access_mask[0]) {
243*461e8793SGatien Chevallier 			switch (i) {
244*461e8793SGatien Chevallier 			case 0:
245*461e8793SGatien Chevallier 				access_mask_sec_reg |= _TAMP_SECCFGR_TAMPSEC;
246*461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_TAMPPRIV;
247*461e8793SGatien Chevallier 				break;
248*461e8793SGatien Chevallier 			case 1:
249*461e8793SGatien Chevallier 				access_mask_sec_reg |= _TAMP_SECCFGR_CNT1SEC;
250*461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_CNT1PRIV;
251*461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_BKPRWPRIV;
252*461e8793SGatien Chevallier 				break;
253*461e8793SGatien Chevallier 			case 2:
254*461e8793SGatien Chevallier 				access_mask_sec_reg |= _TAMP_SECCFGR_CNT2SEC;
255*461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_CNT2PRIV;
256*461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_BKPWPRIV;
257*461e8793SGatien Chevallier 				break;
258*461e8793SGatien Chevallier 			default:
259*461e8793SGatien Chevallier 				panic();
260*461e8793SGatien Chevallier 			}
261*461e8793SGatien Chevallier 		}
262*461e8793SGatien Chevallier 	}
263*461e8793SGatien Chevallier 
264*461e8793SGatien Chevallier 	/*
265*461e8793SGatien Chevallier 	 * When TDCID, OP-TEE should be the one to set the CID filtering
266*461e8793SGatien Chevallier 	 * configuration. Clearing previous configuration prevents
267*461e8793SGatien Chevallier 	 * undesired events during the only legitimate configuration.
268*461e8793SGatien Chevallier 	 */
269*461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.is_tdcid) {
270*461e8793SGatien Chevallier 		for (i = 0; i < TAMP_RIF_RESOURCES; i++)
271*461e8793SGatien Chevallier 			if (BIT(i) & rif_conf->access_mask[0])
272*461e8793SGatien Chevallier 				io_clrbits32(base + _TAMP_CIDCFGR(i),
273*461e8793SGatien Chevallier 					     _TAMP_CIDCFGR_CONF_MASK);
274*461e8793SGatien Chevallier 	}
275*461e8793SGatien Chevallier 
276*461e8793SGatien Chevallier 	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_TAMP_SEC)
277*461e8793SGatien Chevallier 		seccfgr |= _TAMP_SECCFGR_TAMPSEC;
278*461e8793SGatien Chevallier 	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_1)
279*461e8793SGatien Chevallier 		seccfgr |= _TAMP_SECCFGR_CNT1SEC;
280*461e8793SGatien Chevallier 	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_2)
281*461e8793SGatien Chevallier 		seccfgr |= _TAMP_SECCFGR_CNT2SEC;
282*461e8793SGatien Chevallier 
283*461e8793SGatien Chevallier 	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_TAMP_PRIV)
284*461e8793SGatien Chevallier 		privcfgr |= _TAMP_PRIVCFG_TAMPPRIV;
285*461e8793SGatien Chevallier 	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R1)
286*461e8793SGatien Chevallier 		privcfgr |= _TAMP_PRIVCFG_CNT1PRIV | _TAMP_PRIVCFG_BKPRWPRIV;
287*461e8793SGatien Chevallier 	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R2)
288*461e8793SGatien Chevallier 		privcfgr |= _TAMP_PRIVCFG_CNT2PRIV | _TAMP_PRIVCFG_BKPWPRIV;
289*461e8793SGatien Chevallier 
290*461e8793SGatien Chevallier 	/* Security and privilege RIF configuration */
291*461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_PRIVCFGR, access_mask_priv_reg, privcfgr);
292*461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_SECCFGR, access_mask_sec_reg, seccfgr);
293*461e8793SGatien Chevallier 
294*461e8793SGatien Chevallier 	if (!stm32_tamp_dev->pdata.is_tdcid)
295*461e8793SGatien Chevallier 		return;
296*461e8793SGatien Chevallier 
297*461e8793SGatien Chevallier 	for (i = 0; i < TAMP_RIF_RESOURCES; i++) {
298*461e8793SGatien Chevallier 		if (!(BIT(i) & rif_conf->access_mask[0]))
299*461e8793SGatien Chevallier 			continue;
300*461e8793SGatien Chevallier 
301*461e8793SGatien Chevallier 		io_clrsetbits32(base + _TAMP_CIDCFGR(i),
302*461e8793SGatien Chevallier 				_TAMP_CIDCFGR_CONF_MASK,
303*461e8793SGatien Chevallier 				rif_conf->cid_confs[i]);
304*461e8793SGatien Chevallier 	}
305*461e8793SGatien Chevallier }
306*461e8793SGatien Chevallier 
307*461e8793SGatien Chevallier static TEE_Result stm32_tamp_apply_bkpr_rif_conf(void)
308*461e8793SGatien Chevallier {
309*461e8793SGatien Chevallier 	struct stm32_bkpregs_conf_new *bkpregs_conf =
310*461e8793SGatien Chevallier 			&stm32_tamp_dev->pdata.bkpregs_conf;
311*461e8793SGatien Chevallier 	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
312*461e8793SGatien Chevallier 	unsigned int i = 0;
313*461e8793SGatien Chevallier 
314*461e8793SGatien Chevallier 	if (!bkpregs_conf->rif_offsets)
315*461e8793SGatien Chevallier 		panic("No backup register configuration");
316*461e8793SGatien Chevallier 
317*461e8793SGatien Chevallier 	for (i = 0; i < TAMP_RIF_OFFSET_CNT; i++) {
318*461e8793SGatien Chevallier 		if (bkpregs_conf->rif_offsets[i] >
319*461e8793SGatien Chevallier 		    (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG))
320*461e8793SGatien Chevallier 			return TEE_ERROR_NOT_SUPPORTED;
321*461e8793SGatien Chevallier 	}
322*461e8793SGatien Chevallier 
323*461e8793SGatien Chevallier 	/* Fill the 3 TAMP_BKPRIFRx registers */
324*461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_BKPRIFR(1), _TAMP_BKPRIFR_1_MASK,
325*461e8793SGatien Chevallier 			bkpregs_conf->rif_offsets[0]);
326*461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_BKPRIFR(2), _TAMP_BKPRIFR_2_MASK,
327*461e8793SGatien Chevallier 			bkpregs_conf->rif_offsets[1]);
328*461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_BKPRIFR(3), _TAMP_BKPRIFR_3_MASK,
329*461e8793SGatien Chevallier 			bkpregs_conf->rif_offsets[2] |
330*461e8793SGatien Chevallier 			SHIFT_U32(bkpregs_conf->rif_offsets[3],
331*461e8793SGatien Chevallier 				  _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT));
332*461e8793SGatien Chevallier 
333*461e8793SGatien Chevallier 	DMSG("Backup registers mapping :");
334*461e8793SGatien Chevallier 	DMSG("********START of zone 1********");
335*461e8793SGatien Chevallier 	DMSG("Protection Zone 1-RIF1 begins at register: 0");
336*461e8793SGatien Chevallier 	DMSG("Protection Zone 1-RIF2 begins at register: %"PRIu32,
337*461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[0]);
338*461e8793SGatien Chevallier 	DMSG("Protection Zone 1-RIF2 ends at register: %"PRIu32,
339*461e8793SGatien Chevallier 	     bkpregs_conf->zone1_end ? bkpregs_conf->zone1_end - 1 : 0);
340*461e8793SGatien Chevallier 	DMSG("********END of zone 1********");
341*461e8793SGatien Chevallier 	DMSG("********START of zone 2********");
342*461e8793SGatien Chevallier 	DMSG("Protection Zone 2-RIF1 begins at register: %"PRIu32,
343*461e8793SGatien Chevallier 	     bkpregs_conf->zone1_end);
344*461e8793SGatien Chevallier 	DMSG("Protection Zone 2-RIF2 begins at register: %"PRIu32,
345*461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[1]);
346*461e8793SGatien Chevallier 	DMSG("Protection Zone 2-RIF2 ends at register: %"PRIu32,
347*461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[1] > bkpregs_conf->zone1_end ?
348*461e8793SGatien Chevallier 	     bkpregs_conf->zone2_end - 1 : 0);
349*461e8793SGatien Chevallier 	DMSG("********END of zone 2********");
350*461e8793SGatien Chevallier 	DMSG("********START of zone 3********");
351*461e8793SGatien Chevallier 	DMSG("Protection Zone 3-RIF1 begins at register: %"PRIu32,
352*461e8793SGatien Chevallier 	     bkpregs_conf->zone2_end);
353*461e8793SGatien Chevallier 	DMSG("Protection Zone 3-RIF0 begins at register: %"PRIu32,
354*461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[2]);
355*461e8793SGatien Chevallier 	DMSG("Protection Zone 3-RIF2 begins at register: %"PRIu32,
356*461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[3]);
357*461e8793SGatien Chevallier 	DMSG("Protection Zone 3-RIF2 ends at the last register: %"PRIu32,
358*461e8793SGatien Chevallier 	     stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG);
359*461e8793SGatien Chevallier 	DMSG("********END of zone 3********");
360*461e8793SGatien Chevallier 
361*461e8793SGatien Chevallier 	return TEE_SUCCESS;
362*461e8793SGatien Chevallier }
36369b8b983SEtienne Carriere 
36469b8b983SEtienne Carriere TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *bkr_conf)
36569b8b983SEtienne Carriere {
366*461e8793SGatien Chevallier 	struct stm32_tamp_instance *tamp = stm32_tamp_dev;
36769b8b983SEtienne Carriere 	vaddr_t base = 0;
36869b8b983SEtienne Carriere 	uint32_t first_z2 = 0;
36969b8b983SEtienne Carriere 	uint32_t first_z3 = 0;
37069b8b983SEtienne Carriere 
37169b8b983SEtienne Carriere 	if (!tamp)
37269b8b983SEtienne Carriere 		return TEE_ERROR_DEFER_DRIVER_INIT;
37369b8b983SEtienne Carriere 
37469b8b983SEtienne Carriere 	if (!bkr_conf)
37569b8b983SEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
37669b8b983SEtienne Carriere 
377*461e8793SGatien Chevallier 	base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
37869b8b983SEtienne Carriere 
37969b8b983SEtienne Carriere 	first_z2 = bkr_conf->nb_zone1_regs;
38069b8b983SEtienne Carriere 	first_z3 = bkr_conf->nb_zone1_regs + bkr_conf->nb_zone2_regs;
38169b8b983SEtienne Carriere 
382*461e8793SGatien Chevallier 	if ((first_z2 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) ||
383*461e8793SGatien Chevallier 	    (first_z3 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)))
38469b8b983SEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
38569b8b983SEtienne Carriere 
386*461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.compat &&
387*461e8793SGatien Chevallier 	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) {
38869b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SECCFGR,
38969b8b983SEtienne Carriere 				_TAMP_SECCFGR_BKPRWSEC_MASK,
39069b8b983SEtienne Carriere 				(first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) &
39169b8b983SEtienne Carriere 				_TAMP_SECCFGR_BKPRWSEC_MASK);
39269b8b983SEtienne Carriere 
39369b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SECCFGR,
39469b8b983SEtienne Carriere 				_TAMP_SECCFGR_BKPWSEC_MASK,
39569b8b983SEtienne Carriere 				(first_z3 << _TAMP_SECCFGR_BKPWSEC_SHIFT) &
39669b8b983SEtienne Carriere 				_TAMP_SECCFGR_BKPWSEC_MASK);
39769b8b983SEtienne Carriere 	} else {
39869b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SMCR,
39969b8b983SEtienne Carriere 				_TAMP_SMCR_BKPRWDPROT_MASK,
40069b8b983SEtienne Carriere 				(first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) &
40169b8b983SEtienne Carriere 				_TAMP_SMCR_BKPRWDPROT_MASK);
40269b8b983SEtienne Carriere 
40369b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SMCR,
40469b8b983SEtienne Carriere 				_TAMP_SMCR_BKPWDPROT_MASK,
40569b8b983SEtienne Carriere 				(first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) &
40669b8b983SEtienne Carriere 				_TAMP_SMCR_BKPWDPROT_MASK);
40769b8b983SEtienne Carriere 	}
40869b8b983SEtienne Carriere 
40969b8b983SEtienne Carriere 	return TEE_SUCCESS;
41069b8b983SEtienne Carriere }
41169b8b983SEtienne Carriere 
412*461e8793SGatien Chevallier static void stm32_tamp_set_secure(uint32_t mode)
41369b8b983SEtienne Carriere {
414*461e8793SGatien Chevallier 	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
41569b8b983SEtienne Carriere 
416*461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.compat &&
417*461e8793SGatien Chevallier 	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) {
41869b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SECCFGR,
41969b8b983SEtienne Carriere 				_TAMP_SECCFGR_BUT_BKP_MASK,
42069b8b983SEtienne Carriere 				mode & _TAMP_SECCFGR_BUT_BKP_MASK);
42169b8b983SEtienne Carriere 	} else {
42269b8b983SEtienne Carriere 		/*
42369b8b983SEtienne Carriere 		 * Note: MP15 doesn't use SECCFG register and
42469b8b983SEtienne Carriere 		 * inverts the secure bit.
42569b8b983SEtienne Carriere 		 */
42669b8b983SEtienne Carriere 		if (mode & _TAMP_SECCFGR_TAMPSEC)
42769b8b983SEtienne Carriere 			io_clrbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT);
42869b8b983SEtienne Carriere 		else
42969b8b983SEtienne Carriere 			io_setbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT);
43069b8b983SEtienne Carriere 	}
43169b8b983SEtienne Carriere }
43269b8b983SEtienne Carriere 
433*461e8793SGatien Chevallier static void stm32_tamp_set_privilege(uint32_t mode)
43469b8b983SEtienne Carriere {
435*461e8793SGatien Chevallier 	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
43669b8b983SEtienne Carriere 
437*461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.compat &&
438*461e8793SGatien Chevallier 	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_PRIVCFGR))
43969b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK,
44069b8b983SEtienne Carriere 				mode & _TAMP_PRIVCFGR_MASK);
44169b8b983SEtienne Carriere }
44269b8b983SEtienne Carriere 
443*461e8793SGatien Chevallier static void parse_bkpregs_dt_conf(const void *fdt, int node,
444*461e8793SGatien Chevallier 				  struct stm32_tamp_platdata *pdata)
445*461e8793SGatien Chevallier {
446*461e8793SGatien Chevallier 	const fdt32_t *cuint = NULL;
447*461e8793SGatien Chevallier 	unsigned int bkpregs_count = 0;
448*461e8793SGatien Chevallier 	int lenp = 0;
449*461e8793SGatien Chevallier 
450*461e8793SGatien Chevallier 	cuint = fdt_getprop(fdt, node, "st,backup-zones", &lenp);
451*461e8793SGatien Chevallier 	if (!cuint)
452*461e8793SGatien Chevallier 		panic("Missing backup registers configuration");
453*461e8793SGatien Chevallier 
454*461e8793SGatien Chevallier 	/*
455*461e8793SGatien Chevallier 	 * When TAMP does not support RIF, the backup registers can
456*461e8793SGatien Chevallier 	 * be splited in 3 zones. These zones have specific read/write
457*461e8793SGatien Chevallier 	 * access permissions based on the secure status of the accesser.
458*461e8793SGatien Chevallier 	 * When RIF is supported, these zones can additionally be splited
459*461e8793SGatien Chevallier 	 * in subzones that have CID filtering. Zones/Subzones can be empty and
460*461e8793SGatien Chevallier 	 * are contiguous.
461*461e8793SGatien Chevallier 	 */
462*461e8793SGatien Chevallier 	if (!(stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT)) {
463*461e8793SGatien Chevallier 		/* 3 zones, 2 offsets to apply */
464*461e8793SGatien Chevallier 		if (lenp != sizeof(uint32_t) * TAMP_NB_BKPR_ZONES)
465*461e8793SGatien Chevallier 			panic("Incorrect bkpregs configuration");
466*461e8793SGatien Chevallier 
467*461e8793SGatien Chevallier 		pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]);
468*461e8793SGatien Chevallier 		bkpregs_count = fdt32_to_cpu(cuint[0]);
469*461e8793SGatien Chevallier 
470*461e8793SGatien Chevallier 		pdata->bkpregs_conf.zone2_end = bkpregs_count +
471*461e8793SGatien Chevallier 						fdt32_to_cpu(cuint[1]);
472*461e8793SGatien Chevallier 	} else {
473*461e8793SGatien Chevallier 		/*
474*461e8793SGatien Chevallier 		 * Zone 3
475*461e8793SGatien Chevallier 		 * ----------------------|
476*461e8793SGatien Chevallier 		 * Protection Zone 3-RIF2|Read non-
477*461e8793SGatien Chevallier 		 * ----------------------|secure
478*461e8793SGatien Chevallier 		 * Protection Zone 3-RIF0|Write non-
479*461e8793SGatien Chevallier 		 * ----------------------|secure
480*461e8793SGatien Chevallier 		 * Protection Zone 3-RIF1|
481*461e8793SGatien Chevallier 		 * ----------------------|
482*461e8793SGatien Chevallier 		 *
483*461e8793SGatien Chevallier 		 * Zone 2
484*461e8793SGatien Chevallier 		 * ----------------------|
485*461e8793SGatien Chevallier 		 * Protection Zone 2-RIF2|Read non-
486*461e8793SGatien Chevallier 		 * ----------------------|secure
487*461e8793SGatien Chevallier 		 * Protection Zone 2-RIF1|Write secure
488*461e8793SGatien Chevallier 		 * ----------------------|
489*461e8793SGatien Chevallier 		 *
490*461e8793SGatien Chevallier 		 * Zone 1
491*461e8793SGatien Chevallier 		 * ----------------------|
492*461e8793SGatien Chevallier 		 * Protection Zone 1-RIF2|Read secure
493*461e8793SGatien Chevallier 		 * ----------------------|Write secure
494*461e8793SGatien Chevallier 		 * Protection Zone 1-RIF1|
495*461e8793SGatien Chevallier 		 * ----------------------|
496*461e8793SGatien Chevallier 		 *
497*461e8793SGatien Chevallier 		 * (BHK => First 8 registers)
498*461e8793SGatien Chevallier 		 */
499*461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets = calloc(TAMP_RIF_OFFSET_CNT,
500*461e8793SGatien Chevallier 							 sizeof(uint32_t));
501*461e8793SGatien Chevallier 		if (!pdata->bkpregs_conf.rif_offsets)
502*461e8793SGatien Chevallier 			panic();
503*461e8793SGatien Chevallier 
504*461e8793SGatien Chevallier 		/*
505*461e8793SGatien Chevallier 		 * 3 zones with 7 subzones in total(6 offsets):
506*461e8793SGatien Chevallier 		 * - 2 zone offsets
507*461e8793SGatien Chevallier 		 * - 4 subzones offsets
508*461e8793SGatien Chevallier 		 */
509*461e8793SGatien Chevallier 		if (lenp != sizeof(uint32_t) *
510*461e8793SGatien Chevallier 		    (TAMP_RIF_OFFSET_CNT + TAMP_NB_BKPR_ZONES))
511*461e8793SGatien Chevallier 			panic("Incorrect bkpregs configuration");
512*461e8793SGatien Chevallier 
513*461e8793SGatien Chevallier 		/* Backup registers zone 1 */
514*461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets[0] = fdt32_to_cpu(cuint[0]);
515*461e8793SGatien Chevallier 		pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]) +
516*461e8793SGatien Chevallier 						fdt32_to_cpu(cuint[1]);
517*461e8793SGatien Chevallier 
518*461e8793SGatien Chevallier 		bkpregs_count = pdata->bkpregs_conf.zone1_end;
519*461e8793SGatien Chevallier 
520*461e8793SGatien Chevallier 		/* Backup registers zone 2 */
521*461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets[1] = bkpregs_count +
522*461e8793SGatien Chevallier 						     fdt32_to_cpu(cuint[2]);
523*461e8793SGatien Chevallier 		pdata->bkpregs_conf.zone2_end = bkpregs_count +
524*461e8793SGatien Chevallier 						fdt32_to_cpu(cuint[2]) +
525*461e8793SGatien Chevallier 						fdt32_to_cpu(cuint[3]);
526*461e8793SGatien Chevallier 
527*461e8793SGatien Chevallier 		bkpregs_count = pdata->bkpregs_conf.zone2_end;
528*461e8793SGatien Chevallier 
529*461e8793SGatien Chevallier 		/* Backup registers zone 3 */
530*461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets[2] = bkpregs_count +
531*461e8793SGatien Chevallier 						     fdt32_to_cpu(cuint[4]);
532*461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets[3] = bkpregs_count +
533*461e8793SGatien Chevallier 						      fdt32_to_cpu(cuint[4]) +
534*461e8793SGatien Chevallier 						      fdt32_to_cpu(cuint[5]);
535*461e8793SGatien Chevallier 	}
536*461e8793SGatien Chevallier }
537*461e8793SGatien Chevallier 
538*461e8793SGatien Chevallier static TEE_Result stm32_tamp_parse_fdt(const void *fdt, int node,
53969b8b983SEtienne Carriere 				       const void *compat)
54069b8b983SEtienne Carriere {
541*461e8793SGatien Chevallier 	struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata;
542*461e8793SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
54369b8b983SEtienne Carriere 	struct dt_node_info dt_tamp = { };
54469b8b983SEtienne Carriere 
545f354a5d8SGatien Chevallier 	fdt_fill_device_info(fdt, &dt_tamp, node);
54669b8b983SEtienne Carriere 
54769b8b983SEtienne Carriere 	if (dt_tamp.reg == DT_INFO_INVALID_REG ||
54869b8b983SEtienne Carriere 	    dt_tamp.reg_size == DT_INFO_INVALID_REG_SIZE)
54969b8b983SEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
55069b8b983SEtienne Carriere 
551*461e8793SGatien Chevallier 	pdata->compat = (struct stm32_tamp_compat *)compat;
552*461e8793SGatien Chevallier 	pdata->it = dt_tamp.interrupt;
553*461e8793SGatien Chevallier 	pdata->base.pa = dt_tamp.reg;
554*461e8793SGatien Chevallier 	io_pa_or_va_secure(&pdata->base, dt_tamp.reg_size);
55569b8b983SEtienne Carriere 
556*461e8793SGatien Chevallier 	res = clk_dt_get_by_index(fdt, node, 0, &pdata->clock);
557*461e8793SGatien Chevallier 	if (res)
558*461e8793SGatien Chevallier 		return res;
559*461e8793SGatien Chevallier 
560*461e8793SGatien Chevallier 	parse_bkpregs_dt_conf(fdt, node, pdata);
561*461e8793SGatien Chevallier 
562*461e8793SGatien Chevallier 	if (pdata->compat->tags & TAMP_HAS_RIF_SUPPORT) {
563*461e8793SGatien Chevallier 		const fdt32_t *cuint = NULL;
564*461e8793SGatien Chevallier 		unsigned int i = 0;
565*461e8793SGatien Chevallier 		int lenp = 0;
566*461e8793SGatien Chevallier 
567*461e8793SGatien Chevallier 		res = stm32_rifsc_check_tdcid(&pdata->is_tdcid);
568*461e8793SGatien Chevallier 		if (res)
569*461e8793SGatien Chevallier 			return res;
570*461e8793SGatien Chevallier 
571*461e8793SGatien Chevallier 		cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
572*461e8793SGatien Chevallier 		if (!cuint) {
573*461e8793SGatien Chevallier 			DMSG("No RIF configuration available");
574*461e8793SGatien Chevallier 			return TEE_SUCCESS;
575*461e8793SGatien Chevallier 		}
576*461e8793SGatien Chevallier 
577*461e8793SGatien Chevallier 		pdata->conf_data = calloc(1, sizeof(*pdata->conf_data));
578*461e8793SGatien Chevallier 		if (!pdata->conf_data)
579*461e8793SGatien Chevallier 			panic();
580*461e8793SGatien Chevallier 
581*461e8793SGatien Chevallier 		pdata->nb_rif_resources = (unsigned int)(lenp /
582*461e8793SGatien Chevallier 							 sizeof(uint32_t));
583*461e8793SGatien Chevallier 		assert(pdata->nb_rif_resources <= TAMP_RIF_RESOURCES);
584*461e8793SGatien Chevallier 
585*461e8793SGatien Chevallier 		pdata->conf_data->cid_confs = calloc(TAMP_RIF_RESOURCES,
586*461e8793SGatien Chevallier 						     sizeof(uint32_t));
587*461e8793SGatien Chevallier 		pdata->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
588*461e8793SGatien Chevallier 		pdata->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
589*461e8793SGatien Chevallier 		pdata->conf_data->access_mask = calloc(1, sizeof(uint32_t));
590*461e8793SGatien Chevallier 		if (!pdata->conf_data->cid_confs ||
591*461e8793SGatien Chevallier 		    !pdata->conf_data->sec_conf ||
592*461e8793SGatien Chevallier 		    !pdata->conf_data->priv_conf ||
593*461e8793SGatien Chevallier 		    !pdata->conf_data->access_mask)
594*461e8793SGatien Chevallier 			panic("Not enough memory capacity for TAMP RIF config");
595*461e8793SGatien Chevallier 
596*461e8793SGatien Chevallier 		for (i = 0; i < pdata->nb_rif_resources; i++)
597*461e8793SGatien Chevallier 			stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]),
598*461e8793SGatien Chevallier 					    pdata->conf_data,
599*461e8793SGatien Chevallier 					    TAMP_RIF_RESOURCES);
600*461e8793SGatien Chevallier 	}
601*461e8793SGatien Chevallier 
602*461e8793SGatien Chevallier 	return TEE_SUCCESS;
60369b8b983SEtienne Carriere }
60469b8b983SEtienne Carriere 
60569b8b983SEtienne Carriere static TEE_Result stm32_tamp_probe(const void *fdt, int node,
60669b8b983SEtienne Carriere 				   const void *compat_data)
60769b8b983SEtienne Carriere {
60869b8b983SEtienne Carriere 	uint32_t __maybe_unused revision = 0;
60969b8b983SEtienne Carriere 	TEE_Result res = TEE_SUCCESS;
61069b8b983SEtienne Carriere 	vaddr_t base = 0;
61169b8b983SEtienne Carriere 
612*461e8793SGatien Chevallier 	stm32_tamp_dev = calloc(1, sizeof(*stm32_tamp_dev));
613*461e8793SGatien Chevallier 	if (!stm32_tamp_dev)
61469b8b983SEtienne Carriere 		return TEE_ERROR_OUT_OF_MEMORY;
61569b8b983SEtienne Carriere 
616*461e8793SGatien Chevallier 	res = stm32_tamp_parse_fdt(fdt, node, compat_data);
61769b8b983SEtienne Carriere 	if (res)
61869b8b983SEtienne Carriere 		goto err;
61969b8b983SEtienne Carriere 
620*461e8793SGatien Chevallier 	if (clk_enable(stm32_tamp_dev->pdata.clock))
621*461e8793SGatien Chevallier 		panic();
62269b8b983SEtienne Carriere 
623*461e8793SGatien Chevallier 	base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
62469b8b983SEtienne Carriere 
625*461e8793SGatien Chevallier 	stm32_tamp_dev->hwconf1 = io_read32(base + _TAMP_HWCFGR1);
626*461e8793SGatien Chevallier 	stm32_tamp_dev->hwconf2 = io_read32(base + _TAMP_HWCFGR2);
62769b8b983SEtienne Carriere 
62869b8b983SEtienne Carriere 	revision = io_read32(base + _TAMP_VERR);
62969b8b983SEtienne Carriere 	FMSG("STM32 TAMPER V%"PRIx32".%"PRIu32,
63069b8b983SEtienne Carriere 	     (revision & _TAMP_VERR_MAJREV) >> 4, revision & _TAMP_VERR_MINREV);
63169b8b983SEtienne Carriere 
632*461e8793SGatien Chevallier 	if (!(stm32_tamp_dev->hwconf2 & _TAMP_HWCFGR2_TZ)) {
63369b8b983SEtienne Carriere 		EMSG("TAMP doesn't support TrustZone");
63469b8b983SEtienne Carriere 		res = TEE_ERROR_NOT_SUPPORTED;
63569b8b983SEtienne Carriere 		goto err_clk;
63669b8b983SEtienne Carriere 	}
63769b8b983SEtienne Carriere 
638*461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) {
639*461e8793SGatien Chevallier 		apply_rif_config();
640*461e8793SGatien Chevallier 
641*461e8793SGatien Chevallier 		if (stm32_tamp_dev->pdata.is_tdcid) {
642*461e8793SGatien Chevallier 			res = stm32_tamp_apply_bkpr_rif_conf();
643*461e8793SGatien Chevallier 			if (res)
644*461e8793SGatien Chevallier 				goto err_clk;
645*461e8793SGatien Chevallier 		}
646*461e8793SGatien Chevallier 	} else {
64769b8b983SEtienne Carriere 		/*
64869b8b983SEtienne Carriere 		 * Enforce secure only access to protected TAMP registers.
64969b8b983SEtienne Carriere 		 * Allow non-secure access to monotonic counter.
65069b8b983SEtienne Carriere 		 */
651*461e8793SGatien Chevallier 		stm32_tamp_set_secure(_TAMP_SECCFGR_TAMPSEC);
65269b8b983SEtienne Carriere 
65369b8b983SEtienne Carriere 		/*
65469b8b983SEtienne Carriere 		 * Enforce privilege only access to TAMP registers, backup
65569b8b983SEtienne Carriere 		 * registers and monotonic counter.
65669b8b983SEtienne Carriere 		 */
657*461e8793SGatien Chevallier 		stm32_tamp_set_privilege(_TAMP_PRIVCFG_TAMPPRIV |
65869b8b983SEtienne Carriere 					 _TAMP_PRIVCFG_BKPRWPRIV |
65969b8b983SEtienne Carriere 					 _TAMP_PRIVCFG_BKPWPRIV);
660*461e8793SGatien Chevallier 	}
66169b8b983SEtienne Carriere 
66269b8b983SEtienne Carriere 	return TEE_SUCCESS;
66369b8b983SEtienne Carriere 
66469b8b983SEtienne Carriere err_clk:
665*461e8793SGatien Chevallier 	clk_disable(stm32_tamp_dev->pdata.clock);
66669b8b983SEtienne Carriere err:
667*461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.conf_data) {
668*461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data->cid_confs);
669*461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data->sec_conf);
670*461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data->priv_conf);
671*461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data->access_mask);
672*461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data);
673*461e8793SGatien Chevallier 	}
674*461e8793SGatien Chevallier 	free(stm32_tamp_dev->pdata.bkpregs_conf.rif_offsets);
675*461e8793SGatien Chevallier 	free(stm32_tamp_dev);
676*461e8793SGatien Chevallier 
67769b8b983SEtienne Carriere 	return res;
67869b8b983SEtienne Carriere }
67969b8b983SEtienne Carriere 
68069b8b983SEtienne Carriere static const struct stm32_tamp_compat mp13_compat = {
68169b8b983SEtienne Carriere 	.nb_monotonic_counter = 2,
682*461e8793SGatien Chevallier 	.tags = TAMP_HAS_REGISTER_SECCFGR | TAMP_HAS_REGISTER_PRIVCFGR,
68369b8b983SEtienne Carriere };
68469b8b983SEtienne Carriere 
68569b8b983SEtienne Carriere static const struct stm32_tamp_compat mp15_compat = {
68669b8b983SEtienne Carriere 	.nb_monotonic_counter = 1,
68769b8b983SEtienne Carriere 	.tags = 0,
68869b8b983SEtienne Carriere };
68969b8b983SEtienne Carriere 
690*461e8793SGatien Chevallier static const struct stm32_tamp_compat mp25_compat = {
691*461e8793SGatien Chevallier 	.nb_monotonic_counter = 2,
692*461e8793SGatien Chevallier 	.tags = TAMP_HAS_REGISTER_SECCFGR |
693*461e8793SGatien Chevallier 		TAMP_HAS_REGISTER_PRIVCFGR |
694*461e8793SGatien Chevallier 		TAMP_HAS_RIF_SUPPORT,
695*461e8793SGatien Chevallier };
696*461e8793SGatien Chevallier 
69769b8b983SEtienne Carriere static const struct dt_device_match stm32_tamp_match_table[] = {
698*461e8793SGatien Chevallier 	{ .compatible = "st,stm32mp25-tamp", .compat_data = &mp25_compat },
69969b8b983SEtienne Carriere 	{ .compatible = "st,stm32mp13-tamp", .compat_data = &mp13_compat },
70069b8b983SEtienne Carriere 	{ .compatible = "st,stm32-tamp", .compat_data = &mp15_compat },
70169b8b983SEtienne Carriere 	{ }
70269b8b983SEtienne Carriere };
70369b8b983SEtienne Carriere 
70469b8b983SEtienne Carriere DEFINE_DT_DRIVER(stm32_tamp_dt_driver) = {
70569b8b983SEtienne Carriere 	.name = "stm32-tamp",
70669b8b983SEtienne Carriere 	.match_table = stm32_tamp_match_table,
70769b8b983SEtienne Carriere 	.probe = stm32_tamp_probe,
70869b8b983SEtienne Carriere };
709