1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2021 Mark Kettenis <kettenis@openbsd.org>
8 #include <dm/uclass-internal.h>
9 #include <efi_loader.h>
12 #include <asm/armv8/mmu.h>
13 #include <asm/global_data.h>
15 #include <asm/system.h>
17 DECLARE_GLOBAL_DATA_PTR;
21 static struct mm_region t8103_mem_map[] = {
27 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
29 PTE_BLOCK_PXN | PTE_BLOCK_UXN
35 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
37 PTE_BLOCK_PXN | PTE_BLOCK_UXN
43 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
45 PTE_BLOCK_PXN | PTE_BLOCK_UXN
51 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
53 PTE_BLOCK_PXN | PTE_BLOCK_UXN
59 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
60 PTE_BLOCK_INNER_SHARE |
61 PTE_BLOCK_PXN | PTE_BLOCK_UXN
67 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
68 PTE_BLOCK_INNER_SHARE |
69 PTE_BLOCK_PXN | PTE_BLOCK_UXN
75 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
79 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
80 PTE_BLOCK_INNER_SHARE |
81 PTE_BLOCK_PXN | PTE_BLOCK_UXN
88 /* Apple M1 Pro/Max */
90 static struct mm_region t6000_mem_map[] = {
96 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
98 PTE_BLOCK_PXN | PTE_BLOCK_UXN
104 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
105 PTE_BLOCK_NON_SHARE |
106 PTE_BLOCK_PXN | PTE_BLOCK_UXN
112 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
113 PTE_BLOCK_NON_SHARE |
114 PTE_BLOCK_PXN | PTE_BLOCK_UXN
120 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
121 PTE_BLOCK_INNER_SHARE |
122 PTE_BLOCK_PXN | PTE_BLOCK_UXN
128 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
129 PTE_BLOCK_INNER_SHARE |
130 PTE_BLOCK_PXN | PTE_BLOCK_UXN
136 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
137 PTE_BLOCK_NON_SHARE |
138 PTE_BLOCK_PXN | PTE_BLOCK_UXN
144 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
145 PTE_BLOCK_NON_SHARE |
146 PTE_BLOCK_PXN | PTE_BLOCK_UXN
152 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
153 PTE_BLOCK_NON_SHARE |
154 PTE_BLOCK_PXN | PTE_BLOCK_UXN
157 .virt = 0x1300000000,
158 .phys = 0x1300000000,
160 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
161 PTE_BLOCK_NON_SHARE |
162 PTE_BLOCK_PXN | PTE_BLOCK_UXN
165 .virt = 0x10000000000,
166 .phys = 0x10000000000,
167 .size = 16UL * SZ_1G,
168 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
169 PTE_BLOCK_INNER_SHARE
172 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
173 PTE_BLOCK_INNER_SHARE |
174 PTE_BLOCK_PXN | PTE_BLOCK_UXN
176 /* List terminator */
183 static struct mm_region t6002_mem_map[] = {
189 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
190 PTE_BLOCK_NON_SHARE |
191 PTE_BLOCK_PXN | PTE_BLOCK_UXN
197 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
198 PTE_BLOCK_NON_SHARE |
199 PTE_BLOCK_PXN | PTE_BLOCK_UXN
205 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
206 PTE_BLOCK_NON_SHARE |
207 PTE_BLOCK_PXN | PTE_BLOCK_UXN
213 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
214 PTE_BLOCK_INNER_SHARE |
215 PTE_BLOCK_PXN | PTE_BLOCK_UXN
221 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
222 PTE_BLOCK_INNER_SHARE |
223 PTE_BLOCK_PXN | PTE_BLOCK_UXN
229 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
230 PTE_BLOCK_NON_SHARE |
231 PTE_BLOCK_PXN | PTE_BLOCK_UXN
237 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
238 PTE_BLOCK_NON_SHARE |
239 PTE_BLOCK_PXN | PTE_BLOCK_UXN
245 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
246 PTE_BLOCK_NON_SHARE |
247 PTE_BLOCK_PXN | PTE_BLOCK_UXN
250 .virt = 0x1300000000,
251 .phys = 0x1300000000,
253 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
254 PTE_BLOCK_NON_SHARE |
255 PTE_BLOCK_PXN | PTE_BLOCK_UXN
258 .virt = 0x2280000000,
259 .phys = 0x2280000000,
261 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
262 PTE_BLOCK_NON_SHARE |
263 PTE_BLOCK_PXN | PTE_BLOCK_UXN
266 .virt = 0x2380000000,
267 .phys = 0x2380000000,
269 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
270 PTE_BLOCK_NON_SHARE |
271 PTE_BLOCK_PXN | PTE_BLOCK_UXN
274 .virt = 0x2580000000,
275 .phys = 0x2580000000,
277 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
278 PTE_BLOCK_NON_SHARE |
279 PTE_BLOCK_PXN | PTE_BLOCK_UXN
282 .virt = 0x25a0000000,
283 .phys = 0x25a0000000,
285 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
286 PTE_BLOCK_INNER_SHARE |
287 PTE_BLOCK_PXN | PTE_BLOCK_UXN
290 .virt = 0x25c0000000,
291 .phys = 0x25c0000000,
293 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
294 PTE_BLOCK_INNER_SHARE |
295 PTE_BLOCK_PXN | PTE_BLOCK_UXN
298 .virt = 0x2700000000,
299 .phys = 0x2700000000,
301 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
302 PTE_BLOCK_NON_SHARE |
303 PTE_BLOCK_PXN | PTE_BLOCK_UXN
306 .virt = 0x2b00000000,
307 .phys = 0x2b00000000,
309 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
310 PTE_BLOCK_NON_SHARE |
311 PTE_BLOCK_PXN | PTE_BLOCK_UXN
314 .virt = 0x2f00000000,
315 .phys = 0x2f00000000,
317 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
318 PTE_BLOCK_NON_SHARE |
319 PTE_BLOCK_PXN | PTE_BLOCK_UXN
322 .virt = 0x3300000000,
323 .phys = 0x3300000000,
325 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
326 PTE_BLOCK_NON_SHARE |
327 PTE_BLOCK_PXN | PTE_BLOCK_UXN
330 .virt = 0x10000000000,
331 .phys = 0x10000000000,
332 .size = 16UL * SZ_1G,
333 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
334 PTE_BLOCK_INNER_SHARE
337 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
338 PTE_BLOCK_INNER_SHARE |
339 PTE_BLOCK_PXN | PTE_BLOCK_UXN
341 /* List terminator */
346 struct mm_region *mem_map;
355 return fdtdec_setup_mem_size_base();
358 int dram_init_banksize(void)
360 return fdtdec_setup_memory_banksize();
363 extern long fw_dtb_pointer;
365 void *board_fdt_blob_setup(int *err)
367 /* Return DTB pointer passed by m1n1 */
369 return (void *)fw_dtb_pointer;
372 void build_mem_map(void)
379 if (of_machine_is_compatible("apple,t8103") ||
380 of_machine_is_compatible("apple,t8112"))
381 mem_map = t8103_mem_map;
382 else if (of_machine_is_compatible("apple,t6000"))
383 mem_map = t6000_mem_map;
384 else if (of_machine_is_compatible("apple,t6001"))
385 mem_map = t6000_mem_map;
386 else if (of_machine_is_compatible("apple,t6002"))
387 mem_map = t6002_mem_map;
389 panic("Unsupported SoC\n");
391 /* Find list terminator. */
392 for (i = 0; mem_map[i].size || mem_map[i].attrs; i++)
395 /* Align RAM mapping to page boundaries */
396 base = gd->bd->bi_dram[0].start;
397 size = gd->bd->bi_dram[0].size;
398 size += (base - ALIGN_DOWN(base, SZ_4K));
399 base = ALIGN_DOWN(base, SZ_4K);
400 size = ALIGN(size, SZ_4K);
402 /* Update RAM mapping */
403 mem_map[i - 2].virt = base;
404 mem_map[i - 2].phys = base;
405 mem_map[i - 2].size = size;
407 node = ofnode_path("/chosen/framebuffer");
408 if (!ofnode_valid(node))
411 base = ofnode_get_addr_size(node, "reg", &size);
412 if (base == FDT_ADDR_T_NONE)
415 /* Align framebuffer mapping to page boundaries */
416 size += (base - ALIGN_DOWN(base, SZ_4K));
417 base = ALIGN_DOWN(base, SZ_4K);
418 size = ALIGN(size, SZ_4K);
420 /* Add framebuffer mapping */
421 mem_map[i - 1].virt = base;
422 mem_map[i - 1].phys = base;
423 mem_map[i - 1].size = size;
426 void enable_caches(void)
434 u64 get_page_table_size(void)
439 #define KERNEL_COMP_SIZE SZ_128M
441 int board_late_init(void)
446 lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
448 /* somewhat based on the Linux Kernel boot requirements:
449 * align by 2M and maximal FDT size 2M
451 status |= env_set_hex("loadaddr", lmb_alloc(&lmb, SZ_1G, SZ_2M));
452 status |= env_set_hex("fdt_addr_r", lmb_alloc(&lmb, SZ_2M, SZ_2M));
453 status |= env_set_hex("kernel_addr_r", lmb_alloc(&lmb, SZ_128M, SZ_2M));
454 status |= env_set_hex("ramdisk_addr_r", lmb_alloc(&lmb, SZ_1G, SZ_2M));
455 status |= env_set_hex("kernel_comp_addr_r",
456 lmb_alloc(&lmb, KERNEL_COMP_SIZE, SZ_2M));
457 status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
458 status |= env_set_hex("scriptaddr", lmb_alloc(&lmb, SZ_4M, SZ_2M));
459 status |= env_set_hex("pxefile_addr_r", lmb_alloc(&lmb, SZ_4M, SZ_2M));
462 log_warning("late_init: Failed to set run time variables\n");
467 int ft_board_setup(void *blob, struct bd_info *bd)
470 const char *stdoutname;
474 * Modify the "stdout-path" property under "/chosen" to point
475 * at "/chosen/framebuffer if a keyboard is available and
476 * we're not running under the m1n1 hypervisor.
477 * Developers can override this behaviour by dropping
478 * "vidconsole" from the "stdout" environment variable.
481 /* EL1 means we're running under the m1n1 hypervisor. */
482 if (current_el() == 1)
485 ret = uclass_find_device(UCLASS_KEYBOARD, 0, &dev);
489 stdoutname = env_get("stdout");
490 if (!stdoutname || !strstr(stdoutname, "vidconsole"))
493 /* Make sure we actually have a framebuffer. */
494 node = fdt_path_offset(blob, "/chosen/framebuffer");
495 if (node < 0 || !fdtdec_get_is_enabled(blob, node))
498 node = fdt_path_offset(blob, "/chosen");
501 fdt_setprop_string(blob, node, "stdout-path", "/chosen/framebuffer");