xref: /rk3399_ARM-atf/plat/mediatek/drivers/iommu/mtk_iommu_smc.c (revision 5fb5ff5694c1bcf0ddfc972600b69d7494ca6645)
1be457248SChengci Xu /*
298415e1aSChengci.Xu  * Copyright (c) 2022-2023, MediaTek Inc. All rights reserved.
3be457248SChengci Xu  *
4be457248SChengci Xu  * SPDX-License-Identifier: BSD-3-Clause
5be457248SChengci Xu  */
6be457248SChengci Xu 
7be457248SChengci Xu #include <stddef.h>
8*5fb5ff56Skiwi liu #include <mtk_iommu_priv.h>
9be457248SChengci Xu 
10be457248SChengci Xu /* defination */
11be457248SChengci Xu /* smi larb */
12be457248SChengci Xu #define SMI_LARB_NON_SEC_CON(port)	(0x380 + ((port) << 2))
13be457248SChengci Xu #define PATH_SEL_MASK			(0xf0000) /* to sram (INT) */
14be457248SChengci Xu #define SMI_LARB_SEC_CON_INT(port)	(0xf00 + ((port) << 2))
15be457248SChengci Xu #define SMI_LARB_SEC_CON(port)		(0xf80 + ((port) << 2))
16be457248SChengci Xu #define MMU_MASK			BIT(0)
17be457248SChengci Xu #define MMU_EN(en)			((!!(en)) << 0)
18be457248SChengci Xu #define SEC_MASK			BIT(1)
19be457248SChengci Xu #define SEC_EN(en)			((!!(en)) << 1)
20be457248SChengci Xu #define DOMAIN_MASK			(0x1f << 4)
21be457248SChengci Xu #define SMI_MMU_EN(port)		(0x1 << (port))
22be457248SChengci Xu 
23be457248SChengci Xu /* infra master */
24be457248SChengci Xu #define IFR_CFG_MMU_EN_MSK(r_bit)	(0x3 << (r_bit))
25be457248SChengci Xu 
26*5fb5ff56Skiwi liu /* secure iommu */
27*5fb5ff56Skiwi liu #define MMU_INT_CONTROL0		(0x120)
28*5fb5ff56Skiwi liu #define INT_CLR				BIT(12)
29*5fb5ff56Skiwi liu #define MMU_FAULT_ST1			(0x134)
30*5fb5ff56Skiwi liu #define MMU_AXI_0_ERR_MASK		GENMASK(6, 0)
31*5fb5ff56Skiwi liu #define MMU_AXI_FAULT_STATUS(bus)	(0x13c + (bus) * 8)
32*5fb5ff56Skiwi liu #define MMU_AXI_INVLD_PA(bus)		(0x140 + (bus) * 8)
33*5fb5ff56Skiwi liu #define MMU_AXI_INT_ID(bus)		(0x150 + (bus) * 4)
34*5fb5ff56Skiwi liu 
35be457248SChengci Xu /* smi larb configure */
36be457248SChengci Xu /*
37be457248SChengci Xu  * If multimedia security config is enabled, the SMI config register must be
38be457248SChengci Xu  * configurated in security world.
39be457248SChengci Xu  * And the SRAM path is also configurated here to enhance security.
40be457248SChengci Xu  */
41*5fb5ff56Skiwi liu #ifdef ATF_MTK_SMI_LARB_CFG_SUPPORT
42*5fb5ff56Skiwi liu 
43be457248SChengci Xu static void mtk_smi_larb_port_config_to_sram(
44be457248SChengci Xu 				const struct mtk_smi_larb_config *larb,
45be457248SChengci Xu 				uint32_t port_id)
46be457248SChengci Xu {
47be457248SChengci Xu 	mmio_clrbits_32(larb->base + SMI_LARB_SEC_CON_INT(port_id),
48be457248SChengci Xu 			MMU_MASK | SEC_MASK | DOMAIN_MASK);
49be457248SChengci Xu 
50be457248SChengci Xu 	mmio_setbits_32(larb->base + SMI_LARB_NON_SEC_CON(port_id),
51be457248SChengci Xu 			PATH_SEL_MASK);
52be457248SChengci Xu }
53be457248SChengci Xu 
54be457248SChengci Xu static void mtk_smi_port_config(const struct mtk_smi_larb_config *larb,
55be457248SChengci Xu 				uint32_t port_id, uint8_t mmu_en, uint8_t sec_en)
56be457248SChengci Xu {
57be457248SChengci Xu 	mmio_clrsetbits_32(larb->base + SMI_LARB_SEC_CON(port_id),
58be457248SChengci Xu 			   MMU_MASK | SEC_MASK | DOMAIN_MASK,
59be457248SChengci Xu 			   MMU_EN(mmu_en) | SEC_EN(sec_en));
60be457248SChengci Xu }
61be457248SChengci Xu 
62be457248SChengci Xu static int mtk_smi_larb_port_config_sec(uint32_t larb_id, uint32_t mmu_en_msk)
63be457248SChengci Xu {
64be457248SChengci Xu 	uint32_t port_id, port_nr;
65be457248SChengci Xu 	const struct mtk_smi_larb_config *larb;
66be457248SChengci Xu 	uint32_t to_sram;
67be457248SChengci Xu 	uint8_t mmu_en;
68be457248SChengci Xu 
69*5fb5ff56Skiwi liu 	if (larb_id >= g_larb_num) {
70be457248SChengci Xu 		return MTK_SIP_E_INVALID_PARAM;
71be457248SChengci Xu 	}
72be457248SChengci Xu 
73be457248SChengci Xu 	larb = &g_larb_cfg[larb_id];
74be457248SChengci Xu 	port_nr = larb->port_nr;
75be457248SChengci Xu 	to_sram = larb->to_sram;
76be457248SChengci Xu 
77be457248SChengci Xu 	for (port_id = 0; port_id < port_nr; port_id++) {
78be457248SChengci Xu 		if ((to_sram & BIT(port_id)) > 0U) {
79be457248SChengci Xu 			mtk_smi_larb_port_config_to_sram(larb, port_id);
80be457248SChengci Xu 			continue;
81be457248SChengci Xu 		}
82be457248SChengci Xu 		mmu_en = !!(mmu_en_msk & SMI_MMU_EN(port_id));
83be457248SChengci Xu 		mtk_smi_port_config(larb, port_id, mmu_en, 0);
84be457248SChengci Xu 	}
85be457248SChengci Xu 
86be457248SChengci Xu 	return MTK_SIP_E_SUCCESS;
87be457248SChengci Xu }
88be457248SChengci Xu 
89*5fb5ff56Skiwi liu #endif /* ATF_MTK_SMI_LARB_CFG_SUPPORT */
90*5fb5ff56Skiwi liu 
91*5fb5ff56Skiwi liu /* infra iommu configure */
92*5fb5ff56Skiwi liu #ifdef ATF_MTK_INFRA_MASTER_CFG_SUPPORT
93*5fb5ff56Skiwi liu 
9498415e1aSChengci.Xu static int mtk_infra_master_config_sec(uint32_t dev_id_msk, uint32_t enable)
95be457248SChengci Xu {
96be457248SChengci Xu 	const struct mtk_ifr_mst_config *ifr_cfg;
9798415e1aSChengci.Xu 	uint32_t dev_id, reg_addr, reg_mask;
98be457248SChengci Xu 
99be457248SChengci Xu 	mtk_infra_iommu_enable_protect();
100be457248SChengci Xu 
101*5fb5ff56Skiwi liu 	if (dev_id_msk >= BIT(g_ifr_mst_num)) {
10298415e1aSChengci.Xu 		return MTK_SIP_E_INVALID_PARAM;
10398415e1aSChengci.Xu 	}
10498415e1aSChengci.Xu 
105*5fb5ff56Skiwi liu 	for (dev_id = 0U; dev_id < g_ifr_mst_num; dev_id++) {
10698415e1aSChengci.Xu 		if ((dev_id_msk & BIT(dev_id)) == 0U) {
10798415e1aSChengci.Xu 			continue;
108be457248SChengci Xu 		}
109be457248SChengci Xu 
110be457248SChengci Xu 		ifr_cfg = &g_ifr_mst_cfg[dev_id];
111be457248SChengci Xu 		reg_addr = g_ifr_mst_cfg_base[(ifr_cfg->cfg_addr_idx)] +
112be457248SChengci Xu 			   g_ifr_mst_cfg_offs[(ifr_cfg->cfg_addr_idx)];
11398415e1aSChengci.Xu 		reg_mask = IFR_CFG_MMU_EN_MSK(ifr_cfg->r_mmu_en_bit);
114be457248SChengci Xu 
115be457248SChengci Xu 		if (enable > 0U) {
11698415e1aSChengci.Xu 			mmio_setbits_32(reg_addr, reg_mask);
117be457248SChengci Xu 		} else {
11898415e1aSChengci.Xu 			mmio_clrbits_32(reg_addr, reg_mask);
11998415e1aSChengci.Xu 		}
120be457248SChengci Xu 	}
121be457248SChengci Xu 
122be457248SChengci Xu 	return MTK_SIP_E_SUCCESS;
123be457248SChengci Xu }
124*5fb5ff56Skiwi liu #endif /* ATF_MTK_INFRA_MASTER_CFG_SUPPORT */
125be457248SChengci Xu 
126*5fb5ff56Skiwi liu /* secure iommu */
127*5fb5ff56Skiwi liu #ifdef ATF_MTK_IOMMU_CFG_SUPPORT
128*5fb5ff56Skiwi liu /* Report secure IOMMU fault status to normal world for the debug version */
129*5fb5ff56Skiwi liu static int mtk_secure_iommu_fault_report(uint32_t sec_mmu_base,
130*5fb5ff56Skiwi liu 					 uint32_t *f_sta, uint32_t *f_pa,
131*5fb5ff56Skiwi liu 					 uint32_t *f_id)
132*5fb5ff56Skiwi liu {
133*5fb5ff56Skiwi liu 	const struct mtk_secure_iommu_config *mmu_cfg = NULL;
134*5fb5ff56Skiwi liu 	uint32_t __maybe_unused bus_id, fault_type;
135*5fb5ff56Skiwi liu 	uint32_t i;
136*5fb5ff56Skiwi liu 	int ret = MTK_SIP_E_NOT_SUPPORTED;
137*5fb5ff56Skiwi liu 
138*5fb5ff56Skiwi liu 	for (i = 0; i < g_sec_iommu_num; i++) {
139*5fb5ff56Skiwi liu 		if (g_sec_iommu_cfg[i].base == sec_mmu_base) {
140*5fb5ff56Skiwi liu 			mmu_cfg = &g_sec_iommu_cfg[i];
141*5fb5ff56Skiwi liu 			break;
142*5fb5ff56Skiwi liu 		}
143*5fb5ff56Skiwi liu 	}
144*5fb5ff56Skiwi liu 
145*5fb5ff56Skiwi liu 	if (!mmu_cfg)
146*5fb5ff56Skiwi liu 		return MTK_SIP_E_INVALID_PARAM;
147*5fb5ff56Skiwi liu #if DEBUG
148*5fb5ff56Skiwi liu 	fault_type = mmio_read_32(mmu_cfg->base + MMU_FAULT_ST1);
149*5fb5ff56Skiwi liu 	bus_id = (fault_type & MMU_AXI_0_ERR_MASK) ? 0 : 1;
150*5fb5ff56Skiwi liu 
151*5fb5ff56Skiwi liu 	if (f_sta)
152*5fb5ff56Skiwi liu 		*f_sta = mmio_read_32(mmu_cfg->base + MMU_AXI_FAULT_STATUS(bus_id));
153*5fb5ff56Skiwi liu 	if (f_pa)
154*5fb5ff56Skiwi liu 		*f_pa = mmio_read_32(mmu_cfg->base + MMU_AXI_INVLD_PA(bus_id));
155*5fb5ff56Skiwi liu 	if (f_id)
156*5fb5ff56Skiwi liu 		*f_id = mmio_read_32(mmu_cfg->base + MMU_AXI_INT_ID(bus_id));
157*5fb5ff56Skiwi liu 	ret = MTK_SIP_E_SUCCESS;
158*5fb5ff56Skiwi liu #endif
159*5fb5ff56Skiwi liu 	mmio_setbits_32(mmu_cfg->base + MMU_INT_CONTROL0, INT_CLR);
160*5fb5ff56Skiwi liu 
161*5fb5ff56Skiwi liu 	return ret;
162*5fb5ff56Skiwi liu }
163*5fb5ff56Skiwi liu #endif /* ATF_MTK_IOMMU_CFG_SUPPORT */
164*5fb5ff56Skiwi liu 
165*5fb5ff56Skiwi liu u_register_t mtk_iommu_handler(u_register_t x1, u_register_t x2,
166be457248SChengci Xu 			u_register_t x3, u_register_t x4,
167be457248SChengci Xu 			void *handle, struct smccc_res *smccc_ret)
168be457248SChengci Xu {
169be457248SChengci Xu 	uint32_t cmd_id = x1, mdl_id = x2, val = x3;
170be457248SChengci Xu 	int ret = MTK_SIP_E_NOT_SUPPORTED;
171be457248SChengci Xu 
172be457248SChengci Xu 	(void)x4;
173be457248SChengci Xu 	(void)handle;
174be457248SChengci Xu 
175be457248SChengci Xu 	switch (cmd_id) {
176*5fb5ff56Skiwi liu #ifdef ATF_MTK_SMI_LARB_CFG_SUPPORT
177be457248SChengci Xu 	case IOMMU_ATF_CMD_CONFIG_SMI_LARB:
178be457248SChengci Xu 		ret = mtk_smi_larb_port_config_sec(mdl_id, val);
179be457248SChengci Xu 		break;
180*5fb5ff56Skiwi liu #endif
181*5fb5ff56Skiwi liu #ifdef ATF_MTK_INFRA_MASTER_CFG_SUPPORT
182be457248SChengci Xu 	case IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU:
183be457248SChengci Xu 		ret = mtk_infra_master_config_sec(mdl_id, val);
184be457248SChengci Xu 		break;
185*5fb5ff56Skiwi liu #endif
186*5fb5ff56Skiwi liu #ifdef ATF_MTK_IOMMU_CFG_SUPPORT
187*5fb5ff56Skiwi liu 	case IOMMU_ATF_CMD_GET_SECURE_IOMMU_STATUS:
188*5fb5ff56Skiwi liu 		(void)val;
189*5fb5ff56Skiwi liu 		ret = mtk_secure_iommu_fault_report(mdl_id,
190*5fb5ff56Skiwi liu 					(uint32_t *)&smccc_ret->a1,
191*5fb5ff56Skiwi liu 					(uint32_t *)&smccc_ret->a2,
192*5fb5ff56Skiwi liu 					(uint32_t *)&smccc_ret->a3);
193*5fb5ff56Skiwi liu 		break;
194*5fb5ff56Skiwi liu #endif
195be457248SChengci Xu 	default:
196be457248SChengci Xu 		break;
197be457248SChengci Xu 	}
198be457248SChengci Xu 
199be457248SChengci Xu 	return ret;
200be457248SChengci Xu }
201be457248SChengci Xu DECLARE_SMC_HANDLER(MTK_SIP_IOMMU_CONTROL, mtk_iommu_handler);
202