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