142f2fa82SXi Chen /*
242f2fa82SXi Chen * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
342f2fa82SXi Chen *
442f2fa82SXi Chen * SPDX-License-Identifier: BSD-3-Clause
542f2fa82SXi Chen */
642f2fa82SXi Chen
742f2fa82SXi Chen #include <common/debug.h>
842f2fa82SXi Chen #include <emi_mpu.h>
942f2fa82SXi Chen #include <lib/mmio.h>
1042f2fa82SXi Chen
1142f2fa82SXi Chen /*
1242f2fa82SXi Chen * emi_mpu_set_region_protection: protect a region.
1342f2fa82SXi Chen * @start: start address of the region
1442f2fa82SXi Chen * @end: end address of the region
1542f2fa82SXi Chen * @access_permission: EMI MPU access permission
1642f2fa82SXi Chen * Return 0 for success, otherwise negative status code.
1742f2fa82SXi Chen */
_emi_mpu_set_protection(unsigned long start,unsigned long end,unsigned int apc)1842f2fa82SXi Chen static int _emi_mpu_set_protection(
1942f2fa82SXi Chen unsigned long start, unsigned long end,
2042f2fa82SXi Chen unsigned int apc)
2142f2fa82SXi Chen {
2242f2fa82SXi Chen unsigned int dgroup;
2342f2fa82SXi Chen unsigned int region;
2442f2fa82SXi Chen
2542f2fa82SXi Chen region = (start >> 24) & 0xFF;
2642f2fa82SXi Chen start &= 0x00FFFFFF;
2742f2fa82SXi Chen dgroup = (end >> 24) & 0xFF;
2842f2fa82SXi Chen end &= 0x00FFFFFF;
2942f2fa82SXi Chen
3042f2fa82SXi Chen if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
3142f2fa82SXi Chen WARN("Region:%u or dgroup:%u is wrong!\n", region, dgroup);
3242f2fa82SXi Chen return -1;
3342f2fa82SXi Chen }
3442f2fa82SXi Chen
3542f2fa82SXi Chen apc &= 0x80FFFFFF;
3642f2fa82SXi Chen
3742f2fa82SXi Chen if ((start >= DRAM_OFFSET) && (end >= start)) {
3842f2fa82SXi Chen start -= DRAM_OFFSET;
3942f2fa82SXi Chen end -= DRAM_OFFSET;
4042f2fa82SXi Chen } else {
4142f2fa82SXi Chen WARN("start:0x%lx or end:0x%lx address is wrong!\n",
4242f2fa82SXi Chen start, end);
4342f2fa82SXi Chen return -2;
4442f2fa82SXi Chen }
4542f2fa82SXi Chen
4642f2fa82SXi Chen mmio_write_32(EMI_MPU_SA(region), start);
4742f2fa82SXi Chen mmio_write_32(EMI_MPU_EA(region), end);
4842f2fa82SXi Chen mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
4942f2fa82SXi Chen
5042f2fa82SXi Chen return 0;
5142f2fa82SXi Chen }
5242f2fa82SXi Chen
dump_emi_mpu_regions(void)5342f2fa82SXi Chen void dump_emi_mpu_regions(void)
5442f2fa82SXi Chen {
5542f2fa82SXi Chen unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea;
5642f2fa82SXi Chen
5742f2fa82SXi Chen int region, i;
5842f2fa82SXi Chen
5942f2fa82SXi Chen /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
6042f2fa82SXi Chen for (region = 0; region < 8; ++region) {
6142f2fa82SXi Chen for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i)
6242f2fa82SXi Chen apc[i] = mmio_read_32(EMI_MPU_APC(region, i));
6342f2fa82SXi Chen sa = mmio_read_32(EMI_MPU_SA(region));
6442f2fa82SXi Chen ea = mmio_read_32(EMI_MPU_EA(region));
6542f2fa82SXi Chen
6642f2fa82SXi Chen WARN("region %d:\n", region);
6742f2fa82SXi Chen WARN("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n",
6842f2fa82SXi Chen sa, ea, apc[0], apc[1]);
6942f2fa82SXi Chen }
7042f2fa82SXi Chen }
7142f2fa82SXi Chen
emi_mpu_set_protection(struct emi_region_info_t * region_info)7242f2fa82SXi Chen int emi_mpu_set_protection(struct emi_region_info_t *region_info)
7342f2fa82SXi Chen {
7442f2fa82SXi Chen unsigned long start, end;
7542f2fa82SXi Chen int i;
7642f2fa82SXi Chen
7742f2fa82SXi Chen if (region_info->region >= EMI_MPU_REGION_NUM)
7842f2fa82SXi Chen return -1;
7942f2fa82SXi Chen
8042f2fa82SXi Chen start = (unsigned long)(region_info->start >> EMI_MPU_ALIGN_BITS) |
8142f2fa82SXi Chen (region_info->region << 24);
8242f2fa82SXi Chen
8342f2fa82SXi Chen for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
8442f2fa82SXi Chen end = (unsigned long)(region_info->end >> EMI_MPU_ALIGN_BITS) |
8542f2fa82SXi Chen (i << 24);
8642f2fa82SXi Chen _emi_mpu_set_protection(start, end, region_info->apc[i]);
8742f2fa82SXi Chen }
8842f2fa82SXi Chen
8942f2fa82SXi Chen return 0;
9042f2fa82SXi Chen }
9142f2fa82SXi Chen
emi_mpu_init(void)9242f2fa82SXi Chen void emi_mpu_init(void)
9342f2fa82SXi Chen {
9442f2fa82SXi Chen struct emi_region_info_t region_info;
9542f2fa82SXi Chen
96a564bdc5SXi Chen /* reserve region 0 for future use */
97a564bdc5SXi Chen
98a564bdc5SXi Chen /* PCI-e protect address(64MB) */
99a564bdc5SXi Chen region_info.start = 0xC0000000ULL;
100*7587cfddSkiwi liu region_info.end = 0xC3FFFFFFULL;
10142f2fa82SXi Chen region_info.region = 1;
10242f2fa82SXi Chen SET_ACCESS_PERMISSION(region_info.apc, 1,
10342f2fa82SXi Chen FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
10442f2fa82SXi Chen FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
10542f2fa82SXi Chen FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
106a564bdc5SXi Chen FORBIDDEN, FORBIDDEN, NO_PROT, NO_PROT);
107a564bdc5SXi Chen emi_mpu_set_protection(®ion_info);
108a564bdc5SXi Chen
109a564bdc5SXi Chen /* SCP protect address */
110a564bdc5SXi Chen region_info.start = 0x50000000ULL;
111*7587cfddSkiwi liu region_info.end = 0x513FFFFFULL;
112a564bdc5SXi Chen region_info.region = 2;
113a564bdc5SXi Chen SET_ACCESS_PERMISSION(region_info.apc, 1,
114a564bdc5SXi Chen FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
115a564bdc5SXi Chen FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
116a564bdc5SXi Chen FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
117a564bdc5SXi Chen NO_PROT, FORBIDDEN, FORBIDDEN, NO_PROT);
11842f2fa82SXi Chen emi_mpu_set_protection(®ion_info);
11942f2fa82SXi Chen
1206c4973b0SJiaxin Yu /* Forbidden All */
1216c4973b0SJiaxin Yu region_info.start = 0x40000000ULL; /* dram base addr */
122*7587cfddSkiwi liu region_info.end = 0x1FFFFFFFFULL;
123*7587cfddSkiwi liu region_info.region = 3;
1246c4973b0SJiaxin Yu SET_ACCESS_PERMISSION(region_info.apc, 1,
1256c4973b0SJiaxin Yu FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1266c4973b0SJiaxin Yu FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1276c4973b0SJiaxin Yu FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1286c4973b0SJiaxin Yu FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROT);
1296c4973b0SJiaxin Yu emi_mpu_set_protection(®ion_info);
1306c4973b0SJiaxin Yu
13142f2fa82SXi Chen dump_emi_mpu_regions();
13242f2fa82SXi Chen }
13342f2fa82SXi Chen
134