From be457248c6b0a7f3c61bd95af58372938d13decd Mon Sep 17 00:00:00 2001 From: Chengci Xu Date: Wed, 20 Jul 2022 16:20:15 +0800 Subject: [PATCH] feat(mt8188): add IOMMU enable control in SiP service Add SiP service for multimedia & infra master to enable/disable MM & INFRA IOMMU in secure world TEST=build pass BUG=b:236339614 Signed-off-by: Chengci Xu Change-Id: I4eb1fda6044cf2cb6c22c005cb2fa550906b71e9 --- .../drivers/iommu/mt8188/mtk_iommu_plat.c | 99 ++++++++++++++ .../drivers/iommu/mt8188/mtk_iommu_plat.h | 24 ++++ plat/mediatek/drivers/iommu/mtk_iommu_priv.h | 44 ++++++ plat/mediatek/drivers/iommu/mtk_iommu_smc.c | 125 ++++++++++++++++++ plat/mediatek/drivers/iommu/rules.mk | 17 +++ plat/mediatek/include/mt8188/platform_def.h | 37 ++++++ plat/mediatek/include/mtk_sip_def.h | 1 + plat/mediatek/mt8188/platform.mk | 1 + 8 files changed, 348 insertions(+) create mode 100644 plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c create mode 100644 plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h create mode 100644 plat/mediatek/drivers/iommu/mtk_iommu_priv.h create mode 100644 plat/mediatek/drivers/iommu/mtk_iommu_smc.c create mode 100644 plat/mediatek/drivers/iommu/rules.mk diff --git a/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c new file mode 100644 index 000000000..1d6863ff5 --- /dev/null +++ b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* mm iommu */ +#define SMI_L0_ID (0) +#define SMI_L1_ID (1) +#define SMI_L2_ID (2) +#define SMI_L3_ID (3) +#define SMI_L4_ID (4) +#define SMI_L5_ID (5) +#define SMI_L6_ID (6) +#define SMI_L7_ID (7) +#define SMI_L9_ID (8) +#define SMI_L10_ID (9) +#define SMI_L11A_ID (10) +#define SMI_L11B_ID (11) +#define SMI_L11C_ID (12) +#define SMI_L12_ID (13) +#define SMI_L13_ID (14) +#define SMI_L14_ID (15) +#define SMI_L15_ID (16) +#define SMI_L16A_ID (17) +#define SMI_L16B_ID (18) +#define SMI_L17A_ID (19) +#define SMI_L17B_ID (20) +#define SMI_L19_ID (21) +#define SMI_L21_ID (22) +#define SMI_L23_ID (23) +#define SMI_L27_ID (24) +#define SMI_L28_ID (25) + +/* infra iommu */ +#define PERI_MST_PROT (0x710) +#define PERICFG_AO_IOMMU_1 (0x714) +#define MMU_DEV_PCIE_0 (0) +#define IFR_CFG_GROUP_NUM (1) + +static struct mtk_smi_larb_config mt8188_larb_cfg[SMI_LARB_NUM] = { + [SMI_L0_ID] = LARB_CFG_ENTRY(SMI_LARB_0_BASE, 7, 0), + [SMI_L1_ID] = LARB_CFG_ENTRY(SMI_LARB_1_BASE, 7, 0), + [SMI_L2_ID] = LARB_CFG_ENTRY(SMI_LARB_2_BASE, 5, 0), + [SMI_L3_ID] = LARB_CFG_ENTRY(SMI_LARB_3_BASE, 7, 0), + [SMI_L4_ID] = LARB_CFG_ENTRY(SMI_LARB_4_BASE, 7, 0), + [SMI_L5_ID] = LARB_CFG_ENTRY(SMI_LARB_5_BASE, 8, 0), + [SMI_L6_ID] = LARB_CFG_ENTRY(SMI_LARB_6_BASE, 4, 0), + [SMI_L7_ID] = LARB_CFG_ENTRY(SMI_LARB_7_BASE, 3, 0), + [SMI_L9_ID] = LARB_CFG_ENTRY(SMI_LARB_9_BASE, 25, 0), + [SMI_L10_ID] = LARB_CFG_ENTRY(SMI_LARB_10_BASE, 20, 0), + [SMI_L11A_ID] = LARB_CFG_ENTRY(SMI_LARB_11A_BASE, 30, 0), + [SMI_L11B_ID] = LARB_CFG_ENTRY(SMI_LARB_11B_BASE, 30, 0), + [SMI_L11C_ID] = LARB_CFG_ENTRY(SMI_LARB_11C_BASE, 30, 0), + [SMI_L12_ID] = LARB_CFG_ENTRY(SMI_LARB_12_BASE, 16, 0), + [SMI_L13_ID] = LARB_CFG_ENTRY(SMI_LARB_13_BASE, 24, 0), + [SMI_L14_ID] = LARB_CFG_ENTRY(SMI_LARB_14_BASE, 23, 0), + [SMI_L15_ID] = LARB_CFG_ENTRY(SMI_LARB_15_BASE, 19, 0), + [SMI_L16A_ID] = LARB_CFG_ENTRY(SMI_LARB_16A_BASE, 17, 0), + [SMI_L16B_ID] = LARB_CFG_ENTRY(SMI_LARB_16B_BASE, 17, 0), + [SMI_L17A_ID] = LARB_CFG_ENTRY(SMI_LARB_17A_BASE, 7, 0), + [SMI_L17B_ID] = LARB_CFG_ENTRY(SMI_LARB_17B_BASE, 7, 0), + /* venc nbm ports (5/6/11/15/16/17) to sram */ + [SMI_L19_ID] = LARB_CFG_ENTRY_WITH_PATH(SMI_LARB_19_BASE, 27, 0, 0x38860), + [SMI_L21_ID] = LARB_CFG_ENTRY(SMI_LARB_21_BASE, 11, 0), + [SMI_L23_ID] = LARB_CFG_ENTRY(SMI_LARB_23_BASE, 9, 0), + [SMI_L27_ID] = LARB_CFG_ENTRY(SMI_LARB_27_BASE, 4, 0), + [SMI_L28_ID] = LARB_CFG_ENTRY(SMI_LARB_28_BASE, 0, 0), +}; + +static bool is_protected; + +static uint32_t mt8188_ifr_mst_cfg_base[IFR_CFG_GROUP_NUM] = { + PERICFG_AO_BASE, +}; +static uint32_t mt8188_ifr_mst_cfg_offs[IFR_CFG_GROUP_NUM] = { + PERICFG_AO_IOMMU_1, +}; +static struct mtk_ifr_mst_config mt8188_ifr_mst_cfg[MMU_DEV_NUM] = { + [MMU_DEV_PCIE_0] = IFR_MST_CFG_ENTRY(0, 18), +}; + +struct mtk_smi_larb_config *g_larb_cfg = &mt8188_larb_cfg[0]; +struct mtk_ifr_mst_config *g_ifr_mst_cfg = &mt8188_ifr_mst_cfg[0]; +uint32_t *g_ifr_mst_cfg_base = &mt8188_ifr_mst_cfg_base[0]; +uint32_t *g_ifr_mst_cfg_offs = &mt8188_ifr_mst_cfg_offs[0]; + +/* Protect infra iommu enable setting registers as secure access. */ +void mtk_infra_iommu_enable_protect(void) +{ + if (!is_protected) { + mmio_write_32(PERICFG_AO_BASE + PERI_MST_PROT, 0xffffffff); + is_protected = true; + } +} diff --git a/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h new file mode 100644 index 000000000..a59e0c78f --- /dev/null +++ b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IOMMU_PLAT_H +#define IOMMU_PLAT_H + +#include + +/* mm iommu */ +#define SMI_LARB_NUM (26) +extern struct mtk_smi_larb_config *g_larb_cfg; + +/* infra iommu */ +#define MMU_DEV_NUM (1) +extern struct mtk_ifr_mst_config *g_ifr_mst_cfg; +extern uint32_t *g_ifr_mst_cfg_base; +extern uint32_t *g_ifr_mst_cfg_offs; + +extern void mtk_infra_iommu_enable_protect(void); + +#endif /* IOMMU_PLAT_H */ diff --git a/plat/mediatek/drivers/iommu/mtk_iommu_priv.h b/plat/mediatek/drivers/iommu/mtk_iommu_priv.h new file mode 100644 index 000000000..3404d313b --- /dev/null +++ b/plat/mediatek/drivers/iommu/mtk_iommu_priv.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IOMMU_PRIV_H +#define IOMMU_PRIV_H + +#include +#include +#include + +#define LARB_CFG_ENTRY(bs, p_nr, dom) \ + { .base = (bs), .port_nr = (p_nr), \ + .dom_id = (dom), .to_sram = 0, } + +#define LARB_CFG_ENTRY_WITH_PATH(bs, p_nr, dom, sram) \ + { .base = (bs), .port_nr = (p_nr), \ + .dom_id = (dom), .to_sram = (sram), } + +#define IFR_MST_CFG_ENTRY(idx, bit) \ + { .cfg_addr_idx = (idx), .r_mmu_en_bit = (bit), } + +enum IOMMU_ATF_CMD { + IOMMU_ATF_CMD_CONFIG_SMI_LARB, /* For mm master to enable iommu */ + IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU, /* For infra master to enable iommu */ + IOMMU_ATF_CMD_COUNT, +}; + +struct mtk_smi_larb_config { + uint32_t base; + uint32_t port_nr; + uint32_t dom_id; + uint32_t to_sram; + uint32_t sec_en_msk; +}; + +struct mtk_ifr_mst_config { + uint8_t cfg_addr_idx; + uint8_t r_mmu_en_bit; +}; + +#endif /* IOMMU_PRIV_H */ diff --git a/plat/mediatek/drivers/iommu/mtk_iommu_smc.c b/plat/mediatek/drivers/iommu/mtk_iommu_smc.c new file mode 100644 index 000000000..9762d0b2c --- /dev/null +++ b/plat/mediatek/drivers/iommu/mtk_iommu_smc.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* defination */ +/* smi larb */ +#define SMI_LARB_NON_SEC_CON(port) (0x380 + ((port) << 2)) +#define PATH_SEL_MASK (0xf0000) /* to sram (INT) */ +#define SMI_LARB_SEC_CON_INT(port) (0xf00 + ((port) << 2)) +#define SMI_LARB_SEC_CON(port) (0xf80 + ((port) << 2)) +#define MMU_MASK BIT(0) +#define MMU_EN(en) ((!!(en)) << 0) +#define SEC_MASK BIT(1) +#define SEC_EN(en) ((!!(en)) << 1) +#define DOMAIN_MASK (0x1f << 4) +#define SMI_MMU_EN(port) (0x1 << (port)) + +/* infra master */ +#define IFR_CFG_MMU_EN_MSK(r_bit) (0x3 << (r_bit)) + +/* smi larb configure */ +/* + * If multimedia security config is enabled, the SMI config register must be + * configurated in security world. + * And the SRAM path is also configurated here to enhance security. + */ +static void mtk_smi_larb_port_config_to_sram( + const struct mtk_smi_larb_config *larb, + uint32_t port_id) +{ + mmio_clrbits_32(larb->base + SMI_LARB_SEC_CON_INT(port_id), + MMU_MASK | SEC_MASK | DOMAIN_MASK); + + mmio_setbits_32(larb->base + SMI_LARB_NON_SEC_CON(port_id), + PATH_SEL_MASK); +} + +static void mtk_smi_port_config(const struct mtk_smi_larb_config *larb, + uint32_t port_id, uint8_t mmu_en, uint8_t sec_en) +{ + mmio_clrsetbits_32(larb->base + SMI_LARB_SEC_CON(port_id), + MMU_MASK | SEC_MASK | DOMAIN_MASK, + MMU_EN(mmu_en) | SEC_EN(sec_en)); +} + +static int mtk_smi_larb_port_config_sec(uint32_t larb_id, uint32_t mmu_en_msk) +{ + uint32_t port_id, port_nr; + const struct mtk_smi_larb_config *larb; + uint32_t to_sram; + uint8_t mmu_en; + + if (larb_id >= SMI_LARB_NUM) { + return MTK_SIP_E_INVALID_PARAM; + } + + larb = &g_larb_cfg[larb_id]; + port_nr = larb->port_nr; + to_sram = larb->to_sram; + + for (port_id = 0; port_id < port_nr; port_id++) { + if ((to_sram & BIT(port_id)) > 0U) { + mtk_smi_larb_port_config_to_sram(larb, port_id); + continue; + } + mmu_en = !!(mmu_en_msk & SMI_MMU_EN(port_id)); + mtk_smi_port_config(larb, port_id, mmu_en, 0); + } + + return MTK_SIP_E_SUCCESS; +} + +static int mtk_infra_master_config_sec(uint32_t dev_id, uint32_t enable) +{ + const struct mtk_ifr_mst_config *ifr_cfg; + uint32_t reg_addr; + + mtk_infra_iommu_enable_protect(); + + if (dev_id >= MMU_DEV_NUM) { + return MTK_SIP_E_NOT_SUPPORTED; + } + + ifr_cfg = &g_ifr_mst_cfg[dev_id]; + reg_addr = g_ifr_mst_cfg_base[(ifr_cfg->cfg_addr_idx)] + + g_ifr_mst_cfg_offs[(ifr_cfg->cfg_addr_idx)]; + + if (enable > 0U) { + mmio_setbits_32(reg_addr, IFR_CFG_MMU_EN_MSK(ifr_cfg->r_mmu_en_bit)); + } else { + mmio_clrbits_32(reg_addr, IFR_CFG_MMU_EN_MSK(ifr_cfg->r_mmu_en_bit)); + } + + return MTK_SIP_E_SUCCESS; +} + +static u_register_t mtk_iommu_handler(u_register_t x1, u_register_t x2, + u_register_t x3, u_register_t x4, + void *handle, struct smccc_res *smccc_ret) +{ + uint32_t cmd_id = x1, mdl_id = x2, val = x3; + int ret = MTK_SIP_E_NOT_SUPPORTED; + + (void)x4; + (void)handle; + + switch (cmd_id) { + case IOMMU_ATF_CMD_CONFIG_SMI_LARB: + ret = mtk_smi_larb_port_config_sec(mdl_id, val); + break; + case IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU: + ret = mtk_infra_master_config_sec(mdl_id, val); + break; + default: + break; + } + + return ret; +} +DECLARE_SMC_HANDLER(MTK_SIP_IOMMU_CONTROL, mtk_iommu_handler); diff --git a/plat/mediatek/drivers/iommu/rules.mk b/plat/mediatek/drivers/iommu/rules.mk new file mode 100644 index 000000000..5490f4120 --- /dev/null +++ b/plat/mediatek/drivers/iommu/rules.mk @@ -0,0 +1,17 @@ +# +# Copyright (c) 2022, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +LOCAL_DIR := $(call GET_LOCAL_DIR) + +MODULE := mtk_iommu + +LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_iommu_smc.c +LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/mtk_iommu_plat.c + +PLAT_INCLUDES += -I${LOCAL_DIR} +PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC} + +$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL))) diff --git a/plat/mediatek/include/mt8188/platform_def.h b/plat/mediatek/include/mt8188/platform_def.h index 15ea5b63a..fa8cd41dc 100644 --- a/plat/mediatek/include/mt8188/platform_def.h +++ b/plat/mediatek/include/mt8188/platform_def.h @@ -25,6 +25,12 @@ #define UART0_BASE (IO_PHYS + 0x01002000) #define UART_BAUDRATE (115200) +/******************************************************************************* + * Infra IOMMU related constants + ******************************************************************************/ +#define PERICFG_AO_BASE (IO_PHYS + 0x01003000) +#define PERICFG_AO_REG_SIZE (0x1000) + /******************************************************************************* * GIC-600 & interrupt handling related constants ******************************************************************************/ @@ -41,6 +47,37 @@ #define CIRQ_REG_NUM (23) #define CIRQ_SPI_START (96) +/******************************************************************************* + * MM IOMMU & SMI related constants + ******************************************************************************/ +#define SMI_LARB_0_BASE (IO_PHYS + 0x0c022000) +#define SMI_LARB_1_BASE (IO_PHYS + 0x0c023000) +#define SMI_LARB_2_BASE (IO_PHYS + 0x0c102000) +#define SMI_LARB_3_BASE (IO_PHYS + 0x0c103000) +#define SMI_LARB_4_BASE (IO_PHYS + 0x04013000) +#define SMI_LARB_5_BASE (IO_PHYS + 0x04f02000) +#define SMI_LARB_6_BASE (IO_PHYS + 0x04f03000) +#define SMI_LARB_7_BASE (IO_PHYS + 0x04e04000) +#define SMI_LARB_9_BASE (IO_PHYS + 0x05001000) +#define SMI_LARB_10_BASE (IO_PHYS + 0x05120000) +#define SMI_LARB_11A_BASE (IO_PHYS + 0x05230000) +#define SMI_LARB_11B_BASE (IO_PHYS + 0x05530000) +#define SMI_LARB_11C_BASE (IO_PHYS + 0x05630000) +#define SMI_LARB_12_BASE (IO_PHYS + 0x05340000) +#define SMI_LARB_13_BASE (IO_PHYS + 0x06001000) +#define SMI_LARB_14_BASE (IO_PHYS + 0x06002000) +#define SMI_LARB_15_BASE (IO_PHYS + 0x05140000) +#define SMI_LARB_16A_BASE (IO_PHYS + 0x06008000) +#define SMI_LARB_16B_BASE (IO_PHYS + 0x0600a000) +#define SMI_LARB_17A_BASE (IO_PHYS + 0x06009000) +#define SMI_LARB_17B_BASE (IO_PHYS + 0x0600b000) +#define SMI_LARB_19_BASE (IO_PHYS + 0x0a010000) +#define SMI_LARB_21_BASE (IO_PHYS + 0x0802e000) +#define SMI_LARB_23_BASE (IO_PHYS + 0x0800d000) +#define SMI_LARB_27_BASE (IO_PHYS + 0x07201000) +#define SMI_LARB_28_BASE (IO_PHYS + 0x00000000) +#define SMI_LARB_REG_RNG_SIZE (0x1000) + /******************************************************************************* * DP related constants ******************************************************************************/ diff --git a/plat/mediatek/include/mtk_sip_def.h b/plat/mediatek/include/mtk_sip_def.h index 37734eaa1..d760101cd 100644 --- a/plat/mediatek/include/mtk_sip_def.h +++ b/plat/mediatek/include/mtk_sip_def.h @@ -11,6 +11,7 @@ #define MTK_SIP_SMC_FROM_NS_EL1_TABLE(_func) \ _func(MTK_SIP_KERNEL_TIME_SYNC, 0x202) \ _func(MTK_SIP_VCORE_CONTROL, 0x506) \ + _func(MTK_SIP_IOMMU_CONTROL, 0x514) \ _func(MTK_SIP_APUSYS_CONTROL, 0x51E) \ _func(MTK_SIP_DP_CONTROL, 0x523) \ _func(MTK_SIP_KERNEL_GIC_OP, 0x526) diff --git a/plat/mediatek/mt8188/platform.mk b/plat/mediatek/mt8188/platform.mk index 61b61dbe0..8ba66da60 100644 --- a/plat/mediatek/mt8188/platform.mk +++ b/plat/mediatek/mt8188/platform.mk @@ -25,6 +25,7 @@ MODULES-y += $(MTK_PLAT)/lib/pm MODULES-y += $(MTK_PLAT)/drivers/cirq MODULES-y += $(MTK_PLAT)/drivers/dp MODULES-y += $(MTK_PLAT)/drivers/gic600 +MODULES-y += $(MTK_PLAT)/drivers/iommu MODULES-y += $(MTK_PLAT)/drivers/timer PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \