11db09b84Saurel32 /* 2b3305981SScott Wood * QEMU PowerPC e500-based platforms 31db09b84Saurel32 * 41db09b84Saurel32 * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved. 51db09b84Saurel32 * 61db09b84Saurel32 * Author: Yu Liu, <yu.liu@freescale.com> 71db09b84Saurel32 * 81db09b84Saurel32 * This file is derived from hw/ppc440_bamboo.c, 91db09b84Saurel32 * the copyright for that material belongs to the original owners. 101db09b84Saurel32 * 111db09b84Saurel32 * This is free software; you can redistribute it and/or modify 121db09b84Saurel32 * it under the terms of the GNU General Public License as published by 131db09b84Saurel32 * the Free Software Foundation; either version 2 of the License, or 141db09b84Saurel32 * (at your option) any later version. 151db09b84Saurel32 */ 161db09b84Saurel32 171db09b84Saurel32 #include "config.h" 181db09b84Saurel32 #include "qemu-common.h" 19e6eaabebSScott Wood #include "e500.h" 201db09b84Saurel32 #include "net.h" 214a18e7c9SScott Wood #include "hw/hw.h" 224a18e7c9SScott Wood #include "hw/pc.h" 234a18e7c9SScott Wood #include "hw/pci.h" 244a18e7c9SScott Wood #include "hw/boards.h" 251db09b84Saurel32 #include "sysemu.h" 261db09b84Saurel32 #include "kvm.h" 271db09b84Saurel32 #include "kvm_ppc.h" 281db09b84Saurel32 #include "device_tree.h" 294a18e7c9SScott Wood #include "hw/openpic.h" 304a18e7c9SScott Wood #include "hw/ppc.h" 314a18e7c9SScott Wood #include "hw/loader.h" 32ca20cf32SBlue Swirl #include "elf.h" 334a18e7c9SScott Wood #include "hw/sysbus.h" 3439186d8aSRichard Henderson #include "exec-memory.h" 35cba2026aSAlexander Graf #include "host-utils.h" 361db09b84Saurel32 371db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" 381db09b84Saurel32 #define UIMAGE_LOAD_BASE 0 399dd5eba1SScott Wood #define DTC_LOAD_PAD 0x1800000 4075bb6589SLiu Yu #define DTC_PAD_MASK 0xFFFFF 4175bb6589SLiu Yu #define INITRD_LOAD_PAD 0x2000000 4275bb6589SLiu Yu #define INITRD_PAD_MASK 0xFFFFFF 431db09b84Saurel32 441db09b84Saurel32 #define RAM_SIZES_ALIGN (64UL << 20) 451db09b84Saurel32 46b3305981SScott Wood /* TODO: parameterize */ 47ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE 0xE0000000ULL 48ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE 0x00100000ULL 49ed2bc496SAlexander Graf #define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000ULL) 50ed2bc496SAlexander Graf #define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500ULL) 51ed2bc496SAlexander Graf #define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600ULL) 52ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000ULL) 53ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE 0x1000ULL 54ed2bc496SAlexander Graf #define MPC8544_PCI_IO 0xE1000000ULL 55ed2bc496SAlexander Graf #define MPC8544_PCI_IOLEN 0x10000ULL 56ed2bc496SAlexander Graf #define MPC8544_UTIL_BASE (MPC8544_CCSRBAR_BASE + 0xe0000ULL) 57ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE 0xEF000000ULL 581db09b84Saurel32 593b989d49SAlexander Graf struct boot_info 603b989d49SAlexander Graf { 613b989d49SAlexander Graf uint32_t dt_base; 62cba2026aSAlexander Graf uint32_t dt_size; 633b989d49SAlexander Graf uint32_t entry; 643b989d49SAlexander Graf }; 653b989d49SAlexander Graf 660dbc0798SAlexander Graf static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic) 670dbc0798SAlexander Graf { 680dbc0798SAlexander Graf int i; 690dbc0798SAlexander Graf const uint32_t tmp[] = { 700dbc0798SAlexander Graf /* IDSEL 0x11 J17 Slot 1 */ 717e99826cSAlexander Graf 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1, 727e99826cSAlexander Graf 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1, 737e99826cSAlexander Graf 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1, 747e99826cSAlexander Graf 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, 750dbc0798SAlexander Graf 760dbc0798SAlexander Graf /* IDSEL 0x12 J16 Slot 2 */ 777e99826cSAlexander Graf 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1, 787e99826cSAlexander Graf 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1, 797e99826cSAlexander Graf 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1, 807e99826cSAlexander Graf 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1, 810dbc0798SAlexander Graf }; 827e99826cSAlexander Graf for (i = 0; i < (7 * 8); i++) { 830dbc0798SAlexander Graf pci_map[i] = cpu_to_be32(tmp[i]); 840dbc0798SAlexander Graf } 850dbc0798SAlexander Graf } 860dbc0798SAlexander Graf 87a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset, 88a053a7ceSAlexander Graf const char *soc, const char *mpic, 89a053a7ceSAlexander Graf const char *alias, int idx, bool defcon) 90a053a7ceSAlexander Graf { 91a053a7ceSAlexander Graf char ser[128]; 92a053a7ceSAlexander Graf 93a053a7ceSAlexander Graf snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset); 94a053a7ceSAlexander Graf qemu_devtree_add_subnode(fdt, ser); 95a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, ser, "device_type", "serial"); 96a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550"); 97a053a7ceSAlexander Graf qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100); 98a053a7ceSAlexander Graf qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx); 99a053a7ceSAlexander Graf qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0); 1007e99826cSAlexander Graf qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2); 101a053a7ceSAlexander Graf qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic); 102a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, "/aliases", alias, ser); 103a053a7ceSAlexander Graf 104a053a7ceSAlexander Graf if (defcon) { 105a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser); 106a053a7ceSAlexander Graf } 107a053a7ceSAlexander Graf } 108a053a7ceSAlexander Graf 109b3305981SScott Wood static int ppce500_load_device_tree(CPUPPCState *env, 110e6eaabebSScott Wood PPCE500Params *params, 1115de6b46dSAlexander Graf target_phys_addr_t addr, 112c227f099SAnthony Liguori target_phys_addr_t initrd_base, 113e6eaabebSScott Wood target_phys_addr_t initrd_size) 1141db09b84Saurel32 { 115dbf916d8SAurelien Jarno int ret = -1; 116e6eaabebSScott Wood uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) }; 1177ec632b4Spbrook int fdt_size; 118dbf916d8SAurelien Jarno void *fdt; 1195de6b46dSAlexander Graf uint8_t hypercall[16]; 120911d6e7aSAlexander Graf uint32_t clock_freq = 400000000; 121911d6e7aSAlexander Graf uint32_t tb_freq = 400000000; 122621d05e3SAlexander Graf int i; 123e6eaabebSScott Wood const char *toplevel_compat = NULL; /* user override */ 124ebb9518aSAlexander Graf char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; 1255da96624SAlexander Graf char soc[128]; 12619ac9deaSAlexander Graf char mpic[128]; 12719ac9deaSAlexander Graf uint32_t mpic_ph; 128f5038483SAlexander Graf char gutil[128]; 1290dbc0798SAlexander Graf char pci[128]; 1307e99826cSAlexander Graf uint32_t pci_map[7 * 8]; 1313627757eSAlexander Graf uint32_t pci_ranges[14] = 1323627757eSAlexander Graf { 1333627757eSAlexander Graf 0x2000000, 0x0, 0xc0000000, 1343627757eSAlexander Graf 0x0, 0xc0000000, 1353627757eSAlexander Graf 0x0, 0x20000000, 1363627757eSAlexander Graf 1373627757eSAlexander Graf 0x1000000, 0x0, 0x0, 1383627757eSAlexander Graf 0x0, 0xe1000000, 1393627757eSAlexander Graf 0x0, 0x10000, 1403627757eSAlexander Graf }; 14125b42708SAlexander Graf QemuOpts *machine_opts; 142d1b93565SAlexander Graf const char *dtb_file = NULL; 143d1b93565SAlexander Graf 144d1b93565SAlexander Graf machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); 145d1b93565SAlexander Graf if (machine_opts) { 146d1b93565SAlexander Graf dtb_file = qemu_opt_get(machine_opts, "dtb"); 147e6eaabebSScott Wood toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); 148d1b93565SAlexander Graf } 149d1b93565SAlexander Graf 150d1b93565SAlexander Graf if (dtb_file) { 151d1b93565SAlexander Graf char *filename; 152d1b93565SAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file); 153d1b93565SAlexander Graf if (!filename) { 154d1b93565SAlexander Graf goto out; 155d1b93565SAlexander Graf } 156d1b93565SAlexander Graf 157d1b93565SAlexander Graf fdt = load_device_tree(filename, &fdt_size); 158d1b93565SAlexander Graf if (!fdt) { 159d1b93565SAlexander Graf goto out; 160d1b93565SAlexander Graf } 161d1b93565SAlexander Graf goto done; 162d1b93565SAlexander Graf } 1631db09b84Saurel32 1642636fcb6SAlexander Graf fdt = create_device_tree(&fdt_size); 1655cea8590SPaul Brook if (fdt == NULL) { 1665cea8590SPaul Brook goto out; 1675cea8590SPaul Brook } 1681db09b84Saurel32 1691db09b84Saurel32 /* Manipulate device tree in memory. */ 1703627757eSAlexander Graf qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2); 1713627757eSAlexander Graf qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2); 17251b852b7SAlexander Graf 173dd0bcfcaSAlexander Graf qemu_devtree_add_subnode(fdt, "/memory"); 174dd0bcfcaSAlexander Graf qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory"); 175dd0bcfcaSAlexander Graf qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, 1761db09b84Saurel32 sizeof(mem_reg_property)); 1771db09b84Saurel32 178f5231aafSAlexander Graf qemu_devtree_add_subnode(fdt, "/chosen"); 1793b989d49SAlexander Graf if (initrd_size) { 1801db09b84Saurel32 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", 1811db09b84Saurel32 initrd_base); 1823b989d49SAlexander Graf if (ret < 0) { 1831db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); 1843b989d49SAlexander Graf } 1851db09b84Saurel32 1861db09b84Saurel32 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end", 1871db09b84Saurel32 (initrd_base + initrd_size)); 1883b989d49SAlexander Graf if (ret < 0) { 1891db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); 1903b989d49SAlexander Graf } 1913b989d49SAlexander Graf } 1921db09b84Saurel32 1931db09b84Saurel32 ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", 194e6eaabebSScott Wood params->kernel_cmdline); 1951db09b84Saurel32 if (ret < 0) 1961db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/bootargs\n"); 1971db09b84Saurel32 1981db09b84Saurel32 if (kvm_enabled()) { 199911d6e7aSAlexander Graf /* Read out host's frequencies */ 200911d6e7aSAlexander Graf clock_freq = kvmppc_get_clockfreq(); 201911d6e7aSAlexander Graf tb_freq = kvmppc_get_tbfreq(); 2025de6b46dSAlexander Graf 2035de6b46dSAlexander Graf /* indicate KVM hypercall interface */ 204d50f71a5SAlexander Graf qemu_devtree_add_subnode(fdt, "/hypervisor"); 2055de6b46dSAlexander Graf qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible", 2065de6b46dSAlexander Graf "linux,kvm"); 2075de6b46dSAlexander Graf kvmppc_get_hypercall(env, hypercall, sizeof(hypercall)); 2085de6b46dSAlexander Graf qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions", 2095de6b46dSAlexander Graf hypercall, sizeof(hypercall)); 2101db09b84Saurel32 } 2111db09b84Saurel32 212625e665bSAlexander Graf /* Create CPU nodes */ 213625e665bSAlexander Graf qemu_devtree_add_subnode(fdt, "/cpus"); 214625e665bSAlexander Graf qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1); 215625e665bSAlexander Graf qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0); 216625e665bSAlexander Graf 2171e3debf0SAlexander Graf /* We need to generate the cpu nodes in reverse order, so Linux can pick 2181e3debf0SAlexander Graf the first node as boot node and be happy */ 2191e3debf0SAlexander Graf for (i = smp_cpus - 1; i >= 0; i--) { 220621d05e3SAlexander Graf char cpu_name[128]; 2211d2e5c52SAlexander Graf uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); 22210f25a46SAlexander Graf 2231e3debf0SAlexander Graf for (env = first_cpu; env != NULL; env = env->next_cpu) { 2241e3debf0SAlexander Graf if (env->cpu_index == i) { 2251e3debf0SAlexander Graf break; 2261e3debf0SAlexander Graf } 227621d05e3SAlexander Graf } 228911d6e7aSAlexander Graf 2291e3debf0SAlexander Graf if (!env) { 2301e3debf0SAlexander Graf continue; 2311e3debf0SAlexander Graf } 2321e3debf0SAlexander Graf 2331e3debf0SAlexander Graf snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index); 2341e3debf0SAlexander Graf qemu_devtree_add_subnode(fdt, cpu_name); 2351e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq); 2361e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq); 2371e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu"); 2381e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index); 2391e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size", 2401e3debf0SAlexander Graf env->dcache_line_size); 2411e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size", 2421e3debf0SAlexander Graf env->icache_line_size); 2431e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000); 2441e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000); 2451e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0); 2461e3debf0SAlexander Graf if (env->cpu_index) { 2471e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled"); 2481e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table"); 2491d2e5c52SAlexander Graf qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr", 2501d2e5c52SAlexander Graf cpu_release_addr); 2511e3debf0SAlexander Graf } else { 2521e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay"); 2531e3debf0SAlexander Graf } 2541db09b84Saurel32 } 2551db09b84Saurel32 2560cfc6e8dSAlexander Graf qemu_devtree_add_subnode(fdt, "/aliases"); 2575da96624SAlexander Graf /* XXX These should go into their respective devices' code */ 258ed2bc496SAlexander Graf snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE); 2595da96624SAlexander Graf qemu_devtree_add_subnode(fdt, soc); 2605da96624SAlexander Graf qemu_devtree_setprop_string(fdt, soc, "device_type", "soc"); 261ebb9518aSAlexander Graf qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb, 262ebb9518aSAlexander Graf sizeof(compatible_sb)); 2635da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1); 2645da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1); 2653627757eSAlexander Graf qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0, 2663627757eSAlexander Graf MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE, 2675da96624SAlexander Graf MPC8544_CCSRBAR_SIZE); 2685da96624SAlexander Graf /* XXX should contain a reasonable value */ 2695da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); 2705da96624SAlexander Graf 271ed2bc496SAlexander Graf snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, 27219ac9deaSAlexander Graf MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE); 27319ac9deaSAlexander Graf qemu_devtree_add_subnode(fdt, mpic); 27419ac9deaSAlexander Graf qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); 2757e99826cSAlexander Graf qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic"); 27619ac9deaSAlexander Graf qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_BASE - 27719ac9deaSAlexander Graf MPC8544_CCSRBAR_BASE, 0x40000); 27819ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); 2797e99826cSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); 28019ac9deaSAlexander Graf mpic_ph = qemu_devtree_alloc_phandle(fdt); 28119ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph); 28219ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); 28319ac9deaSAlexander Graf qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0); 28419ac9deaSAlexander Graf 2850cfc6e8dSAlexander Graf /* 2860cfc6e8dSAlexander Graf * We have to generate ser1 first, because Linux takes the first 2870cfc6e8dSAlexander Graf * device it finds in the dt as serial output device. And we generate 2880cfc6e8dSAlexander Graf * devices in reverse order to the dt. 2890cfc6e8dSAlexander Graf */ 290a053a7ceSAlexander Graf dt_serial_create(fdt, MPC8544_SERIAL1_REGS_BASE - MPC8544_CCSRBAR_BASE, 291a053a7ceSAlexander Graf soc, mpic, "serial1", 1, false); 292a053a7ceSAlexander Graf dt_serial_create(fdt, MPC8544_SERIAL0_REGS_BASE - MPC8544_CCSRBAR_BASE, 293a053a7ceSAlexander Graf soc, mpic, "serial0", 0, true); 2940cfc6e8dSAlexander Graf 295ed2bc496SAlexander Graf snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, 296f5038483SAlexander Graf MPC8544_UTIL_BASE - MPC8544_CCSRBAR_BASE); 297f5038483SAlexander Graf qemu_devtree_add_subnode(fdt, gutil); 298f5038483SAlexander Graf qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); 299f5038483SAlexander Graf qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_BASE - 300f5038483SAlexander Graf MPC8544_CCSRBAR_BASE, 0x1000); 301f5038483SAlexander Graf qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); 302f5038483SAlexander Graf 303ed2bc496SAlexander Graf snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); 3040dbc0798SAlexander Graf qemu_devtree_add_subnode(fdt, pci); 3050dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0); 3060dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); 3070dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, pci, "device_type", "pci"); 3080dbc0798SAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 3090dbc0798SAlexander Graf 0x0, 0x7); 3100dbc0798SAlexander Graf pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic)); 3110dbc0798SAlexander Graf qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map)); 3120dbc0798SAlexander Graf qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); 3137e99826cSAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); 3140dbc0798SAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); 3153627757eSAlexander Graf for (i = 0; i < 14; i++) { 3160dbc0798SAlexander Graf pci_ranges[i] = cpu_to_be32(pci_ranges[i]); 3170dbc0798SAlexander Graf } 3180dbc0798SAlexander Graf qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); 3193627757eSAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32, 3203627757eSAlexander Graf MPC8544_PCI_REGS_BASE, 0, 0x1000); 3210dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666); 3220dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1); 3230dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2); 3240dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); 3250dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); 3260dbc0798SAlexander Graf 327e6eaabebSScott Wood params->fixup_devtree(params, fdt); 328e6eaabebSScott Wood 329e6eaabebSScott Wood if (toplevel_compat) { 330e6eaabebSScott Wood qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat, 331e6eaabebSScott Wood strlen(toplevel_compat) + 1); 332e6eaabebSScott Wood } 333e6eaabebSScott Wood 334d1b93565SAlexander Graf done: 33571193433SAlexander Graf qemu_devtree_dumpdtb(fdt, fdt_size); 33604088adbSLiu Yu ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); 337cba2026aSAlexander Graf if (ret < 0) { 338cba2026aSAlexander Graf goto out; 339cba2026aSAlexander Graf } 3407267c094SAnthony Liguori g_free(fdt); 341cba2026aSAlexander Graf ret = fdt_size; 3427ec632b4Spbrook 3431db09b84Saurel32 out: 3441db09b84Saurel32 34504088adbSLiu Yu return ret; 3461db09b84Saurel32 } 3471db09b84Saurel32 348cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE. */ 349d1e256feSAlexander Graf static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size) 350d1e256feSAlexander Graf { 351cba2026aSAlexander Graf return 63 - clz64(size >> 10); 352d1e256feSAlexander Graf } 353d1e256feSAlexander Graf 354cba2026aSAlexander Graf static void mmubooke_create_initial_mapping(CPUPPCState *env) 3553b989d49SAlexander Graf { 356cba2026aSAlexander Graf struct boot_info *bi = env->load_info; 357d1e256feSAlexander Graf ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); 358cba2026aSAlexander Graf target_phys_addr_t size, dt_end; 359cba2026aSAlexander Graf int ps; 3603b989d49SAlexander Graf 361cba2026aSAlexander Graf /* Our initial TLB entry needs to cover everything from 0 to 362cba2026aSAlexander Graf the device tree top */ 363cba2026aSAlexander Graf dt_end = bi->dt_base + bi->dt_size; 364cba2026aSAlexander Graf ps = booke206_page_size_to_tlb(dt_end) + 1; 365cba2026aSAlexander Graf size = (ps << MAS1_TSIZE_SHIFT); 366d1e256feSAlexander Graf tlb->mas1 = MAS1_VALID | size; 367cba2026aSAlexander Graf tlb->mas2 = 0; 368cba2026aSAlexander Graf tlb->mas7_3 = 0; 369d1e256feSAlexander Graf tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; 37093dd5e85SScott Wood 37193dd5e85SScott Wood env->tlb_dirty = true; 3723b989d49SAlexander Graf } 3733b989d49SAlexander Graf 374b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque) 3755c145dacSAlexander Graf { 37638f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 37738f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 3785c145dacSAlexander Graf 37938f92da6SAndreas Färber cpu_reset(CPU(cpu)); 3805c145dacSAlexander Graf 3815c145dacSAlexander Graf /* Secondary CPU starts in halted state for now. Needs to change when 3825c145dacSAlexander Graf implementing non-kernel boot. */ 3835c145dacSAlexander Graf env->halted = 1; 3845c145dacSAlexander Graf env->exception_index = EXCP_HLT; 3853b989d49SAlexander Graf } 3863b989d49SAlexander Graf 387b3305981SScott Wood static void ppce500_cpu_reset(void *opaque) 3883b989d49SAlexander Graf { 38938f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 39038f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 3913b989d49SAlexander Graf struct boot_info *bi = env->load_info; 3923b989d49SAlexander Graf 39338f92da6SAndreas Färber cpu_reset(CPU(cpu)); 3943b989d49SAlexander Graf 3953b989d49SAlexander Graf /* Set initial guest state. */ 3965c145dacSAlexander Graf env->halted = 0; 3973b989d49SAlexander Graf env->gpr[1] = (16<<20) - 8; 3983b989d49SAlexander Graf env->gpr[3] = bi->dt_base; 3993b989d49SAlexander Graf env->nip = bi->entry; 400cba2026aSAlexander Graf mmubooke_create_initial_mapping(env); 4013b989d49SAlexander Graf } 4023b989d49SAlexander Graf 403e6eaabebSScott Wood void ppce500_init(PPCE500Params *params) 4041db09b84Saurel32 { 40539186d8aSRichard Henderson MemoryRegion *address_space_mem = get_system_memory(); 4062646c133SAvi Kivity MemoryRegion *ram = g_new(MemoryRegion, 1); 4071db09b84Saurel32 PCIBus *pci_bus; 408e2684c0bSAndreas Färber CPUPPCState *env = NULL; 4091db09b84Saurel32 uint64_t elf_entry; 4101db09b84Saurel32 uint64_t elf_lowaddr; 411c227f099SAnthony Liguori target_phys_addr_t entry=0; 412c227f099SAnthony Liguori target_phys_addr_t loadaddr=UIMAGE_LOAD_BASE; 4131db09b84Saurel32 target_long kernel_size=0; 41475bb6589SLiu Yu target_ulong dt_base = 0; 41575bb6589SLiu Yu target_ulong initrd_base = 0; 4161db09b84Saurel32 target_long initrd_size=0; 4171db09b84Saurel32 int i=0; 4181db09b84Saurel32 unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; 419a915249fSAlexander Graf qemu_irq **irqs, *mpic; 420be13cc7aSAlexander Graf DeviceState *dev; 421e2684c0bSAndreas Färber CPUPPCState *firstenv = NULL; 4221db09b84Saurel32 423e61c36d5SAlexander Graf /* Setup CPUs */ 424e6eaabebSScott Wood if (params->cpu_model == NULL) { 425e6eaabebSScott Wood params->cpu_model = "e500v2_v30"; 426ef250db6SAlexander Graf } 427ef250db6SAlexander Graf 428a915249fSAlexander Graf irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); 429a915249fSAlexander Graf irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); 430e61c36d5SAlexander Graf for (i = 0; i < smp_cpus; i++) { 431397b457dSAndreas Färber PowerPCCPU *cpu; 432e61c36d5SAlexander Graf qemu_irq *input; 433397b457dSAndreas Färber 434e6eaabebSScott Wood cpu = cpu_ppc_init(params->cpu_model); 435397b457dSAndreas Färber if (cpu == NULL) { 4361db09b84Saurel32 fprintf(stderr, "Unable to initialize CPU!\n"); 4371db09b84Saurel32 exit(1); 4381db09b84Saurel32 } 439397b457dSAndreas Färber env = &cpu->env; 4401db09b84Saurel32 441e61c36d5SAlexander Graf if (!firstenv) { 442e61c36d5SAlexander Graf firstenv = env; 443e61c36d5SAlexander Graf } 444e61c36d5SAlexander Graf 445a915249fSAlexander Graf irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB); 446a915249fSAlexander Graf input = (qemu_irq *)env->irq_inputs; 447a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; 448a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; 449e61c36d5SAlexander Graf env->spr[SPR_BOOKE_PIR] = env->cpu_index = i; 4502a7a47fcSAlexander Graf env->mpic_cpu_base = MPC8544_MPIC_REGS_BASE + 0x20000; 451e61c36d5SAlexander Graf 452ddd1055bSFabien Chouteau ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500); 4533b989d49SAlexander Graf 4543b989d49SAlexander Graf /* Register reset handler */ 4555c145dacSAlexander Graf if (!i) { 4565c145dacSAlexander Graf /* Primary CPU */ 4575c145dacSAlexander Graf struct boot_info *boot_info; 458e61c36d5SAlexander Graf boot_info = g_malloc0(sizeof(struct boot_info)); 459b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset, cpu); 460e61c36d5SAlexander Graf env->load_info = boot_info; 4615c145dacSAlexander Graf } else { 4625c145dacSAlexander Graf /* Secondary CPUs */ 463b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset_sec, cpu); 4645c145dacSAlexander Graf } 465e61c36d5SAlexander Graf } 466e61c36d5SAlexander Graf 467e61c36d5SAlexander Graf env = firstenv; 4683b989d49SAlexander Graf 4691db09b84Saurel32 /* Fixup Memory size on a alignment boundary */ 4701db09b84Saurel32 ram_size &= ~(RAM_SIZES_ALIGN - 1); 4711db09b84Saurel32 4721db09b84Saurel32 /* Register Memory */ 473c5705a77SAvi Kivity memory_region_init_ram(ram, "mpc8544ds.ram", ram_size); 474c5705a77SAvi Kivity vmstate_register_ram_global(ram); 4752646c133SAvi Kivity memory_region_add_subregion(address_space_mem, 0, ram); 4761db09b84Saurel32 4771db09b84Saurel32 /* MPIC */ 478df2921d3SAvi Kivity mpic = mpic_init(address_space_mem, MPC8544_MPIC_REGS_BASE, 479df2921d3SAvi Kivity smp_cpus, irqs, NULL); 480a915249fSAlexander Graf 481a915249fSAlexander Graf if (!mpic) { 482a915249fSAlexander Graf cpu_abort(env, "MPIC failed to initialize\n"); 483a915249fSAlexander Graf } 4841db09b84Saurel32 4851db09b84Saurel32 /* Serial */ 4862d48377aSBlue Swirl if (serial_hds[0]) { 48739186d8aSRichard Henderson serial_mm_init(address_space_mem, MPC8544_SERIAL0_REGS_BASE, 4881db09b84Saurel32 0, mpic[12+26], 399193, 4892ff0c7c3SRichard Henderson serial_hds[0], DEVICE_BIG_ENDIAN); 4902d48377aSBlue Swirl } 4911db09b84Saurel32 4922d48377aSBlue Swirl if (serial_hds[1]) { 49339186d8aSRichard Henderson serial_mm_init(address_space_mem, MPC8544_SERIAL1_REGS_BASE, 4941db09b84Saurel32 0, mpic[12+26], 399193, 4952ff0c7c3SRichard Henderson serial_hds[0], DEVICE_BIG_ENDIAN); 4962d48377aSBlue Swirl } 4971db09b84Saurel32 498b0fb8423SAlexander Graf /* General Utility device */ 499b0fb8423SAlexander Graf sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL); 500b0fb8423SAlexander Graf 5011db09b84Saurel32 /* PCI */ 502be13cc7aSAlexander Graf dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE, 503be13cc7aSAlexander Graf mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]], 504be13cc7aSAlexander Graf mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]], 505be13cc7aSAlexander Graf NULL); 506d461e3b9SAlexander Graf pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); 5071db09b84Saurel32 if (!pci_bus) 5081db09b84Saurel32 printf("couldn't create PCI controller!\n"); 5091db09b84Saurel32 510968d683cSAlexander Graf isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN); 5111db09b84Saurel32 5121db09b84Saurel32 if (pci_bus) { 5131db09b84Saurel32 /* Register network interfaces. */ 5141db09b84Saurel32 for (i = 0; i < nb_nics; i++) { 51507caea31SMarkus Armbruster pci_nic_init_nofail(&nd_table[i], "virtio", NULL); 5161db09b84Saurel32 } 5171db09b84Saurel32 } 5181db09b84Saurel32 5195c145dacSAlexander Graf /* Register spinning region */ 5205c145dacSAlexander Graf sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); 5215c145dacSAlexander Graf 5221db09b84Saurel32 /* Load kernel. */ 523e6eaabebSScott Wood if (params->kernel_filename) { 524e6eaabebSScott Wood kernel_size = load_uimage(params->kernel_filename, &entry, 525e6eaabebSScott Wood &loadaddr, NULL); 5261db09b84Saurel32 if (kernel_size < 0) { 527e6eaabebSScott Wood kernel_size = load_elf(params->kernel_filename, NULL, NULL, 528e6eaabebSScott Wood &elf_entry, &elf_lowaddr, NULL, 1, 529e6eaabebSScott Wood ELF_MACHINE, 0); 5301db09b84Saurel32 entry = elf_entry; 5311db09b84Saurel32 loadaddr = elf_lowaddr; 5321db09b84Saurel32 } 5331db09b84Saurel32 /* XXX try again as binary */ 5341db09b84Saurel32 if (kernel_size < 0) { 5351db09b84Saurel32 fprintf(stderr, "qemu: could not load kernel '%s'\n", 536e6eaabebSScott Wood params->kernel_filename); 5371db09b84Saurel32 exit(1); 5381db09b84Saurel32 } 5391db09b84Saurel32 } 5401db09b84Saurel32 5411db09b84Saurel32 /* Load initrd. */ 542e6eaabebSScott Wood if (params->initrd_filename) { 543*7e7ec2d2SScott Wood initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) & 544*7e7ec2d2SScott Wood ~INITRD_PAD_MASK; 545e6eaabebSScott Wood initrd_size = load_image_targphys(params->initrd_filename, initrd_base, 546d7585251Spbrook ram_size - initrd_base); 5471db09b84Saurel32 5481db09b84Saurel32 if (initrd_size < 0) { 5491db09b84Saurel32 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 550e6eaabebSScott Wood params->initrd_filename); 5511db09b84Saurel32 exit(1); 5521db09b84Saurel32 } 5531db09b84Saurel32 } 5541db09b84Saurel32 5551db09b84Saurel32 /* If we're loading a kernel directly, we must load the device tree too. */ 556e6eaabebSScott Wood if (params->kernel_filename) { 5575c145dacSAlexander Graf struct boot_info *boot_info; 558cba2026aSAlexander Graf int dt_size; 5595c145dacSAlexander Graf 560cba2026aSAlexander Graf dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; 561e6eaabebSScott Wood dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base, 562e6eaabebSScott Wood initrd_size); 563cba2026aSAlexander Graf if (dt_size < 0) { 5641db09b84Saurel32 fprintf(stderr, "couldn't load device tree\n"); 5651db09b84Saurel32 exit(1); 5661db09b84Saurel32 } 5671db09b84Saurel32 568e61c36d5SAlexander Graf boot_info = env->load_info; 5693b989d49SAlexander Graf boot_info->entry = entry; 5703b989d49SAlexander Graf boot_info->dt_base = dt_base; 571cba2026aSAlexander Graf boot_info->dt_size = dt_size; 5721db09b84Saurel32 } 5731db09b84Saurel32 5743b989d49SAlexander Graf if (kvm_enabled()) { 5751db09b84Saurel32 kvmppc_init(); 5763b989d49SAlexander Graf } 5771db09b84Saurel32 } 578