1 /*
2 * Copyright (c) 2021-2023, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <string.h>
8 #include <common/debug.h>
9 #include <lib/mmio.h>
10 #include <emi_mpu.h>
11 #include <mtk_sip_svc.h>
12
13 #if ENABLE_EMI_MPU_SW_LOCK
14 static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
15 #endif
16
17 #define EMI_MPU_START_MASK (0x00FFFFFF)
18 #define EMI_MPU_END_MASK (0x00FFFFFF)
19 #define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF)
20 #define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF)
21 #define MPU_PHYSICAL_ADDR_SHIFT_BITS (16)
22
_emi_mpu_set_protection(unsigned int start,unsigned int end,unsigned int apc)23 static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
24 unsigned int apc)
25 {
26 unsigned int dgroup;
27 unsigned int region;
28
29 region = (start >> 24) & 0xFF;
30 start &= EMI_MPU_START_MASK;
31 dgroup = (end >> 24) & 0xFF;
32 end &= EMI_MPU_END_MASK;
33
34 if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
35 WARN("invalid region, domain\n");
36 return -1;
37 }
38
39 #if ENABLE_EMI_MPU_SW_LOCK
40 if (region_lock_state[region] == 1) {
41 WARN("invalid region\n");
42 return -1;
43 }
44
45 if ((dgroup == 0) && ((apc >> 31) & 0x1)) {
46 region_lock_state[region] = 1;
47 }
48
49 apc &= EMI_MPU_APC_SW_LOCK_MASK;
50 #else
51 apc &= EMI_MPU_APC_HW_LOCK_MASK;
52 #endif
53
54 if ((start >= DRAM_OFFSET) && (end >= start)) {
55 start -= DRAM_OFFSET;
56 end -= DRAM_OFFSET;
57 } else {
58 WARN("invalid range\n");
59 return -1;
60 }
61
62 mmio_write_32(EMI_MPU_SA(region), start);
63 mmio_write_32(EMI_MPU_EA(region), end);
64 mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
65
66 #if defined(SUB_EMI_MPU_BASE)
67 mmio_write_32(SUB_EMI_MPU_SA(region), start);
68 mmio_write_32(SUB_EMI_MPU_EA(region), end);
69 mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
70 #endif
71 return 1;
72 }
73
emi_mpu_set_protection(struct emi_region_info_t * region_info)74 int emi_mpu_set_protection(struct emi_region_info_t *region_info)
75 {
76 unsigned int start, end;
77 int i;
78
79 if (region_info->region >= EMI_MPU_REGION_NUM) {
80 WARN("invalid region\n");
81 return -1;
82 }
83
84 start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
85 (region_info->region << 24);
86
87 for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
88 end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) |
89 (i << 24);
90 _emi_mpu_set_protection(start, end, region_info->apc[i]);
91 }
92
93 return 0;
94 }
95
dump_emi_mpu_regions(void)96 void dump_emi_mpu_regions(void)
97 {
98 unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea;
99
100 int region, i;
101
102 /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
103 for (region = 0; region < 8; ++region) {
104 for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i)
105 apc[i] = mmio_read_32(EMI_MPU_APC(region, i));
106 sa = mmio_read_32(EMI_MPU_SA(region));
107 ea = mmio_read_32(EMI_MPU_EA(region));
108
109 INFO("region %d:\n", region);
110 INFO("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n",
111 sa, ea, apc[0], apc[1]);
112 }
113 }
114
emi_mpu_init(void)115 void emi_mpu_init(void)
116 {
117 struct emi_region_info_t region_info;
118
119 /* SCP DRAM */
120 region_info.start = 0x50000000ULL;
121 region_info.end = 0x51400000ULL;
122 region_info.region = 2;
123 SET_ACCESS_PERMISSION(region_info.apc, 1,
124 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
125 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
126 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
127 NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
128 emi_mpu_set_protection(®ion_info);
129
130 /* DSP protect address */
131 region_info.start = 0x60000000ULL; /* dram base addr */
132 region_info.end = 0x610FFFFFULL;
133 region_info.region = 3;
134 SET_ACCESS_PERMISSION(region_info.apc, 1,
135 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
136 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
137 FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION,
138 FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
139 emi_mpu_set_protection(®ion_info);
140
141 /* Forbidden All */
142 region_info.start = 0x40000000ULL; /* dram base addr */
143 region_info.end = 0x1FFFF0000ULL;
144 region_info.region = 5;
145 SET_ACCESS_PERMISSION(region_info.apc, 1,
146 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
147 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
148 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
149 FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
150 emi_mpu_set_protection(®ion_info);
151
152 dump_emi_mpu_regions();
153 }
154
get_decoded_phys_addr(uint64_t addr)155 static inline uint64_t get_decoded_phys_addr(uint64_t addr)
156 {
157 return (addr << MPU_PHYSICAL_ADDR_SHIFT_BITS);
158 }
159
get_decoded_zone_id(uint32_t info)160 static inline uint32_t get_decoded_zone_id(uint32_t info)
161 {
162 return ((info & 0xFFFF0000) >> MPU_PHYSICAL_ADDR_SHIFT_BITS);
163 }
164
emi_mpu_sip_handler(uint64_t encoded_addr,uint64_t zone_size,uint64_t zone_info)165 int32_t emi_mpu_sip_handler(uint64_t encoded_addr, uint64_t zone_size, uint64_t zone_info)
166 {
167 uint64_t phys_addr = get_decoded_phys_addr(encoded_addr);
168 struct emi_region_info_t region_info;
169 enum MPU_REQ_ORIGIN_ZONE_ID zone_id = get_decoded_zone_id(zone_info);
170
171 INFO("encoded_addr = 0x%lx, zone_size = 0x%lx, zone_info = 0x%lx\n",
172 encoded_addr, zone_size, zone_info);
173
174 if (zone_id != MPU_REQ_ORIGIN_TEE_ZONE_SVP) {
175 ERROR("Invalid param %s, %d\n", __func__, __LINE__);
176 return MTK_SIP_E_INVALID_PARAM;
177 }
178
179 /* SVP DRAM */
180 region_info.start = phys_addr;
181 region_info.end = phys_addr + zone_size;
182 region_info.region = 4;
183 SET_ACCESS_PERMISSION(region_info.apc, 1,
184 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
185 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
186 FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
187 FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_RW);
188
189 emi_mpu_set_protection(®ion_info);
190
191 return 0;
192 }
193