blob: 233ed4f5e5ac0079d5cff656272936c7f6b1d1d6 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2015 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <reg.h>
24#include <err.h>
25#include <debug.h>
26#include <trace.h>
27#include <libfdt.h>
28
29#include <dev/uart.h>
30#include <arch.h>
31#include <arch/arm64.h>
32#include <arch/arm64/mmu.h>
33#include <lk/init.h>
34#include <kernel/vm.h>
35#include <kernel/spinlock.h>
36#include <dev/timer/arm_generic.h>
37#include <platform.h>
38#include <platform/interrupts.h>
39#include <platform/bcm2837.h>
40
41extern void intc_init(void);
42extern void arm_reset(void);
43
44/* initial memory mappings. parsed by start.S */
45struct mmu_initial_mapping mmu_initial_mappings[] = {
46 /* 1GB of sdram space */
47 {
48 .phys = SDRAM_BASE,
49 .virt = KERNEL_BASE,
50 .size = MEMORY_APERTURE_SIZE,
51 .flags = 0,
52 .name = "memory"
53 },
54
55 /* peripherals */
56 {
57 .phys = BCM_PERIPH_BASE_PHYS,
58 .virt = BCM_PERIPH_BASE_VIRT,
59 .size = BCM_PERIPH_SIZE,
60 .flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
61 .name = "bcm peripherals"
62 },
63
64 /* null entry to terminate the list */
65 { 0 }
66};
67
68static pmm_arena_t arena = {
69 .name = "sdram",
70 .base = SDRAM_BASE,
71 .size = MEMSIZE,
72 .flags = PMM_ARENA_FLAG_KMAP,
73};
74
75void platform_init_mmu_mappings(void)
76{
77}
78
79void platform_early_init(void)
80{
81 uart_init_early();
82
83 intc_init();
84
85 arm_generic_timer_init(INTERRUPT_ARM_LOCAL_CNTPNSIRQ, 1000000);
86
87
88 /* look for a flattened device tree just before the kernel */
89 const void *fdt = (void *)KERNEL_BASE;
90 int err = fdt_check_header(fdt);
91 if (err >= 0) {
92 /* walk the nodes, looking for 'memory' */
93 int depth = 0;
94 int offset = 0;
95 for (;;) {
96 offset = fdt_next_node(fdt, offset, &depth);
97 if (offset < 0)
98 break;
99
100 /* get the name */
101 const char *name = fdt_get_name(fdt, offset, NULL);
102 if (!name)
103 continue;
104
105 /* look for the 'memory' property */
106 if (strcmp(name, "memory") == 0) {
107 printf("Found memory in fdt\n");
108 int lenp;
109 const void *prop_ptr = fdt_getprop(fdt, offset, "reg", &lenp);
110 if (prop_ptr && lenp == 0x10) {
111 /* we're looking at a memory descriptor */
112 //uint64_t base = fdt64_to_cpu(*(uint64_t *)prop_ptr);
113 uint64_t len = fdt64_to_cpu(*((const uint64_t *)prop_ptr + 1));
114
115 /* trim size on certain platforms */
116#if ARCH_ARM
117 if (len > 1024*1024*1024U) {
118 len = 1024*1024*1024; /* only use the first 1GB on ARM32 */
119 printf("trimming memory to 1GB\n");
120 }
121#endif
122
123 /* set the size in the pmm arena */
124 arena.size = len;
125 }
126 }
127 }
128 }
129
130 /* add the main memory arena */
131 pmm_add_arena(&arena);
132
133 /* reserve the first 64k of ram, which should be holding the fdt */
134 struct list_node list = LIST_INITIAL_VALUE(list);
135 pmm_alloc_range(MEMBASE, 0x80000 / PAGE_SIZE, &list);
136
137#if WITH_SMP
138 /* start the other cpus */
139 uintptr_t sec_entry = (uintptr_t)&arm_reset;
140 sec_entry -= (KERNEL_BASE - MEMBASE);
141 for (uint i = 1; i <= 3; i++) {
142 *REG32(ARM_LOCAL_BASE + 0x8c + 0x10 * i) = sec_entry;
143 }
144#endif
145}
146
147void platform_init(void)
148{
149 uart_init();
150}
151
152#define DEBUG_UART 1
153
154void platform_dputc(char c)
155{
156 if (c == '\n')
157 uart_putc(DEBUG_UART, '\r');
158 uart_putc(DEBUG_UART, c);
159}
160
161int platform_dgetc(char *c, bool wait)
162{
163 int ret = uart_getc(DEBUG_UART, wait);
164 if (ret == -1)
165 return -1;
166 *c = ret;
167 return 0;
168}
169