blob: b6e5a2d92f8c3ea6c5a4aa001e62c64aa024501c [file] [log] [blame]
developere2be2dd2021-08-19 15:34:43 +08001/*
developer551250c2023-03-01 16:12:46 +08002 * Copyright (c) 2021-2023, ARM Limited and Contributors. All rights reserved.
developere2be2dd2021-08-19 15:34:43 +08003 *
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>
developer551250c2023-03-01 16:12:46 +080011#include <mtk_sip_svc.h>
developere2be2dd2021-08-19 15:34:43 +080012
13#if ENABLE_EMI_MPU_SW_LOCK
14static 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)
developer551250c2023-03-01 16:12:46 +080021#define MPU_PHYSICAL_ADDR_SHIFT_BITS (16)
developere2be2dd2021-08-19 15:34:43 +080022
23static 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
74int 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
developerfe2308b2021-11-15 18:07:47 +080096void 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
developere2be2dd2021-08-19 15:34:43 +0800115void emi_mpu_init(void)
116{
developerdfc61e02021-11-15 18:08:10 +0800117 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(&region_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(&region_info);
140
141 /* Forbidden All */
142 region_info.start = 0x40000000ULL; /* dram base addr */
143 region_info.end = 0x1FFFF0000ULL;
developer551250c2023-03-01 16:12:46 +0800144 region_info.region = 5;
developerdfc61e02021-11-15 18:08:10 +0800145 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(&region_info);
151
developerfe2308b2021-11-15 18:07:47 +0800152 dump_emi_mpu_regions();
developere2be2dd2021-08-19 15:34:43 +0800153}
developer551250c2023-03-01 16:12:46 +0800154
155static inline uint64_t get_decoded_phys_addr(uint64_t addr)
156{
157 return (addr << MPU_PHYSICAL_ADDR_SHIFT_BITS);
158}
159
160static inline uint32_t get_decoded_zone_id(uint32_t info)
161{
162 return ((info & 0xFFFF0000) >> MPU_PHYSICAL_ADDR_SHIFT_BITS);
163}
164
165int32_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(&region_info);
190
191 return 0;
192}