xref: /optee_os/core/drivers/stm32_tamp.c (revision 92ab653563a4e91acc4790d73534df3b835cd05d)
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>
8461e8793SGatien Chevallier #include <drivers/stm32_rif.h>
969b8b983SEtienne Carriere #include <io.h>
1069b8b983SEtienne Carriere #include <kernel/dt.h>
119e3c57c8SEtienne Carriere #include <kernel/dt_driver.h>
1269b8b983SEtienne Carriere #include <kernel/interrupt.h>
1369b8b983SEtienne Carriere #include <libfdt.h>
1469b8b983SEtienne Carriere #include <mm/core_memprot.h>
1569b8b983SEtienne Carriere #include <stdbool.h>
1669b8b983SEtienne Carriere 
1769b8b983SEtienne Carriere /* STM32 Registers */
1869b8b983SEtienne Carriere #define _TAMP_CR1			0x00U
1969b8b983SEtienne Carriere #define _TAMP_CR2			0x04U
2069b8b983SEtienne Carriere #define _TAMP_CR3			0x08U
2169b8b983SEtienne Carriere #define _TAMP_FLTCR			0x0CU
2269b8b983SEtienne Carriere #define _TAMP_ATCR1			0x10U
2369b8b983SEtienne Carriere #define _TAMP_ATSEEDR			0x14U
2469b8b983SEtienne Carriere #define _TAMP_ATOR			0x18U
2569b8b983SEtienne Carriere #define _TAMP_ATCR2			0x1CU
2669b8b983SEtienne Carriere #define _TAMP_SECCFGR			0x20U
2769b8b983SEtienne Carriere #define _TAMP_SMCR			0x20U
2869b8b983SEtienne Carriere #define _TAMP_PRIVCFGR			0x24U
2969b8b983SEtienne Carriere #define _TAMP_IER			0x2CU
3069b8b983SEtienne Carriere #define _TAMP_SR			0x30U
3169b8b983SEtienne Carriere #define _TAMP_MISR			0x34U
3269b8b983SEtienne Carriere #define _TAMP_SMISR			0x38U
3369b8b983SEtienne Carriere #define _TAMP_SCR			0x3CU
3469b8b983SEtienne Carriere #define _TAMP_COUNTR			0x40U
3569b8b983SEtienne Carriere #define _TAMP_COUNT2R			0x44U
3669b8b983SEtienne Carriere #define _TAMP_OR			0x50U
3769b8b983SEtienne Carriere #define _TAMP_ERCFGR			0X54U
38461e8793SGatien Chevallier #define _TAMP_BKPRIFR(x)		(0x70U + 0x4U * ((x) - 1U))
39461e8793SGatien Chevallier #define _TAMP_CIDCFGR(x)		(0x80U + 0x4U * (x))
40461e8793SGatien Chevallier #define _TAMP_BKPxR(x)			(0x100U + 0x4U * ((x) - 1U))
4169b8b983SEtienne Carriere #define _TAMP_HWCFGR2			0x3ECU
4269b8b983SEtienne Carriere #define _TAMP_HWCFGR1			0x3F0U
4369b8b983SEtienne Carriere #define _TAMP_VERR			0x3F4U
4469b8b983SEtienne Carriere #define _TAMP_IPIDR			0x3F8U
4569b8b983SEtienne Carriere #define _TAMP_SIDR			0x3FCU
4669b8b983SEtienne Carriere 
4769b8b983SEtienne Carriere /* _TAMP_SECCFGR bit fields */
4869b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_MASK	GENMASK_32(7, 0)
4969b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPRWSEC_SHIFT	0U
5069b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT2SEC		BIT(14)
51461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT2SEC_SHIFT	14U
5269b8b983SEtienne Carriere #define _TAMP_SECCFGR_CNT1SEC		BIT(15)
53461e8793SGatien Chevallier #define _TAMP_SECCFGR_CNT1SEC_SHIFT	15U
5469b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_MASK	GENMASK_32(23, 16)
5569b8b983SEtienne Carriere #define _TAMP_SECCFGR_BKPWSEC_SHIFT	16U
5669b8b983SEtienne Carriere #define _TAMP_SECCFGR_BHKLOCK		BIT(30)
5769b8b983SEtienne Carriere #define _TAMP_SECCFGR_TAMPSEC		BIT(31)
58461e8793SGatien Chevallier #define _TAMP_SECCFGR_TAMPSEC_SHIFT	31U
5969b8b983SEtienne Carriere #define _TAMP_SECCFGR_BUT_BKP_MASK	(GENMASK_32(31, 30) | \
6069b8b983SEtienne Carriere 					 GENMASK_32(15, 14))
61461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_TAMP_SEC	BIT(0)
62461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_1	BIT(1)
63461e8793SGatien Chevallier #define _TAMP_SECCFGR_RIF_COUNT_2	BIT(2)
6469b8b983SEtienne Carriere 
6569b8b983SEtienne Carriere /* _TAMP_SMCR bit fields */
6669b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_MASK	GENMASK_32(7, 0)
6769b8b983SEtienne Carriere #define _TAMP_SMCR_BKPRWDPROT_SHIFT	0U
6869b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_MASK	GENMASK_32(23, 16)
6969b8b983SEtienne Carriere #define _TAMP_SMCR_BKPWDPROT_SHIFT	16U
7069b8b983SEtienne Carriere #define _TAMP_SMCR_DPROT		BIT(31)
7169b8b983SEtienne Carriere /*
7269b8b983SEtienne Carriere  * _TAMP_PRIVCFGR bit fields
7369b8b983SEtienne Carriere  */
7469b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV		BIT(14)
7569b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV		BIT(15)
7669b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV		BIT(29)
7769b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV		BIT(30)
7869b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV		BIT(31)
7969b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK		(GENMASK_32(31, 29) | \
8069b8b983SEtienne Carriere 					 GENMASK_32(15, 14))
81461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_TAMP_PRIV	BIT(0)
82461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R1		BIT(1)
83461e8793SGatien Chevallier #define _TAMP_PRIVCFGR_RIF_R2		BIT(2)
8469b8b983SEtienne Carriere 
8569b8b983SEtienne Carriere /*
8669b8b983SEtienne Carriere  * _TAMP_PRIVCFGR bit fields
8769b8b983SEtienne Carriere  */
8869b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT2PRIV		BIT(14)
8969b8b983SEtienne Carriere #define _TAMP_PRIVCFG_CNT1PRIV		BIT(15)
9069b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPRWPRIV		BIT(29)
9169b8b983SEtienne Carriere #define _TAMP_PRIVCFG_BKPWPRIV		BIT(30)
9269b8b983SEtienne Carriere #define _TAMP_PRIVCFG_TAMPPRIV		BIT(31)
9369b8b983SEtienne Carriere #define _TAMP_PRIVCFGR_MASK		(GENMASK_32(31, 29) | \
9469b8b983SEtienne Carriere 					 GENMASK_32(15, 14))
9569b8b983SEtienne Carriere 
9669b8b983SEtienne Carriere /* _TAMP_HWCFGR2 bit fields */
9769b8b983SEtienne Carriere #define _TAMP_HWCFGR2_TZ		GENMASK_32(11, 8)
9869b8b983SEtienne Carriere #define _TAMP_HWCFGR2_OR		GENMASK_32(7, 0)
9969b8b983SEtienne Carriere 
10069b8b983SEtienne Carriere /* _TAMP_HWCFGR1 bit fields */
10169b8b983SEtienne Carriere #define _TAMP_HWCFGR1_BKPREG		GENMASK_32(7, 0)
10269b8b983SEtienne Carriere #define _TAMP_HWCFGR1_TAMPER		GENMASK_32(11, 8)
10369b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ACTIVE		GENMASK_32(15, 12)
10469b8b983SEtienne Carriere #define _TAMP_HWCFGR1_INTERN		GENMASK_32(31, 16)
10569b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP_MAX_ID	16U
10669b8b983SEtienne Carriere #define _TAMP_HWCFGR1_ITAMP(id)		BIT((id) - INT_TAMP1 + 16U)
10769b8b983SEtienne Carriere 
10869b8b983SEtienne Carriere /* _TAMP_VERR bit fields */
10969b8b983SEtienne Carriere #define _TAMP_VERR_MINREV		GENMASK_32(3, 0)
11069b8b983SEtienne Carriere #define _TAMP_VERR_MAJREV		GENMASK_32(7, 4)
11169b8b983SEtienne Carriere 
11269b8b983SEtienne Carriere /*
113461e8793SGatien Chevallier  * CIDCFGR register bitfields
11469b8b983SEtienne Carriere  */
115461e8793SGatien Chevallier #define _TAMP_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
116461e8793SGatien Chevallier #define _TAMP_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	 \
117461e8793SGatien Chevallier 					 _CIDCFGR_SEMEN |	 \
118461e8793SGatien Chevallier 					 _TAMP_CIDCFGR_SCID_MASK)
119461e8793SGatien Chevallier 
120461e8793SGatien Chevallier /* _TAMP_BKPRIFR */
121461e8793SGatien Chevallier #define _TAMP_BKPRIFR_1_MASK		GENMASK_32(7, 0)
122461e8793SGatien Chevallier #define _TAMP_BKPRIFR_2_MASK		GENMASK_32(7, 0)
123461e8793SGatien Chevallier #define _TAMP_BKPRIFR_3_MASK		(GENMASK_32(23, 16) | GENMASK_32(7, 0))
124461e8793SGatien Chevallier #define _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT	16U
125461e8793SGatien Chevallier 
126461e8793SGatien Chevallier /*
127461e8793SGatien Chevallier  * RIF miscellaneous
128461e8793SGatien Chevallier  */
129461e8793SGatien Chevallier #define TAMP_NB_BKPR_ZONES		3U
130461e8793SGatien Chevallier #define TAMP_RIF_RESOURCES		3U
131461e8793SGatien Chevallier #define TAMP_RIF_OFFSET_CNT		4U
13269b8b983SEtienne Carriere 
13369b8b983SEtienne Carriere /*
13469b8b983SEtienne Carriere  * Compatibility capabilities
135461e8793SGatien Chevallier  * TAMP_HAS_REGISTER_SECCFGR - Supports SECCFGR, otherwise supports SMCR
136461e8793SGatien Chevallier  * register
13769b8b983SEtienne Carriere  * TAMP_HAS_REGISTER_PRIVCFG - Supports PRIVCFGR configuration register
138461e8793SGatien Chevallier  * TAMP_HAS_RIF_SUPPORT - Supports RIF
13969b8b983SEtienne Carriere  */
140461e8793SGatien Chevallier #define TAMP_HAS_REGISTER_SECCFGR	BIT(0)
14169b8b983SEtienne Carriere #define TAMP_HAS_REGISTER_PRIVCFGR	BIT(1)
142461e8793SGatien Chevallier #define TAMP_HAS_RIF_SUPPORT		BIT(31)
14369b8b983SEtienne Carriere 
144461e8793SGatien Chevallier /**
145461e8793SGatien Chevallier  * struct stm32_tamp_compat - TAMP compatible data
146461e8793SGatien Chevallier  * @nb_monotonic_counter: Number of monotic counter supported
147461e8793SGatien Chevallier  * @tags: Bit flags TAMP_HAS_* for compatibility management
14869b8b983SEtienne Carriere  */
14969b8b983SEtienne Carriere struct stm32_tamp_compat {
15069b8b983SEtienne Carriere 	int nb_monotonic_counter;
15169b8b983SEtienne Carriere 	uint32_t tags;
15269b8b983SEtienne Carriere };
15369b8b983SEtienne Carriere 
154461e8793SGatien Chevallier /*
155*92ab6535SGatien Chevallier  * struct stm32_bkpregs_conf - Backup registers zone bounds
156461e8793SGatien Chevallier  * @zone1_end - Number of backup registers in zone 1
157461e8793SGatien Chevallier  * @zone2_end - Number of backup registers in zone 2 + zone 1
158461e8793SGatien Chevallier  * @rif_offsets - RIF offsets used for CID compartments
159461e8793SGatien Chevallier  *
160461e8793SGatien Chevallier  * TAMP backup registers access permissions
161461e8793SGatien Chevallier  *
162461e8793SGatien Chevallier  * Zone 1: read/write in secure state, no access in non-secure state
163461e8793SGatien Chevallier  * Zone 2: read/write in secure state, read-only in non-secure state
164461e8793SGatien Chevallier  * Zone 3: read/write in secure state, read/write in non-secure state
165461e8793SGatien Chevallier  *
166461e8793SGatien Chevallier  * Protection zone 1
167461e8793SGatien Chevallier  * If zone1_end == 0 no backup register are in zone 1.
168461e8793SGatien Chevallier  * Otherwise backup registers from TAMP_BKP0R to TAMP_BKP<x>R are in zone 1,
169461e8793SGatien Chevallier  * with <x> = (@zone1_end - 1).
170461e8793SGatien Chevallier  *
171461e8793SGatien Chevallier  * Protection zone 2
172461e8793SGatien Chevallier  * If zone2_end == 0 no backup register are in zone 2 and zone 1.
173461e8793SGatien Chevallier  * Otherwise backup registers from TAMP_BKP<y>R to TAMP_BKP<z>R are in zone 2,
174461e8793SGatien Chevallier  * with <y> = @zone1_end and <z> = (@zone2_end - 1).
175461e8793SGatien Chevallier  *
176461e8793SGatien Chevallier  * Protection zone 3
177461e8793SGatien Chevallier  * Backup registers from TAMP_BKP<t>R to last backup register are in zone 3,
178461e8793SGatien Chevallier  * with <t> = (@zone2_end - 1).
179461e8793SGatien Chevallier  *
180461e8793SGatien Chevallier  * When RIF is supported, each zone can be subdivided to restrain accesses to
181461e8793SGatien Chevallier  * some CIDs.
182461e8793SGatien Chevallier  */
183*92ab6535SGatien Chevallier struct stm32_bkpregs_conf {
184461e8793SGatien Chevallier 	uint32_t zone1_end;
185461e8793SGatien Chevallier 	uint32_t zone2_end;
186461e8793SGatien Chevallier 	uint32_t *rif_offsets;
187461e8793SGatien Chevallier };
188461e8793SGatien Chevallier 
189461e8793SGatien Chevallier /**
190461e8793SGatien Chevallier  * struct stm32_tamp_platdata - TAMP platform data
191461e8793SGatien Chevallier  * @base: IOMEM base address
192461e8793SGatien Chevallier  * @bkpregs_conf: TAMP backup register configuration reference
193461e8793SGatien Chevallier  * @compat: Reference to compat data passed at driver initialization
194461e8793SGatien Chevallier  * @conf_data: RIF configuration data
195461e8793SGatien Chevallier  * @clock: TAMP clock
196461e8793SGatien Chevallier  * @nb_rif_resources: Number of RIF resources
197461e8793SGatien Chevallier  * @it: TAMP interrupt number
198461e8793SGatien Chevallier  * @is_tdcid: True if current processor is TDCID
199461e8793SGatien Chevallier  */
200461e8793SGatien Chevallier struct stm32_tamp_platdata {
201461e8793SGatien Chevallier 	struct io_pa_va base;
202*92ab6535SGatien Chevallier 	struct stm32_bkpregs_conf bkpregs_conf;
203461e8793SGatien Chevallier 	struct stm32_tamp_compat *compat;
204461e8793SGatien Chevallier 	struct rif_conf_data *conf_data;
205461e8793SGatien Chevallier 	struct clk *clock;
206461e8793SGatien Chevallier 	unsigned int nb_rif_resources;
207461e8793SGatien Chevallier 	int it;
208461e8793SGatien Chevallier 	bool is_tdcid;
209461e8793SGatien Chevallier };
210461e8793SGatien Chevallier 
211461e8793SGatien Chevallier /**
212461e8793SGatien Chevallier  * struct stm32_tamp_instance - TAMP instance data
213461e8793SGatien Chevallier  * @pdata: TAMP platform data
214461e8793SGatien Chevallier  * @hwconf1: Copy of TAMP HWCONF1 register content
215461e8793SGatien Chevallier  * @hwconf2: Copy of TAMP HWCONF2 register content
216461e8793SGatien Chevallier  */
217461e8793SGatien Chevallier struct stm32_tamp_instance {
218461e8793SGatien Chevallier 	struct stm32_tamp_platdata pdata;
219461e8793SGatien Chevallier 	uint32_t hwconf1;
220461e8793SGatien Chevallier 	uint32_t hwconf2;
221461e8793SGatien Chevallier };
222461e8793SGatien Chevallier 
22369b8b983SEtienne Carriere /* Expects at most a single instance */
224461e8793SGatien Chevallier static struct stm32_tamp_instance *stm32_tamp_dev;
225461e8793SGatien Chevallier 
226461e8793SGatien Chevallier static void apply_rif_config(void)
227461e8793SGatien Chevallier {
228461e8793SGatien Chevallier 	struct rif_conf_data *rif_conf = stm32_tamp_dev->pdata.conf_data;
229461e8793SGatien Chevallier 	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
230461e8793SGatien Chevallier 	uint32_t access_mask_priv_reg = 0;
231461e8793SGatien Chevallier 	uint32_t access_mask_sec_reg = 0;
232461e8793SGatien Chevallier 	uint32_t privcfgr = 0;
233461e8793SGatien Chevallier 	uint32_t seccfgr = 0;
234461e8793SGatien Chevallier 	unsigned int i = 0;
235461e8793SGatien Chevallier 
236461e8793SGatien Chevallier 	if (!stm32_tamp_dev->pdata.conf_data)
237461e8793SGatien Chevallier 		return;
238461e8793SGatien Chevallier 
239461e8793SGatien Chevallier 	/* Build access masks for _TAMP_PRIVCFGR and _TAMP_SECCFGR */
240461e8793SGatien Chevallier 	for (i = 0; i < TAMP_RIF_RESOURCES; i++) {
241461e8793SGatien Chevallier 		if (BIT(i) & rif_conf->access_mask[0]) {
242461e8793SGatien Chevallier 			switch (i) {
243461e8793SGatien Chevallier 			case 0:
244461e8793SGatien Chevallier 				access_mask_sec_reg |= _TAMP_SECCFGR_TAMPSEC;
245461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_TAMPPRIV;
246461e8793SGatien Chevallier 				break;
247461e8793SGatien Chevallier 			case 1:
248461e8793SGatien Chevallier 				access_mask_sec_reg |= _TAMP_SECCFGR_CNT1SEC;
249461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_CNT1PRIV;
250461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_BKPRWPRIV;
251461e8793SGatien Chevallier 				break;
252461e8793SGatien Chevallier 			case 2:
253461e8793SGatien Chevallier 				access_mask_sec_reg |= _TAMP_SECCFGR_CNT2SEC;
254461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_CNT2PRIV;
255461e8793SGatien Chevallier 				access_mask_priv_reg |= _TAMP_PRIVCFG_BKPWPRIV;
256461e8793SGatien Chevallier 				break;
257461e8793SGatien Chevallier 			default:
258461e8793SGatien Chevallier 				panic();
259461e8793SGatien Chevallier 			}
260461e8793SGatien Chevallier 		}
261461e8793SGatien Chevallier 	}
262461e8793SGatien Chevallier 
263461e8793SGatien Chevallier 	/*
264461e8793SGatien Chevallier 	 * When TDCID, OP-TEE should be the one to set the CID filtering
265461e8793SGatien Chevallier 	 * configuration. Clearing previous configuration prevents
266461e8793SGatien Chevallier 	 * undesired events during the only legitimate configuration.
267461e8793SGatien Chevallier 	 */
268461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.is_tdcid) {
269461e8793SGatien Chevallier 		for (i = 0; i < TAMP_RIF_RESOURCES; i++)
270461e8793SGatien Chevallier 			if (BIT(i) & rif_conf->access_mask[0])
271461e8793SGatien Chevallier 				io_clrbits32(base + _TAMP_CIDCFGR(i),
272461e8793SGatien Chevallier 					     _TAMP_CIDCFGR_CONF_MASK);
273461e8793SGatien Chevallier 	}
274461e8793SGatien Chevallier 
275461e8793SGatien Chevallier 	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_TAMP_SEC)
276461e8793SGatien Chevallier 		seccfgr |= _TAMP_SECCFGR_TAMPSEC;
277461e8793SGatien Chevallier 	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_1)
278461e8793SGatien Chevallier 		seccfgr |= _TAMP_SECCFGR_CNT1SEC;
279461e8793SGatien Chevallier 	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_2)
280461e8793SGatien Chevallier 		seccfgr |= _TAMP_SECCFGR_CNT2SEC;
281461e8793SGatien Chevallier 
282461e8793SGatien Chevallier 	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_TAMP_PRIV)
283461e8793SGatien Chevallier 		privcfgr |= _TAMP_PRIVCFG_TAMPPRIV;
284461e8793SGatien Chevallier 	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R1)
285461e8793SGatien Chevallier 		privcfgr |= _TAMP_PRIVCFG_CNT1PRIV | _TAMP_PRIVCFG_BKPRWPRIV;
286461e8793SGatien Chevallier 	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R2)
287461e8793SGatien Chevallier 		privcfgr |= _TAMP_PRIVCFG_CNT2PRIV | _TAMP_PRIVCFG_BKPWPRIV;
288461e8793SGatien Chevallier 
289461e8793SGatien Chevallier 	/* Security and privilege RIF configuration */
290461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_PRIVCFGR, access_mask_priv_reg, privcfgr);
291461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_SECCFGR, access_mask_sec_reg, seccfgr);
292461e8793SGatien Chevallier 
293461e8793SGatien Chevallier 	if (!stm32_tamp_dev->pdata.is_tdcid)
294461e8793SGatien Chevallier 		return;
295461e8793SGatien Chevallier 
296461e8793SGatien Chevallier 	for (i = 0; i < TAMP_RIF_RESOURCES; i++) {
297461e8793SGatien Chevallier 		if (!(BIT(i) & rif_conf->access_mask[0]))
298461e8793SGatien Chevallier 			continue;
299461e8793SGatien Chevallier 
300461e8793SGatien Chevallier 		io_clrsetbits32(base + _TAMP_CIDCFGR(i),
301461e8793SGatien Chevallier 				_TAMP_CIDCFGR_CONF_MASK,
302461e8793SGatien Chevallier 				rif_conf->cid_confs[i]);
303461e8793SGatien Chevallier 	}
304461e8793SGatien Chevallier }
305461e8793SGatien Chevallier 
306461e8793SGatien Chevallier static TEE_Result stm32_tamp_apply_bkpr_rif_conf(void)
307461e8793SGatien Chevallier {
308*92ab6535SGatien Chevallier 	struct stm32_bkpregs_conf *bkpregs_conf =
309461e8793SGatien Chevallier 			&stm32_tamp_dev->pdata.bkpregs_conf;
310461e8793SGatien Chevallier 	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
311461e8793SGatien Chevallier 	unsigned int i = 0;
312461e8793SGatien Chevallier 
313461e8793SGatien Chevallier 	if (!bkpregs_conf->rif_offsets)
314461e8793SGatien Chevallier 		panic("No backup register configuration");
315461e8793SGatien Chevallier 
316461e8793SGatien Chevallier 	for (i = 0; i < TAMP_RIF_OFFSET_CNT; i++) {
317461e8793SGatien Chevallier 		if (bkpregs_conf->rif_offsets[i] >
318461e8793SGatien Chevallier 		    (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG))
319461e8793SGatien Chevallier 			return TEE_ERROR_NOT_SUPPORTED;
320461e8793SGatien Chevallier 	}
321461e8793SGatien Chevallier 
322461e8793SGatien Chevallier 	/* Fill the 3 TAMP_BKPRIFRx registers */
323461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_BKPRIFR(1), _TAMP_BKPRIFR_1_MASK,
324461e8793SGatien Chevallier 			bkpregs_conf->rif_offsets[0]);
325461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_BKPRIFR(2), _TAMP_BKPRIFR_2_MASK,
326461e8793SGatien Chevallier 			bkpregs_conf->rif_offsets[1]);
327461e8793SGatien Chevallier 	io_clrsetbits32(base + _TAMP_BKPRIFR(3), _TAMP_BKPRIFR_3_MASK,
328461e8793SGatien Chevallier 			bkpregs_conf->rif_offsets[2] |
329461e8793SGatien Chevallier 			SHIFT_U32(bkpregs_conf->rif_offsets[3],
330461e8793SGatien Chevallier 				  _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT));
331461e8793SGatien Chevallier 
332461e8793SGatien Chevallier 	DMSG("Backup registers mapping :");
333461e8793SGatien Chevallier 	DMSG("********START of zone 1********");
334461e8793SGatien Chevallier 	DMSG("Protection Zone 1-RIF1 begins at register: 0");
335461e8793SGatien Chevallier 	DMSG("Protection Zone 1-RIF2 begins at register: %"PRIu32,
336461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[0]);
337461e8793SGatien Chevallier 	DMSG("Protection Zone 1-RIF2 ends at register: %"PRIu32,
338461e8793SGatien Chevallier 	     bkpregs_conf->zone1_end ? bkpregs_conf->zone1_end - 1 : 0);
339461e8793SGatien Chevallier 	DMSG("********END of zone 1********");
340461e8793SGatien Chevallier 	DMSG("********START of zone 2********");
341461e8793SGatien Chevallier 	DMSG("Protection Zone 2-RIF1 begins at register: %"PRIu32,
342461e8793SGatien Chevallier 	     bkpregs_conf->zone1_end);
343461e8793SGatien Chevallier 	DMSG("Protection Zone 2-RIF2 begins at register: %"PRIu32,
344461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[1]);
345461e8793SGatien Chevallier 	DMSG("Protection Zone 2-RIF2 ends at register: %"PRIu32,
346461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[1] > bkpregs_conf->zone1_end ?
347461e8793SGatien Chevallier 	     bkpregs_conf->zone2_end - 1 : 0);
348461e8793SGatien Chevallier 	DMSG("********END of zone 2********");
349461e8793SGatien Chevallier 	DMSG("********START of zone 3********");
350461e8793SGatien Chevallier 	DMSG("Protection Zone 3-RIF1 begins at register: %"PRIu32,
351461e8793SGatien Chevallier 	     bkpregs_conf->zone2_end);
352461e8793SGatien Chevallier 	DMSG("Protection Zone 3-RIF0 begins at register: %"PRIu32,
353461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[2]);
354461e8793SGatien Chevallier 	DMSG("Protection Zone 3-RIF2 begins at register: %"PRIu32,
355461e8793SGatien Chevallier 	     bkpregs_conf->rif_offsets[3]);
356461e8793SGatien Chevallier 	DMSG("Protection Zone 3-RIF2 ends at the last register: %"PRIu32,
357461e8793SGatien Chevallier 	     stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG);
358461e8793SGatien Chevallier 	DMSG("********END of zone 3********");
359461e8793SGatien Chevallier 
360461e8793SGatien Chevallier 	return TEE_SUCCESS;
361461e8793SGatien Chevallier }
36269b8b983SEtienne Carriere 
363*92ab6535SGatien Chevallier static TEE_Result stm32_tamp_set_secure_bkpregs(void)
36469b8b983SEtienne Carriere {
365*92ab6535SGatien Chevallier 	struct stm32_bkpregs_conf *bkpregs_conf =
366*92ab6535SGatien Chevallier 		&stm32_tamp_dev->pdata.bkpregs_conf;
36769b8b983SEtienne Carriere 	vaddr_t base = 0;
36869b8b983SEtienne Carriere 	uint32_t first_z2 = 0;
36969b8b983SEtienne Carriere 	uint32_t first_z3 = 0;
37069b8b983SEtienne Carriere 
371461e8793SGatien Chevallier 	base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
37269b8b983SEtienne Carriere 
373*92ab6535SGatien Chevallier 	first_z2 = bkpregs_conf->zone1_end;
374*92ab6535SGatien Chevallier 	first_z3 = bkpregs_conf->zone2_end;
37569b8b983SEtienne Carriere 
376461e8793SGatien Chevallier 	if ((first_z2 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) ||
377461e8793SGatien Chevallier 	    (first_z3 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)))
37869b8b983SEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
37969b8b983SEtienne Carriere 
380461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.compat &&
381461e8793SGatien Chevallier 	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) {
38269b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SECCFGR,
38369b8b983SEtienne Carriere 				_TAMP_SECCFGR_BKPRWSEC_MASK,
38469b8b983SEtienne Carriere 				(first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) &
38569b8b983SEtienne Carriere 				_TAMP_SECCFGR_BKPRWSEC_MASK);
38669b8b983SEtienne Carriere 
38769b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SECCFGR,
38869b8b983SEtienne Carriere 				_TAMP_SECCFGR_BKPWSEC_MASK,
38969b8b983SEtienne Carriere 				(first_z3 << _TAMP_SECCFGR_BKPWSEC_SHIFT) &
39069b8b983SEtienne Carriere 				_TAMP_SECCFGR_BKPWSEC_MASK);
39169b8b983SEtienne Carriere 	} else {
39269b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SMCR,
39369b8b983SEtienne Carriere 				_TAMP_SMCR_BKPRWDPROT_MASK,
39469b8b983SEtienne Carriere 				(first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) &
39569b8b983SEtienne Carriere 				_TAMP_SMCR_BKPRWDPROT_MASK);
39669b8b983SEtienne Carriere 
39769b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SMCR,
39869b8b983SEtienne Carriere 				_TAMP_SMCR_BKPWDPROT_MASK,
39969b8b983SEtienne Carriere 				(first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) &
40069b8b983SEtienne Carriere 				_TAMP_SMCR_BKPWDPROT_MASK);
40169b8b983SEtienne Carriere 	}
40269b8b983SEtienne Carriere 
40369b8b983SEtienne Carriere 	return TEE_SUCCESS;
40469b8b983SEtienne Carriere }
40569b8b983SEtienne Carriere 
406461e8793SGatien Chevallier static void stm32_tamp_set_secure(uint32_t mode)
40769b8b983SEtienne Carriere {
408461e8793SGatien Chevallier 	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
40969b8b983SEtienne Carriere 
410461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.compat &&
411461e8793SGatien Chevallier 	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) {
41269b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_SECCFGR,
41369b8b983SEtienne Carriere 				_TAMP_SECCFGR_BUT_BKP_MASK,
41469b8b983SEtienne Carriere 				mode & _TAMP_SECCFGR_BUT_BKP_MASK);
41569b8b983SEtienne Carriere 	} else {
41669b8b983SEtienne Carriere 		/*
41769b8b983SEtienne Carriere 		 * Note: MP15 doesn't use SECCFG register and
41869b8b983SEtienne Carriere 		 * inverts the secure bit.
41969b8b983SEtienne Carriere 		 */
42069b8b983SEtienne Carriere 		if (mode & _TAMP_SECCFGR_TAMPSEC)
42169b8b983SEtienne Carriere 			io_clrbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT);
42269b8b983SEtienne Carriere 		else
42369b8b983SEtienne Carriere 			io_setbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT);
42469b8b983SEtienne Carriere 	}
42569b8b983SEtienne Carriere }
42669b8b983SEtienne Carriere 
427461e8793SGatien Chevallier static void stm32_tamp_set_privilege(uint32_t mode)
42869b8b983SEtienne Carriere {
429461e8793SGatien Chevallier 	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
43069b8b983SEtienne Carriere 
431461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.compat &&
432461e8793SGatien Chevallier 	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_PRIVCFGR))
43369b8b983SEtienne Carriere 		io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK,
43469b8b983SEtienne Carriere 				mode & _TAMP_PRIVCFGR_MASK);
43569b8b983SEtienne Carriere }
43669b8b983SEtienne Carriere 
437*92ab6535SGatien Chevallier static void parse_bkpregs_dt_conf(const void *fdt, int node)
438461e8793SGatien Chevallier {
439*92ab6535SGatien Chevallier 	struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata;
440461e8793SGatien Chevallier 	unsigned int bkpregs_count = 0;
441*92ab6535SGatien Chevallier 	const fdt32_t *cuint = NULL;
442461e8793SGatien Chevallier 	int lenp = 0;
443461e8793SGatien Chevallier 
444461e8793SGatien Chevallier 	cuint = fdt_getprop(fdt, node, "st,backup-zones", &lenp);
445461e8793SGatien Chevallier 	if (!cuint)
446461e8793SGatien Chevallier 		panic("Missing backup registers configuration");
447461e8793SGatien Chevallier 
448461e8793SGatien Chevallier 	/*
449461e8793SGatien Chevallier 	 * When TAMP does not support RIF, the backup registers can
450461e8793SGatien Chevallier 	 * be splited in 3 zones. These zones have specific read/write
451461e8793SGatien Chevallier 	 * access permissions based on the secure status of the accesser.
452461e8793SGatien Chevallier 	 * When RIF is supported, these zones can additionally be splited
453461e8793SGatien Chevallier 	 * in subzones that have CID filtering. Zones/Subzones can be empty and
454461e8793SGatien Chevallier 	 * are contiguous.
455461e8793SGatien Chevallier 	 */
456*92ab6535SGatien Chevallier 	if (!(pdata->compat->tags & TAMP_HAS_RIF_SUPPORT)) {
457461e8793SGatien Chevallier 		/* 3 zones, 2 offsets to apply */
458461e8793SGatien Chevallier 		if (lenp != sizeof(uint32_t) * TAMP_NB_BKPR_ZONES)
459461e8793SGatien Chevallier 			panic("Incorrect bkpregs configuration");
460461e8793SGatien Chevallier 
461461e8793SGatien Chevallier 		pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]);
462461e8793SGatien Chevallier 		bkpregs_count = fdt32_to_cpu(cuint[0]);
463461e8793SGatien Chevallier 
464461e8793SGatien Chevallier 		pdata->bkpregs_conf.zone2_end = bkpregs_count +
465461e8793SGatien Chevallier 						fdt32_to_cpu(cuint[1]);
466461e8793SGatien Chevallier 	} else {
467461e8793SGatien Chevallier 		/*
468461e8793SGatien Chevallier 		 * Zone 3
469461e8793SGatien Chevallier 		 * ----------------------|
470461e8793SGatien Chevallier 		 * Protection Zone 3-RIF2|Read non-
471461e8793SGatien Chevallier 		 * ----------------------|secure
472461e8793SGatien Chevallier 		 * Protection Zone 3-RIF0|Write non-
473461e8793SGatien Chevallier 		 * ----------------------|secure
474461e8793SGatien Chevallier 		 * Protection Zone 3-RIF1|
475461e8793SGatien Chevallier 		 * ----------------------|
476461e8793SGatien Chevallier 		 *
477461e8793SGatien Chevallier 		 * Zone 2
478461e8793SGatien Chevallier 		 * ----------------------|
479461e8793SGatien Chevallier 		 * Protection Zone 2-RIF2|Read non-
480461e8793SGatien Chevallier 		 * ----------------------|secure
481461e8793SGatien Chevallier 		 * Protection Zone 2-RIF1|Write secure
482461e8793SGatien Chevallier 		 * ----------------------|
483461e8793SGatien Chevallier 		 *
484461e8793SGatien Chevallier 		 * Zone 1
485461e8793SGatien Chevallier 		 * ----------------------|
486461e8793SGatien Chevallier 		 * Protection Zone 1-RIF2|Read secure
487461e8793SGatien Chevallier 		 * ----------------------|Write secure
488461e8793SGatien Chevallier 		 * Protection Zone 1-RIF1|
489461e8793SGatien Chevallier 		 * ----------------------|
490461e8793SGatien Chevallier 		 *
491461e8793SGatien Chevallier 		 * (BHK => First 8 registers)
492461e8793SGatien Chevallier 		 */
493461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets = calloc(TAMP_RIF_OFFSET_CNT,
494461e8793SGatien Chevallier 							 sizeof(uint32_t));
495461e8793SGatien Chevallier 		if (!pdata->bkpregs_conf.rif_offsets)
496461e8793SGatien Chevallier 			panic();
497461e8793SGatien Chevallier 
498461e8793SGatien Chevallier 		/*
499461e8793SGatien Chevallier 		 * 3 zones with 7 subzones in total(6 offsets):
500461e8793SGatien Chevallier 		 * - 2 zone offsets
501461e8793SGatien Chevallier 		 * - 4 subzones offsets
502461e8793SGatien Chevallier 		 */
503461e8793SGatien Chevallier 		if (lenp != sizeof(uint32_t) *
504461e8793SGatien Chevallier 		    (TAMP_RIF_OFFSET_CNT + TAMP_NB_BKPR_ZONES))
505461e8793SGatien Chevallier 			panic("Incorrect bkpregs configuration");
506461e8793SGatien Chevallier 
507461e8793SGatien Chevallier 		/* Backup registers zone 1 */
508461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets[0] = fdt32_to_cpu(cuint[0]);
509461e8793SGatien Chevallier 		pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]) +
510461e8793SGatien Chevallier 						fdt32_to_cpu(cuint[1]);
511461e8793SGatien Chevallier 
512461e8793SGatien Chevallier 		bkpregs_count = pdata->bkpregs_conf.zone1_end;
513461e8793SGatien Chevallier 
514461e8793SGatien Chevallier 		/* Backup registers zone 2 */
515461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets[1] = bkpregs_count +
516461e8793SGatien Chevallier 						     fdt32_to_cpu(cuint[2]);
517461e8793SGatien Chevallier 		pdata->bkpregs_conf.zone2_end = bkpregs_count +
518461e8793SGatien Chevallier 						fdt32_to_cpu(cuint[2]) +
519461e8793SGatien Chevallier 						fdt32_to_cpu(cuint[3]);
520461e8793SGatien Chevallier 
521461e8793SGatien Chevallier 		bkpregs_count = pdata->bkpregs_conf.zone2_end;
522461e8793SGatien Chevallier 
523461e8793SGatien Chevallier 		/* Backup registers zone 3 */
524461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets[2] = bkpregs_count +
525461e8793SGatien Chevallier 						     fdt32_to_cpu(cuint[4]);
526461e8793SGatien Chevallier 		pdata->bkpregs_conf.rif_offsets[3] = bkpregs_count +
527461e8793SGatien Chevallier 						      fdt32_to_cpu(cuint[4]) +
528461e8793SGatien Chevallier 						      fdt32_to_cpu(cuint[5]);
529461e8793SGatien Chevallier 	}
530461e8793SGatien Chevallier }
531461e8793SGatien Chevallier 
532461e8793SGatien Chevallier static TEE_Result stm32_tamp_parse_fdt(const void *fdt, int node,
53369b8b983SEtienne Carriere 				       const void *compat)
53469b8b983SEtienne Carriere {
535461e8793SGatien Chevallier 	struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata;
536461e8793SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
53769b8b983SEtienne Carriere 	struct dt_node_info dt_tamp = { };
53869b8b983SEtienne Carriere 
539f354a5d8SGatien Chevallier 	fdt_fill_device_info(fdt, &dt_tamp, node);
54069b8b983SEtienne Carriere 
54169b8b983SEtienne Carriere 	if (dt_tamp.reg == DT_INFO_INVALID_REG ||
54269b8b983SEtienne Carriere 	    dt_tamp.reg_size == DT_INFO_INVALID_REG_SIZE)
54369b8b983SEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
54469b8b983SEtienne Carriere 
545461e8793SGatien Chevallier 	pdata->compat = (struct stm32_tamp_compat *)compat;
546461e8793SGatien Chevallier 	pdata->it = dt_tamp.interrupt;
547461e8793SGatien Chevallier 	pdata->base.pa = dt_tamp.reg;
548461e8793SGatien Chevallier 	io_pa_or_va_secure(&pdata->base, dt_tamp.reg_size);
54969b8b983SEtienne Carriere 
550461e8793SGatien Chevallier 	res = clk_dt_get_by_index(fdt, node, 0, &pdata->clock);
551461e8793SGatien Chevallier 	if (res)
552461e8793SGatien Chevallier 		return res;
553461e8793SGatien Chevallier 
554*92ab6535SGatien Chevallier 	parse_bkpregs_dt_conf(fdt, node);
555461e8793SGatien Chevallier 
556461e8793SGatien Chevallier 	if (pdata->compat->tags & TAMP_HAS_RIF_SUPPORT) {
557461e8793SGatien Chevallier 		const fdt32_t *cuint = NULL;
558461e8793SGatien Chevallier 		unsigned int i = 0;
559461e8793SGatien Chevallier 		int lenp = 0;
560461e8793SGatien Chevallier 
561461e8793SGatien Chevallier 		res = stm32_rifsc_check_tdcid(&pdata->is_tdcid);
562461e8793SGatien Chevallier 		if (res)
563461e8793SGatien Chevallier 			return res;
564461e8793SGatien Chevallier 
565461e8793SGatien Chevallier 		cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
566461e8793SGatien Chevallier 		if (!cuint) {
567461e8793SGatien Chevallier 			DMSG("No RIF configuration available");
568461e8793SGatien Chevallier 			return TEE_SUCCESS;
569461e8793SGatien Chevallier 		}
570461e8793SGatien Chevallier 
571461e8793SGatien Chevallier 		pdata->conf_data = calloc(1, sizeof(*pdata->conf_data));
572461e8793SGatien Chevallier 		if (!pdata->conf_data)
573461e8793SGatien Chevallier 			panic();
574461e8793SGatien Chevallier 
575461e8793SGatien Chevallier 		pdata->nb_rif_resources = (unsigned int)(lenp /
576461e8793SGatien Chevallier 							 sizeof(uint32_t));
577461e8793SGatien Chevallier 		assert(pdata->nb_rif_resources <= TAMP_RIF_RESOURCES);
578461e8793SGatien Chevallier 
579461e8793SGatien Chevallier 		pdata->conf_data->cid_confs = calloc(TAMP_RIF_RESOURCES,
580461e8793SGatien Chevallier 						     sizeof(uint32_t));
581461e8793SGatien Chevallier 		pdata->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
582461e8793SGatien Chevallier 		pdata->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
583461e8793SGatien Chevallier 		pdata->conf_data->access_mask = calloc(1, sizeof(uint32_t));
584461e8793SGatien Chevallier 		if (!pdata->conf_data->cid_confs ||
585461e8793SGatien Chevallier 		    !pdata->conf_data->sec_conf ||
586461e8793SGatien Chevallier 		    !pdata->conf_data->priv_conf ||
587461e8793SGatien Chevallier 		    !pdata->conf_data->access_mask)
588461e8793SGatien Chevallier 			panic("Not enough memory capacity for TAMP RIF config");
589461e8793SGatien Chevallier 
590461e8793SGatien Chevallier 		for (i = 0; i < pdata->nb_rif_resources; i++)
591461e8793SGatien Chevallier 			stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]),
592461e8793SGatien Chevallier 					    pdata->conf_data,
593461e8793SGatien Chevallier 					    TAMP_RIF_RESOURCES);
594461e8793SGatien Chevallier 	}
595461e8793SGatien Chevallier 
596461e8793SGatien Chevallier 	return TEE_SUCCESS;
59769b8b983SEtienne Carriere }
59869b8b983SEtienne Carriere 
59969b8b983SEtienne Carriere static TEE_Result stm32_tamp_probe(const void *fdt, int node,
60069b8b983SEtienne Carriere 				   const void *compat_data)
60169b8b983SEtienne Carriere {
60269b8b983SEtienne Carriere 	uint32_t __maybe_unused revision = 0;
60369b8b983SEtienne Carriere 	TEE_Result res = TEE_SUCCESS;
60469b8b983SEtienne Carriere 	vaddr_t base = 0;
60569b8b983SEtienne Carriere 
606461e8793SGatien Chevallier 	stm32_tamp_dev = calloc(1, sizeof(*stm32_tamp_dev));
607461e8793SGatien Chevallier 	if (!stm32_tamp_dev)
60869b8b983SEtienne Carriere 		return TEE_ERROR_OUT_OF_MEMORY;
60969b8b983SEtienne Carriere 
610461e8793SGatien Chevallier 	res = stm32_tamp_parse_fdt(fdt, node, compat_data);
61169b8b983SEtienne Carriere 	if (res)
61269b8b983SEtienne Carriere 		goto err;
61369b8b983SEtienne Carriere 
614461e8793SGatien Chevallier 	if (clk_enable(stm32_tamp_dev->pdata.clock))
615461e8793SGatien Chevallier 		panic();
61669b8b983SEtienne Carriere 
617461e8793SGatien Chevallier 	base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
61869b8b983SEtienne Carriere 
619461e8793SGatien Chevallier 	stm32_tamp_dev->hwconf1 = io_read32(base + _TAMP_HWCFGR1);
620461e8793SGatien Chevallier 	stm32_tamp_dev->hwconf2 = io_read32(base + _TAMP_HWCFGR2);
62169b8b983SEtienne Carriere 
62269b8b983SEtienne Carriere 	revision = io_read32(base + _TAMP_VERR);
62369b8b983SEtienne Carriere 	FMSG("STM32 TAMPER V%"PRIx32".%"PRIu32,
62469b8b983SEtienne Carriere 	     (revision & _TAMP_VERR_MAJREV) >> 4, revision & _TAMP_VERR_MINREV);
62569b8b983SEtienne Carriere 
626461e8793SGatien Chevallier 	if (!(stm32_tamp_dev->hwconf2 & _TAMP_HWCFGR2_TZ)) {
62769b8b983SEtienne Carriere 		EMSG("TAMP doesn't support TrustZone");
62869b8b983SEtienne Carriere 		res = TEE_ERROR_NOT_SUPPORTED;
62969b8b983SEtienne Carriere 		goto err_clk;
63069b8b983SEtienne Carriere 	}
63169b8b983SEtienne Carriere 
632461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) {
633461e8793SGatien Chevallier 		apply_rif_config();
634461e8793SGatien Chevallier 
635461e8793SGatien Chevallier 		if (stm32_tamp_dev->pdata.is_tdcid) {
636461e8793SGatien Chevallier 			res = stm32_tamp_apply_bkpr_rif_conf();
637461e8793SGatien Chevallier 			if (res)
638461e8793SGatien Chevallier 				goto err_clk;
639461e8793SGatien Chevallier 		}
640461e8793SGatien Chevallier 	} else {
64169b8b983SEtienne Carriere 		/*
64269b8b983SEtienne Carriere 		 * Enforce secure only access to protected TAMP registers.
64369b8b983SEtienne Carriere 		 * Allow non-secure access to monotonic counter.
64469b8b983SEtienne Carriere 		 */
645461e8793SGatien Chevallier 		stm32_tamp_set_secure(_TAMP_SECCFGR_TAMPSEC);
64669b8b983SEtienne Carriere 
64769b8b983SEtienne Carriere 		/*
64869b8b983SEtienne Carriere 		 * Enforce privilege only access to TAMP registers, backup
64969b8b983SEtienne Carriere 		 * registers and monotonic counter.
65069b8b983SEtienne Carriere 		 */
651461e8793SGatien Chevallier 		stm32_tamp_set_privilege(_TAMP_PRIVCFG_TAMPPRIV |
65269b8b983SEtienne Carriere 					 _TAMP_PRIVCFG_BKPRWPRIV |
65369b8b983SEtienne Carriere 					 _TAMP_PRIVCFG_BKPWPRIV);
654461e8793SGatien Chevallier 	}
65569b8b983SEtienne Carriere 
656*92ab6535SGatien Chevallier 	if (!(stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) ||
657*92ab6535SGatien Chevallier 	    stm32_tamp_dev->pdata.is_tdcid) {
658*92ab6535SGatien Chevallier 		res = stm32_tamp_set_secure_bkpregs();
659*92ab6535SGatien Chevallier 		if (res)
660*92ab6535SGatien Chevallier 			goto err_clk;
661*92ab6535SGatien Chevallier 	}
662*92ab6535SGatien Chevallier 
66369b8b983SEtienne Carriere 	return TEE_SUCCESS;
66469b8b983SEtienne Carriere 
66569b8b983SEtienne Carriere err_clk:
666461e8793SGatien Chevallier 	clk_disable(stm32_tamp_dev->pdata.clock);
66769b8b983SEtienne Carriere err:
668461e8793SGatien Chevallier 	if (stm32_tamp_dev->pdata.conf_data) {
669461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data->cid_confs);
670461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data->sec_conf);
671461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data->priv_conf);
672461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data->access_mask);
673461e8793SGatien Chevallier 		free(stm32_tamp_dev->pdata.conf_data);
674461e8793SGatien Chevallier 	}
675461e8793SGatien Chevallier 	free(stm32_tamp_dev->pdata.bkpregs_conf.rif_offsets);
676461e8793SGatien Chevallier 	free(stm32_tamp_dev);
677461e8793SGatien Chevallier 
67869b8b983SEtienne Carriere 	return res;
67969b8b983SEtienne Carriere }
68069b8b983SEtienne Carriere 
68169b8b983SEtienne Carriere static const struct stm32_tamp_compat mp13_compat = {
68269b8b983SEtienne Carriere 	.nb_monotonic_counter = 2,
683461e8793SGatien Chevallier 	.tags = TAMP_HAS_REGISTER_SECCFGR | TAMP_HAS_REGISTER_PRIVCFGR,
68469b8b983SEtienne Carriere };
68569b8b983SEtienne Carriere 
68669b8b983SEtienne Carriere static const struct stm32_tamp_compat mp15_compat = {
68769b8b983SEtienne Carriere 	.nb_monotonic_counter = 1,
68869b8b983SEtienne Carriere 	.tags = 0,
68969b8b983SEtienne Carriere };
69069b8b983SEtienne Carriere 
691461e8793SGatien Chevallier static const struct stm32_tamp_compat mp25_compat = {
692461e8793SGatien Chevallier 	.nb_monotonic_counter = 2,
693461e8793SGatien Chevallier 	.tags = TAMP_HAS_REGISTER_SECCFGR |
694461e8793SGatien Chevallier 		TAMP_HAS_REGISTER_PRIVCFGR |
695461e8793SGatien Chevallier 		TAMP_HAS_RIF_SUPPORT,
696461e8793SGatien Chevallier };
697461e8793SGatien Chevallier 
69869b8b983SEtienne Carriere static const struct dt_device_match stm32_tamp_match_table[] = {
699461e8793SGatien Chevallier 	{ .compatible = "st,stm32mp25-tamp", .compat_data = &mp25_compat },
70069b8b983SEtienne Carriere 	{ .compatible = "st,stm32mp13-tamp", .compat_data = &mp13_compat },
70169b8b983SEtienne Carriere 	{ .compatible = "st,stm32-tamp", .compat_data = &mp15_compat },
70269b8b983SEtienne Carriere 	{ }
70369b8b983SEtienne Carriere };
70469b8b983SEtienne Carriere 
70569b8b983SEtienne Carriere DEFINE_DT_DRIVER(stm32_tamp_dt_driver) = {
70669b8b983SEtienne Carriere 	.name = "stm32-tamp",
70769b8b983SEtienne Carriere 	.match_table = stm32_tamp_match_table,
70869b8b983SEtienne Carriere 	.probe = stm32_tamp_probe,
70969b8b983SEtienne Carriere };
710