1 /* 2 * Copyright (c) 2022, 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 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 22 static int _emi_mpu_set_protection(unsigned int start, unsigned int end, 23 unsigned int apc) 24 { 25 unsigned int dgroup; 26 unsigned int region; 27 28 region = (start >> 24) & 0xFF; 29 start &= EMI_MPU_START_MASK; 30 dgroup = (end >> 24) & 0xFF; 31 end &= EMI_MPU_END_MASK; 32 33 if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) { 34 WARN("invalid region, domain\n"); 35 return -1; 36 } 37 38 #if ENABLE_EMI_MPU_SW_LOCK 39 if (region_lock_state[region] == 1) { 40 WARN("invalid region\n"); 41 return -1; 42 } 43 44 if ((dgroup == 0) && ((apc >> 31) & 0x1)) { 45 region_lock_state[region] = 1; 46 } 47 48 apc &= EMI_MPU_APC_SW_LOCK_MASK; 49 #else 50 apc &= EMI_MPU_APC_HW_LOCK_MASK; 51 #endif 52 53 if ((start >= DRAM_OFFSET) && (end >= start)) { 54 start -= DRAM_OFFSET; 55 end -= DRAM_OFFSET; 56 } else { 57 WARN("invalid range\n"); 58 return -1; 59 } 60 61 mmio_write_32(EMI_MPU_SA(region), start); 62 mmio_write_32(EMI_MPU_EA(region), end); 63 mmio_write_32(EMI_MPU_APC(region, dgroup), apc); 64 65 #if defined(SUB_EMI_MPU_BASE) 66 mmio_write_32(SUB_EMI_MPU_SA(region), start); 67 mmio_write_32(SUB_EMI_MPU_EA(region), end); 68 mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc); 69 #endif 70 return 0; 71 } 72 73 static void dump_emi_mpu_regions(void) 74 { 75 int region, i; 76 77 /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */ 78 for (region = 0; region < 8; ++region) { 79 INFO("region %d:\n", region); 80 INFO("\tsa: 0x%x, ea: 0x%x\n", 81 mmio_read_32(EMI_MPU_SA(region)), mmio_read_32(EMI_MPU_EA(region))); 82 83 for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) { 84 INFO("\tapc%d: 0x%x\n", i, mmio_read_32(EMI_MPU_APC(region, i))); 85 } 86 } 87 } 88 89 int emi_mpu_set_protection(struct emi_region_info_t *region_info) 90 { 91 unsigned int start, end; 92 int i; 93 94 if (region_info->region >= EMI_MPU_REGION_NUM) { 95 WARN("invalid region\n"); 96 return -1; 97 } 98 99 start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) | 100 (region_info->region << 24); 101 102 for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) { 103 end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24); 104 105 if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) { 106 WARN("Failed to set emi mpu protection(%d, %d, %d)\n", 107 start, end, region_info->apc[i]); 108 } 109 } 110 111 return 0; 112 } 113 114 int emi_mpu_init(void) 115 { 116 INFO("[%s] emi mpu initialization\n", __func__); 117 118 set_emi_mpu_regions(); 119 dump_emi_mpu_regions(); 120 121 return 0; 122 } 123 MTK_PLAT_SETUP_0_INIT(emi_mpu_init); 124