1 /*
2  * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <common/debug.h>
8 #include <lib/mmio.h>
9 #include <emi_mpu.h>
10 
is_4GB(void)11 int is_4GB(void)
12 {
13 	return 0; /* 8183 doesn't use 4GB */
14 }
15 
16 /*
17  * emi_mpu_set_region_protection: protect a region.
18  * @start: start address of the region
19  * @end: end address of the region
20  * @region: EMI MPU region id
21  * @access_permission: EMI MPU access permission
22  * Return 0 for success, otherwise negative status code.
23  */
emi_mpu_set_region_protection(unsigned long start,unsigned long end,int region,unsigned int access_permission)24 int emi_mpu_set_region_protection(
25 	unsigned long start, unsigned long end,
26 	int region,
27 	unsigned int access_permission)
28 {
29 	int ret = 0;
30 
31 	if (end <= start) {
32 		ERROR("[EMI][MTEE][MPU] Invalid address!.\n");
33 		return -1;
34 	}
35 
36 	if (is_4GB()) {
37 		/* 4GB mode: emi_addr = phy_addr & 0xffff */
38 		start = EMI_PHY_OFFSET & 0xffff;
39 		end = EMI_PHY_OFFSET & 0xffff;
40 	} else {
41 		/* non-4GB mode: emi_addr = phy_addr - MEM_OFFSET */
42 		start = start - EMI_PHY_OFFSET;
43 		end = end - EMI_PHY_OFFSET;
44 	}
45 
46 	/*Address 64KB alignment*/
47 	start = start >> 16;
48 	end = end >> 16;
49 
50 	switch (region) {
51 	case 0:
52 		mmio_write_32(EMI_MPU_APC0, 0);
53 		mmio_write_32(EMI_MPU_SA0, start);
54 		mmio_write_32(EMI_MPU_EA0, end);
55 		mmio_write_32(EMI_MPU_APC0, access_permission);
56 		break;
57 
58 	case 1:
59 		mmio_write_32(EMI_MPU_APC1, 0);
60 		mmio_write_32(EMI_MPU_SA1, start);
61 		mmio_write_32(EMI_MPU_EA1, end);
62 		mmio_write_32(EMI_MPU_APC1, access_permission);
63 		break;
64 
65 	case 2:
66 		mmio_write_32(EMI_MPU_APC2, 0);
67 		mmio_write_32(EMI_MPU_SA2, start);
68 		mmio_write_32(EMI_MPU_EA2, end);
69 		mmio_write_32(EMI_MPU_APC2, access_permission);
70 		break;
71 
72 	case 3:
73 		mmio_write_32(EMI_MPU_APC3, 0);
74 		mmio_write_32(EMI_MPU_SA3, start);
75 		mmio_write_32(EMI_MPU_EA3, end);
76 		mmio_write_32(EMI_MPU_APC3, access_permission);
77 		break;
78 
79 	case 4:
80 		mmio_write_32(EMI_MPU_APC4, 0);
81 		mmio_write_32(EMI_MPU_SA4, start);
82 		mmio_write_32(EMI_MPU_EA4, end);
83 		mmio_write_32(EMI_MPU_APC4, access_permission);
84 		break;
85 
86 	case 5:
87 		mmio_write_32(EMI_MPU_APC5, 0);
88 		mmio_write_32(EMI_MPU_SA5, start);
89 		mmio_write_32(EMI_MPU_EA5, end);
90 		mmio_write_32(EMI_MPU_APC5, access_permission);
91 		break;
92 
93 	case 6:
94 		mmio_write_32(EMI_MPU_APC6, 0);
95 		mmio_write_32(EMI_MPU_SA6, start);
96 		mmio_write_32(EMI_MPU_EA6, end);
97 		mmio_write_32(EMI_MPU_APC6, access_permission);
98 		break;
99 
100 	case 7:
101 		mmio_write_32(EMI_MPU_APC7, 0);
102 		mmio_write_32(EMI_MPU_SA7, start);
103 		mmio_write_32(EMI_MPU_EA7, end);
104 		mmio_write_32(EMI_MPU_APC7, access_permission);
105 		break;
106 
107 	default:
108 		ret = -1;
109 		break;
110 	}
111 
112 	return ret;
113 }
114 
dump_emi_mpu_regions(void)115 void dump_emi_mpu_regions(void)
116 {
117 	unsigned int apc, sa, ea;
118 	unsigned int apc_addr = EMI_MPU_APC0;
119 	unsigned int sa_addr = EMI_MPU_SA0;
120 	unsigned int ea_addr = EMI_MPU_EA0;
121 	int i;
122 
123 	for (i = 0; i < 8; ++i) {
124 		apc = mmio_read_32(apc_addr + i * 4);
125 		sa = mmio_read_32(sa_addr + i * 4);
126 		ea = mmio_read_32(ea_addr + i * 4);
127 		WARN("region %d:\n", i);
128 		WARN("\tapc:0x%x, sa:0x%x, ea:0x%x\n", apc, sa, ea);
129 	}
130 }
131 
emi_mpu_init(void)132 void emi_mpu_init(void)
133 {
134 	/* Set permission */
135 	emi_mpu_set_region_protection(0x40000000UL, 0x4FFFFFFFUL, 0,
136 				(FORBIDDEN << 3 | FORBIDDEN << 6));
137 	emi_mpu_set_region_protection(0x50000000UL, 0x528FFFFFUL, 1,
138 				(FORBIDDEN << 6));
139 	emi_mpu_set_region_protection(0x52900000UL, 0x5FFFFFFFUL, 2,
140 				(FORBIDDEN << 3 | FORBIDDEN << 6));
141 	emi_mpu_set_region_protection(0x60000000UL, 0xFFFFFFFFUL, 3,
142 				(FORBIDDEN << 3 | FORBIDDEN << 6));
143 	emi_mpu_set_region_protection(0x100000000UL, 0x23FFFFFFFUL, 4,
144 				(FORBIDDEN << 3 | FORBIDDEN << 6));
145 	dump_emi_mpu_regions();
146 }
147 
148