]> Git Repo - u-boot.git/blob - board/emulation/qemu-ppce500/qemu-ppce500.c
doc: replace @return by Return:
[u-boot.git] / board / emulation / qemu-ppce500 / qemu-ppce500.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2007,2009-2014 Freescale Semiconductor, Inc.
4  * Copyright (C) 2021, Bin Meng <[email protected]>
5  */
6
7 #include <common.h>
8 #include <command.h>
9 #include <cpu_func.h>
10 #include <dm.h>
11 #include <env.h>
12 #include <init.h>
13 #include <log.h>
14 #include <net.h>
15 #include <pci.h>
16 #include <time.h>
17 #include <dm/simple_bus.h>
18 #include <dm/uclass-internal.h>
19 #include <asm/global_data.h>
20 #include <asm/processor.h>
21 #include <asm/mmu.h>
22 #include <asm/fsl_pci.h>
23 #include <asm/io.h>
24 #include <linux/libfdt.h>
25 #include <fdt_support.h>
26 #include <netdev.h>
27 #include <fdtdec.h>
28 #include <errno.h>
29 #include <malloc.h>
30 #include <virtio_types.h>
31 #include <virtio.h>
32
33 DECLARE_GLOBAL_DATA_PTR;
34
35 static void *get_fdt_virt(void)
36 {
37         if (gd->flags & GD_FLG_RELOC)
38                 return (void *)gd->fdt_blob;
39         else
40                 return (void *)CONFIG_SYS_TMPVIRT;
41 }
42
43 static uint64_t get_fdt_phys(void)
44 {
45         return (uint64_t)(uintptr_t)gd->fdt_blob;
46 }
47
48 static void map_fdt_as(int esel)
49 {
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;
54
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);
60
61         write_tlb(mas0, mas1, mas2, mas3, mas7);
62 }
63
64 uint64_t get_phys_ccsrbar_addr_early(void)
65 {
66         void *fdt = get_fdt_virt();
67         uint64_t r;
68         int size, node;
69         u32 naddr;
70         const fdt32_t *prop;
71
72         /*
73          * To be able to read the FDT we need to create a temporary TLB
74          * map for it.
75          */
76         map_fdt_as(10);
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);
81         disable_tlb(10);
82
83         return r;
84 }
85
86 int checkboard(void)
87 {
88         return 0;
89 }
90
91 static int pci_map_region(phys_addr_t paddr, phys_size_t size, ulong *pmap_addr)
92 {
93         ulong map_addr;
94
95         if (!pmap_addr)
96                 return 0;
97
98         map_addr = *pmap_addr;
99
100         /* Align map_addr */
101         map_addr += size - 1;
102         map_addr &= ~(size - 1);
103
104         if (map_addr + size >= CONFIG_SYS_PCI_MAP_END)
105                 return -1;
106
107         /* Map virtual memory for range */
108         assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
109         *pmap_addr = map_addr + size;
110
111         return 0;
112 }
113
114 static void platform_bus_map_region(ulong map_addr, phys_addr_t paddr,
115                                     phys_size_t size)
116 {
117         /* Align map_addr */
118         map_addr += size - 1;
119         map_addr &= ~(size - 1);
120
121         /* Map virtual memory for range */
122         assert(!tlb_map_range(map_addr, paddr, size, TLB_MAP_IO));
123 }
124
125 int misc_init_r(void)
126 {
127         struct udevice *dev;
128         struct pci_region *io;
129         struct pci_region *mem;
130         struct pci_region *pre;
131         ulong map_addr;
132         int ret;
133
134         /* Ensure PCI is probed */
135         uclass_first_device(UCLASS_PCI, &dev);
136
137         pci_get_regions(dev, &io, &mem, &pre);
138
139         /* Start MMIO and PIO range maps above RAM */
140         map_addr = CONFIG_SYS_PCI_MAP_START;
141
142         /* Map MMIO range */
143         ret = pci_map_region(mem->phys_start, mem->size, &map_addr);
144         if (ret)
145                 return ret;
146
147         /* Map PIO range */
148         ret = pci_map_region(io->phys_start, io->size, &map_addr);
149         if (ret)
150                 return ret;
151
152         /*
153          * Make sure virtio bus is enumerated so that peripherals
154          * on the virtio bus can be discovered by their drivers.
155          */
156         virtio_init();
157
158         /*
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.
161          */
162         disable_tlb(find_tlb_idx((void *)CONFIG_SYS_TMPVIRT, 1));
163
164         /*
165          * Detect the presence of the platform bus node, and
166          * create a virtual memory mapping for it.
167          */
168         for (ret = uclass_find_first_device(UCLASS_SIMPLE_BUS, &dev);
169              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);
173
174                         platform_bus_map_region(CONFIG_PLATFORM_BUS_MAP_ADDR,
175                                                 plat->target, plat->size);
176                         break;
177                 }
178         }
179
180         return 0;
181 }
182
183 int last_stage_init(void)
184 {
185         void *fdt = get_fdt_virt();
186         int len = 0;
187         const uint64_t *prop;
188         int chosen;
189
190         chosen = fdt_path_offset(fdt, "/chosen");
191         if (chosen < 0) {
192                 printf("Couldn't find /chosen node in fdt\n");
193                 return -EIO;
194         }
195
196         /* -kernel boot */
197         prop = fdt_getprop(fdt, chosen, "qemu,boot-kernel", &len);
198         if (prop && (len >= 8))
199                 env_set_hex("qemu_kernel_addr", *prop);
200
201         return 0;
202 }
203
204 static uint64_t get_linear_ram_size(void)
205 {
206         void *fdt = get_fdt_virt();
207         const void *prop;
208         int memory;
209         int len;
210
211         memory = fdt_path_offset(fdt, "/memory");
212         prop = fdt_getprop(fdt, memory, "reg", &len);
213
214         if (prop && len >= 16)
215                 return *(uint64_t *)(prop+8);
216
217         panic("Couldn't determine RAM size");
218 }
219
220 phys_size_t fsl_ddr_sdram_size(void)
221 {
222         return get_linear_ram_size();
223 }
224
225 void init_tlbs(void)
226 {
227         phys_size_t ram_size;
228
229         /*
230          * Create a temporary AS=1 map for the fdt
231          *
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.
234          */
235         map_fdt_as(0);
236
237         /* Fetch RAM size from the fdt */
238         ram_size = get_linear_ram_size();
239
240         /* And remove our fdt map again */
241         disable_tlb(0);
242
243         /* Create an internal map of manually created TLB maps */
244         init_used_tlb_cams();
245
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));
249
250         /* Create a RAM map that spans all accessible RAM */
251         setup_ddr_tlbs(ram_size >> 20);
252
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));
256 }
257
258 static uint32_t get_cpu_freq(void)
259 {
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);
265 }
266
267 void get_sys_info(sys_info_t *sys_info)
268 {
269         int freq = get_cpu_freq();
270
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;
275 }
276
277 int get_clocks(void)
278 {
279         sys_info_t sys_info;
280
281         get_sys_info(&sys_info);
282
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;
287
288         return 0;
289 }
290
291 unsigned long get_tbclk(void)
292 {
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);
298 }
299
300 /********************************************
301  * get_bus_freq
302  * return system bus freq in Hz
303  *********************************************/
304 ulong get_bus_freq(ulong dummy)
305 {
306         sys_info_t sys_info;
307         get_sys_info(&sys_info);
308         return sys_info.freq_systembus;
309 }
310
311 /*
312  * Return the number of cores on this SOC.
313  */
314 int cpu_numcores(void)
315 {
316         /*
317          * The QEMU u-boot target only needs to drive the first core,
318          * spinning and device tree nodes get driven by QEMU itself
319          */
320         return 1;
321 }
322
323 /*
324  * Return a 32-bit mask indicating which cores are present on this SOC.
325  */
326 u32 cpu_mask(void)
327 {
328         return (1 << cpu_numcores()) - 1;
329 }
330
331 /**
332  * Return the virtual address of FDT that was passed by QEMU
333  *
334  * Return: virtual address of FDT received from QEMU in r3 register
335  */
336 void *board_fdt_blob_setup(int *err)
337 {
338         *err = 0;
339         return get_fdt_virt();
340 }
341
342 /* See CONFIG_SYS_NS16550_CLK in arch/powerpc/include/asm/config.h */
343 int get_serial_clock(void)
344 {
345         return get_bus_freq(0);
346 }
This page took 0.046855 seconds and 4 git commands to generate.