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" 39f7087343SAlexander Graf #include "qemu/error-report.h" 40f7087343SAlexander Graf #include "hw/platform-bus.h" 41*fdfb7f2cSAlexander Graf #include "hw/net/fsl_etsec/etsec.h" 421db09b84Saurel32 43cefd3cdbSBharat Bhushan #define EPAPR_MAGIC (0x45504150) 441db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" 459dd5eba1SScott Wood #define DTC_LOAD_PAD 0x1800000 4675bb6589SLiu Yu #define DTC_PAD_MASK 0xFFFFF 47b8dec144SAlexander Graf #define DTB_MAX_SIZE (8 * 1024 * 1024) 4875bb6589SLiu Yu #define INITRD_LOAD_PAD 0x2000000 4975bb6589SLiu Yu #define INITRD_PAD_MASK 0xFFFFFF 501db09b84Saurel32 511db09b84Saurel32 #define RAM_SIZES_ALIGN (64UL << 20) 521db09b84Saurel32 53b3305981SScott Wood /* TODO: parameterize */ 54ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE 0xE0000000ULL 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 61dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + \ 62dffb1dc2SBharat Bhushan MPC8544_PCI_REGS_OFFSET) 63ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE 0x1000ULL 64ed2bc496SAlexander Graf #define MPC8544_PCI_IO 0xE1000000ULL 65dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET 0xe0000ULL 66ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE 0xEF000000ULL 67b88e77f4SAlexander Graf #define MPC8XXX_GPIO_OFFSET 0x000FF000ULL 68b88e77f4SAlexander Graf #define MPC8XXX_GPIO_IRQ 43 691db09b84Saurel32 703b989d49SAlexander Graf struct boot_info 713b989d49SAlexander Graf { 723b989d49SAlexander Graf uint32_t dt_base; 73cba2026aSAlexander Graf uint32_t dt_size; 743b989d49SAlexander Graf uint32_t entry; 753b989d49SAlexander Graf }; 763b989d49SAlexander Graf 77347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot, 78347dd79dSAlexander Graf int nr_slots, int *len) 790dbc0798SAlexander Graf { 80347dd79dSAlexander Graf int i = 0; 81347dd79dSAlexander Graf int slot; 82347dd79dSAlexander Graf int pci_irq; 839e2c1298SAlexander Graf int host_irq; 84347dd79dSAlexander Graf int last_slot = first_slot + nr_slots; 85347dd79dSAlexander Graf uint32_t *pci_map; 860dbc0798SAlexander Graf 87347dd79dSAlexander Graf *len = nr_slots * 4 * 7 * sizeof(uint32_t); 88347dd79dSAlexander Graf pci_map = g_malloc(*len); 89347dd79dSAlexander Graf 90347dd79dSAlexander Graf for (slot = first_slot; slot < last_slot; slot++) { 91347dd79dSAlexander Graf for (pci_irq = 0; pci_irq < 4; pci_irq++) { 92347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(slot << 11); 93347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x0); 94347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x0); 95347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(pci_irq + 1); 96347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(mpic); 979e2c1298SAlexander Graf host_irq = ppce500_pci_map_irq_slot(slot, pci_irq); 989e2c1298SAlexander Graf pci_map[i++] = cpu_to_be32(host_irq + 1); 99347dd79dSAlexander Graf pci_map[i++] = cpu_to_be32(0x1); 1000dbc0798SAlexander Graf } 1010dbc0798SAlexander Graf } 1020dbc0798SAlexander Graf 103347dd79dSAlexander Graf assert((i * sizeof(uint32_t)) == *len); 104347dd79dSAlexander Graf 105347dd79dSAlexander Graf return pci_map; 106347dd79dSAlexander Graf } 107347dd79dSAlexander Graf 108a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset, 109a053a7ceSAlexander Graf const char *soc, const char *mpic, 110a053a7ceSAlexander Graf const char *alias, int idx, bool defcon) 111a053a7ceSAlexander Graf { 112a053a7ceSAlexander Graf char ser[128]; 113a053a7ceSAlexander Graf 114a053a7ceSAlexander Graf snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset); 1155a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, ser); 1165a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, ser, "device_type", "serial"); 1175a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, ser, "compatible", "ns16550"); 1185a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, ser, "reg", offset, 0x100); 1195a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, ser, "cell-index", idx); 1205a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", 0); 1215a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, ser, "interrupts", 42, 2); 1225a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, ser, "interrupt-parent", mpic); 1235a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/aliases", alias, ser); 124a053a7ceSAlexander Graf 125a053a7ceSAlexander Graf if (defcon) { 1265a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/chosen", "linux,stdout-path", ser); 127a053a7ceSAlexander Graf } 128a053a7ceSAlexander Graf } 129a053a7ceSAlexander Graf 130b88e77f4SAlexander Graf static void create_dt_mpc8xxx_gpio(void *fdt, const char *soc, const char *mpic) 131b88e77f4SAlexander Graf { 132b88e77f4SAlexander Graf hwaddr mmio0 = MPC8XXX_GPIO_OFFSET; 133b88e77f4SAlexander Graf int irq0 = MPC8XXX_GPIO_IRQ; 134b88e77f4SAlexander Graf gchar *node = g_strdup_printf("%s/gpio@%"PRIx64, soc, mmio0); 135016f7758SAlexander Graf gchar *poweroff = g_strdup_printf("%s/power-off", soc); 136016f7758SAlexander Graf int gpio_ph; 137b88e77f4SAlexander Graf 138b88e77f4SAlexander Graf qemu_fdt_add_subnode(fdt, node); 139b88e77f4SAlexander Graf qemu_fdt_setprop_string(fdt, node, "compatible", "fsl,qoriq-gpio"); 140b88e77f4SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "reg", mmio0, 0x1000); 141b88e77f4SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "interrupts", irq0, 0x2); 142b88e77f4SAlexander Graf qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic); 143b88e77f4SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "#gpio-cells", 2); 144b88e77f4SAlexander Graf qemu_fdt_setprop(fdt, node, "gpio-controller", NULL, 0); 145016f7758SAlexander Graf gpio_ph = qemu_fdt_alloc_phandle(fdt); 146016f7758SAlexander Graf qemu_fdt_setprop_cell(fdt, node, "phandle", gpio_ph); 147016f7758SAlexander Graf qemu_fdt_setprop_cell(fdt, node, "linux,phandle", gpio_ph); 148016f7758SAlexander Graf 149016f7758SAlexander Graf /* Power Off Pin */ 150016f7758SAlexander Graf qemu_fdt_add_subnode(fdt, poweroff); 151016f7758SAlexander Graf qemu_fdt_setprop_string(fdt, poweroff, "compatible", "gpio-poweroff"); 152016f7758SAlexander Graf qemu_fdt_setprop_cells(fdt, poweroff, "gpios", gpio_ph, 0, 0); 153b88e77f4SAlexander Graf 154b88e77f4SAlexander Graf g_free(node); 155016f7758SAlexander Graf g_free(poweroff); 156b88e77f4SAlexander Graf } 157b88e77f4SAlexander Graf 158f7087343SAlexander Graf typedef struct PlatformDevtreeData { 159f7087343SAlexander Graf void *fdt; 160f7087343SAlexander Graf const char *mpic; 161f7087343SAlexander Graf int irq_start; 162f7087343SAlexander Graf const char *node; 163f7087343SAlexander Graf PlatformBusDevice *pbus; 164f7087343SAlexander Graf } PlatformDevtreeData; 165f7087343SAlexander Graf 166*fdfb7f2cSAlexander Graf static int create_devtree_etsec(SysBusDevice *sbdev, PlatformDevtreeData *data) 167*fdfb7f2cSAlexander Graf { 168*fdfb7f2cSAlexander Graf eTSEC *etsec = ETSEC_COMMON(sbdev); 169*fdfb7f2cSAlexander Graf PlatformBusDevice *pbus = data->pbus; 170*fdfb7f2cSAlexander Graf hwaddr mmio0 = platform_bus_get_mmio_addr(pbus, sbdev, 0); 171*fdfb7f2cSAlexander Graf int irq0 = platform_bus_get_irqn(pbus, sbdev, 0); 172*fdfb7f2cSAlexander Graf int irq1 = platform_bus_get_irqn(pbus, sbdev, 1); 173*fdfb7f2cSAlexander Graf int irq2 = platform_bus_get_irqn(pbus, sbdev, 2); 174*fdfb7f2cSAlexander Graf gchar *node = g_strdup_printf("/platform/ethernet@%"PRIx64, mmio0); 175*fdfb7f2cSAlexander Graf gchar *group = g_strdup_printf("%s/queue-group", node); 176*fdfb7f2cSAlexander Graf void *fdt = data->fdt; 177*fdfb7f2cSAlexander Graf 178*fdfb7f2cSAlexander Graf assert((int64_t)mmio0 >= 0); 179*fdfb7f2cSAlexander Graf assert(irq0 >= 0); 180*fdfb7f2cSAlexander Graf assert(irq1 >= 0); 181*fdfb7f2cSAlexander Graf assert(irq2 >= 0); 182*fdfb7f2cSAlexander Graf 183*fdfb7f2cSAlexander Graf qemu_fdt_add_subnode(fdt, node); 184*fdfb7f2cSAlexander Graf qemu_fdt_setprop_string(fdt, node, "device_type", "network"); 185*fdfb7f2cSAlexander Graf qemu_fdt_setprop_string(fdt, node, "compatible", "fsl,etsec2"); 186*fdfb7f2cSAlexander Graf qemu_fdt_setprop_string(fdt, node, "model", "eTSEC"); 187*fdfb7f2cSAlexander Graf qemu_fdt_setprop(fdt, node, "local-mac-address", etsec->conf.macaddr.a, 6); 188*fdfb7f2cSAlexander Graf qemu_fdt_setprop_cells(fdt, node, "fixed-link", 0, 1, 1000, 0, 0); 189*fdfb7f2cSAlexander Graf 190*fdfb7f2cSAlexander Graf qemu_fdt_add_subnode(fdt, group); 191*fdfb7f2cSAlexander Graf qemu_fdt_setprop_cells(fdt, group, "reg", mmio0, 0x1000); 192*fdfb7f2cSAlexander Graf qemu_fdt_setprop_cells(fdt, group, "interrupts", 193*fdfb7f2cSAlexander Graf data->irq_start + irq0, 0x2, 194*fdfb7f2cSAlexander Graf data->irq_start + irq1, 0x2, 195*fdfb7f2cSAlexander Graf data->irq_start + irq2, 0x2); 196*fdfb7f2cSAlexander Graf 197*fdfb7f2cSAlexander Graf g_free(node); 198*fdfb7f2cSAlexander Graf g_free(group); 199*fdfb7f2cSAlexander Graf 200*fdfb7f2cSAlexander Graf return 0; 201*fdfb7f2cSAlexander Graf } 202*fdfb7f2cSAlexander Graf 203f7087343SAlexander Graf static int sysbus_device_create_devtree(SysBusDevice *sbdev, void *opaque) 204f7087343SAlexander Graf { 205f7087343SAlexander Graf PlatformDevtreeData *data = opaque; 206f7087343SAlexander Graf bool matched = false; 207f7087343SAlexander Graf 208*fdfb7f2cSAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_ETSEC_COMMON)) { 209*fdfb7f2cSAlexander Graf create_devtree_etsec(sbdev, data); 210*fdfb7f2cSAlexander Graf matched = true; 211*fdfb7f2cSAlexander Graf } 212*fdfb7f2cSAlexander Graf 213f7087343SAlexander Graf if (!matched) { 214f7087343SAlexander Graf error_report("Device %s is not supported by this machine yet.", 215f7087343SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 216f7087343SAlexander Graf exit(1); 217f7087343SAlexander Graf } 218f7087343SAlexander Graf 219f7087343SAlexander Graf return 0; 220f7087343SAlexander Graf } 221f7087343SAlexander Graf 222f7087343SAlexander Graf static void platform_bus_create_devtree(PPCE500Params *params, void *fdt, 223f7087343SAlexander Graf const char *mpic) 224f7087343SAlexander Graf { 225f7087343SAlexander Graf gchar *node = g_strdup_printf("/platform@%"PRIx64, params->platform_bus_base); 226f7087343SAlexander Graf const char platcomp[] = "qemu,platform\0simple-bus"; 227f7087343SAlexander Graf uint64_t addr = params->platform_bus_base; 228f7087343SAlexander Graf uint64_t size = params->platform_bus_size; 229f7087343SAlexander Graf int irq_start = params->platform_bus_first_irq; 230f7087343SAlexander Graf PlatformBusDevice *pbus; 231f7087343SAlexander Graf DeviceState *dev; 232f7087343SAlexander Graf 233f7087343SAlexander Graf /* Create a /platform node that we can put all devices into */ 234f7087343SAlexander Graf 235f7087343SAlexander Graf qemu_fdt_add_subnode(fdt, node); 236f7087343SAlexander Graf qemu_fdt_setprop(fdt, node, "compatible", platcomp, sizeof(platcomp)); 237f7087343SAlexander Graf 238f7087343SAlexander Graf /* Our platform bus region is less than 32bit big, so 1 cell is enough for 239f7087343SAlexander Graf address and size */ 240f7087343SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "#size-cells", 1); 241f7087343SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "#address-cells", 1); 242f7087343SAlexander Graf qemu_fdt_setprop_cells(fdt, node, "ranges", 0, addr >> 32, addr, size); 243f7087343SAlexander Graf 244f7087343SAlexander Graf qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic); 245f7087343SAlexander Graf 246f7087343SAlexander Graf dev = qdev_find_recursive(sysbus_get_default(), TYPE_PLATFORM_BUS_DEVICE); 247f7087343SAlexander Graf pbus = PLATFORM_BUS_DEVICE(dev); 248f7087343SAlexander Graf 249f7087343SAlexander Graf /* We can only create dt nodes for dynamic devices when they're ready */ 250f7087343SAlexander Graf if (pbus->done_gathering) { 251f7087343SAlexander Graf PlatformDevtreeData data = { 252f7087343SAlexander Graf .fdt = fdt, 253f7087343SAlexander Graf .mpic = mpic, 254f7087343SAlexander Graf .irq_start = irq_start, 255f7087343SAlexander Graf .node = node, 256f7087343SAlexander Graf .pbus = pbus, 257f7087343SAlexander Graf }; 258f7087343SAlexander Graf 259f7087343SAlexander Graf /* Loop through all dynamic sysbus devices and create nodes for them */ 260f7087343SAlexander Graf foreach_dynamic_sysbus_device(sysbus_device_create_devtree, &data); 261f7087343SAlexander Graf } 262f7087343SAlexander Graf 263f7087343SAlexander Graf g_free(node); 264f7087343SAlexander Graf } 265f7087343SAlexander Graf 2663ef96221SMarcel Apfelbaum static int ppce500_load_device_tree(MachineState *machine, 267e6eaabebSScott Wood PPCE500Params *params, 268a8170e5eSAvi Kivity hwaddr addr, 269a8170e5eSAvi Kivity hwaddr initrd_base, 27028290f37SAlexander Graf hwaddr initrd_size, 271903585deSAlexander Graf hwaddr kernel_base, 272903585deSAlexander Graf hwaddr kernel_size, 27328290f37SAlexander Graf bool dry_run) 2741db09b84Saurel32 { 27528290f37SAlexander Graf CPUPPCState *env = first_cpu->env_ptr; 276dbf916d8SAurelien Jarno int ret = -1; 2773ef96221SMarcel Apfelbaum uint64_t mem_reg_property[] = { 0, cpu_to_be64(machine->ram_size) }; 2787ec632b4Spbrook int fdt_size; 279dbf916d8SAurelien Jarno void *fdt; 2805de6b46dSAlexander Graf uint8_t hypercall[16]; 281911d6e7aSAlexander Graf uint32_t clock_freq = 400000000; 282911d6e7aSAlexander Graf uint32_t tb_freq = 400000000; 283621d05e3SAlexander Graf int i; 284ebb9518aSAlexander Graf char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; 2855da96624SAlexander Graf char soc[128]; 28619ac9deaSAlexander Graf char mpic[128]; 28719ac9deaSAlexander Graf uint32_t mpic_ph; 288a911b7a9SAlexander Graf uint32_t msi_ph; 289f5038483SAlexander Graf char gutil[128]; 2900dbc0798SAlexander Graf char pci[128]; 291a911b7a9SAlexander Graf char msi[128]; 292347dd79dSAlexander Graf uint32_t *pci_map = NULL; 293347dd79dSAlexander Graf int len; 2943627757eSAlexander Graf uint32_t pci_ranges[14] = 2953627757eSAlexander Graf { 2963627757eSAlexander Graf 0x2000000, 0x0, 0xc0000000, 2973627757eSAlexander Graf 0x0, 0xc0000000, 2983627757eSAlexander Graf 0x0, 0x20000000, 2993627757eSAlexander Graf 3003627757eSAlexander Graf 0x1000000, 0x0, 0x0, 3013627757eSAlexander Graf 0x0, 0xe1000000, 3023627757eSAlexander Graf 0x0, 0x10000, 3033627757eSAlexander Graf }; 3042ff3de68SMarkus Armbruster QemuOpts *machine_opts = qemu_get_machine_opts(); 3052ff3de68SMarkus Armbruster const char *dtb_file = qemu_opt_get(machine_opts, "dtb"); 3062ff3de68SMarkus Armbruster const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); 307d1b93565SAlexander Graf 308d1b93565SAlexander Graf if (dtb_file) { 309d1b93565SAlexander Graf char *filename; 310d1b93565SAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file); 311d1b93565SAlexander Graf if (!filename) { 312d1b93565SAlexander Graf goto out; 313d1b93565SAlexander Graf } 314d1b93565SAlexander Graf 315d1b93565SAlexander Graf fdt = load_device_tree(filename, &fdt_size); 316d1b93565SAlexander Graf if (!fdt) { 317d1b93565SAlexander Graf goto out; 318d1b93565SAlexander Graf } 319d1b93565SAlexander Graf goto done; 320d1b93565SAlexander Graf } 3211db09b84Saurel32 3222636fcb6SAlexander Graf fdt = create_device_tree(&fdt_size); 3235cea8590SPaul Brook if (fdt == NULL) { 3245cea8590SPaul Brook goto out; 3255cea8590SPaul Brook } 3261db09b84Saurel32 3271db09b84Saurel32 /* Manipulate device tree in memory. */ 3285a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 2); 3295a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 2); 33051b852b7SAlexander Graf 3315a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/memory"); 3325a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory"); 3335a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, 3341db09b84Saurel32 sizeof(mem_reg_property)); 3351db09b84Saurel32 3365a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/chosen"); 3373b989d49SAlexander Graf if (initrd_size) { 3385a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", 3391db09b84Saurel32 initrd_base); 3403b989d49SAlexander Graf if (ret < 0) { 3411db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); 3423b989d49SAlexander Graf } 3431db09b84Saurel32 3445a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", 3451db09b84Saurel32 (initrd_base + initrd_size)); 3463b989d49SAlexander Graf if (ret < 0) { 3471db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); 3483b989d49SAlexander Graf } 349903585deSAlexander Graf 350903585deSAlexander Graf } 351903585deSAlexander Graf 352903585deSAlexander Graf if (kernel_base != -1ULL) { 353903585deSAlexander Graf qemu_fdt_setprop_cells(fdt, "/chosen", "qemu,boot-kernel", 354903585deSAlexander Graf kernel_base >> 32, kernel_base, 355903585deSAlexander Graf kernel_size >> 32, kernel_size); 3563b989d49SAlexander Graf } 3571db09b84Saurel32 3585a4348d1SPeter Crosthwaite ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", 3593ef96221SMarcel Apfelbaum machine->kernel_cmdline); 3601db09b84Saurel32 if (ret < 0) 3611db09b84Saurel32 fprintf(stderr, "couldn't set /chosen/bootargs\n"); 3621db09b84Saurel32 3631db09b84Saurel32 if (kvm_enabled()) { 364911d6e7aSAlexander Graf /* Read out host's frequencies */ 365911d6e7aSAlexander Graf clock_freq = kvmppc_get_clockfreq(); 366911d6e7aSAlexander Graf tb_freq = kvmppc_get_tbfreq(); 3675de6b46dSAlexander Graf 3685de6b46dSAlexander Graf /* indicate KVM hypercall interface */ 3695a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/hypervisor"); 3705a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/hypervisor", "compatible", 3715de6b46dSAlexander Graf "linux,kvm"); 3725de6b46dSAlexander Graf kvmppc_get_hypercall(env, hypercall, sizeof(hypercall)); 3735a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/hypervisor", "hcall-instructions", 3745de6b46dSAlexander Graf hypercall, sizeof(hypercall)); 3751a61a9aeSStuart Yoder /* if KVM supports the idle hcall, set property indicating this */ 3761a61a9aeSStuart Yoder if (kvmppc_get_hasidle(env)) { 3775a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/hypervisor", "has-idle", NULL, 0); 3781a61a9aeSStuart Yoder } 3791db09b84Saurel32 } 3801db09b84Saurel32 381625e665bSAlexander Graf /* Create CPU nodes */ 3825a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/cpus"); 3835a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1); 3845a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0); 385625e665bSAlexander Graf 3861e3debf0SAlexander Graf /* We need to generate the cpu nodes in reverse order, so Linux can pick 3871e3debf0SAlexander Graf the first node as boot node and be happy */ 3881e3debf0SAlexander Graf for (i = smp_cpus - 1; i >= 0; i--) { 389440c8152SAndreas Färber CPUState *cpu; 3900f20ba62SAlexey Kardashevskiy PowerPCCPU *pcpu; 391621d05e3SAlexander Graf char cpu_name[128]; 3921d2e5c52SAlexander Graf uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20); 39310f25a46SAlexander Graf 394440c8152SAndreas Färber cpu = qemu_get_cpu(i); 39555e5c285SAndreas Färber if (cpu == NULL) { 3961e3debf0SAlexander Graf continue; 3971e3debf0SAlexander Graf } 398440c8152SAndreas Färber env = cpu->env_ptr; 3990f20ba62SAlexey Kardashevskiy pcpu = POWERPC_CPU(cpu); 4001e3debf0SAlexander Graf 40155e5c285SAndreas Färber snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", 4020f20ba62SAlexey Kardashevskiy ppc_get_vcpu_dt_id(pcpu)); 4035a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, cpu_name); 4045a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq); 4055a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq); 4065a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu"); 4070f20ba62SAlexey Kardashevskiy qemu_fdt_setprop_cell(fdt, cpu_name, "reg", 4080f20ba62SAlexey Kardashevskiy ppc_get_vcpu_dt_id(pcpu)); 4095a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size", 4101e3debf0SAlexander Graf env->dcache_line_size); 4115a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size", 4121e3debf0SAlexander Graf env->icache_line_size); 4135a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000); 4145a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000); 4155a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, cpu_name, "bus-frequency", 0); 41655e5c285SAndreas Färber if (cpu->cpu_index) { 4175a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "status", "disabled"); 4185a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "enable-method", 4195a4348d1SPeter Crosthwaite "spin-table"); 4205a4348d1SPeter Crosthwaite qemu_fdt_setprop_u64(fdt, cpu_name, "cpu-release-addr", 4211d2e5c52SAlexander Graf cpu_release_addr); 4221e3debf0SAlexander Graf } else { 4235a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay"); 4241e3debf0SAlexander Graf } 4251db09b84Saurel32 } 4261db09b84Saurel32 4275a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, "/aliases"); 4285da96624SAlexander Graf /* XXX These should go into their respective devices' code */ 429ed2bc496SAlexander Graf snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE); 4305a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, soc); 4315a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, soc, "device_type", "soc"); 4325a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb, 433ebb9518aSAlexander Graf sizeof(compatible_sb)); 4345a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1); 4355a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1); 4365a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0, 4373627757eSAlexander Graf MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE, 4385da96624SAlexander Graf MPC8544_CCSRBAR_SIZE); 4395da96624SAlexander Graf /* XXX should contain a reasonable value */ 4405a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0); 4415da96624SAlexander Graf 442dffb1dc2SBharat Bhushan snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET); 4435a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, mpic); 4445a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, mpic, "device_type", "open-pic"); 4455a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, mpic, "compatible", "fsl,mpic"); 4465a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET, 447dffb1dc2SBharat Bhushan 0x40000); 4485a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "#address-cells", 0); 4495a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "#interrupt-cells", 2); 4505a4348d1SPeter Crosthwaite mpic_ph = qemu_fdt_alloc_phandle(fdt); 4515a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "phandle", mpic_ph); 4525a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph); 4535a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, mpic, "interrupt-controller", NULL, 0); 45419ac9deaSAlexander Graf 4550cfc6e8dSAlexander Graf /* 4560cfc6e8dSAlexander Graf * We have to generate ser1 first, because Linux takes the first 4570cfc6e8dSAlexander Graf * device it finds in the dt as serial output device. And we generate 4580cfc6e8dSAlexander Graf * devices in reverse order to the dt. 4590cfc6e8dSAlexander Graf */ 46079c0ff2cSAlexander Graf if (serial_hds[1]) { 461dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET, 462a053a7ceSAlexander Graf soc, mpic, "serial1", 1, false); 46379c0ff2cSAlexander Graf } 46479c0ff2cSAlexander Graf 46579c0ff2cSAlexander Graf if (serial_hds[0]) { 466dffb1dc2SBharat Bhushan dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET, 467a053a7ceSAlexander Graf soc, mpic, "serial0", 0, true); 46879c0ff2cSAlexander Graf } 4690cfc6e8dSAlexander Graf 470ed2bc496SAlexander Graf snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc, 471dffb1dc2SBharat Bhushan MPC8544_UTIL_OFFSET); 4725a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, gutil); 4735a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts"); 4745a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000); 4755a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0); 476f5038483SAlexander Graf 477a911b7a9SAlexander Graf snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET); 4785a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, msi); 4795a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi"); 4805a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200); 4815a4348d1SPeter Crosthwaite msi_ph = qemu_fdt_alloc_phandle(fdt); 4825a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100); 4835a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, msi, "interrupt-parent", mpic); 4845a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, msi, "interrupts", 485a911b7a9SAlexander Graf 0xe0, 0x0, 486a911b7a9SAlexander Graf 0xe1, 0x0, 487a911b7a9SAlexander Graf 0xe2, 0x0, 488a911b7a9SAlexander Graf 0xe3, 0x0, 489a911b7a9SAlexander Graf 0xe4, 0x0, 490a911b7a9SAlexander Graf 0xe5, 0x0, 491a911b7a9SAlexander Graf 0xe6, 0x0, 492a911b7a9SAlexander Graf 0xe7, 0x0); 4935a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, msi, "phandle", msi_ph); 4945a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph); 495a911b7a9SAlexander Graf 496ed2bc496SAlexander Graf snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE); 4975a4348d1SPeter Crosthwaite qemu_fdt_add_subnode(fdt, pci); 4985a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "cell-index", 0); 4995a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci"); 5005a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, pci, "device_type", "pci"); 5015a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0, 5020dbc0798SAlexander Graf 0x0, 0x7); 5035a4348d1SPeter Crosthwaite pci_map = pci_map_create(fdt, qemu_fdt_get_phandle(fdt, mpic), 504492ec48dSAlexander Graf params->pci_first_slot, params->pci_nr_slots, 505492ec48dSAlexander Graf &len); 5065a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, pci, "interrupt-map", pci_map, len); 5075a4348d1SPeter Crosthwaite qemu_fdt_setprop_phandle(fdt, pci, "interrupt-parent", mpic); 5085a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "interrupts", 24, 2); 5095a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "bus-range", 0, 255); 5103627757eSAlexander Graf for (i = 0; i < 14; i++) { 5110dbc0798SAlexander Graf pci_ranges[i] = cpu_to_be32(pci_ranges[i]); 5120dbc0798SAlexander Graf } 5135a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph); 5145a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges)); 5155a4348d1SPeter Crosthwaite qemu_fdt_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32, 5163627757eSAlexander Graf MPC8544_PCI_REGS_BASE, 0, 0x1000); 5175a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666); 5185a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1); 5195a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#size-cells", 2); 5205a4348d1SPeter Crosthwaite qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3); 5215a4348d1SPeter Crosthwaite qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci); 5220dbc0798SAlexander Graf 523b88e77f4SAlexander Graf if (params->has_mpc8xxx_gpio) { 524b88e77f4SAlexander Graf create_dt_mpc8xxx_gpio(fdt, soc, mpic); 525b88e77f4SAlexander Graf } 526b88e77f4SAlexander Graf 527f7087343SAlexander Graf if (params->has_platform_bus) { 528f7087343SAlexander Graf platform_bus_create_devtree(params, fdt, mpic); 529f7087343SAlexander Graf } 530f7087343SAlexander Graf 531e6eaabebSScott Wood params->fixup_devtree(params, fdt); 532e6eaabebSScott Wood 533e6eaabebSScott Wood if (toplevel_compat) { 5345a4348d1SPeter Crosthwaite qemu_fdt_setprop(fdt, "/", "compatible", toplevel_compat, 535e6eaabebSScott Wood strlen(toplevel_compat) + 1); 536e6eaabebSScott Wood } 537e6eaabebSScott Wood 538d1b93565SAlexander Graf done: 53928290f37SAlexander Graf if (!dry_run) { 5405a4348d1SPeter Crosthwaite qemu_fdt_dumpdtb(fdt, fdt_size); 54128290f37SAlexander Graf cpu_physical_memory_write(addr, fdt, fdt_size); 542cba2026aSAlexander Graf } 543cba2026aSAlexander Graf ret = fdt_size; 5447ec632b4Spbrook 5451db09b84Saurel32 out: 546347dd79dSAlexander Graf g_free(pci_map); 5471db09b84Saurel32 54804088adbSLiu Yu return ret; 5491db09b84Saurel32 } 5501db09b84Saurel32 55128290f37SAlexander Graf typedef struct DeviceTreeParams { 5523ef96221SMarcel Apfelbaum MachineState *machine; 55328290f37SAlexander Graf PPCE500Params params; 55428290f37SAlexander Graf hwaddr addr; 55528290f37SAlexander Graf hwaddr initrd_base; 55628290f37SAlexander Graf hwaddr initrd_size; 557903585deSAlexander Graf hwaddr kernel_base; 558903585deSAlexander Graf hwaddr kernel_size; 559f7087343SAlexander Graf Notifier notifier; 56028290f37SAlexander Graf } DeviceTreeParams; 56128290f37SAlexander Graf 56228290f37SAlexander Graf static void ppce500_reset_device_tree(void *opaque) 56328290f37SAlexander Graf { 56428290f37SAlexander Graf DeviceTreeParams *p = opaque; 5653812c71fSAlexander Graf ppce500_load_device_tree(p->machine, &p->params, p->addr, p->initrd_base, 566903585deSAlexander Graf p->initrd_size, p->kernel_base, p->kernel_size, 567903585deSAlexander Graf false); 56828290f37SAlexander Graf } 56928290f37SAlexander Graf 570f7087343SAlexander Graf static void ppce500_init_notify(Notifier *notifier, void *data) 571f7087343SAlexander Graf { 572f7087343SAlexander Graf DeviceTreeParams *p = container_of(notifier, DeviceTreeParams, notifier); 573f7087343SAlexander Graf ppce500_reset_device_tree(p); 574f7087343SAlexander Graf } 575f7087343SAlexander Graf 5763ef96221SMarcel Apfelbaum static int ppce500_prep_device_tree(MachineState *machine, 57728290f37SAlexander Graf PPCE500Params *params, 57828290f37SAlexander Graf hwaddr addr, 57928290f37SAlexander Graf hwaddr initrd_base, 580903585deSAlexander Graf hwaddr initrd_size, 581903585deSAlexander Graf hwaddr kernel_base, 582903585deSAlexander Graf hwaddr kernel_size) 58328290f37SAlexander Graf { 58428290f37SAlexander Graf DeviceTreeParams *p = g_new(DeviceTreeParams, 1); 5853ef96221SMarcel Apfelbaum p->machine = machine; 58628290f37SAlexander Graf p->params = *params; 58728290f37SAlexander Graf p->addr = addr; 58828290f37SAlexander Graf p->initrd_base = initrd_base; 58928290f37SAlexander Graf p->initrd_size = initrd_size; 590903585deSAlexander Graf p->kernel_base = kernel_base; 591903585deSAlexander Graf p->kernel_size = kernel_size; 59228290f37SAlexander Graf 59328290f37SAlexander Graf qemu_register_reset(ppce500_reset_device_tree, p); 594f7087343SAlexander Graf p->notifier.notify = ppce500_init_notify; 595f7087343SAlexander Graf qemu_add_machine_init_done_notifier(&p->notifier); 59628290f37SAlexander Graf 59728290f37SAlexander Graf /* Issue the device tree loader once, so that we get the size of the blob */ 5983ef96221SMarcel Apfelbaum return ppce500_load_device_tree(machine, params, addr, initrd_base, 599903585deSAlexander Graf initrd_size, kernel_base, kernel_size, 600903585deSAlexander Graf true); 60128290f37SAlexander Graf } 60228290f37SAlexander Graf 603cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE. */ 604a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size) 605d1e256feSAlexander Graf { 606cba2026aSAlexander Graf return 63 - clz64(size >> 10); 607d1e256feSAlexander Graf } 608d1e256feSAlexander Graf 609cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env) 6103b989d49SAlexander Graf { 611cba2026aSAlexander Graf struct boot_info *bi = env->load_info; 612cefd3cdbSBharat Bhushan hwaddr dt_end; 613cba2026aSAlexander Graf int ps; 6143b989d49SAlexander Graf 615cba2026aSAlexander Graf /* Our initial TLB entry needs to cover everything from 0 to 616cba2026aSAlexander Graf the device tree top */ 617cba2026aSAlexander Graf dt_end = bi->dt_base + bi->dt_size; 618cba2026aSAlexander Graf ps = booke206_page_size_to_tlb(dt_end) + 1; 619fb37c302SAlexander Graf if (ps & 1) { 620fb37c302SAlexander Graf /* e500v2 can only do even TLB size bits */ 621fb37c302SAlexander Graf ps++; 622fb37c302SAlexander Graf } 623cefd3cdbSBharat Bhushan return ps; 624cefd3cdbSBharat Bhushan } 625cefd3cdbSBharat Bhushan 626cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env) 627cefd3cdbSBharat Bhushan { 628cefd3cdbSBharat Bhushan int tsize; 629cefd3cdbSBharat Bhushan 630cefd3cdbSBharat Bhushan tsize = booke206_initial_map_tsize(env); 631cefd3cdbSBharat Bhushan return (1ULL << 10 << tsize); 632cefd3cdbSBharat Bhushan } 633cefd3cdbSBharat Bhushan 634cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env) 635cefd3cdbSBharat Bhushan { 636cefd3cdbSBharat Bhushan ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0); 637cefd3cdbSBharat Bhushan hwaddr size; 638cefd3cdbSBharat Bhushan int ps; 639cefd3cdbSBharat Bhushan 640cefd3cdbSBharat Bhushan ps = booke206_initial_map_tsize(env); 641cba2026aSAlexander Graf size = (ps << MAS1_TSIZE_SHIFT); 642d1e256feSAlexander Graf tlb->mas1 = MAS1_VALID | size; 643cba2026aSAlexander Graf tlb->mas2 = 0; 644cba2026aSAlexander Graf tlb->mas7_3 = 0; 645d1e256feSAlexander Graf tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; 64693dd5e85SScott Wood 64793dd5e85SScott Wood env->tlb_dirty = true; 6483b989d49SAlexander Graf } 6493b989d49SAlexander Graf 650b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque) 6515c145dacSAlexander Graf { 65238f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 653259186a7SAndreas Färber CPUState *cs = CPU(cpu); 6545c145dacSAlexander Graf 655259186a7SAndreas Färber cpu_reset(cs); 6565c145dacSAlexander Graf 6575c145dacSAlexander Graf /* Secondary CPU starts in halted state for now. Needs to change when 6585c145dacSAlexander Graf implementing non-kernel boot. */ 659259186a7SAndreas Färber cs->halted = 1; 66027103424SAndreas Färber cs->exception_index = EXCP_HLT; 6613b989d49SAlexander Graf } 6623b989d49SAlexander Graf 663b3305981SScott Wood static void ppce500_cpu_reset(void *opaque) 6643b989d49SAlexander Graf { 66538f92da6SAndreas Färber PowerPCCPU *cpu = opaque; 666259186a7SAndreas Färber CPUState *cs = CPU(cpu); 66738f92da6SAndreas Färber CPUPPCState *env = &cpu->env; 6683b989d49SAlexander Graf struct boot_info *bi = env->load_info; 6693b989d49SAlexander Graf 670259186a7SAndreas Färber cpu_reset(cs); 6713b989d49SAlexander Graf 6723b989d49SAlexander Graf /* Set initial guest state. */ 673259186a7SAndreas Färber cs->halted = 0; 6743b989d49SAlexander Graf env->gpr[1] = (16<<20) - 8; 6753b989d49SAlexander Graf env->gpr[3] = bi->dt_base; 676cefd3cdbSBharat Bhushan env->gpr[4] = 0; 677cefd3cdbSBharat Bhushan env->gpr[5] = 0; 678cefd3cdbSBharat Bhushan env->gpr[6] = EPAPR_MAGIC; 679cefd3cdbSBharat Bhushan env->gpr[7] = mmubooke_initial_mapsize(env); 680cefd3cdbSBharat Bhushan env->gpr[8] = 0; 681cefd3cdbSBharat Bhushan env->gpr[9] = 0; 6823b989d49SAlexander Graf env->nip = bi->entry; 683cba2026aSAlexander Graf mmubooke_create_initial_mapping(env); 6843b989d49SAlexander Graf } 6853b989d49SAlexander Graf 686d85937e6SScott Wood static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params, 68782fc73b6SScott Wood qemu_irq **irqs) 68882fc73b6SScott Wood { 68982fc73b6SScott Wood DeviceState *dev; 69082fc73b6SScott Wood SysBusDevice *s; 69182fc73b6SScott Wood int i, j, k; 69282fc73b6SScott Wood 693e1766344SAndreas Färber dev = qdev_create(NULL, TYPE_OPENPIC); 69482fc73b6SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 695d85937e6SScott Wood qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus); 696d85937e6SScott Wood 69782fc73b6SScott Wood qdev_init_nofail(dev); 69882fc73b6SScott Wood s = SYS_BUS_DEVICE(dev); 69982fc73b6SScott Wood 70082fc73b6SScott Wood k = 0; 70182fc73b6SScott Wood for (i = 0; i < smp_cpus; i++) { 70282fc73b6SScott Wood for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { 70382fc73b6SScott Wood sysbus_connect_irq(s, k++, irqs[i][j]); 70482fc73b6SScott Wood } 70582fc73b6SScott Wood } 70682fc73b6SScott Wood 707d85937e6SScott Wood return dev; 708d85937e6SScott Wood } 709d85937e6SScott Wood 710d85937e6SScott Wood static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, 711d85937e6SScott Wood qemu_irq **irqs) 712d85937e6SScott Wood { 713d85937e6SScott Wood DeviceState *dev; 714d85937e6SScott Wood CPUState *cs; 715d85937e6SScott Wood int r; 716d85937e6SScott Wood 717dd49c038SAndreas Färber dev = qdev_create(NULL, TYPE_KVM_OPENPIC); 718d85937e6SScott Wood qdev_prop_set_uint32(dev, "model", params->mpic_version); 719d85937e6SScott Wood 720d85937e6SScott Wood r = qdev_init(dev); 721d85937e6SScott Wood if (r) { 722d85937e6SScott Wood return NULL; 723d85937e6SScott Wood } 724d85937e6SScott Wood 725bdc44640SAndreas Färber CPU_FOREACH(cs) { 726d85937e6SScott Wood if (kvm_openpic_connect_vcpu(dev, cs)) { 727d85937e6SScott Wood fprintf(stderr, "%s: failed to connect vcpu to irqchip\n", 728d85937e6SScott Wood __func__); 729d85937e6SScott Wood abort(); 730d85937e6SScott Wood } 731d85937e6SScott Wood } 732d85937e6SScott Wood 733d85937e6SScott Wood return dev; 734d85937e6SScott Wood } 735d85937e6SScott Wood 736d85937e6SScott Wood static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, 737d85937e6SScott Wood qemu_irq **irqs) 738d85937e6SScott Wood { 739d85937e6SScott Wood qemu_irq *mpic; 740d85937e6SScott Wood DeviceState *dev = NULL; 741d85937e6SScott Wood SysBusDevice *s; 742d85937e6SScott Wood int i; 743d85937e6SScott Wood 744aa2ac1daSPeter Crosthwaite mpic = g_new0(qemu_irq, 256); 745d85937e6SScott Wood 746d85937e6SScott Wood if (kvm_enabled()) { 74736ad0e94SMarkus Armbruster QemuOpts *machine_opts = qemu_get_machine_opts(); 74836ad0e94SMarkus Armbruster bool irqchip_allowed = qemu_opt_get_bool(machine_opts, 749d85937e6SScott Wood "kernel_irqchip", true); 75036ad0e94SMarkus Armbruster bool irqchip_required = qemu_opt_get_bool(machine_opts, 751d85937e6SScott Wood "kernel_irqchip", false); 752d85937e6SScott Wood 753d85937e6SScott Wood if (irqchip_allowed) { 754d85937e6SScott Wood dev = ppce500_init_mpic_kvm(params, irqs); 755d85937e6SScott Wood } 756d85937e6SScott Wood 757d85937e6SScott Wood if (irqchip_required && !dev) { 758d85937e6SScott Wood fprintf(stderr, "%s: irqchip requested but unavailable\n", 759d85937e6SScott Wood __func__); 760d85937e6SScott Wood abort(); 761d85937e6SScott Wood } 762d85937e6SScott Wood } 763d85937e6SScott Wood 764d85937e6SScott Wood if (!dev) { 765d85937e6SScott Wood dev = ppce500_init_mpic_qemu(params, irqs); 766d85937e6SScott Wood } 767d85937e6SScott Wood 76882fc73b6SScott Wood for (i = 0; i < 256; i++) { 76982fc73b6SScott Wood mpic[i] = qdev_get_gpio_in(dev, i); 77082fc73b6SScott Wood } 77182fc73b6SScott Wood 772d85937e6SScott Wood s = SYS_BUS_DEVICE(dev); 77382fc73b6SScott Wood memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET, 77482fc73b6SScott Wood s->mmio[0].memory); 77582fc73b6SScott Wood 77682fc73b6SScott Wood return mpic; 77782fc73b6SScott Wood } 77882fc73b6SScott Wood 779016f7758SAlexander Graf static void ppce500_power_off(void *opaque, int line, int on) 780016f7758SAlexander Graf { 781016f7758SAlexander Graf if (on) { 782016f7758SAlexander Graf qemu_system_shutdown_request(); 783016f7758SAlexander Graf } 784016f7758SAlexander Graf } 785016f7758SAlexander Graf 7863ef96221SMarcel Apfelbaum void ppce500_init(MachineState *machine, PPCE500Params *params) 7871db09b84Saurel32 { 78839186d8aSRichard Henderson MemoryRegion *address_space_mem = get_system_memory(); 7892646c133SAvi Kivity MemoryRegion *ram = g_new(MemoryRegion, 1); 7901db09b84Saurel32 PCIBus *pci_bus; 791e2684c0bSAndreas Färber CPUPPCState *env = NULL; 7923812c71fSAlexander Graf uint64_t loadaddr; 7933812c71fSAlexander Graf hwaddr kernel_base = -1LL; 7943812c71fSAlexander Graf int kernel_size = 0; 7953812c71fSAlexander Graf hwaddr dt_base = 0; 7963812c71fSAlexander Graf hwaddr initrd_base = 0; 7973812c71fSAlexander Graf int initrd_size = 0; 7983812c71fSAlexander Graf hwaddr cur_base = 0; 7993812c71fSAlexander Graf char *filename; 8003812c71fSAlexander Graf hwaddr bios_entry = 0; 8013812c71fSAlexander Graf target_long bios_size; 8023812c71fSAlexander Graf struct boot_info *boot_info; 8033812c71fSAlexander Graf int dt_size; 80482fc73b6SScott Wood int i; 805d575a6ceSBharat Bhushan /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and 806d575a6ceSBharat Bhushan * 4 respectively */ 807d575a6ceSBharat Bhushan unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4}; 808a915249fSAlexander Graf qemu_irq **irqs, *mpic; 809be13cc7aSAlexander Graf DeviceState *dev; 810e2684c0bSAndreas Färber CPUPPCState *firstenv = NULL; 8113eddc1beSBharat Bhushan MemoryRegion *ccsr_addr_space; 812dffb1dc2SBharat Bhushan SysBusDevice *s; 8133eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 8141db09b84Saurel32 815e61c36d5SAlexander Graf /* Setup CPUs */ 8163ef96221SMarcel Apfelbaum if (machine->cpu_model == NULL) { 8173ef96221SMarcel Apfelbaum machine->cpu_model = "e500v2_v30"; 818ef250db6SAlexander Graf } 819ef250db6SAlexander Graf 820a915249fSAlexander Graf irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); 821a915249fSAlexander Graf irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); 822e61c36d5SAlexander Graf for (i = 0; i < smp_cpus; i++) { 823397b457dSAndreas Färber PowerPCCPU *cpu; 82455e5c285SAndreas Färber CPUState *cs; 825e61c36d5SAlexander Graf qemu_irq *input; 826397b457dSAndreas Färber 8273ef96221SMarcel Apfelbaum cpu = cpu_ppc_init(machine->cpu_model); 828397b457dSAndreas Färber if (cpu == NULL) { 8291db09b84Saurel32 fprintf(stderr, "Unable to initialize CPU!\n"); 8301db09b84Saurel32 exit(1); 8311db09b84Saurel32 } 832397b457dSAndreas Färber env = &cpu->env; 83355e5c285SAndreas Färber cs = CPU(cpu); 8341db09b84Saurel32 835e61c36d5SAlexander Graf if (!firstenv) { 836e61c36d5SAlexander Graf firstenv = env; 837e61c36d5SAlexander Graf } 838e61c36d5SAlexander Graf 839a915249fSAlexander Graf irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB); 840a915249fSAlexander Graf input = (qemu_irq *)env->irq_inputs; 841a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT]; 842a915249fSAlexander Graf irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT]; 8436a450df9SAlexander Graf env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i; 84468c2dd70SAlexander Graf env->mpic_iack = MPC8544_CCSRBAR_BASE + 845bd25922eSScott Wood MPC8544_MPIC_REGS_OFFSET + 0xa0; 846e61c36d5SAlexander Graf 847a34a92b9SAndreas Färber ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); 8483b989d49SAlexander Graf 8493b989d49SAlexander Graf /* Register reset handler */ 8505c145dacSAlexander Graf if (!i) { 8515c145dacSAlexander Graf /* Primary CPU */ 8525c145dacSAlexander Graf struct boot_info *boot_info; 853e61c36d5SAlexander Graf boot_info = g_malloc0(sizeof(struct boot_info)); 854b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset, cpu); 855e61c36d5SAlexander Graf env->load_info = boot_info; 8565c145dacSAlexander Graf } else { 8575c145dacSAlexander Graf /* Secondary CPUs */ 858b3305981SScott Wood qemu_register_reset(ppce500_cpu_reset_sec, cpu); 8595c145dacSAlexander Graf } 860e61c36d5SAlexander Graf } 861e61c36d5SAlexander Graf 862e61c36d5SAlexander Graf env = firstenv; 8633b989d49SAlexander Graf 8641db09b84Saurel32 /* Fixup Memory size on a alignment boundary */ 8651db09b84Saurel32 ram_size &= ~(RAM_SIZES_ALIGN - 1); 8663ef96221SMarcel Apfelbaum machine->ram_size = ram_size; 8671db09b84Saurel32 8681db09b84Saurel32 /* Register Memory */ 869e938ba0cSShreyas B. Prabhu memory_region_allocate_system_memory(ram, NULL, "mpc8544ds.ram", ram_size); 8702646c133SAvi Kivity memory_region_add_subregion(address_space_mem, 0, ram); 8711db09b84Saurel32 8723eddc1beSBharat Bhushan dev = qdev_create(NULL, "e500-ccsr"); 8733eddc1beSBharat Bhushan object_property_add_child(qdev_get_machine(), "e500-ccsr", 8743eddc1beSBharat Bhushan OBJECT(dev), NULL); 8753eddc1beSBharat Bhushan qdev_init_nofail(dev); 8763eddc1beSBharat Bhushan ccsr = CCSR(dev); 8773eddc1beSBharat Bhushan ccsr_addr_space = &ccsr->ccsr_space; 8783eddc1beSBharat Bhushan memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE, 8793eddc1beSBharat Bhushan ccsr_addr_space); 880dffb1dc2SBharat Bhushan 88182fc73b6SScott Wood mpic = ppce500_init_mpic(params, ccsr_addr_space, irqs); 8821db09b84Saurel32 8831db09b84Saurel32 /* Serial */ 8842d48377aSBlue Swirl if (serial_hds[0]) { 8853eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET, 886cdbb912aSAlexander Graf 0, mpic[42], 399193, 8872ff0c7c3SRichard Henderson serial_hds[0], DEVICE_BIG_ENDIAN); 8882d48377aSBlue Swirl } 8891db09b84Saurel32 8902d48377aSBlue Swirl if (serial_hds[1]) { 8913eddc1beSBharat Bhushan serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET, 892cdbb912aSAlexander Graf 0, mpic[42], 399193, 89359de4f98SBharat Bhushan serial_hds[1], DEVICE_BIG_ENDIAN); 8942d48377aSBlue Swirl } 8951db09b84Saurel32 896b0fb8423SAlexander Graf /* General Utility device */ 897dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "mpc8544-guts"); 898dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 899dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 9003eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET, 901dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 902b0fb8423SAlexander Graf 9031db09b84Saurel32 /* PCI */ 904dffb1dc2SBharat Bhushan dev = qdev_create(NULL, "e500-pcihost"); 905492ec48dSAlexander Graf qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); 9063016dca0SBharat Bhushan qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]); 907dffb1dc2SBharat Bhushan qdev_init_nofail(dev); 908dffb1dc2SBharat Bhushan s = SYS_BUS_DEVICE(dev); 909d575a6ceSBharat Bhushan for (i = 0; i < PCI_NUM_PINS; i++) { 910d575a6ceSBharat Bhushan sysbus_connect_irq(s, i, mpic[pci_irq_nrs[i]]); 911d575a6ceSBharat Bhushan } 912d575a6ceSBharat Bhushan 9133eddc1beSBharat Bhushan memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, 914dffb1dc2SBharat Bhushan sysbus_mmio_get_region(s, 0)); 915dffb1dc2SBharat Bhushan 916d461e3b9SAlexander Graf pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); 9171db09b84Saurel32 if (!pci_bus) 9181db09b84Saurel32 printf("couldn't create PCI controller!\n"); 9191db09b84Saurel32 9201356b98dSAndreas Färber sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO); 9211db09b84Saurel32 9221db09b84Saurel32 if (pci_bus) { 9231db09b84Saurel32 /* Register network interfaces. */ 9241db09b84Saurel32 for (i = 0; i < nb_nics; i++) { 92529b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL); 9261db09b84Saurel32 } 9271db09b84Saurel32 } 9281db09b84Saurel32 9295c145dacSAlexander Graf /* Register spinning region */ 9305c145dacSAlexander Graf sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); 9315c145dacSAlexander Graf 9323812c71fSAlexander Graf if (cur_base < (32 * 1024 * 1024)) { 9333812c71fSAlexander Graf /* u-boot occupies memory up to 32MB, so load blobs above */ 9343812c71fSAlexander Graf cur_base = (32 * 1024 * 1024); 9353812c71fSAlexander Graf } 9363812c71fSAlexander Graf 937b88e77f4SAlexander Graf if (params->has_mpc8xxx_gpio) { 938016f7758SAlexander Graf qemu_irq poweroff_irq; 939016f7758SAlexander Graf 940b88e77f4SAlexander Graf dev = qdev_create(NULL, "mpc8xxx_gpio"); 941b88e77f4SAlexander Graf s = SYS_BUS_DEVICE(dev); 942b88e77f4SAlexander Graf qdev_init_nofail(dev); 943b88e77f4SAlexander Graf sysbus_connect_irq(s, 0, mpic[MPC8XXX_GPIO_IRQ]); 944b88e77f4SAlexander Graf memory_region_add_subregion(ccsr_addr_space, MPC8XXX_GPIO_OFFSET, 945b88e77f4SAlexander Graf sysbus_mmio_get_region(s, 0)); 946016f7758SAlexander Graf 947016f7758SAlexander Graf /* Power Off GPIO at Pin 0 */ 948016f7758SAlexander Graf poweroff_irq = qemu_allocate_irq(ppce500_power_off, NULL, 0); 949016f7758SAlexander Graf qdev_connect_gpio_out(dev, 0, poweroff_irq); 950b88e77f4SAlexander Graf } 951b88e77f4SAlexander Graf 952f7087343SAlexander Graf /* Platform Bus Device */ 953f7087343SAlexander Graf if (params->has_platform_bus) { 954f7087343SAlexander Graf dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE); 955f7087343SAlexander Graf dev->id = TYPE_PLATFORM_BUS_DEVICE; 956f7087343SAlexander Graf qdev_prop_set_uint32(dev, "num_irqs", params->platform_bus_num_irqs); 957f7087343SAlexander Graf qdev_prop_set_uint32(dev, "mmio_size", params->platform_bus_size); 958f7087343SAlexander Graf qdev_init_nofail(dev); 959f7087343SAlexander Graf s = SYS_BUS_DEVICE(dev); 960f7087343SAlexander Graf 961f7087343SAlexander Graf for (i = 0; i < params->platform_bus_num_irqs; i++) { 962f7087343SAlexander Graf int irqn = params->platform_bus_first_irq + i; 963f7087343SAlexander Graf sysbus_connect_irq(s, i, mpic[irqn]); 964f7087343SAlexander Graf } 965f7087343SAlexander Graf 966f7087343SAlexander Graf memory_region_add_subregion(address_space_mem, 967f7087343SAlexander Graf params->platform_bus_base, 968f7087343SAlexander Graf sysbus_mmio_get_region(s, 0)); 969f7087343SAlexander Graf } 970f7087343SAlexander Graf 9711db09b84Saurel32 /* Load kernel. */ 9723ef96221SMarcel Apfelbaum if (machine->kernel_filename) { 9733812c71fSAlexander Graf kernel_base = cur_base; 9743812c71fSAlexander Graf kernel_size = load_image_targphys(machine->kernel_filename, 9753812c71fSAlexander Graf cur_base, 9763812c71fSAlexander Graf ram_size - cur_base); 9771db09b84Saurel32 if (kernel_size < 0) { 9781db09b84Saurel32 fprintf(stderr, "qemu: could not load kernel '%s'\n", 9793ef96221SMarcel Apfelbaum machine->kernel_filename); 9801db09b84Saurel32 exit(1); 9811db09b84Saurel32 } 982528e536eSAlexander Graf 9833812c71fSAlexander Graf cur_base += kernel_size; 9841db09b84Saurel32 } 9851db09b84Saurel32 9861db09b84Saurel32 /* Load initrd. */ 9873ef96221SMarcel Apfelbaum if (machine->initrd_filename) { 988528e536eSAlexander Graf initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; 9893ef96221SMarcel Apfelbaum initrd_size = load_image_targphys(machine->initrd_filename, initrd_base, 990d7585251Spbrook ram_size - initrd_base); 9911db09b84Saurel32 9921db09b84Saurel32 if (initrd_size < 0) { 9931db09b84Saurel32 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 9943ef96221SMarcel Apfelbaum machine->initrd_filename); 9951db09b84Saurel32 exit(1); 9961db09b84Saurel32 } 997528e536eSAlexander Graf 998528e536eSAlexander Graf cur_base = initrd_base + initrd_size; 9991db09b84Saurel32 } 10001db09b84Saurel32 10013812c71fSAlexander Graf /* 10023812c71fSAlexander Graf * Smart firmware defaults ahead! 10033812c71fSAlexander Graf * 10043812c71fSAlexander Graf * We follow the following table to select which payload we execute. 10053812c71fSAlexander Graf * 10063812c71fSAlexander Graf * -kernel | -bios | payload 10073812c71fSAlexander Graf * ---------+-------+--------- 10083812c71fSAlexander Graf * N | Y | u-boot 10093812c71fSAlexander Graf * N | N | u-boot 10103812c71fSAlexander Graf * Y | Y | u-boot 10113812c71fSAlexander Graf * Y | N | kernel 10123812c71fSAlexander Graf * 10133812c71fSAlexander Graf * This ensures backwards compatibility with how we used to expose 10143812c71fSAlexander Graf * -kernel to users but allows them to run through u-boot as well. 10153812c71fSAlexander Graf */ 10163812c71fSAlexander Graf if (bios_name == NULL) { 10173ef96221SMarcel Apfelbaum if (machine->kernel_filename) { 10183812c71fSAlexander Graf bios_name = machine->kernel_filename; 10193812c71fSAlexander Graf } else { 10203812c71fSAlexander Graf bios_name = "u-boot.e500"; 10213812c71fSAlexander Graf } 10223812c71fSAlexander Graf } 10233812c71fSAlexander Graf filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 10243812c71fSAlexander Graf 10253812c71fSAlexander Graf bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL, 10263812c71fSAlexander Graf 1, ELF_MACHINE, 0); 10273812c71fSAlexander Graf if (bios_size < 0) { 10283812c71fSAlexander Graf /* 10293812c71fSAlexander Graf * Hrm. No ELF image? Try a uImage, maybe someone is giving us an 10303812c71fSAlexander Graf * ePAPR compliant kernel 10313812c71fSAlexander Graf */ 103225bda50aSMax Filippov kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL, 103325bda50aSMax Filippov NULL, NULL); 10343812c71fSAlexander Graf if (kernel_size < 0) { 10353812c71fSAlexander Graf fprintf(stderr, "qemu: could not load firmware '%s'\n", filename); 10363812c71fSAlexander Graf exit(1); 10373812c71fSAlexander Graf } 10383812c71fSAlexander Graf } 10393812c71fSAlexander Graf 10403812c71fSAlexander Graf /* Reserve space for dtb */ 10413812c71fSAlexander Graf dt_base = (loadaddr + bios_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; 10425c145dacSAlexander Graf 10433ef96221SMarcel Apfelbaum dt_size = ppce500_prep_device_tree(machine, params, dt_base, 1044903585deSAlexander Graf initrd_base, initrd_size, 10453812c71fSAlexander Graf kernel_base, kernel_size); 1046cba2026aSAlexander Graf if (dt_size < 0) { 10471db09b84Saurel32 fprintf(stderr, "couldn't load device tree\n"); 10481db09b84Saurel32 exit(1); 10491db09b84Saurel32 } 1050b8dec144SAlexander Graf assert(dt_size < DTB_MAX_SIZE); 10511db09b84Saurel32 1052e61c36d5SAlexander Graf boot_info = env->load_info; 10533812c71fSAlexander Graf boot_info->entry = bios_entry; 10543b989d49SAlexander Graf boot_info->dt_base = dt_base; 1055cba2026aSAlexander Graf boot_info->dt_size = dt_size; 10561db09b84Saurel32 10573b989d49SAlexander Graf if (kvm_enabled()) { 10581db09b84Saurel32 kvmppc_init(); 10593b989d49SAlexander Graf } 10601db09b84Saurel32 } 10613eddc1beSBharat Bhushan 10623eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev) 10633eddc1beSBharat Bhushan { 10643eddc1beSBharat Bhushan PPCE500CCSRState *ccsr; 10653eddc1beSBharat Bhushan 10663eddc1beSBharat Bhushan ccsr = CCSR(dev); 106740c5dce9SPaolo Bonzini memory_region_init(&ccsr->ccsr_space, OBJECT(ccsr), "e500-ccsr", 10683eddc1beSBharat Bhushan MPC8544_CCSRBAR_SIZE); 10693eddc1beSBharat Bhushan return 0; 10703eddc1beSBharat Bhushan } 10713eddc1beSBharat Bhushan 10723eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data) 10733eddc1beSBharat Bhushan { 10743eddc1beSBharat Bhushan SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 10753eddc1beSBharat Bhushan k->init = e500_ccsr_initfn; 10763eddc1beSBharat Bhushan } 10773eddc1beSBharat Bhushan 10783eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = { 10793eddc1beSBharat Bhushan .name = TYPE_CCSR, 10803eddc1beSBharat Bhushan .parent = TYPE_SYS_BUS_DEVICE, 10813eddc1beSBharat Bhushan .instance_size = sizeof(PPCE500CCSRState), 10823eddc1beSBharat Bhushan .class_init = e500_ccsr_class_init, 10833eddc1beSBharat Bhushan }; 10843eddc1beSBharat Bhushan 10853eddc1beSBharat Bhushan static void e500_register_types(void) 10863eddc1beSBharat Bhushan { 10873eddc1beSBharat Bhushan type_register_static(&e500_ccsr_info); 10883eddc1beSBharat Bhushan } 10893eddc1beSBharat Bhushan 10903eddc1beSBharat Bhushan type_init(e500_register_types) 1091