1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2007,2009-2014 Freescale Semiconductor, Inc.
17 #include <dm/simple_bus.h>
18 #include <dm/uclass-internal.h>
19 #include <asm/global_data.h>
20 #include <asm/processor.h>
22 #include <asm/fsl_pci.h>
24 #include <linux/libfdt.h>
25 #include <fdt_support.h>
30 #include <virtio_types.h>
33 DECLARE_GLOBAL_DATA_PTR;
35 static void *get_fdt_virt(void)
37 if (gd->flags & GD_FLG_RELOC)
38 return (void *)gd->fdt_blob;
40 return (void *)CONFIG_SYS_TMPVIRT;
43 static uint64_t get_fdt_phys(void)
45 return (uint64_t)(uintptr_t)gd->fdt_blob;
48 static void map_fdt_as(int esel)
50 u32 mas0, mas1, mas2, mas3, mas7;
51 uint64_t fdt_phys = get_fdt_phys();
52 unsigned long fdt_phys_tlb = fdt_phys & ~0xffffful;
53 unsigned long fdt_virt_tlb = (ulong)get_fdt_virt() & ~0xffffful;
55 mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(esel);
56 mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_1M);
57 mas2 = FSL_BOOKE_MAS2(fdt_virt_tlb, 0);
58 mas3 = FSL_BOOKE_MAS3(fdt_phys_tlb, 0, MAS3_SW|MAS3_SR);
59 mas7 = FSL_BOOKE_MAS7(fdt_phys_tlb);
61 write_tlb(mas0, mas1, mas2, mas3, mas7);
64 uint64_t get_phys_ccsrbar_addr_early(void)
66 void *fdt = get_fdt_virt();
73 * To be able to read the FDT we need to create a temporary TLB
77 node = fdt_path_offset(fdt, "/soc");
78 naddr = fdt_address_cells(fdt, node);
79 prop = fdt_getprop(fdt, node, "ranges", &size);
80 r = fdt_translate_address(fdt, node, prop + naddr);
91 static int pci_map_region(phys_addr_t paddr, phys_size_t size, ulong *pmap_addr)
98 map_addr = *pmap_addr;
101 map_addr += size - 1;
102 map_addr &= ~(size - 1);
104 if (map_addr + size >= CONFIG_SYS_PCI_MAP_END)
107 /* Map virtual memory for range */
108 assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
109 *pmap_addr = map_addr + size;
114 static void platform_bus_map_region(ulong map_addr, phys_addr_t paddr,
118 map_addr += size - 1;
119 map_addr &= ~(size - 1);
121 /* Map virtual memory for range */
122 assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
125 int misc_init_r(void)
128 struct pci_region *io;
129 struct pci_region *mem;
130 struct pci_region *pre;
134 /* Ensure PCI is probed */
135 uclass_first_device(UCLASS_PCI, &dev);
137 pci_get_regions(dev, &io, &mem, &pre);
139 /* Start MMIO and PIO range maps above RAM */
140 map_addr = CONFIG_SYS_PCI_MAP_START;
143 ret = pci_map_region(mem->phys_start, mem->size, &map_addr);
148 ret = pci_map_region(io->phys_start, io->size, &map_addr);
153 * Make sure virtio bus is enumerated so that peripherals
154 * on the virtio bus can be discovered by their drivers.
159 * U-Boot is relocated to RAM already, let's delete the temporary FDT
160 * virtual-physical mapping that was used in the pre-relocation phase.
162 disable_tlb(find_tlb_idx((void *)CONFIG_SYS_TMPVIRT, 1));
165 * Detect the presence of the platform bus node, and
166 * create a virtual memory mapping for it.
168 for (ret = uclass_find_first_device(UCLASS_SIMPLE_BUS, &dev);
170 ret = uclass_find_next_device(&dev)) {
171 if (device_is_compatible(dev, "qemu,platform")) {
172 struct simple_bus_plat *plat = dev_get_uclass_plat(dev);
174 platform_bus_map_region(CONFIG_PLATFORM_BUS_MAP_ADDR,
175 plat->target, plat->size);
183 int last_stage_init(void)
185 void *fdt = get_fdt_virt();
187 const uint64_t *prop;
190 chosen = fdt_path_offset(fdt, "/chosen");
192 printf("Couldn't find /chosen node in fdt\n");
197 prop = fdt_getprop(fdt, chosen, "qemu,boot-kernel", &len);
198 if (prop && (len >= 8))
199 env_set_hex("qemu_kernel_addr", *prop);
204 static uint64_t get_linear_ram_size(void)
206 void *fdt = get_fdt_virt();
211 memory = fdt_path_offset(fdt, "/memory");
212 prop = fdt_getprop(fdt, memory, "reg", &len);
214 if (prop && len >= 16)
215 return *(uint64_t *)(prop+8);
217 panic("Couldn't determine RAM size");
220 phys_size_t fsl_ddr_sdram_size(void)
222 return get_linear_ram_size();
227 phys_size_t ram_size;
230 * Create a temporary AS=1 map for the fdt
232 * We use ESEL=0 here to overwrite the previous AS=0 map for ourselves
233 * which was only 4k big. This way we don't have to clear any other maps.
237 /* Fetch RAM size from the fdt */
238 ram_size = get_linear_ram_size();
240 /* And remove our fdt map again */
243 /* Create an internal map of manually created TLB maps */
244 init_used_tlb_cams();
246 /* Create a dynamic AS=0 CCSRBAR mapping */
247 assert(!tlb_map_range(CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
248 1024 * 1024, TLB_MAP_IO));
250 /* Create a RAM map that spans all accessible RAM */
251 setup_ddr_tlbs(ram_size >> 20);
253 /* Create a map for the TLB */
254 assert(!tlb_map_range((ulong)get_fdt_virt(), get_fdt_phys(),
255 1024 * 1024, TLB_MAP_RAM));
258 static uint32_t get_cpu_freq(void)
260 void *fdt = get_fdt_virt();
261 int cpus_node = fdt_path_offset(fdt, "/cpus");
262 int cpu_node = fdt_first_subnode(fdt, cpus_node);
263 const char *prop = "clock-frequency";
264 return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0);
267 void get_sys_info(sys_info_t *sys_info)
269 int freq = get_cpu_freq();
271 memset(sys_info, 0, sizeof(sys_info_t));
272 sys_info->freq_systembus = freq;
273 sys_info->freq_ddrbus = freq;
274 sys_info->freq_processor[0] = freq;
281 get_sys_info(&sys_info);
283 gd->cpu_clk = sys_info.freq_processor[0];
284 gd->bus_clk = sys_info.freq_systembus;
285 gd->mem_clk = sys_info.freq_ddrbus;
286 gd->arch.lbc_clk = sys_info.freq_ddrbus;
291 unsigned long get_tbclk(void)
293 void *fdt = get_fdt_virt();
294 int cpus_node = fdt_path_offset(fdt, "/cpus");
295 int cpu_node = fdt_first_subnode(fdt, cpus_node);
296 const char *prop = "timebase-frequency";
297 return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0);
300 /********************************************
302 * return system bus freq in Hz
303 *********************************************/
304 ulong get_bus_freq(ulong dummy)
307 get_sys_info(&sys_info);
308 return sys_info.freq_systembus;
312 * Return the number of cores on this SOC.
314 int cpu_numcores(void)
317 * The QEMU u-boot target only needs to drive the first core,
318 * spinning and device tree nodes get driven by QEMU itself
324 * Return a 32-bit mask indicating which cores are present on this SOC.
328 return (1 << cpu_numcores()) - 1;
332 * Return the virtual address of FDT that was passed by QEMU
334 * Return: virtual address of FDT received from QEMU in r3 register
336 void *board_fdt_blob_setup(int *err)
339 return get_fdt_virt();
342 /* See CONFIG_SYS_NS16550_CLK in arch/powerpc/include/asm/config.h */
343 int get_serial_clock(void)
345 return get_bus_freq(0);