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" 203eddc1beSBharat Bhushan #include "e500-ccsr.h" 211422e32dSPaolo Bonzini #include "net/net.h" 221de7afc9SPaolo Bonzini #include "qemu/config-file.h" 234a18e7c9SScott Wood #include "hw/hw.h" 240d09e41aSPaolo Bonzini #include "hw/char/serial.h" 25a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h" 264a18e7c9SScott Wood #include "hw/boards.h" 279c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 289c17d615SPaolo Bonzini #include "sysemu/kvm.h" 291db09b84Saurel32 #include "kvm_ppc.h" 309c17d615SPaolo Bonzini #include "sysemu/device_tree.h" 310d09e41aSPaolo Bonzini #include "hw/ppc/openpic.h" 320d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 334a18e7c9SScott Wood #include "hw/loader.h" 34ca20cf32SBlue Swirl #include "elf.h" 354a18e7c9SScott Wood #include "hw/sysbus.h" 36022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 371de7afc9SPaolo Bonzini #include "qemu/host-utils.h" 380d09e41aSPaolo Bonzini #include "hw/pci-host/ppce500.h" 391db09b84Saurel32 40*cefd3cdbSBharat Bhushan #define EPAPR_MAGIC (0x45504150) 411db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" 421db09b84Saurel32 #define UIMAGE_LOAD_BASE 0 439dd5eba1SScott Wood #define DTC_LOAD_PAD 0x1800000 4475bb6589SLiu Yu #define DTC_PAD_MASK 0xFFFFF 45b8dec144SAlexander Graf #define DTB_MAX_SIZE (8 * 1024 * 1024) 4675bb6589SLiu Yu #define INITRD_LOAD_PAD 0x2000000 4775bb6589SLiu Yu #define INITRD_PAD_MASK 0xFFFFFF 481db09b84Saurel32 491db09b84Saurel32 #define RAM_SIZES_ALIGN (64UL << 20) 501db09b84Saurel32 51b3305981SScott Wood /* TODO: parameterize */ 52ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE 0xE0000000ULL 53ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE 0x00100000ULL 54dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET 0x40000ULL 55a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET 0x41600ULL 56dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL 57dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL 58dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET 0x8000ULL 59dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + \ 60dffb1dc2SBharat Bhushan MPC8544_PCI_REGS_OFFSET) 61ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE 0x1000ULL 62ed2bc496SAlexander Graf #define MPC8544_PCI_IO 0xE1000000ULL 63dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET 0xe0000ULL 64ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE 0xEF000000ULL 651db09b84Saurel32 663b989d49SAlexander Graf struct boot_info 673b989d49SAlexander Graf { 683b989d49SAlexander Graf uint32_t dt_base; 69cba2026aSAlexander Graf uint32_t dt_size; 703b989d49SAlexander Graf uint32_t entry; 713b989d49SAlexander Graf }; 723b989d49SAlexander Graf 73347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot, 74347dd79dSAlexander Graf int nr_slots, int *len) 750dbc0798SAlexander Graf { 76347dd79dSAlexander Graf int i = 0; 77347dd79dSAlexander Graf int slot; 78347dd79dSAlexander Graf int pci_irq; 799e2c1298SAlexander Graf int host_irq; 80347dd79dSAlexander Graf int last_slot = first_slot + nr_slots; 81347dd79dSAlexander Graf uint32_t *pci_map; 820dbc0798SAlexander Graf 83347dd79dSAlexander Graf *len = nr_slots * 4 * 7 * sizeof(uint32_t); 84347dd79dSAlexander Graf pci_map = g_malloc(*len); 85347dd79dSAlexander Graf 86347dd79dSAlexander Graf for (slot = first_slot; slot < last_slot; slot++) { 87347dd79dSAlexander Graf for (pci_irq = 0; pci_irq < 4; pci_irq++) { 88347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(slot << 11); 89347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x0); 90347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x0); 91347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(pci_irq + 1); 92347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(mpic); 939e2c1298SAlexander Graf host_irq = ppce500_pci_map_irq_slot(slot, pci_irq); 949e2c1298SAlexander Graf pci_map[i++] = cpu_to_be32(host_irq + 1); 95347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x1); 960dbc0798SAlexander Graf } 970dbc0798SAlexander Graf } 980dbc0798SAlexander Graf 99347dd79dSAlexander Graf assert((i * sizeof(uint32_t)) == *len); 100347dd79dSAlexander Graf 101347dd79dSAlexander Graf return pci_map; 102347dd79dSAlexander Graf } 103347dd79dSAlexander Graf 104a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset, 105a053a7ceSAlexander Graf const char *soc, const char *mpic, 106a053a7ceSAlexander Graf const char *alias, int idx, bool defcon) 107a053a7ceSAlexander Graf { 108a053a7ceSAlexander Graf char ser[128]; 109a053a7ceSAlexander Graf 110a053a7ceSAlexander Graf snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset); 111a053a7ceSAlexander Graf qemu_devtree_add_subnode(fdt, ser); 112a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, ser, "device_type", "serial"); 113a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550"); 114a053a7ceSAlexander Graf qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100); 115a053a7ceSAlexander Graf qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx); 116a053a7ceSAlexander Graf qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0); 1177e99826cSAlexander Graf qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2); 118a053a7ceSAlexander Graf qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic); 119a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, "/aliases", alias, ser); 120a053a7ceSAlexander Graf 121a053a7ceSAlexander Graf if (defcon) { 122a053a7ceSAlexander Graf qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser); 123a053a7ceSAlexander Graf } 124a053a7ceSAlexander Graf } 125a053a7ceSAlexander Graf 126b3305981SScott Wood static int ppce500_load_device_tree(CPUPPCState *env, 127e6eaabebSScott Wood PPCE500Params *params, 128a8170e5eSAvi Kivity hwaddr addr, 129a8170e5eSAvi Kivity hwaddr initrd_base, 130a8170e5eSAvi Kivity hwaddr initrd_size) 1311db09b84Saurel32 { 132dbf916d8SAurelien Jarno int ret = -1; 133e6eaabebSScott Wood uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) }; 1347ec632b4Spbrook int fdt_size; 135dbf916d8SAurelien Jarno void *fdt; 1365de6b46dSAlexander Graf uint8_t hypercall[16]; 137911d6e7aSAlexander Graf uint32_t clock_freq = 400000000; 138911d6e7aSAlexander Graf uint32_t tb_freq = 400000000; 139621d05e3SAlexander Graf int i; 140e6eaabebSScott Wood const char *toplevel_compat = NULL; /* user override */ 141ebb9518aSAlexander Graf char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; 1425da96624SAlexander Graf char soc[128]; 14319ac9deaSAlexander Graf char mpic[128]; 14419ac9deaSAlexander Graf uint32_t mpic_ph; 145a911b7a9SAlexander Graf uint32_t msi_ph; 146f5038483SAlexander Graf char gutil[128]; 1470dbc0798SAlexander Graf char pci[128]; 148a911b7a9SAlexander Graf char msi[128]; 149347dd79dSAlexander Graf uint32_t *pci_map = NULL; 150347dd79dSAlexander Graf int len; 1513627757eSAlexander Graf uint32_t pci_ranges[14] = 1523627757eSAlexander Graf { 1533627757eSAlexander Graf 0x2000000, 0x0, 0xc0000000, 1543627757eSAlexander Graf 0x0, 0xc0000000, 1553627757eSAlexander Graf 0x0, 0x20000000, 1563627757eSAlexander Graf 1573627757eSAlexander Graf 0x1000000, 0x0, 0x0, 1583627757eSAlexander Graf 0x0, 0xe1000000, 1593627757eSAlexander Graf 0x0, 0x10000, 1603627757eSAlexander Graf }; 16125b42708SAlexander Graf QemuOpts *machine_opts; 162d1b93565SAlexander Graf const char *dtb_file = NULL; 163d1b93565SAlexander Graf 164d1b93565SAlexander Graf machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); 165d1b93565SAlexander Graf if (machine_opts) { 166d1b93565SAlexander Graf dtb_file = qemu_opt_get(machine_opts, "dtb"); 167e6eaabebSScott Wood toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); 168d1b93565SAlexander Graf } 169d1b93565SAlexander Graf 170d1b93565SAlexander Graf if (dtb_file) { 171d1b93565SAlexander Graf char *filename; 172d1b93565SAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file); 173d1b93565SAlexander Graf if (!filename) { 174d1b93565SAlexander Graf goto out; 175d1b93565SAlexander Graf } 176d1b93565SAlexander Graf 177d1b93565SAlexander Graf fdt = load_device_tree(filename, &fdt_size); 178d1b93565SAlexander Graf if (!fdt) { 179d1b93565SAlexander Graf goto out; 180d1b93565SAlexander Graf } 181d1b93565SAlexander Graf goto done; 182d1b93565SAlexander Graf } 1831db09b84Saurel32 1842636fcb6SAlexander Graf fdt = create_device_tree(&fdt_size); 1855cea8590SPaul Brook if (fdt == NULL) { 1865cea8590SPaul Brook goto out; 1875cea8590SPaul Brook } 1881db09b84Saurel32 1891db09b84Saurel32 /* Manipulate device tree in memory. */ 1903627757eSAlexander Graf qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2); 1913627757eSAlexander Graf qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2); 19251b852b7SAlexander Graf 193dd0bcfcaSAlexander Graf qemu_devtree_add_subnode(fdt, "/memory"); 194dd0bcfcaSAlexander Graf qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory"); 195dd0bcfcaSAlexander Graf qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, 1961db09b84Saurel32 sizeof(mem_reg_property)); 1971db09b84Saurel32 198f5231aafSAlexander Graf qemu_devtree_add_subnode(fdt, "/chosen"); 1993b989d49SAlexander Graf if (initrd_size) { 2001db09b84Saurel32 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", 2011db09b84Saurel32 initrd_base); 2023b989d49SAlexander Graf if (ret < 0) { 2031db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); 2043b989d49SAlexander Graf } 2051db09b84Saurel32 2061db09b84Saurel32 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end", 2071db09b84Saurel32 (initrd_base + initrd_size)); 2083b989d49SAlexander Graf if (ret < 0) { 2091db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); 2103b989d49SAlexander Graf } 2113b989d49SAlexander Graf } 2121db09b84Saurel32 2131db09b84Saurel32 ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", 214e6eaabebSScott Wood params->kernel_cmdline); 2151db09b84Saurel32 if (ret < 0) 2161db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/bootargs\n"); 2171db09b84Saurel32 2181db09b84Saurel32 if (kvm_enabled()) { 219911d6e7aSAlexander Graf /* Read out host's frequencies */ 220911d6e7aSAlexander Graf clock_freq = kvmppc_get_clockfreq(); 221911d6e7aSAlexander Graf tb_freq = kvmppc_get_tbfreq(); 2225de6b46dSAlexander Graf 2235de6b46dSAlexander Graf /* indicate KVM hypercall interface */ 224d50f71a5SAlexander Graf qemu_devtree_add_subnode(fdt, "/hypervisor"); 2255de6b46dSAlexander Graf qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible", 2265de6b46dSAlexander Graf "linux,kvm"); 2275de6b46dSAlexander Graf kvmppc_get_hypercall(env, hypercall, sizeof(hypercall)); 2285de6b46dSAlexander Graf qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions", 2295de6b46dSAlexander Graf hypercall, sizeof(hypercall)); 2301a61a9aeSStuart Yoder /* if KVM supports the idle hcall, set property indicating this */ 2311a61a9aeSStuart Yoder if (kvmppc_get_hasidle(env)) { 2321a61a9aeSStuart Yoder qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0); 2331a61a9aeSStuart Yoder } 2341db09b84Saurel32 } 2351db09b84Saurel32 236625e665bSAlexander Graf /* Create CPU nodes */ 237625e665bSAlexander Graf qemu_devtree_add_subnode(fdt, "/cpus"); 238625e665bSAlexander Graf qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1); 239625e665bSAlexander Graf qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0); 240625e665bSAlexander Graf 2411e3debf0SAlexander Graf /* We need to generate the cpu nodes in reverse order, so Linux can pick 2421e3debf0SAlexander Graf the first node as boot node and be happy */ 2431e3debf0SAlexander Graf for (i = smp_cpus - 1; i >= 0; i--) { 244440c8152SAndreas Färber CPUState *cpu; 245621d05e3SAlexander Graf char cpu_name[128]; 2461d2e5c52SAlexander Graf uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); 24710f25a46SAlexander Graf 248440c8152SAndreas Färber cpu = qemu_get_cpu(i); 24955e5c285SAndreas Färber if (cpu == NULL) { 2501e3debf0SAlexander Graf continue; 2511e3debf0SAlexander Graf } 252440c8152SAndreas Färber env = cpu->env_ptr; 2531e3debf0SAlexander Graf 25455e5c285SAndreas Färber snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", 25555e5c285SAndreas Färber cpu->cpu_index); 2561e3debf0SAlexander Graf qemu_devtree_add_subnode(fdt, cpu_name); 2571e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq); 2581e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq); 2591e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu"); 26055e5c285SAndreas Färber qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index); 2611e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size", 2621e3debf0SAlexander Graf env->dcache_line_size); 2631e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size", 2641e3debf0SAlexander Graf env->icache_line_size); 2651e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000); 2661e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000); 2671e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0); 26855e5c285SAndreas Färber if (cpu->cpu_index) { 2691e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled"); 2701e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table"); 2711d2e5c52SAlexander Graf qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr", 2721d2e5c52SAlexander Graf cpu_release_addr); 2731e3debf0SAlexander Graf } else { 2741e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay"); 2751e3debf0SAlexander Graf } 2761db09b84Saurel32 } 2771db09b84Saurel32 2780cfc6e8dSAlexander Graf qemu_devtree_add_subnode(fdt, "/aliases"); 2795da96624SAlexander Graf /* XXX These should go into their respective devices' code */ 280ed2bc496SAlexander Graf snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE); 2815da96624SAlexander Graf qemu_devtree_add_subnode(fdt, soc); 2825da96624SAlexander Graf qemu_devtree_setprop_string(fdt, soc, "device_type", "soc"); 283ebb9518aSAlexander Graf qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb, 284ebb9518aSAlexander Graf sizeof(compatible_sb)); 2855da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1); 2865da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1); 2873627757eSAlexander Graf qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0, 2883627757eSAlexander Graf MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE, 2895da96624SAlexander Graf MPC8544_CCSRBAR_SIZE); 2905da96624SAlexander Graf /* XXX should contain a reasonable value */ 2915da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); 2925da96624SAlexander Graf 293dffb1dc2SBharat Bhushan snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET); 29419ac9deaSAlexander Graf qemu_devtree_add_subnode(fdt, mpic); 29519ac9deaSAlexander Graf qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); 296f5fba9d2SScott Wood qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); 297dffb1dc2SBharat Bhushan qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET, 298dffb1dc2SBharat Bhushan 0x40000); 29919ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); 3007e99826cSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); 30119ac9deaSAlexander Graf mpic_ph = qemu_devtree_alloc_phandle(fdt); 30219ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph); 30319ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); 30419ac9deaSAlexander Graf qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0); 30519ac9deaSAlexander Graf 3060cfc6e8dSAlexander Graf /* 3070cfc6e8dSAlexander Graf * We have to generate ser1 first, because Linux takes the first 3080cfc6e8dSAlexander Graf * device it finds in the dt as serial output device. And we generate 3090cfc6e8dSAlexander Graf * devices in reverse order to the dt. 3100cfc6e8dSAlexander Graf */ 311dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET, 312a053a7ceSAlexander Graf soc, mpic, "serial1", 1, false); 313dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET, 314a053a7ceSAlexander Graf soc, mpic, "serial0", 0, true); 3150cfc6e8dSAlexander Graf 316ed2bc496SAlexander Graf snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, 317dffb1dc2SBharat Bhushan MPC8544_UTIL_OFFSET); 318f5038483SAlexander Graf qemu_devtree_add_subnode(fdt, gutil); 319f5038483SAlexander Graf qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); 320dffb1dc2SBharat Bhushan qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000); 321f5038483SAlexander Graf qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); 322f5038483SAlexander Graf 323a911b7a9SAlexander Graf snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET); 324a911b7a9SAlexander Graf qemu_devtree_add_subnode(fdt, msi); 325a911b7a9SAlexander Graf qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi"); 326a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200); 327a911b7a9SAlexander Graf msi_ph = qemu_devtree_alloc_phandle(fdt); 328a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100); 329a911b7a9SAlexander Graf qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic); 330a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "interrupts", 331a911b7a9SAlexander Graf 0xe0, 0x0, 332a911b7a9SAlexander Graf 0xe1, 0x0, 333a911b7a9SAlexander Graf 0xe2, 0x0, 334a911b7a9SAlexander Graf 0xe3, 0x0, 335a911b7a9SAlexander Graf 0xe4, 0x0, 336a911b7a9SAlexander Graf 0xe5, 0x0, 337a911b7a9SAlexander Graf 0xe6, 0x0, 338a911b7a9SAlexander Graf 0xe7, 0x0); 339a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph); 340a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph); 341a911b7a9SAlexander Graf 342ed2bc496SAlexander Graf snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); 3430dbc0798SAlexander Graf qemu_devtree_add_subnode(fdt, pci); 3440dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0); 3450dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); 3460dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, pci, "device_type", "pci"); 3470dbc0798SAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 3480dbc0798SAlexander Graf 0x0, 0x7); 349347dd79dSAlexander Graf pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic), 350492ec48dSAlexander Graf params->pci_first_slot, params->pci_nr_slots, 351492ec48dSAlexander Graf &len); 352347dd79dSAlexander Graf qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len); 3530dbc0798SAlexander Graf qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); 3547e99826cSAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); 3550dbc0798SAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); 3563627757eSAlexander Graf for (i = 0; i < 14; i++) { 3570dbc0798SAlexander Graf pci_ranges[i] = cpu_to_be32(pci_ranges[i]); 3580dbc0798SAlexander Graf } 359a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph); 3600dbc0798SAlexander Graf qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); 3613627757eSAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32, 3623627757eSAlexander Graf MPC8544_PCI_REGS_BASE, 0, 0x1000); 3630dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666); 3640dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1); 3650dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2); 3660dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); 3670dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); 3680dbc0798SAlexander Graf 369e6eaabebSScott Wood params->fixup_devtree(params, fdt); 370e6eaabebSScott Wood 371e6eaabebSScott Wood if (toplevel_compat) { 372e6eaabebSScott Wood qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat, 373e6eaabebSScott Wood strlen(toplevel_compat) + 1); 374e6eaabebSScott Wood } 375e6eaabebSScott Wood 376d1b93565SAlexander Graf done: 37771193433SAlexander Graf qemu_devtree_dumpdtb(fdt, fdt_size); 37804088adbSLiu Yu ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); 379cba2026aSAlexander Graf if (ret < 0) { 380cba2026aSAlexander Graf goto out; 381cba2026aSAlexander Graf } 3827267c094SAnthony Liguori g_free(fdt); 383cba2026aSAlexander Graf ret = fdt_size; 3847ec632b4Spbrook 3851db09b84Saurel32 out: 386347dd79dSAlexander Graf g_free(pci_map); 3871db09b84Saurel32 38804088adbSLiu Yu return ret; 3891db09b84Saurel32 } 3901db09b84Saurel32 391cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE. */ 392a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size) 393d1e256feSAlexander Graf { 394cba2026aSAlexander Graf return 63 - clz64(size >> 10); 395d1e256feSAlexander Graf } 396d1e256feSAlexander Graf 397*cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env) 3983b989d49SAlexander Graf { 399cba2026aSAlexander Graf struct boot_info *bi = env->load_info; 400*cefd3cdbSBharat Bhushan hwaddr dt_end; 401cba2026aSAlexander Graf int ps; 4023b989d49SAlexander Graf 403cba2026aSAlexander Graf /* Our initial TLB entry needs to cover everything from 0 to 404cba2026aSAlexander Graf the device tree top */ 405cba2026aSAlexander Graf dt_end = bi->dt_base + bi->dt_size; 406cba2026aSAlexander Graf ps = booke206_page_size_to_tlb(dt_end) + 1; 407fb37c302SAlexander Graf if (ps & 1) { 408fb37c302SAlexander Graf /* e500v2 can only do even TLB size bits */ 409fb37c302SAlexander Graf ps++; 410fb37c302SAlexander Graf } 411*cefd3cdbSBharat Bhushan return ps; 412*cefd3cdbSBharat Bhushan } 413*cefd3cdbSBharat Bhushan 414*cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env) 415*cefd3cdbSBharat Bhushan { 416*cefd3cdbSBharat Bhushan int tsize; 417*cefd3cdbSBharat Bhushan 418*cefd3cdbSBharat Bhushan tsize = booke206_initial_map_tsize(env); 419*cefd3cdbSBharat Bhushan return (1ULL << 10 << tsize); 420*cefd3cdbSBharat Bhushan } 421*cefd3cdbSBharat Bhushan 422*cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env) 423*cefd3cdbSBharat Bhushan { 424*cefd3cdbSBharat Bhushan ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); 425*cefd3cdbSBharat Bhushan hwaddr size; 426*cefd3cdbSBharat Bhushan int ps; 427*cefd3cdbSBharat Bhushan 428*cefd3cdbSBharat Bhushan ps = booke206_initial_map_tsize(env); 429cba2026aSAlexander Graf size = (ps << MAS1_TSIZE_SHIFT); 430d1e256feSAlexander Graf tlb->mas1 = MAS1_VALID | size; 431cba2026aSAlexander Graf tlb->mas2 = 0; 432cba2026aSAlexander Graf tlb->mas7_3 = 0; 433d1e256feSAlexander Graf tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; 43493dd5e85SScott Wood 43593dd5e85SScott Wood env->tlb_dirty = true; 4363b989d49SAlexander Graf } 4373b989d49SAlexander Graf 438b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque) 4395c145dacSAlexander Graf { 44038f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 441259186a7SAndreas Färber CPUState *cs = CPU(cpu); 44238f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 4435c145dacSAlexander Graf 444259186a7SAndreas Färber cpu_reset(cs); 4455c145dacSAlexander Graf 4465c145dacSAlexander Graf /* Secondary CPU starts in halted state for now. Needs to change when 4475c145dacSAlexander Graf implementing non-kernel boot. */ 448259186a7SAndreas Färber cs->halted = 1; 4495c145dacSAlexander Graf env->exception_index = EXCP_HLT; 4503b989d49SAlexander Graf } 4513b989d49SAlexander Graf 452b3305981SScott Wood static void ppce500_cpu_reset(void *opaque) 4533b989d49SAlexander Graf { 45438f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 455259186a7SAndreas Färber CPUState *cs = CPU(cpu); 45638f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 4573b989d49SAlexander Graf struct boot_info *bi = env->load_info; 4583b989d49SAlexander Graf 459259186a7SAndreas Färber cpu_reset(cs); 4603b989d49SAlexander Graf 4613b989d49SAlexander Graf /* Set initial guest state. */ 462259186a7SAndreas Färber cs->halted = 0; 4633b989d49SAlexander Graf env->gpr[1] = (16<<20) - 8; 4643b989d49SAlexander Graf env->gpr[3] = bi->dt_base; 465*cefd3cdbSBharat Bhushan env->gpr[4] = 0; 466*cefd3cdbSBharat Bhushan env->gpr[5] = 0; 467*cefd3cdbSBharat Bhushan env->gpr[6] = EPAPR_MAGIC; 468*cefd3cdbSBharat Bhushan env->gpr[7] = mmubooke_initial_mapsize(env); 469*cefd3cdbSBharat Bhushan env->gpr[8] = 0; 470*cefd3cdbSBharat Bhushan env->gpr[9] = 0; 4713b989d49SAlexander Graf env->nip = bi->entry; 472cba2026aSAlexander Graf mmubooke_create_initial_mapping(env); 4733b989d49SAlexander Graf } 4743b989d49SAlexander Graf 475e6eaabebSScott Wood void ppce500_init(PPCE500Params *params) 4761db09b84Saurel32 { 47739186d8aSRichard Henderson MemoryRegion *address_space_mem = get_system_memory(); 4782646c133SAvi Kivity MemoryRegion *ram = g_new(MemoryRegion, 1); 4791db09b84Saurel32 PCIBus *pci_bus; 480e2684c0bSAndreas Färber CPUPPCState *env = NULL; 4811db09b84Saurel32 uint64_t elf_entry; 4821db09b84Saurel32 uint64_t elf_lowaddr; 483a8170e5eSAvi Kivity hwaddr entry=0; 484a8170e5eSAvi Kivity hwaddr loadaddr=UIMAGE_LOAD_BASE; 4851db09b84Saurel32 target_long kernel_size=0; 48675bb6589SLiu Yu target_ulong dt_base = 0; 48775bb6589SLiu Yu target_ulong initrd_base = 0; 4881db09b84Saurel32 target_long initrd_size = 0; 489528e536eSAlexander Graf target_ulong cur_base = 0; 490d0b72631SAlexander Graf int i = 0, j, k; 4911db09b84Saurel32 unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; 492a915249fSAlexander Graf qemu_irq **irqs, *mpic; 493be13cc7aSAlexander Graf DeviceState *dev; 494e2684c0bSAndreas Färber CPUPPCState *firstenv = NULL; 4953eddc1beSBharat Bhushan MemoryRegion *ccsr_addr_space; 496dffb1dc2SBharat Bhushan SysBusDevice *s; 4973eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 4981db09b84Saurel32 499e61c36d5SAlexander Graf /* Setup CPUs */ 500e6eaabebSScott Wood if (params->cpu_model == NULL) { 501e6eaabebSScott Wood params->cpu_model = "e500v2_v30"; 502ef250db6SAlexander Graf } 503ef250db6SAlexander Graf 504a915249fSAlexander Graf irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); 505a915249fSAlexander Graf irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); 506e61c36d5SAlexander Graf for (i = 0; i < smp_cpus; i++) { 507397b457dSAndreas Färber PowerPCCPU *cpu; 50855e5c285SAndreas Färber CPUState *cs; 509e61c36d5SAlexander Graf qemu_irq *input; 510397b457dSAndreas Färber 511e6eaabebSScott Wood cpu = cpu_ppc_init(params->cpu_model); 512397b457dSAndreas Färber if (cpu == NULL) { 5131db09b84Saurel32 fprintf(stderr, "Unable to initialize CPU!\n"); 5141db09b84Saurel32 exit(1); 5151db09b84Saurel32 } 516397b457dSAndreas Färber env = &cpu->env; 51755e5c285SAndreas Färber cs = CPU(cpu); 5181db09b84Saurel32 519e61c36d5SAlexander Graf if (!firstenv) { 520e61c36d5SAlexander Graf firstenv = env; 521e61c36d5SAlexander Graf } 522e61c36d5SAlexander Graf 523a915249fSAlexander Graf irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB); 524a915249fSAlexander Graf input = (qemu_irq *)env->irq_inputs; 525a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; 526a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; 52755e5c285SAndreas Färber env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i; 52868c2dd70SAlexander Graf env->mpic_iack = MPC8544_CCSRBAR_BASE + 529bd25922eSScott Wood MPC8544_MPIC_REGS_OFFSET + 0xa0; 530e61c36d5SAlexander Graf 531a34a92b9SAndreas Färber ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); 5323b989d49SAlexander Graf 5333b989d49SAlexander Graf /* Register reset handler */ 5345c145dacSAlexander Graf if (!i) { 5355c145dacSAlexander Graf /* Primary CPU */ 5365c145dacSAlexander Graf struct boot_info *boot_info; 537e61c36d5SAlexander Graf boot_info = g_malloc0(sizeof(struct boot_info)); 538b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset, cpu); 539e61c36d5SAlexander Graf env->load_info = boot_info; 5405c145dacSAlexander Graf } else { 5415c145dacSAlexander Graf /* Secondary CPUs */ 542b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset_sec, cpu); 5435c145dacSAlexander Graf } 544e61c36d5SAlexander Graf } 545e61c36d5SAlexander Graf 546e61c36d5SAlexander Graf env = firstenv; 5473b989d49SAlexander Graf 5481db09b84Saurel32 /* Fixup Memory size on a alignment boundary */ 5491db09b84Saurel32 ram_size &= ~(RAM_SIZES_ALIGN - 1); 5501db09b84Saurel32 5511db09b84Saurel32 /* Register Memory */ 552c5705a77SAvi Kivity memory_region_init_ram(ram, "mpc8544ds.ram", ram_size); 553c5705a77SAvi Kivity vmstate_register_ram_global(ram); 5542646c133SAvi Kivity memory_region_add_subregion(address_space_mem, 0, ram); 5551db09b84Saurel32 5563eddc1beSBharat Bhushan dev = qdev_create(NULL, "e500-ccsr"); 5573eddc1beSBharat Bhushan object_property_add_child(qdev_get_machine(), "e500-ccsr", 5583eddc1beSBharat Bhushan OBJECT(dev), NULL); 5593eddc1beSBharat Bhushan qdev_init_nofail(dev); 5603eddc1beSBharat Bhushan ccsr = CCSR(dev); 5613eddc1beSBharat Bhushan ccsr_addr_space = &ccsr->ccsr_space; 5623eddc1beSBharat Bhushan memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE, 5633eddc1beSBharat Bhushan ccsr_addr_space); 564dffb1dc2SBharat Bhushan 5651db09b84Saurel32 /* MPIC */ 566d0b72631SAlexander Graf mpic = g_new(qemu_irq, 256); 567d0b72631SAlexander Graf dev = qdev_create(NULL, "openpic"); 568d0b72631SAlexander Graf qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); 569f5fba9d2SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 570d0b72631SAlexander Graf qdev_init_nofail(dev); 5711356b98dSAndreas Färber s = SYS_BUS_DEVICE(dev); 572a915249fSAlexander Graf 573d0b72631SAlexander Graf k = 0; 574d0b72631SAlexander Graf for (i = 0; i < smp_cpus; i++) { 575d0b72631SAlexander Graf for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { 576d0b72631SAlexander Graf sysbus_connect_irq(s, k++, irqs[i][j]); 577a915249fSAlexander Graf } 578d0b72631SAlexander Graf } 579d0b72631SAlexander Graf 580d0b72631SAlexander Graf for (i = 0; i < 256; i++) { 581d0b72631SAlexander Graf mpic[i] = qdev_get_gpio_in(dev, i); 582d0b72631SAlexander Graf } 583d0b72631SAlexander Graf 584d0b72631SAlexander Graf memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET, 585d0b72631SAlexander Graf s->mmio[0].memory); 5861db09b84Saurel32 5871db09b84Saurel32 /* Serial */ 5882d48377aSBlue Swirl if (serial_hds[0]) { 5893eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, 590cdbb912aSAlexander Graf 0, mpic[42], 399193, 5912ff0c7c3SRichard Henderson serial_hds[0], DEVICE_BIG_ENDIAN); 5922d48377aSBlue Swirl } 5931db09b84Saurel32 5942d48377aSBlue Swirl if (serial_hds[1]) { 5953eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, 596cdbb912aSAlexander Graf 0, mpic[42], 399193, 59759de4f98SBharat Bhushan serial_hds[1], DEVICE_BIG_ENDIAN); 5982d48377aSBlue Swirl } 5991db09b84Saurel32 600b0fb8423SAlexander Graf /* General Utility device */ 601dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "mpc8544-guts"); 602dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 603dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 6043eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET, 605dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 606b0fb8423SAlexander Graf 6071db09b84Saurel32 /* PCI */ 608dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "e500-pcihost"); 609492ec48dSAlexander Graf qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); 610dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 611dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 612dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]); 613dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]); 614dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]); 615dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]); 6163eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, 617dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 618dffb1dc2SBharat Bhushan 619d461e3b9SAlexander Graf pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); 6201db09b84Saurel32 if (!pci_bus) 6211db09b84Saurel32 printf("couldn't create PCI controller!\n"); 6221db09b84Saurel32 6231356b98dSAndreas Färber sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO); 6241db09b84Saurel32 6251db09b84Saurel32 if (pci_bus) { 6261db09b84Saurel32 /* Register network interfaces. */ 6271db09b84Saurel32 for (i = 0; i < nb_nics; i++) { 62807caea31SMarkus Armbruster pci_nic_init_nofail(&nd_table[i], "virtio", NULL); 6291db09b84Saurel32 } 6301db09b84Saurel32 } 6311db09b84Saurel32 6325c145dacSAlexander Graf /* Register spinning region */ 6335c145dacSAlexander Graf sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); 6345c145dacSAlexander Graf 6351db09b84Saurel32 /* Load kernel. */ 636e6eaabebSScott Wood if (params->kernel_filename) { 637e6eaabebSScott Wood kernel_size = load_uimage(params->kernel_filename, &entry, 638e6eaabebSScott Wood &loadaddr, NULL); 6391db09b84Saurel32 if (kernel_size < 0) { 640e6eaabebSScott Wood kernel_size = load_elf(params->kernel_filename, NULL, NULL, 641e6eaabebSScott Wood &elf_entry, &elf_lowaddr, NULL, 1, 642e6eaabebSScott Wood ELF_MACHINE, 0); 6431db09b84Saurel32 entry = elf_entry; 6441db09b84Saurel32 loadaddr = elf_lowaddr; 6451db09b84Saurel32 } 6461db09b84Saurel32 /* XXX try again as binary */ 6471db09b84Saurel32 if (kernel_size < 0) { 6481db09b84Saurel32 fprintf(stderr, "qemu: could not load kernel '%s'\n", 649e6eaabebSScott Wood params->kernel_filename); 6501db09b84Saurel32 exit(1); 6511db09b84Saurel32 } 652528e536eSAlexander Graf 653528e536eSAlexander Graf cur_base = loadaddr + kernel_size; 654b8dec144SAlexander Graf 655b8dec144SAlexander Graf /* Reserve space for dtb */ 656b8dec144SAlexander Graf dt_base = (cur_base + DTC_LOAD_PAD) & ~DTC_PAD_MASK; 657b8dec144SAlexander Graf cur_base += DTB_MAX_SIZE; 6581db09b84Saurel32 } 6591db09b84Saurel32 6601db09b84Saurel32 /* Load initrd. */ 661e6eaabebSScott Wood if (params->initrd_filename) { 662528e536eSAlexander Graf initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; 663e6eaabebSScott Wood initrd_size = load_image_targphys(params->initrd_filename, initrd_base, 664d7585251Spbrook ram_size - initrd_base); 6651db09b84Saurel32 6661db09b84Saurel32 if (initrd_size < 0) { 6671db09b84Saurel32 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 668e6eaabebSScott Wood params->initrd_filename); 6691db09b84Saurel32 exit(1); 6701db09b84Saurel32 } 671528e536eSAlexander Graf 672528e536eSAlexander Graf cur_base = initrd_base + initrd_size; 6731db09b84Saurel32 } 6741db09b84Saurel32 6751db09b84Saurel32 /* If we're loading a kernel directly, we must load the device tree too. */ 676e6eaabebSScott Wood if (params->kernel_filename) { 6775c145dacSAlexander Graf struct boot_info *boot_info; 678cba2026aSAlexander Graf int dt_size; 6795c145dacSAlexander Graf 680e6eaabebSScott Wood dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base, 681e6eaabebSScott Wood initrd_size); 682cba2026aSAlexander Graf if (dt_size < 0) { 6831db09b84Saurel32 fprintf(stderr, "couldn't load device tree\n"); 6841db09b84Saurel32 exit(1); 6851db09b84Saurel32 } 686b8dec144SAlexander Graf assert(dt_size < DTB_MAX_SIZE); 6871db09b84Saurel32 688e61c36d5SAlexander Graf boot_info = env->load_info; 6893b989d49SAlexander Graf boot_info->entry = entry; 6903b989d49SAlexander Graf boot_info->dt_base = dt_base; 691cba2026aSAlexander Graf boot_info->dt_size = dt_size; 6921db09b84Saurel32 } 6931db09b84Saurel32 6943b989d49SAlexander Graf if (kvm_enabled()) { 6951db09b84Saurel32 kvmppc_init(); 6963b989d49SAlexander Graf } 6971db09b84Saurel32 } 6983eddc1beSBharat Bhushan 6993eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev) 7003eddc1beSBharat Bhushan { 7013eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 7023eddc1beSBharat Bhushan 7033eddc1beSBharat Bhushan ccsr = CCSR(dev); 7043eddc1beSBharat Bhushan memory_region_init(&ccsr->ccsr_space, "e500-ccsr", 7053eddc1beSBharat Bhushan MPC8544_CCSRBAR_SIZE); 7063eddc1beSBharat Bhushan return 0; 7073eddc1beSBharat Bhushan } 7083eddc1beSBharat Bhushan 7093eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data) 7103eddc1beSBharat Bhushan { 7113eddc1beSBharat Bhushan SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 7123eddc1beSBharat Bhushan k->init = e500_ccsr_initfn; 7133eddc1beSBharat Bhushan } 7143eddc1beSBharat Bhushan 7153eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = { 7163eddc1beSBharat Bhushan .name = TYPE_CCSR, 7173eddc1beSBharat Bhushan .parent = TYPE_SYS_BUS_DEVICE, 7183eddc1beSBharat Bhushan .instance_size = sizeof(PPCE500CCSRState), 7193eddc1beSBharat Bhushan .class_init = e500_ccsr_class_init, 7203eddc1beSBharat Bhushan }; 7213eddc1beSBharat Bhushan 7223eddc1beSBharat Bhushan static void e500_register_types(void) 7233eddc1beSBharat Bhushan { 7243eddc1beSBharat Bhushan type_register_static(&e500_ccsr_info); 7253eddc1beSBharat Bhushan } 7263eddc1beSBharat Bhushan 7273eddc1beSBharat Bhushan type_init(e500_register_types) 728