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