1 /* 2 * Copyright (c) 2021-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 <mtk_sip_svc.h> 12 13 #if ENABLE_EMI_MPU_SW_LOCK 14 static unsigned char region_lock_state[EMI_MPU_REGION_NUM]; 15 #endif 16 17 #define EMI_MPU_START_MASK (0x00FFFFFF) 18 #define EMI_MPU_END_MASK (0x00FFFFFF) 19 #define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF) 20 #define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF) 21 #define MPU_PHYSICAL_ADDR_SHIFT_BITS (16) 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 1; 72 } 73 74 int emi_mpu_set_protection(struct emi_region_info_t *region_info) 75 { 76 unsigned int start, end; 77 int i; 78 79 if (region_info->region >= EMI_MPU_REGION_NUM) { 80 WARN("invalid region\n"); 81 return -1; 82 } 83 84 start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) | 85 (region_info->region << 24); 86 87 for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) { 88 end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | 89 (i << 24); 90 _emi_mpu_set_protection(start, end, region_info->apc[i]); 91 } 92 93 return 0; 94 } 95 96 void dump_emi_mpu_regions(void) 97 { 98 unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea; 99 100 int region, i; 101 102 /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */ 103 for (region = 0; region < 8; ++region) { 104 for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) 105 apc[i] = mmio_read_32(EMI_MPU_APC(region, i)); 106 sa = mmio_read_32(EMI_MPU_SA(region)); 107 ea = mmio_read_32(EMI_MPU_EA(region)); 108 109 INFO("region %d:\n", region); 110 INFO("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n", 111 sa, ea, apc[0], apc[1]); 112 } 113 } 114 115 void emi_mpu_init(void) 116 { 117 struct emi_region_info_t region_info; 118 119 /* SCP DRAM */ 120 region_info.start = 0x50000000ULL; 121 region_info.end = 0x51400000ULL; 122 region_info.region = 2; 123 SET_ACCESS_PERMISSION(region_info.apc, 1, 124 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 125 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 126 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 127 NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION); 128 emi_mpu_set_protection(®ion_info); 129 130 /* DSP protect address */ 131 region_info.start = 0x60000000ULL; /* dram base addr */ 132 region_info.end = 0x610FFFFFULL; 133 region_info.region = 3; 134 SET_ACCESS_PERMISSION(region_info.apc, 1, 135 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 136 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 137 FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, 138 FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION); 139 emi_mpu_set_protection(®ion_info); 140 141 /* Forbidden All */ 142 region_info.start = 0x40000000ULL; /* dram base addr */ 143 region_info.end = 0x1FFFF0000ULL; 144 region_info.region = 5; 145 SET_ACCESS_PERMISSION(region_info.apc, 1, 146 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 147 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 148 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 149 FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION); 150 emi_mpu_set_protection(®ion_info); 151 152 dump_emi_mpu_regions(); 153 } 154 155 static inline uint64_t get_decoded_phys_addr(uint64_t addr) 156 { 157 return (addr << MPU_PHYSICAL_ADDR_SHIFT_BITS); 158 } 159 160 static inline uint32_t get_decoded_zone_id(uint32_t info) 161 { 162 return ((info & 0xFFFF0000) >> MPU_PHYSICAL_ADDR_SHIFT_BITS); 163 } 164 165 int32_t emi_mpu_sip_handler(uint64_t encoded_addr, uint64_t zone_size, uint64_t zone_info) 166 { 167 uint64_t phys_addr = get_decoded_phys_addr(encoded_addr); 168 struct emi_region_info_t region_info; 169 enum MPU_REQ_ORIGIN_ZONE_ID zone_id = get_decoded_zone_id(zone_info); 170 171 INFO("encoded_addr = 0x%lx, zone_size = 0x%lx, zone_info = 0x%lx\n", 172 encoded_addr, zone_size, zone_info); 173 174 if (zone_id != MPU_REQ_ORIGIN_TEE_ZONE_SVP) { 175 ERROR("Invalid param %s, %d\n", __func__, __LINE__); 176 return MTK_SIP_E_INVALID_PARAM; 177 } 178 179 /* SVP DRAM */ 180 region_info.start = phys_addr; 181 region_info.end = phys_addr + zone_size; 182 region_info.region = 4; 183 SET_ACCESS_PERMISSION(region_info.apc, 1, 184 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 185 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 186 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 187 FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_RW); 188 189 emi_mpu_set_protection(®ion_info); 190 191 return 0; 192 } 193