blob: daa103c5646e255b13e2bbb27fc975b8a75c0e41 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Alexander Graffa08d392014-04-11 17:09:45 +02002/*
3 * Copyright 2007,2009-2014 Freescale Semiconductor, Inc.
Bin Meng1d636a02021-02-25 17:22:58 +08004 * Copyright (C) 2021, Bin Meng <bmeng.cn@gmail.com>
Alexander Graffa08d392014-04-11 17:09:45 +02005 */
6
7#include <common.h>
8#include <command.h>
Simon Glassb5981472019-11-14 12:57:32 -07009#include <cpu_func.h>
Bin Meng8ee40162021-02-25 17:22:43 +080010#include <dm.h>
Simon Glassc7694dd2019-08-01 09:46:46 -060011#include <env.h>
Simon Glass2cf431c2019-11-14 12:57:47 -070012#include <init.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060013#include <log.h>
Simon Glass90526e92020-05-10 11:39:56 -060014#include <net.h>
Alexander Graffa08d392014-04-11 17:09:45 +020015#include <pci.h>
Simon Glass049f8d62019-12-28 10:44:59 -070016#include <time.h>
Simon Glass401d1c42020-10-30 21:38:53 -060017#include <asm/global_data.h>
Alexander Graffa08d392014-04-11 17:09:45 +020018#include <asm/processor.h>
19#include <asm/mmu.h>
20#include <asm/fsl_pci.h>
21#include <asm/io.h>
Masahiro Yamadab08c8c42018-03-05 01:20:11 +090022#include <linux/libfdt.h>
Alexander Graffa08d392014-04-11 17:09:45 +020023#include <fdt_support.h>
24#include <netdev.h>
25#include <fdtdec.h>
26#include <errno.h>
27#include <malloc.h>
Bin Meng46c9b592021-02-25 17:22:46 +080028#include <virtio_types.h>
29#include <virtio.h>
Alexander Graffa08d392014-04-11 17:09:45 +020030
31DECLARE_GLOBAL_DATA_PTR;
32
33static void *get_fdt_virt(void)
34{
Bin Mengc8f911c2021-02-25 17:22:55 +080035 if (gd->flags & GD_FLG_RELOC)
36 return (void *)gd->fdt_blob;
37 else
38 return (void *)CONFIG_SYS_TMPVIRT;
Alexander Graffa08d392014-04-11 17:09:45 +020039}
40
41static uint64_t get_fdt_phys(void)
42{
43 return (uint64_t)(uintptr_t)gd->fdt_blob;
44}
45
46static void map_fdt_as(int esel)
47{
48 u32 mas0, mas1, mas2, mas3, mas7;
49 uint64_t fdt_phys = get_fdt_phys();
50 unsigned long fdt_phys_tlb = fdt_phys & ~0xffffful;
51 unsigned long fdt_virt_tlb = (ulong)get_fdt_virt() & ~0xffffful;
52
53 mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(esel);
54 mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_1M);
55 mas2 = FSL_BOOKE_MAS2(fdt_virt_tlb, 0);
56 mas3 = FSL_BOOKE_MAS3(fdt_phys_tlb, 0, MAS3_SW|MAS3_SR);
57 mas7 = FSL_BOOKE_MAS7(fdt_phys_tlb);
58
59 write_tlb(mas0, mas1, mas2, mas3, mas7);
60}
61
62uint64_t get_phys_ccsrbar_addr_early(void)
63{
64 void *fdt = get_fdt_virt();
65 uint64_t r;
Tom Rini9f841552017-08-03 08:53:36 -040066 int size, node;
67 u32 naddr;
68 const fdt32_t *prop;
Alexander Graffa08d392014-04-11 17:09:45 +020069
70 /*
71 * To be able to read the FDT we need to create a temporary TLB
72 * map for it.
73 */
74 map_fdt_as(10);
Tom Rini9f841552017-08-03 08:53:36 -040075 node = fdt_path_offset(fdt, "/soc");
76 naddr = fdt_address_cells(fdt, node);
77 prop = fdt_getprop(fdt, node, "ranges", &size);
78 r = fdt_translate_address(fdt, node, prop + naddr);
Alexander Graffa08d392014-04-11 17:09:45 +020079 disable_tlb(10);
80
81 return r;
82}
83
Alexander Graffa08d392014-04-11 17:09:45 +020084int checkboard(void)
85{
86 return 0;
87}
88
Bin Meng8ee40162021-02-25 17:22:43 +080089static int pci_map_region(phys_addr_t paddr, phys_size_t size, ulong *pmap_addr)
Alexander Graffa08d392014-04-11 17:09:45 +020090{
Alexander Graffa08d392014-04-11 17:09:45 +020091 ulong map_addr;
Alexander Graffa08d392014-04-11 17:09:45 +020092
93 if (!pmap_addr)
94 return 0;
95
96 map_addr = *pmap_addr;
97
98 /* Align map_addr */
99 map_addr += size - 1;
100 map_addr &= ~(size - 1);
101
102 if (map_addr + size >= CONFIG_SYS_PCI_MAP_END)
103 return -1;
104
105 /* Map virtual memory for range */
Bin Meng84912a72021-02-25 17:22:25 +0800106 assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
Alexander Graffa08d392014-04-11 17:09:45 +0200107 *pmap_addr = map_addr + size;
108
Alexander Graffa08d392014-04-11 17:09:45 +0200109 return 0;
110}
111
Bin Meng8ee40162021-02-25 17:22:43 +0800112int misc_init_r(void)
Alexander Graffa08d392014-04-11 17:09:45 +0200113{
Bin Meng8ee40162021-02-25 17:22:43 +0800114 struct udevice *dev;
115 struct pci_region *io;
116 struct pci_region *mem;
117 struct pci_region *pre;
Alexander Graffa08d392014-04-11 17:09:45 +0200118 ulong map_addr;
Bin Meng8ee40162021-02-25 17:22:43 +0800119 int ret;
Alexander Graffa08d392014-04-11 17:09:45 +0200120
Bin Meng8ee40162021-02-25 17:22:43 +0800121 /* Ensure PCI is probed */
122 uclass_first_device(UCLASS_PCI, &dev);
123
124 pci_get_regions(dev, &io, &mem, &pre);
Alexander Graffa08d392014-04-11 17:09:45 +0200125
126 /* Start MMIO and PIO range maps above RAM */
127 map_addr = CONFIG_SYS_PCI_MAP_START;
128
Bin Meng8ee40162021-02-25 17:22:43 +0800129 /* Map MMIO range */
130 ret = pci_map_region(mem->phys_start, mem->size, &map_addr);
131 if (ret)
132 return ret;
Alexander Graffa08d392014-04-11 17:09:45 +0200133
Bin Meng8ee40162021-02-25 17:22:43 +0800134 /* Map PIO range */
135 ret = pci_map_region(io->phys_start, io->size, &map_addr);
136 if (ret)
137 return ret;
Alexander Graffa08d392014-04-11 17:09:45 +0200138
Bin Meng46c9b592021-02-25 17:22:46 +0800139 /*
140 * Make sure virtio bus is enumerated so that peripherals
141 * on the virtio bus can be discovered by their drivers.
142 */
143 virtio_init();
144
Bin Mengc8f911c2021-02-25 17:22:55 +0800145 /*
146 * U-Boot is relocated to RAM already, let's delete the temporary FDT
147 * virtual-physical mapping that was used in the pre-relocation phase.
148 */
149 disable_tlb(find_tlb_idx((void *)CONFIG_SYS_TMPVIRT, 1));
150
Bin Meng8ee40162021-02-25 17:22:43 +0800151 return 0;
Alexander Graffa08d392014-04-11 17:09:45 +0200152}
153
154int last_stage_init(void)
155{
156 void *fdt = get_fdt_virt();
157 int len = 0;
158 const uint64_t *prop;
159 int chosen;
160
161 chosen = fdt_path_offset(fdt, "/chosen");
162 if (chosen < 0) {
163 printf("Couldn't find /chosen node in fdt\n");
164 return -EIO;
165 }
166
167 /* -kernel boot */
168 prop = fdt_getprop(fdt, chosen, "qemu,boot-kernel", &len);
169 if (prop && (len >= 8))
Simon Glass018f5302017-08-03 12:22:10 -0600170 env_set_hex("qemu_kernel_addr", *prop);
Alexander Graffa08d392014-04-11 17:09:45 +0200171
Alexander Graffa08d392014-04-11 17:09:45 +0200172 return 0;
173}
174
175static uint64_t get_linear_ram_size(void)
176{
177 void *fdt = get_fdt_virt();
178 const void *prop;
179 int memory;
180 int len;
181
182 memory = fdt_path_offset(fdt, "/memory");
183 prop = fdt_getprop(fdt, memory, "reg", &len);
184
185 if (prop && len >= 16)
186 return *(uint64_t *)(prop+8);
187
188 panic("Couldn't determine RAM size");
189}
190
Alexander Graffa08d392014-04-11 17:09:45 +0200191phys_size_t fsl_ddr_sdram_size(void)
192{
193 return get_linear_ram_size();
194}
195
196void init_tlbs(void)
197{
198 phys_size_t ram_size;
199
200 /*
201 * Create a temporary AS=1 map for the fdt
202 *
203 * We use ESEL=0 here to overwrite the previous AS=0 map for ourselves
204 * which was only 4k big. This way we don't have to clear any other maps.
205 */
206 map_fdt_as(0);
207
208 /* Fetch RAM size from the fdt */
209 ram_size = get_linear_ram_size();
210
211 /* And remove our fdt map again */
212 disable_tlb(0);
213
214 /* Create an internal map of manually created TLB maps */
215 init_used_tlb_cams();
216
217 /* Create a dynamic AS=0 CCSRBAR mapping */
218 assert(!tlb_map_range(CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
219 1024 * 1024, TLB_MAP_IO));
220
221 /* Create a RAM map that spans all accessible RAM */
222 setup_ddr_tlbs(ram_size >> 20);
223
224 /* Create a map for the TLB */
225 assert(!tlb_map_range((ulong)get_fdt_virt(), get_fdt_phys(),
226 1024 * 1024, TLB_MAP_RAM));
227}
228
Alexander Graffa08d392014-04-11 17:09:45 +0200229static uint32_t get_cpu_freq(void)
230{
231 void *fdt = get_fdt_virt();
232 int cpus_node = fdt_path_offset(fdt, "/cpus");
233 int cpu_node = fdt_first_subnode(fdt, cpus_node);
234 const char *prop = "clock-frequency";
235 return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0);
236}
237
238void get_sys_info(sys_info_t *sys_info)
239{
240 int freq = get_cpu_freq();
241
242 memset(sys_info, 0, sizeof(sys_info_t));
243 sys_info->freq_systembus = freq;
244 sys_info->freq_ddrbus = freq;
245 sys_info->freq_processor[0] = freq;
246}
247
Simon Glassd96c2602019-12-28 10:44:58 -0700248int get_clocks(void)
Alexander Graffa08d392014-04-11 17:09:45 +0200249{
250 sys_info_t sys_info;
251
252 get_sys_info(&sys_info);
253
254 gd->cpu_clk = sys_info.freq_processor[0];
255 gd->bus_clk = sys_info.freq_systembus;
256 gd->mem_clk = sys_info.freq_ddrbus;
257 gd->arch.lbc_clk = sys_info.freq_ddrbus;
258
259 return 0;
260}
261
Simon Glass049f8d62019-12-28 10:44:59 -0700262unsigned long get_tbclk(void)
Alexander Graffa08d392014-04-11 17:09:45 +0200263{
264 void *fdt = get_fdt_virt();
265 int cpus_node = fdt_path_offset(fdt, "/cpus");
266 int cpu_node = fdt_first_subnode(fdt, cpus_node);
267 const char *prop = "timebase-frequency";
268 return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0);
269}
270
271/********************************************
272 * get_bus_freq
273 * return system bus freq in Hz
274 *********************************************/
Simon Glassd96c2602019-12-28 10:44:58 -0700275ulong get_bus_freq(ulong dummy)
Alexander Graffa08d392014-04-11 17:09:45 +0200276{
277 sys_info_t sys_info;
278 get_sys_info(&sys_info);
279 return sys_info.freq_systembus;
280}
Alexander Grafb5395342014-04-30 19:21:10 +0200281
282/*
283 * Return the number of cores on this SOC.
284 */
285int cpu_numcores(void)
286{
287 /*
288 * The QEMU u-boot target only needs to drive the first core,
289 * spinning and device tree nodes get driven by QEMU itself
290 */
291 return 1;
292}
293
294/*
295 * Return a 32-bit mask indicating which cores are present on this SOC.
296 */
297u32 cpu_mask(void)
298{
299 return (1 << cpu_numcores()) - 1;
300}
Bin Mengc1979d72021-02-25 17:22:30 +0800301
302/**
303 * Return the virtual address of FDT that was passed by QEMU
304 *
305 * @return virtual address of FDT received from QEMU in r3 register
306 */
307void *board_fdt_blob_setup(void)
308{
309 return get_fdt_virt();
310}
Bin Meng2e91e8b2021-02-25 17:22:39 +0800311
312/* See CONFIG_SYS_NS16550_CLK in arch/powerpc/include/asm/config.h */
313int get_serial_clock(void)
314{
315 return get_bus_freq(0);
316}