1 /* 2 * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <string.h> 8 #include <common/debug.h> 9 #include <lib/mmio.h> 10 #include <emi_mpu.h> 11 #include <lib/mtk_init/mtk_init.h> 12 #include <mtk_sip_svc.h> 13 14 #if ENABLE_EMI_MPU_SW_LOCK 15 static unsigned char region_lock_state[EMI_MPU_REGION_NUM]; 16 #endif 17 18 #define EMI_MPU_START_MASK (0x00FFFFFF) 19 #define EMI_MPU_END_MASK (0x00FFFFFF) 20 #define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF) 21 #define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF) 22 23 static int _emi_mpu_set_protection(unsigned int start, unsigned int end, 24 unsigned int apc) 25 { 26 unsigned int dgroup; 27 unsigned int region; 28 29 region = (start >> 24) & 0xFF; 30 start &= EMI_MPU_START_MASK; 31 dgroup = (end >> 24) & 0xFF; 32 end &= EMI_MPU_END_MASK; 33 34 if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) { 35 WARN("invalid region, domain\n"); 36 return -1; 37 } 38 39 #if ENABLE_EMI_MPU_SW_LOCK 40 if (region_lock_state[region] == 1) { 41 WARN("invalid region\n"); 42 return -1; 43 } 44 45 if ((dgroup == 0) && ((apc >> 31) & 0x1)) { 46 region_lock_state[region] = 1; 47 } 48 49 apc &= EMI_MPU_APC_SW_LOCK_MASK; 50 #else 51 apc &= EMI_MPU_APC_HW_LOCK_MASK; 52 #endif 53 54 if ((start >= DRAM_OFFSET) && (end >= start)) { 55 start -= DRAM_OFFSET; 56 end -= DRAM_OFFSET; 57 } else { 58 WARN("invalid range\n"); 59 return -1; 60 } 61 62 mmio_write_32(EMI_MPU_SA(region), start); 63 mmio_write_32(EMI_MPU_EA(region), end); 64 mmio_write_32(EMI_MPU_APC(region, dgroup), apc); 65 66 #if defined(SUB_EMI_MPU_BASE) 67 mmio_write_32(SUB_EMI_MPU_SA(region), start); 68 mmio_write_32(SUB_EMI_MPU_EA(region), end); 69 mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc); 70 #endif 71 return 0; 72 } 73 74 static void dump_emi_mpu_regions(void) 75 { 76 int region, i; 77 78 /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */ 79 for (region = 0; region < 8; ++region) { 80 INFO("region %d:\n", region); 81 INFO("\tsa: 0x%x, ea: 0x%x\n", 82 mmio_read_32(EMI_MPU_SA(region)), mmio_read_32(EMI_MPU_EA(region))); 83 84 for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) { 85 INFO("\tapc%d: 0x%x\n", i, mmio_read_32(EMI_MPU_APC(region, i))); 86 } 87 } 88 } 89 90 int emi_mpu_set_protection(struct emi_region_info_t *region_info) 91 { 92 unsigned int start, end; 93 int i; 94 95 if (region_info->region >= EMI_MPU_REGION_NUM) { 96 WARN("invalid region\n"); 97 return -1; 98 } 99 100 start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) | 101 (region_info->region << 24); 102 103 for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) { 104 end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24); 105 106 if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) { 107 WARN("Failed to set emi mpu protection(%d, %d, %d)\n", 108 start, end, region_info->apc[i]); 109 } 110 } 111 112 return 0; 113 } 114 115 u_register_t mtk_emi_mpu_sip_handler(u_register_t x1, u_register_t x2, 116 u_register_t x3, u_register_t x4, 117 void *handle, struct smccc_res *smccc_ret) 118 { 119 /* TODO: implement emi mpu handler */ 120 121 return 0; 122 } 123 DECLARE_SMC_HANDLER(MTK_SIP_TEE_MPU_PERM_SET, mtk_emi_mpu_sip_handler); 124 125 int emi_mpu_init(void) 126 { 127 INFO("[%s] emi mpu initialization\n", __func__); 128 129 set_emi_mpu_regions(); 130 dump_emi_mpu_regions(); 131 132 return 0; 133 } 134 MTK_PLAT_SETUP_0_INIT(emi_mpu_init); 135