xref: /qemu/hw/ppc/e500.c (revision a911b7a92064d17b862ae85fe8e5ec91b7ba1aa9)
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"
211db09b84Saurel32 #include "net.h"
224a18e7c9SScott Wood #include "hw/hw.h"
23488cb996SGerd Hoffmann #include "hw/serial.h"
244a18e7c9SScott Wood #include "hw/pci.h"
254a18e7c9SScott Wood #include "hw/boards.h"
261db09b84Saurel32 #include "sysemu.h"
271db09b84Saurel32 #include "kvm.h"
281db09b84Saurel32 #include "kvm_ppc.h"
291db09b84Saurel32 #include "device_tree.h"
304a18e7c9SScott Wood #include "hw/openpic.h"
314a18e7c9SScott Wood #include "hw/ppc.h"
324a18e7c9SScott Wood #include "hw/loader.h"
33ca20cf32SBlue Swirl #include "elf.h"
344a18e7c9SScott Wood #include "hw/sysbus.h"
3539186d8aSRichard Henderson #include "exec-memory.h"
36cba2026aSAlexander Graf #include "host-utils.h"
371db09b84Saurel32 
381db09b84Saurel32 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
391db09b84Saurel32 #define UIMAGE_LOAD_BASE           0
409dd5eba1SScott Wood #define DTC_LOAD_PAD               0x1800000
4175bb6589SLiu Yu #define DTC_PAD_MASK               0xFFFFF
4275bb6589SLiu Yu #define INITRD_LOAD_PAD            0x2000000
4375bb6589SLiu Yu #define INITRD_PAD_MASK            0xFFFFFF
441db09b84Saurel32 
451db09b84Saurel32 #define RAM_SIZES_ALIGN            (64UL << 20)
461db09b84Saurel32 
47b3305981SScott Wood /* TODO: parameterize */
48ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_BASE       0xE0000000ULL
49ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE       0x00100000ULL
50dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET   0x40000ULL
51*a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET   0x41600ULL
52dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL
53dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL
54dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET    0x8000ULL
55dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_BASE      (MPC8544_CCSRBAR_BASE + \
56dffb1dc2SBharat Bhushan                                     MPC8544_PCI_REGS_OFFSET)
57ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE      0x1000ULL
58ed2bc496SAlexander Graf #define MPC8544_PCI_IO             0xE1000000ULL
59dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET        0xe0000ULL
60ed2bc496SAlexander Graf #define MPC8544_SPIN_BASE          0xEF000000ULL
611db09b84Saurel32 
623b989d49SAlexander Graf struct boot_info
633b989d49SAlexander Graf {
643b989d49SAlexander Graf     uint32_t dt_base;
65cba2026aSAlexander Graf     uint32_t dt_size;
663b989d49SAlexander Graf     uint32_t entry;
673b989d49SAlexander Graf };
683b989d49SAlexander Graf 
690dbc0798SAlexander Graf static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic)
700dbc0798SAlexander Graf {
710dbc0798SAlexander Graf     int i;
720dbc0798SAlexander Graf     const uint32_t tmp[] = {
730dbc0798SAlexander Graf                              /* IDSEL 0x11 J17 Slot 1 */
747e99826cSAlexander Graf                              0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1,
757e99826cSAlexander Graf                              0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1,
767e99826cSAlexander Graf                              0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1,
777e99826cSAlexander Graf                              0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1,
780dbc0798SAlexander Graf 
790dbc0798SAlexander Graf                              /* IDSEL 0x12 J16 Slot 2 */
807e99826cSAlexander Graf                              0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1,
817e99826cSAlexander Graf                              0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1,
827e99826cSAlexander Graf                              0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1,
837e99826cSAlexander Graf                              0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1,
840dbc0798SAlexander Graf                            };
857e99826cSAlexander Graf     for (i = 0; i < (7 * 8); i++) {
860dbc0798SAlexander Graf         pci_map[i] = cpu_to_be32(tmp[i]);
870dbc0798SAlexander Graf     }
880dbc0798SAlexander Graf }
890dbc0798SAlexander Graf 
90a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset,
91a053a7ceSAlexander Graf                              const char *soc, const char *mpic,
92a053a7ceSAlexander Graf                              const char *alias, int idx, bool defcon)
93a053a7ceSAlexander Graf {
94a053a7ceSAlexander Graf     char ser[128];
95a053a7ceSAlexander Graf 
96a053a7ceSAlexander Graf     snprintf(ser, sizeof(ser), "%s/serial@%llx", soc, offset);
97a053a7ceSAlexander Graf     qemu_devtree_add_subnode(fdt, ser);
98a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, ser, "device_type", "serial");
99a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, ser, "compatible", "ns16550");
100a053a7ceSAlexander Graf     qemu_devtree_setprop_cells(fdt, ser, "reg", offset, 0x100);
101a053a7ceSAlexander Graf     qemu_devtree_setprop_cell(fdt, ser, "cell-index", idx);
102a053a7ceSAlexander Graf     qemu_devtree_setprop_cell(fdt, ser, "clock-frequency", 0);
1037e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, ser, "interrupts", 42, 2);
104a053a7ceSAlexander Graf     qemu_devtree_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
105a053a7ceSAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", alias, ser);
106a053a7ceSAlexander Graf 
107a053a7ceSAlexander Graf     if (defcon) {
108a053a7ceSAlexander Graf         qemu_devtree_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
109a053a7ceSAlexander Graf     }
110a053a7ceSAlexander Graf }
111a053a7ceSAlexander Graf 
112b3305981SScott Wood static int ppce500_load_device_tree(CPUPPCState *env,
113e6eaabebSScott Wood                                     PPCE500Params *params,
114a8170e5eSAvi Kivity                                     hwaddr addr,
115a8170e5eSAvi Kivity                                     hwaddr initrd_base,
116a8170e5eSAvi Kivity                                     hwaddr initrd_size)
1171db09b84Saurel32 {
118dbf916d8SAurelien Jarno     int ret = -1;
119e6eaabebSScott Wood     uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) };
1207ec632b4Spbrook     int fdt_size;
121dbf916d8SAurelien Jarno     void *fdt;
1225de6b46dSAlexander Graf     uint8_t hypercall[16];
123911d6e7aSAlexander Graf     uint32_t clock_freq = 400000000;
124911d6e7aSAlexander Graf     uint32_t tb_freq = 400000000;
125621d05e3SAlexander Graf     int i;
126e6eaabebSScott Wood     const char *toplevel_compat = NULL; /* user override */
127ebb9518aSAlexander Graf     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
1285da96624SAlexander Graf     char soc[128];
12919ac9deaSAlexander Graf     char mpic[128];
13019ac9deaSAlexander Graf     uint32_t mpic_ph;
131*a911b7a9SAlexander Graf     uint32_t msi_ph;
132f5038483SAlexander Graf     char gutil[128];
1330dbc0798SAlexander Graf     char pci[128];
134*a911b7a9SAlexander Graf     char msi[128];
1357e99826cSAlexander Graf     uint32_t pci_map[7 * 8];
1363627757eSAlexander Graf     uint32_t pci_ranges[14] =
1373627757eSAlexander Graf         {
1383627757eSAlexander Graf             0x2000000, 0x0, 0xc0000000,
1393627757eSAlexander Graf             0x0, 0xc0000000,
1403627757eSAlexander Graf             0x0, 0x20000000,
1413627757eSAlexander Graf 
1423627757eSAlexander Graf             0x1000000, 0x0, 0x0,
1433627757eSAlexander Graf             0x0, 0xe1000000,
1443627757eSAlexander Graf             0x0, 0x10000,
1453627757eSAlexander Graf         };
14625b42708SAlexander Graf     QemuOpts *machine_opts;
147d1b93565SAlexander Graf     const char *dtb_file = NULL;
148d1b93565SAlexander Graf 
149d1b93565SAlexander Graf     machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
150d1b93565SAlexander Graf     if (machine_opts) {
151d1b93565SAlexander Graf         dtb_file = qemu_opt_get(machine_opts, "dtb");
152e6eaabebSScott Wood         toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
153d1b93565SAlexander Graf     }
154d1b93565SAlexander Graf 
155d1b93565SAlexander Graf     if (dtb_file) {
156d1b93565SAlexander Graf         char *filename;
157d1b93565SAlexander Graf         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
158d1b93565SAlexander Graf         if (!filename) {
159d1b93565SAlexander Graf             goto out;
160d1b93565SAlexander Graf         }
161d1b93565SAlexander Graf 
162d1b93565SAlexander Graf         fdt = load_device_tree(filename, &fdt_size);
163d1b93565SAlexander Graf         if (!fdt) {
164d1b93565SAlexander Graf             goto out;
165d1b93565SAlexander Graf         }
166d1b93565SAlexander Graf         goto done;
167d1b93565SAlexander Graf     }
1681db09b84Saurel32 
1692636fcb6SAlexander Graf     fdt = create_device_tree(&fdt_size);
1705cea8590SPaul Brook     if (fdt == NULL) {
1715cea8590SPaul Brook         goto out;
1725cea8590SPaul Brook     }
1731db09b84Saurel32 
1741db09b84Saurel32     /* Manipulate device tree in memory. */
1753627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#address-cells", 2);
1763627757eSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/", "#size-cells", 2);
17751b852b7SAlexander Graf 
178dd0bcfcaSAlexander Graf     qemu_devtree_add_subnode(fdt, "/memory");
179dd0bcfcaSAlexander Graf     qemu_devtree_setprop_string(fdt, "/memory", "device_type", "memory");
180dd0bcfcaSAlexander Graf     qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
1811db09b84Saurel32                          sizeof(mem_reg_property));
1821db09b84Saurel32 
183f5231aafSAlexander Graf     qemu_devtree_add_subnode(fdt, "/chosen");
1843b989d49SAlexander Graf     if (initrd_size) {
1851db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
1861db09b84Saurel32                                         initrd_base);
1873b989d49SAlexander Graf         if (ret < 0) {
1881db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
1893b989d49SAlexander Graf         }
1901db09b84Saurel32 
1911db09b84Saurel32         ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
1921db09b84Saurel32                                         (initrd_base + initrd_size));
1933b989d49SAlexander Graf         if (ret < 0) {
1941db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
1953b989d49SAlexander Graf         }
1963b989d49SAlexander Graf     }
1971db09b84Saurel32 
1981db09b84Saurel32     ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
199e6eaabebSScott Wood                                       params->kernel_cmdline);
2001db09b84Saurel32     if (ret < 0)
2011db09b84Saurel32         fprintf(stderr, "couldn't set /chosen/bootargs\n");
2021db09b84Saurel32 
2031db09b84Saurel32     if (kvm_enabled()) {
204911d6e7aSAlexander Graf         /* Read out host's frequencies */
205911d6e7aSAlexander Graf         clock_freq = kvmppc_get_clockfreq();
206911d6e7aSAlexander Graf         tb_freq = kvmppc_get_tbfreq();
2075de6b46dSAlexander Graf 
2085de6b46dSAlexander Graf         /* indicate KVM hypercall interface */
209d50f71a5SAlexander Graf         qemu_devtree_add_subnode(fdt, "/hypervisor");
2105de6b46dSAlexander Graf         qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
2115de6b46dSAlexander Graf                                     "linux,kvm");
2125de6b46dSAlexander Graf         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
2135de6b46dSAlexander Graf         qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
2145de6b46dSAlexander Graf                              hypercall, sizeof(hypercall));
2151db09b84Saurel32     }
2161db09b84Saurel32 
217625e665bSAlexander Graf     /* Create CPU nodes */
218625e665bSAlexander Graf     qemu_devtree_add_subnode(fdt, "/cpus");
219625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#address-cells", 1);
220625e665bSAlexander Graf     qemu_devtree_setprop_cell(fdt, "/cpus", "#size-cells", 0);
221625e665bSAlexander Graf 
2221e3debf0SAlexander Graf     /* We need to generate the cpu nodes in reverse order, so Linux can pick
2231e3debf0SAlexander Graf        the first node as boot node and be happy */
2241e3debf0SAlexander Graf     for (i = smp_cpus - 1; i >= 0; i--) {
225621d05e3SAlexander Graf         char cpu_name[128];
2261d2e5c52SAlexander Graf         uint64_t cpu_release_addr = MPC8544_SPIN_BASE + (i * 0x20);
22710f25a46SAlexander Graf 
2281e3debf0SAlexander Graf         for (env = first_cpu; env != NULL; env = env->next_cpu) {
2291e3debf0SAlexander Graf             if (env->cpu_index == i) {
2301e3debf0SAlexander Graf                 break;
2311e3debf0SAlexander Graf             }
232621d05e3SAlexander Graf         }
233911d6e7aSAlexander Graf 
2341e3debf0SAlexander Graf         if (!env) {
2351e3debf0SAlexander Graf             continue;
2361e3debf0SAlexander Graf         }
2371e3debf0SAlexander Graf 
2381e3debf0SAlexander Graf         snprintf(cpu_name, sizeof(cpu_name), "/cpus/PowerPC,8544@%x", env->cpu_index);
2391e3debf0SAlexander Graf         qemu_devtree_add_subnode(fdt, cpu_name);
2401e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
2411e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
2421e3debf0SAlexander Graf         qemu_devtree_setprop_string(fdt, cpu_name, "device_type", "cpu");
2431e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "reg", env->cpu_index);
2441e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-line-size",
2451e3debf0SAlexander Graf                                   env->dcache_line_size);
2461e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-line-size",
2471e3debf0SAlexander Graf                                   env->icache_line_size);
2481e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
2491e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
2501e3debf0SAlexander Graf         qemu_devtree_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
2511e3debf0SAlexander Graf         if (env->cpu_index) {
2521e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "disabled");
2531e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "enable-method", "spin-table");
2541d2e5c52SAlexander Graf             qemu_devtree_setprop_u64(fdt, cpu_name, "cpu-release-addr",
2551d2e5c52SAlexander Graf                                      cpu_release_addr);
2561e3debf0SAlexander Graf         } else {
2571e3debf0SAlexander Graf             qemu_devtree_setprop_string(fdt, cpu_name, "status", "okay");
2581e3debf0SAlexander Graf         }
2591db09b84Saurel32     }
2601db09b84Saurel32 
2610cfc6e8dSAlexander Graf     qemu_devtree_add_subnode(fdt, "/aliases");
2625da96624SAlexander Graf     /* XXX These should go into their respective devices' code */
263ed2bc496SAlexander Graf     snprintf(soc, sizeof(soc), "/soc@%llx", MPC8544_CCSRBAR_BASE);
2645da96624SAlexander Graf     qemu_devtree_add_subnode(fdt, soc);
2655da96624SAlexander Graf     qemu_devtree_setprop_string(fdt, soc, "device_type", "soc");
266ebb9518aSAlexander Graf     qemu_devtree_setprop(fdt, soc, "compatible", compatible_sb,
267ebb9518aSAlexander Graf                          sizeof(compatible_sb));
2685da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#address-cells", 1);
2695da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "#size-cells", 1);
2703627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, soc, "ranges", 0x0,
2713627757eSAlexander Graf                                MPC8544_CCSRBAR_BASE >> 32, MPC8544_CCSRBAR_BASE,
2725da96624SAlexander Graf                                MPC8544_CCSRBAR_SIZE);
2735da96624SAlexander Graf     /* XXX should contain a reasonable value */
2745da96624SAlexander Graf     qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);
2755da96624SAlexander Graf 
276dffb1dc2SBharat Bhushan     snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
27719ac9deaSAlexander Graf     qemu_devtree_add_subnode(fdt, mpic);
27819ac9deaSAlexander Graf     qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
2797e99826cSAlexander Graf     qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic");
280dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
281dffb1dc2SBharat Bhushan                                0x40000);
28219ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
2837e99826cSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
28419ac9deaSAlexander Graf     mpic_ph = qemu_devtree_alloc_phandle(fdt);
28519ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "phandle", mpic_ph);
28619ac9deaSAlexander Graf     qemu_devtree_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
28719ac9deaSAlexander Graf     qemu_devtree_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
28819ac9deaSAlexander Graf 
2890cfc6e8dSAlexander Graf     /*
2900cfc6e8dSAlexander Graf      * We have to generate ser1 first, because Linux takes the first
2910cfc6e8dSAlexander Graf      * device it finds in the dt as serial output device. And we generate
2920cfc6e8dSAlexander Graf      * devices in reverse order to the dt.
2930cfc6e8dSAlexander Graf      */
294dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
295a053a7ceSAlexander Graf                      soc, mpic, "serial1", 1, false);
296dffb1dc2SBharat Bhushan     dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
297a053a7ceSAlexander Graf                      soc, mpic, "serial0", 0, true);
2980cfc6e8dSAlexander Graf 
299ed2bc496SAlexander Graf     snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
300dffb1dc2SBharat Bhushan              MPC8544_UTIL_OFFSET);
301f5038483SAlexander Graf     qemu_devtree_add_subnode(fdt, gutil);
302f5038483SAlexander Graf     qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
303dffb1dc2SBharat Bhushan     qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
304f5038483SAlexander Graf     qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
305f5038483SAlexander Graf 
306*a911b7a9SAlexander Graf     snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
307*a911b7a9SAlexander Graf     qemu_devtree_add_subnode(fdt, msi);
308*a911b7a9SAlexander Graf     qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
309*a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
310*a911b7a9SAlexander Graf     msi_ph = qemu_devtree_alloc_phandle(fdt);
311*a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
312*a911b7a9SAlexander Graf     qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
313*a911b7a9SAlexander Graf     qemu_devtree_setprop_cells(fdt, msi, "interrupts",
314*a911b7a9SAlexander Graf         0xe0, 0x0,
315*a911b7a9SAlexander Graf         0xe1, 0x0,
316*a911b7a9SAlexander Graf         0xe2, 0x0,
317*a911b7a9SAlexander Graf         0xe3, 0x0,
318*a911b7a9SAlexander Graf         0xe4, 0x0,
319*a911b7a9SAlexander Graf         0xe5, 0x0,
320*a911b7a9SAlexander Graf         0xe6, 0x0,
321*a911b7a9SAlexander Graf         0xe7, 0x0);
322*a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);
323*a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
324*a911b7a9SAlexander Graf 
325ed2bc496SAlexander Graf     snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
3260dbc0798SAlexander Graf     qemu_devtree_add_subnode(fdt, pci);
3270dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
3280dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
3290dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
3300dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
3310dbc0798SAlexander Graf                                0x0, 0x7);
3320dbc0798SAlexander Graf     pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic));
3330dbc0798SAlexander Graf     qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map));
3340dbc0798SAlexander Graf     qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
3357e99826cSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
3360dbc0798SAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
3373627757eSAlexander Graf     for (i = 0; i < 14; i++) {
3380dbc0798SAlexander Graf         pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
3390dbc0798SAlexander Graf     }
340*a911b7a9SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
3410dbc0798SAlexander Graf     qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
3423627757eSAlexander Graf     qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
3433627757eSAlexander Graf                                MPC8544_PCI_REGS_BASE, 0, 0x1000);
3440dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "clock-frequency", 66666666);
3450dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#interrupt-cells", 1);
3460dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#size-cells", 2);
3470dbc0798SAlexander Graf     qemu_devtree_setprop_cell(fdt, pci, "#address-cells", 3);
3480dbc0798SAlexander Graf     qemu_devtree_setprop_string(fdt, "/aliases", "pci0", pci);
3490dbc0798SAlexander Graf 
350e6eaabebSScott Wood     params->fixup_devtree(params, fdt);
351e6eaabebSScott Wood 
352e6eaabebSScott Wood     if (toplevel_compat) {
353e6eaabebSScott Wood         qemu_devtree_setprop(fdt, "/", "compatible", toplevel_compat,
354e6eaabebSScott Wood                              strlen(toplevel_compat) + 1);
355e6eaabebSScott Wood     }
356e6eaabebSScott Wood 
357d1b93565SAlexander Graf done:
35871193433SAlexander Graf     qemu_devtree_dumpdtb(fdt, fdt_size);
35904088adbSLiu Yu     ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
360cba2026aSAlexander Graf     if (ret < 0) {
361cba2026aSAlexander Graf         goto out;
362cba2026aSAlexander Graf     }
3637267c094SAnthony Liguori     g_free(fdt);
364cba2026aSAlexander Graf     ret = fdt_size;
3657ec632b4Spbrook 
3661db09b84Saurel32 out:
3671db09b84Saurel32 
36804088adbSLiu Yu     return ret;
3691db09b84Saurel32 }
3701db09b84Saurel32 
371cba2026aSAlexander Graf /* Create -kernel TLB entries for BookE.  */
372a8170e5eSAvi Kivity static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
373d1e256feSAlexander Graf {
374cba2026aSAlexander Graf     return 63 - clz64(size >> 10);
375d1e256feSAlexander Graf }
376d1e256feSAlexander Graf 
377cba2026aSAlexander Graf static void mmubooke_create_initial_mapping(CPUPPCState *env)
3783b989d49SAlexander Graf {
379cba2026aSAlexander Graf     struct boot_info *bi = env->load_info;
380d1e256feSAlexander Graf     ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
381a8170e5eSAvi Kivity     hwaddr size, dt_end;
382cba2026aSAlexander Graf     int ps;
3833b989d49SAlexander Graf 
384cba2026aSAlexander Graf     /* Our initial TLB entry needs to cover everything from 0 to
385cba2026aSAlexander Graf        the device tree top */
386cba2026aSAlexander Graf     dt_end = bi->dt_base + bi->dt_size;
387cba2026aSAlexander Graf     ps = booke206_page_size_to_tlb(dt_end) + 1;
388fb37c302SAlexander Graf     if (ps & 1) {
389fb37c302SAlexander Graf         /* e500v2 can only do even TLB size bits */
390fb37c302SAlexander Graf         ps++;
391fb37c302SAlexander Graf     }
392cba2026aSAlexander Graf     size = (ps << MAS1_TSIZE_SHIFT);
393d1e256feSAlexander Graf     tlb->mas1 = MAS1_VALID | size;
394cba2026aSAlexander Graf     tlb->mas2 = 0;
395cba2026aSAlexander Graf     tlb->mas7_3 = 0;
396d1e256feSAlexander Graf     tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
39793dd5e85SScott Wood 
39893dd5e85SScott Wood     env->tlb_dirty = true;
3993b989d49SAlexander Graf }
4003b989d49SAlexander Graf 
401b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque)
4025c145dacSAlexander Graf {
40338f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
40438f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4055c145dacSAlexander Graf 
40638f92da6SAndreas Färber     cpu_reset(CPU(cpu));
4075c145dacSAlexander Graf 
4085c145dacSAlexander Graf     /* Secondary CPU starts in halted state for now. Needs to change when
4095c145dacSAlexander Graf        implementing non-kernel boot. */
4105c145dacSAlexander Graf     env->halted = 1;
4115c145dacSAlexander Graf     env->exception_index = EXCP_HLT;
4123b989d49SAlexander Graf }
4133b989d49SAlexander Graf 
414b3305981SScott Wood static void ppce500_cpu_reset(void *opaque)
4153b989d49SAlexander Graf {
41638f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
41738f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
4183b989d49SAlexander Graf     struct boot_info *bi = env->load_info;
4193b989d49SAlexander Graf 
42038f92da6SAndreas Färber     cpu_reset(CPU(cpu));
4213b989d49SAlexander Graf 
4223b989d49SAlexander Graf     /* Set initial guest state. */
4235c145dacSAlexander Graf     env->halted = 0;
4243b989d49SAlexander Graf     env->gpr[1] = (16<<20) - 8;
4253b989d49SAlexander Graf     env->gpr[3] = bi->dt_base;
4263b989d49SAlexander Graf     env->nip = bi->entry;
427cba2026aSAlexander Graf     mmubooke_create_initial_mapping(env);
4283b989d49SAlexander Graf }
4293b989d49SAlexander Graf 
430e6eaabebSScott Wood void ppce500_init(PPCE500Params *params)
4311db09b84Saurel32 {
43239186d8aSRichard Henderson     MemoryRegion *address_space_mem = get_system_memory();
4332646c133SAvi Kivity     MemoryRegion *ram = g_new(MemoryRegion, 1);
4341db09b84Saurel32     PCIBus *pci_bus;
435e2684c0bSAndreas Färber     CPUPPCState *env = NULL;
4361db09b84Saurel32     uint64_t elf_entry;
4371db09b84Saurel32     uint64_t elf_lowaddr;
438a8170e5eSAvi Kivity     hwaddr entry=0;
439a8170e5eSAvi Kivity     hwaddr loadaddr=UIMAGE_LOAD_BASE;
4401db09b84Saurel32     target_long kernel_size=0;
44175bb6589SLiu Yu     target_ulong dt_base = 0;
44275bb6589SLiu Yu     target_ulong initrd_base = 0;
4431db09b84Saurel32     target_long initrd_size=0;
444d0b72631SAlexander Graf     int i = 0, j, k;
4451db09b84Saurel32     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
446a915249fSAlexander Graf     qemu_irq **irqs, *mpic;
447be13cc7aSAlexander Graf     DeviceState *dev;
448e2684c0bSAndreas Färber     CPUPPCState *firstenv = NULL;
4493eddc1beSBharat Bhushan     MemoryRegion *ccsr_addr_space;
450dffb1dc2SBharat Bhushan     SysBusDevice *s;
4513eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
4521db09b84Saurel32 
453e61c36d5SAlexander Graf     /* Setup CPUs */
454e6eaabebSScott Wood     if (params->cpu_model == NULL) {
455e6eaabebSScott Wood         params->cpu_model = "e500v2_v30";
456ef250db6SAlexander Graf     }
457ef250db6SAlexander Graf 
458a915249fSAlexander Graf     irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
459a915249fSAlexander Graf     irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
460e61c36d5SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
461397b457dSAndreas Färber         PowerPCCPU *cpu;
462e61c36d5SAlexander Graf         qemu_irq *input;
463397b457dSAndreas Färber 
464e6eaabebSScott Wood         cpu = cpu_ppc_init(params->cpu_model);
465397b457dSAndreas Färber         if (cpu == NULL) {
4661db09b84Saurel32             fprintf(stderr, "Unable to initialize CPU!\n");
4671db09b84Saurel32             exit(1);
4681db09b84Saurel32         }
469397b457dSAndreas Färber         env = &cpu->env;
4701db09b84Saurel32 
471e61c36d5SAlexander Graf         if (!firstenv) {
472e61c36d5SAlexander Graf             firstenv = env;
473e61c36d5SAlexander Graf         }
474e61c36d5SAlexander Graf 
475a915249fSAlexander Graf         irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
476a915249fSAlexander Graf         input = (qemu_irq *)env->irq_inputs;
477a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
478a915249fSAlexander Graf         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
479e61c36d5SAlexander Graf         env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
480dffb1dc2SBharat Bhushan         env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
481dffb1dc2SBharat Bhushan                               MPC8544_MPIC_REGS_OFFSET + 0x20000;
482e61c36d5SAlexander Graf 
483ddd1055bSFabien Chouteau         ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);
4843b989d49SAlexander Graf 
4853b989d49SAlexander Graf         /* Register reset handler */
4865c145dacSAlexander Graf         if (!i) {
4875c145dacSAlexander Graf             /* Primary CPU */
4885c145dacSAlexander Graf             struct boot_info *boot_info;
489e61c36d5SAlexander Graf             boot_info = g_malloc0(sizeof(struct boot_info));
490b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset, cpu);
491e61c36d5SAlexander Graf             env->load_info = boot_info;
4925c145dacSAlexander Graf         } else {
4935c145dacSAlexander Graf             /* Secondary CPUs */
494b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset_sec, cpu);
4955c145dacSAlexander Graf         }
496e61c36d5SAlexander Graf     }
497e61c36d5SAlexander Graf 
498e61c36d5SAlexander Graf     env = firstenv;
4993b989d49SAlexander Graf 
5001db09b84Saurel32     /* Fixup Memory size on a alignment boundary */
5011db09b84Saurel32     ram_size &= ~(RAM_SIZES_ALIGN - 1);
5021db09b84Saurel32 
5031db09b84Saurel32     /* Register Memory */
504c5705a77SAvi Kivity     memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
505c5705a77SAvi Kivity     vmstate_register_ram_global(ram);
5062646c133SAvi Kivity     memory_region_add_subregion(address_space_mem, 0, ram);
5071db09b84Saurel32 
5083eddc1beSBharat Bhushan     dev = qdev_create(NULL, "e500-ccsr");
5093eddc1beSBharat Bhushan     object_property_add_child(qdev_get_machine(), "e500-ccsr",
5103eddc1beSBharat Bhushan                               OBJECT(dev), NULL);
5113eddc1beSBharat Bhushan     qdev_init_nofail(dev);
5123eddc1beSBharat Bhushan     ccsr = CCSR(dev);
5133eddc1beSBharat Bhushan     ccsr_addr_space = &ccsr->ccsr_space;
5143eddc1beSBharat Bhushan     memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
5153eddc1beSBharat Bhushan                                 ccsr_addr_space);
516dffb1dc2SBharat Bhushan 
5171db09b84Saurel32     /* MPIC */
518d0b72631SAlexander Graf     mpic = g_new(qemu_irq, 256);
519d0b72631SAlexander Graf     dev = qdev_create(NULL, "openpic");
520d0b72631SAlexander Graf     qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
521d0b72631SAlexander Graf     qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_FSL_MPIC_20);
522d0b72631SAlexander Graf     qdev_init_nofail(dev);
523d0b72631SAlexander Graf     s = sysbus_from_qdev(dev);
524a915249fSAlexander Graf 
525d0b72631SAlexander Graf     k = 0;
526d0b72631SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
527d0b72631SAlexander Graf         for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
528d0b72631SAlexander Graf             sysbus_connect_irq(s, k++, irqs[i][j]);
529a915249fSAlexander Graf         }
530d0b72631SAlexander Graf     }
531d0b72631SAlexander Graf 
532d0b72631SAlexander Graf     for (i = 0; i < 256; i++) {
533d0b72631SAlexander Graf         mpic[i] = qdev_get_gpio_in(dev, i);
534d0b72631SAlexander Graf     }
535d0b72631SAlexander Graf 
536d0b72631SAlexander Graf     memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET,
537d0b72631SAlexander Graf                                 s->mmio[0].memory);
5381db09b84Saurel32 
5391db09b84Saurel32     /* Serial */
5402d48377aSBlue Swirl     if (serial_hds[0]) {
5413eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
542cdbb912aSAlexander Graf                        0, mpic[42], 399193,
5432ff0c7c3SRichard Henderson                        serial_hds[0], DEVICE_BIG_ENDIAN);
5442d48377aSBlue Swirl     }
5451db09b84Saurel32 
5462d48377aSBlue Swirl     if (serial_hds[1]) {
5473eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
548cdbb912aSAlexander Graf                        0, mpic[42], 399193,
54959de4f98SBharat Bhushan                        serial_hds[1], DEVICE_BIG_ENDIAN);
5502d48377aSBlue Swirl     }
5511db09b84Saurel32 
552b0fb8423SAlexander Graf     /* General Utility device */
553dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "mpc8544-guts");
554dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
555dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
5563eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,
557dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
558b0fb8423SAlexander Graf 
5591db09b84Saurel32     /* PCI */
560dffb1dc2SBharat Bhushan     dev = qdev_create(NULL, "e500-pcihost");
561dffb1dc2SBharat Bhushan     qdev_init_nofail(dev);
562dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
563dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]);
564dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]);
565dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]);
566dffb1dc2SBharat Bhushan     sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]);
5673eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
568dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
569dffb1dc2SBharat Bhushan 
570d461e3b9SAlexander Graf     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
5711db09b84Saurel32     if (!pci_bus)
5721db09b84Saurel32         printf("couldn't create PCI controller!\n");
5731db09b84Saurel32 
574a1bc20dfSAlexander Graf     sysbus_mmio_map(sysbus_from_qdev(dev), 1, MPC8544_PCI_IO);
5751db09b84Saurel32 
5761db09b84Saurel32     if (pci_bus) {
5771db09b84Saurel32         /* Register network interfaces. */
5781db09b84Saurel32         for (i = 0; i < nb_nics; i++) {
57907caea31SMarkus Armbruster             pci_nic_init_nofail(&nd_table[i], "virtio", NULL);
5801db09b84Saurel32         }
5811db09b84Saurel32     }
5821db09b84Saurel32 
5835c145dacSAlexander Graf     /* Register spinning region */
5845c145dacSAlexander Graf     sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
5855c145dacSAlexander Graf 
5861db09b84Saurel32     /* Load kernel. */
587e6eaabebSScott Wood     if (params->kernel_filename) {
588e6eaabebSScott Wood         kernel_size = load_uimage(params->kernel_filename, &entry,
589e6eaabebSScott Wood                                   &loadaddr, NULL);
5901db09b84Saurel32         if (kernel_size < 0) {
591e6eaabebSScott Wood             kernel_size = load_elf(params->kernel_filename, NULL, NULL,
592e6eaabebSScott Wood                                    &elf_entry, &elf_lowaddr, NULL, 1,
593e6eaabebSScott Wood                                    ELF_MACHINE, 0);
5941db09b84Saurel32             entry = elf_entry;
5951db09b84Saurel32             loadaddr = elf_lowaddr;
5961db09b84Saurel32         }
5971db09b84Saurel32         /* XXX try again as binary */
5981db09b84Saurel32         if (kernel_size < 0) {
5991db09b84Saurel32             fprintf(stderr, "qemu: could not load kernel '%s'\n",
600e6eaabebSScott Wood                     params->kernel_filename);
6011db09b84Saurel32             exit(1);
6021db09b84Saurel32         }
6031db09b84Saurel32     }
6041db09b84Saurel32 
6051db09b84Saurel32     /* Load initrd. */
606e6eaabebSScott Wood     if (params->initrd_filename) {
6077e7ec2d2SScott Wood         initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) &
6087e7ec2d2SScott Wood             ~INITRD_PAD_MASK;
609e6eaabebSScott Wood         initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
610d7585251Spbrook                                           ram_size - initrd_base);
6111db09b84Saurel32 
6121db09b84Saurel32         if (initrd_size < 0) {
6131db09b84Saurel32             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
614e6eaabebSScott Wood                     params->initrd_filename);
6151db09b84Saurel32             exit(1);
6161db09b84Saurel32         }
6171db09b84Saurel32     }
6181db09b84Saurel32 
6191db09b84Saurel32     /* If we're loading a kernel directly, we must load the device tree too. */
620e6eaabebSScott Wood     if (params->kernel_filename) {
6215c145dacSAlexander Graf         struct boot_info *boot_info;
622cba2026aSAlexander Graf         int dt_size;
6235c145dacSAlexander Graf 
624cba2026aSAlexander Graf         dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
625e6eaabebSScott Wood         dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,
626e6eaabebSScott Wood                                            initrd_size);
627cba2026aSAlexander Graf         if (dt_size < 0) {
6281db09b84Saurel32             fprintf(stderr, "couldn't load device tree\n");
6291db09b84Saurel32             exit(1);
6301db09b84Saurel32         }
6311db09b84Saurel32 
632e61c36d5SAlexander Graf         boot_info = env->load_info;
6333b989d49SAlexander Graf         boot_info->entry = entry;
6343b989d49SAlexander Graf         boot_info->dt_base = dt_base;
635cba2026aSAlexander Graf         boot_info->dt_size = dt_size;
6361db09b84Saurel32     }
6371db09b84Saurel32 
6383b989d49SAlexander Graf     if (kvm_enabled()) {
6391db09b84Saurel32         kvmppc_init();
6403b989d49SAlexander Graf     }
6411db09b84Saurel32 }
6423eddc1beSBharat Bhushan 
6433eddc1beSBharat Bhushan static int e500_ccsr_initfn(SysBusDevice *dev)
6443eddc1beSBharat Bhushan {
6453eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
6463eddc1beSBharat Bhushan 
6473eddc1beSBharat Bhushan     ccsr = CCSR(dev);
6483eddc1beSBharat Bhushan     memory_region_init(&ccsr->ccsr_space, "e500-ccsr",
6493eddc1beSBharat Bhushan                        MPC8544_CCSRBAR_SIZE);
6503eddc1beSBharat Bhushan     return 0;
6513eddc1beSBharat Bhushan }
6523eddc1beSBharat Bhushan 
6533eddc1beSBharat Bhushan static void e500_ccsr_class_init(ObjectClass *klass, void *data)
6543eddc1beSBharat Bhushan {
6553eddc1beSBharat Bhushan     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
6563eddc1beSBharat Bhushan     k->init = e500_ccsr_initfn;
6573eddc1beSBharat Bhushan }
6583eddc1beSBharat Bhushan 
6593eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = {
6603eddc1beSBharat Bhushan     .name          = TYPE_CCSR,
6613eddc1beSBharat Bhushan     .parent        = TYPE_SYS_BUS_DEVICE,
6623eddc1beSBharat Bhushan     .instance_size = sizeof(PPCE500CCSRState),
6633eddc1beSBharat Bhushan     .class_init    = e500_ccsr_class_init,
6643eddc1beSBharat Bhushan };
6653eddc1beSBharat Bhushan 
6663eddc1beSBharat Bhushan static void e500_register_types(void)
6673eddc1beSBharat Bhushan {
6683eddc1beSBharat Bhushan     type_register_static(&e500_ccsr_info);
6693eddc1beSBharat Bhushan }
6703eddc1beSBharat Bhushan 
6713eddc1beSBharat Bhushan type_init(e500_register_types)
672