xref: /qemu/hw/ppc/e500.c (revision b88e77f49331f1187118b7ce2494ec169d3a865a)
11db09b84Saurel32 /*
2b3305981SScott Wood  * QEMU PowerPC e500-based platforms
31db09b84Saurel32  *
41db09b84Saurel32  * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
51db09b84Saurel32  *
61db09b84Saurel32  * Author: Yu Liu,     <yu.liu@freescale.com>
71db09b84Saurel32  *
81db09b84Saurel32  * This file is derived from hw/ppc440_bamboo.c,
91db09b84Saurel32  * the copyright for that material belongs to the original owners.
101db09b84Saurel32  *
111db09b84Saurel32  * This is free software; you can redistribute it and/or modify
121db09b84Saurel32  * it under the terms of  the GNU General  Public License as published by
131db09b84Saurel32  * the Free Software Foundation;  either version 2 of the  License, or
141db09b84Saurel32  * (at your option) any later version.
151db09b84Saurel32  */
161db09b84Saurel32 
171db09b84Saurel32 #include "config.h"
181db09b84Saurel32 #include "qemu-common.h"
19e6eaabebSScott Wood #include "e500.h"
203eddc1beSBharat Bhushan #include "e500-ccsr.h"
211422e32dSPaolo Bonzini #include "net/net.h"
221de7afc9SPaolo Bonzini #include "qemu/config-file.h"
234a18e7c9SScott Wood #include "hw/hw.h"
240d09e41aSPaolo Bonzini #include "hw/char/serial.h"
25a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h"
264a18e7c9SScott Wood #include "hw/boards.h"
279c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
289c17d615SPaolo Bonzini #include "sysemu/kvm.h"
291db09b84Saurel32 #include "kvm_ppc.h"
309c17d615SPaolo Bonzini #include "sysemu/device_tree.h"
310d09e41aSPaolo Bonzini #include "hw/ppc/openpic.h"
320d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h"
334a18e7c9SScott Wood #include "hw/loader.h"
34ca20cf32SBlue Swirl #include "elf.h"
354a18e7c9SScott Wood #include "hw/sysbus.h"
36022c62cbSPaolo Bonzini #include "exec/address-spaces.h"
371de7afc9SPaolo Bonzini #include "qemu/host-utils.h"
380d09e41aSPaolo Bonzini #include "hw/pci-host/ppce500.h"
391db09b84Saurel32 
40cefd3cdbSBharat Bhushan #define EPAPR_MAGIC                (0x45504150)
411db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
429dd5eba1SScott Wood #define DTC_LOAD_PAD               0x1800000
4375bb6589SLiu Yu #define DTC_PAD_MASK               0xFFFFF
44b8dec144SAlexander Graf #define DTB_MAX_SIZE               (8 * 1024 * 1024)
4575bb6589SLiu Yu #define INITRD_LOAD_PAD            0x2000000
4675bb6589SLiu Yu #define INITRD_PAD_MASK            0xFFFFFF
471db09b84Saurel32 
481db09b84Saurel32 #define RAM_SIZES_ALIGN            (64UL << 20)
491db09b84Saurel32 
50b3305981SScott Wood /* TODO: parameterize */
51ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE       0xE0000000ULL
52ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE       0x00100000ULL
53dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET   0x40000ULL
54a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET   0x41600ULL
55dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL
56dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL
57dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET    0x8000ULL
58dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE      (MPC8544_CCSRBAR_BASE + \
59dffb1dc2SBharat Bhushan                                     MPC8544_PCI_REGS_OFFSET)
60ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE      0x1000ULL
61ed2bc496SAlexander Graf #define MPC8544_PCI_IO             0xE1000000ULL
62dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET        0xe0000ULL
63ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE          0xEF000000ULL
64*b88e77f4SAlexander Graf #define MPC8XXX_GPIO_OFFSET        0x000FF000ULL
65*b88e77f4SAlexander Graf #define MPC8XXX_GPIO_IRQ           43
661db09b84Saurel32 
673b989d49SAlexander Graf struct boot_info
683b989d49SAlexander Graf {
693b989d49SAlexander Graf     uint32_t dt_base;
70cba2026aSAlexander Graf     uint32_t dt_size;
713b989d49SAlexander Graf     uint32_t entry;
723b989d49SAlexander Graf };
733b989d49SAlexander Graf 
74347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot,
75347dd79dSAlexander Graf                                 int nr_slots, int *len)
760dbc0798SAlexander Graf {
77347dd79dSAlexander Graf     int i = 0;
78347dd79dSAlexander Graf     int slot;
79347dd79dSAlexander Graf     int pci_irq;
809e2c1298SAlexander Graf     int host_irq;
81347dd79dSAlexander Graf     int last_slot = first_slot + nr_slots;
82347dd79dSAlexander Graf     uint32_t *pci_map;
830dbc0798SAlexander Graf 
84347dd79dSAlexander Graf     *len = nr_slots * 4 * 7 * sizeof(uint32_t);
85347dd79dSAlexander Graf     pci_map = g_malloc(*len);
86347dd79dSAlexander Graf 
87347dd79dSAlexander Graf     for (slot = first_slot; slot < last_slot; slot++) {
88347dd79dSAlexander Graf         for (pci_irq = 0; pci_irq < 4; pci_irq++) {
89347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(slot << 11);
90347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
91347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
92347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(pci_irq + 1);
93347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(mpic);
949e2c1298SAlexander Graf             host_irq = ppce500_pci_map_irq_slot(slot, pci_irq);
959e2c1298SAlexander Graf             pci_map[i++] = cpu_to_be32(host_irq + 1);
96347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x1);
970dbc0798SAlexander Graf         }
980dbc0798SAlexander Graf     }
990dbc0798SAlexander Graf 
100347dd79dSAlexander Graf     assert((i * sizeof(uint32_t)) == *len);
101347dd79dSAlexander Graf 
102347dd79dSAlexander Graf     return pci_map;
103347dd79dSAlexander Graf }
104347dd79dSAlexander Graf 
105a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset,
106a053a7ceSAlexander Graf                              const char *soc, const char *mpic,
107a053a7ceSAlexander Graf                              const char *alias, int idx, bool defcon)
108a053a7ceSAlexander Graf {
109a053a7ceSAlexander Graf     char ser[128];
110a053a7ceSAlexander Graf 
111a053a7ceSAlexander Graf     snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset);
1125a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, ser);
1135a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, ser, "device_type", "serial");
1145a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, ser, "compatible", "ns16550");
1155a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, ser, "reg", offset, 0x100);
1165a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, ser, "cell-index", idx);
1175a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", 0);
1185a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, ser, "interrupts", 42, 2);
1195a4348d1SPeter Crosthwaite     qemu_fdt_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
1205a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, "/aliases", alias, ser);
121a053a7ceSAlexander Graf 
122a053a7ceSAlexander Graf     if (defcon) {
1235a4348d1SPeter Crosthwaite         qemu_fdt_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
124a053a7ceSAlexander Graf     }
125a053a7ceSAlexander Graf }
126a053a7ceSAlexander Graf 
127*b88e77f4SAlexander Graf static void create_dt_mpc8xxx_gpio(void *fdt, const char *soc, const char *mpic)
128*b88e77f4SAlexander Graf {
129*b88e77f4SAlexander Graf     hwaddr mmio0 = MPC8XXX_GPIO_OFFSET;
130*b88e77f4SAlexander Graf     int irq0 = MPC8XXX_GPIO_IRQ;
131*b88e77f4SAlexander Graf     gchar *node = g_strdup_printf("%s/gpio@%"PRIx64, soc, mmio0);
132*b88e77f4SAlexander Graf 
133*b88e77f4SAlexander Graf     qemu_fdt_add_subnode(fdt, node);
134*b88e77f4SAlexander Graf     qemu_fdt_setprop_string(fdt, node, "compatible", "fsl,qoriq-gpio");
135*b88e77f4SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "reg", mmio0, 0x1000);
136*b88e77f4SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "interrupts", irq0, 0x2);
137*b88e77f4SAlexander Graf     qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic);
138*b88e77f4SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "#gpio-cells", 2);
139*b88e77f4SAlexander Graf     qemu_fdt_setprop(fdt, node, "gpio-controller", NULL, 0);
140*b88e77f4SAlexander Graf 
141*b88e77f4SAlexander Graf     g_free(node);
142*b88e77f4SAlexander Graf }
143*b88e77f4SAlexander Graf 
1443ef96221SMarcel Apfelbaum static int ppce500_load_device_tree(MachineState *machine,
145e6eaabebSScott Wood                                     PPCE500Params *params,
146a8170e5eSAvi Kivity                                     hwaddr addr,
147a8170e5eSAvi Kivity                                     hwaddr initrd_base,
14828290f37SAlexander Graf                                     hwaddr initrd_size,
149903585deSAlexander Graf                                     hwaddr kernel_base,
150903585deSAlexander Graf                                     hwaddr kernel_size,
15128290f37SAlexander Graf                                     bool dry_run)
1521db09b84Saurel32 {
15328290f37SAlexander Graf     CPUPPCState *env = first_cpu->env_ptr;
154dbf916d8SAurelien Jarno     int ret = -1;
1553ef96221SMarcel Apfelbaum     uint64_t mem_reg_property[] = { 0, cpu_to_be64(machine->ram_size) };
1567ec632b4Spbrook     int fdt_size;
157dbf916d8SAurelien Jarno     void *fdt;
1585de6b46dSAlexander Graf     uint8_t hypercall[16];
159911d6e7aSAlexander Graf     uint32_t clock_freq = 400000000;
160911d6e7aSAlexander Graf     uint32_t tb_freq = 400000000;
161621d05e3SAlexander Graf     int i;
162ebb9518aSAlexander Graf     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
1635da96624SAlexander Graf     char soc[128];
16419ac9deaSAlexander Graf     char mpic[128];
16519ac9deaSAlexander Graf     uint32_t mpic_ph;
166a911b7a9SAlexander Graf     uint32_t msi_ph;
167f5038483SAlexander Graf     char gutil[128];
1680dbc0798SAlexander Graf     char pci[128];
169a911b7a9SAlexander Graf     char msi[128];
170347dd79dSAlexander Graf     uint32_t *pci_map = NULL;
171347dd79dSAlexander Graf     int len;
1723627757eSAlexander Graf     uint32_t pci_ranges[14] =
1733627757eSAlexander Graf         {
1743627757eSAlexander Graf             0x2000000, 0x0, 0xc0000000,
1753627757eSAlexander Graf             0x0, 0xc0000000,
1763627757eSAlexander Graf             0x0, 0x20000000,
1773627757eSAlexander Graf 
1783627757eSAlexander Graf             0x1000000, 0x0, 0x0,
1793627757eSAlexander Graf             0x0, 0xe1000000,
1803627757eSAlexander Graf             0x0, 0x10000,
1813627757eSAlexander Graf         };
1822ff3de68SMarkus Armbruster     QemuOpts *machine_opts = qemu_get_machine_opts();
1832ff3de68SMarkus Armbruster     const char *dtb_file = qemu_opt_get(machine_opts, "dtb");
1842ff3de68SMarkus Armbruster     const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
185d1b93565SAlexander Graf 
186d1b93565SAlexander Graf     if (dtb_file) {
187d1b93565SAlexander Graf         char *filename;
188d1b93565SAlexander Graf         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
189d1b93565SAlexander Graf         if (!filename) {
190d1b93565SAlexander Graf             goto out;
191d1b93565SAlexander Graf         }
192d1b93565SAlexander Graf 
193d1b93565SAlexander Graf         fdt = load_device_tree(filename, &fdt_size);
194d1b93565SAlexander Graf         if (!fdt) {
195d1b93565SAlexander Graf             goto out;
196d1b93565SAlexander Graf         }
197d1b93565SAlexander Graf         goto done;
198d1b93565SAlexander Graf     }
1991db09b84Saurel32 
2002636fcb6SAlexander Graf     fdt = create_device_tree(&fdt_size);
2015cea8590SPaul Brook     if (fdt == NULL) {
2025cea8590SPaul Brook         goto out;
2035cea8590SPaul Brook     }
2041db09b84Saurel32 
2051db09b84Saurel32     /* Manipulate device tree in memory. */
2065a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 2);
2075a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 2);
20851b852b7SAlexander Graf 
2095a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, "/memory");
2105a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory");
2115a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
2121db09b84Saurel32                      sizeof(mem_reg_property));
2131db09b84Saurel32 
2145a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, "/chosen");
2153b989d49SAlexander Graf     if (initrd_size) {
2165a4348d1SPeter Crosthwaite         ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
2171db09b84Saurel32                                     initrd_base);
2183b989d49SAlexander Graf         if (ret < 0) {
2191db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
2203b989d49SAlexander Graf         }
2211db09b84Saurel32 
2225a4348d1SPeter Crosthwaite         ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
2231db09b84Saurel32                                     (initrd_base + initrd_size));
2243b989d49SAlexander Graf         if (ret < 0) {
2251db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
2263b989d49SAlexander Graf         }
227903585deSAlexander Graf 
228903585deSAlexander Graf     }
229903585deSAlexander Graf 
230903585deSAlexander Graf     if (kernel_base != -1ULL) {
231903585deSAlexander Graf         qemu_fdt_setprop_cells(fdt, "/chosen", "qemu,boot-kernel",
232903585deSAlexander Graf                                      kernel_base >> 32, kernel_base,
233903585deSAlexander Graf                                      kernel_size >> 32, kernel_size);
2343b989d49SAlexander Graf     }
2351db09b84Saurel32 
2365a4348d1SPeter Crosthwaite     ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
2373ef96221SMarcel Apfelbaum                                       machine->kernel_cmdline);
2381db09b84Saurel32     if (ret < 0)
2391db09b84Saurel32         fprintf(stderr, "couldn't set /chosen/bootargs\n");
2401db09b84Saurel32 
2411db09b84Saurel32     if (kvm_enabled()) {
242911d6e7aSAlexander Graf         /* Read out host's frequencies */
243911d6e7aSAlexander Graf         clock_freq = kvmppc_get_clockfreq();
244911d6e7aSAlexander Graf         tb_freq = kvmppc_get_tbfreq();
2455de6b46dSAlexander Graf 
2465de6b46dSAlexander Graf         /* indicate KVM hypercall interface */
2475a4348d1SPeter Crosthwaite         qemu_fdt_add_subnode(fdt, "/hypervisor");
2485a4348d1SPeter Crosthwaite         qemu_fdt_setprop_string(fdt, "/hypervisor", "compatible",
2495de6b46dSAlexander Graf                                 "linux,kvm");
2505de6b46dSAlexander Graf         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
2515a4348d1SPeter Crosthwaite         qemu_fdt_setprop(fdt, "/hypervisor", "hcall-instructions",
2525de6b46dSAlexander Graf                          hypercall, sizeof(hypercall));
2531a61a9aeSStuart Yoder         /* if KVM supports the idle hcall, set property indicating this */
2541a61a9aeSStuart Yoder         if (kvmppc_get_hasidle(env)) {
2555a4348d1SPeter Crosthwaite             qemu_fdt_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
2561a61a9aeSStuart Yoder         }
2571db09b84Saurel32     }
2581db09b84Saurel32 
259625e665bSAlexander Graf     /* Create CPU nodes */
2605a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, "/cpus");
2615a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1);
2625a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0);
263625e665bSAlexander Graf 
2641e3debf0SAlexander Graf     /* We need to generate the cpu nodes in reverse order, so Linux can pick
2651e3debf0SAlexander Graf        the first node as boot node and be happy */
2661e3debf0SAlexander Graf     for (i = smp_cpus - 1; i >= 0; i--) {
267440c8152SAndreas Färber         CPUState *cpu;
2680f20ba62SAlexey Kardashevskiy         PowerPCCPU *pcpu;
269621d05e3SAlexander Graf         char cpu_name[128];
2701d2e5c52SAlexander Graf         uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
27110f25a46SAlexander Graf 
272440c8152SAndreas Färber         cpu = qemu_get_cpu(i);
27355e5c285SAndreas Färber         if (cpu == NULL) {
2741e3debf0SAlexander Graf             continue;
2751e3debf0SAlexander Graf         }
276440c8152SAndreas Färber         env = cpu->env_ptr;
2770f20ba62SAlexey Kardashevskiy         pcpu = POWERPC_CPU(cpu);
2781e3debf0SAlexander Graf 
27955e5c285SAndreas Färber         snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x",
2800f20ba62SAlexey Kardashevskiy                  ppc_get_vcpu_dt_id(pcpu));
2815a4348d1SPeter Crosthwaite         qemu_fdt_add_subnode(fdt, cpu_name);
2825a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
2835a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
2845a4348d1SPeter Crosthwaite         qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
2850f20ba62SAlexey Kardashevskiy         qemu_fdt_setprop_cell(fdt, cpu_name, "reg",
2860f20ba62SAlexey Kardashevskiy                               ppc_get_vcpu_dt_id(pcpu));
2875a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size",
2881e3debf0SAlexander Graf                               env->dcache_line_size);
2895a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size",
2901e3debf0SAlexander Graf                               env->icache_line_size);
2915a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
2925a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
2935a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
29455e5c285SAndreas Färber         if (cpu->cpu_index) {
2955a4348d1SPeter Crosthwaite             qemu_fdt_setprop_string(fdt, cpu_name, "status", "disabled");
2965a4348d1SPeter Crosthwaite             qemu_fdt_setprop_string(fdt, cpu_name, "enable-method",
2975a4348d1SPeter Crosthwaite                                     "spin-table");
2985a4348d1SPeter Crosthwaite             qemu_fdt_setprop_u64(fdt, cpu_name, "cpu-release-addr",
2991d2e5c52SAlexander Graf                                  cpu_release_addr);
3001e3debf0SAlexander Graf         } else {
3015a4348d1SPeter Crosthwaite             qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay");
3021e3debf0SAlexander Graf         }
3031db09b84Saurel32     }
3041db09b84Saurel32 
3055a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, "/aliases");
3065da96624SAlexander Graf     /* XXX These should go into their respective devices' code */
307ed2bc496SAlexander Graf     snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
3085a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, soc);
3095a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, soc, "device_type", "soc");
3105a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb,
311ebb9518aSAlexander Graf                      sizeof(compatible_sb));
3125a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1);
3135a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1);
3145a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0,
3153627757eSAlexander Graf                            MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
3165da96624SAlexander Graf                            MPC8544_CCSRBAR_SIZE);
3175da96624SAlexander Graf     /* XXX should contain a reasonable value */
3185a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0);
3195da96624SAlexander Graf 
320dffb1dc2SBharat Bhushan     snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
3215a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, mpic);
3225a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, mpic, "device_type", "open-pic");
3235a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, mpic, "compatible", "fsl,mpic");
3245a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
325dffb1dc2SBharat Bhushan                            0x40000);
3265a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, mpic, "#address-cells", 0);
3275a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
3285a4348d1SPeter Crosthwaite     mpic_ph = qemu_fdt_alloc_phandle(fdt);
3295a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, mpic, "phandle", mpic_ph);
3305a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
3315a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
33219ac9deaSAlexander Graf 
3330cfc6e8dSAlexander Graf     /*
3340cfc6e8dSAlexander Graf      * We have to generate ser1 first, because Linux takes the first
3350cfc6e8dSAlexander Graf      * device it finds in the dt as serial output device. And we generate
3360cfc6e8dSAlexander Graf      * devices in reverse order to the dt.
3370cfc6e8dSAlexander Graf      */
33879c0ff2cSAlexander Graf     if (serial_hds[1]) {
339dffb1dc2SBharat Bhushan         dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
340a053a7ceSAlexander Graf                          soc, mpic, "serial1", 1, false);
34179c0ff2cSAlexander Graf     }
34279c0ff2cSAlexander Graf 
34379c0ff2cSAlexander Graf     if (serial_hds[0]) {
344dffb1dc2SBharat Bhushan         dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
345a053a7ceSAlexander Graf                          soc, mpic, "serial0", 0, true);
34679c0ff2cSAlexander Graf     }
3470cfc6e8dSAlexander Graf 
348ed2bc496SAlexander Graf     snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
349dffb1dc2SBharat Bhushan              MPC8544_UTIL_OFFSET);
3505a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, gutil);
3515a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
3525a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
3535a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
354f5038483SAlexander Graf 
355a911b7a9SAlexander Graf     snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
3565a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, msi);
3575a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
3585a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
3595a4348d1SPeter Crosthwaite     msi_ph = qemu_fdt_alloc_phandle(fdt);
3605a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
3615a4348d1SPeter Crosthwaite     qemu_fdt_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
3625a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, msi, "interrupts",
363a911b7a9SAlexander Graf         0xe0, 0x0,
364a911b7a9SAlexander Graf         0xe1, 0x0,
365a911b7a9SAlexander Graf         0xe2, 0x0,
366a911b7a9SAlexander Graf         0xe3, 0x0,
367a911b7a9SAlexander Graf         0xe4, 0x0,
368a911b7a9SAlexander Graf         0xe5, 0x0,
369a911b7a9SAlexander Graf         0xe6, 0x0,
370a911b7a9SAlexander Graf         0xe7, 0x0);
3715a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, msi, "phandle", msi_ph);
3725a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
373a911b7a9SAlexander Graf 
374ed2bc496SAlexander Graf     snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
3755a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, pci);
3765a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "cell-index", 0);
3775a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
3785a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, pci, "device_type", "pci");
3795a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
3800dbc0798SAlexander Graf                            0x0, 0x7);
3815a4348d1SPeter Crosthwaite     pci_map = pci_map_create(fdt, qemu_fdt_get_phandle(fdt, mpic),
382492ec48dSAlexander Graf                              params->pci_first_slot, params->pci_nr_slots,
383492ec48dSAlexander Graf                              &len);
3845a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, pci, "interrupt-map", pci_map, len);
3855a4348d1SPeter Crosthwaite     qemu_fdt_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
3865a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, pci, "interrupts", 24, 2);
3875a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, pci, "bus-range", 0, 255);
3883627757eSAlexander Graf     for (i = 0; i < 14; i++) {
3890dbc0798SAlexander Graf         pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
3900dbc0798SAlexander Graf     }
3915a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
3925a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
3935a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
3943627757eSAlexander Graf                            MPC8544_PCI_REGS_BASE, 0, 0x1000);
3955a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666);
3965a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1);
3975a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "#size-cells", 2);
3985a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3);
3995a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci);
4000dbc0798SAlexander Graf 
401*b88e77f4SAlexander Graf     if (params->has_mpc8xxx_gpio) {
402*b88e77f4SAlexander Graf         create_dt_mpc8xxx_gpio(fdt, soc, mpic);
403*b88e77f4SAlexander Graf     }
404*b88e77f4SAlexander Graf 
405e6eaabebSScott Wood     params->fixup_devtree(params, fdt);
406e6eaabebSScott Wood 
407e6eaabebSScott Wood     if (toplevel_compat) {
4085a4348d1SPeter Crosthwaite         qemu_fdt_setprop(fdt, "/", "compatible", toplevel_compat,
409e6eaabebSScott Wood                          strlen(toplevel_compat) + 1);
410e6eaabebSScott Wood     }
411e6eaabebSScott Wood 
412d1b93565SAlexander Graf done:
41328290f37SAlexander Graf     if (!dry_run) {
4145a4348d1SPeter Crosthwaite         qemu_fdt_dumpdtb(fdt, fdt_size);
41528290f37SAlexander Graf         cpu_physical_memory_write(addr, fdt, fdt_size);
416cba2026aSAlexander Graf     }
417cba2026aSAlexander Graf     ret = fdt_size;
4187ec632b4Spbrook 
4191db09b84Saurel32 out:
420347dd79dSAlexander Graf     g_free(pci_map);
4211db09b84Saurel32 
42204088adbSLiu Yu     return ret;
4231db09b84Saurel32 }
4241db09b84Saurel32 
42528290f37SAlexander Graf typedef struct DeviceTreeParams {
4263ef96221SMarcel Apfelbaum     MachineState *machine;
42728290f37SAlexander Graf     PPCE500Params params;
42828290f37SAlexander Graf     hwaddr addr;
42928290f37SAlexander Graf     hwaddr initrd_base;
43028290f37SAlexander Graf     hwaddr initrd_size;
431903585deSAlexander Graf     hwaddr kernel_base;
432903585deSAlexander Graf     hwaddr kernel_size;
43328290f37SAlexander Graf } DeviceTreeParams;
43428290f37SAlexander Graf 
43528290f37SAlexander Graf static void ppce500_reset_device_tree(void *opaque)
43628290f37SAlexander Graf {
43728290f37SAlexander Graf     DeviceTreeParams *p = opaque;
4383812c71fSAlexander Graf     ppce500_load_device_tree(p->machine, &p->params, p->addr, p->initrd_base,
439903585deSAlexander Graf                              p->initrd_size, p->kernel_base, p->kernel_size,
440903585deSAlexander Graf                              false);
44128290f37SAlexander Graf }
44228290f37SAlexander Graf 
4433ef96221SMarcel Apfelbaum static int ppce500_prep_device_tree(MachineState *machine,
44428290f37SAlexander Graf                                     PPCE500Params *params,
44528290f37SAlexander Graf                                     hwaddr addr,
44628290f37SAlexander Graf                                     hwaddr initrd_base,
447903585deSAlexander Graf                                     hwaddr initrd_size,
448903585deSAlexander Graf                                     hwaddr kernel_base,
449903585deSAlexander Graf                                     hwaddr kernel_size)
45028290f37SAlexander Graf {
45128290f37SAlexander Graf     DeviceTreeParams *p = g_new(DeviceTreeParams, 1);
4523ef96221SMarcel Apfelbaum     p->machine = machine;
45328290f37SAlexander Graf     p->params = *params;
45428290f37SAlexander Graf     p->addr = addr;
45528290f37SAlexander Graf     p->initrd_base = initrd_base;
45628290f37SAlexander Graf     p->initrd_size = initrd_size;
457903585deSAlexander Graf     p->kernel_base = kernel_base;
458903585deSAlexander Graf     p->kernel_size = kernel_size;
45928290f37SAlexander Graf 
46028290f37SAlexander Graf     qemu_register_reset(ppce500_reset_device_tree, p);
46128290f37SAlexander Graf 
46228290f37SAlexander Graf     /* Issue the device tree loader once, so that we get the size of the blob */
4633ef96221SMarcel Apfelbaum     return ppce500_load_device_tree(machine, params, addr, initrd_base,
464903585deSAlexander Graf                                     initrd_size, kernel_base, kernel_size,
465903585deSAlexander Graf                                     true);
46628290f37SAlexander Graf }
46728290f37SAlexander Graf 
468cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE.  */
469a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
470d1e256feSAlexander Graf {
471cba2026aSAlexander Graf     return 63 - clz64(size >> 10);
472d1e256feSAlexander Graf }
473d1e256feSAlexander Graf 
474cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env)
4753b989d49SAlexander Graf {
476cba2026aSAlexander Graf     struct boot_info *bi = env->load_info;
477cefd3cdbSBharat Bhushan     hwaddr dt_end;
478cba2026aSAlexander Graf     int ps;
4793b989d49SAlexander Graf 
480cba2026aSAlexander Graf     /* Our initial TLB entry needs to cover everything from 0 to
481cba2026aSAlexander Graf        the device tree top */
482cba2026aSAlexander Graf     dt_end = bi->dt_base + bi->dt_size;
483cba2026aSAlexander Graf     ps = booke206_page_size_to_tlb(dt_end) + 1;
484fb37c302SAlexander Graf     if (ps & 1) {
485fb37c302SAlexander Graf         /* e500v2 can only do even TLB size bits */
486fb37c302SAlexander Graf         ps++;
487fb37c302SAlexander Graf     }
488cefd3cdbSBharat Bhushan     return ps;
489cefd3cdbSBharat Bhushan }
490cefd3cdbSBharat Bhushan 
491cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env)
492cefd3cdbSBharat Bhushan {
493cefd3cdbSBharat Bhushan     int tsize;
494cefd3cdbSBharat Bhushan 
495cefd3cdbSBharat Bhushan     tsize = booke206_initial_map_tsize(env);
496cefd3cdbSBharat Bhushan     return (1ULL << 10 << tsize);
497cefd3cdbSBharat Bhushan }
498cefd3cdbSBharat Bhushan 
499cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env)
500cefd3cdbSBharat Bhushan {
501cefd3cdbSBharat Bhushan     ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
502cefd3cdbSBharat Bhushan     hwaddr size;
503cefd3cdbSBharat Bhushan     int ps;
504cefd3cdbSBharat Bhushan 
505cefd3cdbSBharat Bhushan     ps = booke206_initial_map_tsize(env);
506cba2026aSAlexander Graf     size = (ps << MAS1_TSIZE_SHIFT);
507d1e256feSAlexander Graf     tlb->mas1 = MAS1_VALID | size;
508cba2026aSAlexander Graf     tlb->mas2 = 0;
509cba2026aSAlexander Graf     tlb->mas7_3 = 0;
510d1e256feSAlexander Graf     tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
51193dd5e85SScott Wood 
51293dd5e85SScott Wood     env->tlb_dirty = true;
5133b989d49SAlexander Graf }
5143b989d49SAlexander Graf 
515b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque)
5165c145dacSAlexander Graf {
51738f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
518259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
5195c145dacSAlexander Graf 
520259186a7SAndreas Färber     cpu_reset(cs);
5215c145dacSAlexander Graf 
5225c145dacSAlexander Graf     /* Secondary CPU starts in halted state for now. Needs to change when
5235c145dacSAlexander Graf        implementing non-kernel boot. */
524259186a7SAndreas Färber     cs->halted = 1;
52527103424SAndreas Färber     cs->exception_index = EXCP_HLT;
5263b989d49SAlexander Graf }
5273b989d49SAlexander Graf 
528b3305981SScott Wood static void ppce500_cpu_reset(void *opaque)
5293b989d49SAlexander Graf {
53038f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
531259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
53238f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
5333b989d49SAlexander Graf     struct boot_info *bi = env->load_info;
5343b989d49SAlexander Graf 
535259186a7SAndreas Färber     cpu_reset(cs);
5363b989d49SAlexander Graf 
5373b989d49SAlexander Graf     /* Set initial guest state. */
538259186a7SAndreas Färber     cs->halted = 0;
5393b989d49SAlexander Graf     env->gpr[1] = (16<<20) - 8;
5403b989d49SAlexander Graf     env->gpr[3] = bi->dt_base;
541cefd3cdbSBharat Bhushan     env->gpr[4] = 0;
542cefd3cdbSBharat Bhushan     env->gpr[5] = 0;
543cefd3cdbSBharat Bhushan     env->gpr[6] = EPAPR_MAGIC;
544cefd3cdbSBharat Bhushan     env->gpr[7] = mmubooke_initial_mapsize(env);
545cefd3cdbSBharat Bhushan     env->gpr[8] = 0;
546cefd3cdbSBharat Bhushan     env->gpr[9] = 0;
5473b989d49SAlexander Graf     env->nip = bi->entry;
548cba2026aSAlexander Graf     mmubooke_create_initial_mapping(env);
5493b989d49SAlexander Graf }
5503b989d49SAlexander Graf 
551d85937e6SScott Wood static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,
55282fc73b6SScott Wood                                            qemu_irq **irqs)
55382fc73b6SScott Wood {
55482fc73b6SScott Wood     DeviceState *dev;
55582fc73b6SScott Wood     SysBusDevice *s;
55682fc73b6SScott Wood     int i, j, k;
55782fc73b6SScott Wood 
558e1766344SAndreas Färber     dev = qdev_create(NULL, TYPE_OPENPIC);
55982fc73b6SScott Wood     qdev_prop_set_uint32(dev, "model", params->mpic_version);
560d85937e6SScott Wood     qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
561d85937e6SScott Wood 
56282fc73b6SScott Wood     qdev_init_nofail(dev);
56382fc73b6SScott Wood     s = SYS_BUS_DEVICE(dev);
56482fc73b6SScott Wood 
56582fc73b6SScott Wood     k = 0;
56682fc73b6SScott Wood     for (i = 0; i < smp_cpus; i++) {
56782fc73b6SScott Wood         for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
56882fc73b6SScott Wood             sysbus_connect_irq(s, k++, irqs[i][j]);
56982fc73b6SScott Wood         }
57082fc73b6SScott Wood     }
57182fc73b6SScott Wood 
572d85937e6SScott Wood     return dev;
573d85937e6SScott Wood }
574d85937e6SScott Wood 
575d85937e6SScott Wood static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
576d85937e6SScott Wood                                           qemu_irq **irqs)
577d85937e6SScott Wood {
578d85937e6SScott Wood     DeviceState *dev;
579d85937e6SScott Wood     CPUState *cs;
580d85937e6SScott Wood     int r;
581d85937e6SScott Wood 
582dd49c038SAndreas Färber     dev = qdev_create(NULL, TYPE_KVM_OPENPIC);
583d85937e6SScott Wood     qdev_prop_set_uint32(dev, "model", params->mpic_version);
584d85937e6SScott Wood 
585d85937e6SScott Wood     r = qdev_init(dev);
586d85937e6SScott Wood     if (r) {
587d85937e6SScott Wood         return NULL;
588d85937e6SScott Wood     }
589d85937e6SScott Wood 
590bdc44640SAndreas Färber     CPU_FOREACH(cs) {
591d85937e6SScott Wood         if (kvm_openpic_connect_vcpu(dev, cs)) {
592d85937e6SScott Wood             fprintf(stderr, "%s: failed to connect vcpu to irqchip\n",
593d85937e6SScott Wood                     __func__);
594d85937e6SScott Wood             abort();
595d85937e6SScott Wood         }
596d85937e6SScott Wood     }
597d85937e6SScott Wood 
598d85937e6SScott Wood     return dev;
599d85937e6SScott Wood }
600d85937e6SScott Wood 
601d85937e6SScott Wood static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
602d85937e6SScott Wood                                    qemu_irq **irqs)
603d85937e6SScott Wood {
604d85937e6SScott Wood     qemu_irq *mpic;
605d85937e6SScott Wood     DeviceState *dev = NULL;
606d85937e6SScott Wood     SysBusDevice *s;
607d85937e6SScott Wood     int i;
608d85937e6SScott Wood 
609aa2ac1daSPeter Crosthwaite     mpic = g_new0(qemu_irq, 256);
610d85937e6SScott Wood 
611d85937e6SScott Wood     if (kvm_enabled()) {
61236ad0e94SMarkus Armbruster         QemuOpts *machine_opts = qemu_get_machine_opts();
61336ad0e94SMarkus Armbruster         bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
614d85937e6SScott Wood                                                 "kernel_irqchip", true);
61536ad0e94SMarkus Armbruster         bool irqchip_required = qemu_opt_get_bool(machine_opts,
616d85937e6SScott Wood                                                   "kernel_irqchip", false);
617d85937e6SScott Wood 
618d85937e6SScott Wood         if (irqchip_allowed) {
619d85937e6SScott Wood             dev = ppce500_init_mpic_kvm(params, irqs);
620d85937e6SScott Wood         }
621d85937e6SScott Wood 
622d85937e6SScott Wood         if (irqchip_required && !dev) {
623d85937e6SScott Wood             fprintf(stderr, "%s: irqchip requested but unavailable\n",
624d85937e6SScott Wood                     __func__);
625d85937e6SScott Wood             abort();
626d85937e6SScott Wood         }
627d85937e6SScott Wood     }
628d85937e6SScott Wood 
629d85937e6SScott Wood     if (!dev) {
630d85937e6SScott Wood         dev = ppce500_init_mpic_qemu(params, irqs);
631d85937e6SScott Wood     }
632d85937e6SScott Wood 
63382fc73b6SScott Wood     for (i = 0; i < 256; i++) {
63482fc73b6SScott Wood         mpic[i] = qdev_get_gpio_in(dev, i);
63582fc73b6SScott Wood     }
63682fc73b6SScott Wood 
637d85937e6SScott Wood     s = SYS_BUS_DEVICE(dev);
63882fc73b6SScott Wood     memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET,
63982fc73b6SScott Wood                                 s->mmio[0].memory);
64082fc73b6SScott Wood 
64182fc73b6SScott Wood     return mpic;
64282fc73b6SScott Wood }
64382fc73b6SScott Wood 
6443ef96221SMarcel Apfelbaum void ppce500_init(MachineState *machine, PPCE500Params *params)
6451db09b84Saurel32 {
64639186d8aSRichard Henderson     MemoryRegion *address_space_mem = get_system_memory();
6472646c133SAvi Kivity     MemoryRegion *ram = g_new(MemoryRegion, 1);
6481db09b84Saurel32     PCIBus *pci_bus;
649e2684c0bSAndreas Färber     CPUPPCState *env = NULL;
6503812c71fSAlexander Graf     uint64_t loadaddr;
6513812c71fSAlexander Graf     hwaddr kernel_base = -1LL;
6523812c71fSAlexander Graf     int kernel_size = 0;
6533812c71fSAlexander Graf     hwaddr dt_base = 0;
6543812c71fSAlexander Graf     hwaddr initrd_base = 0;
6553812c71fSAlexander Graf     int initrd_size = 0;
6563812c71fSAlexander Graf     hwaddr cur_base = 0;
6573812c71fSAlexander Graf     char *filename;
6583812c71fSAlexander Graf     hwaddr bios_entry = 0;
6593812c71fSAlexander Graf     target_long bios_size;
6603812c71fSAlexander Graf     struct boot_info *boot_info;
6613812c71fSAlexander Graf     int dt_size;
66282fc73b6SScott Wood     int i;
663d575a6ceSBharat Bhushan     /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and
664d575a6ceSBharat Bhushan      * 4 respectively */
665d575a6ceSBharat Bhushan     unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4};
666a915249fSAlexander Graf     qemu_irq **irqs, *mpic;
667be13cc7aSAlexander Graf     DeviceState *dev;
668e2684c0bSAndreas Färber     CPUPPCState *firstenv = NULL;
6693eddc1beSBharat Bhushan     MemoryRegion *ccsr_addr_space;
670dffb1dc2SBharat Bhushan     SysBusDevice *s;
6713eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
6721db09b84Saurel32 
673e61c36d5SAlexander Graf     /* Setup CPUs */
6743ef96221SMarcel Apfelbaum     if (machine->cpu_model == NULL) {
6753ef96221SMarcel Apfelbaum         machine->cpu_model = "e500v2_v30";
676ef250db6SAlexander Graf     }
677ef250db6SAlexander Graf 
678a915249fSAlexander Graf     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
679a915249fSAlexander Graf     irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
680e61c36d5SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
681397b457dSAndreas Färber         PowerPCCPU *cpu;
68255e5c285SAndreas Färber         CPUState *cs;
683e61c36d5SAlexander Graf         qemu_irq *input;
684397b457dSAndreas Färber 
6853ef96221SMarcel Apfelbaum         cpu = cpu_ppc_init(machine->cpu_model);
686397b457dSAndreas Färber         if (cpu == NULL) {
6871db09b84Saurel32             fprintf(stderr, "Unable to initialize CPU!\n");
6881db09b84Saurel32             exit(1);
6891db09b84Saurel32         }
690397b457dSAndreas Färber         env = &cpu->env;
69155e5c285SAndreas Färber         cs = CPU(cpu);
6921db09b84Saurel32 
693e61c36d5SAlexander Graf         if (!firstenv) {
694e61c36d5SAlexander Graf             firstenv = env;
695e61c36d5SAlexander Graf         }
696e61c36d5SAlexander Graf 
697a915249fSAlexander Graf         irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
698a915249fSAlexander Graf         input = (qemu_irq *)env->irq_inputs;
699a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
700a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
7016a450df9SAlexander Graf         env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
70268c2dd70SAlexander Graf         env->mpic_iack = MPC8544_CCSRBAR_BASE +
703bd25922eSScott Wood                          MPC8544_MPIC_REGS_OFFSET + 0xa0;
704e61c36d5SAlexander Graf 
705a34a92b9SAndreas Färber         ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
7063b989d49SAlexander Graf 
7073b989d49SAlexander Graf         /* Register reset handler */
7085c145dacSAlexander Graf         if (!i) {
7095c145dacSAlexander Graf             /* Primary CPU */
7105c145dacSAlexander Graf             struct boot_info *boot_info;
711e61c36d5SAlexander Graf             boot_info = g_malloc0(sizeof(struct boot_info));
712b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset, cpu);
713e61c36d5SAlexander Graf             env->load_info = boot_info;
7145c145dacSAlexander Graf         } else {
7155c145dacSAlexander Graf             /* Secondary CPUs */
716b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset_sec, cpu);
7175c145dacSAlexander Graf         }
718e61c36d5SAlexander Graf     }
719e61c36d5SAlexander Graf 
720e61c36d5SAlexander Graf     env = firstenv;
7213b989d49SAlexander Graf 
7221db09b84Saurel32     /* Fixup Memory size on a alignment boundary */
7231db09b84Saurel32     ram_size &= ~(RAM_SIZES_ALIGN - 1);
7243ef96221SMarcel Apfelbaum     machine->ram_size = ram_size;
7251db09b84Saurel32 
7261db09b84Saurel32     /* Register Memory */
727e938ba0cSShreyas B. Prabhu     memory_region_allocate_system_memory(ram, NULL, "mpc8544ds.ram", ram_size);
7282646c133SAvi Kivity     memory_region_add_subregion(address_space_mem, 0, ram);
7291db09b84Saurel32 
7303eddc1beSBharat Bhushan     dev = qdev_create(NULL, "e500-ccsr");
7313eddc1beSBharat Bhushan     object_property_add_child(qdev_get_machine(), "e500-ccsr",
7323eddc1beSBharat Bhushan                               OBJECT(dev), NULL);
7333eddc1beSBharat Bhushan     qdev_init_nofail(dev);
7343eddc1beSBharat Bhushan     ccsr = CCSR(dev);
7353eddc1beSBharat Bhushan     ccsr_addr_space = &ccsr->ccsr_space;
7363eddc1beSBharat Bhushan     memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
7373eddc1beSBharat Bhushan                                 ccsr_addr_space);
738dffb1dc2SBharat Bhushan 
73982fc73b6SScott Wood     mpic = ppce500_init_mpic(params, ccsr_addr_space, irqs);
7401db09b84Saurel32 
7411db09b84Saurel32     /* Serial */
7422d48377aSBlue Swirl     if (serial_hds[0]) {
7433eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
744cdbb912aSAlexander Graf                        0, mpic[42], 399193,
7452ff0c7c3SRichard Henderson                        serial_hds[0], DEVICE_BIG_ENDIAN);
7462d48377aSBlue Swirl     }
7471db09b84Saurel32 
7482d48377aSBlue Swirl     if (serial_hds[1]) {
7493eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
750cdbb912aSAlexander Graf                        0, mpic[42], 399193,
75159de4f98SBharat Bhushan                        serial_hds[1], DEVICE_BIG_ENDIAN);
7522d48377aSBlue Swirl     }
7531db09b84Saurel32 
754b0fb8423SAlexander Graf     /* General Utility device */
755dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "mpc8544-guts");
756dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
757dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
7583eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,
759dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
760b0fb8423SAlexander Graf 
7611db09b84Saurel32     /* PCI */
762dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "e500-pcihost");
763492ec48dSAlexander Graf     qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot);
7643016dca0SBharat Bhushan     qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]);
765dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
766dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
767d575a6ceSBharat Bhushan     for (i = 0; i < PCI_NUM_PINS; i++) {
768d575a6ceSBharat Bhushan         sysbus_connect_irq(s, i, mpic[pci_irq_nrs[i]]);
769d575a6ceSBharat Bhushan     }
770d575a6ceSBharat Bhushan 
7713eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
772dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
773dffb1dc2SBharat Bhushan 
774d461e3b9SAlexander Graf     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
7751db09b84Saurel32     if (!pci_bus)
7761db09b84Saurel32         printf("couldn't create PCI controller!\n");
7771db09b84Saurel32 
7781356b98dSAndreas Färber     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO);
7791db09b84Saurel32 
7801db09b84Saurel32     if (pci_bus) {
7811db09b84Saurel32         /* Register network interfaces. */
7821db09b84Saurel32         for (i = 0; i < nb_nics; i++) {
78329b358f9SDavid Gibson             pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL);
7841db09b84Saurel32         }
7851db09b84Saurel32     }
7861db09b84Saurel32 
7875c145dacSAlexander Graf     /* Register spinning region */
7885c145dacSAlexander Graf     sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
7895c145dacSAlexander Graf 
7903812c71fSAlexander Graf     if (cur_base < (32 * 1024 * 1024)) {
7913812c71fSAlexander Graf         /* u-boot occupies memory up to 32MB, so load blobs above */
7923812c71fSAlexander Graf         cur_base = (32 * 1024 * 1024);
7933812c71fSAlexander Graf     }
7943812c71fSAlexander Graf 
795*b88e77f4SAlexander Graf     if (params->has_mpc8xxx_gpio) {
796*b88e77f4SAlexander Graf         dev = qdev_create(NULL, "mpc8xxx_gpio");
797*b88e77f4SAlexander Graf         s = SYS_BUS_DEVICE(dev);
798*b88e77f4SAlexander Graf         qdev_init_nofail(dev);
799*b88e77f4SAlexander Graf         sysbus_connect_irq(s, 0, mpic[MPC8XXX_GPIO_IRQ]);
800*b88e77f4SAlexander Graf         memory_region_add_subregion(ccsr_addr_space, MPC8XXX_GPIO_OFFSET,
801*b88e77f4SAlexander Graf                                     sysbus_mmio_get_region(s, 0));
802*b88e77f4SAlexander Graf     }
803*b88e77f4SAlexander Graf 
8041db09b84Saurel32     /* Load kernel. */
8053ef96221SMarcel Apfelbaum     if (machine->kernel_filename) {
8063812c71fSAlexander Graf         kernel_base = cur_base;
8073812c71fSAlexander Graf         kernel_size = load_image_targphys(machine->kernel_filename,
8083812c71fSAlexander Graf                                           cur_base,
8093812c71fSAlexander Graf                                           ram_size - cur_base);
8101db09b84Saurel32         if (kernel_size < 0) {
8111db09b84Saurel32             fprintf(stderr, "qemu: could not load kernel '%s'\n",
8123ef96221SMarcel Apfelbaum                     machine->kernel_filename);
8131db09b84Saurel32             exit(1);
8141db09b84Saurel32         }
815528e536eSAlexander Graf 
8163812c71fSAlexander Graf         cur_base += kernel_size;
8171db09b84Saurel32     }
8181db09b84Saurel32 
8191db09b84Saurel32     /* Load initrd. */
8203ef96221SMarcel Apfelbaum     if (machine->initrd_filename) {
821528e536eSAlexander Graf         initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
8223ef96221SMarcel Apfelbaum         initrd_size = load_image_targphys(machine->initrd_filename, initrd_base,
823d7585251Spbrook                                           ram_size - initrd_base);
8241db09b84Saurel32 
8251db09b84Saurel32         if (initrd_size < 0) {
8261db09b84Saurel32             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
8273ef96221SMarcel Apfelbaum                     machine->initrd_filename);
8281db09b84Saurel32             exit(1);
8291db09b84Saurel32         }
830528e536eSAlexander Graf 
831528e536eSAlexander Graf         cur_base = initrd_base + initrd_size;
8321db09b84Saurel32     }
8331db09b84Saurel32 
8343812c71fSAlexander Graf     /*
8353812c71fSAlexander Graf      * Smart firmware defaults ahead!
8363812c71fSAlexander Graf      *
8373812c71fSAlexander Graf      * We follow the following table to select which payload we execute.
8383812c71fSAlexander Graf      *
8393812c71fSAlexander Graf      *  -kernel | -bios | payload
8403812c71fSAlexander Graf      * ---------+-------+---------
8413812c71fSAlexander Graf      *     N    |   Y   | u-boot
8423812c71fSAlexander Graf      *     N    |   N   | u-boot
8433812c71fSAlexander Graf      *     Y    |   Y   | u-boot
8443812c71fSAlexander Graf      *     Y    |   N   | kernel
8453812c71fSAlexander Graf      *
8463812c71fSAlexander Graf      * This ensures backwards compatibility with how we used to expose
8473812c71fSAlexander Graf      * -kernel to users but allows them to run through u-boot as well.
8483812c71fSAlexander Graf      */
8493812c71fSAlexander Graf     if (bios_name == NULL) {
8503ef96221SMarcel Apfelbaum         if (machine->kernel_filename) {
8513812c71fSAlexander Graf             bios_name = machine->kernel_filename;
8523812c71fSAlexander Graf         } else {
8533812c71fSAlexander Graf             bios_name = "u-boot.e500";
8543812c71fSAlexander Graf         }
8553812c71fSAlexander Graf     }
8563812c71fSAlexander Graf     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
8573812c71fSAlexander Graf 
8583812c71fSAlexander Graf     bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL,
8593812c71fSAlexander Graf                          1, ELF_MACHINE, 0);
8603812c71fSAlexander Graf     if (bios_size < 0) {
8613812c71fSAlexander Graf         /*
8623812c71fSAlexander Graf          * Hrm. No ELF image? Try a uImage, maybe someone is giving us an
8633812c71fSAlexander Graf          * ePAPR compliant kernel
8643812c71fSAlexander Graf          */
86525bda50aSMax Filippov         kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
86625bda50aSMax Filippov                                   NULL, NULL);
8673812c71fSAlexander Graf         if (kernel_size < 0) {
8683812c71fSAlexander Graf             fprintf(stderr, "qemu: could not load firmware '%s'\n", filename);
8693812c71fSAlexander Graf             exit(1);
8703812c71fSAlexander Graf         }
8713812c71fSAlexander Graf     }
8723812c71fSAlexander Graf 
8733812c71fSAlexander Graf     /* Reserve space for dtb */
8743812c71fSAlexander Graf     dt_base = (loadaddr + bios_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
8755c145dacSAlexander Graf 
8763ef96221SMarcel Apfelbaum     dt_size = ppce500_prep_device_tree(machine, params, dt_base,
877903585deSAlexander Graf                                        initrd_base, initrd_size,
8783812c71fSAlexander Graf                                        kernel_base, kernel_size);
879cba2026aSAlexander Graf     if (dt_size < 0) {
8801db09b84Saurel32         fprintf(stderr, "couldn't load device tree\n");
8811db09b84Saurel32         exit(1);
8821db09b84Saurel32     }
883b8dec144SAlexander Graf     assert(dt_size < DTB_MAX_SIZE);
8841db09b84Saurel32 
885e61c36d5SAlexander Graf     boot_info = env->load_info;
8863812c71fSAlexander Graf     boot_info->entry = bios_entry;
8873b989d49SAlexander Graf     boot_info->dt_base = dt_base;
888cba2026aSAlexander Graf     boot_info->dt_size = dt_size;
8891db09b84Saurel32 
8903b989d49SAlexander Graf     if (kvm_enabled()) {
8911db09b84Saurel32         kvmppc_init();
8923b989d49SAlexander Graf     }
8931db09b84Saurel32 }
8943eddc1beSBharat Bhushan 
8953eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev)
8963eddc1beSBharat Bhushan {
8973eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
8983eddc1beSBharat Bhushan 
8993eddc1beSBharat Bhushan     ccsr = CCSR(dev);
90040c5dce9SPaolo Bonzini     memory_region_init(&ccsr->ccsr_space, OBJECT(ccsr), "e500-ccsr",
9013eddc1beSBharat Bhushan                        MPC8544_CCSRBAR_SIZE);
9023eddc1beSBharat Bhushan     return 0;
9033eddc1beSBharat Bhushan }
9043eddc1beSBharat Bhushan 
9053eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data)
9063eddc1beSBharat Bhushan {
9073eddc1beSBharat Bhushan     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
9083eddc1beSBharat Bhushan     k->init = e500_ccsr_initfn;
9093eddc1beSBharat Bhushan }
9103eddc1beSBharat Bhushan 
9113eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = {
9123eddc1beSBharat Bhushan     .name          = TYPE_CCSR,
9133eddc1beSBharat Bhushan     .parent        = TYPE_SYS_BUS_DEVICE,
9143eddc1beSBharat Bhushan     .instance_size = sizeof(PPCE500CCSRState),
9153eddc1beSBharat Bhushan     .class_init    = e500_ccsr_class_init,
9163eddc1beSBharat Bhushan };
9173eddc1beSBharat Bhushan 
9183eddc1beSBharat Bhushan static void e500_register_types(void)
9193eddc1beSBharat Bhushan {
9203eddc1beSBharat Bhushan     type_register_static(&e500_ccsr_info);
9213eddc1beSBharat Bhushan }
9223eddc1beSBharat Bhushan 
9233eddc1beSBharat Bhushan type_init(e500_register_types)
924