blob: b680015c0bb2fb983d1637fb2424c701e8f46a2d [file] [log] [blame]
Caleb Connollye6c284b2023-11-20 20:48:00 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Common initialisation for Qualcomm Snapdragon boards.
4 *
5 * Copyright (c) 2023 Linaro Ltd.
6 * Author: Caleb Connolly <caleb.connolly@linaro.org>
7 */
8
9#define LOG_DEBUG
10
11#include <asm/armv8/mmu.h>
12#include <asm/gpio.h>
13#include <asm/io.h>
14#include <asm/psci.h>
15#include <asm/system.h>
16#include <dm/device.h>
17#include <env.h>
18#include <init.h>
19#include <linux/arm-smccc.h>
20#include <linux/bug.h>
21#include <linux/psci.h>
22#include <linux/sizes.h>
Caleb Connolly16da8c72023-10-03 11:35:40 +010023#include <lmb.h>
Caleb Connollye6c284b2023-11-20 20:48:00 +000024#include <malloc.h>
25
26DECLARE_GLOBAL_DATA_PTR;
27
28static struct mm_region rbx_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { { 0 } };
29
30struct mm_region *mem_map = rbx_mem_map;
31
32int dram_init(void)
33{
34 return fdtdec_setup_mem_size_base();
35}
36
37int dram_init_banksize(void)
38{
39 int ret;
40 phys_addr_t start, size;
41
42 ret = fdtdec_setup_memory_banksize();
43 if (ret < 0)
44 return ret;
45
46 if (WARN(CONFIG_NR_DRAM_BANKS < 2, "CONFIG_NR_DRAM_BANKS should be at least 2"))
47 return 0;
48
49 /* Some bootloaders populate the RAM banks in the wrong order -_- */
50 start = gd->bd->bi_dram[1].start;
51 size = gd->bd->bi_dram[1].size;
52 if (size && start < gd->bd->bi_dram[0].start) {
53 debug("Swapping DRAM banks\n");
54 gd->bd->bi_dram[1].start = gd->bd->bi_dram[0].start;
55 gd->bd->bi_dram[1].size = gd->bd->bi_dram[0].size;
56 gd->bd->bi_dram[0].start = start;
57 gd->bd->bi_dram[0].size = size;
58 }
59
60 return 0;
61}
62
63static void show_psci_version(void)
64{
65 struct arm_smccc_res res;
66
67 arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
68
69 debug("PSCI: v%ld.%ld\n",
70 PSCI_VERSION_MAJOR(res.a0),
71 PSCI_VERSION_MINOR(res.a0));
72}
73
74void *board_fdt_blob_setup(int *err)
75{
76 phys_addr_t fdt;
77 /* Return DTB pointer passed by ABL */
78 *err = 0;
79 fdt = get_prev_bl_fdt_addr();
80
81 /*
82 * If we bail then the board will simply not boot, instead let's
83 * try and use the FDT built into U-Boot if there is one...
84 * This avoids having a hard dependency on the previous stage bootloader
85 */
86 if (IS_ENABLED(CONFIG_OF_SEPARATE) && (!fdt || fdt != ALIGN(fdt, SZ_4K))) {
87 debug("%s: Using built in FDT, bootloader gave us %#llx\n", __func__, fdt);
88 return (void *)gd->fdt_blob;
89 }
90
91 return (void *)fdt;
92}
93
94void reset_cpu(void)
95{
96 psci_system_reset();
97}
98
99/*
100 * Some boards still need board specific init code, they can implement that by
101 * overriding this function.
102 *
103 * FIXME: get rid of board specific init code
104 */
105void __weak qcom_board_init(void)
106{
107}
108
109int board_init(void)
110{
111 show_psci_version();
112 qcom_board_init();
113 return 0;
114}
115
Caleb Connolly16da8c72023-10-03 11:35:40 +0100116void __weak qcom_late_init(void)
117{
118}
119
120#define KERNEL_COMP_SIZE SZ_64M
121#define SZ_96M (SZ_64M + SZ_32M)
122
123#define addr_alloc(lmb, size) lmb_alloc(lmb, size, SZ_2M)
124
125/* Stolen from arch/arm/mach-apple/board.c */
126int board_late_init(void)
127{
128 struct lmb lmb;
129 u32 status = 0;
130
131 lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
132
133 /* We need to be fairly conservative here as we support boards with just 1G of TOTAL RAM */
134 status |= env_set_hex("kernel_addr_r", addr_alloc(&lmb, SZ_128M));
135 status |= env_set_hex("ramdisk_addr_r", addr_alloc(&lmb, SZ_96M));
136 status |= env_set_hex("kernel_comp_addr_r", addr_alloc(&lmb, KERNEL_COMP_SIZE));
137 status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
138 status |= env_set_hex("scriptaddr", addr_alloc(&lmb, SZ_4M));
139 status |= env_set_hex("pxefile_addr_r", addr_alloc(&lmb, SZ_4M));
140 status |= env_set_hex("fdt_addr_r", addr_alloc(&lmb, SZ_2M));
141
142 if (status)
143 log_warning("%s: Failed to set run time variables\n", __func__);
144
145 qcom_late_init();
146
147 return 0;
148}
149
Caleb Connollye6c284b2023-11-20 20:48:00 +0000150static void build_mem_map(void)
151{
152 int i;
153
154 /*
155 * Ensure the peripheral block is sized to correctly cover the address range
156 * up to the first memory bank.
157 * Don't map the first page to ensure that we actually trigger an abort on a
158 * null pointer access rather than just hanging.
159 * FIXME: we should probably split this into more precise regions
160 */
161 mem_map[0].phys = 0x1000;
162 mem_map[0].virt = mem_map[0].phys;
163 mem_map[0].size = gd->bd->bi_dram[0].start - mem_map[0].phys;
164 mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
165 PTE_BLOCK_NON_SHARE |
166 PTE_BLOCK_PXN | PTE_BLOCK_UXN;
167
168 debug("Configured memory map:\n");
169 debug(" 0x%016llx - 0x%016llx: Peripheral block\n",
170 mem_map[0].phys, mem_map[0].phys + mem_map[0].size);
171
172 /*
173 * Now add memory map entries for each DRAM bank, ensuring we don't
174 * overwrite the list terminator
175 */
176 for (i = 0; i < ARRAY_SIZE(rbx_mem_map) - 2 && gd->bd->bi_dram[i].size; i++) {
177 if (i == ARRAY_SIZE(rbx_mem_map) - 1) {
178 log_warning("Too many DRAM banks!\n");
179 break;
180 }
181 mem_map[i + 1].phys = gd->bd->bi_dram[i].start;
182 mem_map[i + 1].virt = mem_map[i + 1].phys;
183 mem_map[i + 1].size = gd->bd->bi_dram[i].size;
184 mem_map[i + 1].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
185 PTE_BLOCK_INNER_SHARE;
186
187 debug(" 0x%016llx - 0x%016llx: DDR bank %d\n",
188 mem_map[i + 1].phys, mem_map[i + 1].phys + mem_map[i + 1].size, i);
189 }
190}
191
192u64 get_page_table_size(void)
193{
194 return SZ_64K;
195}
196
197void enable_caches(void)
198{
199 build_mem_map();
200
201 icache_enable();
202 dcache_enable();
203}