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