diff options
Diffstat (limited to 'plat/mediatek/drivers/emi_mpu')
-rw-r--r-- | plat/mediatek/drivers/emi_mpu/emi_mpu.h | 74 | ||||
-rw-r--r-- | plat/mediatek/drivers/emi_mpu/emi_mpu_common.c | 134 | ||||
-rw-r--r-- | plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c | 117 | ||||
-rw-r--r-- | plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h | 50 | ||||
-rw-r--r-- | plat/mediatek/drivers/emi_mpu/rules.mk | 16 |
5 files changed, 391 insertions, 0 deletions
diff --git a/plat/mediatek/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..ef7134c --- /dev/null +++ b/plat/mediatek/drivers/emi_mpu/emi_mpu.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMI_MPU_H +#define EMI_MPU_H + +#include <emi_mpu_priv.h> +#include <platform_def.h> + +#define NO_PROTECTION (0) +#define SEC_RW (1) +#define SEC_RW_NSEC_R (2) +#define SEC_RW_NSEC_W (3) +#define SEC_R_NSEC_R (4) +#define FORBIDDEN (5) +#define SEC_R_NSEC_RW (6) + +#define LOCK (1) +#define UNLOCK (0) + +#if (EMI_MPU_DGROUP_NUM == 1) +#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \ +do { \ + apc_ary[1] = 0; \ + apc_ary[0] = \ + (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \ + (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \ + (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \ + (((unsigned int) d1) << 3) | ((unsigned int) d0) | \ + ((unsigned int) lock << 31); \ +} while (0) +#elif (EMI_MPU_DGROUP_NUM == 2) +#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \ + d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \ +do { \ + apc_ary[1] = \ + (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \ + (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \ + (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) | \ + (((unsigned int) d9) << 3) | ((unsigned int) d8); \ + apc_ary[0] = \ + (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \ + (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \ + (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \ + (((unsigned int) d1) << 3) | ((unsigned int) d0) | \ + ((unsigned int) lock << 31); \ +} while (0) +#endif + +struct emi_region_info_t { + unsigned long long start; + unsigned long long end; + unsigned int region; + unsigned int apc[EMI_MPU_DGROUP_NUM]; +}; + +enum MPU_REQ_ORIGIN_ZONE_ID { + MPU_REQ_ORIGIN_TEE_ZONE_SVP = 0, + MPU_REQ_ORIGIN_TEE_ZONE_TUI = 1, + MPU_REQ_ORIGIN_TEE_ZONE_WFD = 2, + MPU_REQ_ORIGIN_TEE_ZONE_MAX = 3, + MPU_REQ_ORIGIN_ZONE_INVALID = 0x7FFFFFFF, +}; + +int emi_mpu_init(void); +int emi_mpu_optee_handler(uint64_t encoded_addr, uint64_t zone_size, + uint64_t zone_info); +int emi_mpu_set_protection(struct emi_region_info_t *region_info); +void set_emi_mpu_regions(void); +int set_apu_emi_mpu_region(void); +#endif diff --git a/plat/mediatek/drivers/emi_mpu/emi_mpu_common.c b/plat/mediatek/drivers/emi_mpu/emi_mpu_common.c new file mode 100644 index 0000000..8810be3 --- /dev/null +++ b/plat/mediatek/drivers/emi_mpu/emi_mpu_common.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <string.h> +#include <common/debug.h> +#include <lib/mmio.h> +#include <smccc_helpers.h> + +#include <emi_mpu.h> +#include <lib/mtk_init/mtk_init.h> +#include <mtk_sip_svc.h> + +#if ENABLE_EMI_MPU_SW_LOCK +static unsigned char region_lock_state[EMI_MPU_REGION_NUM]; +#endif + +#define EMI_MPU_START_MASK (0x00FFFFFF) +#define EMI_MPU_END_MASK (0x00FFFFFF) +#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF) +#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF) + +static int _emi_mpu_set_protection(unsigned int start, unsigned int end, + unsigned int apc) +{ + unsigned int dgroup; + unsigned int region; + + region = (start >> 24) & 0xFF; + start &= EMI_MPU_START_MASK; + dgroup = (end >> 24) & 0xFF; + end &= EMI_MPU_END_MASK; + + if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) { + WARN("invalid region, domain\n"); + return -1; + } + +#if ENABLE_EMI_MPU_SW_LOCK + if (region_lock_state[region] == 1) { + WARN("invalid region\n"); + return -1; + } + + if ((dgroup == 0) && ((apc >> 31) & 0x1)) { + region_lock_state[region] = 1; + } + + apc &= EMI_MPU_APC_SW_LOCK_MASK; +#else + apc &= EMI_MPU_APC_HW_LOCK_MASK; +#endif + + if ((start >= DRAM_OFFSET) && (end >= start)) { + start -= DRAM_OFFSET; + end -= DRAM_OFFSET; + } else { + WARN("invalid range\n"); + return -1; + } + + mmio_write_32(EMI_MPU_SA(region), start); + mmio_write_32(EMI_MPU_EA(region), end); + mmio_write_32(EMI_MPU_APC(region, dgroup), apc); + +#if defined(SUB_EMI_MPU_BASE) + mmio_write_32(SUB_EMI_MPU_SA(region), start); + mmio_write_32(SUB_EMI_MPU_EA(region), end); + mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc); +#endif + return 0; +} + +static void dump_emi_mpu_regions(void) +{ + int region, i; + + /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */ + for (region = 0; region < 8; ++region) { + INFO("region %d:\n", region); + INFO("\tsa: 0x%x, ea: 0x%x\n", + mmio_read_32(EMI_MPU_SA(region)), mmio_read_32(EMI_MPU_EA(region))); + + for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) { + INFO("\tapc%d: 0x%x\n", i, mmio_read_32(EMI_MPU_APC(region, i))); + } + } +} + +int emi_mpu_set_protection(struct emi_region_info_t *region_info) +{ + unsigned int start, end; + int i; + + if (region_info->region >= EMI_MPU_REGION_NUM) { + WARN("invalid region\n"); + return -1; + } + + start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) | + (region_info->region << 24); + + for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) { + end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24); + + if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) { + WARN("Failed to set emi mpu protection(%d, %d, %d)\n", + start, end, region_info->apc[i]); + } + } + + return 0; +} + +u_register_t mtk_emi_mpu_sip_handler(u_register_t x1, u_register_t x2, + u_register_t x3, u_register_t x4, + void *handle, struct smccc_res *smccc_ret) +{ + return (u_register_t) emi_mpu_optee_handler(x1, x2, x3); +} +DECLARE_SMC_HANDLER(MTK_SIP_TEE_MPU_PERM_SET, mtk_emi_mpu_sip_handler); + +int emi_mpu_init(void) +{ + INFO("[%s] emi mpu initialization\n", __func__); + + set_emi_mpu_regions(); + dump_emi_mpu_regions(); + + return 0; +} +MTK_PLAT_SETUP_0_INIT(emi_mpu_init); diff --git a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c new file mode 100644 index 0000000..e8882f0 --- /dev/null +++ b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <emi_mpu.h> +#include <mtk_sip_svc.h> + +#define MPU_PHYSICAL_ADDR_SHIFT_BITS (16) + +void set_emi_mpu_regions(void) +{ + struct emi_region_info_t region_info; + + /* SCP core0 DRAM */ + region_info.start = 0x50000000ULL; + region_info.end = 0x528FFFFFULL; + region_info.region = 2; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION); + emi_mpu_set_protection(®ion_info); + + /* SCP core1 DRAM */ + region_info.start = 0x70000000ULL; + region_info.end = 0x729FFFFFULL; + region_info.region = 3; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION); + emi_mpu_set_protection(®ion_info); + + /* DSP protect address */ + region_info.start = 0x60000000ULL; + region_info.end = 0x610FFFFFULL; + region_info.region = 4; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, + FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION); + emi_mpu_set_protection(®ion_info); + + /* All default settings */ + region_info.start = 0x40000000ULL; + region_info.end = 0x1FFFF0000ULL; + region_info.region = 31; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, NO_PROTECTION, + NO_PROTECTION, SEC_R_NSEC_RW, NO_PROTECTION, FORBIDDEN, + NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION); + emi_mpu_set_protection(®ion_info); +} + +int set_apu_emi_mpu_region(void) +{ + struct emi_region_info_t region_info; + + region_info.start = (unsigned long long)APUSYS_SEC_BUF_PA; + region_info.end = (unsigned long long)(APUSYS_SEC_BUF_PA + APUSYS_SEC_BUF_SZ) - 1; + region_info.region = APUSYS_SEC_BUF_EMI_REGION; + + SET_ACCESS_PERMISSION(region_info.apc, UNLOCK, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_RW); + + return emi_mpu_set_protection(®ion_info); +} + +static inline uint64_t get_decoded_phys_addr(uint64_t addr) +{ + return (addr << MPU_PHYSICAL_ADDR_SHIFT_BITS); +} + +static inline uint32_t get_decoded_zone_id(uint32_t info) +{ + return ((info & 0xFFFF0000) >> MPU_PHYSICAL_ADDR_SHIFT_BITS); +} + +int emi_mpu_optee_handler(uint64_t encoded_addr, uint64_t zone_size, + uint64_t zone_info) +{ + uint64_t phys_addr = get_decoded_phys_addr(encoded_addr); + struct emi_region_info_t region_info; + enum MPU_REQ_ORIGIN_ZONE_ID zone_id = get_decoded_zone_id(zone_info); + + INFO("encoded_addr = 0x%lx, zone_size = 0x%lx, zone_info = 0x%lx\n", + encoded_addr, zone_size, zone_info); + + if (zone_id != MPU_REQ_ORIGIN_TEE_ZONE_SVP) { + ERROR("Invalid param %s, %d\n", __func__, __LINE__); + return MTK_SIP_E_INVALID_PARAM; + } + + /* SVP DRAM */ + region_info.start = phys_addr; + region_info.end = phys_addr + zone_size; + region_info.region = 4; + SET_ACCESS_PERMISSION(region_info.apc, 1, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, + FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_RW); + + emi_mpu_set_protection(®ion_info); + + return 0; +}
\ No newline at end of file diff --git a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h new file mode 100644 index 0000000..cc7f7f1 --- /dev/null +++ b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMI_MPU_PRIV_H +#define EMI_MPU_PRIV_H + +#define ENABLE_EMI_MPU_SW_LOCK (1) + +#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x000) +#define EMI_MPU_DBG (EMI_MPU_BASE + 0x004) +#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100) +#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200) +#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region * 4)) +#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region * 4)) +#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300) +#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100)) +#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800) +#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + (domain * 4)) +#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900) +#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + (domain * 4)) + +#define SUB_EMI_MPU_CTRL (SUB_EMI_MPU_BASE + 0x000) +#define SUB_EMI_MPU_DBG (SUB_EMI_MPU_BASE + 0x004) +#define SUB_EMI_MPU_SA0 (SUB_EMI_MPU_BASE + 0x100) +#define SUB_EMI_MPU_EA0 (SUB_EMI_MPU_BASE + 0x200) +#define SUB_EMI_MPU_SA(region) (SUB_EMI_MPU_SA0 + (region * 4)) +#define SUB_EMI_MPU_EA(region) (SUB_EMI_MPU_EA0 + (region * 4)) +#define SUB_EMI_MPU_APC0 (SUB_EMI_MPU_BASE + 0x300) +#define SUB_EMI_MPU_APC(region, dgroup) (SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100)) +#define SUB_EMI_MPU_CTRL_D0 (SUB_EMI_MPU_BASE + 0x800) +#define SUB_EMI_MPU_CTRL_D(domain) (SUB_EMI_MPU_CTRL_D0 + (domain * 4)) +#define SUB_EMI_RG_MASK_D0 (SUB_EMI_MPU_BASE + 0x900) +#define SUB_EMI_RG_MASK_D(domain) (SUB_EMI_RG_MASK_D0 + (domain * 4)) + +#define EMI_MPU_DOMAIN_NUM (16) +#define EMI_MPU_REGION_NUM (32) +#define EMI_MPU_ALIGN_BITS (16) +#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS) + +#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8) + +/* APU EMI MPU Setting */ +#define APUSYS_SEC_BUF_EMI_REGION (21) +#define APUSYS_SEC_BUF_PA (0x55000000) +#define APUSYS_SEC_BUF_SZ (0x100000) + +#endif diff --git a/plat/mediatek/drivers/emi_mpu/rules.mk b/plat/mediatek/drivers/emi_mpu/rules.mk new file mode 100644 index 0000000..ed3d777 --- /dev/null +++ b/plat/mediatek/drivers/emi_mpu/rules.mk @@ -0,0 +1,16 @@ +# +# Copyright (c) 2022, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +LOCAL_DIR := $(call GET_LOCAL_DIR) + +MODULE := emi_mpu +LOCAL_SRCS-y := $(LOCAL_DIR)/emi_mpu_common.c +LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/emi_mpu.c + +PLAT_INCLUDES += -I${LOCAL_DIR} +PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC} + +$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL))) |