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 170d75590dSPeter Maydell #include "qemu/osdep.h" 18da34e65cSMarkus Armbruster #include "qapi/error.h" 191db09b84Saurel32 #include "qemu-common.h" 20e6eaabebSScott Wood #include "e500.h" 213eddc1beSBharat Bhushan #include "e500-ccsr.h" 221422e32dSPaolo Bonzini #include "net/net.h" 231de7afc9SPaolo Bonzini #include "qemu/config-file.h" 244a18e7c9SScott Wood #include "hw/hw.h" 250d09e41aSPaolo Bonzini #include "hw/char/serial.h" 26a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h" 274a18e7c9SScott Wood #include "hw/boards.h" 289c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 299c17d615SPaolo Bonzini #include "sysemu/kvm.h" 301db09b84Saurel32 #include "kvm_ppc.h" 319c17d615SPaolo Bonzini #include "sysemu/device_tree.h" 320d09e41aSPaolo Bonzini #include "hw/ppc/openpic.h" 330d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 344a18e7c9SScott Wood #include "hw/loader.h" 35ca20cf32SBlue Swirl #include "elf.h" 364a18e7c9SScott Wood #include "hw/sysbus.h" 37022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 381de7afc9SPaolo Bonzini #include "qemu/host-utils.h" 390d09e41aSPaolo Bonzini #include "hw/pci-host/ppce500.h" 40f7087343SAlexander Graf #include "qemu/error-report.h" 41f7087343SAlexander Graf #include "hw/platform-bus.h" 42fdfb7f2cSAlexander Graf #include "hw/net/fsl_etsec/etsec.h" 431db09b84Saurel32 44cefd3cdbSBharat Bhushan #define EPAPR_MAGIC (0x45504150) 451db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" 469dd5eba1SScott Wood #define DTC_LOAD_PAD 0x1800000 4775bb6589SLiu Yu #define DTC_PAD_MASK 0xFFFFF 48b8dec144SAlexander Graf #define DTB_MAX_SIZE (8 * 1024 * 1024) 4975bb6589SLiu Yu #define INITRD_LOAD_PAD 0x2000000 5075bb6589SLiu Yu #define INITRD_PAD_MASK 0xFFFFFF 511db09b84Saurel32 521db09b84Saurel32 #define RAM_SIZES_ALIGN (64UL << 20) 531db09b84Saurel32 54b3305981SScott Wood /* TODO: parameterize */ 55ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE 0x00100000ULL 56dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET 0x40000ULL 57a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET 0x41600ULL 58dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL 59dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL 60dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET 0x8000ULL 61ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE 0x1000ULL 62dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET 0xe0000ULL 63b88e77f4SAlexander Graf #define MPC8XXX_GPIO_OFFSET 0x000FF000ULL 6482e345f5SAmit Tomar #define MPC8XXX_GPIO_IRQ 47 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); 1115a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, ser); 1125a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, ser, "device_type", "serial"); 1135a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, ser, "compatible", "ns16550"); 1145a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, ser, "reg", offset, 0x100); 1155a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, ser, "cell-index", idx); 1165a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", 0); 1175a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, ser, "interrupts", 42, 2); 1185a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, ser, "interrupt-parent", mpic); 1195a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/aliases", alias, ser); 120a053a7ceSAlexander Graf 121a053a7ceSAlexander Graf if (defcon) { 1225a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/chosen", "linux,stdout-path", ser); 123a053a7ceSAlexander Graf } 124a053a7ceSAlexander Graf } 125a053a7ceSAlexander Graf 126b88e77f4SAlexander Graf static void create_dt_mpc8xxx_gpio(void *fdt, const char *soc, const char *mpic) 127b88e77f4SAlexander Graf { 128b88e77f4SAlexander Graf hwaddr mmio0 = MPC8XXX_GPIO_OFFSET; 129b88e77f4SAlexander Graf int irq0 = MPC8XXX_GPIO_IRQ; 130b88e77f4SAlexander Graf gchar *node = g_strdup_printf("%s/gpio@%"PRIx64, soc, mmio0); 131016f7758SAlexander Graf gchar *poweroff = g_strdup_printf("%s/power-off", soc); 132016f7758SAlexander Graf int gpio_ph; 133b88e77f4SAlexander Graf 134b88e77f4SAlexander Graf qemu_fdt_add_subnode(fdt, node); 135b88e77f4SAlexander Graf qemu_fdt_setprop_string(fdt, node, "compatible", "fsl,qoriq-gpio"); 136b88e77f4SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "reg", mmio0, 0x1000); 137b88e77f4SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "interrupts", irq0, 0x2); 138b88e77f4SAlexander Graf qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic); 139b88e77f4SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "#gpio-cells", 2); 140b88e77f4SAlexander Graf qemu_fdt_setprop(fdt, node, "gpio-controller", NULL, 0); 141016f7758SAlexander Graf gpio_ph = qemu_fdt_alloc_phandle(fdt); 142016f7758SAlexander Graf qemu_fdt_setprop_cell(fdt, node, "phandle", gpio_ph); 143016f7758SAlexander Graf qemu_fdt_setprop_cell(fdt, node, "linux,phandle", gpio_ph); 144016f7758SAlexander Graf 145016f7758SAlexander Graf /* Power Off Pin */ 146016f7758SAlexander Graf qemu_fdt_add_subnode(fdt, poweroff); 147016f7758SAlexander Graf qemu_fdt_setprop_string(fdt, poweroff, "compatible", "gpio-poweroff"); 148016f7758SAlexander Graf qemu_fdt_setprop_cells(fdt, poweroff, "gpios", gpio_ph, 0, 0); 149b88e77f4SAlexander Graf 150b88e77f4SAlexander Graf g_free(node); 151016f7758SAlexander Graf g_free(poweroff); 152b88e77f4SAlexander Graf } 153b88e77f4SAlexander Graf 154f7087343SAlexander Graf typedef struct PlatformDevtreeData { 155f7087343SAlexander Graf void *fdt; 156f7087343SAlexander Graf const char *mpic; 157f7087343SAlexander Graf int irq_start; 158f7087343SAlexander Graf const char *node; 159f7087343SAlexander Graf PlatformBusDevice *pbus; 160f7087343SAlexander Graf } PlatformDevtreeData; 161f7087343SAlexander Graf 162fdfb7f2cSAlexander Graf static int create_devtree_etsec(SysBusDevice *sbdev, PlatformDevtreeData *data) 163fdfb7f2cSAlexander Graf { 164fdfb7f2cSAlexander Graf eTSEC *etsec = ETSEC_COMMON(sbdev); 165fdfb7f2cSAlexander Graf PlatformBusDevice *pbus = data->pbus; 166fdfb7f2cSAlexander Graf hwaddr mmio0 = platform_bus_get_mmio_addr(pbus, sbdev, 0); 167fdfb7f2cSAlexander Graf int irq0 = platform_bus_get_irqn(pbus, sbdev, 0); 168fdfb7f2cSAlexander Graf int irq1 = platform_bus_get_irqn(pbus, sbdev, 1); 169fdfb7f2cSAlexander Graf int irq2 = platform_bus_get_irqn(pbus, sbdev, 2); 170fdfb7f2cSAlexander Graf gchar *node = g_strdup_printf("/platform/ethernet@%"PRIx64, mmio0); 171fdfb7f2cSAlexander Graf gchar *group = g_strdup_printf("%s/queue-group", node); 172fdfb7f2cSAlexander Graf void *fdt = data->fdt; 173fdfb7f2cSAlexander Graf 174fdfb7f2cSAlexander Graf assert((int64_t)mmio0 >= 0); 175fdfb7f2cSAlexander Graf assert(irq0 >= 0); 176fdfb7f2cSAlexander Graf assert(irq1 >= 0); 177fdfb7f2cSAlexander Graf assert(irq2 >= 0); 178fdfb7f2cSAlexander Graf 179fdfb7f2cSAlexander Graf qemu_fdt_add_subnode(fdt, node); 180fdfb7f2cSAlexander Graf qemu_fdt_setprop_string(fdt, node, "device_type", "network"); 181fdfb7f2cSAlexander Graf qemu_fdt_setprop_string(fdt, node, "compatible", "fsl,etsec2"); 182fdfb7f2cSAlexander Graf qemu_fdt_setprop_string(fdt, node, "model", "eTSEC"); 183fdfb7f2cSAlexander Graf qemu_fdt_setprop(fdt, node, "local-mac-address", etsec->conf.macaddr.a, 6); 184fdfb7f2cSAlexander Graf qemu_fdt_setprop_cells(fdt, node, "fixed-link", 0, 1, 1000, 0, 0); 185fdfb7f2cSAlexander Graf 186fdfb7f2cSAlexander Graf qemu_fdt_add_subnode(fdt, group); 187fdfb7f2cSAlexander Graf qemu_fdt_setprop_cells(fdt, group, "reg", mmio0, 0x1000); 188fdfb7f2cSAlexander Graf qemu_fdt_setprop_cells(fdt, group, "interrupts", 189fdfb7f2cSAlexander Graf data->irq_start + irq0, 0x2, 190fdfb7f2cSAlexander Graf data->irq_start + irq1, 0x2, 191fdfb7f2cSAlexander Graf data->irq_start + irq2, 0x2); 192fdfb7f2cSAlexander Graf 193fdfb7f2cSAlexander Graf g_free(node); 194fdfb7f2cSAlexander Graf g_free(group); 195fdfb7f2cSAlexander Graf 196fdfb7f2cSAlexander Graf return 0; 197fdfb7f2cSAlexander Graf } 198fdfb7f2cSAlexander Graf 1994f01a637SDavid Gibson static void sysbus_device_create_devtree(SysBusDevice *sbdev, void *opaque) 200f7087343SAlexander Graf { 201f7087343SAlexander Graf PlatformDevtreeData *data = opaque; 202f7087343SAlexander Graf bool matched = false; 203f7087343SAlexander Graf 204fdfb7f2cSAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_ETSEC_COMMON)) { 205fdfb7f2cSAlexander Graf create_devtree_etsec(sbdev, data); 206fdfb7f2cSAlexander Graf matched = true; 207fdfb7f2cSAlexander Graf } 208fdfb7f2cSAlexander Graf 209f7087343SAlexander Graf if (!matched) { 210f7087343SAlexander Graf error_report("Device %s is not supported by this machine yet.", 211f7087343SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 212f7087343SAlexander Graf exit(1); 213f7087343SAlexander Graf } 214f7087343SAlexander Graf } 215f7087343SAlexander Graf 216f7087343SAlexander Graf static void platform_bus_create_devtree(PPCE500Params *params, void *fdt, 217f7087343SAlexander Graf const char *mpic) 218f7087343SAlexander Graf { 219f7087343SAlexander Graf gchar *node = g_strdup_printf("/platform@%"PRIx64, params->platform_bus_base); 220f7087343SAlexander Graf const char platcomp[] = "qemu,platform\0simple-bus"; 221f7087343SAlexander Graf uint64_t addr = params->platform_bus_base; 222f7087343SAlexander Graf uint64_t size = params->platform_bus_size; 223f7087343SAlexander Graf int irq_start = params->platform_bus_first_irq; 224f7087343SAlexander Graf PlatformBusDevice *pbus; 225f7087343SAlexander Graf DeviceState *dev; 226f7087343SAlexander Graf 227f7087343SAlexander Graf /* Create a /platform node that we can put all devices into */ 228f7087343SAlexander Graf 229f7087343SAlexander Graf qemu_fdt_add_subnode(fdt, node); 230f7087343SAlexander Graf qemu_fdt_setprop(fdt, node, "compatible", platcomp, sizeof(platcomp)); 231f7087343SAlexander Graf 232f7087343SAlexander Graf /* Our platform bus region is less than 32bit big, so 1 cell is enough for 233f7087343SAlexander Graf address and size */ 234f7087343SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "#size-cells", 1); 235f7087343SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "#address-cells", 1); 236f7087343SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "ranges", 0, addr >> 32, addr, size); 237f7087343SAlexander Graf 238f7087343SAlexander Graf qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic); 239f7087343SAlexander Graf 240f7087343SAlexander Graf dev = qdev_find_recursive(sysbus_get_default(), TYPE_PLATFORM_BUS_DEVICE); 241f7087343SAlexander Graf pbus = PLATFORM_BUS_DEVICE(dev); 242f7087343SAlexander Graf 243f7087343SAlexander Graf /* We can only create dt nodes for dynamic devices when they're ready */ 244f7087343SAlexander Graf if (pbus->done_gathering) { 245f7087343SAlexander Graf PlatformDevtreeData data = { 246f7087343SAlexander Graf .fdt = fdt, 247f7087343SAlexander Graf .mpic = mpic, 248f7087343SAlexander Graf .irq_start = irq_start, 249f7087343SAlexander Graf .node = node, 250f7087343SAlexander Graf .pbus = pbus, 251f7087343SAlexander Graf }; 252f7087343SAlexander Graf 253f7087343SAlexander Graf /* Loop through all dynamic sysbus devices and create nodes for them */ 254f7087343SAlexander Graf foreach_dynamic_sysbus_device(sysbus_device_create_devtree, &data); 255f7087343SAlexander Graf } 256f7087343SAlexander Graf 257f7087343SAlexander Graf g_free(node); 258f7087343SAlexander Graf } 259f7087343SAlexander Graf 2603ef96221SMarcel Apfelbaum static int ppce500_load_device_tree(MachineState *machine, 261e6eaabebSScott Wood PPCE500Params *params, 262a8170e5eSAvi Kivity hwaddr addr, 263a8170e5eSAvi Kivity hwaddr initrd_base, 26428290f37SAlexander Graf hwaddr initrd_size, 265903585deSAlexander Graf hwaddr kernel_base, 266903585deSAlexander Graf hwaddr kernel_size, 26728290f37SAlexander Graf bool dry_run) 2681db09b84Saurel32 { 26928290f37SAlexander Graf CPUPPCState *env = first_cpu->env_ptr; 270dbf916d8SAurelien Jarno int ret = -1; 2713ef96221SMarcel Apfelbaum uint64_t mem_reg_property[] = { 0, cpu_to_be64(machine->ram_size) }; 2727ec632b4Spbrook int fdt_size; 273dbf916d8SAurelien Jarno void *fdt; 2745de6b46dSAlexander Graf uint8_t hypercall[16]; 275911d6e7aSAlexander Graf uint32_t clock_freq = 400000000; 276911d6e7aSAlexander Graf uint32_t tb_freq = 400000000; 277621d05e3SAlexander Graf int i; 278ebb9518aSAlexander Graf char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; 2795da96624SAlexander Graf char soc[128]; 28019ac9deaSAlexander Graf char mpic[128]; 28119ac9deaSAlexander Graf uint32_t mpic_ph; 282a911b7a9SAlexander Graf uint32_t msi_ph; 283f5038483SAlexander Graf char gutil[128]; 2840dbc0798SAlexander Graf char pci[128]; 285a911b7a9SAlexander Graf char msi[128]; 286347dd79dSAlexander Graf uint32_t *pci_map = NULL; 287347dd79dSAlexander Graf int len; 2883627757eSAlexander Graf uint32_t pci_ranges[14] = 2893627757eSAlexander Graf { 290cb3778a0SAlexander Graf 0x2000000, 0x0, params->pci_mmio_bus_base, 291cb3778a0SAlexander Graf params->pci_mmio_base >> 32, params->pci_mmio_base, 2923627757eSAlexander Graf 0x0, 0x20000000, 2933627757eSAlexander Graf 2943627757eSAlexander Graf 0x1000000, 0x0, 0x0, 2952eaaac1fSAlexander Graf params->pci_pio_base >> 32, params->pci_pio_base, 2963627757eSAlexander Graf 0x0, 0x10000, 2973627757eSAlexander Graf }; 2982ff3de68SMarkus Armbruster QemuOpts *machine_opts = qemu_get_machine_opts(); 2992ff3de68SMarkus Armbruster const char *dtb_file = qemu_opt_get(machine_opts, "dtb"); 3002ff3de68SMarkus Armbruster const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); 301d1b93565SAlexander Graf 302d1b93565SAlexander Graf if (dtb_file) { 303d1b93565SAlexander Graf char *filename; 304d1b93565SAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file); 305d1b93565SAlexander Graf if (!filename) { 306d1b93565SAlexander Graf goto out; 307d1b93565SAlexander Graf } 308d1b93565SAlexander Graf 309d1b93565SAlexander Graf fdt = load_device_tree(filename, &fdt_size); 3102343dd11SMichael Tokarev g_free(filename); 311d1b93565SAlexander Graf if (!fdt) { 312d1b93565SAlexander Graf goto out; 313d1b93565SAlexander Graf } 314d1b93565SAlexander Graf goto done; 315d1b93565SAlexander Graf } 3161db09b84Saurel32 3172636fcb6SAlexander Graf fdt = create_device_tree(&fdt_size); 3185cea8590SPaul Brook if (fdt == NULL) { 3195cea8590SPaul Brook goto out; 3205cea8590SPaul Brook } 3211db09b84Saurel32 3221db09b84Saurel32 /* Manipulate device tree in memory. */ 3235a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 2); 3245a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 2); 32551b852b7SAlexander Graf 3265a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/memory"); 3275a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory"); 3285a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, 3291db09b84Saurel32 sizeof(mem_reg_property)); 3301db09b84Saurel32 3315a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/chosen"); 3323b989d49SAlexander Graf if (initrd_size) { 3335a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", 3341db09b84Saurel32 initrd_base); 3353b989d49SAlexander Graf if (ret < 0) { 3361db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); 3373b989d49SAlexander Graf } 3381db09b84Saurel32 3395a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", 3401db09b84Saurel32 (initrd_base + initrd_size)); 3413b989d49SAlexander Graf if (ret < 0) { 3421db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); 3433b989d49SAlexander Graf } 344903585deSAlexander Graf 345903585deSAlexander Graf } 346903585deSAlexander Graf 347903585deSAlexander Graf if (kernel_base != -1ULL) { 348903585deSAlexander Graf qemu_fdt_setprop_cells(fdt, "/chosen", "qemu,boot-kernel", 349903585deSAlexander Graf kernel_base >> 32, kernel_base, 350903585deSAlexander Graf kernel_size >> 32, kernel_size); 3513b989d49SAlexander Graf } 3521db09b84Saurel32 3535a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", 3543ef96221SMarcel Apfelbaum machine->kernel_cmdline); 3551db09b84Saurel32 if (ret < 0) 3561db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/bootargs\n"); 3571db09b84Saurel32 3581db09b84Saurel32 if (kvm_enabled()) { 359911d6e7aSAlexander Graf /* Read out host's frequencies */ 360911d6e7aSAlexander Graf clock_freq = kvmppc_get_clockfreq(); 361911d6e7aSAlexander Graf tb_freq = kvmppc_get_tbfreq(); 3625de6b46dSAlexander Graf 3635de6b46dSAlexander Graf /* indicate KVM hypercall interface */ 3645a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/hypervisor"); 3655a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/hypervisor", "compatible", 3665de6b46dSAlexander Graf "linux,kvm"); 3675de6b46dSAlexander Graf kvmppc_get_hypercall(env, hypercall, sizeof(hypercall)); 3685a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/hypervisor", "hcall-instructions", 3695de6b46dSAlexander Graf hypercall, sizeof(hypercall)); 3701a61a9aeSStuart Yoder /* if KVM supports the idle hcall, set property indicating this */ 3711a61a9aeSStuart Yoder if (kvmppc_get_hasidle(env)) { 3725a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/hypervisor", "has-idle", NULL, 0); 3731a61a9aeSStuart Yoder } 3741db09b84Saurel32 } 3751db09b84Saurel32 376625e665bSAlexander Graf /* Create CPU nodes */ 3775a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/cpus"); 3785a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1); 3795a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0); 380625e665bSAlexander Graf 3811e3debf0SAlexander Graf /* We need to generate the cpu nodes in reverse order, so Linux can pick 3821e3debf0SAlexander Graf the first node as boot node and be happy */ 3831e3debf0SAlexander Graf for (i = smp_cpus - 1; i >= 0; i--) { 384440c8152SAndreas Färber CPUState *cpu; 385621d05e3SAlexander Graf char cpu_name[128]; 3862eaaac1fSAlexander Graf uint64_t cpu_release_addr = params->spin_base + (i * 0x20); 38710f25a46SAlexander Graf 388440c8152SAndreas Färber cpu = qemu_get_cpu(i); 38955e5c285SAndreas Färber if (cpu == NULL) { 3901e3debf0SAlexander Graf continue; 3911e3debf0SAlexander Graf } 392440c8152SAndreas Färber env = cpu->env_ptr; 3931e3debf0SAlexander Graf 3946d536570SSam Bobroff snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", i); 3955a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, cpu_name); 3965a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq); 3975a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq); 3985a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu"); 3996d536570SSam Bobroff qemu_fdt_setprop_cell(fdt, cpu_name, "reg", i); 4005a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size", 4011e3debf0SAlexander Graf env->dcache_line_size); 4025a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size", 4031e3debf0SAlexander Graf env->icache_line_size); 4045a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000); 4055a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000); 4065a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "bus-frequency", 0); 40755e5c285SAndreas Färber if (cpu->cpu_index) { 4085a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "status", "disabled"); 4095a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "enable-method", 4105a4348d1SPeter Crosthwaite "spin-table"); 4115a4348d1SPeter Crosthwaite qemu_fdt_setprop_u64(fdt, cpu_name, "cpu-release-addr", 4121d2e5c52SAlexander Graf cpu_release_addr); 4131e3debf0SAlexander Graf } else { 4145a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay"); 4151e3debf0SAlexander Graf } 4161db09b84Saurel32 } 4171db09b84Saurel32 4185a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/aliases"); 4195da96624SAlexander Graf /* XXX These should go into their respective devices' code */ 4202eaaac1fSAlexander Graf snprintf(soc, sizeof(soc), "/soc@%"PRIx64, params->ccsrbar_base); 4215a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, soc); 4225a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, soc, "device_type", "soc"); 4235a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb, 424ebb9518aSAlexander Graf sizeof(compatible_sb)); 4255a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1); 4265a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1); 4275a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0, 4282eaaac1fSAlexander Graf params->ccsrbar_base >> 32, params->ccsrbar_base, 4295da96624SAlexander Graf MPC8544_CCSRBAR_SIZE); 4305da96624SAlexander Graf /* XXX should contain a reasonable value */ 4315a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0); 4325da96624SAlexander Graf 433dffb1dc2SBharat Bhushan snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET); 4345a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, mpic); 4355a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, mpic, "device_type", "open-pic"); 4365a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); 4375a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET, 438dffb1dc2SBharat Bhushan 0x40000); 4395a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "#address-cells", 0); 4405a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "#interrupt-cells", 2); 4415a4348d1SPeter Crosthwaite mpic_ph = qemu_fdt_alloc_phandle(fdt); 4425a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "phandle", mpic_ph); 4435a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); 4445a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, mpic, "interrupt-controller", NULL, 0); 44519ac9deaSAlexander Graf 4460cfc6e8dSAlexander Graf /* 4470cfc6e8dSAlexander Graf * We have to generate ser1 first, because Linux takes the first 4480cfc6e8dSAlexander Graf * device it finds in the dt as serial output device. And we generate 4490cfc6e8dSAlexander Graf * devices in reverse order to the dt. 4500cfc6e8dSAlexander Graf */ 45179c0ff2cSAlexander Graf if (serial_hds[1]) { 452dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET, 453a053a7ceSAlexander Graf soc, mpic, "serial1", 1, false); 45479c0ff2cSAlexander Graf } 45579c0ff2cSAlexander Graf 45679c0ff2cSAlexander Graf if (serial_hds[0]) { 457dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET, 458a053a7ceSAlexander Graf soc, mpic, "serial0", 0, true); 45979c0ff2cSAlexander Graf } 4600cfc6e8dSAlexander Graf 461ed2bc496SAlexander Graf snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, 462dffb1dc2SBharat Bhushan MPC8544_UTIL_OFFSET); 4635a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, gutil); 4645a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); 4655a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000); 4665a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); 467f5038483SAlexander Graf 468a911b7a9SAlexander Graf snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET); 4695a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, msi); 4705a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi"); 4715a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200); 4725a4348d1SPeter Crosthwaite msi_ph = qemu_fdt_alloc_phandle(fdt); 4735a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100); 4745a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, msi, "interrupt-parent", mpic); 4755a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "interrupts", 476a911b7a9SAlexander Graf 0xe0, 0x0, 477a911b7a9SAlexander Graf 0xe1, 0x0, 478a911b7a9SAlexander Graf 0xe2, 0x0, 479a911b7a9SAlexander Graf 0xe3, 0x0, 480a911b7a9SAlexander Graf 0xe4, 0x0, 481a911b7a9SAlexander Graf 0xe5, 0x0, 482a911b7a9SAlexander Graf 0xe6, 0x0, 483a911b7a9SAlexander Graf 0xe7, 0x0); 4845a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, msi, "phandle", msi_ph); 4855a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph); 486a911b7a9SAlexander Graf 4872eaaac1fSAlexander Graf snprintf(pci, sizeof(pci), "/pci@%llx", 4882eaaac1fSAlexander Graf params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET); 4895a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, pci); 4905a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "cell-index", 0); 4915a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); 4925a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, pci, "device_type", "pci"); 4935a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 4940dbc0798SAlexander Graf 0x0, 0x7); 4955a4348d1SPeter Crosthwaite pci_map = pci_map_create(fdt, qemu_fdt_get_phandle(fdt, mpic), 496492ec48dSAlexander Graf params->pci_first_slot, params->pci_nr_slots, 497492ec48dSAlexander Graf &len); 4985a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, pci, "interrupt-map", pci_map, len); 4995a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, pci, "interrupt-parent", mpic); 5005a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "interrupts", 24, 2); 5015a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "bus-range", 0, 255); 5023627757eSAlexander Graf for (i = 0; i < 14; i++) { 5030dbc0798SAlexander Graf pci_ranges[i] = cpu_to_be32(pci_ranges[i]); 5040dbc0798SAlexander Graf } 5055a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph); 5065a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); 5072eaaac1fSAlexander Graf qemu_fdt_setprop_cells(fdt, pci, "reg", 5082eaaac1fSAlexander Graf (params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET) >> 32, 5092eaaac1fSAlexander Graf (params->ccsrbar_base + MPC8544_PCI_REGS_OFFSET), 5102eaaac1fSAlexander Graf 0, 0x1000); 5115a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666); 5125a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1); 5135a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#size-cells", 2); 5145a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3); 5155a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci); 5160dbc0798SAlexander Graf 517b88e77f4SAlexander Graf if (params->has_mpc8xxx_gpio) { 518b88e77f4SAlexander Graf create_dt_mpc8xxx_gpio(fdt, soc, mpic); 519b88e77f4SAlexander Graf } 520b88e77f4SAlexander Graf 521f7087343SAlexander Graf if (params->has_platform_bus) { 522f7087343SAlexander Graf platform_bus_create_devtree(params, fdt, mpic); 523f7087343SAlexander Graf } 524f7087343SAlexander Graf 525e6eaabebSScott Wood params->fixup_devtree(params, fdt); 526e6eaabebSScott Wood 527e6eaabebSScott Wood if (toplevel_compat) { 5285a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/", "compatible", toplevel_compat, 529e6eaabebSScott Wood strlen(toplevel_compat) + 1); 530e6eaabebSScott Wood } 531e6eaabebSScott Wood 532d1b93565SAlexander Graf done: 53328290f37SAlexander Graf if (!dry_run) { 5345a4348d1SPeter Crosthwaite qemu_fdt_dumpdtb(fdt, fdt_size); 53528290f37SAlexander Graf cpu_physical_memory_write(addr, fdt, fdt_size); 536cba2026aSAlexander Graf } 537cba2026aSAlexander Graf ret = fdt_size; 5387ec632b4Spbrook 5391db09b84Saurel32 out: 540347dd79dSAlexander Graf g_free(pci_map); 5411db09b84Saurel32 54204088adbSLiu Yu return ret; 5431db09b84Saurel32 } 5441db09b84Saurel32 54528290f37SAlexander Graf typedef struct DeviceTreeParams { 5463ef96221SMarcel Apfelbaum MachineState *machine; 54728290f37SAlexander Graf PPCE500Params params; 54828290f37SAlexander Graf hwaddr addr; 54928290f37SAlexander Graf hwaddr initrd_base; 55028290f37SAlexander Graf hwaddr initrd_size; 551903585deSAlexander Graf hwaddr kernel_base; 552903585deSAlexander Graf hwaddr kernel_size; 553f7087343SAlexander Graf Notifier notifier; 55428290f37SAlexander Graf } DeviceTreeParams; 55528290f37SAlexander Graf 55628290f37SAlexander Graf static void ppce500_reset_device_tree(void *opaque) 55728290f37SAlexander Graf { 55828290f37SAlexander Graf DeviceTreeParams *p = opaque; 5593812c71fSAlexander Graf ppce500_load_device_tree(p->machine, &p->params, p->addr, p->initrd_base, 560903585deSAlexander Graf p->initrd_size, p->kernel_base, p->kernel_size, 561903585deSAlexander Graf false); 56228290f37SAlexander Graf } 56328290f37SAlexander Graf 564f7087343SAlexander Graf static void ppce500_init_notify(Notifier *notifier, void *data) 565f7087343SAlexander Graf { 566f7087343SAlexander Graf DeviceTreeParams *p = container_of(notifier, DeviceTreeParams, notifier); 567f7087343SAlexander Graf ppce500_reset_device_tree(p); 568f7087343SAlexander Graf } 569f7087343SAlexander Graf 5703ef96221SMarcel Apfelbaum static int ppce500_prep_device_tree(MachineState *machine, 57128290f37SAlexander Graf PPCE500Params *params, 57228290f37SAlexander Graf hwaddr addr, 57328290f37SAlexander Graf hwaddr initrd_base, 574903585deSAlexander Graf hwaddr initrd_size, 575903585deSAlexander Graf hwaddr kernel_base, 576903585deSAlexander Graf hwaddr kernel_size) 57728290f37SAlexander Graf { 57828290f37SAlexander Graf DeviceTreeParams *p = g_new(DeviceTreeParams, 1); 5793ef96221SMarcel Apfelbaum p->machine = machine; 58028290f37SAlexander Graf p->params = *params; 58128290f37SAlexander Graf p->addr = addr; 58228290f37SAlexander Graf p->initrd_base = initrd_base; 58328290f37SAlexander Graf p->initrd_size = initrd_size; 584903585deSAlexander Graf p->kernel_base = kernel_base; 585903585deSAlexander Graf p->kernel_size = kernel_size; 58628290f37SAlexander Graf 58728290f37SAlexander Graf qemu_register_reset(ppce500_reset_device_tree, p); 588f7087343SAlexander Graf p->notifier.notify = ppce500_init_notify; 589f7087343SAlexander Graf qemu_add_machine_init_done_notifier(&p->notifier); 59028290f37SAlexander Graf 59128290f37SAlexander Graf /* Issue the device tree loader once, so that we get the size of the blob */ 5923ef96221SMarcel Apfelbaum return ppce500_load_device_tree(machine, params, addr, initrd_base, 593903585deSAlexander Graf initrd_size, kernel_base, kernel_size, 594903585deSAlexander Graf true); 59528290f37SAlexander Graf } 59628290f37SAlexander Graf 597cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE. */ 598a36848ffSAaron Larson hwaddr booke206_page_size_to_tlb(uint64_t size) 599d1e256feSAlexander Graf { 600cba2026aSAlexander Graf return 63 - clz64(size >> 10); 601d1e256feSAlexander Graf } 602d1e256feSAlexander Graf 603cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env) 6043b989d49SAlexander Graf { 605cba2026aSAlexander Graf struct boot_info *bi = env->load_info; 606cefd3cdbSBharat Bhushan hwaddr dt_end; 607cba2026aSAlexander Graf int ps; 6083b989d49SAlexander Graf 609cba2026aSAlexander Graf /* Our initial TLB entry needs to cover everything from 0 to 610cba2026aSAlexander Graf the device tree top */ 611cba2026aSAlexander Graf dt_end = bi->dt_base + bi->dt_size; 612cba2026aSAlexander Graf ps = booke206_page_size_to_tlb(dt_end) + 1; 613fb37c302SAlexander Graf if (ps & 1) { 614fb37c302SAlexander Graf /* e500v2 can only do even TLB size bits */ 615fb37c302SAlexander Graf ps++; 616fb37c302SAlexander Graf } 617cefd3cdbSBharat Bhushan return ps; 618cefd3cdbSBharat Bhushan } 619cefd3cdbSBharat Bhushan 620cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env) 621cefd3cdbSBharat Bhushan { 622cefd3cdbSBharat Bhushan int tsize; 623cefd3cdbSBharat Bhushan 624cefd3cdbSBharat Bhushan tsize = booke206_initial_map_tsize(env); 625cefd3cdbSBharat Bhushan return (1ULL << 10 << tsize); 626cefd3cdbSBharat Bhushan } 627cefd3cdbSBharat Bhushan 628cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env) 629cefd3cdbSBharat Bhushan { 630cefd3cdbSBharat Bhushan ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); 631cefd3cdbSBharat Bhushan hwaddr size; 632cefd3cdbSBharat Bhushan int ps; 633cefd3cdbSBharat Bhushan 634cefd3cdbSBharat Bhushan ps = booke206_initial_map_tsize(env); 635cba2026aSAlexander Graf size = (ps << MAS1_TSIZE_SHIFT); 636d1e256feSAlexander Graf tlb->mas1 = MAS1_VALID | size; 637cba2026aSAlexander Graf tlb->mas2 = 0; 638cba2026aSAlexander Graf tlb->mas7_3 = 0; 639d1e256feSAlexander Graf tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; 64093dd5e85SScott Wood 64193dd5e85SScott Wood env->tlb_dirty = true; 6423b989d49SAlexander Graf } 6433b989d49SAlexander Graf 644b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque) 6455c145dacSAlexander Graf { 64638f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 647259186a7SAndreas Färber CPUState *cs = CPU(cpu); 6485c145dacSAlexander Graf 649259186a7SAndreas Färber cpu_reset(cs); 6505c145dacSAlexander Graf 6515c145dacSAlexander Graf /* Secondary CPU starts in halted state for now. Needs to change when 6525c145dacSAlexander Graf implementing non-kernel boot. */ 653259186a7SAndreas Färber cs->halted = 1; 65427103424SAndreas Färber cs->exception_index = EXCP_HLT; 6553b989d49SAlexander Graf } 6563b989d49SAlexander Graf 657b3305981SScott Wood static void ppce500_cpu_reset(void *opaque) 6583b989d49SAlexander Graf { 65938f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 660259186a7SAndreas Färber CPUState *cs = CPU(cpu); 66138f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 6623b989d49SAlexander Graf struct boot_info *bi = env->load_info; 6633b989d49SAlexander Graf 664259186a7SAndreas Färber cpu_reset(cs); 6653b989d49SAlexander Graf 6663b989d49SAlexander Graf /* Set initial guest state. */ 667259186a7SAndreas Färber cs->halted = 0; 6683b989d49SAlexander Graf env->gpr[1] = (16<<20) - 8; 6693b989d49SAlexander Graf env->gpr[3] = bi->dt_base; 670cefd3cdbSBharat Bhushan env->gpr[4] = 0; 671cefd3cdbSBharat Bhushan env->gpr[5] = 0; 672cefd3cdbSBharat Bhushan env->gpr[6] = EPAPR_MAGIC; 673cefd3cdbSBharat Bhushan env->gpr[7] = mmubooke_initial_mapsize(env); 674cefd3cdbSBharat Bhushan env->gpr[8] = 0; 675cefd3cdbSBharat Bhushan env->gpr[9] = 0; 6763b989d49SAlexander Graf env->nip = bi->entry; 677cba2026aSAlexander Graf mmubooke_create_initial_mapping(env); 6783b989d49SAlexander Graf } 6793b989d49SAlexander Graf 680d85937e6SScott Wood static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params, 68182fc73b6SScott Wood qemu_irq **irqs) 68282fc73b6SScott Wood { 68382fc73b6SScott Wood DeviceState *dev; 68482fc73b6SScott Wood SysBusDevice *s; 68582fc73b6SScott Wood int i, j, k; 68682fc73b6SScott Wood 687e1766344SAndreas Färber dev = qdev_create(NULL, TYPE_OPENPIC); 688e75ce32aSMichael Davidsaver object_property_add_child(qdev_get_machine(), "pic", OBJECT(dev), 689e75ce32aSMichael Davidsaver &error_fatal); 69082fc73b6SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 691d85937e6SScott Wood qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); 692d85937e6SScott Wood 69382fc73b6SScott Wood qdev_init_nofail(dev); 69482fc73b6SScott Wood s = SYS_BUS_DEVICE(dev); 69582fc73b6SScott Wood 69682fc73b6SScott Wood k = 0; 69782fc73b6SScott Wood for (i = 0; i < smp_cpus; i++) { 69882fc73b6SScott Wood for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { 69982fc73b6SScott Wood sysbus_connect_irq(s, k++, irqs[i][j]); 70082fc73b6SScott Wood } 70182fc73b6SScott Wood } 70282fc73b6SScott Wood 703d85937e6SScott Wood return dev; 704d85937e6SScott Wood } 705d85937e6SScott Wood 706d85937e6SScott Wood static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, 707fe656ebdSMarkus Armbruster qemu_irq **irqs, Error **errp) 708d85937e6SScott Wood { 709fe656ebdSMarkus Armbruster Error *err = NULL; 710d85937e6SScott Wood DeviceState *dev; 711d85937e6SScott Wood CPUState *cs; 712d85937e6SScott Wood 713dd49c038SAndreas Färber dev = qdev_create(NULL, TYPE_KVM_OPENPIC); 714d85937e6SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 715d85937e6SScott Wood 716fe656ebdSMarkus Armbruster object_property_set_bool(OBJECT(dev), true, "realized", &err); 717fe656ebdSMarkus Armbruster if (err) { 718fe656ebdSMarkus Armbruster error_propagate(errp, err); 719fe656ebdSMarkus Armbruster object_unparent(OBJECT(dev)); 720d85937e6SScott Wood return NULL; 721d85937e6SScott Wood } 722d85937e6SScott Wood 723bdc44640SAndreas Färber CPU_FOREACH(cs) { 724d85937e6SScott Wood if (kvm_openpic_connect_vcpu(dev, cs)) { 725d85937e6SScott Wood fprintf(stderr, "%s: failed to connect vcpu to irqchip\n", 726d85937e6SScott Wood __func__); 727d85937e6SScott Wood abort(); 728d85937e6SScott Wood } 729d85937e6SScott Wood } 730d85937e6SScott Wood 731d85937e6SScott Wood return dev; 732d85937e6SScott Wood } 733d85937e6SScott Wood 734c91c187fSMichael Davidsaver static DeviceState *ppce500_init_mpic(MachineState *machine, 735c91c187fSMichael Davidsaver PPCE500Params *params, 736c91c187fSMichael Davidsaver MemoryRegion *ccsr, 737c91c187fSMichael Davidsaver qemu_irq **irqs) 738d85937e6SScott Wood { 739d85937e6SScott Wood DeviceState *dev = NULL; 740d85937e6SScott Wood SysBusDevice *s; 741d85937e6SScott Wood 742d85937e6SScott Wood if (kvm_enabled()) { 743fe656ebdSMarkus Armbruster Error *err = NULL; 744d85937e6SScott Wood 745446f16a6SMarcel Apfelbaum if (machine_kernel_irqchip_allowed(machine)) { 746fe656ebdSMarkus Armbruster dev = ppce500_init_mpic_kvm(params, irqs, &err); 747d85937e6SScott Wood } 748446f16a6SMarcel Apfelbaum if (machine_kernel_irqchip_required(machine) && !dev) { 749c29b77f9SMarkus Armbruster error_reportf_err(err, 750c29b77f9SMarkus Armbruster "kernel_irqchip requested but unavailable: "); 751fe656ebdSMarkus Armbruster exit(1); 752d85937e6SScott Wood } 753d85937e6SScott Wood } 754d85937e6SScott Wood 755d85937e6SScott Wood if (!dev) { 756d85937e6SScott Wood dev = ppce500_init_mpic_qemu(params, irqs); 757d85937e6SScott Wood } 758d85937e6SScott Wood 759d85937e6SScott Wood s = SYS_BUS_DEVICE(dev); 76082fc73b6SScott Wood memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET, 76182fc73b6SScott Wood s->mmio[0].memory); 76282fc73b6SScott Wood 763c91c187fSMichael Davidsaver return dev; 76482fc73b6SScott Wood } 76582fc73b6SScott Wood 766016f7758SAlexander Graf static void ppce500_power_off(void *opaque, int line, int on) 767016f7758SAlexander Graf { 768016f7758SAlexander Graf if (on) { 769cf83f140SEric Blake qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 770016f7758SAlexander Graf } 771016f7758SAlexander Graf } 772016f7758SAlexander Graf 7733ef96221SMarcel Apfelbaum void ppce500_init(MachineState *machine, PPCE500Params *params) 7741db09b84Saurel32 { 77539186d8aSRichard Henderson MemoryRegion *address_space_mem = get_system_memory(); 7762646c133SAvi Kivity MemoryRegion *ram = g_new(MemoryRegion, 1); 7771db09b84Saurel32 PCIBus *pci_bus; 778e2684c0bSAndreas Färber CPUPPCState *env = NULL; 7793812c71fSAlexander Graf uint64_t loadaddr; 7803812c71fSAlexander Graf hwaddr kernel_base = -1LL; 7813812c71fSAlexander Graf int kernel_size = 0; 7823812c71fSAlexander Graf hwaddr dt_base = 0; 7833812c71fSAlexander Graf hwaddr initrd_base = 0; 7843812c71fSAlexander Graf int initrd_size = 0; 7853812c71fSAlexander Graf hwaddr cur_base = 0; 7863812c71fSAlexander Graf char *filename; 7873812c71fSAlexander Graf hwaddr bios_entry = 0; 7883812c71fSAlexander Graf target_long bios_size; 7893812c71fSAlexander Graf struct boot_info *boot_info; 7903812c71fSAlexander Graf int dt_size; 79182fc73b6SScott Wood int i; 792d575a6ceSBharat Bhushan /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and 793d575a6ceSBharat Bhushan * 4 respectively */ 794d575a6ceSBharat Bhushan unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4}; 795c91c187fSMichael Davidsaver qemu_irq **irqs; 796c91c187fSMichael Davidsaver DeviceState *dev, *mpicdev; 797e2684c0bSAndreas Färber CPUPPCState *firstenv = NULL; 7983eddc1beSBharat Bhushan MemoryRegion *ccsr_addr_space; 799dffb1dc2SBharat Bhushan SysBusDevice *s; 8003eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 8011db09b84Saurel32 802a915249fSAlexander Graf irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); 803a915249fSAlexander Graf irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); 804e61c36d5SAlexander Graf for (i = 0; i < smp_cpus; i++) { 805397b457dSAndreas Färber PowerPCCPU *cpu; 80655e5c285SAndreas Färber CPUState *cs; 807e61c36d5SAlexander Graf qemu_irq *input; 808397b457dSAndreas Färber 80959e816fdSIgor Mammedov cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); 810397b457dSAndreas Färber env = &cpu->env; 81155e5c285SAndreas Färber cs = CPU(cpu); 8121db09b84Saurel32 81300469dc3SValentin Plotkin if (env->mmu_model != POWERPC_MMU_BOOKE206) { 814*6f76b817SAlistair Francis error_report("MMU model %i not supported by this machine", 81500469dc3SValentin Plotkin env->mmu_model); 81600469dc3SValentin Plotkin exit(1); 81700469dc3SValentin Plotkin } 81800469dc3SValentin Plotkin 819e61c36d5SAlexander Graf if (!firstenv) { 820e61c36d5SAlexander Graf firstenv = env; 821e61c36d5SAlexander Graf } 822e61c36d5SAlexander Graf 823a915249fSAlexander Graf irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB); 824a915249fSAlexander Graf input = (qemu_irq *)env->irq_inputs; 825a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; 826a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; 8276a450df9SAlexander Graf env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i; 8282eaaac1fSAlexander Graf env->mpic_iack = params->ccsrbar_base + 829bd25922eSScott Wood MPC8544_MPIC_REGS_OFFSET + 0xa0; 830e61c36d5SAlexander Graf 831a34a92b9SAndreas Färber ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); 8323b989d49SAlexander Graf 8333b989d49SAlexander Graf /* Register reset handler */ 8345c145dacSAlexander Graf if (!i) { 8355c145dacSAlexander Graf /* Primary CPU */ 8365c145dacSAlexander Graf struct boot_info *boot_info; 837e61c36d5SAlexander Graf boot_info = g_malloc0(sizeof(struct boot_info)); 838b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset, cpu); 839e61c36d5SAlexander Graf env->load_info = boot_info; 8405c145dacSAlexander Graf } else { 8415c145dacSAlexander Graf /* Secondary CPUs */ 842b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset_sec, cpu); 8435c145dacSAlexander Graf } 844e61c36d5SAlexander Graf } 845e61c36d5SAlexander Graf 846e61c36d5SAlexander Graf env = firstenv; 8473b989d49SAlexander Graf 8481db09b84Saurel32 /* Fixup Memory size on a alignment boundary */ 8491db09b84Saurel32 ram_size &= ~(RAM_SIZES_ALIGN - 1); 8503ef96221SMarcel Apfelbaum machine->ram_size = ram_size; 8511db09b84Saurel32 8521db09b84Saurel32 /* Register Memory */ 853e938ba0cSShreyas B. Prabhu memory_region_allocate_system_memory(ram, NULL, "mpc8544ds.ram", ram_size); 8542646c133SAvi Kivity memory_region_add_subregion(address_space_mem, 0, ram); 8551db09b84Saurel32 8563eddc1beSBharat Bhushan dev = qdev_create(NULL, "e500-ccsr"); 8573eddc1beSBharat Bhushan object_property_add_child(qdev_get_machine(), "e500-ccsr", 8583eddc1beSBharat Bhushan OBJECT(dev), NULL); 8593eddc1beSBharat Bhushan qdev_init_nofail(dev); 8603eddc1beSBharat Bhushan ccsr = CCSR(dev); 8613eddc1beSBharat Bhushan ccsr_addr_space = &ccsr->ccsr_space; 8622eaaac1fSAlexander Graf memory_region_add_subregion(address_space_mem, params->ccsrbar_base, 8633eddc1beSBharat Bhushan ccsr_addr_space); 864dffb1dc2SBharat Bhushan 865c91c187fSMichael Davidsaver mpicdev = ppce500_init_mpic(machine, params, ccsr_addr_space, irqs); 8661db09b84Saurel32 8671db09b84Saurel32 /* Serial */ 8682d48377aSBlue Swirl if (serial_hds[0]) { 8693eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, 870c91c187fSMichael Davidsaver 0, qdev_get_gpio_in(mpicdev, 42), 399193, 8712ff0c7c3SRichard Henderson serial_hds[0], DEVICE_BIG_ENDIAN); 8722d48377aSBlue Swirl } 8731db09b84Saurel32 8742d48377aSBlue Swirl if (serial_hds[1]) { 8753eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, 876c91c187fSMichael Davidsaver 0, qdev_get_gpio_in(mpicdev, 42), 399193, 87759de4f98SBharat Bhushan serial_hds[1], DEVICE_BIG_ENDIAN); 8782d48377aSBlue Swirl } 8791db09b84Saurel32 880b0fb8423SAlexander Graf /* General Utility device */ 881dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "mpc8544-guts"); 882dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 883dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 8843eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET, 885dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 886b0fb8423SAlexander Graf 8871db09b84Saurel32 /* PCI */ 888dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "e500-pcihost"); 889e75ce32aSMichael Davidsaver object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev), 890e75ce32aSMichael Davidsaver &error_abort); 891492ec48dSAlexander Graf qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); 8923016dca0SBharat Bhushan qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]); 893dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 894dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 895d575a6ceSBharat Bhushan for (i = 0; i < PCI_NUM_PINS; i++) { 896c91c187fSMichael Davidsaver sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, pci_irq_nrs[i])); 897d575a6ceSBharat Bhushan } 898d575a6ceSBharat Bhushan 8993eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, 900dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 901dffb1dc2SBharat Bhushan 902d461e3b9SAlexander Graf pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); 9031db09b84Saurel32 if (!pci_bus) 9041db09b84Saurel32 printf("couldn't create PCI controller!\n"); 9051db09b84Saurel32 9061db09b84Saurel32 if (pci_bus) { 9071db09b84Saurel32 /* Register network interfaces. */ 9081db09b84Saurel32 for (i = 0; i < nb_nics; i++) { 90929b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL); 9101db09b84Saurel32 } 9111db09b84Saurel32 } 9121db09b84Saurel32 9135c145dacSAlexander Graf /* Register spinning region */ 9142eaaac1fSAlexander Graf sysbus_create_simple("e500-spin", params->spin_base, NULL); 9155c145dacSAlexander Graf 9163812c71fSAlexander Graf if (cur_base < (32 * 1024 * 1024)) { 9173812c71fSAlexander Graf /* u-boot occupies memory up to 32MB, so load blobs above */ 9183812c71fSAlexander Graf cur_base = (32 * 1024 * 1024); 9193812c71fSAlexander Graf } 9203812c71fSAlexander Graf 921b88e77f4SAlexander Graf if (params->has_mpc8xxx_gpio) { 922016f7758SAlexander Graf qemu_irq poweroff_irq; 923016f7758SAlexander Graf 924b88e77f4SAlexander Graf dev = qdev_create(NULL, "mpc8xxx_gpio"); 925b88e77f4SAlexander Graf s = SYS_BUS_DEVICE(dev); 926b88e77f4SAlexander Graf qdev_init_nofail(dev); 927c91c187fSMichael Davidsaver sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8XXX_GPIO_IRQ)); 928b88e77f4SAlexander Graf memory_region_add_subregion(ccsr_addr_space, MPC8XXX_GPIO_OFFSET, 929b88e77f4SAlexander Graf sysbus_mmio_get_region(s, 0)); 930016f7758SAlexander Graf 931016f7758SAlexander Graf /* Power Off GPIO at Pin 0 */ 932016f7758SAlexander Graf poweroff_irq = qemu_allocate_irq(ppce500_power_off, NULL, 0); 933016f7758SAlexander Graf qdev_connect_gpio_out(dev, 0, poweroff_irq); 934b88e77f4SAlexander Graf } 935b88e77f4SAlexander Graf 936f7087343SAlexander Graf /* Platform Bus Device */ 937f7087343SAlexander Graf if (params->has_platform_bus) { 938f7087343SAlexander Graf dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE); 939f7087343SAlexander Graf dev->id = TYPE_PLATFORM_BUS_DEVICE; 940f7087343SAlexander Graf qdev_prop_set_uint32(dev, "num_irqs", params->platform_bus_num_irqs); 941f7087343SAlexander Graf qdev_prop_set_uint32(dev, "mmio_size", params->platform_bus_size); 942f7087343SAlexander Graf qdev_init_nofail(dev); 943f7087343SAlexander Graf s = SYS_BUS_DEVICE(dev); 944f7087343SAlexander Graf 945f7087343SAlexander Graf for (i = 0; i < params->platform_bus_num_irqs; i++) { 946f7087343SAlexander Graf int irqn = params->platform_bus_first_irq + i; 947c91c187fSMichael Davidsaver sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn)); 948f7087343SAlexander Graf } 949f7087343SAlexander Graf 950f7087343SAlexander Graf memory_region_add_subregion(address_space_mem, 951f7087343SAlexander Graf params->platform_bus_base, 952f7087343SAlexander Graf sysbus_mmio_get_region(s, 0)); 953f7087343SAlexander Graf } 954f7087343SAlexander Graf 9551db09b84Saurel32 /* Load kernel. */ 9563ef96221SMarcel Apfelbaum if (machine->kernel_filename) { 9573812c71fSAlexander Graf kernel_base = cur_base; 9583812c71fSAlexander Graf kernel_size = load_image_targphys(machine->kernel_filename, 9593812c71fSAlexander Graf cur_base, 9603812c71fSAlexander Graf ram_size - cur_base); 9611db09b84Saurel32 if (kernel_size < 0) { 962*6f76b817SAlistair Francis error_report("could not load kernel '%s'", 9633ef96221SMarcel Apfelbaum machine->kernel_filename); 9641db09b84Saurel32 exit(1); 9651db09b84Saurel32 } 966528e536eSAlexander Graf 9673812c71fSAlexander Graf cur_base += kernel_size; 9681db09b84Saurel32 } 9691db09b84Saurel32 9701db09b84Saurel32 /* Load initrd. */ 9713ef96221SMarcel Apfelbaum if (machine->initrd_filename) { 972528e536eSAlexander Graf initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; 9733ef96221SMarcel Apfelbaum initrd_size = load_image_targphys(machine->initrd_filename, initrd_base, 974d7585251Spbrook ram_size - initrd_base); 9751db09b84Saurel32 9761db09b84Saurel32 if (initrd_size < 0) { 977*6f76b817SAlistair Francis error_report("could not load initial ram disk '%s'", 9783ef96221SMarcel Apfelbaum machine->initrd_filename); 9791db09b84Saurel32 exit(1); 9801db09b84Saurel32 } 981528e536eSAlexander Graf 982528e536eSAlexander Graf cur_base = initrd_base + initrd_size; 9831db09b84Saurel32 } 9841db09b84Saurel32 9853812c71fSAlexander Graf /* 9863812c71fSAlexander Graf * Smart firmware defaults ahead! 9873812c71fSAlexander Graf * 9883812c71fSAlexander Graf * We follow the following table to select which payload we execute. 9893812c71fSAlexander Graf * 9903812c71fSAlexander Graf * -kernel | -bios | payload 9913812c71fSAlexander Graf * ---------+-------+--------- 9923812c71fSAlexander Graf * N | Y | u-boot 9933812c71fSAlexander Graf * N | N | u-boot 9943812c71fSAlexander Graf * Y | Y | u-boot 9953812c71fSAlexander Graf * Y | N | kernel 9963812c71fSAlexander Graf * 9973812c71fSAlexander Graf * This ensures backwards compatibility with how we used to expose 9983812c71fSAlexander Graf * -kernel to users but allows them to run through u-boot as well. 9993812c71fSAlexander Graf */ 10003812c71fSAlexander Graf if (bios_name == NULL) { 10013ef96221SMarcel Apfelbaum if (machine->kernel_filename) { 10023812c71fSAlexander Graf bios_name = machine->kernel_filename; 10033812c71fSAlexander Graf } else { 10043812c71fSAlexander Graf bios_name = "u-boot.e500"; 10053812c71fSAlexander Graf } 10063812c71fSAlexander Graf } 10073812c71fSAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 10083812c71fSAlexander Graf 10093812c71fSAlexander Graf bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL, 10107ef295eaSPeter Crosthwaite 1, PPC_ELF_MACHINE, 0, 0); 10113812c71fSAlexander Graf if (bios_size < 0) { 10123812c71fSAlexander Graf /* 10133812c71fSAlexander Graf * Hrm. No ELF image? Try a uImage, maybe someone is giving us an 10143812c71fSAlexander Graf * ePAPR compliant kernel 10153812c71fSAlexander Graf */ 101625bda50aSMax Filippov kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL, 101725bda50aSMax Filippov NULL, NULL); 10183812c71fSAlexander Graf if (kernel_size < 0) { 1019*6f76b817SAlistair Francis error_report("could not load firmware '%s'", filename); 10203812c71fSAlexander Graf exit(1); 10213812c71fSAlexander Graf } 10223812c71fSAlexander Graf } 1023f19377bfSShannon Zhao g_free(filename); 10243812c71fSAlexander Graf 10253812c71fSAlexander Graf /* Reserve space for dtb */ 10263812c71fSAlexander Graf dt_base = (loadaddr + bios_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; 10275c145dacSAlexander Graf 10283ef96221SMarcel Apfelbaum dt_size = ppce500_prep_device_tree(machine, params, dt_base, 1029903585deSAlexander Graf initrd_base, initrd_size, 10303812c71fSAlexander Graf kernel_base, kernel_size); 1031cba2026aSAlexander Graf if (dt_size < 0) { 1032*6f76b817SAlistair Francis error_report("couldn't load device tree"); 10331db09b84Saurel32 exit(1); 10341db09b84Saurel32 } 1035b8dec144SAlexander Graf assert(dt_size < DTB_MAX_SIZE); 10361db09b84Saurel32 1037e61c36d5SAlexander Graf boot_info = env->load_info; 10383812c71fSAlexander Graf boot_info->entry = bios_entry; 10393b989d49SAlexander Graf boot_info->dt_base = dt_base; 1040cba2026aSAlexander Graf boot_info->dt_size = dt_size; 10411db09b84Saurel32 } 10423eddc1beSBharat Bhushan 1043d0c2b0d0Sxiaoqiang zhao static void e500_ccsr_initfn(Object *obj) 10443eddc1beSBharat Bhushan { 1045d0c2b0d0Sxiaoqiang zhao PPCE500CCSRState *ccsr = CCSR(obj); 1046d0c2b0d0Sxiaoqiang zhao memory_region_init(&ccsr->ccsr_space, obj, "e500-ccsr", 10473eddc1beSBharat Bhushan MPC8544_CCSRBAR_SIZE); 10483eddc1beSBharat Bhushan } 10493eddc1beSBharat Bhushan 10503eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = { 10513eddc1beSBharat Bhushan .name = TYPE_CCSR, 10523eddc1beSBharat Bhushan .parent = TYPE_SYS_BUS_DEVICE, 10533eddc1beSBharat Bhushan .instance_size = sizeof(PPCE500CCSRState), 1054d0c2b0d0Sxiaoqiang zhao .instance_init = e500_ccsr_initfn, 10553eddc1beSBharat Bhushan }; 10563eddc1beSBharat Bhushan 10573eddc1beSBharat Bhushan static void e500_register_types(void) 10583eddc1beSBharat Bhushan { 10593eddc1beSBharat Bhushan type_register_static(&e500_ccsr_info); 10603eddc1beSBharat Bhushan } 10613eddc1beSBharat Bhushan 10623eddc1beSBharat Bhushan type_init(e500_register_types) 1063