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 40cefd3cdbSBharat 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 126*28290f37SAlexander Graf static int ppce500_load_device_tree(QEMUMachineInitArgs *args, 127e6eaabebSScott Wood PPCE500Params *params, 128a8170e5eSAvi Kivity hwaddr addr, 129a8170e5eSAvi Kivity hwaddr initrd_base, 130*28290f37SAlexander Graf hwaddr initrd_size, 131*28290f37SAlexander Graf bool dry_run) 1321db09b84Saurel32 { 133*28290f37SAlexander Graf CPUPPCState *env = first_cpu->env_ptr; 134dbf916d8SAurelien Jarno int ret = -1; 13592238367SMarkus Armbruster uint64_t mem_reg_property[] = { 0, cpu_to_be64(args->ram_size) }; 1367ec632b4Spbrook int fdt_size; 137dbf916d8SAurelien Jarno void *fdt; 1385de6b46dSAlexander Graf uint8_t hypercall[16]; 139911d6e7aSAlexander Graf uint32_t clock_freq = 400000000; 140911d6e7aSAlexander Graf uint32_t tb_freq = 400000000; 141621d05e3SAlexander Graf int i; 142ebb9518aSAlexander Graf char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; 1435da96624SAlexander Graf char soc[128]; 14419ac9deaSAlexander Graf char mpic[128]; 14519ac9deaSAlexander Graf uint32_t mpic_ph; 146a911b7a9SAlexander Graf uint32_t msi_ph; 147f5038483SAlexander Graf char gutil[128]; 1480dbc0798SAlexander Graf char pci[128]; 149a911b7a9SAlexander Graf char msi[128]; 150347dd79dSAlexander Graf uint32_t *pci_map = NULL; 151347dd79dSAlexander Graf int len; 1523627757eSAlexander Graf uint32_t pci_ranges[14] = 1533627757eSAlexander Graf { 1543627757eSAlexander Graf 0x2000000, 0x0, 0xc0000000, 1553627757eSAlexander Graf 0x0, 0xc0000000, 1563627757eSAlexander Graf 0x0, 0x20000000, 1573627757eSAlexander Graf 1583627757eSAlexander Graf 0x1000000, 0x0, 0x0, 1593627757eSAlexander Graf 0x0, 0xe1000000, 1603627757eSAlexander Graf 0x0, 0x10000, 1613627757eSAlexander Graf }; 1622ff3de68SMarkus Armbruster QemuOpts *machine_opts = qemu_get_machine_opts(); 1632ff3de68SMarkus Armbruster const char *dtb_file = qemu_opt_get(machine_opts, "dtb"); 1642ff3de68SMarkus Armbruster const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); 165d1b93565SAlexander Graf 166d1b93565SAlexander Graf if (dtb_file) { 167d1b93565SAlexander Graf char *filename; 168d1b93565SAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file); 169d1b93565SAlexander Graf if (!filename) { 170d1b93565SAlexander Graf goto out; 171d1b93565SAlexander Graf } 172d1b93565SAlexander Graf 173d1b93565SAlexander Graf fdt = load_device_tree(filename, &fdt_size); 174d1b93565SAlexander Graf if (!fdt) { 175d1b93565SAlexander Graf goto out; 176d1b93565SAlexander Graf } 177d1b93565SAlexander Graf goto done; 178d1b93565SAlexander Graf } 1791db09b84Saurel32 1802636fcb6SAlexander Graf fdt = create_device_tree(&fdt_size); 1815cea8590SPaul Brook if (fdt == NULL) { 1825cea8590SPaul Brook goto out; 1835cea8590SPaul Brook } 1841db09b84Saurel32 1851db09b84Saurel32 /* Manipulate device tree in memory. */ 1863627757eSAlexander Graf qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2); 1873627757eSAlexander Graf qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2); 18851b852b7SAlexander Graf 189dd0bcfcaSAlexander Graf qemu_devtree_add_subnode(fdt, "/memory"); 190dd0bcfcaSAlexander Graf qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory"); 191dd0bcfcaSAlexander Graf qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property, 1921db09b84Saurel32 sizeof(mem_reg_property)); 1931db09b84Saurel32 194f5231aafSAlexander Graf qemu_devtree_add_subnode(fdt, "/chosen"); 1953b989d49SAlexander Graf if (initrd_size) { 1961db09b84Saurel32 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start", 1971db09b84Saurel32 initrd_base); 1983b989d49SAlexander Graf if (ret < 0) { 1991db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); 2003b989d49SAlexander Graf } 2011db09b84Saurel32 2021db09b84Saurel32 ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end", 2031db09b84Saurel32 (initrd_base + initrd_size)); 2043b989d49SAlexander Graf if (ret < 0) { 2051db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); 2063b989d49SAlexander Graf } 2073b989d49SAlexander Graf } 2081db09b84Saurel32 2091db09b84Saurel32 ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", 21092238367SMarkus Armbruster args->kernel_cmdline); 2111db09b84Saurel32 if (ret < 0) 2121db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/bootargs\n"); 2131db09b84Saurel32 2141db09b84Saurel32 if (kvm_enabled()) { 215911d6e7aSAlexander Graf /* Read out host's frequencies */ 216911d6e7aSAlexander Graf clock_freq = kvmppc_get_clockfreq(); 217911d6e7aSAlexander Graf tb_freq = kvmppc_get_tbfreq(); 2185de6b46dSAlexander Graf 2195de6b46dSAlexander Graf /* indicate KVM hypercall interface */ 220d50f71a5SAlexander Graf qemu_devtree_add_subnode(fdt, "/hypervisor"); 2215de6b46dSAlexander Graf qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible", 2225de6b46dSAlexander Graf "linux,kvm"); 2235de6b46dSAlexander Graf kvmppc_get_hypercall(env, hypercall, sizeof(hypercall)); 2245de6b46dSAlexander Graf qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions", 2255de6b46dSAlexander Graf hypercall, sizeof(hypercall)); 2261a61a9aeSStuart Yoder /* if KVM supports the idle hcall, set property indicating this */ 2271a61a9aeSStuart Yoder if (kvmppc_get_hasidle(env)) { 2281a61a9aeSStuart Yoder qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0); 2291a61a9aeSStuart Yoder } 2301db09b84Saurel32 } 2311db09b84Saurel32 232625e665bSAlexander Graf /* Create CPU nodes */ 233625e665bSAlexander Graf qemu_devtree_add_subnode(fdt, "/cpus"); 234625e665bSAlexander Graf qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1); 235625e665bSAlexander Graf qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0); 236625e665bSAlexander Graf 2371e3debf0SAlexander Graf /* We need to generate the cpu nodes in reverse order, so Linux can pick 2381e3debf0SAlexander Graf the first node as boot node and be happy */ 2391e3debf0SAlexander Graf for (i = smp_cpus - 1; i >= 0; i--) { 240440c8152SAndreas Färber CPUState *cpu; 241621d05e3SAlexander Graf char cpu_name[128]; 2421d2e5c52SAlexander Graf uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); 24310f25a46SAlexander Graf 244440c8152SAndreas Färber cpu = qemu_get_cpu(i); 24555e5c285SAndreas Färber if (cpu == NULL) { 2461e3debf0SAlexander Graf continue; 2471e3debf0SAlexander Graf } 248440c8152SAndreas Färber env = cpu->env_ptr; 2491e3debf0SAlexander Graf 25055e5c285SAndreas Färber snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", 25155e5c285SAndreas Färber cpu->cpu_index); 2521e3debf0SAlexander Graf qemu_devtree_add_subnode(fdt, cpu_name); 2531e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq); 2541e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq); 2551e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu"); 25655e5c285SAndreas Färber qemu_devtree_setprop_cell(fdt, cpu_name, "reg", cpu->cpu_index); 2571e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size", 2581e3debf0SAlexander Graf env->dcache_line_size); 2591e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size", 2601e3debf0SAlexander Graf env->icache_line_size); 2611e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000); 2621e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000); 2631e3debf0SAlexander Graf qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0); 26455e5c285SAndreas Färber if (cpu->cpu_index) { 2651e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled"); 2661e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table"); 2671d2e5c52SAlexander Graf qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr", 2681d2e5c52SAlexander Graf cpu_release_addr); 2691e3debf0SAlexander Graf } else { 2701e3debf0SAlexander Graf qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay"); 2711e3debf0SAlexander Graf } 2721db09b84Saurel32 } 2731db09b84Saurel32 2740cfc6e8dSAlexander Graf qemu_devtree_add_subnode(fdt, "/aliases"); 2755da96624SAlexander Graf /* XXX These should go into their respective devices' code */ 276ed2bc496SAlexander Graf snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE); 2775da96624SAlexander Graf qemu_devtree_add_subnode(fdt, soc); 2785da96624SAlexander Graf qemu_devtree_setprop_string(fdt, soc, "device_type", "soc"); 279ebb9518aSAlexander Graf qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb, 280ebb9518aSAlexander Graf sizeof(compatible_sb)); 2815da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1); 2825da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1); 2833627757eSAlexander Graf qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0, 2843627757eSAlexander Graf MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE, 2855da96624SAlexander Graf MPC8544_CCSRBAR_SIZE); 2865da96624SAlexander Graf /* XXX should contain a reasonable value */ 2875da96624SAlexander Graf qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0); 2885da96624SAlexander Graf 289dffb1dc2SBharat Bhushan snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET); 29019ac9deaSAlexander Graf qemu_devtree_add_subnode(fdt, mpic); 29119ac9deaSAlexander Graf qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic"); 292f5fba9d2SScott Wood qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); 293dffb1dc2SBharat Bhushan qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET, 294dffb1dc2SBharat Bhushan 0x40000); 29519ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0); 2967e99826cSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2); 29719ac9deaSAlexander Graf mpic_ph = qemu_devtree_alloc_phandle(fdt); 29819ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph); 29919ac9deaSAlexander Graf qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); 30019ac9deaSAlexander Graf qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0); 30119ac9deaSAlexander Graf 3020cfc6e8dSAlexander Graf /* 3030cfc6e8dSAlexander Graf * We have to generate ser1 first, because Linux takes the first 3040cfc6e8dSAlexander Graf * device it finds in the dt as serial output device. And we generate 3050cfc6e8dSAlexander Graf * devices in reverse order to the dt. 3060cfc6e8dSAlexander Graf */ 307dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET, 308a053a7ceSAlexander Graf soc, mpic, "serial1", 1, false); 309dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET, 310a053a7ceSAlexander Graf soc, mpic, "serial0", 0, true); 3110cfc6e8dSAlexander Graf 312ed2bc496SAlexander Graf snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, 313dffb1dc2SBharat Bhushan MPC8544_UTIL_OFFSET); 314f5038483SAlexander Graf qemu_devtree_add_subnode(fdt, gutil); 315f5038483SAlexander Graf qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); 316dffb1dc2SBharat Bhushan qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000); 317f5038483SAlexander Graf qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); 318f5038483SAlexander Graf 319a911b7a9SAlexander Graf snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET); 320a911b7a9SAlexander Graf qemu_devtree_add_subnode(fdt, msi); 321a911b7a9SAlexander Graf qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi"); 322a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200); 323a911b7a9SAlexander Graf msi_ph = qemu_devtree_alloc_phandle(fdt); 324a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100); 325a911b7a9SAlexander Graf qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic); 326a911b7a9SAlexander Graf qemu_devtree_setprop_cells(fdt, msi, "interrupts", 327a911b7a9SAlexander Graf 0xe0, 0x0, 328a911b7a9SAlexander Graf 0xe1, 0x0, 329a911b7a9SAlexander Graf 0xe2, 0x0, 330a911b7a9SAlexander Graf 0xe3, 0x0, 331a911b7a9SAlexander Graf 0xe4, 0x0, 332a911b7a9SAlexander Graf 0xe5, 0x0, 333a911b7a9SAlexander Graf 0xe6, 0x0, 334a911b7a9SAlexander Graf 0xe7, 0x0); 335a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph); 336a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph); 337a911b7a9SAlexander Graf 338ed2bc496SAlexander Graf snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); 3390dbc0798SAlexander Graf qemu_devtree_add_subnode(fdt, pci); 3400dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0); 3410dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); 3420dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, pci, "device_type", "pci"); 3430dbc0798SAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 3440dbc0798SAlexander Graf 0x0, 0x7); 345347dd79dSAlexander Graf pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic), 346492ec48dSAlexander Graf params->pci_first_slot, params->pci_nr_slots, 347492ec48dSAlexander Graf &len); 348347dd79dSAlexander Graf qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len); 3490dbc0798SAlexander Graf qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic); 3507e99826cSAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2); 3510dbc0798SAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255); 3523627757eSAlexander Graf for (i = 0; i < 14; i++) { 3530dbc0798SAlexander Graf pci_ranges[i] = cpu_to_be32(pci_ranges[i]); 3540dbc0798SAlexander Graf } 355a911b7a9SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph); 3560dbc0798SAlexander Graf qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); 3573627757eSAlexander Graf qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32, 3583627757eSAlexander Graf MPC8544_PCI_REGS_BASE, 0, 0x1000); 3590dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666); 3600dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1); 3610dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2); 3620dbc0798SAlexander Graf qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3); 3630dbc0798SAlexander Graf qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci); 3640dbc0798SAlexander Graf 365e6eaabebSScott Wood params->fixup_devtree(params, fdt); 366e6eaabebSScott Wood 367e6eaabebSScott Wood if (toplevel_compat) { 368e6eaabebSScott Wood qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat, 369e6eaabebSScott Wood strlen(toplevel_compat) + 1); 370e6eaabebSScott Wood } 371e6eaabebSScott Wood 372d1b93565SAlexander Graf done: 373*28290f37SAlexander Graf if (!dry_run) { 37471193433SAlexander Graf qemu_devtree_dumpdtb(fdt, fdt_size); 375*28290f37SAlexander Graf cpu_physical_memory_write(addr, fdt, fdt_size); 376cba2026aSAlexander Graf } 377cba2026aSAlexander Graf ret = fdt_size; 3787ec632b4Spbrook 3791db09b84Saurel32 out: 380347dd79dSAlexander Graf g_free(pci_map); 3811db09b84Saurel32 38204088adbSLiu Yu return ret; 3831db09b84Saurel32 } 3841db09b84Saurel32 385*28290f37SAlexander Graf typedef struct DeviceTreeParams { 386*28290f37SAlexander Graf QEMUMachineInitArgs args; 387*28290f37SAlexander Graf PPCE500Params params; 388*28290f37SAlexander Graf hwaddr addr; 389*28290f37SAlexander Graf hwaddr initrd_base; 390*28290f37SAlexander Graf hwaddr initrd_size; 391*28290f37SAlexander Graf } DeviceTreeParams; 392*28290f37SAlexander Graf 393*28290f37SAlexander Graf static void ppce500_reset_device_tree(void *opaque) 394*28290f37SAlexander Graf { 395*28290f37SAlexander Graf DeviceTreeParams *p = opaque; 396*28290f37SAlexander Graf ppce500_load_device_tree(&p->args, &p->params, p->addr, p->initrd_base, 397*28290f37SAlexander Graf p->initrd_size, false); 398*28290f37SAlexander Graf } 399*28290f37SAlexander Graf 400*28290f37SAlexander Graf static int ppce500_prep_device_tree(QEMUMachineInitArgs *args, 401*28290f37SAlexander Graf PPCE500Params *params, 402*28290f37SAlexander Graf hwaddr addr, 403*28290f37SAlexander Graf hwaddr initrd_base, 404*28290f37SAlexander Graf hwaddr initrd_size) 405*28290f37SAlexander Graf { 406*28290f37SAlexander Graf DeviceTreeParams *p = g_new(DeviceTreeParams, 1); 407*28290f37SAlexander Graf p->args = *args; 408*28290f37SAlexander Graf p->params = *params; 409*28290f37SAlexander Graf p->addr = addr; 410*28290f37SAlexander Graf p->initrd_base = initrd_base; 411*28290f37SAlexander Graf p->initrd_size = initrd_size; 412*28290f37SAlexander Graf 413*28290f37SAlexander Graf qemu_register_reset(ppce500_reset_device_tree, p); 414*28290f37SAlexander Graf 415*28290f37SAlexander Graf /* Issue the device tree loader once, so that we get the size of the blob */ 416*28290f37SAlexander Graf return ppce500_load_device_tree(args, params, addr, initrd_base, 417*28290f37SAlexander Graf initrd_size, true); 418*28290f37SAlexander Graf } 419*28290f37SAlexander Graf 420cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE. */ 421a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size) 422d1e256feSAlexander Graf { 423cba2026aSAlexander Graf return 63 - clz64(size >> 10); 424d1e256feSAlexander Graf } 425d1e256feSAlexander Graf 426cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env) 4273b989d49SAlexander Graf { 428cba2026aSAlexander Graf struct boot_info *bi = env->load_info; 429cefd3cdbSBharat Bhushan hwaddr dt_end; 430cba2026aSAlexander Graf int ps; 4313b989d49SAlexander Graf 432cba2026aSAlexander Graf /* Our initial TLB entry needs to cover everything from 0 to 433cba2026aSAlexander Graf the device tree top */ 434cba2026aSAlexander Graf dt_end = bi->dt_base + bi->dt_size; 435cba2026aSAlexander Graf ps = booke206_page_size_to_tlb(dt_end) + 1; 436fb37c302SAlexander Graf if (ps & 1) { 437fb37c302SAlexander Graf /* e500v2 can only do even TLB size bits */ 438fb37c302SAlexander Graf ps++; 439fb37c302SAlexander Graf } 440cefd3cdbSBharat Bhushan return ps; 441cefd3cdbSBharat Bhushan } 442cefd3cdbSBharat Bhushan 443cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env) 444cefd3cdbSBharat Bhushan { 445cefd3cdbSBharat Bhushan int tsize; 446cefd3cdbSBharat Bhushan 447cefd3cdbSBharat Bhushan tsize = booke206_initial_map_tsize(env); 448cefd3cdbSBharat Bhushan return (1ULL << 10 << tsize); 449cefd3cdbSBharat Bhushan } 450cefd3cdbSBharat Bhushan 451cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env) 452cefd3cdbSBharat Bhushan { 453cefd3cdbSBharat Bhushan ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); 454cefd3cdbSBharat Bhushan hwaddr size; 455cefd3cdbSBharat Bhushan int ps; 456cefd3cdbSBharat Bhushan 457cefd3cdbSBharat Bhushan ps = booke206_initial_map_tsize(env); 458cba2026aSAlexander Graf size = (ps << MAS1_TSIZE_SHIFT); 459d1e256feSAlexander Graf tlb->mas1 = MAS1_VALID | size; 460cba2026aSAlexander Graf tlb->mas2 = 0; 461cba2026aSAlexander Graf tlb->mas7_3 = 0; 462d1e256feSAlexander Graf tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; 46393dd5e85SScott Wood 46493dd5e85SScott Wood env->tlb_dirty = true; 4653b989d49SAlexander Graf } 4663b989d49SAlexander Graf 467b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque) 4685c145dacSAlexander Graf { 46938f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 470259186a7SAndreas Färber CPUState *cs = CPU(cpu); 47138f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 4725c145dacSAlexander Graf 473259186a7SAndreas Färber cpu_reset(cs); 4745c145dacSAlexander Graf 4755c145dacSAlexander Graf /* Secondary CPU starts in halted state for now. Needs to change when 4765c145dacSAlexander Graf implementing non-kernel boot. */ 477259186a7SAndreas Färber cs->halted = 1; 4785c145dacSAlexander Graf env->exception_index = EXCP_HLT; 4793b989d49SAlexander Graf } 4803b989d49SAlexander Graf 481b3305981SScott Wood static void ppce500_cpu_reset(void *opaque) 4823b989d49SAlexander Graf { 48338f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 484259186a7SAndreas Färber CPUState *cs = CPU(cpu); 48538f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 4863b989d49SAlexander Graf struct boot_info *bi = env->load_info; 4873b989d49SAlexander Graf 488259186a7SAndreas Färber cpu_reset(cs); 4893b989d49SAlexander Graf 4903b989d49SAlexander Graf /* Set initial guest state. */ 491259186a7SAndreas Färber cs->halted = 0; 4923b989d49SAlexander Graf env->gpr[1] = (16<<20) - 8; 4933b989d49SAlexander Graf env->gpr[3] = bi->dt_base; 494cefd3cdbSBharat Bhushan env->gpr[4] = 0; 495cefd3cdbSBharat Bhushan env->gpr[5] = 0; 496cefd3cdbSBharat Bhushan env->gpr[6] = EPAPR_MAGIC; 497cefd3cdbSBharat Bhushan env->gpr[7] = mmubooke_initial_mapsize(env); 498cefd3cdbSBharat Bhushan env->gpr[8] = 0; 499cefd3cdbSBharat Bhushan env->gpr[9] = 0; 5003b989d49SAlexander Graf env->nip = bi->entry; 501cba2026aSAlexander Graf mmubooke_create_initial_mapping(env); 5023b989d49SAlexander Graf } 5033b989d49SAlexander Graf 504d85937e6SScott Wood static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params, 50582fc73b6SScott Wood qemu_irq **irqs) 50682fc73b6SScott Wood { 50782fc73b6SScott Wood DeviceState *dev; 50882fc73b6SScott Wood SysBusDevice *s; 50982fc73b6SScott Wood int i, j, k; 51082fc73b6SScott Wood 511e1766344SAndreas Färber dev = qdev_create(NULL, TYPE_OPENPIC); 51282fc73b6SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 513d85937e6SScott Wood qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); 514d85937e6SScott Wood 51582fc73b6SScott Wood qdev_init_nofail(dev); 51682fc73b6SScott Wood s = SYS_BUS_DEVICE(dev); 51782fc73b6SScott Wood 51882fc73b6SScott Wood k = 0; 51982fc73b6SScott Wood for (i = 0; i < smp_cpus; i++) { 52082fc73b6SScott Wood for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { 52182fc73b6SScott Wood sysbus_connect_irq(s, k++, irqs[i][j]); 52282fc73b6SScott Wood } 52382fc73b6SScott Wood } 52482fc73b6SScott Wood 525d85937e6SScott Wood return dev; 526d85937e6SScott Wood } 527d85937e6SScott Wood 528d85937e6SScott Wood static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, 529d85937e6SScott Wood qemu_irq **irqs) 530d85937e6SScott Wood { 531d85937e6SScott Wood DeviceState *dev; 532d85937e6SScott Wood CPUState *cs; 533d85937e6SScott Wood int r; 534d85937e6SScott Wood 535dd49c038SAndreas Färber dev = qdev_create(NULL, TYPE_KVM_OPENPIC); 536d85937e6SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 537d85937e6SScott Wood 538d85937e6SScott Wood r = qdev_init(dev); 539d85937e6SScott Wood if (r) { 540d85937e6SScott Wood return NULL; 541d85937e6SScott Wood } 542d85937e6SScott Wood 543182735efSAndreas Färber for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { 544d85937e6SScott Wood if (kvm_openpic_connect_vcpu(dev, cs)) { 545d85937e6SScott Wood fprintf(stderr, "%s: failed to connect vcpu to irqchip\n", 546d85937e6SScott Wood __func__); 547d85937e6SScott Wood abort(); 548d85937e6SScott Wood } 549d85937e6SScott Wood } 550d85937e6SScott Wood 551d85937e6SScott Wood return dev; 552d85937e6SScott Wood } 553d85937e6SScott Wood 554d85937e6SScott Wood static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, 555d85937e6SScott Wood qemu_irq **irqs) 556d85937e6SScott Wood { 557d85937e6SScott Wood qemu_irq *mpic; 558d85937e6SScott Wood DeviceState *dev = NULL; 559d85937e6SScott Wood SysBusDevice *s; 560d85937e6SScott Wood int i; 561d85937e6SScott Wood 562d85937e6SScott Wood mpic = g_new(qemu_irq, 256); 563d85937e6SScott Wood 564d85937e6SScott Wood if (kvm_enabled()) { 56536ad0e94SMarkus Armbruster QemuOpts *machine_opts = qemu_get_machine_opts(); 56636ad0e94SMarkus Armbruster bool irqchip_allowed = qemu_opt_get_bool(machine_opts, 567d85937e6SScott Wood "kernel_irqchip", true); 56836ad0e94SMarkus Armbruster bool irqchip_required = qemu_opt_get_bool(machine_opts, 569d85937e6SScott Wood "kernel_irqchip", false); 570d85937e6SScott Wood 571d85937e6SScott Wood if (irqchip_allowed) { 572d85937e6SScott Wood dev = ppce500_init_mpic_kvm(params, irqs); 573d85937e6SScott Wood } 574d85937e6SScott Wood 575d85937e6SScott Wood if (irqchip_required && !dev) { 576d85937e6SScott Wood fprintf(stderr, "%s: irqchip requested but unavailable\n", 577d85937e6SScott Wood __func__); 578d85937e6SScott Wood abort(); 579d85937e6SScott Wood } 580d85937e6SScott Wood } 581d85937e6SScott Wood 582d85937e6SScott Wood if (!dev) { 583d85937e6SScott Wood dev = ppce500_init_mpic_qemu(params, irqs); 584d85937e6SScott Wood } 585d85937e6SScott Wood 58682fc73b6SScott Wood for (i = 0; i < 256; i++) { 58782fc73b6SScott Wood mpic[i] = qdev_get_gpio_in(dev, i); 58882fc73b6SScott Wood } 58982fc73b6SScott Wood 590d85937e6SScott Wood s = SYS_BUS_DEVICE(dev); 59182fc73b6SScott Wood memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET, 59282fc73b6SScott Wood s->mmio[0].memory); 59382fc73b6SScott Wood 59482fc73b6SScott Wood return mpic; 59582fc73b6SScott Wood } 59682fc73b6SScott Wood 59792238367SMarkus Armbruster void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) 5981db09b84Saurel32 { 59939186d8aSRichard Henderson MemoryRegion *address_space_mem = get_system_memory(); 6002646c133SAvi Kivity MemoryRegion *ram = g_new(MemoryRegion, 1); 6011db09b84Saurel32 PCIBus *pci_bus; 602e2684c0bSAndreas Färber CPUPPCState *env = NULL; 6031db09b84Saurel32 uint64_t elf_entry; 6041db09b84Saurel32 uint64_t elf_lowaddr; 605a8170e5eSAvi Kivity hwaddr entry=0; 606a8170e5eSAvi Kivity hwaddr loadaddr=UIMAGE_LOAD_BASE; 6071db09b84Saurel32 target_long kernel_size=0; 60875bb6589SLiu Yu target_ulong dt_base = 0; 60975bb6589SLiu Yu target_ulong initrd_base = 0; 6101db09b84Saurel32 target_long initrd_size = 0; 611528e536eSAlexander Graf target_ulong cur_base = 0; 61282fc73b6SScott Wood int i; 6131db09b84Saurel32 unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; 614a915249fSAlexander Graf qemu_irq **irqs, *mpic; 615be13cc7aSAlexander Graf DeviceState *dev; 616e2684c0bSAndreas Färber CPUPPCState *firstenv = NULL; 6173eddc1beSBharat Bhushan MemoryRegion *ccsr_addr_space; 618dffb1dc2SBharat Bhushan SysBusDevice *s; 6193eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 6201db09b84Saurel32 621e61c36d5SAlexander Graf /* Setup CPUs */ 62292238367SMarkus Armbruster if (args->cpu_model == NULL) { 62392238367SMarkus Armbruster args->cpu_model = "e500v2_v30"; 624ef250db6SAlexander Graf } 625ef250db6SAlexander Graf 626a915249fSAlexander Graf irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); 627a915249fSAlexander Graf irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); 628e61c36d5SAlexander Graf for (i = 0; i < smp_cpus; i++) { 629397b457dSAndreas Färber PowerPCCPU *cpu; 63055e5c285SAndreas Färber CPUState *cs; 631e61c36d5SAlexander Graf qemu_irq *input; 632397b457dSAndreas Färber 63392238367SMarkus Armbruster cpu = cpu_ppc_init(args->cpu_model); 634397b457dSAndreas Färber if (cpu == NULL) { 6351db09b84Saurel32 fprintf(stderr, "Unable to initialize CPU!\n"); 6361db09b84Saurel32 exit(1); 6371db09b84Saurel32 } 638397b457dSAndreas Färber env = &cpu->env; 63955e5c285SAndreas Färber cs = CPU(cpu); 6401db09b84Saurel32 641e61c36d5SAlexander Graf if (!firstenv) { 642e61c36d5SAlexander Graf firstenv = env; 643e61c36d5SAlexander Graf } 644e61c36d5SAlexander Graf 645a915249fSAlexander Graf irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB); 646a915249fSAlexander Graf input = (qemu_irq *)env->irq_inputs; 647a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; 648a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; 64955e5c285SAndreas Färber env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i; 65068c2dd70SAlexander Graf env->mpic_iack = MPC8544_CCSRBAR_BASE + 651bd25922eSScott Wood MPC8544_MPIC_REGS_OFFSET + 0xa0; 652e61c36d5SAlexander Graf 653a34a92b9SAndreas Färber ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); 6543b989d49SAlexander Graf 6553b989d49SAlexander Graf /* Register reset handler */ 6565c145dacSAlexander Graf if (!i) { 6575c145dacSAlexander Graf /* Primary CPU */ 6585c145dacSAlexander Graf struct boot_info *boot_info; 659e61c36d5SAlexander Graf boot_info = g_malloc0(sizeof(struct boot_info)); 660b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset, cpu); 661e61c36d5SAlexander Graf env->load_info = boot_info; 6625c145dacSAlexander Graf } else { 6635c145dacSAlexander Graf /* Secondary CPUs */ 664b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset_sec, cpu); 6655c145dacSAlexander Graf } 666e61c36d5SAlexander Graf } 667e61c36d5SAlexander Graf 668e61c36d5SAlexander Graf env = firstenv; 6693b989d49SAlexander Graf 6701db09b84Saurel32 /* Fixup Memory size on a alignment boundary */ 6711db09b84Saurel32 ram_size &= ~(RAM_SIZES_ALIGN - 1); 67292238367SMarkus Armbruster args->ram_size = ram_size; 6731db09b84Saurel32 6741db09b84Saurel32 /* Register Memory */ 6752c9b15caSPaolo Bonzini memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size); 676c5705a77SAvi Kivity vmstate_register_ram_global(ram); 6772646c133SAvi Kivity memory_region_add_subregion(address_space_mem, 0, ram); 6781db09b84Saurel32 6793eddc1beSBharat Bhushan dev = qdev_create(NULL, "e500-ccsr"); 6803eddc1beSBharat Bhushan object_property_add_child(qdev_get_machine(), "e500-ccsr", 6813eddc1beSBharat Bhushan OBJECT(dev), NULL); 6823eddc1beSBharat Bhushan qdev_init_nofail(dev); 6833eddc1beSBharat Bhushan ccsr = CCSR(dev); 6843eddc1beSBharat Bhushan ccsr_addr_space = &ccsr->ccsr_space; 6853eddc1beSBharat Bhushan memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE, 6863eddc1beSBharat Bhushan ccsr_addr_space); 687dffb1dc2SBharat Bhushan 68882fc73b6SScott Wood mpic = ppce500_init_mpic(params, ccsr_addr_space, irqs); 6891db09b84Saurel32 6901db09b84Saurel32 /* Serial */ 6912d48377aSBlue Swirl if (serial_hds[0]) { 6923eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, 693cdbb912aSAlexander Graf 0, mpic[42], 399193, 6942ff0c7c3SRichard Henderson serial_hds[0], DEVICE_BIG_ENDIAN); 6952d48377aSBlue Swirl } 6961db09b84Saurel32 6972d48377aSBlue Swirl if (serial_hds[1]) { 6983eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, 699cdbb912aSAlexander Graf 0, mpic[42], 399193, 70059de4f98SBharat Bhushan serial_hds[1], DEVICE_BIG_ENDIAN); 7012d48377aSBlue Swirl } 7021db09b84Saurel32 703b0fb8423SAlexander Graf /* General Utility device */ 704dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "mpc8544-guts"); 705dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 706dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 7073eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET, 708dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 709b0fb8423SAlexander Graf 7101db09b84Saurel32 /* PCI */ 711dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "e500-pcihost"); 712492ec48dSAlexander Graf qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); 713dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 714dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 715dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]); 716dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]); 717dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]); 718dffb1dc2SBharat Bhushan sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]); 7193eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, 720dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 721dffb1dc2SBharat Bhushan 722d461e3b9SAlexander Graf pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); 7231db09b84Saurel32 if (!pci_bus) 7241db09b84Saurel32 printf("couldn't create PCI controller!\n"); 7251db09b84Saurel32 7261356b98dSAndreas Färber sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO); 7271db09b84Saurel32 7281db09b84Saurel32 if (pci_bus) { 7291db09b84Saurel32 /* Register network interfaces. */ 7301db09b84Saurel32 for (i = 0; i < nb_nics; i++) { 73129b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL); 7321db09b84Saurel32 } 7331db09b84Saurel32 } 7341db09b84Saurel32 7355c145dacSAlexander Graf /* Register spinning region */ 7365c145dacSAlexander Graf sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); 7375c145dacSAlexander Graf 7381db09b84Saurel32 /* Load kernel. */ 73992238367SMarkus Armbruster if (args->kernel_filename) { 74092238367SMarkus Armbruster kernel_size = load_uimage(args->kernel_filename, &entry, 741e6eaabebSScott Wood &loadaddr, NULL); 7421db09b84Saurel32 if (kernel_size < 0) { 74392238367SMarkus Armbruster kernel_size = load_elf(args->kernel_filename, NULL, NULL, 744e6eaabebSScott Wood &elf_entry, &elf_lowaddr, NULL, 1, 745e6eaabebSScott Wood ELF_MACHINE, 0); 7461db09b84Saurel32 entry = elf_entry; 7471db09b84Saurel32 loadaddr = elf_lowaddr; 7481db09b84Saurel32 } 7491db09b84Saurel32 /* XXX try again as binary */ 7501db09b84Saurel32 if (kernel_size < 0) { 7511db09b84Saurel32 fprintf(stderr, "qemu: could not load kernel '%s'\n", 75292238367SMarkus Armbruster args->kernel_filename); 7531db09b84Saurel32 exit(1); 7541db09b84Saurel32 } 755528e536eSAlexander Graf 756528e536eSAlexander Graf cur_base = loadaddr + kernel_size; 757b8dec144SAlexander Graf 758b8dec144SAlexander Graf /* Reserve space for dtb */ 759b8dec144SAlexander Graf dt_base = (cur_base + DTC_LOAD_PAD) & ~DTC_PAD_MASK; 760b8dec144SAlexander Graf cur_base += DTB_MAX_SIZE; 7611db09b84Saurel32 } 7621db09b84Saurel32 7631db09b84Saurel32 /* Load initrd. */ 76492238367SMarkus Armbruster if (args->initrd_filename) { 765528e536eSAlexander Graf initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; 76692238367SMarkus Armbruster initrd_size = load_image_targphys(args->initrd_filename, initrd_base, 767d7585251Spbrook ram_size - initrd_base); 7681db09b84Saurel32 7691db09b84Saurel32 if (initrd_size < 0) { 7701db09b84Saurel32 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 77192238367SMarkus Armbruster args->initrd_filename); 7721db09b84Saurel32 exit(1); 7731db09b84Saurel32 } 774528e536eSAlexander Graf 775528e536eSAlexander Graf cur_base = initrd_base + initrd_size; 7761db09b84Saurel32 } 7771db09b84Saurel32 7781db09b84Saurel32 /* If we're loading a kernel directly, we must load the device tree too. */ 77992238367SMarkus Armbruster if (args->kernel_filename) { 7805c145dacSAlexander Graf struct boot_info *boot_info; 781cba2026aSAlexander Graf int dt_size; 7825c145dacSAlexander Graf 783*28290f37SAlexander Graf dt_size = ppce500_prep_device_tree(args, params, dt_base, 78492238367SMarkus Armbruster initrd_base, initrd_size); 785cba2026aSAlexander Graf if (dt_size < 0) { 7861db09b84Saurel32 fprintf(stderr, "couldn't load device tree\n"); 7871db09b84Saurel32 exit(1); 7881db09b84Saurel32 } 789b8dec144SAlexander Graf assert(dt_size < DTB_MAX_SIZE); 7901db09b84Saurel32 791e61c36d5SAlexander Graf boot_info = env->load_info; 7923b989d49SAlexander Graf boot_info->entry = entry; 7933b989d49SAlexander Graf boot_info->dt_base = dt_base; 794cba2026aSAlexander Graf boot_info->dt_size = dt_size; 7951db09b84Saurel32 } 7961db09b84Saurel32 7973b989d49SAlexander Graf if (kvm_enabled()) { 7981db09b84Saurel32 kvmppc_init(); 7993b989d49SAlexander Graf } 8001db09b84Saurel32 } 8013eddc1beSBharat Bhushan 8023eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev) 8033eddc1beSBharat Bhushan { 8043eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 8053eddc1beSBharat Bhushan 8063eddc1beSBharat Bhushan ccsr = CCSR(dev); 80740c5dce9SPaolo Bonzini memory_region_init(&ccsr->ccsr_space, OBJECT(ccsr), "e500-ccsr", 8083eddc1beSBharat Bhushan MPC8544_CCSRBAR_SIZE); 8093eddc1beSBharat Bhushan return 0; 8103eddc1beSBharat Bhushan } 8113eddc1beSBharat Bhushan 8123eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data) 8133eddc1beSBharat Bhushan { 8143eddc1beSBharat Bhushan SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 8153eddc1beSBharat Bhushan k->init = e500_ccsr_initfn; 8163eddc1beSBharat Bhushan } 8173eddc1beSBharat Bhushan 8183eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = { 8193eddc1beSBharat Bhushan .name = TYPE_CCSR, 8203eddc1beSBharat Bhushan .parent = TYPE_SYS_BUS_DEVICE, 8213eddc1beSBharat Bhushan .instance_size = sizeof(PPCE500CCSRState), 8223eddc1beSBharat Bhushan .class_init = e500_ccsr_class_init, 8233eddc1beSBharat Bhushan }; 8243eddc1beSBharat Bhushan 8253eddc1beSBharat Bhushan static void e500_register_types(void) 8263eddc1beSBharat Bhushan { 8273eddc1beSBharat Bhushan type_register_static(&e500_ccsr_info); 8283eddc1beSBharat Bhushan } 8293eddc1beSBharat Bhushan 8303eddc1beSBharat Bhushan type_init(e500_register_types) 831