blob: 71982ba4d20620dbc0c90f437a1817fe6494eb5d [file] [log] [blame]
developer2de1f362025-01-23 16:55:01 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2024 MediaTek Inc.
4 *
5 * Author: Weijie Gao <weijie.gao@mediatek.com>
6 */
7
8#include <errno.h>
9#include <stdio.h>
10#include <asm/global_data.h>
11#include <linux/kernel.h>
12#include <linux/arm-smccc.h>
13#include <linux/sizes.h>
14#include <command.h>
15#include <fdtdec.h>
16#include <fdt_support.h>
17#include <lmb.h>
18
19DECLARE_GLOBAL_DATA_PTR;
20
21#define MTK_SIP_GET_BL31_REGION 0x82000300
22#define MTK_SIP_GET_BL32_REGION 0x82000301
23
24#define BL31_DEFAULT_ADDR 0x43000000
25#define BL31_DEFAULT_SIZE 0x80000
26
27#define TZ_REGION_MAX_SIZE SZ_16M
28#define U_BOOT_MIN_SIZE SZ_4M
29#define U_BOOT_MIN_STACK_SIZE SZ_1M
30#define REGION_ALIGNMENT SZ_64K
31
32struct tz_reserved_region {
33 phys_addr_t addr;
34 phys_addr_t size;
35};
36
37static bool fix_tz_region(struct tz_reserved_region region[],
38 uint32_t used_regions)
39{
40 phys_addr_t size;
41
42 if (region[0].addr + region[0].size > gd->ram_top) {
43 if (region[0].addr >= gd->ram_top) {
44 debug("Discarded region 0x%08llx, size 0x%llx\n",
45 region[0].addr, region[0].size);
46
47 if (used_regions > 1)
48 region[0] = region[1];
49
50 return true;
51 }
52
53 size = gd->ram_top - region[0].addr;
54
55 debug("Truncated region 0x%08llx, size 0x%llx -> 0x%llx\n",
56 region[0].addr, region[0].size, size);
57
58 region[0].size = size;
59 }
60
61 return false;
62}
63
64phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
65{
66 phys_addr_t uboot_ram_top, pstore_size, uboot_size = 0;
67 struct tz_reserved_region region[2], tmp;
68 phys_addr_t top_addr, low_addr;
69 struct arm_smccc_res res;
70 u32 used_regions = 1;
71
72 /* BL31 region */
73 arm_smccc_smc(MTK_SIP_GET_BL31_REGION, 0, 0, 0, 0, 0, 0, 0, &res);
74 if (res.a0) {
75 /* Assume PIE is not enabled for BL31 */
76 region[0].addr = BL31_DEFAULT_ADDR;
77 region[0].size = BL31_DEFAULT_SIZE;
78 } else {
79 region[0].addr = res.a1;
80 region[0].size = res.a2;
81 }
82
83 debug("BL31 @ 0x%08llx, size 0x%llx\n", region[0].addr,
84 region[0].size);
85
86 /* BL32 region is optional */
87 arm_smccc_smc(MTK_SIP_GET_BL32_REGION, 0, 0, 0, 0, 0, 0, 0, &res);
88 if (!res.a0 && res.a1 && res.a2) {
89 region[used_regions].addr = res.a1;
90 region[used_regions].size = res.a2;
91
92 debug("BL32 @ 0x%08llx, size 0x%llx\n",
93 region[used_regions].addr, region[used_regions].size);
94
95 used_regions++;
96 }
97
98 if (used_regions == 2) {
99 if (region[0].addr < region[1].addr) {
100 /* Make sure region[0] is higher than region[1] */
101 tmp = region[0];
102 region[0] = region[1];
103 region[1] = tmp;
104 }
105
106 top_addr = region[0].addr + region[0].size;
107 low_addr = min_t(phys_addr_t, region[0].addr, region[1].addr);
108
109 if (top_addr - low_addr <= TZ_REGION_MAX_SIZE) {
110 /* Merge region if they're overlapped or close enough */
111 region[0].size = top_addr - low_addr;
112 region[0].addr = low_addr;
113
114 debug("Merged region @ 0x%08llx, size 0x%llx\n",
115 region[0].addr, region[0].size);
116
117 used_regions = 1;
118 }
119 }
120
121 debug("Effective memory @ 0x%08zx, size 0x%llx\n", gd->ram_base,
122 gd->ram_top - gd->ram_base);
123
124 /* Discard/fix region which is outside the effective memory */
125 if (fix_tz_region(region, used_regions)) {
126 used_regions--;
127
128 if (used_regions) {
129 if (fix_tz_region(region, used_regions))
130 used_regions--;
131 }
132 }
133
134 /* Size needed for u-boot & pstore */
135#if IS_ENABLED(CONFIG_CMD_PSTORE)
136 /* pstore will be placed under ram top */
137 pstore_size = (CONFIG_CMD_PSTORE_MEM_SIZE + REGION_ALIGNMENT - 1) &
138 ~(REGION_ALIGNMENT - 1);
139 /* u-boot will be placed under pstore */
140 uboot_size += pstore_size;
141#endif
142
143 uboot_size += max_t(uintptr_t, U_BOOT_MIN_SIZE, total_size);
144 uboot_size += U_BOOT_MIN_STACK_SIZE + REGION_ALIGNMENT - 1;
145 uboot_size &= ~(REGION_ALIGNMENT - 1);
146
147 uboot_ram_top = gd->ram_top & ~(REGION_ALIGNMENT - 1);
148
149 if (!used_regions ||
150 (uboot_ram_top - region[0].addr - region[0].size >= uboot_size)) {
151 /* No reserved region present,
152 * or gap between high region and ram top is large enough
153 */
154 uboot_ram_top -= pstore_size;
155 return uboot_ram_top;
156 }
157
158 uboot_ram_top = region[0].addr & ~(REGION_ALIGNMENT - 1);
159
160 if (used_regions == 2 &&
161 (uboot_ram_top - region[1].addr - region[1].size >= uboot_size)) {
162 /* Gap between high region and low region is large enough */
163 uboot_ram_top -= pstore_size;
164 return uboot_ram_top;
165 }
166
167 uboot_ram_top = region[used_regions - 1].addr & ~(REGION_ALIGNMENT - 1);
168
169 /* Under low region */
170 uboot_ram_top -= pstore_size;
171 return uboot_ram_top;
172}
173
174int arch_misc_init(void)
175{
176 struct arm_smccc_res res;
177
178 /*
179 * Since board_get_usable_ram_top is be called before arch_misc_init,
180 * there's no need to check the result
181 */
182 arm_smccc_smc(MTK_SIP_GET_BL31_REGION, 0, 0, 0, 0, 0, 0, 0, &res);
183 lmb_reserve(res.a1, res.a2, LMB_NOMAP);
184
185 arm_smccc_smc(MTK_SIP_GET_BL32_REGION, 0, 0, 0, 0, 0, 0, 0, &res);
186 if (!res.a0 && res.a1 && res.a2)
187 lmb_reserve(res.a1, res.a2, LMB_NOMAP);
188
189#if IS_ENABLED(CONFIG_CMD_PSTORE)
190 char cmd[64];
191
192 /* Override default pstore address */
193 snprintf(cmd, sizeof(cmd), "pstore set 0x%llx 0x%x", gd->ram_top,
194 CONFIG_CMD_PSTORE_MEM_SIZE);
195 run_command(cmd, 0);
196#endif
197
198 return 0;
199}
200
201/* For board-level setup */
202__weak int mtk_ft_system_setup(void *blob, struct bd_info *bd)
203{
204 return 0;
205}
206
207int ft_system_setup(void *blob, struct bd_info *bd)
208{
209 struct arm_smccc_res res;
210 struct fdt_memory mem;
211 int ret;
212
213 arm_smccc_smc(MTK_SIP_GET_BL31_REGION, 0, 0, 0, 0, 0, 0, 0, &res);
214
215 mem.start = res.a1;
216 mem.end = res.a1 + res.a2 - 1;
217
218 ret = fdtdec_add_reserved_memory(blob, "secmon", &mem, NULL, 0, NULL,
219 FDTDEC_RESERVED_MEMORY_NO_MAP);
220 if (ret < 0) {
221 log_err("Failed to add reserved-memory for BL31: %s\n",
222 fdt_strerror(ret));
223 return ret;
224 }
225
226 arm_smccc_smc(MTK_SIP_GET_BL32_REGION, 0, 0, 0, 0, 0, 0, 0, &res);
227 if (!res.a0 && res.a1 && res.a2) {
228 mem.start = res.a1;
229 mem.end = res.a1 + res.a2 - 1;
230
231 ret = fdtdec_add_reserved_memory(blob, "trustzone", &mem, NULL,
232 0, NULL,
233 FDTDEC_RESERVED_MEMORY_NO_MAP);
234 if (ret < 0) {
235 log_err("Failed to add reserved-memory for BL32: %s\n",
236 fdt_strerror(ret));
237 return ret;
238 }
239 }
240
241 return mtk_ft_system_setup(blob, bd);
242}