1 /* 2 * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <common/debug.h> 8 #include <emi_mpu.h> 9 #include <lib/mmio.h> 10 11 /* 12 * emi_mpu_set_region_protection: protect a region. 13 * @start: start address of the region 14 * @end: end address of the region 15 * @access_permission: EMI MPU access permission 16 * Return 0 for success, otherwise negative status code. 17 */ 18 static int _emi_mpu_set_protection( 19 unsigned long start, unsigned long end, 20 unsigned int apc) 21 { 22 unsigned int dgroup; 23 unsigned int region; 24 25 region = (start >> 24) & 0xFF; 26 start &= 0x00FFFFFF; 27 dgroup = (end >> 24) & 0xFF; 28 end &= 0x00FFFFFF; 29 30 if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) { 31 WARN("Region:%u or dgroup:%u is wrong!\n", region, dgroup); 32 return -1; 33 } 34 35 apc &= 0x80FFFFFF; 36 37 if ((start >= DRAM_OFFSET) && (end >= start)) { 38 start -= DRAM_OFFSET; 39 end -= DRAM_OFFSET; 40 } else { 41 WARN("start:0x%lx or end:0x%lx address is wrong!\n", 42 start, end); 43 return -2; 44 } 45 46 mmio_write_32(EMI_MPU_SA(region), start); 47 mmio_write_32(EMI_MPU_EA(region), end); 48 mmio_write_32(EMI_MPU_APC(region, dgroup), apc); 49 50 return 0; 51 } 52 53 void dump_emi_mpu_regions(void) 54 { 55 unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea; 56 57 int region, i; 58 59 /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */ 60 for (region = 0; region < 8; ++region) { 61 for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) 62 apc[i] = mmio_read_32(EMI_MPU_APC(region, i)); 63 sa = mmio_read_32(EMI_MPU_SA(region)); 64 ea = mmio_read_32(EMI_MPU_EA(region)); 65 66 WARN("region %d:\n", region); 67 WARN("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n", 68 sa, ea, apc[0], apc[1]); 69 } 70 } 71 72 int emi_mpu_set_protection(struct emi_region_info_t *region_info) 73 { 74 unsigned long start, end; 75 int i; 76 77 if (region_info->region >= EMI_MPU_REGION_NUM) 78 return -1; 79 80 start = (unsigned long)(region_info->start >> EMI_MPU_ALIGN_BITS) | 81 (region_info->region << 24); 82 83 for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) { 84 end = (unsigned long)(region_info->end >> EMI_MPU_ALIGN_BITS) | 85 (i << 24); 86 _emi_mpu_set_protection(start, end, region_info->apc[i]); 87 } 88 89 return 0; 90 } 91 92 void emi_mpu_init(void) 93 { 94 struct emi_region_info_t region_info; 95 96 /* reserve region 0 for future use */ 97 98 /* PCI-e protect address(64MB) */ 99 region_info.start = 0xC0000000ULL; 100 region_info.end = 0xC3FFFFFFULL; 101 region_info.region = 1; 102 SET_ACCESS_PERMISSION(region_info.apc, 1, 103 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 104 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 105 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 106 FORBIDDEN, FORBIDDEN, NO_PROT, NO_PROT); 107 emi_mpu_set_protection(®ion_info); 108 109 /* SCP protect address */ 110 region_info.start = 0x50000000ULL; 111 region_info.end = 0x513FFFFFULL; 112 region_info.region = 2; 113 SET_ACCESS_PERMISSION(region_info.apc, 1, 114 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 115 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 116 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 117 NO_PROT, FORBIDDEN, FORBIDDEN, NO_PROT); 118 emi_mpu_set_protection(®ion_info); 119 120 /* Forbidden All */ 121 region_info.start = 0x40000000ULL; /* dram base addr */ 122 region_info.end = 0x1FFFFFFFFULL; 123 region_info.region = 3; 124 SET_ACCESS_PERMISSION(region_info.apc, 1, 125 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 126 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 127 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, 128 FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROT); 129 emi_mpu_set_protection(®ion_info); 130 131 dump_emi_mpu_regions(); 132 } 133 134