xref: /optee_os/core/drivers/firewall/stm32_risaf.c (revision e78e87a9dd468a610e8c239e2c82d936eadd8992)
11b104208SGatien Chevallier // SPDX-License-Identifier: BSD-2-Clause
21b104208SGatien Chevallier /*
31b104208SGatien Chevallier  * Copyright (c) 2021-2024, STMicroelectronics
41b104208SGatien Chevallier  */
51b104208SGatien Chevallier 
61b104208SGatien Chevallier #include <assert.h>
71b104208SGatien Chevallier #include <drivers/clk.h>
81b104208SGatien Chevallier #include <drivers/clk_dt.h>
9*e78e87a9SGatien Chevallier #include <drivers/firewall.h>
101b104208SGatien Chevallier #include <drivers/stm32_rif.h>
111b104208SGatien Chevallier #include <drivers/stm32_risaf.h>
121b104208SGatien Chevallier #include <dt-bindings/firewall/stm32mp25-risaf.h>
131b104208SGatien Chevallier #include <io.h>
141b104208SGatien Chevallier #include <kernel/boot.h>
151b104208SGatien Chevallier #include <kernel/dt.h>
161b104208SGatien Chevallier #include <kernel/pm.h>
17*e78e87a9SGatien Chevallier #include <kernel/spinlock.h>
181b104208SGatien Chevallier #include <kernel/tee_misc.h>
191b104208SGatien Chevallier #include <libfdt.h>
201b104208SGatien Chevallier #include <mm/core_memprot.h>
211b104208SGatien Chevallier #include <platform_config.h>
221b104208SGatien Chevallier #include <stdint.h>
231b104208SGatien Chevallier #include <util.h>
241b104208SGatien Chevallier 
251b104208SGatien Chevallier /* RISAF general registers (base relative) */
261b104208SGatien Chevallier #define _RISAF_CR			U(0x00)
271b104208SGatien Chevallier #define _RISAF_SR			U(0x04)
281b104208SGatien Chevallier #define _RISAF_IASR			U(0x08)
291b104208SGatien Chevallier #define _RISAF_IACR			U(0xC)
301b104208SGatien Chevallier #define _RISAF_IAESR0			U(0x20)
311b104208SGatien Chevallier #define _RISAF_IADDR0			U(0x24)
321b104208SGatien Chevallier #define _RISAF_IAESR1			U(0x28)
331b104208SGatien Chevallier #define _RISAF_IADDR1			U(0x2C)
341b104208SGatien Chevallier #define _RISAF_KEYR			U(0x30)
351b104208SGatien Chevallier #define _RISAF_HWCFGR			U(0xFF0)
361b104208SGatien Chevallier #define _RISAF_VERR			U(0xFF4)
371b104208SGatien Chevallier #define _RISAF_IPIDR			U(0xFF8)
381b104208SGatien Chevallier #define _RISAF_SIDR			U(0xFFC)
391b104208SGatien Chevallier 
401b104208SGatien Chevallier /* RISAF general register field description */
411b104208SGatien Chevallier /* _RISAF_CR register fields */
421b104208SGatien Chevallier #define _RISAF_CR_GLOCK			BIT(0)
431b104208SGatien Chevallier /* _RISAF_SR register fields */
441b104208SGatien Chevallier #define _RISAF_SR_KEYVALID		BIT(0)
451b104208SGatien Chevallier #define _RISAF_SR_KEYRDY		BIT(1)
461b104208SGatien Chevallier #define _RISAF_SR_ENCDIS		BIT(2)
471b104208SGatien Chevallier /* _RISAF_IACR register fields */
481b104208SGatien Chevallier #define _RISAF_IACR_CAEF		BIT(0)
491b104208SGatien Chevallier #define _RISAF_IACR_IAEF0		BIT(1)
501b104208SGatien Chevallier #define _RISAF_IACR_IAEF1		BIT(2)
511b104208SGatien Chevallier /* _RISAF_HWCFGR register fields */
521b104208SGatien Chevallier #define _RISAF_HWCFGR_CFG1_SHIFT	U(0)
531b104208SGatien Chevallier #define _RISAF_HWCFGR_CFG1_MASK		GENMASK_32(7, 0)
541b104208SGatien Chevallier #define _RISAF_HWCFGR_CFG2_SHIFT	U(8)
551b104208SGatien Chevallier #define _RISAF_HWCFGR_CFG2_MASK		GENMASK_32(15, 8)
561b104208SGatien Chevallier #define _RISAF_HWCFGR_CFG3_SHIFT	U(16)
571b104208SGatien Chevallier #define _RISAF_HWCFGR_CFG3_MASK		GENMASK_32(23, 16)
581b104208SGatien Chevallier #define _RISAF_HWCFGR_CFG4_SHIFT	U(24)
591b104208SGatien Chevallier #define _RISAF_HWCFGR_CFG4_MASK		GENMASK_32(31, 24)
601b104208SGatien Chevallier /* _RISAF_VERR register fields */
611b104208SGatien Chevallier #define _RISAF_VERR_MINREV_SHIFT	U(0)
621b104208SGatien Chevallier #define _RISAF_VERR_MINREV_MASK		GENMASK_32(3, 0)
631b104208SGatien Chevallier #define _RISAF_VERR_MAJREV_SHIFT	U(4)
641b104208SGatien Chevallier #define _RISAF_VERR_MAJREV_MASK		GENMASK_32(7, 4)
651b104208SGatien Chevallier 
661b104208SGatien Chevallier /* RISAF region registers (base relative) */
671b104208SGatien Chevallier #define _RISAF_REG_BASE			U(0x40)
681b104208SGatien Chevallier #define _RISAF_REG_SIZE			U(0x40)
691b104208SGatien Chevallier #define _RISAF_REG(n)			(_RISAF_REG_BASE + \
701b104208SGatien Chevallier 					 (((n) - 1) * _RISAF_REG_SIZE))
711b104208SGatien Chevallier #define _RISAF_REG_CFGR_OFFSET		U(0x0)
721b104208SGatien Chevallier #define _RISAF_REG_CFGR(n)		(_RISAF_REG(n) + _RISAF_REG_CFGR_OFFSET)
731b104208SGatien Chevallier #define _RISAF_REG_STARTR_OFFSET	U(0x4)
741b104208SGatien Chevallier #define _RISAF_REG_STARTR(n)		(_RISAF_REG(n) + \
751b104208SGatien Chevallier 					 _RISAF_REG_STARTR_OFFSET)
761b104208SGatien Chevallier #define _RISAF_REG_ENDR_OFFSET		U(0x8)
771b104208SGatien Chevallier #define _RISAF_REG_ENDR(n)		(_RISAF_REG(n) + _RISAF_REG_ENDR_OFFSET)
781b104208SGatien Chevallier #define _RISAF_REG_CIDCFGR_OFFSET	U(0xC)
791b104208SGatien Chevallier #define _RISAF_REG_CIDCFGR(n)		(_RISAF_REG(n) + \
801b104208SGatien Chevallier 					 _RISAF_REG_CIDCFGR_OFFSET)
811b104208SGatien Chevallier 
821b104208SGatien Chevallier /* RISAF region register field description */
831b104208SGatien Chevallier /* _RISAF_REG_CFGR(n) register fields */
841b104208SGatien Chevallier #define _RISAF_REG_CFGR_BREN_SHIFT	U(0)
851b104208SGatien Chevallier #define _RISAF_REG_CFGR_BREN		BIT(_RISAF_REG_CFGR_BREN_SHIFT)
861b104208SGatien Chevallier #define _RISAF_REG_CFGR_SEC_SHIFT	U(8)
871b104208SGatien Chevallier #define _RISAF_REG_CFGR_SEC		BIT(_RISAF_REG_CFGR_SEC_SHIFT)
881b104208SGatien Chevallier #define _RISAF_REG_CFGR_ENC_SHIFT	U(15)
891b104208SGatien Chevallier #define _RISAF_REG_CFGR_ENC		BIT(_RISAF_REG_CFGR_ENC_SHIFT)
901b104208SGatien Chevallier #define _RISAF_REG_CFGR_PRIVC_SHIFT	U(16)
911b104208SGatien Chevallier #define _RISAF_REG_CFGR_PRIVC_MASK	GENMASK_32(23, 16)
921b104208SGatien Chevallier #define _RISAF_REG_CFGR_ALL_MASK	(_RISAF_REG_CFGR_BREN | \
931b104208SGatien Chevallier 					 _RISAF_REG_CFGR_SEC | \
941b104208SGatien Chevallier 					 _RISAF_REG_CFGR_ENC | \
951b104208SGatien Chevallier 					 _RISAF_REG_CFGR_PRIVC_MASK)
961b104208SGatien Chevallier 
971b104208SGatien Chevallier /* _RISAF_REG_CIDCFGR(n) register fields */
981b104208SGatien Chevallier #define _RISAF_REG_CIDCFGR_RDENC_SHIFT	U(0)
991b104208SGatien Chevallier #define _RISAF_REG_CIDCFGR_RDENC_MASK	GENMASK_32(7, 0)
1001b104208SGatien Chevallier #define _RISAF_REG_CIDCFGR_WRENC_SHIFT	U(16)
1011b104208SGatien Chevallier #define _RISAF_REG_CIDCFGR_WRENC_MASK	GENMASK_32(23, 16)
1021b104208SGatien Chevallier #define _RISAF_REG_CIDCFGR_ALL_MASK	(_RISAF_REG_CIDCFGR_RDENC_MASK | \
1031b104208SGatien Chevallier 					 _RISAF_REG_CIDCFGR_WRENC_MASK)
1041b104208SGatien Chevallier #define _RISAF_REG_READ_OK(reg, cid) \
1051b104208SGatien Chevallier 	((reg) & BIT((cid) + _RISAF_REG_CIDCFGR_RDENC_SHIFT))
1061b104208SGatien Chevallier #define _RISAF_REG_WRITE_OK(reg, cid)	\
1071b104208SGatien Chevallier 	((reg) & BIT((cid) + _RISAF_REG_CIDCFGR_WRENC_SHIFT))
1081b104208SGatien Chevallier 
1091b104208SGatien Chevallier #define _RISAF_GET_REGION_ID(cfg)	((cfg) & DT_RISAF_REG_ID_MASK)
1101b104208SGatien Chevallier 
1111b104208SGatien Chevallier #define _RISAF_NB_CID_SUPPORTED		U(8)
1121b104208SGatien Chevallier 
1131b104208SGatien Chevallier /**
1141b104208SGatien Chevallier  * struct stm32_risaf_region - RISAF memory region
1151b104208SGatien Chevallier  *
1161b104208SGatien Chevallier  * @addr: Region base address.
1171b104208SGatien Chevallier  * @len: Length of the memory region.
1181b104208SGatien Chevallier  * @cfg: Region configuration.
1191b104208SGatien Chevallier  */
1201b104208SGatien Chevallier struct stm32_risaf_region {
1211b104208SGatien Chevallier 	paddr_t addr;
1221b104208SGatien Chevallier 	size_t len;
1231b104208SGatien Chevallier 	uint32_t cfg;
1241b104208SGatien Chevallier };
1251b104208SGatien Chevallier 
1261b104208SGatien Chevallier /**
1271b104208SGatien Chevallier  * struct stm32_risaf_pdata - RISAF platform data
1281b104208SGatien Chevallier  *
1291b104208SGatien Chevallier  * @base: Base address of the RISAF instance.
1301b104208SGatien Chevallier  * @clock: Clock of the RISAF.
1311b104208SGatien Chevallier  * @regions: Number of memory regions, defined by the device tree configuration.
1321b104208SGatien Chevallier  * @risaf_name: Name of the RISAF instance
1331b104208SGatien Chevallier  * @nregions: Number of memory regions found in the device tree.
1341b104208SGatien Chevallier  * @conf_lock: State whether the RISAF configuration is locked.
1351b104208SGatien Chevallier  * @mem_base: Base address of the memory range covered by the RISAF instance.
1361b104208SGatien Chevallier  * @mem_size: Size of the memory range covered by the RISAF instance.
1371b104208SGatien Chevallier  * @enc_supported: If true, the RISAF instance supports encryption of the memory
1381b104208SGatien Chevallier  * regions.
1391b104208SGatien Chevallier  */
1401b104208SGatien Chevallier struct stm32_risaf_pdata {
1411b104208SGatien Chevallier 	struct io_pa_va base;
1421b104208SGatien Chevallier 	struct clk *clock;
1431b104208SGatien Chevallier 	struct stm32_risaf_region *regions;
1441b104208SGatien Chevallier 	char risaf_name[20];
1451b104208SGatien Chevallier 	unsigned int nregions;
1461b104208SGatien Chevallier 	unsigned int conf_lock;
1471b104208SGatien Chevallier 	paddr_t mem_base;
1481b104208SGatien Chevallier 	size_t mem_size;
1491b104208SGatien Chevallier 	bool enc_supported;
1501b104208SGatien Chevallier };
1511b104208SGatien Chevallier 
1521b104208SGatien Chevallier /**
1531b104208SGatien Chevallier  * struct stm32_risaf_ddata - RISAF driver data
1541b104208SGatien Chevallier  *
1551b104208SGatien Chevallier  * @mask_regions: Number of address bits to match when determining access to a
1561b104208SGatien Chevallier  * base region or subregion (WIDTH).
1571b104208SGatien Chevallier  * @max_base_regions: Number of subdivision of the memory range (A.K.A memory
1581b104208SGatien Chevallier  * regions) supported by the RISAF instance.
1591b104208SGatien Chevallier  * @granularity: Length of the smallest possible region size.
1601b104208SGatien Chevallier  */
1611b104208SGatien Chevallier struct stm32_risaf_ddata {
1621b104208SGatien Chevallier 	uint32_t mask_regions;
1631b104208SGatien Chevallier 	uint32_t max_base_regions;
1641b104208SGatien Chevallier 	uint32_t granularity;
1651b104208SGatien Chevallier };
1661b104208SGatien Chevallier 
1671b104208SGatien Chevallier struct stm32_risaf_instance {
1681b104208SGatien Chevallier 	struct stm32_risaf_pdata pdata;
1691b104208SGatien Chevallier 	struct stm32_risaf_ddata *ddata;
1701b104208SGatien Chevallier 
1711b104208SGatien Chevallier 	SLIST_ENTRY(stm32_risaf_instance) link;
1721b104208SGatien Chevallier };
1731b104208SGatien Chevallier 
1741b104208SGatien Chevallier struct stm32_risaf_version {
1751b104208SGatien Chevallier 	uint32_t major;
1761b104208SGatien Chevallier 	uint32_t minor;
1771b104208SGatien Chevallier 	uint32_t ip_id;
1781b104208SGatien Chevallier 	uint32_t size_id;
1791b104208SGatien Chevallier };
1801b104208SGatien Chevallier 
1811b104208SGatien Chevallier /**
1821b104208SGatien Chevallier  * struct stm32_risaf_compat_data  - Describes RISAF associated data
1831b104208SGatien Chevallier  * for compatible list.
1841b104208SGatien Chevallier  *
1851b104208SGatien Chevallier  * @supported_encryption:	identify RISAF encryption capabilities.
1861b104208SGatien Chevallier  */
1871b104208SGatien Chevallier struct stm32_risaf_compat_data {
1881b104208SGatien Chevallier 	bool supported_encryption;
1891b104208SGatien Chevallier };
1901b104208SGatien Chevallier 
1911b104208SGatien Chevallier static bool is_tdcid;
1921b104208SGatien Chevallier 
1931b104208SGatien Chevallier static const struct stm32_risaf_compat_data stm32_risaf_compat = {
1941b104208SGatien Chevallier 	.supported_encryption = false,
1951b104208SGatien Chevallier };
1961b104208SGatien Chevallier 
1971b104208SGatien Chevallier static const struct stm32_risaf_compat_data stm32_risaf_enc_compat = {
1981b104208SGatien Chevallier 	.supported_encryption = true,
1991b104208SGatien Chevallier };
2001b104208SGatien Chevallier 
2011b104208SGatien Chevallier static SLIST_HEAD(, stm32_risaf_instance) risaf_list =
2021b104208SGatien Chevallier 		SLIST_HEAD_INITIALIZER(risaf_list);
2031b104208SGatien Chevallier 
risaf_base(struct stm32_risaf_instance * risaf)2041b104208SGatien Chevallier static vaddr_t risaf_base(struct stm32_risaf_instance *risaf)
2051b104208SGatien Chevallier {
2061b104208SGatien Chevallier 	return io_pa_or_va_secure(&risaf->pdata.base, 1);
2071b104208SGatien Chevallier }
2081b104208SGatien Chevallier 
stm32_risaf_get_region_config(uint32_t cfg)2091b104208SGatien Chevallier static uint32_t stm32_risaf_get_region_config(uint32_t cfg)
2101b104208SGatien Chevallier {
2111b104208SGatien Chevallier 	return SHIFT_U32((cfg & DT_RISAF_EN_MASK) >> DT_RISAF_EN_SHIFT,
2121b104208SGatien Chevallier 			 _RISAF_REG_CFGR_BREN_SHIFT) |
2131b104208SGatien Chevallier 	       SHIFT_U32((cfg & DT_RISAF_SEC_MASK) >> DT_RISAF_SEC_SHIFT,
2141b104208SGatien Chevallier 			 _RISAF_REG_CFGR_SEC_SHIFT) |
2151b104208SGatien Chevallier 	       SHIFT_U32((cfg & DT_RISAF_ENC_MASK) >> (DT_RISAF_ENC_SHIFT + 1),
2161b104208SGatien Chevallier 			 _RISAF_REG_CFGR_ENC_SHIFT) |
2171b104208SGatien Chevallier 	       SHIFT_U32((cfg & DT_RISAF_PRIV_MASK) >> DT_RISAF_PRIV_SHIFT,
2181b104208SGatien Chevallier 			 _RISAF_REG_CFGR_PRIVC_SHIFT);
2191b104208SGatien Chevallier }
2201b104208SGatien Chevallier 
stm32_risaf_get_region_cid_config(uint32_t cfg)2211b104208SGatien Chevallier static uint32_t stm32_risaf_get_region_cid_config(uint32_t cfg)
2221b104208SGatien Chevallier {
2231b104208SGatien Chevallier 	return SHIFT_U32((cfg & DT_RISAF_WRITE_MASK) >> DT_RISAF_WRITE_SHIFT,
2241b104208SGatien Chevallier 			 _RISAF_REG_CIDCFGR_WRENC_SHIFT) |
2251b104208SGatien Chevallier 	       SHIFT_U32((cfg & DT_RISAF_READ_MASK) >> DT_RISAF_READ_SHIFT,
2261b104208SGatien Chevallier 			 _RISAF_REG_CIDCFGR_RDENC_SHIFT);
2271b104208SGatien Chevallier }
2281b104208SGatien Chevallier 
stm32_risaf_clear_illegal_access_flags(void)2291b104208SGatien Chevallier void stm32_risaf_clear_illegal_access_flags(void)
2301b104208SGatien Chevallier {
2311b104208SGatien Chevallier 	struct stm32_risaf_instance *risaf = NULL;
2321b104208SGatien Chevallier 
2331b104208SGatien Chevallier 	SLIST_FOREACH(risaf, &risaf_list, link) {
2341b104208SGatien Chevallier 		vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1);
2351b104208SGatien Chevallier 
2361b104208SGatien Chevallier 		if (!io_read32(base + _RISAF_IASR))
2371b104208SGatien Chevallier 			continue;
2381b104208SGatien Chevallier 
2391b104208SGatien Chevallier 		io_write32(base + _RISAF_IACR, _RISAF_IACR_CAEF |
2401b104208SGatien Chevallier 			   _RISAF_IACR_IAEF0 | _RISAF_IACR_IAEF1);
2411b104208SGatien Chevallier 	}
2421b104208SGatien Chevallier }
2431b104208SGatien Chevallier 
stm32_risaf_print_erroneous_data(void)2441b104208SGatien Chevallier void stm32_risaf_print_erroneous_data(void)
2451b104208SGatien Chevallier {
2461b104208SGatien Chevallier 	struct stm32_risaf_instance *risaf = NULL;
2471b104208SGatien Chevallier 
2481b104208SGatien Chevallier 	if (!IS_ENABLED(CFG_TEE_CORE_DEBUG))
2491b104208SGatien Chevallier 		return;
2501b104208SGatien Chevallier 
2511b104208SGatien Chevallier 	SLIST_FOREACH(risaf, &risaf_list, link) {
2521b104208SGatien Chevallier 		vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1);
2531b104208SGatien Chevallier 
2541b104208SGatien Chevallier 		/* Check if faulty address on this RISAF */
2551b104208SGatien Chevallier 		if (!io_read32(base + _RISAF_IASR))
2561b104208SGatien Chevallier 			continue;
2571b104208SGatien Chevallier 
2581b104208SGatien Chevallier 		IMSG("\n\nDUMPING DATA FOR %s\n\n", risaf->pdata.risaf_name);
2591b104208SGatien Chevallier 		IMSG("=====================================================");
2601b104208SGatien Chevallier 		IMSG("Status register (IAESR0): %#"PRIx32,
2611b104208SGatien Chevallier 		     io_read32(base + _RISAF_IAESR0));
2621b104208SGatien Chevallier 
2631b104208SGatien Chevallier 		/* Reserved if dual port feature not available */
2641b104208SGatien Chevallier 		if (io_read32(base + _RISAF_IAESR1))
2651b104208SGatien Chevallier 			IMSG("Status register Dual Port (IAESR1) %#"PRIx32,
2661b104208SGatien Chevallier 			     io_read32(base + _RISAF_IAESR1));
2671b104208SGatien Chevallier 
2681b104208SGatien Chevallier 		IMSG("-----------------------------------------------------");
2691b104208SGatien Chevallier 		if (virt_to_phys((void *)base) == RISAF4_BASE) {
2701b104208SGatien Chevallier 			IMSG("Faulty address (IADDR0): %#"PRIxPA,
2711b104208SGatien Chevallier 			     risaf->pdata.mem_base +
2721b104208SGatien Chevallier 			     io_read32(base + _RISAF_IADDR0));
2731b104208SGatien Chevallier 
2741b104208SGatien Chevallier 			/* Reserved if dual port feature not available */
2751b104208SGatien Chevallier 			if (io_read32(base + _RISAF_IADDR1))
2761b104208SGatien Chevallier 				IMSG("Dual port faulty address (IADDR1): %#"PRIxPA,
2771b104208SGatien Chevallier 				     risaf->pdata.mem_base +
2781b104208SGatien Chevallier 				     io_read32(base + _RISAF_IADDR1));
2791b104208SGatien Chevallier 		} else {
2801b104208SGatien Chevallier 			IMSG("Faulty address (IADDR0): %#"PRIx32,
2811b104208SGatien Chevallier 			     io_read32(base + _RISAF_IADDR0));
2821b104208SGatien Chevallier 
2831b104208SGatien Chevallier 			/* Reserved if dual port feature not available */
2841b104208SGatien Chevallier 			if (io_read32(base + _RISAF_IADDR1))
2851b104208SGatien Chevallier 				IMSG("Dual port faulty address (IADDR1): %#"PRIx32,
2861b104208SGatien Chevallier 				     io_read32(base + _RISAF_IADDR1));
2871b104208SGatien Chevallier 		}
2881b104208SGatien Chevallier 
2891b104208SGatien Chevallier 		IMSG("=====================================================\n");
2901b104208SGatien Chevallier 	};
2911b104208SGatien Chevallier }
2921b104208SGatien Chevallier 
2931b104208SGatien Chevallier static __maybe_unused
risaf_is_hw_encryption_enabled(struct stm32_risaf_instance * risaf)2941b104208SGatien Chevallier bool risaf_is_hw_encryption_enabled(struct stm32_risaf_instance *risaf)
2951b104208SGatien Chevallier {
2961b104208SGatien Chevallier 	return (io_read32(risaf_base(risaf) + _RISAF_SR) &
2971b104208SGatien Chevallier 		_RISAF_SR_ENCDIS) != _RISAF_SR_ENCDIS;
2981b104208SGatien Chevallier }
2991b104208SGatien Chevallier 
3001b104208SGatien Chevallier static TEE_Result
risaf_check_region_boundaries(struct stm32_risaf_instance * risaf,struct stm32_risaf_region * region)3011b104208SGatien Chevallier risaf_check_region_boundaries(struct stm32_risaf_instance *risaf,
3021b104208SGatien Chevallier 			      struct stm32_risaf_region *region)
3031b104208SGatien Chevallier {
3041b104208SGatien Chevallier 	if (!core_is_buffer_inside(region->addr, region->len,
3051b104208SGatien Chevallier 				   risaf->pdata.mem_base,
3061b104208SGatien Chevallier 				   risaf->pdata.mem_size)) {
3071b104208SGatien Chevallier 		EMSG("Region %#"PRIxPA"..%#"PRIxPA" outside RISAF area %#"PRIxPA"...%#"PRIxPA,
3081b104208SGatien Chevallier 		     region->addr, region->addr + region->len - 1,
3091b104208SGatien Chevallier 		     risaf->pdata.mem_base,
3101b104208SGatien Chevallier 		     risaf->pdata.mem_base + risaf->pdata.mem_size - 1);
3111b104208SGatien Chevallier 		return TEE_ERROR_BAD_PARAMETERS;
3121b104208SGatien Chevallier 	}
3131b104208SGatien Chevallier 
3141b104208SGatien Chevallier 	if (!risaf->ddata->granularity ||
3151b104208SGatien Chevallier 	    (region->addr % risaf->ddata->granularity) ||
3161b104208SGatien Chevallier 	    (region->len % risaf->ddata->granularity)) {
3171b104208SGatien Chevallier 		EMSG("RISAF %#"PRIxPA": start/end address granularity not respected",
3181b104208SGatien Chevallier 		     risaf->pdata.base.pa);
3191b104208SGatien Chevallier 		return TEE_ERROR_BAD_PARAMETERS;
3201b104208SGatien Chevallier 	}
3211b104208SGatien Chevallier 
3221b104208SGatien Chevallier 	return TEE_SUCCESS;
3231b104208SGatien Chevallier }
3241b104208SGatien Chevallier 
3251b104208SGatien Chevallier static TEE_Result
risaf_check_overlap(struct stm32_risaf_instance * risaf __maybe_unused,struct stm32_risaf_region * region,unsigned int index)3261b104208SGatien Chevallier risaf_check_overlap(struct stm32_risaf_instance *risaf __maybe_unused,
3271b104208SGatien Chevallier 		    struct stm32_risaf_region *region, unsigned int index)
3281b104208SGatien Chevallier {
3291b104208SGatien Chevallier 	unsigned int i = 0;
3301b104208SGatien Chevallier 
3311b104208SGatien Chevallier 	for (i = 0; i < index; i++) {
3321b104208SGatien Chevallier 		/* Skip region if there's no configuration */
3331b104208SGatien Chevallier 		if (!region[i].cfg)
3341b104208SGatien Chevallier 			continue;
3351b104208SGatien Chevallier 
3361b104208SGatien Chevallier 		if (core_is_buffer_intersect(region[index].addr,
3371b104208SGatien Chevallier 					     region[index].len,
3381b104208SGatien Chevallier 					     region[i].addr,
3391b104208SGatien Chevallier 					     region[i].len)) {
3401b104208SGatien Chevallier 			EMSG("RISAF %#"PRIxPA": Regions %u and %u overlap",
3411b104208SGatien Chevallier 			     risaf->pdata.base.pa, index, i);
3421b104208SGatien Chevallier 			return TEE_ERROR_GENERIC;
3431b104208SGatien Chevallier 		}
3441b104208SGatien Chevallier 	}
3451b104208SGatien Chevallier 
3461b104208SGatien Chevallier 	return TEE_SUCCESS;
3471b104208SGatien Chevallier }
3481b104208SGatien Chevallier 
risaf_configure_region(struct stm32_risaf_instance * risaf,uint32_t region_id,uint32_t cfg,uint32_t cid_cfg,paddr_t saddr,paddr_t eaddr)3491b104208SGatien Chevallier static TEE_Result risaf_configure_region(struct stm32_risaf_instance *risaf,
3501b104208SGatien Chevallier 					 uint32_t region_id, uint32_t cfg,
3511b104208SGatien Chevallier 					 uint32_t cid_cfg, paddr_t saddr,
3521b104208SGatien Chevallier 					 paddr_t eaddr)
3531b104208SGatien Chevallier {
3541b104208SGatien Chevallier 	uint32_t mask = risaf->ddata->mask_regions;
3551b104208SGatien Chevallier 	vaddr_t base = risaf_base(risaf);
3561b104208SGatien Chevallier 
3571b104208SGatien Chevallier 	if (cfg & _RISAF_REG_CFGR_ENC) {
3581b104208SGatien Chevallier 		if (!risaf->pdata.enc_supported) {
3591b104208SGatien Chevallier 			EMSG("RISAF %#"PRIxPA": encryption feature error",
3601b104208SGatien Chevallier 			     risaf->pdata.base.pa);
3611b104208SGatien Chevallier 			return TEE_ERROR_GENERIC;
3621b104208SGatien Chevallier 		}
3631b104208SGatien Chevallier 
3641b104208SGatien Chevallier 		if ((cfg & _RISAF_REG_CFGR_SEC) != _RISAF_REG_CFGR_SEC) {
3651b104208SGatien Chevallier 			EMSG("RISAF %#"PRIxPA": encryption on non-secure area",
3661b104208SGatien Chevallier 			     risaf->pdata.base.pa);
3671b104208SGatien Chevallier 			return TEE_ERROR_GENERIC;
3681b104208SGatien Chevallier 		}
3691b104208SGatien Chevallier 	}
3701b104208SGatien Chevallier 
3711b104208SGatien Chevallier 	io_clrbits32(base + _RISAF_REG_CFGR(region_id), _RISAF_REG_CFGR_BREN);
3721b104208SGatien Chevallier 
3731b104208SGatien Chevallier 	io_clrsetbits32(base + _RISAF_REG_STARTR(region_id), mask,
3741b104208SGatien Chevallier 			(saddr - risaf->pdata.mem_base) & mask);
3751b104208SGatien Chevallier 	io_clrsetbits32(base + _RISAF_REG_ENDR(region_id), mask,
3761b104208SGatien Chevallier 			(eaddr - risaf->pdata.mem_base) & mask);
3771b104208SGatien Chevallier 	io_clrsetbits32(base + _RISAF_REG_CIDCFGR(region_id),
3781b104208SGatien Chevallier 			_RISAF_REG_CIDCFGR_ALL_MASK,
3791b104208SGatien Chevallier 			cid_cfg & _RISAF_REG_CIDCFGR_ALL_MASK);
3801b104208SGatien Chevallier 
3811b104208SGatien Chevallier 	io_clrsetbits32(base + _RISAF_REG_CFGR(region_id),
3821b104208SGatien Chevallier 			_RISAF_REG_CFGR_ALL_MASK,
3831b104208SGatien Chevallier 			cfg & _RISAF_REG_CFGR_ALL_MASK);
3841b104208SGatien Chevallier 
3851b104208SGatien Chevallier 	DMSG("RISAF %#"PRIxPA": region %02"PRIu32" - start %#"PRIxPA
3861b104208SGatien Chevallier 	     "- end %#"PRIxPA" - cfg %#08"PRIx32" - cidcfg %#08"PRIx32,
3871b104208SGatien Chevallier 	     risaf->pdata.base.pa, region_id,
3881b104208SGatien Chevallier 	     risaf->pdata.mem_base +
3891b104208SGatien Chevallier 	     io_read32(base + _RISAF_REG_STARTR(region_id)),
3901b104208SGatien Chevallier 	     risaf->pdata.mem_base +
3911b104208SGatien Chevallier 	     io_read32(base + _RISAF_REG_ENDR(region_id)),
3921b104208SGatien Chevallier 	     io_read32(base + _RISAF_REG_CFGR(region_id)),
3931b104208SGatien Chevallier 	     io_read32(base + _RISAF_REG_CIDCFGR(region_id)));
3941b104208SGatien Chevallier 
3951b104208SGatien Chevallier 	return TEE_SUCCESS;
3961b104208SGatien Chevallier }
3971b104208SGatien Chevallier 
risaf_print_version(struct stm32_risaf_instance * risaf)3981b104208SGatien Chevallier static void risaf_print_version(struct stm32_risaf_instance *risaf)
3991b104208SGatien Chevallier {
4001b104208SGatien Chevallier 	vaddr_t base = risaf_base(risaf);
4011b104208SGatien Chevallier 	struct stm32_risaf_version __maybe_unused version = {
4021b104208SGatien Chevallier 		.major = (io_read32(base + _RISAF_VERR) &
4031b104208SGatien Chevallier 			  _RISAF_VERR_MAJREV_MASK) >> _RISAF_VERR_MAJREV_SHIFT,
4041b104208SGatien Chevallier 		.minor = (io_read32(base + _RISAF_VERR) &
4051b104208SGatien Chevallier 			  _RISAF_VERR_MINREV_MASK) >> _RISAF_VERR_MINREV_SHIFT,
4061b104208SGatien Chevallier 		.ip_id = io_read32(base + _RISAF_IPIDR),
4071b104208SGatien Chevallier 		.size_id = io_read32(base + _RISAF_SIDR)
4081b104208SGatien Chevallier 	};
4091b104208SGatien Chevallier 
4101b104208SGatien Chevallier 	DMSG("RISAF %#"PRIxPA" version %"PRIu32".%"PRIu32", ip%#"PRIx32" size%#"PRIx32,
4111b104208SGatien Chevallier 	     risaf->pdata.base.pa, version.major, version.minor, version.ip_id,
4121b104208SGatien Chevallier 	     version.size_id);
4131b104208SGatien Chevallier }
4141b104208SGatien Chevallier 
4151b104208SGatien Chevallier static __maybe_unused
stm32_risaf_lock(struct stm32_risaf_instance * risaf)4161b104208SGatien Chevallier void stm32_risaf_lock(struct stm32_risaf_instance *risaf)
4171b104208SGatien Chevallier {
4181b104208SGatien Chevallier 	assert(risaf);
4191b104208SGatien Chevallier 
4201b104208SGatien Chevallier 	io_setbits32(risaf_base(risaf) + _RISAF_CR, _RISAF_CR_GLOCK);
4211b104208SGatien Chevallier }
4221b104208SGatien Chevallier 
4231b104208SGatien Chevallier static __maybe_unused
stm32_risaf_is_locked(struct stm32_risaf_instance * risaf,bool * state)4241b104208SGatien Chevallier void stm32_risaf_is_locked(struct stm32_risaf_instance *risaf, bool *state)
4251b104208SGatien Chevallier {
4261b104208SGatien Chevallier 	assert(risaf);
4271b104208SGatien Chevallier 
4281b104208SGatien Chevallier 	*state = (io_read32(risaf_base(risaf) + _RISAF_CR) &
4291b104208SGatien Chevallier 		  _RISAF_CR_GLOCK) == _RISAF_CR_GLOCK;
4301b104208SGatien Chevallier }
4311b104208SGatien Chevallier 
stm32_risaf_init_ddata(struct stm32_risaf_instance * risaf)4321b104208SGatien Chevallier static TEE_Result stm32_risaf_init_ddata(struct stm32_risaf_instance *risaf)
4331b104208SGatien Chevallier {
4341b104208SGatien Chevallier 	vaddr_t base = risaf_base(risaf);
4351b104208SGatien Chevallier 	uint32_t granularity = 0;
4361b104208SGatien Chevallier 	uint32_t mask_lsb = 0;
4371b104208SGatien Chevallier 	uint32_t mask_msb = 0;
4381b104208SGatien Chevallier 	uint32_t hwcfgr = 0;
4391b104208SGatien Chevallier 
4401b104208SGatien Chevallier 	risaf->ddata = calloc(1, sizeof(*risaf->ddata));
4411b104208SGatien Chevallier 	if (!risaf->ddata)
4421b104208SGatien Chevallier 		return TEE_ERROR_OUT_OF_MEMORY;
4431b104208SGatien Chevallier 
4441b104208SGatien Chevallier 	/* Get address mask depending on RISAF instance HW configuration */
4451b104208SGatien Chevallier 	hwcfgr =  io_read32(base + _RISAF_HWCFGR);
4461b104208SGatien Chevallier 	mask_lsb = (hwcfgr & _RISAF_HWCFGR_CFG3_MASK) >>
4471b104208SGatien Chevallier 		   _RISAF_HWCFGR_CFG3_SHIFT;
4481b104208SGatien Chevallier 	mask_msb = mask_lsb + ((hwcfgr & _RISAF_HWCFGR_CFG4_MASK) >>
4491b104208SGatien Chevallier 			       _RISAF_HWCFGR_CFG4_SHIFT) - 1U;
4501b104208SGatien Chevallier 	risaf->ddata->mask_regions = GENMASK_32(mask_msb, mask_lsb);
4511b104208SGatien Chevallier 	risaf->ddata->max_base_regions = (hwcfgr & _RISAF_HWCFGR_CFG1_MASK) >>
4521b104208SGatien Chevallier 					 _RISAF_HWCFGR_CFG1_SHIFT;
4531b104208SGatien Chevallier 
4541b104208SGatien Chevallier 	/* Get IP region granularity */
4551b104208SGatien Chevallier 	granularity = io_read32(risaf_base(risaf) + _RISAF_HWCFGR);
4561b104208SGatien Chevallier 	granularity = BIT((granularity & _RISAF_HWCFGR_CFG3_MASK) >>
4571b104208SGatien Chevallier 			  _RISAF_HWCFGR_CFG3_SHIFT);
4581b104208SGatien Chevallier 	risaf->ddata->granularity = granularity;
4591b104208SGatien Chevallier 
4601b104208SGatien Chevallier 	return TEE_SUCCESS;
4611b104208SGatien Chevallier }
4621b104208SGatien Chevallier 
stm32_risaf_pm_resume(struct stm32_risaf_instance * risaf)4631b104208SGatien Chevallier static TEE_Result stm32_risaf_pm_resume(struct stm32_risaf_instance *risaf)
4641b104208SGatien Chevallier {
4651b104208SGatien Chevallier 	struct stm32_risaf_region *regions = risaf->pdata.regions;
4661b104208SGatien Chevallier 	size_t i = 0;
4671b104208SGatien Chevallier 
4681b104208SGatien Chevallier 	for (i = 0; i < risaf->pdata.nregions; i++) {
4691b104208SGatien Chevallier 		uint32_t id = _RISAF_GET_REGION_ID(regions[i].cfg);
4701b104208SGatien Chevallier 		paddr_t start_addr = 0;
4711b104208SGatien Chevallier 		paddr_t end_addr = 0;
4721b104208SGatien Chevallier 		uint32_t cid_cfg = 0;
4731b104208SGatien Chevallier 		uint32_t cfg = 0;
4741b104208SGatien Chevallier 
4751b104208SGatien Chevallier 		if (!id)
4761b104208SGatien Chevallier 			continue;
4771b104208SGatien Chevallier 
4781b104208SGatien Chevallier 		cfg = stm32_risaf_get_region_config(regions[i].cfg);
4791b104208SGatien Chevallier 		cid_cfg = stm32_risaf_get_region_cid_config(regions[i].cfg);
4801b104208SGatien Chevallier 		start_addr = regions[i].addr;
4811b104208SGatien Chevallier 		end_addr = start_addr + regions[i].len - 1U;
4821b104208SGatien Chevallier 		if (risaf_configure_region(risaf, id, cfg, cid_cfg,
4831b104208SGatien Chevallier 					   start_addr, end_addr))
4841b104208SGatien Chevallier 			panic();
4851b104208SGatien Chevallier 	}
4861b104208SGatien Chevallier 
4871b104208SGatien Chevallier 	return TEE_SUCCESS;
4881b104208SGatien Chevallier }
4891b104208SGatien Chevallier 
stm32_risaf_pm_suspend(struct stm32_risaf_instance * risaf)4901b104208SGatien Chevallier static TEE_Result stm32_risaf_pm_suspend(struct stm32_risaf_instance *risaf)
4911b104208SGatien Chevallier {
4921b104208SGatien Chevallier 	vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1);
4931b104208SGatien Chevallier 	size_t i = 0;
4941b104208SGatien Chevallier 
4951b104208SGatien Chevallier 	for (i = 0; i < risaf->pdata.nregions; i++) {
4961b104208SGatien Chevallier 		uint32_t id = _RISAF_GET_REGION_ID(risaf->pdata.regions[i].cfg);
4971b104208SGatien Chevallier 		struct stm32_risaf_region *region = risaf->pdata.regions + i;
4981b104208SGatien Chevallier 		paddr_t start_addr = 0;
4991b104208SGatien Chevallier 		paddr_t end_addr = 0;
5001b104208SGatien Chevallier 		uint32_t cid_cfg = 0;
5011b104208SGatien Chevallier 		uint32_t priv = 0;
5021b104208SGatien Chevallier 		uint32_t rden = 0;
5031b104208SGatien Chevallier 		uint32_t wren = 0;
5041b104208SGatien Chevallier 		uint32_t cfg = 0;
5051b104208SGatien Chevallier 		uint32_t enc = 0;
5061b104208SGatien Chevallier 		uint32_t sec = 0;
5071b104208SGatien Chevallier 		uint32_t en = 0;
5081b104208SGatien Chevallier 
5091b104208SGatien Chevallier 		/* Skip region not defined in DT, not configured in probe */
5101b104208SGatien Chevallier 		if (!id)
5111b104208SGatien Chevallier 			continue;
5121b104208SGatien Chevallier 
5131b104208SGatien Chevallier 		cfg = io_read32(base + _RISAF_REG_CFGR(id));
5141b104208SGatien Chevallier 		en = cfg & _RISAF_REG_CFGR_BREN;
5151b104208SGatien Chevallier 		sec = (cfg & _RISAF_REG_CFGR_SEC) >> _RISAF_REG_CFGR_SEC_SHIFT;
5161b104208SGatien Chevallier 		enc = (cfg & _RISAF_REG_CFGR_ENC) >> _RISAF_REG_CFGR_ENC_SHIFT;
5171b104208SGatien Chevallier 		priv = (cfg & _RISAF_REG_CFGR_PRIVC_MASK) >>
5181b104208SGatien Chevallier 		       _RISAF_REG_CFGR_PRIVC_SHIFT;
5191b104208SGatien Chevallier 
5201b104208SGatien Chevallier 		cid_cfg = io_read32(base + _RISAF_REG_CIDCFGR(id));
5211b104208SGatien Chevallier 		rden = cid_cfg & _RISAF_REG_CIDCFGR_RDENC_MASK;
5221b104208SGatien Chevallier 		wren = (cid_cfg & _RISAF_REG_CIDCFGR_WRENC_MASK) >>
5231b104208SGatien Chevallier 		       _RISAF_REG_CIDCFGR_WRENC_SHIFT;
5241b104208SGatien Chevallier 
5251b104208SGatien Chevallier 		region->cfg = id | SHIFT_U32(en, DT_RISAF_EN_SHIFT) |
5261b104208SGatien Chevallier 			      SHIFT_U32(sec, DT_RISAF_SEC_SHIFT) |
5271b104208SGatien Chevallier 			      SHIFT_U32(enc, DT_RISAF_ENC_SHIFT + 1) |
5281b104208SGatien Chevallier 			      SHIFT_U32(priv, DT_RISAF_PRIV_SHIFT) |
5291b104208SGatien Chevallier 			      SHIFT_U32(rden, DT_RISAF_READ_SHIFT) |
5301b104208SGatien Chevallier 			      SHIFT_U32(wren, DT_RISAF_WRITE_SHIFT);
5311b104208SGatien Chevallier 		start_addr = io_read32(base + _RISAF_REG_STARTR(id));
5321b104208SGatien Chevallier 		end_addr = io_read32(base + _RISAF_REG_ENDR(id));
5331b104208SGatien Chevallier 		region->addr = start_addr + risaf->pdata.mem_base;
5341b104208SGatien Chevallier 		region->len = end_addr - start_addr + 1;
5351b104208SGatien Chevallier 	}
5361b104208SGatien Chevallier 
5371b104208SGatien Chevallier 	return TEE_SUCCESS;
5381b104208SGatien Chevallier }
5391b104208SGatien Chevallier 
5401b104208SGatien Chevallier static TEE_Result
stm32_risaf_pm(enum pm_op op,unsigned int pm_hint,const struct pm_callback_handle * pm_handle)5411b104208SGatien Chevallier stm32_risaf_pm(enum pm_op op, unsigned int pm_hint,
5421b104208SGatien Chevallier 	       const struct pm_callback_handle *pm_handle)
5431b104208SGatien Chevallier {
5441b104208SGatien Chevallier 	struct stm32_risaf_instance *risaf = pm_handle->handle;
5451b104208SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
5461b104208SGatien Chevallier 
5471b104208SGatien Chevallier 	assert(risaf);
5481b104208SGatien Chevallier 
5491b104208SGatien Chevallier 	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
5501b104208SGatien Chevallier 		return TEE_SUCCESS;
5511b104208SGatien Chevallier 
5521b104208SGatien Chevallier 	if (op == PM_OP_RESUME)
5531b104208SGatien Chevallier 		res = stm32_risaf_pm_resume(risaf);
5541b104208SGatien Chevallier 	else
5551b104208SGatien Chevallier 		res = stm32_risaf_pm_suspend(risaf);
5561b104208SGatien Chevallier 
5571b104208SGatien Chevallier 	return res;
5581b104208SGatien Chevallier }
5591b104208SGatien Chevallier 
stm32_risaf_acquire_access(struct firewall_query * fw,paddr_t paddr,size_t size,bool read,bool write)560*e78e87a9SGatien Chevallier static TEE_Result stm32_risaf_acquire_access(struct firewall_query *fw,
561*e78e87a9SGatien Chevallier 					     paddr_t paddr, size_t size,
562*e78e87a9SGatien Chevallier 					     bool read, bool write)
563*e78e87a9SGatien Chevallier {
564*e78e87a9SGatien Chevallier 	struct stm32_risaf_instance *risaf = NULL;
565*e78e87a9SGatien Chevallier 	struct stm32_risaf_region *region = NULL;
566*e78e87a9SGatien Chevallier 	uint32_t cidcfgr = 0;
567*e78e87a9SGatien Chevallier 	unsigned int i = 0;
568*e78e87a9SGatien Chevallier 	uint32_t cfgr = 0;
569*e78e87a9SGatien Chevallier 	vaddr_t base = 0;
570*e78e87a9SGatien Chevallier 	uint32_t id = 0;
571*e78e87a9SGatien Chevallier 
572*e78e87a9SGatien Chevallier 	assert(fw->ctrl->priv && (read || write));
573*e78e87a9SGatien Chevallier 
574*e78e87a9SGatien Chevallier 	if (paddr == TZDRAM_BASE && size == TZDRAM_SIZE)
575*e78e87a9SGatien Chevallier 		return TEE_SUCCESS;
576*e78e87a9SGatien Chevallier 
577*e78e87a9SGatien Chevallier 	risaf = fw->ctrl->priv;
578*e78e87a9SGatien Chevallier 	base = risaf_base(risaf);
579*e78e87a9SGatien Chevallier 
580*e78e87a9SGatien Chevallier 	if (fw->arg_count != 1)
581*e78e87a9SGatien Chevallier 		return TEE_ERROR_BAD_PARAMETERS;
582*e78e87a9SGatien Chevallier 
583*e78e87a9SGatien Chevallier 	/*
584*e78e87a9SGatien Chevallier 	 * RISAF region configuration, we assume the query is as
585*e78e87a9SGatien Chevallier 	 * follows:
586*e78e87a9SGatien Chevallier 	 * firewall->args[0]: Region configuration
587*e78e87a9SGatien Chevallier 	 */
588*e78e87a9SGatien Chevallier 	id = _RISAF_GET_REGION_ID(fw->args[0]);
589*e78e87a9SGatien Chevallier 
590*e78e87a9SGatien Chevallier 	if (!id || id >= risaf->pdata.nregions)
591*e78e87a9SGatien Chevallier 		return TEE_ERROR_BAD_PARAMETERS;
592*e78e87a9SGatien Chevallier 
593*e78e87a9SGatien Chevallier 	for (i = 0; i < risaf->pdata.nregions; i++) {
594*e78e87a9SGatien Chevallier 		if (id == _RISAF_GET_REGION_ID(risaf->pdata.regions[i].cfg)) {
595*e78e87a9SGatien Chevallier 			region = &risaf->pdata.regions[i];
596*e78e87a9SGatien Chevallier 			if (region->addr != paddr || region->len != size)
597*e78e87a9SGatien Chevallier 				return TEE_ERROR_GENERIC;
598*e78e87a9SGatien Chevallier 			break;
599*e78e87a9SGatien Chevallier 		}
600*e78e87a9SGatien Chevallier 	}
601*e78e87a9SGatien Chevallier 	if (!region)
602*e78e87a9SGatien Chevallier 		return TEE_ERROR_ITEM_NOT_FOUND;
603*e78e87a9SGatien Chevallier 
604*e78e87a9SGatien Chevallier 	cfgr = io_read32(base + _RISAF_REG_CFGR(id));
605*e78e87a9SGatien Chevallier 	cidcfgr = io_read32(base + _RISAF_REG_CIDCFGR(id));
606*e78e87a9SGatien Chevallier 
607*e78e87a9SGatien Chevallier 	/*
608*e78e87a9SGatien Chevallier 	 * Access is denied if the region is disabled and OP-TEE does not run as
609*e78e87a9SGatien Chevallier 	 * TDCID, or the region is not secure, or if it is not accessible in
610*e78e87a9SGatien Chevallier 	 * read and/or write mode, if requested, by OP-TEE CID.
611*e78e87a9SGatien Chevallier 	 */
612*e78e87a9SGatien Chevallier 	if (!(cfgr & _RISAF_REG_CFGR_BREN) && !is_tdcid)
613*e78e87a9SGatien Chevallier 		return TEE_ERROR_ACCESS_DENIED;
614*e78e87a9SGatien Chevallier 
615*e78e87a9SGatien Chevallier 	if ((cfgr & _RISAF_REG_CFGR_BREN) &&
616*e78e87a9SGatien Chevallier 	    (!(cfgr & _RISAF_REG_CFGR_SEC) ||
617*e78e87a9SGatien Chevallier 	     (read && !_RISAF_REG_READ_OK(cidcfgr, RIF_CID1)) ||
618*e78e87a9SGatien Chevallier 	     (write && !_RISAF_REG_WRITE_OK(cidcfgr, RIF_CID1)))) {
619*e78e87a9SGatien Chevallier 		return TEE_ERROR_ACCESS_DENIED;
620*e78e87a9SGatien Chevallier 	}
621*e78e87a9SGatien Chevallier 
622*e78e87a9SGatien Chevallier 	return TEE_SUCCESS;
623*e78e87a9SGatien Chevallier }
624*e78e87a9SGatien Chevallier 
stm32_risaf_reconfigure_region(struct firewall_query * fw,paddr_t paddr,size_t size)625*e78e87a9SGatien Chevallier static TEE_Result stm32_risaf_reconfigure_region(struct firewall_query *fw,
626*e78e87a9SGatien Chevallier 						 paddr_t paddr, size_t size)
627*e78e87a9SGatien Chevallier {
628*e78e87a9SGatien Chevallier 	struct stm32_risaf_instance *risaf = NULL;
629*e78e87a9SGatien Chevallier 	struct stm32_risaf_region *region = NULL;
630*e78e87a9SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
631*e78e87a9SGatien Chevallier 	uint32_t exceptions = 0;
632*e78e87a9SGatien Chevallier 	uint32_t q_cfg = 0;
633*e78e87a9SGatien Chevallier 	unsigned int i = 0;
634*e78e87a9SGatien Chevallier 	uint32_t id = 0;
635*e78e87a9SGatien Chevallier 
636*e78e87a9SGatien Chevallier 	assert(fw->ctrl->priv);
637*e78e87a9SGatien Chevallier 
638*e78e87a9SGatien Chevallier 	risaf = fw->ctrl->priv;
639*e78e87a9SGatien Chevallier 
640*e78e87a9SGatien Chevallier 	if (fw->arg_count != 1)
641*e78e87a9SGatien Chevallier 		return TEE_ERROR_BAD_PARAMETERS;
642*e78e87a9SGatien Chevallier 
643*e78e87a9SGatien Chevallier 	/*
644*e78e87a9SGatien Chevallier 	 * RISAF region configuration, we assume the query is as
645*e78e87a9SGatien Chevallier 	 * follows:
646*e78e87a9SGatien Chevallier 	 * firewall->args[0]: Region configuration
647*e78e87a9SGatien Chevallier 	 */
648*e78e87a9SGatien Chevallier 	q_cfg = fw->args[0];
649*e78e87a9SGatien Chevallier 	id = _RISAF_GET_REGION_ID(q_cfg);
650*e78e87a9SGatien Chevallier 
651*e78e87a9SGatien Chevallier 	if (!id || id >= risaf->pdata.nregions)
652*e78e87a9SGatien Chevallier 		return TEE_ERROR_BAD_PARAMETERS;
653*e78e87a9SGatien Chevallier 
654*e78e87a9SGatien Chevallier 	for (i = 0; i < risaf->pdata.nregions; i++) {
655*e78e87a9SGatien Chevallier 		if (id == _RISAF_GET_REGION_ID(risaf->pdata.regions[i].cfg)) {
656*e78e87a9SGatien Chevallier 			region = &risaf->pdata.regions[i];
657*e78e87a9SGatien Chevallier 			if (region->addr != paddr || region->len != size)
658*e78e87a9SGatien Chevallier 				return TEE_ERROR_GENERIC;
659*e78e87a9SGatien Chevallier 			break;
660*e78e87a9SGatien Chevallier 		}
661*e78e87a9SGatien Chevallier 	}
662*e78e87a9SGatien Chevallier 	if (!region)
663*e78e87a9SGatien Chevallier 		return TEE_ERROR_ITEM_NOT_FOUND;
664*e78e87a9SGatien Chevallier 
665*e78e87a9SGatien Chevallier 	DMSG("Reconfiguring %s region ID: %"PRIu32, risaf->pdata.risaf_name,
666*e78e87a9SGatien Chevallier 	     id);
667*e78e87a9SGatien Chevallier 
668*e78e87a9SGatien Chevallier 	exceptions = cpu_spin_lock_xsave(&risaf->pdata.conf_lock);
669*e78e87a9SGatien Chevallier 	res = risaf_configure_region(risaf, id,
670*e78e87a9SGatien Chevallier 				     stm32_risaf_get_region_config(q_cfg),
671*e78e87a9SGatien Chevallier 				     stm32_risaf_get_region_cid_config(q_cfg),
672*e78e87a9SGatien Chevallier 				     region->addr,
673*e78e87a9SGatien Chevallier 				     region->addr + region->len - 1);
674*e78e87a9SGatien Chevallier 
675*e78e87a9SGatien Chevallier 	cpu_spin_unlock_xrestore(&risaf->pdata.conf_lock, exceptions);
676*e78e87a9SGatien Chevallier 
677*e78e87a9SGatien Chevallier 	return res;
678*e78e87a9SGatien Chevallier }
679*e78e87a9SGatien Chevallier 
680*e78e87a9SGatien Chevallier static const struct firewall_controller_ops firewall_ops = {
681*e78e87a9SGatien Chevallier 	.acquire_memory_access = stm32_risaf_acquire_access,
682*e78e87a9SGatien Chevallier 	.set_memory_conf = stm32_risaf_reconfigure_region,
683*e78e87a9SGatien Chevallier };
684*e78e87a9SGatien Chevallier 
stm32_risaf_probe(const void * fdt,int node,const void * compat_data)6851b104208SGatien Chevallier static TEE_Result stm32_risaf_probe(const void *fdt, int node,
6861b104208SGatien Chevallier 				    const void *compat_data)
6871b104208SGatien Chevallier {
6881b104208SGatien Chevallier 	const struct stm32_risaf_compat_data *compat = compat_data;
689*e78e87a9SGatien Chevallier 	struct firewall_controller *controller = NULL;
6901b104208SGatien Chevallier 	struct stm32_risaf_instance *risaf = NULL;
6911b104208SGatien Chevallier 	struct stm32_risaf_region *regions = NULL;
6921b104208SGatien Chevallier 	TEE_Result res = TEE_ERROR_GENERIC;
6931b104208SGatien Chevallier 	struct dt_node_info dt_info = { };
6941b104208SGatien Chevallier 	const fdt32_t *conf_list = NULL;
6951b104208SGatien Chevallier 	const fdt64_t *cuint = NULL;
6961b104208SGatien Chevallier 	unsigned int nregions = 0;
6971b104208SGatien Chevallier 	unsigned int i = 0;
6981b104208SGatien Chevallier 	int len = 0;
6991b104208SGatien Chevallier 
7001b104208SGatien Chevallier 	res = stm32_rifsc_check_tdcid(&is_tdcid);
7011b104208SGatien Chevallier 	if (res)
7021b104208SGatien Chevallier 		return res;
7031b104208SGatien Chevallier 
7041b104208SGatien Chevallier 	if (!is_tdcid)
7051b104208SGatien Chevallier 		return TEE_SUCCESS;
7061b104208SGatien Chevallier 
7071b104208SGatien Chevallier 	risaf = calloc(1, sizeof(*risaf));
7081b104208SGatien Chevallier 	if (!risaf)
7091b104208SGatien Chevallier 		return TEE_ERROR_OUT_OF_MEMORY;
7101b104208SGatien Chevallier 
7111b104208SGatien Chevallier 	fdt_fill_device_info(fdt, &dt_info, node);
7121b104208SGatien Chevallier 	if (dt_info.reg == DT_INFO_INVALID_REG ||
7131b104208SGatien Chevallier 	    dt_info.reg_size == DT_INFO_INVALID_REG_SIZE) {
7141b104208SGatien Chevallier 		free(risaf);
7151b104208SGatien Chevallier 		return TEE_ERROR_BAD_PARAMETERS;
7161b104208SGatien Chevallier 	}
7171b104208SGatien Chevallier 
7181b104208SGatien Chevallier 	risaf->pdata.base.pa = dt_info.reg;
7191b104208SGatien Chevallier 	io_pa_or_va_secure(&risaf->pdata.base, dt_info.reg_size);
7201b104208SGatien Chevallier 
7211b104208SGatien Chevallier 	risaf->pdata.enc_supported = compat->supported_encryption;
7221b104208SGatien Chevallier 
7231b104208SGatien Chevallier 	res = clk_dt_get_by_index(fdt, node, 0, &risaf->pdata.clock);
7241b104208SGatien Chevallier 	if (!risaf->pdata.clock)
7251b104208SGatien Chevallier 		goto err;
7261b104208SGatien Chevallier 
7271b104208SGatien Chevallier 	conf_list = fdt_getprop(fdt, node, "memory-region", &len);
7281b104208SGatien Chevallier 	if (!conf_list) {
7291b104208SGatien Chevallier 		DMSG("RISAF %#"PRIxPA": No configuration in DT, use default",
7301b104208SGatien Chevallier 		     risaf->pdata.base.pa);
7311b104208SGatien Chevallier 		free(risaf);
7321b104208SGatien Chevallier 		return TEE_SUCCESS;
7331b104208SGatien Chevallier 	}
7341b104208SGatien Chevallier 
7351b104208SGatien Chevallier 	nregions = (unsigned int)len / sizeof(uint32_t);
7361b104208SGatien Chevallier 
7371b104208SGatien Chevallier 	/* Silently allow unexpected truncated names */
7381b104208SGatien Chevallier 	strncpy(risaf->pdata.risaf_name, fdt_get_name(fdt, node, NULL),
7391b104208SGatien Chevallier 		sizeof(risaf->pdata.risaf_name) - 1);
7401b104208SGatien Chevallier 
7411b104208SGatien Chevallier 	res = clk_enable(risaf->pdata.clock);
7421b104208SGatien Chevallier 	if (res)
7431b104208SGatien Chevallier 		goto err;
7441b104208SGatien Chevallier 
7451b104208SGatien Chevallier 	res = stm32_risaf_init_ddata(risaf);
7461b104208SGatien Chevallier 	if (res)
7471b104208SGatien Chevallier 		goto err_clk;
7481b104208SGatien Chevallier 
7491b104208SGatien Chevallier 	risaf_print_version(risaf);
7501b104208SGatien Chevallier 
7511b104208SGatien Chevallier 	cuint = fdt_getprop(fdt, node, "st,mem-map", &len);
7521b104208SGatien Chevallier 	if (!cuint || (size_t)len != sizeof(*cuint) * 2)
7531b104208SGatien Chevallier 		panic();
7541b104208SGatien Chevallier 
7551b104208SGatien Chevallier 	risaf->pdata.mem_base = (paddr_t)fdt64_to_cpu(*cuint);
7561b104208SGatien Chevallier 	risaf->pdata.mem_size = (size_t)fdt64_to_cpu(*(cuint + 1));
7571b104208SGatien Chevallier 
7581b104208SGatien Chevallier 	regions = calloc(nregions, sizeof(*regions));
7591b104208SGatien Chevallier 	if (nregions && !regions) {
7601b104208SGatien Chevallier 		res = TEE_ERROR_OUT_OF_MEMORY;
7611b104208SGatien Chevallier 		goto err_ddata;
7621b104208SGatien Chevallier 	}
7631b104208SGatien Chevallier 
7641b104208SGatien Chevallier 	DMSG("RISAF %#"PRIxPA" memory range: %#"PRIxPA" - %#"PRIxPA,
7651b104208SGatien Chevallier 	     risaf->pdata.base.pa, risaf->pdata.mem_base,
7661b104208SGatien Chevallier 	     risaf->pdata.mem_base + risaf->pdata.mem_size - 1);
7671b104208SGatien Chevallier 
7681b104208SGatien Chevallier 	for (i = 0; i < nregions; i++) {
7691b104208SGatien Chevallier 		const fdt32_t *prop = NULL;
7701b104208SGatien Chevallier 		paddr_t start_addr = 0;
7711b104208SGatien Chevallier 		paddr_t end_addr = 0;
7721b104208SGatien Chevallier 		uint32_t cid_cfg = 0;
7731b104208SGatien Chevallier 		uint32_t phandle = 0;
7741b104208SGatien Chevallier 		uint32_t cfg = 0;
7751b104208SGatien Chevallier 		uint32_t id = 0;
7761b104208SGatien Chevallier 		int pnode = 0;
7771b104208SGatien Chevallier 
7781b104208SGatien Chevallier 		phandle = fdt32_to_cpu(*(conf_list + i));
7791b104208SGatien Chevallier 		pnode = fdt_node_offset_by_phandle(fdt, phandle);
7801b104208SGatien Chevallier 		if (pnode < 0)
7811b104208SGatien Chevallier 			continue;
7821b104208SGatien Chevallier 
7836a0116edSEtienne Carriere 		if (fdt_reg_info(fdt, pnode, &regions[i].addr,
7846a0116edSEtienne Carriere 				 &regions[i].len)) {
7856a0116edSEtienne Carriere 			EMSG("Invalid config in node %s",
7866a0116edSEtienne Carriere 			     fdt_get_name(fdt, pnode, NULL));
7876a0116edSEtienne Carriere 			panic();
7886a0116edSEtienne Carriere 		}
7891b104208SGatien Chevallier 
7901b104208SGatien Chevallier 		if (!regions[i].len)
7911b104208SGatien Chevallier 			continue;
7921b104208SGatien Chevallier 
7931b104208SGatien Chevallier 		/*
7941b104208SGatien Chevallier 		 * The secure bootloader is in charge of configuring RISAF
7951b104208SGatien Chevallier 		 * related to OP-TEE secure memory. Therefore, skip OP-TEE
7961b104208SGatien Chevallier 		 * region so that RISAF configuration cannot interfere with
7971b104208SGatien Chevallier 		 * OP-TEE execution flow.
7981b104208SGatien Chevallier 		 */
7991b104208SGatien Chevallier 		if (regions[i].addr == TZDRAM_BASE &&
8001b104208SGatien Chevallier 		    regions[i].len == TZDRAM_SIZE) {
8011b104208SGatien Chevallier 			continue;
8021b104208SGatien Chevallier 		}
8031b104208SGatien Chevallier 
8041b104208SGatien Chevallier 		prop = fdt_getprop(fdt, pnode, "st,protreg", NULL);
8051b104208SGatien Chevallier 		if (!prop)
8061b104208SGatien Chevallier 			continue;
8071b104208SGatien Chevallier 
8081b104208SGatien Chevallier 		regions[i].cfg = fdt32_to_cpu(*prop);
8091b104208SGatien Chevallier 
8101b104208SGatien Chevallier 		if (risaf_check_region_boundaries(risaf, &regions[i]) ||
8111b104208SGatien Chevallier 		    risaf_check_overlap(risaf, regions, i))
8121b104208SGatien Chevallier 			panic();
8131b104208SGatien Chevallier 
8141b104208SGatien Chevallier 		id = _RISAF_GET_REGION_ID(regions[i].cfg);
8151b104208SGatien Chevallier 		assert(id < risaf->ddata->max_base_regions);
8161b104208SGatien Chevallier 
8171b104208SGatien Chevallier 		cfg = stm32_risaf_get_region_config(regions[i].cfg);
8181b104208SGatien Chevallier 
8191b104208SGatien Chevallier 		cid_cfg = stm32_risaf_get_region_cid_config(regions[i].cfg);
8201b104208SGatien Chevallier 
8211b104208SGatien Chevallier 		start_addr = regions[i].addr;
8221b104208SGatien Chevallier 		end_addr = start_addr + regions[i].len - 1U;
8231b104208SGatien Chevallier 
8241b104208SGatien Chevallier 		if (risaf_configure_region(risaf, id, cfg, cid_cfg,
8251b104208SGatien Chevallier 					   start_addr, end_addr))
8261b104208SGatien Chevallier 			panic();
8271b104208SGatien Chevallier 	}
8281b104208SGatien Chevallier 
829*e78e87a9SGatien Chevallier 	controller = calloc(1, sizeof(*controller));
830*e78e87a9SGatien Chevallier 	if (!controller)
831*e78e87a9SGatien Chevallier 		panic();
832*e78e87a9SGatien Chevallier 
833*e78e87a9SGatien Chevallier 	controller->base = &risaf->pdata.base;
834*e78e87a9SGatien Chevallier 	controller->name = risaf->pdata.risaf_name;
835*e78e87a9SGatien Chevallier 	controller->priv = risaf;
836*e78e87a9SGatien Chevallier 	controller->ops = &firewall_ops;
837*e78e87a9SGatien Chevallier 
8381b104208SGatien Chevallier 	risaf->pdata.regions = regions;
8391b104208SGatien Chevallier 	risaf->pdata.nregions = nregions;
8401b104208SGatien Chevallier 
8411b104208SGatien Chevallier 	SLIST_INSERT_HEAD(&risaf_list, risaf, link);
8421b104208SGatien Chevallier 
843*e78e87a9SGatien Chevallier 	res = firewall_dt_controller_register(fdt, node, controller);
844*e78e87a9SGatien Chevallier 	if (res)
845*e78e87a9SGatien Chevallier 		panic();
846*e78e87a9SGatien Chevallier 
8471b104208SGatien Chevallier 	register_pm_core_service_cb(stm32_risaf_pm, risaf, "stm32-risaf");
8481b104208SGatien Chevallier 
8491b104208SGatien Chevallier 	return TEE_SUCCESS;
8501b104208SGatien Chevallier 
8511b104208SGatien Chevallier err_ddata:
8521b104208SGatien Chevallier 	free(risaf->ddata);
8531b104208SGatien Chevallier err_clk:
8541b104208SGatien Chevallier 	clk_disable(risaf->pdata.clock);
8551b104208SGatien Chevallier err:
8561b104208SGatien Chevallier 	free(risaf);
8571b104208SGatien Chevallier 	return res;
8581b104208SGatien Chevallier }
8591b104208SGatien Chevallier 
8601b104208SGatien Chevallier static const struct dt_device_match risaf_match_table[] = {
8611b104208SGatien Chevallier 	{
8621b104208SGatien Chevallier 		.compatible = "st,stm32mp25-risaf",
8631b104208SGatien Chevallier 		.compat_data = &stm32_risaf_compat,
8641b104208SGatien Chevallier 	},
8651b104208SGatien Chevallier 	{
8661b104208SGatien Chevallier 		.compatible = "st,stm32mp25-risaf-enc",
8671b104208SGatien Chevallier 		.compat_data = &stm32_risaf_enc_compat,
8681b104208SGatien Chevallier 	},
8691b104208SGatien Chevallier 	{ }
8701b104208SGatien Chevallier };
8711b104208SGatien Chevallier 
8721b104208SGatien Chevallier DEFINE_DT_DRIVER(risaf_dt_driver) = {
8731b104208SGatien Chevallier 	.name = "stm32-risaf",
8741b104208SGatien Chevallier 	.match_table = risaf_match_table,
8751b104208SGatien Chevallier 	.probe = stm32_risaf_probe,
8761b104208SGatien Chevallier };
877