xref: /qemu/hw/ppc/e500.c (revision 1a61a9ae61cdf7b7d24c3eb711fe772c196c235e)
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"
24488cb996SGerd Hoffmann #include "hw/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"
314a18e7c9SScott Wood #include "hw/openpic.h"
324a18e7c9SScott Wood #include "hw/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"
389e2c1298SAlexander Graf #include "hw/ppce500_pci.h"
391db09b84Saurel32 
401db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
411db09b84Saurel32 #define UIMAGE_LOAD_BASE           0
429dd5eba1SScott Wood #define DTC_LOAD_PAD               0x1800000
4375bb6589SLiu Yu #define DTC_PAD_MASK               0xFFFFF
4475bb6589SLiu Yu #define INITRD_LOAD_PAD            0x2000000
4575bb6589SLiu Yu #define INITRD_PAD_MASK            0xFFFFFF
461db09b84Saurel32 
471db09b84Saurel32 #define RAM_SIZES_ALIGN            (64UL << 20)
481db09b84Saurel32 
49b3305981SScott Wood /* TODO: parameterize */
50ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE       0xE0000000ULL
51ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE       0x00100000ULL
52dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET   0x40000ULL
53a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET   0x41600ULL
54dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL
55dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL
56dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET    0x8000ULL
57dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE      (MPC8544_CCSRBAR_BASE + \
58dffb1dc2SBharat Bhushan                                     MPC8544_PCI_REGS_OFFSET)
59ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE      0x1000ULL
60ed2bc496SAlexander Graf #define MPC8544_PCI_IO             0xE1000000ULL
61dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET        0xe0000ULL
62ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE          0xEF000000ULL
631db09b84Saurel32 
643b989d49SAlexander Graf struct boot_info
653b989d49SAlexander Graf {
663b989d49SAlexander Graf     uint32_t dt_base;
67cba2026aSAlexander Graf     uint32_t dt_size;
683b989d49SAlexander Graf     uint32_t entry;
693b989d49SAlexander Graf };
703b989d49SAlexander Graf 
71347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot,
72347dd79dSAlexander Graf                                 int nr_slots, int *len)
730dbc0798SAlexander Graf {
74347dd79dSAlexander Graf     int i = 0;
75347dd79dSAlexander Graf     int slot;
76347dd79dSAlexander Graf     int pci_irq;
779e2c1298SAlexander Graf     int host_irq;
78347dd79dSAlexander Graf     int last_slot = first_slot + nr_slots;
79347dd79dSAlexander Graf     uint32_t *pci_map;
800dbc0798SAlexander Graf 
81347dd79dSAlexander Graf     *len = nr_slots * 4 * 7 * sizeof(uint32_t);
82347dd79dSAlexander Graf     pci_map = g_malloc(*len);
83347dd79dSAlexander Graf 
84347dd79dSAlexander Graf     for (slot = first_slot; slot < last_slot; slot++) {
85347dd79dSAlexander Graf         for (pci_irq = 0; pci_irq < 4; pci_irq++) {
86347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(slot << 11);
87347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
88347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
89347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(pci_irq + 1);
90347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(mpic);
919e2c1298SAlexander Graf             host_irq = ppce500_pci_map_irq_slot(slot, pci_irq);
929e2c1298SAlexander Graf             pci_map[i++] = cpu_to_be32(host_irq + 1);
93347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x1);
940dbc0798SAlexander Graf         }
950dbc0798SAlexander Graf     }
960dbc0798SAlexander Graf 
97347dd79dSAlexander Graf     assert((i * sizeof(uint32_t)) == *len);
98347dd79dSAlexander Graf 
99347dd79dSAlexander Graf     return pci_map;
100347dd79dSAlexander Graf }
101347dd79dSAlexander Graf 
102a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset,
103a053a7ceSAlexander Graf                              const char *soc, const char *mpic,
104a053a7ceSAlexander Graf                              const char *alias, int idx, bool defcon)
105a053a7ceSAlexander Graf {
106a053a7ceSAlexander Graf     char ser[128];
107a053a7ceSAlexander Graf 
108a053a7ceSAlexander Graf     snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset);
109a053a7ceSAlexander Graf     qemu_devtree_add_subnode(fdt, ser);
110a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, ser, "device_type", "serial");
111a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550");
112a053a7ceSAlexander Graf     qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100);
113a053a7ceSAlexander Graf     qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx);
114a053a7ceSAlexander Graf     qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0);
1157e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2);
116a053a7ceSAlexander Graf     qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
117a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", alias, ser);
118a053a7ceSAlexander Graf 
119a053a7ceSAlexander Graf     if (defcon) {
120a053a7ceSAlexander Graf         qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
121a053a7ceSAlexander Graf     }
122a053a7ceSAlexander Graf }
123a053a7ceSAlexander Graf 
124b3305981SScott Wood static int ppce500_load_device_tree(CPUPPCState *env,
125e6eaabebSScott Wood                                     PPCE500Params *params,
126a8170e5eSAvi Kivity                                     hwaddr addr,
127a8170e5eSAvi Kivity                                     hwaddr initrd_base,
128a8170e5eSAvi Kivity                                     hwaddr initrd_size)
1291db09b84Saurel32 {
130dbf916d8SAurelien Jarno     int ret = -1;
131e6eaabebSScott Wood     uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) };
1327ec632b4Spbrook     int fdt_size;
133dbf916d8SAurelien Jarno     void *fdt;
1345de6b46dSAlexander Graf     uint8_t hypercall[16];
135911d6e7aSAlexander Graf     uint32_t clock_freq = 400000000;
136911d6e7aSAlexander Graf     uint32_t tb_freq = 400000000;
137621d05e3SAlexander Graf     int i;
138e6eaabebSScott Wood     const char *toplevel_compat = NULL; /* user override */
139ebb9518aSAlexander Graf     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
1405da96624SAlexander Graf     char soc[128];
14119ac9deaSAlexander Graf     char mpic[128];
14219ac9deaSAlexander Graf     uint32_t mpic_ph;
143a911b7a9SAlexander Graf     uint32_t msi_ph;
144f5038483SAlexander Graf     char gutil[128];
1450dbc0798SAlexander Graf     char pci[128];
146a911b7a9SAlexander Graf     char msi[128];
147347dd79dSAlexander Graf     uint32_t *pci_map = NULL;
148347dd79dSAlexander Graf     int len;
1493627757eSAlexander Graf     uint32_t pci_ranges[14] =
1503627757eSAlexander Graf         {
1513627757eSAlexander Graf             0x2000000, 0x0, 0xc0000000,
1523627757eSAlexander Graf             0x0, 0xc0000000,
1533627757eSAlexander Graf             0x0, 0x20000000,
1543627757eSAlexander Graf 
1553627757eSAlexander Graf             0x1000000, 0x0, 0x0,
1563627757eSAlexander Graf             0x0, 0xe1000000,
1573627757eSAlexander Graf             0x0, 0x10000,
1583627757eSAlexander Graf         };
15925b42708SAlexander Graf     QemuOpts *machine_opts;
160d1b93565SAlexander Graf     const char *dtb_file = NULL;
161d1b93565SAlexander Graf 
162d1b93565SAlexander Graf     machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
163d1b93565SAlexander Graf     if (machine_opts) {
164d1b93565SAlexander Graf         dtb_file = qemu_opt_get(machine_opts, "dtb");
165e6eaabebSScott Wood         toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
166d1b93565SAlexander Graf     }
167d1b93565SAlexander Graf 
168d1b93565SAlexander Graf     if (dtb_file) {
169d1b93565SAlexander Graf         char *filename;
170d1b93565SAlexander Graf         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
171d1b93565SAlexander Graf         if (!filename) {
172d1b93565SAlexander Graf             goto out;
173d1b93565SAlexander Graf         }
174d1b93565SAlexander Graf 
175d1b93565SAlexander Graf         fdt = load_device_tree(filename, &fdt_size);
176d1b93565SAlexander Graf         if (!fdt) {
177d1b93565SAlexander Graf             goto out;
178d1b93565SAlexander Graf         }
179d1b93565SAlexander Graf         goto done;
180d1b93565SAlexander Graf     }
1811db09b84Saurel32 
1822636fcb6SAlexander Graf     fdt = create_device_tree(&fdt_size);
1835cea8590SPaul Brook     if (fdt == NULL) {
1845cea8590SPaul Brook         goto out;
1855cea8590SPaul Brook     }
1861db09b84Saurel32 
1871db09b84Saurel32     /* Manipulate device tree in memory. */
1883627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);
1893627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);
19051b852b7SAlexander Graf 
191dd0bcfcaSAlexander Graf     qemu_devtree_add_subnode(fdt, "/memory");
192dd0bcfcaSAlexander Graf     qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
193dd0bcfcaSAlexander Graf     qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
1941db09b84Saurel32                          sizeof(mem_reg_property));
1951db09b84Saurel32 
196f5231aafSAlexander Graf     qemu_devtree_add_subnode(fdt, "/chosen");
1973b989d49SAlexander Graf     if (initrd_size) {
1981db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
1991db09b84Saurel32                                         initrd_base);
2003b989d49SAlexander Graf         if (ret < 0) {
2011db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
2023b989d49SAlexander Graf         }
2031db09b84Saurel32 
2041db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
2051db09b84Saurel32                                         (initrd_base + initrd_size));
2063b989d49SAlexander Graf         if (ret < 0) {
2071db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
2083b989d49SAlexander Graf         }
2093b989d49SAlexander Graf     }
2101db09b84Saurel32 
2111db09b84Saurel32     ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
212e6eaabebSScott Wood                                       params->kernel_cmdline);
2131db09b84Saurel32     if (ret < 0)
2141db09b84Saurel32         fprintf(stderr, "couldn't set /chosen/bootargs\n");
2151db09b84Saurel32 
2161db09b84Saurel32     if (kvm_enabled()) {
217911d6e7aSAlexander Graf         /* Read out host's frequencies */
218911d6e7aSAlexander Graf         clock_freq = kvmppc_get_clockfreq();
219911d6e7aSAlexander Graf         tb_freq = kvmppc_get_tbfreq();
2205de6b46dSAlexander Graf 
2215de6b46dSAlexander Graf         /* indicate KVM hypercall interface */
222d50f71a5SAlexander Graf         qemu_devtree_add_subnode(fdt, "/hypervisor");
2235de6b46dSAlexander Graf         qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
2245de6b46dSAlexander Graf                                     "linux,kvm");
2255de6b46dSAlexander Graf         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
2265de6b46dSAlexander Graf         qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
2275de6b46dSAlexander Graf                              hypercall, sizeof(hypercall));
228*1a61a9aeSStuart Yoder         /* if KVM supports the idle hcall, set property indicating this */
229*1a61a9aeSStuart Yoder         if (kvmppc_get_hasidle(env)) {
230*1a61a9aeSStuart Yoder             qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
231*1a61a9aeSStuart Yoder         }
2321db09b84Saurel32     }
2331db09b84Saurel32 
234625e665bSAlexander Graf     /* Create CPU nodes */
235625e665bSAlexander Graf     qemu_devtree_add_subnode(fdt, "/cpus");
236625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);
237625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);
238625e665bSAlexander Graf 
2391e3debf0SAlexander Graf     /* We need to generate the cpu nodes in reverse order, so Linux can pick
2401e3debf0SAlexander Graf        the first node as boot node and be happy */
2411e3debf0SAlexander Graf     for (i = smp_cpus - 1; i >= 0; i--) {
242621d05e3SAlexander Graf         char cpu_name[128];
2431d2e5c52SAlexander Graf         uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
24410f25a46SAlexander Graf 
2451e3debf0SAlexander Graf         for (env = first_cpu; env != NULL; env = env->next_cpu) {
2461e3debf0SAlexander Graf             if (env->cpu_index == i) {
2471e3debf0SAlexander Graf                 break;
2481e3debf0SAlexander Graf             }
249621d05e3SAlexander Graf         }
250911d6e7aSAlexander Graf 
2511e3debf0SAlexander Graf         if (!env) {
2521e3debf0SAlexander Graf             continue;
2531e3debf0SAlexander Graf         }
2541e3debf0SAlexander Graf 
2551e3debf0SAlexander Graf         snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index);
2561e3debf0SAlexander Graf         qemu_devtree_add_subnode(fdt, cpu_name);
2571e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
2581e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
2591e3debf0SAlexander Graf         qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
2601e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index);
2611e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
2621e3debf0SAlexander Graf                                   env->dcache_line_size);
2631e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
2641e3debf0SAlexander Graf                                   env->icache_line_size);
2651e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
2661e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
2671e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
2681e3debf0SAlexander Graf         if (env->cpu_index) {
2691e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
2701e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
2711d2e5c52SAlexander Graf             qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
2721d2e5c52SAlexander Graf                                      cpu_release_addr);
2731e3debf0SAlexander Graf         } else {
2741e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
2751e3debf0SAlexander Graf         }
2761db09b84Saurel32     }
2771db09b84Saurel32 
2780cfc6e8dSAlexander Graf     qemu_devtree_add_subnode(fdt, "/aliases");
2795da96624SAlexander Graf     /* XXX These should go into their respective devices' code */
280ed2bc496SAlexander Graf     snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
2815da96624SAlexander Graf     qemu_devtree_add_subnode(fdt, soc);
2825da96624SAlexander Graf     qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");
283ebb9518aSAlexander Graf     qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,
284ebb9518aSAlexander Graf                          sizeof(compatible_sb));
2855da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);
2865da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);
2873627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,
2883627757eSAlexander Graf                                MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
2895da96624SAlexander Graf                                MPC8544_CCSRBAR_SIZE);
2905da96624SAlexander Graf     /* XXX should contain a reasonable value */
2915da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);
2925da96624SAlexander Graf 
293dffb1dc2SBharat Bhushan     snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
29419ac9deaSAlexander Graf     qemu_devtree_add_subnode(fdt, mpic);
29519ac9deaSAlexander Graf     qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
2967e99826cSAlexander Graf     qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic");
297dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
298dffb1dc2SBharat Bhushan                                0x40000);
29919ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
3007e99826cSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
30119ac9deaSAlexander Graf     mpic_ph = qemu_devtree_alloc_phandle(fdt);
30219ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);
30319ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
30419ac9deaSAlexander Graf     qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
30519ac9deaSAlexander Graf 
3060cfc6e8dSAlexander Graf     /*
3070cfc6e8dSAlexander Graf      * We have to generate ser1 first, because Linux takes the first
3080cfc6e8dSAlexander Graf      * device it finds in the dt as serial output device. And we generate
3090cfc6e8dSAlexander Graf      * devices in reverse order to the dt.
3100cfc6e8dSAlexander Graf      */
311dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
312a053a7ceSAlexander Graf                      soc, mpic, "serial1", 1, false);
313dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
314a053a7ceSAlexander Graf                      soc, mpic, "serial0", 0, true);
3150cfc6e8dSAlexander Graf 
316ed2bc496SAlexander Graf     snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
317dffb1dc2SBharat Bhushan              MPC8544_UTIL_OFFSET);
318f5038483SAlexander Graf     qemu_devtree_add_subnode(fdt, gutil);
319f5038483SAlexander Graf     qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
320dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
321f5038483SAlexander Graf     qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
322f5038483SAlexander Graf 
323a911b7a9SAlexander Graf     snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
324a911b7a9SAlexander Graf     qemu_devtree_add_subnode(fdt, msi);
325a911b7a9SAlexander Graf     qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
326a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
327a911b7a9SAlexander Graf     msi_ph = qemu_devtree_alloc_phandle(fdt);
328a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
329a911b7a9SAlexander Graf     qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
330a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "interrupts",
331a911b7a9SAlexander Graf         0xe0, 0x0,
332a911b7a9SAlexander Graf         0xe1, 0x0,
333a911b7a9SAlexander Graf         0xe2, 0x0,
334a911b7a9SAlexander Graf         0xe3, 0x0,
335a911b7a9SAlexander Graf         0xe4, 0x0,
336a911b7a9SAlexander Graf         0xe5, 0x0,
337a911b7a9SAlexander Graf         0xe6, 0x0,
338a911b7a9SAlexander Graf         0xe7, 0x0);
339a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);
340a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
341a911b7a9SAlexander Graf 
342ed2bc496SAlexander Graf     snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
3430dbc0798SAlexander Graf     qemu_devtree_add_subnode(fdt, pci);
3440dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
3450dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
3460dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
3470dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
3480dbc0798SAlexander Graf                                0x0, 0x7);
349347dd79dSAlexander Graf     pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic),
350492ec48dSAlexander Graf                              params->pci_first_slot, params->pci_nr_slots,
351492ec48dSAlexander Graf                              &len);
352347dd79dSAlexander Graf     qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len);
3530dbc0798SAlexander Graf     qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
3547e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
3550dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
3563627757eSAlexander Graf     for (i = 0; i < 14; i++) {
3570dbc0798SAlexander Graf         pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
3580dbc0798SAlexander Graf     }
359a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
3600dbc0798SAlexander Graf     qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
3613627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
3623627757eSAlexander Graf                                MPC8544_PCI_REGS_BASE, 0, 0x1000);
3630dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);
3640dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);
3650dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);
3660dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);
3670dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);
3680dbc0798SAlexander Graf 
369e6eaabebSScott Wood     params->fixup_devtree(params, fdt);
370e6eaabebSScott Wood 
371e6eaabebSScott Wood     if (toplevel_compat) {
372e6eaabebSScott Wood         qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,
373e6eaabebSScott Wood                              strlen(toplevel_compat) + 1);
374e6eaabebSScott Wood     }
375e6eaabebSScott Wood 
376d1b93565SAlexander Graf done:
37771193433SAlexander Graf     qemu_devtree_dumpdtb(fdt, fdt_size);
37804088adbSLiu Yu     ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
379cba2026aSAlexander Graf     if (ret < 0) {
380cba2026aSAlexander Graf         goto out;
381cba2026aSAlexander Graf     }
3827267c094SAnthony Liguori     g_free(fdt);
383cba2026aSAlexander Graf     ret = fdt_size;
3847ec632b4Spbrook 
3851db09b84Saurel32 out:
386347dd79dSAlexander Graf     g_free(pci_map);
3871db09b84Saurel32 
38804088adbSLiu Yu     return ret;
3891db09b84Saurel32 }
3901db09b84Saurel32 
391cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE.  */
392a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
393d1e256feSAlexander Graf {
394cba2026aSAlexander Graf     return 63 - clz64(size >> 10);
395d1e256feSAlexander Graf }
396d1e256feSAlexander Graf 
397cba2026aSAlexander Graf static void mmubooke_create_initial_mapping(CPUPPCState *env)
3983b989d49SAlexander Graf {
399cba2026aSAlexander Graf     struct boot_info *bi = env->load_info;
400d1e256feSAlexander Graf     ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
401a8170e5eSAvi Kivity     hwaddr size, dt_end;
402cba2026aSAlexander Graf     int ps;
4033b989d49SAlexander Graf 
404cba2026aSAlexander Graf     /* Our initial TLB entry needs to cover everything from 0 to
405cba2026aSAlexander Graf        the device tree top */
406cba2026aSAlexander Graf     dt_end = bi->dt_base + bi->dt_size;
407cba2026aSAlexander Graf     ps = booke206_page_size_to_tlb(dt_end) + 1;
408fb37c302SAlexander Graf     if (ps & 1) {
409fb37c302SAlexander Graf         /* e500v2 can only do even TLB size bits */
410fb37c302SAlexander Graf         ps++;
411fb37c302SAlexander Graf     }
412cba2026aSAlexander Graf     size = (ps << MAS1_TSIZE_SHIFT);
413d1e256feSAlexander Graf     tlb->mas1 = MAS1_VALID | size;
414cba2026aSAlexander Graf     tlb->mas2 = 0;
415cba2026aSAlexander Graf     tlb->mas7_3 = 0;
416d1e256feSAlexander Graf     tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
41793dd5e85SScott Wood 
41893dd5e85SScott Wood     env->tlb_dirty = true;
4193b989d49SAlexander Graf }
4203b989d49SAlexander Graf 
421b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque)
4225c145dacSAlexander Graf {
42338f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
42438f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4255c145dacSAlexander Graf 
42638f92da6SAndreas Färber     cpu_reset(CPU(cpu));
4275c145dacSAlexander Graf 
4285c145dacSAlexander Graf     /* Secondary CPU starts in halted state for now. Needs to change when
4295c145dacSAlexander Graf        implementing non-kernel boot. */
4305c145dacSAlexander Graf     env->halted = 1;
4315c145dacSAlexander Graf     env->exception_index = EXCP_HLT;
4323b989d49SAlexander Graf }
4333b989d49SAlexander Graf 
434b3305981SScott Wood static void ppce500_cpu_reset(void *opaque)
4353b989d49SAlexander Graf {
43638f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
43738f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4383b989d49SAlexander Graf     struct boot_info *bi = env->load_info;
4393b989d49SAlexander Graf 
44038f92da6SAndreas Färber     cpu_reset(CPU(cpu));
4413b989d49SAlexander Graf 
4423b989d49SAlexander Graf     /* Set initial guest state. */
4435c145dacSAlexander Graf     env->halted = 0;
4443b989d49SAlexander Graf     env->gpr[1] = (16<<20) - 8;
4453b989d49SAlexander Graf     env->gpr[3] = bi->dt_base;
4463b989d49SAlexander Graf     env->nip = bi->entry;
447cba2026aSAlexander Graf     mmubooke_create_initial_mapping(env);
4483b989d49SAlexander Graf }
4493b989d49SAlexander Graf 
450e6eaabebSScott Wood void ppce500_init(PPCE500Params *params)
4511db09b84Saurel32 {
45239186d8aSRichard Henderson     MemoryRegion *address_space_mem = get_system_memory();
4532646c133SAvi Kivity     MemoryRegion *ram = g_new(MemoryRegion, 1);
4541db09b84Saurel32     PCIBus *pci_bus;
455e2684c0bSAndreas Färber     CPUPPCState *env = NULL;
4561db09b84Saurel32     uint64_t elf_entry;
4571db09b84Saurel32     uint64_t elf_lowaddr;
458a8170e5eSAvi Kivity     hwaddr entry=0;
459a8170e5eSAvi Kivity     hwaddr loadaddr=UIMAGE_LOAD_BASE;
4601db09b84Saurel32     target_long kernel_size=0;
46175bb6589SLiu Yu     target_ulong dt_base = 0;
46275bb6589SLiu Yu     target_ulong initrd_base = 0;
4631db09b84Saurel32     target_long initrd_size=0;
464d0b72631SAlexander Graf     int i = 0, j, k;
4651db09b84Saurel32     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
466a915249fSAlexander Graf     qemu_irq **irqs, *mpic;
467be13cc7aSAlexander Graf     DeviceState *dev;
468e2684c0bSAndreas Färber     CPUPPCState *firstenv = NULL;
4693eddc1beSBharat Bhushan     MemoryRegion *ccsr_addr_space;
470dffb1dc2SBharat Bhushan     SysBusDevice *s;
4713eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
4721db09b84Saurel32 
473e61c36d5SAlexander Graf     /* Setup CPUs */
474e6eaabebSScott Wood     if (params->cpu_model == NULL) {
475e6eaabebSScott Wood         params->cpu_model = "e500v2_v30";
476ef250db6SAlexander Graf     }
477ef250db6SAlexander Graf 
478a915249fSAlexander Graf     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
479a915249fSAlexander Graf     irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
480e61c36d5SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
481397b457dSAndreas Färber         PowerPCCPU *cpu;
482e61c36d5SAlexander Graf         qemu_irq *input;
483397b457dSAndreas Färber 
484e6eaabebSScott Wood         cpu = cpu_ppc_init(params->cpu_model);
485397b457dSAndreas Färber         if (cpu == NULL) {
4861db09b84Saurel32             fprintf(stderr, "Unable to initialize CPU!\n");
4871db09b84Saurel32             exit(1);
4881db09b84Saurel32         }
489397b457dSAndreas Färber         env = &cpu->env;
4901db09b84Saurel32 
491e61c36d5SAlexander Graf         if (!firstenv) {
492e61c36d5SAlexander Graf             firstenv = env;
493e61c36d5SAlexander Graf         }
494e61c36d5SAlexander Graf 
495a915249fSAlexander Graf         irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
496a915249fSAlexander Graf         input = (qemu_irq *)env->irq_inputs;
497a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
498a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
499e61c36d5SAlexander Graf         env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
500dffb1dc2SBharat Bhushan         env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
501dffb1dc2SBharat Bhushan                               MPC8544_MPIC_REGS_OFFSET + 0x20000;
502e61c36d5SAlexander Graf 
503a34a92b9SAndreas Färber         ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
5043b989d49SAlexander Graf 
5053b989d49SAlexander Graf         /* Register reset handler */
5065c145dacSAlexander Graf         if (!i) {
5075c145dacSAlexander Graf             /* Primary CPU */
5085c145dacSAlexander Graf             struct boot_info *boot_info;
509e61c36d5SAlexander Graf             boot_info = g_malloc0(sizeof(struct boot_info));
510b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset, cpu);
511e61c36d5SAlexander Graf             env->load_info = boot_info;
5125c145dacSAlexander Graf         } else {
5135c145dacSAlexander Graf             /* Secondary CPUs */
514b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset_sec, cpu);
5155c145dacSAlexander Graf         }
516e61c36d5SAlexander Graf     }
517e61c36d5SAlexander Graf 
518e61c36d5SAlexander Graf     env = firstenv;
5193b989d49SAlexander Graf 
5201db09b84Saurel32     /* Fixup Memory size on a alignment boundary */
5211db09b84Saurel32     ram_size &= ~(RAM_SIZES_ALIGN - 1);
5221db09b84Saurel32 
5231db09b84Saurel32     /* Register Memory */
524c5705a77SAvi Kivity     memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
525c5705a77SAvi Kivity     vmstate_register_ram_global(ram);
5262646c133SAvi Kivity     memory_region_add_subregion(address_space_mem, 0, ram);
5271db09b84Saurel32 
5283eddc1beSBharat Bhushan     dev = qdev_create(NULL, "e500-ccsr");
5293eddc1beSBharat Bhushan     object_property_add_child(qdev_get_machine(), "e500-ccsr",
5303eddc1beSBharat Bhushan                               OBJECT(dev), NULL);
5313eddc1beSBharat Bhushan     qdev_init_nofail(dev);
5323eddc1beSBharat Bhushan     ccsr = CCSR(dev);
5333eddc1beSBharat Bhushan     ccsr_addr_space = &ccsr->ccsr_space;
5343eddc1beSBharat Bhushan     memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
5353eddc1beSBharat Bhushan                                 ccsr_addr_space);
536dffb1dc2SBharat Bhushan 
5371db09b84Saurel32     /* MPIC */
538d0b72631SAlexander Graf     mpic = g_new(qemu_irq, 256);
539d0b72631SAlexander Graf     dev = qdev_create(NULL, "openpic");
540d0b72631SAlexander Graf     qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
541d0b72631SAlexander Graf     qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_FSL_MPIC_20);
542d0b72631SAlexander Graf     qdev_init_nofail(dev);
543d0b72631SAlexander Graf     s = sysbus_from_qdev(dev);
544a915249fSAlexander Graf 
545d0b72631SAlexander Graf     k = 0;
546d0b72631SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
547d0b72631SAlexander Graf         for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
548d0b72631SAlexander Graf             sysbus_connect_irq(s, k++, irqs[i][j]);
549a915249fSAlexander Graf         }
550d0b72631SAlexander Graf     }
551d0b72631SAlexander Graf 
552d0b72631SAlexander Graf     for (i = 0; i < 256; i++) {
553d0b72631SAlexander Graf         mpic[i] = qdev_get_gpio_in(dev, i);
554d0b72631SAlexander Graf     }
555d0b72631SAlexander Graf 
556d0b72631SAlexander Graf     memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET,
557d0b72631SAlexander Graf                                 s->mmio[0].memory);
5581db09b84Saurel32 
5591db09b84Saurel32     /* Serial */
5602d48377aSBlue Swirl     if (serial_hds[0]) {
5613eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
562cdbb912aSAlexander Graf                        0, mpic[42], 399193,
5632ff0c7c3SRichard Henderson                        serial_hds[0], DEVICE_BIG_ENDIAN);
5642d48377aSBlue Swirl     }
5651db09b84Saurel32 
5662d48377aSBlue Swirl     if (serial_hds[1]) {
5673eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
568cdbb912aSAlexander Graf                        0, mpic[42], 399193,
56959de4f98SBharat Bhushan                        serial_hds[1], DEVICE_BIG_ENDIAN);
5702d48377aSBlue Swirl     }
5711db09b84Saurel32 
572b0fb8423SAlexander Graf     /* General Utility device */
573dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "mpc8544-guts");
574dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
575dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
5763eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,
577dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
578b0fb8423SAlexander Graf 
5791db09b84Saurel32     /* PCI */
580dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "e500-pcihost");
581492ec48dSAlexander Graf     qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot);
582dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
583dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
584dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]);
585dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]);
586dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]);
587dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]);
5883eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
589dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
590dffb1dc2SBharat Bhushan 
591d461e3b9SAlexander Graf     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
5921db09b84Saurel32     if (!pci_bus)
5931db09b84Saurel32         printf("couldn't create PCI controller!\n");
5941db09b84Saurel32 
595a1bc20dfSAlexander Graf     sysbus_mmio_map(sysbus_from_qdev(dev), 1, MPC8544_PCI_IO);
5961db09b84Saurel32 
5971db09b84Saurel32     if (pci_bus) {
5981db09b84Saurel32         /* Register network interfaces. */
5991db09b84Saurel32         for (i = 0; i < nb_nics; i++) {
60007caea31SMarkus Armbruster             pci_nic_init_nofail(&nd_table[i], "virtio", NULL);
6011db09b84Saurel32         }
6021db09b84Saurel32     }
6031db09b84Saurel32 
6045c145dacSAlexander Graf     /* Register spinning region */
6055c145dacSAlexander Graf     sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
6065c145dacSAlexander Graf 
6071db09b84Saurel32     /* Load kernel. */
608e6eaabebSScott Wood     if (params->kernel_filename) {
609e6eaabebSScott Wood         kernel_size = load_uimage(params->kernel_filename, &entry,
610e6eaabebSScott Wood                                   &loadaddr, NULL);
6111db09b84Saurel32         if (kernel_size < 0) {
612e6eaabebSScott Wood             kernel_size = load_elf(params->kernel_filename, NULL, NULL,
613e6eaabebSScott Wood                                    &elf_entry, &elf_lowaddr, NULL, 1,
614e6eaabebSScott Wood                                    ELF_MACHINE, 0);
6151db09b84Saurel32             entry = elf_entry;
6161db09b84Saurel32             loadaddr = elf_lowaddr;
6171db09b84Saurel32         }
6181db09b84Saurel32         /* XXX try again as binary */
6191db09b84Saurel32         if (kernel_size < 0) {
6201db09b84Saurel32             fprintf(stderr, "qemu: could not load kernel '%s'\n",
621e6eaabebSScott Wood                     params->kernel_filename);
6221db09b84Saurel32             exit(1);
6231db09b84Saurel32         }
6241db09b84Saurel32     }
6251db09b84Saurel32 
6261db09b84Saurel32     /* Load initrd. */
627e6eaabebSScott Wood     if (params->initrd_filename) {
6287e7ec2d2SScott Wood         initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) &
6297e7ec2d2SScott Wood             ~INITRD_PAD_MASK;
630e6eaabebSScott Wood         initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
631d7585251Spbrook                                           ram_size - initrd_base);
6321db09b84Saurel32 
6331db09b84Saurel32         if (initrd_size < 0) {
6341db09b84Saurel32             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
635e6eaabebSScott Wood                     params->initrd_filename);
6361db09b84Saurel32             exit(1);
6371db09b84Saurel32         }
6381db09b84Saurel32     }
6391db09b84Saurel32 
6401db09b84Saurel32     /* If we're loading a kernel directly, we must load the device tree too. */
641e6eaabebSScott Wood     if (params->kernel_filename) {
6425c145dacSAlexander Graf         struct boot_info *boot_info;
643cba2026aSAlexander Graf         int dt_size;
6445c145dacSAlexander Graf 
645cba2026aSAlexander Graf         dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
646e6eaabebSScott Wood         dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,
647e6eaabebSScott Wood                                            initrd_size);
648cba2026aSAlexander Graf         if (dt_size < 0) {
6491db09b84Saurel32             fprintf(stderr, "couldn't load device tree\n");
6501db09b84Saurel32             exit(1);
6511db09b84Saurel32         }
6521db09b84Saurel32 
653e61c36d5SAlexander Graf         boot_info = env->load_info;
6543b989d49SAlexander Graf         boot_info->entry = entry;
6553b989d49SAlexander Graf         boot_info->dt_base = dt_base;
656cba2026aSAlexander Graf         boot_info->dt_size = dt_size;
6571db09b84Saurel32     }
6581db09b84Saurel32 
6593b989d49SAlexander Graf     if (kvm_enabled()) {
6601db09b84Saurel32         kvmppc_init();
6613b989d49SAlexander Graf     }
6621db09b84Saurel32 }
6633eddc1beSBharat Bhushan 
6643eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev)
6653eddc1beSBharat Bhushan {
6663eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
6673eddc1beSBharat Bhushan 
6683eddc1beSBharat Bhushan     ccsr = CCSR(dev);
6693eddc1beSBharat Bhushan     memory_region_init(&ccsr->ccsr_space, "e500-ccsr",
6703eddc1beSBharat Bhushan                        MPC8544_CCSRBAR_SIZE);
6713eddc1beSBharat Bhushan     return 0;
6723eddc1beSBharat Bhushan }
6733eddc1beSBharat Bhushan 
6743eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data)
6753eddc1beSBharat Bhushan {
6763eddc1beSBharat Bhushan     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
6773eddc1beSBharat Bhushan     k->init = e500_ccsr_initfn;
6783eddc1beSBharat Bhushan }
6793eddc1beSBharat Bhushan 
6803eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = {
6813eddc1beSBharat Bhushan     .name          = TYPE_CCSR,
6823eddc1beSBharat Bhushan     .parent        = TYPE_SYS_BUS_DEVICE,
6833eddc1beSBharat Bhushan     .instance_size = sizeof(PPCE500CCSRState),
6843eddc1beSBharat Bhushan     .class_init    = e500_ccsr_class_init,
6853eddc1beSBharat Bhushan };
6863eddc1beSBharat Bhushan 
6873eddc1beSBharat Bhushan static void e500_register_types(void)
6883eddc1beSBharat Bhushan {
6893eddc1beSBharat Bhushan     type_register_static(&e500_ccsr_info);
6903eddc1beSBharat Bhushan }
6913eddc1beSBharat Bhushan 
6923eddc1beSBharat Bhushan type_init(e500_register_types)
693