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" 429dd5eba1SScott Wood #define DTC_LOAD_PAD 0x1800000 4375bb6589SLiu Yu #define DTC_PAD_MASK 0xFFFFF 44b8dec144SAlexander Graf #define DTB_MAX_SIZE (8 * 1024 * 1024) 4575bb6589SLiu Yu #define INITRD_LOAD_PAD 0x2000000 4675bb6589SLiu Yu #define INITRD_PAD_MASK 0xFFFFFF 471db09b84Saurel32 481db09b84Saurel32 #define RAM_SIZES_ALIGN (64UL << 20) 491db09b84Saurel32 50b3305981SScott Wood /* TODO: parameterize */ 51ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE 0xE0000000ULL 52ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE 0x00100000ULL 53dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET 0x40000ULL 54a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET 0x41600ULL 55dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL 56dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL 57dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET 0x8000ULL 58dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + \ 59dffb1dc2SBharat Bhushan MPC8544_PCI_REGS_OFFSET) 60ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE 0x1000ULL 61ed2bc496SAlexander Graf #define MPC8544_PCI_IO 0xE1000000ULL 62dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET 0xe0000ULL 63ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE 0xEF000000ULL 641db09b84Saurel32 653b989d49SAlexander Graf struct boot_info 663b989d49SAlexander Graf { 673b989d49SAlexander Graf uint32_t dt_base; 68cba2026aSAlexander Graf uint32_t dt_size; 693b989d49SAlexander Graf uint32_t entry; 703b989d49SAlexander Graf }; 713b989d49SAlexander Graf 72347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot, 73347dd79dSAlexander Graf int nr_slots, int *len) 740dbc0798SAlexander Graf { 75347dd79dSAlexander Graf int i = 0; 76347dd79dSAlexander Graf int slot; 77347dd79dSAlexander Graf int pci_irq; 789e2c1298SAlexander Graf int host_irq; 79347dd79dSAlexander Graf int last_slot = first_slot + nr_slots; 80347dd79dSAlexander Graf uint32_t *pci_map; 810dbc0798SAlexander Graf 82347dd79dSAlexander Graf *len = nr_slots * 4 * 7 * sizeof(uint32_t); 83347dd79dSAlexander Graf pci_map = g_malloc(*len); 84347dd79dSAlexander Graf 85347dd79dSAlexander Graf for (slot = first_slot; slot < last_slot; slot++) { 86347dd79dSAlexander Graf for (pci_irq = 0; pci_irq < 4; pci_irq++) { 87347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(slot << 11); 88347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x0); 89347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x0); 90347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(pci_irq + 1); 91347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(mpic); 929e2c1298SAlexander Graf host_irq = ppce500_pci_map_irq_slot(slot, pci_irq); 939e2c1298SAlexander Graf pci_map[i++] = cpu_to_be32(host_irq + 1); 94347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x1); 950dbc0798SAlexander Graf } 960dbc0798SAlexander Graf } 970dbc0798SAlexander Graf 98347dd79dSAlexander Graf assert((i * sizeof(uint32_t)) == *len); 99347dd79dSAlexander Graf 100347dd79dSAlexander Graf return pci_map; 101347dd79dSAlexander Graf } 102347dd79dSAlexander Graf 103a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset, 104a053a7ceSAlexander Graf const char *soc, const char *mpic, 105a053a7ceSAlexander Graf const char *alias, int idx, bool defcon) 106a053a7ceSAlexander Graf { 107a053a7ceSAlexander Graf char ser[128]; 108a053a7ceSAlexander Graf 109a053a7ceSAlexander Graf snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset); 1105a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, ser); 1115a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, ser, "device_type", "serial"); 1125a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, ser, "compatible", "ns16550"); 1135a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, ser, "reg", offset, 0x100); 1145a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, ser, "cell-index", idx); 1155a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", 0); 1165a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, ser, "interrupts", 42, 2); 1175a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, ser, "interrupt-parent", mpic); 1185a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/aliases", alias, ser); 119a053a7ceSAlexander Graf 120a053a7ceSAlexander Graf if (defcon) { 1215a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/chosen", "linux,stdout-path", ser); 122a053a7ceSAlexander Graf } 123a053a7ceSAlexander Graf } 124a053a7ceSAlexander Graf 1253ef96221SMarcel Apfelbaum static int ppce500_load_device_tree(MachineState *machine, 126e6eaabebSScott Wood PPCE500Params *params, 127a8170e5eSAvi Kivity hwaddr addr, 128a8170e5eSAvi Kivity hwaddr initrd_base, 12928290f37SAlexander Graf hwaddr initrd_size, 130903585deSAlexander Graf hwaddr kernel_base, 131903585deSAlexander Graf hwaddr kernel_size, 13228290f37SAlexander Graf bool dry_run) 1331db09b84Saurel32 { 13428290f37SAlexander Graf CPUPPCState *env = first_cpu->env_ptr; 135dbf916d8SAurelien Jarno int ret = -1; 1363ef96221SMarcel Apfelbaum uint64_t mem_reg_property[] = { 0, cpu_to_be64(machine->ram_size) }; 1377ec632b4Spbrook int fdt_size; 138dbf916d8SAurelien Jarno void *fdt; 1395de6b46dSAlexander Graf uint8_t hypercall[16]; 140911d6e7aSAlexander Graf uint32_t clock_freq = 400000000; 141911d6e7aSAlexander Graf uint32_t tb_freq = 400000000; 142621d05e3SAlexander Graf int i; 143ebb9518aSAlexander Graf char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; 1445da96624SAlexander Graf char soc[128]; 14519ac9deaSAlexander Graf char mpic[128]; 14619ac9deaSAlexander Graf uint32_t mpic_ph; 147a911b7a9SAlexander Graf uint32_t msi_ph; 148f5038483SAlexander Graf char gutil[128]; 1490dbc0798SAlexander Graf char pci[128]; 150a911b7a9SAlexander Graf char msi[128]; 151347dd79dSAlexander Graf uint32_t *pci_map = NULL; 152347dd79dSAlexander Graf int len; 1533627757eSAlexander Graf uint32_t pci_ranges[14] = 1543627757eSAlexander Graf { 1553627757eSAlexander Graf 0x2000000, 0x0, 0xc0000000, 1563627757eSAlexander Graf 0x0, 0xc0000000, 1573627757eSAlexander Graf 0x0, 0x20000000, 1583627757eSAlexander Graf 1593627757eSAlexander Graf 0x1000000, 0x0, 0x0, 1603627757eSAlexander Graf 0x0, 0xe1000000, 1613627757eSAlexander Graf 0x0, 0x10000, 1623627757eSAlexander Graf }; 1632ff3de68SMarkus Armbruster QemuOpts *machine_opts = qemu_get_machine_opts(); 1642ff3de68SMarkus Armbruster const char *dtb_file = qemu_opt_get(machine_opts, "dtb"); 1652ff3de68SMarkus Armbruster const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); 166d1b93565SAlexander Graf 167d1b93565SAlexander Graf if (dtb_file) { 168d1b93565SAlexander Graf char *filename; 169d1b93565SAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file); 170d1b93565SAlexander Graf if (!filename) { 171d1b93565SAlexander Graf goto out; 172d1b93565SAlexander Graf } 173d1b93565SAlexander Graf 174d1b93565SAlexander Graf fdt = load_device_tree(filename, &fdt_size); 175d1b93565SAlexander Graf if (!fdt) { 176d1b93565SAlexander Graf goto out; 177d1b93565SAlexander Graf } 178d1b93565SAlexander Graf goto done; 179d1b93565SAlexander Graf } 1801db09b84Saurel32 1812636fcb6SAlexander Graf fdt = create_device_tree(&fdt_size); 1825cea8590SPaul Brook if (fdt == NULL) { 1835cea8590SPaul Brook goto out; 1845cea8590SPaul Brook } 1851db09b84Saurel32 1861db09b84Saurel32 /* Manipulate device tree in memory. */ 1875a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 2); 1885a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 2); 18951b852b7SAlexander Graf 1905a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/memory"); 1915a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory"); 1925a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, 1931db09b84Saurel32 sizeof(mem_reg_property)); 1941db09b84Saurel32 1955a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/chosen"); 1963b989d49SAlexander Graf if (initrd_size) { 1975a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", 1981db09b84Saurel32 initrd_base); 1993b989d49SAlexander Graf if (ret < 0) { 2001db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); 2013b989d49SAlexander Graf } 2021db09b84Saurel32 2035a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", 2041db09b84Saurel32 (initrd_base + initrd_size)); 2053b989d49SAlexander Graf if (ret < 0) { 2061db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); 2073b989d49SAlexander Graf } 208903585deSAlexander Graf 209903585deSAlexander Graf } 210903585deSAlexander Graf 211903585deSAlexander Graf if (kernel_base != -1ULL) { 212903585deSAlexander Graf qemu_fdt_setprop_cells(fdt, "/chosen", "qemu,boot-kernel", 213903585deSAlexander Graf kernel_base >> 32, kernel_base, 214903585deSAlexander Graf kernel_size >> 32, kernel_size); 2153b989d49SAlexander Graf } 2161db09b84Saurel32 2175a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", 2183ef96221SMarcel Apfelbaum machine->kernel_cmdline); 2191db09b84Saurel32 if (ret < 0) 2201db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/bootargs\n"); 2211db09b84Saurel32 2221db09b84Saurel32 if (kvm_enabled()) { 223911d6e7aSAlexander Graf /* Read out host's frequencies */ 224911d6e7aSAlexander Graf clock_freq = kvmppc_get_clockfreq(); 225911d6e7aSAlexander Graf tb_freq = kvmppc_get_tbfreq(); 2265de6b46dSAlexander Graf 2275de6b46dSAlexander Graf /* indicate KVM hypercall interface */ 2285a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/hypervisor"); 2295a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/hypervisor", "compatible", 2305de6b46dSAlexander Graf "linux,kvm"); 2315de6b46dSAlexander Graf kvmppc_get_hypercall(env, hypercall, sizeof(hypercall)); 2325a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/hypervisor", "hcall-instructions", 2335de6b46dSAlexander Graf hypercall, sizeof(hypercall)); 2341a61a9aeSStuart Yoder /* if KVM supports the idle hcall, set property indicating this */ 2351a61a9aeSStuart Yoder if (kvmppc_get_hasidle(env)) { 2365a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/hypervisor", "has-idle", NULL, 0); 2371a61a9aeSStuart Yoder } 2381db09b84Saurel32 } 2391db09b84Saurel32 240625e665bSAlexander Graf /* Create CPU nodes */ 2415a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/cpus"); 2425a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1); 2435a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0); 244625e665bSAlexander Graf 2451e3debf0SAlexander Graf /* We need to generate the cpu nodes in reverse order, so Linux can pick 2461e3debf0SAlexander Graf the first node as boot node and be happy */ 2471e3debf0SAlexander Graf for (i = smp_cpus - 1; i >= 0; i--) { 248440c8152SAndreas Färber CPUState *cpu; 2490f20ba62SAlexey Kardashevskiy PowerPCCPU *pcpu; 250621d05e3SAlexander Graf char cpu_name[128]; 2511d2e5c52SAlexander Graf uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); 25210f25a46SAlexander Graf 253440c8152SAndreas Färber cpu = qemu_get_cpu(i); 25455e5c285SAndreas Färber if (cpu == NULL) { 2551e3debf0SAlexander Graf continue; 2561e3debf0SAlexander Graf } 257440c8152SAndreas Färber env = cpu->env_ptr; 2580f20ba62SAlexey Kardashevskiy pcpu = POWERPC_CPU(cpu); 2591e3debf0SAlexander Graf 26055e5c285SAndreas Färber snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", 2610f20ba62SAlexey Kardashevskiy ppc_get_vcpu_dt_id(pcpu)); 2625a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, cpu_name); 2635a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq); 2645a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq); 2655a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu"); 2660f20ba62SAlexey Kardashevskiy qemu_fdt_setprop_cell(fdt, cpu_name, "reg", 2670f20ba62SAlexey Kardashevskiy ppc_get_vcpu_dt_id(pcpu)); 2685a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size", 2691e3debf0SAlexander Graf env->dcache_line_size); 2705a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size", 2711e3debf0SAlexander Graf env->icache_line_size); 2725a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000); 2735a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000); 2745a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "bus-frequency", 0); 27555e5c285SAndreas Färber if (cpu->cpu_index) { 2765a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "status", "disabled"); 2775a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "enable-method", 2785a4348d1SPeter Crosthwaite "spin-table"); 2795a4348d1SPeter Crosthwaite qemu_fdt_setprop_u64(fdt, cpu_name, "cpu-release-addr", 2801d2e5c52SAlexander Graf cpu_release_addr); 2811e3debf0SAlexander Graf } else { 2825a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay"); 2831e3debf0SAlexander Graf } 2841db09b84Saurel32 } 2851db09b84Saurel32 2865a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/aliases"); 2875da96624SAlexander Graf /* XXX These should go into their respective devices' code */ 288ed2bc496SAlexander Graf snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE); 2895a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, soc); 2905a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, soc, "device_type", "soc"); 2915a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb, 292ebb9518aSAlexander Graf sizeof(compatible_sb)); 2935a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1); 2945a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1); 2955a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0, 2963627757eSAlexander Graf MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE, 2975da96624SAlexander Graf MPC8544_CCSRBAR_SIZE); 2985da96624SAlexander Graf /* XXX should contain a reasonable value */ 2995a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0); 3005da96624SAlexander Graf 301dffb1dc2SBharat Bhushan snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET); 3025a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, mpic); 3035a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, mpic, "device_type", "open-pic"); 3045a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); 3055a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET, 306dffb1dc2SBharat Bhushan 0x40000); 3075a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "#address-cells", 0); 3085a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "#interrupt-cells", 2); 3095a4348d1SPeter Crosthwaite mpic_ph = qemu_fdt_alloc_phandle(fdt); 3105a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "phandle", mpic_ph); 3115a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); 3125a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, mpic, "interrupt-controller", NULL, 0); 31319ac9deaSAlexander Graf 3140cfc6e8dSAlexander Graf /* 3150cfc6e8dSAlexander Graf * We have to generate ser1 first, because Linux takes the first 3160cfc6e8dSAlexander Graf * device it finds in the dt as serial output device. And we generate 3170cfc6e8dSAlexander Graf * devices in reverse order to the dt. 3180cfc6e8dSAlexander Graf */ 31979c0ff2cSAlexander Graf if (serial_hds[1]) { 320dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET, 321a053a7ceSAlexander Graf soc, mpic, "serial1", 1, false); 32279c0ff2cSAlexander Graf } 32379c0ff2cSAlexander Graf 32479c0ff2cSAlexander Graf if (serial_hds[0]) { 325dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET, 326a053a7ceSAlexander Graf soc, mpic, "serial0", 0, true); 32779c0ff2cSAlexander Graf } 3280cfc6e8dSAlexander Graf 329ed2bc496SAlexander Graf snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, 330dffb1dc2SBharat Bhushan MPC8544_UTIL_OFFSET); 3315a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, gutil); 3325a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); 3335a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000); 3345a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); 335f5038483SAlexander Graf 336a911b7a9SAlexander Graf snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET); 3375a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, msi); 3385a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi"); 3395a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200); 3405a4348d1SPeter Crosthwaite msi_ph = qemu_fdt_alloc_phandle(fdt); 3415a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100); 3425a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, msi, "interrupt-parent", mpic); 3435a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "interrupts", 344a911b7a9SAlexander Graf 0xe0, 0x0, 345a911b7a9SAlexander Graf 0xe1, 0x0, 346a911b7a9SAlexander Graf 0xe2, 0x0, 347a911b7a9SAlexander Graf 0xe3, 0x0, 348a911b7a9SAlexander Graf 0xe4, 0x0, 349a911b7a9SAlexander Graf 0xe5, 0x0, 350a911b7a9SAlexander Graf 0xe6, 0x0, 351a911b7a9SAlexander Graf 0xe7, 0x0); 3525a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, msi, "phandle", msi_ph); 3535a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph); 354a911b7a9SAlexander Graf 355ed2bc496SAlexander Graf snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); 3565a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, pci); 3575a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "cell-index", 0); 3585a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); 3595a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, pci, "device_type", "pci"); 3605a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 3610dbc0798SAlexander Graf 0x0, 0x7); 3625a4348d1SPeter Crosthwaite pci_map = pci_map_create(fdt, qemu_fdt_get_phandle(fdt, mpic), 363492ec48dSAlexander Graf params->pci_first_slot, params->pci_nr_slots, 364492ec48dSAlexander Graf &len); 3655a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, pci, "interrupt-map", pci_map, len); 3665a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, pci, "interrupt-parent", mpic); 3675a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "interrupts", 24, 2); 3685a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "bus-range", 0, 255); 3693627757eSAlexander Graf for (i = 0; i < 14; i++) { 3700dbc0798SAlexander Graf pci_ranges[i] = cpu_to_be32(pci_ranges[i]); 3710dbc0798SAlexander Graf } 3725a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph); 3735a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); 3745a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32, 3753627757eSAlexander Graf MPC8544_PCI_REGS_BASE, 0, 0x1000); 3765a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666); 3775a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1); 3785a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#size-cells", 2); 3795a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3); 3805a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci); 3810dbc0798SAlexander Graf 382e6eaabebSScott Wood params->fixup_devtree(params, fdt); 383e6eaabebSScott Wood 384e6eaabebSScott Wood if (toplevel_compat) { 3855a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/", "compatible", toplevel_compat, 386e6eaabebSScott Wood strlen(toplevel_compat) + 1); 387e6eaabebSScott Wood } 388e6eaabebSScott Wood 389d1b93565SAlexander Graf done: 39028290f37SAlexander Graf if (!dry_run) { 3915a4348d1SPeter Crosthwaite qemu_fdt_dumpdtb(fdt, fdt_size); 39228290f37SAlexander Graf cpu_physical_memory_write(addr, fdt, fdt_size); 393cba2026aSAlexander Graf } 394cba2026aSAlexander Graf ret = fdt_size; 3957ec632b4Spbrook 3961db09b84Saurel32 out: 397347dd79dSAlexander Graf g_free(pci_map); 3981db09b84Saurel32 39904088adbSLiu Yu return ret; 4001db09b84Saurel32 } 4011db09b84Saurel32 40228290f37SAlexander Graf typedef struct DeviceTreeParams { 4033ef96221SMarcel Apfelbaum MachineState *machine; 40428290f37SAlexander Graf PPCE500Params params; 40528290f37SAlexander Graf hwaddr addr; 40628290f37SAlexander Graf hwaddr initrd_base; 40728290f37SAlexander Graf hwaddr initrd_size; 408903585deSAlexander Graf hwaddr kernel_base; 409903585deSAlexander Graf hwaddr kernel_size; 41028290f37SAlexander Graf } DeviceTreeParams; 41128290f37SAlexander Graf 41228290f37SAlexander Graf static void ppce500_reset_device_tree(void *opaque) 41328290f37SAlexander Graf { 41428290f37SAlexander Graf DeviceTreeParams *p = opaque; 4153812c71fSAlexander Graf ppce500_load_device_tree(p->machine, &p->params, p->addr, p->initrd_base, 416903585deSAlexander Graf p->initrd_size, p->kernel_base, p->kernel_size, 417903585deSAlexander Graf false); 41828290f37SAlexander Graf } 41928290f37SAlexander Graf 4203ef96221SMarcel Apfelbaum static int ppce500_prep_device_tree(MachineState *machine, 42128290f37SAlexander Graf PPCE500Params *params, 42228290f37SAlexander Graf hwaddr addr, 42328290f37SAlexander Graf hwaddr initrd_base, 424903585deSAlexander Graf hwaddr initrd_size, 425903585deSAlexander Graf hwaddr kernel_base, 426903585deSAlexander Graf hwaddr kernel_size) 42728290f37SAlexander Graf { 42828290f37SAlexander Graf DeviceTreeParams *p = g_new(DeviceTreeParams, 1); 4293ef96221SMarcel Apfelbaum p->machine = machine; 43028290f37SAlexander Graf p->params = *params; 43128290f37SAlexander Graf p->addr = addr; 43228290f37SAlexander Graf p->initrd_base = initrd_base; 43328290f37SAlexander Graf p->initrd_size = initrd_size; 434903585deSAlexander Graf p->kernel_base = kernel_base; 435903585deSAlexander Graf p->kernel_size = kernel_size; 43628290f37SAlexander Graf 43728290f37SAlexander Graf qemu_register_reset(ppce500_reset_device_tree, p); 43828290f37SAlexander Graf 43928290f37SAlexander Graf /* Issue the device tree loader once, so that we get the size of the blob */ 4403ef96221SMarcel Apfelbaum return ppce500_load_device_tree(machine, params, addr, initrd_base, 441903585deSAlexander Graf initrd_size, kernel_base, kernel_size, 442903585deSAlexander Graf true); 44328290f37SAlexander Graf } 44428290f37SAlexander Graf 445cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE. */ 446a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size) 447d1e256feSAlexander Graf { 448cba2026aSAlexander Graf return 63 - clz64(size >> 10); 449d1e256feSAlexander Graf } 450d1e256feSAlexander Graf 451cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env) 4523b989d49SAlexander Graf { 453cba2026aSAlexander Graf struct boot_info *bi = env->load_info; 454cefd3cdbSBharat Bhushan hwaddr dt_end; 455cba2026aSAlexander Graf int ps; 4563b989d49SAlexander Graf 457cba2026aSAlexander Graf /* Our initial TLB entry needs to cover everything from 0 to 458cba2026aSAlexander Graf the device tree top */ 459cba2026aSAlexander Graf dt_end = bi->dt_base + bi->dt_size; 460cba2026aSAlexander Graf ps = booke206_page_size_to_tlb(dt_end) + 1; 461fb37c302SAlexander Graf if (ps & 1) { 462fb37c302SAlexander Graf /* e500v2 can only do even TLB size bits */ 463fb37c302SAlexander Graf ps++; 464fb37c302SAlexander Graf } 465cefd3cdbSBharat Bhushan return ps; 466cefd3cdbSBharat Bhushan } 467cefd3cdbSBharat Bhushan 468cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env) 469cefd3cdbSBharat Bhushan { 470cefd3cdbSBharat Bhushan int tsize; 471cefd3cdbSBharat Bhushan 472cefd3cdbSBharat Bhushan tsize = booke206_initial_map_tsize(env); 473cefd3cdbSBharat Bhushan return (1ULL << 10 << tsize); 474cefd3cdbSBharat Bhushan } 475cefd3cdbSBharat Bhushan 476cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env) 477cefd3cdbSBharat Bhushan { 478cefd3cdbSBharat Bhushan ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); 479cefd3cdbSBharat Bhushan hwaddr size; 480cefd3cdbSBharat Bhushan int ps; 481cefd3cdbSBharat Bhushan 482cefd3cdbSBharat Bhushan ps = booke206_initial_map_tsize(env); 483cba2026aSAlexander Graf size = (ps << MAS1_TSIZE_SHIFT); 484d1e256feSAlexander Graf tlb->mas1 = MAS1_VALID | size; 485cba2026aSAlexander Graf tlb->mas2 = 0; 486cba2026aSAlexander Graf tlb->mas7_3 = 0; 487d1e256feSAlexander Graf tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; 48893dd5e85SScott Wood 48993dd5e85SScott Wood env->tlb_dirty = true; 4903b989d49SAlexander Graf } 4913b989d49SAlexander Graf 492b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque) 4935c145dacSAlexander Graf { 49438f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 495259186a7SAndreas Färber CPUState *cs = CPU(cpu); 4965c145dacSAlexander Graf 497259186a7SAndreas Färber cpu_reset(cs); 4985c145dacSAlexander Graf 4995c145dacSAlexander Graf /* Secondary CPU starts in halted state for now. Needs to change when 5005c145dacSAlexander Graf implementing non-kernel boot. */ 501259186a7SAndreas Färber cs->halted = 1; 50227103424SAndreas Färber cs->exception_index = EXCP_HLT; 5033b989d49SAlexander Graf } 5043b989d49SAlexander Graf 505b3305981SScott Wood static void ppce500_cpu_reset(void *opaque) 5063b989d49SAlexander Graf { 50738f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 508259186a7SAndreas Färber CPUState *cs = CPU(cpu); 50938f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 5103b989d49SAlexander Graf struct boot_info *bi = env->load_info; 5113b989d49SAlexander Graf 512259186a7SAndreas Färber cpu_reset(cs); 5133b989d49SAlexander Graf 5143b989d49SAlexander Graf /* Set initial guest state. */ 515259186a7SAndreas Färber cs->halted = 0; 5163b989d49SAlexander Graf env->gpr[1] = (16<<20) - 8; 5173b989d49SAlexander Graf env->gpr[3] = bi->dt_base; 518cefd3cdbSBharat Bhushan env->gpr[4] = 0; 519cefd3cdbSBharat Bhushan env->gpr[5] = 0; 520cefd3cdbSBharat Bhushan env->gpr[6] = EPAPR_MAGIC; 521cefd3cdbSBharat Bhushan env->gpr[7] = mmubooke_initial_mapsize(env); 522cefd3cdbSBharat Bhushan env->gpr[8] = 0; 523cefd3cdbSBharat Bhushan env->gpr[9] = 0; 5243b989d49SAlexander Graf env->nip = bi->entry; 525cba2026aSAlexander Graf mmubooke_create_initial_mapping(env); 5263b989d49SAlexander Graf } 5273b989d49SAlexander Graf 528d85937e6SScott Wood static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params, 52982fc73b6SScott Wood qemu_irq **irqs) 53082fc73b6SScott Wood { 53182fc73b6SScott Wood DeviceState *dev; 53282fc73b6SScott Wood SysBusDevice *s; 53382fc73b6SScott Wood int i, j, k; 53482fc73b6SScott Wood 535e1766344SAndreas Färber dev = qdev_create(NULL, TYPE_OPENPIC); 53682fc73b6SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 537d85937e6SScott Wood qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); 538d85937e6SScott Wood 53982fc73b6SScott Wood qdev_init_nofail(dev); 54082fc73b6SScott Wood s = SYS_BUS_DEVICE(dev); 54182fc73b6SScott Wood 54282fc73b6SScott Wood k = 0; 54382fc73b6SScott Wood for (i = 0; i < smp_cpus; i++) { 54482fc73b6SScott Wood for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { 54582fc73b6SScott Wood sysbus_connect_irq(s, k++, irqs[i][j]); 54682fc73b6SScott Wood } 54782fc73b6SScott Wood } 54882fc73b6SScott Wood 549d85937e6SScott Wood return dev; 550d85937e6SScott Wood } 551d85937e6SScott Wood 552d85937e6SScott Wood static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, 553d85937e6SScott Wood qemu_irq **irqs) 554d85937e6SScott Wood { 555d85937e6SScott Wood DeviceState *dev; 556d85937e6SScott Wood CPUState *cs; 557d85937e6SScott Wood int r; 558d85937e6SScott Wood 559dd49c038SAndreas Färber dev = qdev_create(NULL, TYPE_KVM_OPENPIC); 560d85937e6SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 561d85937e6SScott Wood 562d85937e6SScott Wood r = qdev_init(dev); 563d85937e6SScott Wood if (r) { 564d85937e6SScott Wood return NULL; 565d85937e6SScott Wood } 566d85937e6SScott Wood 567bdc44640SAndreas Färber CPU_FOREACH(cs) { 568d85937e6SScott Wood if (kvm_openpic_connect_vcpu(dev, cs)) { 569d85937e6SScott Wood fprintf(stderr, "%s: failed to connect vcpu to irqchip\n", 570d85937e6SScott Wood __func__); 571d85937e6SScott Wood abort(); 572d85937e6SScott Wood } 573d85937e6SScott Wood } 574d85937e6SScott Wood 575d85937e6SScott Wood return dev; 576d85937e6SScott Wood } 577d85937e6SScott Wood 578d85937e6SScott Wood static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, 579d85937e6SScott Wood qemu_irq **irqs) 580d85937e6SScott Wood { 581d85937e6SScott Wood qemu_irq *mpic; 582d85937e6SScott Wood DeviceState *dev = NULL; 583d85937e6SScott Wood SysBusDevice *s; 584d85937e6SScott Wood int i; 585d85937e6SScott Wood 586*aa2ac1daSPeter Crosthwaite mpic = g_new0(qemu_irq, 256); 587d85937e6SScott Wood 588d85937e6SScott Wood if (kvm_enabled()) { 58936ad0e94SMarkus Armbruster QemuOpts *machine_opts = qemu_get_machine_opts(); 59036ad0e94SMarkus Armbruster bool irqchip_allowed = qemu_opt_get_bool(machine_opts, 591d85937e6SScott Wood "kernel_irqchip", true); 59236ad0e94SMarkus Armbruster bool irqchip_required = qemu_opt_get_bool(machine_opts, 593d85937e6SScott Wood "kernel_irqchip", false); 594d85937e6SScott Wood 595d85937e6SScott Wood if (irqchip_allowed) { 596d85937e6SScott Wood dev = ppce500_init_mpic_kvm(params, irqs); 597d85937e6SScott Wood } 598d85937e6SScott Wood 599d85937e6SScott Wood if (irqchip_required && !dev) { 600d85937e6SScott Wood fprintf(stderr, "%s: irqchip requested but unavailable\n", 601d85937e6SScott Wood __func__); 602d85937e6SScott Wood abort(); 603d85937e6SScott Wood } 604d85937e6SScott Wood } 605d85937e6SScott Wood 606d85937e6SScott Wood if (!dev) { 607d85937e6SScott Wood dev = ppce500_init_mpic_qemu(params, irqs); 608d85937e6SScott Wood } 609d85937e6SScott Wood 61082fc73b6SScott Wood for (i = 0; i < 256; i++) { 61182fc73b6SScott Wood mpic[i] = qdev_get_gpio_in(dev, i); 61282fc73b6SScott Wood } 61382fc73b6SScott Wood 614d85937e6SScott Wood s = SYS_BUS_DEVICE(dev); 61582fc73b6SScott Wood memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET, 61682fc73b6SScott Wood s->mmio[0].memory); 61782fc73b6SScott Wood 61882fc73b6SScott Wood return mpic; 61982fc73b6SScott Wood } 62082fc73b6SScott Wood 6213ef96221SMarcel Apfelbaum void ppce500_init(MachineState *machine, PPCE500Params *params) 6221db09b84Saurel32 { 62339186d8aSRichard Henderson MemoryRegion *address_space_mem = get_system_memory(); 6242646c133SAvi Kivity MemoryRegion *ram = g_new(MemoryRegion, 1); 6251db09b84Saurel32 PCIBus *pci_bus; 626e2684c0bSAndreas Färber CPUPPCState *env = NULL; 6273812c71fSAlexander Graf uint64_t loadaddr; 6283812c71fSAlexander Graf hwaddr kernel_base = -1LL; 6293812c71fSAlexander Graf int kernel_size = 0; 6303812c71fSAlexander Graf hwaddr dt_base = 0; 6313812c71fSAlexander Graf hwaddr initrd_base = 0; 6323812c71fSAlexander Graf int initrd_size = 0; 6333812c71fSAlexander Graf hwaddr cur_base = 0; 6343812c71fSAlexander Graf char *filename; 6353812c71fSAlexander Graf hwaddr bios_entry = 0; 6363812c71fSAlexander Graf target_long bios_size; 6373812c71fSAlexander Graf struct boot_info *boot_info; 6383812c71fSAlexander Graf int dt_size; 63982fc73b6SScott Wood int i; 640d575a6ceSBharat Bhushan /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and 641d575a6ceSBharat Bhushan * 4 respectively */ 642d575a6ceSBharat Bhushan unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4}; 643a915249fSAlexander Graf qemu_irq **irqs, *mpic; 644be13cc7aSAlexander Graf DeviceState *dev; 645e2684c0bSAndreas Färber CPUPPCState *firstenv = NULL; 6463eddc1beSBharat Bhushan MemoryRegion *ccsr_addr_space; 647dffb1dc2SBharat Bhushan SysBusDevice *s; 6483eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 6491db09b84Saurel32 650e61c36d5SAlexander Graf /* Setup CPUs */ 6513ef96221SMarcel Apfelbaum if (machine->cpu_model == NULL) { 6523ef96221SMarcel Apfelbaum machine->cpu_model = "e500v2_v30"; 653ef250db6SAlexander Graf } 654ef250db6SAlexander Graf 655a915249fSAlexander Graf irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); 656a915249fSAlexander Graf irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); 657e61c36d5SAlexander Graf for (i = 0; i < smp_cpus; i++) { 658397b457dSAndreas Färber PowerPCCPU *cpu; 65955e5c285SAndreas Färber CPUState *cs; 660e61c36d5SAlexander Graf qemu_irq *input; 661397b457dSAndreas Färber 6623ef96221SMarcel Apfelbaum cpu = cpu_ppc_init(machine->cpu_model); 663397b457dSAndreas Färber if (cpu == NULL) { 6641db09b84Saurel32 fprintf(stderr, "Unable to initialize CPU!\n"); 6651db09b84Saurel32 exit(1); 6661db09b84Saurel32 } 667397b457dSAndreas Färber env = &cpu->env; 66855e5c285SAndreas Färber cs = CPU(cpu); 6691db09b84Saurel32 670e61c36d5SAlexander Graf if (!firstenv) { 671e61c36d5SAlexander Graf firstenv = env; 672e61c36d5SAlexander Graf } 673e61c36d5SAlexander Graf 674a915249fSAlexander Graf irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB); 675a915249fSAlexander Graf input = (qemu_irq *)env->irq_inputs; 676a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; 677a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; 6786a450df9SAlexander Graf env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i; 67968c2dd70SAlexander Graf env->mpic_iack = MPC8544_CCSRBAR_BASE + 680bd25922eSScott Wood MPC8544_MPIC_REGS_OFFSET + 0xa0; 681e61c36d5SAlexander Graf 682a34a92b9SAndreas Färber ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); 6833b989d49SAlexander Graf 6843b989d49SAlexander Graf /* Register reset handler */ 6855c145dacSAlexander Graf if (!i) { 6865c145dacSAlexander Graf /* Primary CPU */ 6875c145dacSAlexander Graf struct boot_info *boot_info; 688e61c36d5SAlexander Graf boot_info = g_malloc0(sizeof(struct boot_info)); 689b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset, cpu); 690e61c36d5SAlexander Graf env->load_info = boot_info; 6915c145dacSAlexander Graf } else { 6925c145dacSAlexander Graf /* Secondary CPUs */ 693b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset_sec, cpu); 6945c145dacSAlexander Graf } 695e61c36d5SAlexander Graf } 696e61c36d5SAlexander Graf 697e61c36d5SAlexander Graf env = firstenv; 6983b989d49SAlexander Graf 6991db09b84Saurel32 /* Fixup Memory size on a alignment boundary */ 7001db09b84Saurel32 ram_size &= ~(RAM_SIZES_ALIGN - 1); 7013ef96221SMarcel Apfelbaum machine->ram_size = ram_size; 7021db09b84Saurel32 7031db09b84Saurel32 /* Register Memory */ 704e938ba0cSShreyas B. Prabhu memory_region_allocate_system_memory(ram, NULL, "mpc8544ds.ram", ram_size); 7052646c133SAvi Kivity memory_region_add_subregion(address_space_mem, 0, ram); 7061db09b84Saurel32 7073eddc1beSBharat Bhushan dev = qdev_create(NULL, "e500-ccsr"); 7083eddc1beSBharat Bhushan object_property_add_child(qdev_get_machine(), "e500-ccsr", 7093eddc1beSBharat Bhushan OBJECT(dev), NULL); 7103eddc1beSBharat Bhushan qdev_init_nofail(dev); 7113eddc1beSBharat Bhushan ccsr = CCSR(dev); 7123eddc1beSBharat Bhushan ccsr_addr_space = &ccsr->ccsr_space; 7133eddc1beSBharat Bhushan memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE, 7143eddc1beSBharat Bhushan ccsr_addr_space); 715dffb1dc2SBharat Bhushan 71682fc73b6SScott Wood mpic = ppce500_init_mpic(params, ccsr_addr_space, irqs); 7171db09b84Saurel32 7181db09b84Saurel32 /* Serial */ 7192d48377aSBlue Swirl if (serial_hds[0]) { 7203eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, 721cdbb912aSAlexander Graf 0, mpic[42], 399193, 7222ff0c7c3SRichard Henderson serial_hds[0], DEVICE_BIG_ENDIAN); 7232d48377aSBlue Swirl } 7241db09b84Saurel32 7252d48377aSBlue Swirl if (serial_hds[1]) { 7263eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, 727cdbb912aSAlexander Graf 0, mpic[42], 399193, 72859de4f98SBharat Bhushan serial_hds[1], DEVICE_BIG_ENDIAN); 7292d48377aSBlue Swirl } 7301db09b84Saurel32 731b0fb8423SAlexander Graf /* General Utility device */ 732dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "mpc8544-guts"); 733dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 734dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 7353eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET, 736dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 737b0fb8423SAlexander Graf 7381db09b84Saurel32 /* PCI */ 739dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "e500-pcihost"); 740492ec48dSAlexander Graf qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); 7413016dca0SBharat Bhushan qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]); 742dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 743dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 744d575a6ceSBharat Bhushan for (i = 0; i < PCI_NUM_PINS; i++) { 745d575a6ceSBharat Bhushan sysbus_connect_irq(s, i, mpic[pci_irq_nrs[i]]); 746d575a6ceSBharat Bhushan } 747d575a6ceSBharat Bhushan 7483eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, 749dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 750dffb1dc2SBharat Bhushan 751d461e3b9SAlexander Graf pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); 7521db09b84Saurel32 if (!pci_bus) 7531db09b84Saurel32 printf("couldn't create PCI controller!\n"); 7541db09b84Saurel32 7551356b98dSAndreas Färber sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO); 7561db09b84Saurel32 7571db09b84Saurel32 if (pci_bus) { 7581db09b84Saurel32 /* Register network interfaces. */ 7591db09b84Saurel32 for (i = 0; i < nb_nics; i++) { 76029b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL); 7611db09b84Saurel32 } 7621db09b84Saurel32 } 7631db09b84Saurel32 7645c145dacSAlexander Graf /* Register spinning region */ 7655c145dacSAlexander Graf sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); 7665c145dacSAlexander Graf 7673812c71fSAlexander Graf if (cur_base < (32 * 1024 * 1024)) { 7683812c71fSAlexander Graf /* u-boot occupies memory up to 32MB, so load blobs above */ 7693812c71fSAlexander Graf cur_base = (32 * 1024 * 1024); 7703812c71fSAlexander Graf } 7713812c71fSAlexander Graf 7721db09b84Saurel32 /* Load kernel. */ 7733ef96221SMarcel Apfelbaum if (machine->kernel_filename) { 7743812c71fSAlexander Graf kernel_base = cur_base; 7753812c71fSAlexander Graf kernel_size = load_image_targphys(machine->kernel_filename, 7763812c71fSAlexander Graf cur_base, 7773812c71fSAlexander Graf ram_size - cur_base); 7781db09b84Saurel32 if (kernel_size < 0) { 7791db09b84Saurel32 fprintf(stderr, "qemu: could not load kernel '%s'\n", 7803ef96221SMarcel Apfelbaum machine->kernel_filename); 7811db09b84Saurel32 exit(1); 7821db09b84Saurel32 } 783528e536eSAlexander Graf 7843812c71fSAlexander Graf cur_base += kernel_size; 7851db09b84Saurel32 } 7861db09b84Saurel32 7871db09b84Saurel32 /* Load initrd. */ 7883ef96221SMarcel Apfelbaum if (machine->initrd_filename) { 789528e536eSAlexander Graf initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; 7903ef96221SMarcel Apfelbaum initrd_size = load_image_targphys(machine->initrd_filename, initrd_base, 791d7585251Spbrook ram_size - initrd_base); 7921db09b84Saurel32 7931db09b84Saurel32 if (initrd_size < 0) { 7941db09b84Saurel32 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 7953ef96221SMarcel Apfelbaum machine->initrd_filename); 7961db09b84Saurel32 exit(1); 7971db09b84Saurel32 } 798528e536eSAlexander Graf 799528e536eSAlexander Graf cur_base = initrd_base + initrd_size; 8001db09b84Saurel32 } 8011db09b84Saurel32 8023812c71fSAlexander Graf /* 8033812c71fSAlexander Graf * Smart firmware defaults ahead! 8043812c71fSAlexander Graf * 8053812c71fSAlexander Graf * We follow the following table to select which payload we execute. 8063812c71fSAlexander Graf * 8073812c71fSAlexander Graf * -kernel | -bios | payload 8083812c71fSAlexander Graf * ---------+-------+--------- 8093812c71fSAlexander Graf * N | Y | u-boot 8103812c71fSAlexander Graf * N | N | u-boot 8113812c71fSAlexander Graf * Y | Y | u-boot 8123812c71fSAlexander Graf * Y | N | kernel 8133812c71fSAlexander Graf * 8143812c71fSAlexander Graf * This ensures backwards compatibility with how we used to expose 8153812c71fSAlexander Graf * -kernel to users but allows them to run through u-boot as well. 8163812c71fSAlexander Graf */ 8173812c71fSAlexander Graf if (bios_name == NULL) { 8183ef96221SMarcel Apfelbaum if (machine->kernel_filename) { 8193812c71fSAlexander Graf bios_name = machine->kernel_filename; 8203812c71fSAlexander Graf } else { 8213812c71fSAlexander Graf bios_name = "u-boot.e500"; 8223812c71fSAlexander Graf } 8233812c71fSAlexander Graf } 8243812c71fSAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 8253812c71fSAlexander Graf 8263812c71fSAlexander Graf bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL, 8273812c71fSAlexander Graf 1, ELF_MACHINE, 0); 8283812c71fSAlexander Graf if (bios_size < 0) { 8293812c71fSAlexander Graf /* 8303812c71fSAlexander Graf * Hrm. No ELF image? Try a uImage, maybe someone is giving us an 8313812c71fSAlexander Graf * ePAPR compliant kernel 8323812c71fSAlexander Graf */ 8333812c71fSAlexander Graf kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL); 8343812c71fSAlexander Graf if (kernel_size < 0) { 8353812c71fSAlexander Graf fprintf(stderr, "qemu: could not load firmware '%s'\n", filename); 8363812c71fSAlexander Graf exit(1); 8373812c71fSAlexander Graf } 8383812c71fSAlexander Graf } 8393812c71fSAlexander Graf 8403812c71fSAlexander Graf /* Reserve space for dtb */ 8413812c71fSAlexander Graf dt_base = (loadaddr + bios_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; 8425c145dacSAlexander Graf 8433ef96221SMarcel Apfelbaum dt_size = ppce500_prep_device_tree(machine, params, dt_base, 844903585deSAlexander Graf initrd_base, initrd_size, 8453812c71fSAlexander Graf kernel_base, kernel_size); 846cba2026aSAlexander Graf if (dt_size < 0) { 8471db09b84Saurel32 fprintf(stderr, "couldn't load device tree\n"); 8481db09b84Saurel32 exit(1); 8491db09b84Saurel32 } 850b8dec144SAlexander Graf assert(dt_size < DTB_MAX_SIZE); 8511db09b84Saurel32 852e61c36d5SAlexander Graf boot_info = env->load_info; 8533812c71fSAlexander Graf boot_info->entry = bios_entry; 8543b989d49SAlexander Graf boot_info->dt_base = dt_base; 855cba2026aSAlexander Graf boot_info->dt_size = dt_size; 8561db09b84Saurel32 8573b989d49SAlexander Graf if (kvm_enabled()) { 8581db09b84Saurel32 kvmppc_init(); 8593b989d49SAlexander Graf } 8601db09b84Saurel32 } 8613eddc1beSBharat Bhushan 8623eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev) 8633eddc1beSBharat Bhushan { 8643eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 8653eddc1beSBharat Bhushan 8663eddc1beSBharat Bhushan ccsr = CCSR(dev); 86740c5dce9SPaolo Bonzini memory_region_init(&ccsr->ccsr_space, OBJECT(ccsr), "e500-ccsr", 8683eddc1beSBharat Bhushan MPC8544_CCSRBAR_SIZE); 8693eddc1beSBharat Bhushan return 0; 8703eddc1beSBharat Bhushan } 8713eddc1beSBharat Bhushan 8723eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data) 8733eddc1beSBharat Bhushan { 8743eddc1beSBharat Bhushan SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 8753eddc1beSBharat Bhushan k->init = e500_ccsr_initfn; 8763eddc1beSBharat Bhushan } 8773eddc1beSBharat Bhushan 8783eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = { 8793eddc1beSBharat Bhushan .name = TYPE_CCSR, 8803eddc1beSBharat Bhushan .parent = TYPE_SYS_BUS_DEVICE, 8813eddc1beSBharat Bhushan .instance_size = sizeof(PPCE500CCSRState), 8823eddc1beSBharat Bhushan .class_init = e500_ccsr_class_init, 8833eddc1beSBharat Bhushan }; 8843eddc1beSBharat Bhushan 8853eddc1beSBharat Bhushan static void e500_register_types(void) 8863eddc1beSBharat Bhushan { 8873eddc1beSBharat Bhushan type_register_static(&e500_ccsr_info); 8883eddc1beSBharat Bhushan } 8893eddc1beSBharat Bhushan 8903eddc1beSBharat Bhushan type_init(e500_register_types) 891