xref: /qemu/hw/ppc/e500.c (revision 0998fcb35360557395b60678e73a9e51334a07dc)
11db09b84Saurel32 /*
2b3305981SScott Wood  * QEMU PowerPC e500-based platforms
31db09b84Saurel32  *
41db09b84Saurel32  * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
51db09b84Saurel32  *
61db09b84Saurel32  * Author: Yu Liu,     <yu.liu@freescale.com>
71db09b84Saurel32  *
81db09b84Saurel32  * This file is derived from hw/ppc440_bamboo.c,
91db09b84Saurel32  * the copyright for that material belongs to the original owners.
101db09b84Saurel32  *
111db09b84Saurel32  * This is free software; you can redistribute it and/or modify
121db09b84Saurel32  * it under the terms of  the GNU General  Public License as published by
131db09b84Saurel32  * the Free Software Foundation;  either version 2 of the  License, or
141db09b84Saurel32  * (at your option) any later version.
151db09b84Saurel32  */
161db09b84Saurel32 
170d75590dSPeter Maydell #include "qemu/osdep.h"
182c65db5eSPaolo Bonzini #include "qemu/datadir.h"
19ab3dd749SPhilippe Mathieu-Daudé #include "qemu/units.h"
20c4b07531SJason A. Donenfeld #include "qemu/guest-random.h"
21da34e65cSMarkus Armbruster #include "qapi/error.h"
22e6eaabebSScott Wood #include "e500.h"
233eddc1beSBharat Bhushan #include "e500-ccsr.h"
241422e32dSPaolo Bonzini #include "net/net.h"
251de7afc9SPaolo Bonzini #include "qemu/config-file.h"
2663e4bf8eSBernhard Beschow #include "hw/block/flash.h"
270d09e41aSPaolo Bonzini #include "hw/char/serial.h"
28a2cb15b0SMichael S. Tsirkin #include "hw/pci/pci.h"
2963e4bf8eSBernhard Beschow #include "sysemu/block-backend-io.h"
309c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
319c17d615SPaolo Bonzini #include "sysemu/kvm.h"
3271e8a915SMarkus Armbruster #include "sysemu/reset.h"
3354d31236SMarkus Armbruster #include "sysemu/runstate.h"
341db09b84Saurel32 #include "kvm_ppc.h"
359c17d615SPaolo Bonzini #include "sysemu/device_tree.h"
360d09e41aSPaolo Bonzini #include "hw/ppc/openpic.h"
378d085cf0SMark Cave-Ayland #include "hw/ppc/openpic_kvm.h"
380d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h"
39a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
404a18e7c9SScott Wood #include "hw/loader.h"
41ca20cf32SBlue Swirl #include "elf.h"
424a18e7c9SScott Wood #include "hw/sysbus.h"
431de7afc9SPaolo Bonzini #include "qemu/host-utils.h"
44922a01a0SMarkus Armbruster #include "qemu/option.h"
450d09e41aSPaolo Bonzini #include "hw/pci-host/ppce500.h"
46f7087343SAlexander Graf #include "qemu/error-report.h"
47f7087343SAlexander Graf #include "hw/platform-bus.h"
48fdfb7f2cSAlexander Graf #include "hw/net/fsl_etsec/etsec.h"
497abb479cSAndrew Randrianasulu #include "hw/i2c/i2c.h"
5064552b6bSMarkus Armbruster #include "hw/irq.h"
513f288c4bSPhilippe Mathieu-Daudé #include "hw/sd/sdhci.h"
523f288c4bSPhilippe Mathieu-Daudé #include "hw/misc/unimp.h"
531db09b84Saurel32 
54cefd3cdbSBharat Bhushan #define EPAPR_MAGIC                (0x45504150)
559dd5eba1SScott Wood #define DTC_LOAD_PAD               0x1800000
5675bb6589SLiu Yu #define DTC_PAD_MASK               0xFFFFF
57ab3dd749SPhilippe Mathieu-Daudé #define DTB_MAX_SIZE               (8 * MiB)
5875bb6589SLiu Yu #define INITRD_LOAD_PAD            0x2000000
5975bb6589SLiu Yu #define INITRD_PAD_MASK            0xFFFFFF
601db09b84Saurel32 
61ab3dd749SPhilippe Mathieu-Daudé #define RAM_SIZES_ALIGN            (64 * MiB)
621db09b84Saurel32 
63b3305981SScott Wood /* TODO: parameterize */
64ed2bc496SAlexander Graf #define MPC8544_CCSRBAR_SIZE       0x00100000ULL
65dffb1dc2SBharat Bhushan #define MPC8544_MPIC_REGS_OFFSET   0x40000ULL
66a911b7a9SAlexander Graf #define MPC8544_MSI_REGS_OFFSET   0x41600ULL
67dffb1dc2SBharat Bhushan #define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL
68dffb1dc2SBharat Bhushan #define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL
69dffb1dc2SBharat Bhushan #define MPC8544_PCI_REGS_OFFSET    0x8000ULL
70ed2bc496SAlexander Graf #define MPC8544_PCI_REGS_SIZE      0x1000ULL
713f288c4bSPhilippe Mathieu-Daudé #define MPC85XX_ESDHC_REGS_OFFSET  0x2e000ULL
723f288c4bSPhilippe Mathieu-Daudé #define MPC85XX_ESDHC_REGS_SIZE    0x1000ULL
73dffb1dc2SBharat Bhushan #define MPC8544_UTIL_OFFSET        0xe0000ULL
74b88e77f4SAlexander Graf #define MPC8XXX_GPIO_OFFSET        0x000FF000ULL
757abb479cSAndrew Randrianasulu #define MPC8544_I2C_REGS_OFFSET    0x3000ULL
7682e345f5SAmit Tomar #define MPC8XXX_GPIO_IRQ           47
777abb479cSAndrew Randrianasulu #define MPC8544_I2C_IRQ            43
783f288c4bSPhilippe Mathieu-Daudé #define MPC85XX_ESDHC_IRQ          72
797abb479cSAndrew Randrianasulu #define RTC_REGS_OFFSET            0x68
801db09b84Saurel32 
810c36ab71SBin Meng #define PLATFORM_CLK_FREQ_HZ       (400 * 1000 * 1000)
820c36ab71SBin Meng 
833b989d49SAlexander Graf struct boot_info
843b989d49SAlexander Graf {
853b989d49SAlexander Graf     uint32_t dt_base;
86cba2026aSAlexander Graf     uint32_t dt_size;
873b989d49SAlexander Graf     uint32_t entry;
883b989d49SAlexander Graf };
893b989d49SAlexander Graf 
90347dd79dSAlexander Graf static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot,
91347dd79dSAlexander Graf                                 int nr_slots, int *len)
920dbc0798SAlexander Graf {
93347dd79dSAlexander Graf     int i = 0;
94347dd79dSAlexander Graf     int slot;
95347dd79dSAlexander Graf     int pci_irq;
969e2c1298SAlexander Graf     int host_irq;
97347dd79dSAlexander Graf     int last_slot = first_slot + nr_slots;
98347dd79dSAlexander Graf     uint32_t *pci_map;
990dbc0798SAlexander Graf 
100347dd79dSAlexander Graf     *len = nr_slots * 4 * 7 * sizeof(uint32_t);
101347dd79dSAlexander Graf     pci_map = g_malloc(*len);
102347dd79dSAlexander Graf 
103347dd79dSAlexander Graf     for (slot = first_slot; slot < last_slot; slot++) {
104347dd79dSAlexander Graf         for (pci_irq = 0; pci_irq < 4; pci_irq++) {
105347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(slot << 11);
106347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
107347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x0);
108347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(pci_irq + 1);
109347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(mpic);
1109e2c1298SAlexander Graf             host_irq = ppce500_pci_map_irq_slot(slot, pci_irq);
1119e2c1298SAlexander Graf             pci_map[i++] = cpu_to_be32(host_irq + 1);
112347dd79dSAlexander Graf             pci_map[i++] = cpu_to_be32(0x1);
1130dbc0798SAlexander Graf         }
1140dbc0798SAlexander Graf     }
1150dbc0798SAlexander Graf 
116347dd79dSAlexander Graf     assert((i * sizeof(uint32_t)) == *len);
117347dd79dSAlexander Graf 
118347dd79dSAlexander Graf     return pci_map;
119347dd79dSAlexander Graf }
120347dd79dSAlexander Graf 
121a053a7ceSAlexander Graf static void dt_serial_create(void *fdt, unsigned long long offset,
122a053a7ceSAlexander Graf                              const char *soc, const char *mpic,
123a053a7ceSAlexander Graf                              const char *alias, int idx, bool defcon)
124a053a7ceSAlexander Graf {
1252fb513d3SGreg Kurz     char *ser;
126a053a7ceSAlexander Graf 
1272fb513d3SGreg Kurz     ser = g_strdup_printf("%s/serial@%llx", soc, offset);
1285a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, ser);
1295a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, ser, "device_type", "serial");
1305a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, ser, "compatible", "ns16550");
1315a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, ser, "reg", offset, 0x100);
1325a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, ser, "cell-index", idx);
13311dbcc70SBin Meng     qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", PLATFORM_CLK_FREQ_HZ);
1345a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, ser, "interrupts", 42, 2);
1355a4348d1SPeter Crosthwaite     qemu_fdt_setprop_phandle(fdt, ser, "interrupt-parent", mpic);
1365a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, "/aliases", alias, ser);
137a053a7ceSAlexander Graf 
138a053a7ceSAlexander Graf     if (defcon) {
13990ee4e01SNikunj A Dadhania         /*
14090ee4e01SNikunj A Dadhania          * "linux,stdout-path" and "stdout" properties are deprecated by linux
14190ee4e01SNikunj A Dadhania          * kernel. New platforms should only use the "stdout-path" property. Set
14290ee4e01SNikunj A Dadhania          * the new property and continue using older property to remain
14390ee4e01SNikunj A Dadhania          * compatible with the existing firmware.
14490ee4e01SNikunj A Dadhania          */
1455a4348d1SPeter Crosthwaite         qemu_fdt_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
14690ee4e01SNikunj A Dadhania         qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", ser);
147a053a7ceSAlexander Graf     }
1482fb513d3SGreg Kurz     g_free(ser);
149a053a7ceSAlexander Graf }
150a053a7ceSAlexander Graf 
151b88e77f4SAlexander Graf static void create_dt_mpc8xxx_gpio(void *fdt, const char *soc, const char *mpic)
152b88e77f4SAlexander Graf {
153b88e77f4SAlexander Graf     hwaddr mmio0 = MPC8XXX_GPIO_OFFSET;
154b88e77f4SAlexander Graf     int irq0 = MPC8XXX_GPIO_IRQ;
155b88e77f4SAlexander Graf     gchar *node = g_strdup_printf("%s/gpio@%"PRIx64, soc, mmio0);
156016f7758SAlexander Graf     gchar *poweroff = g_strdup_printf("%s/power-off", soc);
157016f7758SAlexander Graf     int gpio_ph;
158b88e77f4SAlexander Graf 
159b88e77f4SAlexander Graf     qemu_fdt_add_subnode(fdt, node);
160b88e77f4SAlexander Graf     qemu_fdt_setprop_string(fdt, node, "compatible", "fsl,qoriq-gpio");
161b88e77f4SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "reg", mmio0, 0x1000);
162b88e77f4SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "interrupts", irq0, 0x2);
163b88e77f4SAlexander Graf     qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic);
164b88e77f4SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "#gpio-cells", 2);
165b88e77f4SAlexander Graf     qemu_fdt_setprop(fdt, node, "gpio-controller", NULL, 0);
166016f7758SAlexander Graf     gpio_ph = qemu_fdt_alloc_phandle(fdt);
167016f7758SAlexander Graf     qemu_fdt_setprop_cell(fdt, node, "phandle", gpio_ph);
168016f7758SAlexander Graf     qemu_fdt_setprop_cell(fdt, node, "linux,phandle", gpio_ph);
169016f7758SAlexander Graf 
170016f7758SAlexander Graf     /* Power Off Pin */
171016f7758SAlexander Graf     qemu_fdt_add_subnode(fdt, poweroff);
172016f7758SAlexander Graf     qemu_fdt_setprop_string(fdt, poweroff, "compatible", "gpio-poweroff");
173016f7758SAlexander Graf     qemu_fdt_setprop_cells(fdt, poweroff, "gpios", gpio_ph, 0, 0);
174b88e77f4SAlexander Graf 
175b88e77f4SAlexander Graf     g_free(node);
176016f7758SAlexander Graf     g_free(poweroff);
177b88e77f4SAlexander Graf }
178b88e77f4SAlexander Graf 
1797abb479cSAndrew Randrianasulu static void dt_rtc_create(void *fdt, const char *i2c, const char *alias)
1807abb479cSAndrew Randrianasulu {
1817abb479cSAndrew Randrianasulu     int offset = RTC_REGS_OFFSET;
1827abb479cSAndrew Randrianasulu 
1837abb479cSAndrew Randrianasulu     gchar *rtc = g_strdup_printf("%s/rtc@%"PRIx32, i2c, offset);
1847abb479cSAndrew Randrianasulu     qemu_fdt_add_subnode(fdt, rtc);
1857abb479cSAndrew Randrianasulu     qemu_fdt_setprop_string(fdt, rtc, "compatible", "pericom,pt7c4338");
1867abb479cSAndrew Randrianasulu     qemu_fdt_setprop_cells(fdt, rtc, "reg", offset);
1877abb479cSAndrew Randrianasulu     qemu_fdt_setprop_string(fdt, "/aliases", alias, rtc);
1887abb479cSAndrew Randrianasulu 
1897abb479cSAndrew Randrianasulu     g_free(rtc);
1907abb479cSAndrew Randrianasulu }
1917abb479cSAndrew Randrianasulu 
1927abb479cSAndrew Randrianasulu static void dt_i2c_create(void *fdt, const char *soc, const char *mpic,
1937abb479cSAndrew Randrianasulu                              const char *alias)
1947abb479cSAndrew Randrianasulu {
1957abb479cSAndrew Randrianasulu     hwaddr mmio0 = MPC8544_I2C_REGS_OFFSET;
1967abb479cSAndrew Randrianasulu     int irq0 = MPC8544_I2C_IRQ;
1977abb479cSAndrew Randrianasulu 
1987abb479cSAndrew Randrianasulu     gchar *i2c = g_strdup_printf("%s/i2c@%"PRIx64, soc, mmio0);
1997abb479cSAndrew Randrianasulu     qemu_fdt_add_subnode(fdt, i2c);
2007abb479cSAndrew Randrianasulu     qemu_fdt_setprop_string(fdt, i2c, "device_type", "i2c");
2017abb479cSAndrew Randrianasulu     qemu_fdt_setprop_string(fdt, i2c, "compatible", "fsl-i2c");
2027abb479cSAndrew Randrianasulu     qemu_fdt_setprop_cells(fdt, i2c, "reg", mmio0, 0x14);
2037abb479cSAndrew Randrianasulu     qemu_fdt_setprop_cells(fdt, i2c, "cell-index", 0);
2047abb479cSAndrew Randrianasulu     qemu_fdt_setprop_cells(fdt, i2c, "interrupts", irq0, 0x2);
2057abb479cSAndrew Randrianasulu     qemu_fdt_setprop_phandle(fdt, i2c, "interrupt-parent", mpic);
2067abb479cSAndrew Randrianasulu     qemu_fdt_setprop_string(fdt, "/aliases", alias, i2c);
2077abb479cSAndrew Randrianasulu 
2087abb479cSAndrew Randrianasulu     g_free(i2c);
2097abb479cSAndrew Randrianasulu }
2107abb479cSAndrew Randrianasulu 
2113f288c4bSPhilippe Mathieu-Daudé static void dt_sdhc_create(void *fdt, const char *parent, const char *mpic)
2123f288c4bSPhilippe Mathieu-Daudé {
2133f288c4bSPhilippe Mathieu-Daudé     hwaddr mmio = MPC85XX_ESDHC_REGS_OFFSET;
2143f288c4bSPhilippe Mathieu-Daudé     hwaddr size = MPC85XX_ESDHC_REGS_SIZE;
2153f288c4bSPhilippe Mathieu-Daudé     int irq = MPC85XX_ESDHC_IRQ;
2163f288c4bSPhilippe Mathieu-Daudé     g_autofree char *name = NULL;
2173f288c4bSPhilippe Mathieu-Daudé 
2183f288c4bSPhilippe Mathieu-Daudé     name = g_strdup_printf("%s/sdhc@%" PRIx64, parent, mmio);
2193f288c4bSPhilippe Mathieu-Daudé     qemu_fdt_add_subnode(fdt, name);
2203f288c4bSPhilippe Mathieu-Daudé     qemu_fdt_setprop(fdt, name, "sdhci,auto-cmd12", NULL, 0);
2213f288c4bSPhilippe Mathieu-Daudé     qemu_fdt_setprop_phandle(fdt, name, "interrupt-parent", mpic);
2223f288c4bSPhilippe Mathieu-Daudé     qemu_fdt_setprop_cells(fdt, name, "bus-width", 4);
2233f288c4bSPhilippe Mathieu-Daudé     qemu_fdt_setprop_cells(fdt, name, "interrupts", irq, 0x2);
2243f288c4bSPhilippe Mathieu-Daudé     qemu_fdt_setprop_cells(fdt, name, "reg", mmio, size);
2253f288c4bSPhilippe Mathieu-Daudé     qemu_fdt_setprop_string(fdt, name, "compatible", "fsl,esdhc");
2263f288c4bSPhilippe Mathieu-Daudé }
2277abb479cSAndrew Randrianasulu 
228f7087343SAlexander Graf typedef struct PlatformDevtreeData {
229f7087343SAlexander Graf     void *fdt;
230f7087343SAlexander Graf     const char *mpic;
231f7087343SAlexander Graf     int irq_start;
232f7087343SAlexander Graf     const char *node;
233f7087343SAlexander Graf     PlatformBusDevice *pbus;
234f7087343SAlexander Graf } PlatformDevtreeData;
235f7087343SAlexander Graf 
236fdfb7f2cSAlexander Graf static int create_devtree_etsec(SysBusDevice *sbdev, PlatformDevtreeData *data)
237fdfb7f2cSAlexander Graf {
238fdfb7f2cSAlexander Graf     eTSEC *etsec = ETSEC_COMMON(sbdev);
239fdfb7f2cSAlexander Graf     PlatformBusDevice *pbus = data->pbus;
240fdfb7f2cSAlexander Graf     hwaddr mmio0 = platform_bus_get_mmio_addr(pbus, sbdev, 0);
241fdfb7f2cSAlexander Graf     int irq0 = platform_bus_get_irqn(pbus, sbdev, 0);
242fdfb7f2cSAlexander Graf     int irq1 = platform_bus_get_irqn(pbus, sbdev, 1);
243fdfb7f2cSAlexander Graf     int irq2 = platform_bus_get_irqn(pbus, sbdev, 2);
244fdfb7f2cSAlexander Graf     gchar *node = g_strdup_printf("/platform/ethernet@%"PRIx64, mmio0);
245fdfb7f2cSAlexander Graf     gchar *group = g_strdup_printf("%s/queue-group", node);
246fdfb7f2cSAlexander Graf     void *fdt = data->fdt;
247fdfb7f2cSAlexander Graf 
248fdfb7f2cSAlexander Graf     assert((int64_t)mmio0 >= 0);
249fdfb7f2cSAlexander Graf     assert(irq0 >= 0);
250fdfb7f2cSAlexander Graf     assert(irq1 >= 0);
251fdfb7f2cSAlexander Graf     assert(irq2 >= 0);
252fdfb7f2cSAlexander Graf 
253fdfb7f2cSAlexander Graf     qemu_fdt_add_subnode(fdt, node);
254e5943b00SBin Meng     qemu_fdt_setprop(fdt, node, "ranges", NULL, 0);
255fdfb7f2cSAlexander Graf     qemu_fdt_setprop_string(fdt, node, "device_type", "network");
256fdfb7f2cSAlexander Graf     qemu_fdt_setprop_string(fdt, node, "compatible", "fsl,etsec2");
257fdfb7f2cSAlexander Graf     qemu_fdt_setprop_string(fdt, node, "model", "eTSEC");
258fdfb7f2cSAlexander Graf     qemu_fdt_setprop(fdt, node, "local-mac-address", etsec->conf.macaddr.a, 6);
259fdfb7f2cSAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "fixed-link", 0, 1, 1000, 0, 0);
26009325678SBin Meng     qemu_fdt_setprop_cells(fdt, node, "#size-cells", 1);
26109325678SBin Meng     qemu_fdt_setprop_cells(fdt, node, "#address-cells", 1);
262fdfb7f2cSAlexander Graf 
263fdfb7f2cSAlexander Graf     qemu_fdt_add_subnode(fdt, group);
264fdfb7f2cSAlexander Graf     qemu_fdt_setprop_cells(fdt, group, "reg", mmio0, 0x1000);
265fdfb7f2cSAlexander Graf     qemu_fdt_setprop_cells(fdt, group, "interrupts",
266fdfb7f2cSAlexander Graf         data->irq_start + irq0, 0x2,
267fdfb7f2cSAlexander Graf         data->irq_start + irq1, 0x2,
268fdfb7f2cSAlexander Graf         data->irq_start + irq2, 0x2);
269fdfb7f2cSAlexander Graf 
270fdfb7f2cSAlexander Graf     g_free(node);
271fdfb7f2cSAlexander Graf     g_free(group);
272fdfb7f2cSAlexander Graf 
273fdfb7f2cSAlexander Graf     return 0;
274fdfb7f2cSAlexander Graf }
275fdfb7f2cSAlexander Graf 
2764f01a637SDavid Gibson static void sysbus_device_create_devtree(SysBusDevice *sbdev, void *opaque)
277f7087343SAlexander Graf {
278f7087343SAlexander Graf     PlatformDevtreeData *data = opaque;
279f7087343SAlexander Graf     bool matched = false;
280f7087343SAlexander Graf 
281fdfb7f2cSAlexander Graf     if (object_dynamic_cast(OBJECT(sbdev), TYPE_ETSEC_COMMON)) {
282fdfb7f2cSAlexander Graf         create_devtree_etsec(sbdev, data);
283fdfb7f2cSAlexander Graf         matched = true;
284fdfb7f2cSAlexander Graf     }
285fdfb7f2cSAlexander Graf 
286f7087343SAlexander Graf     if (!matched) {
287f7087343SAlexander Graf         error_report("Device %s is not supported by this machine yet.",
288f7087343SAlexander Graf                      qdev_fw_name(DEVICE(sbdev)));
289f7087343SAlexander Graf         exit(1);
290f7087343SAlexander Graf     }
291f7087343SAlexander Graf }
292f7087343SAlexander Graf 
29363e4bf8eSBernhard Beschow static void create_devtree_flash(SysBusDevice *sbdev,
29463e4bf8eSBernhard Beschow                                  PlatformDevtreeData *data)
29563e4bf8eSBernhard Beschow {
29663e4bf8eSBernhard Beschow     g_autofree char *name = NULL;
29763e4bf8eSBernhard Beschow     uint64_t num_blocks = object_property_get_uint(OBJECT(sbdev),
29863e4bf8eSBernhard Beschow                                                    "num-blocks",
29963e4bf8eSBernhard Beschow                                                    &error_fatal);
30063e4bf8eSBernhard Beschow     uint64_t sector_length = object_property_get_uint(OBJECT(sbdev),
30163e4bf8eSBernhard Beschow                                                       "sector-length",
30263e4bf8eSBernhard Beschow                                                       &error_fatal);
30363e4bf8eSBernhard Beschow     uint64_t bank_width = object_property_get_uint(OBJECT(sbdev),
30463e4bf8eSBernhard Beschow                                                    "width",
30563e4bf8eSBernhard Beschow                                                    &error_fatal);
30663e4bf8eSBernhard Beschow     hwaddr flashbase = 0;
30763e4bf8eSBernhard Beschow     hwaddr flashsize = num_blocks * sector_length;
30863e4bf8eSBernhard Beschow     void *fdt = data->fdt;
30963e4bf8eSBernhard Beschow 
31063e4bf8eSBernhard Beschow     name = g_strdup_printf("%s/nor@%" PRIx64, data->node, flashbase);
31163e4bf8eSBernhard Beschow     qemu_fdt_add_subnode(fdt, name);
31263e4bf8eSBernhard Beschow     qemu_fdt_setprop_string(fdt, name, "compatible", "cfi-flash");
31363e4bf8eSBernhard Beschow     qemu_fdt_setprop_sized_cells(fdt, name, "reg",
31463e4bf8eSBernhard Beschow                                  1, flashbase, 1, flashsize);
31563e4bf8eSBernhard Beschow     qemu_fdt_setprop_cell(fdt, name, "bank-width", bank_width);
31663e4bf8eSBernhard Beschow }
31763e4bf8eSBernhard Beschow 
318a3fc8396SIgor Mammedov static void platform_bus_create_devtree(PPCE500MachineState *pms,
31903f04809SIgor Mammedov                                         void *fdt, const char *mpic)
320f7087343SAlexander Graf {
321a3fc8396SIgor Mammedov     const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
32203f04809SIgor Mammedov     gchar *node = g_strdup_printf("/platform@%"PRIx64, pmc->platform_bus_base);
323f7087343SAlexander Graf     const char platcomp[] = "qemu,platform\0simple-bus";
32403f04809SIgor Mammedov     uint64_t addr = pmc->platform_bus_base;
32503f04809SIgor Mammedov     uint64_t size = pmc->platform_bus_size;
32603f04809SIgor Mammedov     int irq_start = pmc->platform_bus_first_irq;
32763e4bf8eSBernhard Beschow     SysBusDevice *sbdev;
32863e4bf8eSBernhard Beschow     bool ambiguous;
329f7087343SAlexander Graf 
330f7087343SAlexander Graf     /* Create a /platform node that we can put all devices into */
331f7087343SAlexander Graf 
332f7087343SAlexander Graf     qemu_fdt_add_subnode(fdt, node);
333f7087343SAlexander Graf     qemu_fdt_setprop(fdt, node, "compatible", platcomp, sizeof(platcomp));
334f7087343SAlexander Graf 
335f7087343SAlexander Graf     /* Our platform bus region is less than 32bit big, so 1 cell is enough for
336f7087343SAlexander Graf        address and size */
337f7087343SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "#size-cells", 1);
338f7087343SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "#address-cells", 1);
339f7087343SAlexander Graf     qemu_fdt_setprop_cells(fdt, node, "ranges", 0, addr >> 32, addr, size);
340f7087343SAlexander Graf 
341f7087343SAlexander Graf     qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic);
342f7087343SAlexander Graf 
343a3fc8396SIgor Mammedov     /* Create dt nodes for dynamic devices */
344f7087343SAlexander Graf     PlatformDevtreeData data = {
345f7087343SAlexander Graf         .fdt = fdt,
346f7087343SAlexander Graf         .mpic = mpic,
347f7087343SAlexander Graf         .irq_start = irq_start,
348f7087343SAlexander Graf         .node = node,
349a3fc8396SIgor Mammedov         .pbus = pms->pbus_dev,
350f7087343SAlexander Graf     };
351f7087343SAlexander Graf 
352f7087343SAlexander Graf     /* Loop through all dynamic sysbus devices and create nodes for them */
353f7087343SAlexander Graf     foreach_dynamic_sysbus_device(sysbus_device_create_devtree, &data);
354f7087343SAlexander Graf 
35563e4bf8eSBernhard Beschow     sbdev = SYS_BUS_DEVICE(object_resolve_path_type("", TYPE_PFLASH_CFI01,
35663e4bf8eSBernhard Beschow                                                     &ambiguous));
35763e4bf8eSBernhard Beschow     if (sbdev) {
35863e4bf8eSBernhard Beschow         assert(!ambiguous);
35963e4bf8eSBernhard Beschow         create_devtree_flash(sbdev, &data);
36063e4bf8eSBernhard Beschow     }
36163e4bf8eSBernhard Beschow 
362f7087343SAlexander Graf     g_free(node);
363f7087343SAlexander Graf }
364f7087343SAlexander Graf 
36503f04809SIgor Mammedov static int ppce500_load_device_tree(PPCE500MachineState *pms,
366a8170e5eSAvi Kivity                                     hwaddr addr,
367a8170e5eSAvi Kivity                                     hwaddr initrd_base,
36828290f37SAlexander Graf                                     hwaddr initrd_size,
369903585deSAlexander Graf                                     hwaddr kernel_base,
370903585deSAlexander Graf                                     hwaddr kernel_size,
37128290f37SAlexander Graf                                     bool dry_run)
3721db09b84Saurel32 {
37303f04809SIgor Mammedov     MachineState *machine = MACHINE(pms);
374fe6b6346SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
37503f04809SIgor Mammedov     const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
37628290f37SAlexander Graf     CPUPPCState *env = first_cpu->env_ptr;
377dbf916d8SAurelien Jarno     int ret = -1;
3783ef96221SMarcel Apfelbaum     uint64_t mem_reg_property[] = { 0, cpu_to_be64(machine->ram_size) };
3797ec632b4Spbrook     int fdt_size;
380dbf916d8SAurelien Jarno     void *fdt;
3815de6b46dSAlexander Graf     uint8_t hypercall[16];
3820c36ab71SBin Meng     uint32_t clock_freq = PLATFORM_CLK_FREQ_HZ;
3830c36ab71SBin Meng     uint32_t tb_freq = PLATFORM_CLK_FREQ_HZ;
384621d05e3SAlexander Graf     int i;
385ebb9518aSAlexander Graf     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
3862fb513d3SGreg Kurz     char *soc;
3872fb513d3SGreg Kurz     char *mpic;
38819ac9deaSAlexander Graf     uint32_t mpic_ph;
389a911b7a9SAlexander Graf     uint32_t msi_ph;
3902fb513d3SGreg Kurz     char *gutil;
3912fb513d3SGreg Kurz     char *pci;
3922fb513d3SGreg Kurz     char *msi;
393347dd79dSAlexander Graf     uint32_t *pci_map = NULL;
394347dd79dSAlexander Graf     int len;
3953627757eSAlexander Graf     uint32_t pci_ranges[14] =
3963627757eSAlexander Graf         {
39703f04809SIgor Mammedov             0x2000000, 0x0, pmc->pci_mmio_bus_base,
39803f04809SIgor Mammedov             pmc->pci_mmio_base >> 32, pmc->pci_mmio_base,
3993627757eSAlexander Graf             0x0, 0x20000000,
4003627757eSAlexander Graf 
4013627757eSAlexander Graf             0x1000000, 0x0, 0x0,
40203f04809SIgor Mammedov             pmc->pci_pio_base >> 32, pmc->pci_pio_base,
4033627757eSAlexander Graf             0x0, 0x10000,
4043627757eSAlexander Graf         };
405f2ce39b4SPaolo Bonzini     const char *dtb_file = machine->dtb;
406f2ce39b4SPaolo Bonzini     const char *toplevel_compat = machine->dt_compatible;
407c4b07531SJason A. Donenfeld     uint8_t rng_seed[32];
408d1b93565SAlexander Graf 
409d1b93565SAlexander Graf     if (dtb_file) {
410d1b93565SAlexander Graf         char *filename;
411d1b93565SAlexander Graf         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_file);
412d1b93565SAlexander Graf         if (!filename) {
413d1b93565SAlexander Graf             goto out;
414d1b93565SAlexander Graf         }
415d1b93565SAlexander Graf 
416d1b93565SAlexander Graf         fdt = load_device_tree(filename, &fdt_size);
4172343dd11SMichael Tokarev         g_free(filename);
418d1b93565SAlexander Graf         if (!fdt) {
419d1b93565SAlexander Graf             goto out;
420d1b93565SAlexander Graf         }
421d1b93565SAlexander Graf         goto done;
422d1b93565SAlexander Graf     }
4231db09b84Saurel32 
4242636fcb6SAlexander Graf     fdt = create_device_tree(&fdt_size);
4255cea8590SPaul Brook     if (fdt == NULL) {
4265cea8590SPaul Brook         goto out;
4275cea8590SPaul Brook     }
4281db09b84Saurel32 
4291db09b84Saurel32     /* Manipulate device tree in memory. */
4305a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 2);
4315a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 2);
43251b852b7SAlexander Graf 
4335a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, "/memory");
4345a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory");
4355a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
4361db09b84Saurel32                      sizeof(mem_reg_property));
4371db09b84Saurel32 
4385a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, "/chosen");
4393b989d49SAlexander Graf     if (initrd_size) {
4405a4348d1SPeter Crosthwaite         ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
4411db09b84Saurel32                                     initrd_base);
4423b989d49SAlexander Graf         if (ret < 0) {
4431db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
4443b989d49SAlexander Graf         }
4451db09b84Saurel32 
4465a4348d1SPeter Crosthwaite         ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
4471db09b84Saurel32                                     (initrd_base + initrd_size));
4483b989d49SAlexander Graf         if (ret < 0) {
4491db09b84Saurel32             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
4503b989d49SAlexander Graf         }
451903585deSAlexander Graf 
452903585deSAlexander Graf     }
453903585deSAlexander Graf 
454903585deSAlexander Graf     if (kernel_base != -1ULL) {
455903585deSAlexander Graf         qemu_fdt_setprop_cells(fdt, "/chosen", "qemu,boot-kernel",
456903585deSAlexander Graf                                      kernel_base >> 32, kernel_base,
457903585deSAlexander Graf                                      kernel_size >> 32, kernel_size);
4583b989d49SAlexander Graf     }
4591db09b84Saurel32 
4605a4348d1SPeter Crosthwaite     ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
4613ef96221SMarcel Apfelbaum                                       machine->kernel_cmdline);
4621db09b84Saurel32     if (ret < 0)
4631db09b84Saurel32         fprintf(stderr, "couldn't set /chosen/bootargs\n");
4641db09b84Saurel32 
465c4b07531SJason A. Donenfeld     qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
466c4b07531SJason A. Donenfeld     qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
467c4b07531SJason A. Donenfeld 
4681db09b84Saurel32     if (kvm_enabled()) {
469911d6e7aSAlexander Graf         /* Read out host's frequencies */
470911d6e7aSAlexander Graf         clock_freq = kvmppc_get_clockfreq();
471911d6e7aSAlexander Graf         tb_freq = kvmppc_get_tbfreq();
4725de6b46dSAlexander Graf 
4735de6b46dSAlexander Graf         /* indicate KVM hypercall interface */
4745a4348d1SPeter Crosthwaite         qemu_fdt_add_subnode(fdt, "/hypervisor");
4755a4348d1SPeter Crosthwaite         qemu_fdt_setprop_string(fdt, "/hypervisor", "compatible",
4765de6b46dSAlexander Graf                                 "linux,kvm");
4775de6b46dSAlexander Graf         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
4785a4348d1SPeter Crosthwaite         qemu_fdt_setprop(fdt, "/hypervisor", "hcall-instructions",
4795de6b46dSAlexander Graf                          hypercall, sizeof(hypercall));
4801a61a9aeSStuart Yoder         /* if KVM supports the idle hcall, set property indicating this */
4811a61a9aeSStuart Yoder         if (kvmppc_get_hasidle(env)) {
4825a4348d1SPeter Crosthwaite             qemu_fdt_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
4831a61a9aeSStuart Yoder         }
4841db09b84Saurel32     }
4851db09b84Saurel32 
486625e665bSAlexander Graf     /* Create CPU nodes */
4875a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, "/cpus");
4885a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1);
4895a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0);
490625e665bSAlexander Graf 
4911e3debf0SAlexander Graf     /* We need to generate the cpu nodes in reverse order, so Linux can pick
4921e3debf0SAlexander Graf        the first node as boot node and be happy */
4931e3debf0SAlexander Graf     for (i = smp_cpus - 1; i >= 0; i--) {
494440c8152SAndreas Färber         CPUState *cpu;
4952fb513d3SGreg Kurz         char *cpu_name;
49603f04809SIgor Mammedov         uint64_t cpu_release_addr = pmc->spin_base + (i * 0x20);
49710f25a46SAlexander Graf 
498440c8152SAndreas Färber         cpu = qemu_get_cpu(i);
49955e5c285SAndreas Färber         if (cpu == NULL) {
5001e3debf0SAlexander Graf             continue;
5011e3debf0SAlexander Graf         }
502440c8152SAndreas Färber         env = cpu->env_ptr;
5031e3debf0SAlexander Graf 
5042fb513d3SGreg Kurz         cpu_name = g_strdup_printf("/cpus/PowerPC,8544@%x", i);
5055a4348d1SPeter Crosthwaite         qemu_fdt_add_subnode(fdt, cpu_name);
5065a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "clock-frequency", clock_freq);
5075a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "timebase-frequency", tb_freq);
5085a4348d1SPeter Crosthwaite         qemu_fdt_setprop_string(fdt, cpu_name, "device_type", "cpu");
5096d536570SSam Bobroff         qemu_fdt_setprop_cell(fdt, cpu_name, "reg", i);
5105a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-line-size",
5111e3debf0SAlexander Graf                               env->dcache_line_size);
5125a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-line-size",
5131e3debf0SAlexander Graf                               env->icache_line_size);
5145a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "d-cache-size", 0x8000);
5155a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "i-cache-size", 0x8000);
5165a4348d1SPeter Crosthwaite         qemu_fdt_setprop_cell(fdt, cpu_name, "bus-frequency", 0);
51755e5c285SAndreas Färber         if (cpu->cpu_index) {
5185a4348d1SPeter Crosthwaite             qemu_fdt_setprop_string(fdt, cpu_name, "status", "disabled");
5195a4348d1SPeter Crosthwaite             qemu_fdt_setprop_string(fdt, cpu_name, "enable-method",
5205a4348d1SPeter Crosthwaite                                     "spin-table");
5215a4348d1SPeter Crosthwaite             qemu_fdt_setprop_u64(fdt, cpu_name, "cpu-release-addr",
5221d2e5c52SAlexander Graf                                  cpu_release_addr);
5231e3debf0SAlexander Graf         } else {
5245a4348d1SPeter Crosthwaite             qemu_fdt_setprop_string(fdt, cpu_name, "status", "okay");
5251e3debf0SAlexander Graf         }
5262fb513d3SGreg Kurz         g_free(cpu_name);
5271db09b84Saurel32     }
5281db09b84Saurel32 
5295a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, "/aliases");
5305da96624SAlexander Graf     /* XXX These should go into their respective devices' code */
5312fb513d3SGreg Kurz     soc = g_strdup_printf("/soc@%"PRIx64, pmc->ccsrbar_base);
5325a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, soc);
5335a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, soc, "device_type", "soc");
5345a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, soc, "compatible", compatible_sb,
535ebb9518aSAlexander Graf                      sizeof(compatible_sb));
5365a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, soc, "#address-cells", 1);
5375a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, soc, "#size-cells", 1);
5385a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, soc, "ranges", 0x0,
53903f04809SIgor Mammedov                            pmc->ccsrbar_base >> 32, pmc->ccsrbar_base,
5405da96624SAlexander Graf                            MPC8544_CCSRBAR_SIZE);
5415da96624SAlexander Graf     /* XXX should contain a reasonable value */
5425a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, soc, "bus-frequency", 0);
5435da96624SAlexander Graf 
5442fb513d3SGreg Kurz     mpic = g_strdup_printf("%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
5455a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, mpic);
5465a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, mpic, "device_type", "open-pic");
5475a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, mpic, "compatible", "fsl,mpic");
5485a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
549dffb1dc2SBharat Bhushan                            0x40000);
5505a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, mpic, "#address-cells", 0);
5515a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
5525a4348d1SPeter Crosthwaite     mpic_ph = qemu_fdt_alloc_phandle(fdt);
5535a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, mpic, "phandle", mpic_ph);
5545a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, mpic, "linux,phandle", mpic_ph);
5555a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, mpic, "interrupt-controller", NULL, 0);
55619ac9deaSAlexander Graf 
5570cfc6e8dSAlexander Graf     /*
5580cfc6e8dSAlexander Graf      * We have to generate ser1 first, because Linux takes the first
5590cfc6e8dSAlexander Graf      * device it finds in the dt as serial output device. And we generate
5600cfc6e8dSAlexander Graf      * devices in reverse order to the dt.
5610cfc6e8dSAlexander Graf      */
5629bca0edbSPeter Maydell     if (serial_hd(1)) {
563dffb1dc2SBharat Bhushan         dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
564a053a7ceSAlexander Graf                          soc, mpic, "serial1", 1, false);
56579c0ff2cSAlexander Graf     }
56679c0ff2cSAlexander Graf 
5679bca0edbSPeter Maydell     if (serial_hd(0)) {
568dffb1dc2SBharat Bhushan         dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
569a053a7ceSAlexander Graf                          soc, mpic, "serial0", 0, true);
57079c0ff2cSAlexander Graf     }
5710cfc6e8dSAlexander Graf 
5727abb479cSAndrew Randrianasulu     /* i2c */
5737abb479cSAndrew Randrianasulu     dt_i2c_create(fdt, soc, mpic, "i2c");
5747abb479cSAndrew Randrianasulu 
5757abb479cSAndrew Randrianasulu     dt_rtc_create(fdt, "i2c", "rtc");
5767abb479cSAndrew Randrianasulu 
5773f288c4bSPhilippe Mathieu-Daudé     /* sdhc */
5783f288c4bSPhilippe Mathieu-Daudé     if (pmc->has_esdhc) {
5793f288c4bSPhilippe Mathieu-Daudé         dt_sdhc_create(fdt, soc, mpic);
5803f288c4bSPhilippe Mathieu-Daudé     }
5817abb479cSAndrew Randrianasulu 
5822fb513d3SGreg Kurz     gutil = g_strdup_printf("%s/global-utilities@%llx", soc,
583dffb1dc2SBharat Bhushan                             MPC8544_UTIL_OFFSET);
5845a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, gutil);
5855a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
5865a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
5875a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
5882fb513d3SGreg Kurz     g_free(gutil);
589f5038483SAlexander Graf 
5902fb513d3SGreg Kurz     msi = g_strdup_printf("/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
5915a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, msi);
5925a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
5935a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
5945a4348d1SPeter Crosthwaite     msi_ph = qemu_fdt_alloc_phandle(fdt);
5955a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
5965a4348d1SPeter Crosthwaite     qemu_fdt_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
5975a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, msi, "interrupts",
598a911b7a9SAlexander Graf         0xe0, 0x0,
599a911b7a9SAlexander Graf         0xe1, 0x0,
600a911b7a9SAlexander Graf         0xe2, 0x0,
601a911b7a9SAlexander Graf         0xe3, 0x0,
602a911b7a9SAlexander Graf         0xe4, 0x0,
603a911b7a9SAlexander Graf         0xe5, 0x0,
604a911b7a9SAlexander Graf         0xe6, 0x0,
605a911b7a9SAlexander Graf         0xe7, 0x0);
6065a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, msi, "phandle", msi_ph);
6075a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
6082fb513d3SGreg Kurz     g_free(msi);
609a911b7a9SAlexander Graf 
6102fb513d3SGreg Kurz     pci = g_strdup_printf("/pci@%llx",
61103f04809SIgor Mammedov                           pmc->ccsrbar_base + MPC8544_PCI_REGS_OFFSET);
6125a4348d1SPeter Crosthwaite     qemu_fdt_add_subnode(fdt, pci);
6135a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "cell-index", 0);
6145a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, pci, "compatible", "fsl,mpc8540-pci");
6155a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, pci, "device_type", "pci");
6165a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
6170dbc0798SAlexander Graf                            0x0, 0x7);
6185a4348d1SPeter Crosthwaite     pci_map = pci_map_create(fdt, qemu_fdt_get_phandle(fdt, mpic),
61903f04809SIgor Mammedov                              pmc->pci_first_slot, pmc->pci_nr_slots,
620492ec48dSAlexander Graf                              &len);
6215a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, pci, "interrupt-map", pci_map, len);
6225a4348d1SPeter Crosthwaite     qemu_fdt_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
6235a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, pci, "interrupts", 24, 2);
6245a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cells(fdt, pci, "bus-range", 0, 255);
6253627757eSAlexander Graf     for (i = 0; i < 14; i++) {
6260dbc0798SAlexander Graf         pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
6270dbc0798SAlexander Graf     }
6285a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
6295a4348d1SPeter Crosthwaite     qemu_fdt_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
6302eaaac1fSAlexander Graf     qemu_fdt_setprop_cells(fdt, pci, "reg",
63103f04809SIgor Mammedov                            (pmc->ccsrbar_base + MPC8544_PCI_REGS_OFFSET) >> 32,
63203f04809SIgor Mammedov                            (pmc->ccsrbar_base + MPC8544_PCI_REGS_OFFSET),
6332eaaac1fSAlexander Graf                            0, 0x1000);
6345a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "clock-frequency", 66666666);
6355a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "#interrupt-cells", 1);
6365a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "#size-cells", 2);
6375a4348d1SPeter Crosthwaite     qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3);
6385a4348d1SPeter Crosthwaite     qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci);
6392fb513d3SGreg Kurz     g_free(pci);
6400dbc0798SAlexander Graf 
64103f04809SIgor Mammedov     if (pmc->has_mpc8xxx_gpio) {
642b88e77f4SAlexander Graf         create_dt_mpc8xxx_gpio(fdt, soc, mpic);
643b88e77f4SAlexander Graf     }
6442fb513d3SGreg Kurz     g_free(soc);
645b88e77f4SAlexander Graf 
646a3fc8396SIgor Mammedov     platform_bus_create_devtree(pms, fdt, mpic);
647*0998fcb3SBernhard Beschow 
6482fb513d3SGreg Kurz     g_free(mpic);
649f7087343SAlexander Graf 
65003f04809SIgor Mammedov     pmc->fixup_devtree(fdt);
651e6eaabebSScott Wood 
652e6eaabebSScott Wood     if (toplevel_compat) {
6535a4348d1SPeter Crosthwaite         qemu_fdt_setprop(fdt, "/", "compatible", toplevel_compat,
654e6eaabebSScott Wood                          strlen(toplevel_compat) + 1);
655e6eaabebSScott Wood     }
656e6eaabebSScott Wood 
657d1b93565SAlexander Graf done:
65828290f37SAlexander Graf     if (!dry_run) {
6595a4348d1SPeter Crosthwaite         qemu_fdt_dumpdtb(fdt, fdt_size);
66028290f37SAlexander Graf         cpu_physical_memory_write(addr, fdt, fdt_size);
661891d51beSBernhard Beschow 
662891d51beSBernhard Beschow         /* Set machine->fdt for 'dumpdtb' QMP/HMP command */
663891d51beSBernhard Beschow         g_free(machine->fdt);
664891d51beSBernhard Beschow         machine->fdt = fdt;
665891d51beSBernhard Beschow     } else {
666891d51beSBernhard Beschow         g_free(fdt);
667cba2026aSAlexander Graf     }
668cba2026aSAlexander Graf     ret = fdt_size;
6697ec632b4Spbrook 
6701db09b84Saurel32 out:
671347dd79dSAlexander Graf     g_free(pci_map);
6721db09b84Saurel32 
67304088adbSLiu Yu     return ret;
6741db09b84Saurel32 }
6751db09b84Saurel32 
67628290f37SAlexander Graf typedef struct DeviceTreeParams {
67703f04809SIgor Mammedov     PPCE500MachineState *machine;
67828290f37SAlexander Graf     hwaddr addr;
67928290f37SAlexander Graf     hwaddr initrd_base;
68028290f37SAlexander Graf     hwaddr initrd_size;
681903585deSAlexander Graf     hwaddr kernel_base;
682903585deSAlexander Graf     hwaddr kernel_size;
683f7087343SAlexander Graf     Notifier notifier;
68428290f37SAlexander Graf } DeviceTreeParams;
68528290f37SAlexander Graf 
68628290f37SAlexander Graf static void ppce500_reset_device_tree(void *opaque)
68728290f37SAlexander Graf {
68828290f37SAlexander Graf     DeviceTreeParams *p = opaque;
68903f04809SIgor Mammedov     ppce500_load_device_tree(p->machine, p->addr, p->initrd_base,
690903585deSAlexander Graf                              p->initrd_size, p->kernel_base, p->kernel_size,
691903585deSAlexander Graf                              false);
69228290f37SAlexander Graf }
69328290f37SAlexander Graf 
694f7087343SAlexander Graf static void ppce500_init_notify(Notifier *notifier, void *data)
695f7087343SAlexander Graf {
696f7087343SAlexander Graf     DeviceTreeParams *p = container_of(notifier, DeviceTreeParams, notifier);
697f7087343SAlexander Graf     ppce500_reset_device_tree(p);
698f7087343SAlexander Graf }
699f7087343SAlexander Graf 
70003f04809SIgor Mammedov static int ppce500_prep_device_tree(PPCE500MachineState *machine,
70128290f37SAlexander Graf                                     hwaddr addr,
70228290f37SAlexander Graf                                     hwaddr initrd_base,
703903585deSAlexander Graf                                     hwaddr initrd_size,
704903585deSAlexander Graf                                     hwaddr kernel_base,
705903585deSAlexander Graf                                     hwaddr kernel_size)
70628290f37SAlexander Graf {
70728290f37SAlexander Graf     DeviceTreeParams *p = g_new(DeviceTreeParams, 1);
7083ef96221SMarcel Apfelbaum     p->machine = machine;
70928290f37SAlexander Graf     p->addr = addr;
71028290f37SAlexander Graf     p->initrd_base = initrd_base;
71128290f37SAlexander Graf     p->initrd_size = initrd_size;
712903585deSAlexander Graf     p->kernel_base = kernel_base;
713903585deSAlexander Graf     p->kernel_size = kernel_size;
71428290f37SAlexander Graf 
71528290f37SAlexander Graf     qemu_register_reset(ppce500_reset_device_tree, p);
716f7087343SAlexander Graf     p->notifier.notify = ppce500_init_notify;
717f7087343SAlexander Graf     qemu_add_machine_init_done_notifier(&p->notifier);
71828290f37SAlexander Graf 
71928290f37SAlexander Graf     /* Issue the device tree loader once, so that we get the size of the blob */
72003f04809SIgor Mammedov     return ppce500_load_device_tree(machine, addr, initrd_base, initrd_size,
72103f04809SIgor Mammedov                                     kernel_base, kernel_size, true);
72228290f37SAlexander Graf }
72328290f37SAlexander Graf 
724a36848ffSAaron Larson hwaddr booke206_page_size_to_tlb(uint64_t size)
725d1e256feSAlexander Graf {
726ab3dd749SPhilippe Mathieu-Daudé     return 63 - clz64(size / KiB);
727d1e256feSAlexander Graf }
728d1e256feSAlexander Graf 
729cefd3cdbSBharat Bhushan static int booke206_initial_map_tsize(CPUPPCState *env)
7303b989d49SAlexander Graf {
731cba2026aSAlexander Graf     struct boot_info *bi = env->load_info;
732cefd3cdbSBharat Bhushan     hwaddr dt_end;
733cba2026aSAlexander Graf     int ps;
7343b989d49SAlexander Graf 
735cba2026aSAlexander Graf     /* Our initial TLB entry needs to cover everything from 0 to
736cba2026aSAlexander Graf        the device tree top */
737cba2026aSAlexander Graf     dt_end = bi->dt_base + bi->dt_size;
738cba2026aSAlexander Graf     ps = booke206_page_size_to_tlb(dt_end) + 1;
739fb37c302SAlexander Graf     if (ps & 1) {
740fb37c302SAlexander Graf         /* e500v2 can only do even TLB size bits */
741fb37c302SAlexander Graf         ps++;
742fb37c302SAlexander Graf     }
743cefd3cdbSBharat Bhushan     return ps;
744cefd3cdbSBharat Bhushan }
745cefd3cdbSBharat Bhushan 
746cefd3cdbSBharat Bhushan static uint64_t mmubooke_initial_mapsize(CPUPPCState *env)
747cefd3cdbSBharat Bhushan {
748cefd3cdbSBharat Bhushan     int tsize;
749cefd3cdbSBharat Bhushan 
750cefd3cdbSBharat Bhushan     tsize = booke206_initial_map_tsize(env);
751cefd3cdbSBharat Bhushan     return (1ULL << 10 << tsize);
752cefd3cdbSBharat Bhushan }
753cefd3cdbSBharat Bhushan 
754320c5ad8SBernhard Beschow /* Create -kernel TLB entries for BookE. */
755cefd3cdbSBharat Bhushan static void mmubooke_create_initial_mapping(CPUPPCState *env)
756cefd3cdbSBharat Bhushan {
757cefd3cdbSBharat Bhushan     ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
758cefd3cdbSBharat Bhushan     hwaddr size;
759cefd3cdbSBharat Bhushan     int ps;
760cefd3cdbSBharat Bhushan 
761cefd3cdbSBharat Bhushan     ps = booke206_initial_map_tsize(env);
762cba2026aSAlexander Graf     size = (ps << MAS1_TSIZE_SHIFT);
763d1e256feSAlexander Graf     tlb->mas1 = MAS1_VALID | size;
764cba2026aSAlexander Graf     tlb->mas2 = 0;
765cba2026aSAlexander Graf     tlb->mas7_3 = 0;
766d1e256feSAlexander Graf     tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
76793dd5e85SScott Wood 
76893dd5e85SScott Wood     env->tlb_dirty = true;
7693b989d49SAlexander Graf }
7703b989d49SAlexander Graf 
771b3305981SScott Wood static void ppce500_cpu_reset_sec(void *opaque)
7725c145dacSAlexander Graf {
77338f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
774259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
7755c145dacSAlexander Graf 
776259186a7SAndreas Färber     cpu_reset(cs);
7775c145dacSAlexander Graf 
77827103424SAndreas Färber     cs->exception_index = EXCP_HLT;
7793b989d49SAlexander Graf }
7803b989d49SAlexander Graf 
781b3305981SScott Wood static void ppce500_cpu_reset(void *opaque)
7823b989d49SAlexander Graf {
78338f92da6SAndreas Färber     PowerPCCPU *cpu = opaque;
784259186a7SAndreas Färber     CPUState *cs = CPU(cpu);
78538f92da6SAndreas Färber     CPUPPCState *env = &cpu->env;
7863b989d49SAlexander Graf     struct boot_info *bi = env->load_info;
7873b989d49SAlexander Graf 
788259186a7SAndreas Färber     cpu_reset(cs);
7893b989d49SAlexander Graf 
7903b989d49SAlexander Graf     /* Set initial guest state. */
791259186a7SAndreas Färber     cs->halted = 0;
792ab3dd749SPhilippe Mathieu-Daudé     env->gpr[1] = (16 * MiB) - 8;
7933b989d49SAlexander Graf     env->gpr[3] = bi->dt_base;
794cefd3cdbSBharat Bhushan     env->gpr[4] = 0;
795cefd3cdbSBharat Bhushan     env->gpr[5] = 0;
796cefd3cdbSBharat Bhushan     env->gpr[6] = EPAPR_MAGIC;
797cefd3cdbSBharat Bhushan     env->gpr[7] = mmubooke_initial_mapsize(env);
798cefd3cdbSBharat Bhushan     env->gpr[8] = 0;
799cefd3cdbSBharat Bhushan     env->gpr[9] = 0;
8003b989d49SAlexander Graf     env->nip = bi->entry;
801cba2026aSAlexander Graf     mmubooke_create_initial_mapping(env);
8023b989d49SAlexander Graf }
8033b989d49SAlexander Graf 
80403f04809SIgor Mammedov static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms,
8052104d4f5SGreg Kurz                                            IrqLines  *irqs)
80682fc73b6SScott Wood {
80782fc73b6SScott Wood     DeviceState *dev;
80882fc73b6SScott Wood     SysBusDevice *s;
80982fc73b6SScott Wood     int i, j, k;
81003f04809SIgor Mammedov     MachineState *machine = MACHINE(pms);
811fe6b6346SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
81203f04809SIgor Mammedov     const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
81382fc73b6SScott Wood 
8143e80f690SMarkus Armbruster     dev = qdev_new(TYPE_OPENPIC);
815d2623129SMarkus Armbruster     object_property_add_child(OBJECT(machine), "pic", OBJECT(dev));
81603f04809SIgor Mammedov     qdev_prop_set_uint32(dev, "model", pmc->mpic_version);
817d85937e6SScott Wood     qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
818d85937e6SScott Wood 
81982fc73b6SScott Wood     s = SYS_BUS_DEVICE(dev);
8203c6ef471SMarkus Armbruster     sysbus_realize_and_unref(s, &error_fatal);
82182fc73b6SScott Wood 
82282fc73b6SScott Wood     k = 0;
82382fc73b6SScott Wood     for (i = 0; i < smp_cpus; i++) {
82482fc73b6SScott Wood         for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
8252104d4f5SGreg Kurz             sysbus_connect_irq(s, k++, irqs[i].irq[j]);
82682fc73b6SScott Wood         }
82782fc73b6SScott Wood     }
82882fc73b6SScott Wood 
829d85937e6SScott Wood     return dev;
830d85937e6SScott Wood }
831d85937e6SScott Wood 
83203f04809SIgor Mammedov static DeviceState *ppce500_init_mpic_kvm(const PPCE500MachineClass *pmc,
8332104d4f5SGreg Kurz                                           IrqLines *irqs, Error **errp)
834d85937e6SScott Wood {
835d85937e6SScott Wood     DeviceState *dev;
836d85937e6SScott Wood     CPUState *cs;
837d85937e6SScott Wood 
8383e80f690SMarkus Armbruster     dev = qdev_new(TYPE_KVM_OPENPIC);
83903f04809SIgor Mammedov     qdev_prop_set_uint32(dev, "model", pmc->mpic_version);
840d85937e6SScott Wood 
841668f62ecSMarkus Armbruster     if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp)) {
842fe656ebdSMarkus Armbruster         object_unparent(OBJECT(dev));
843d85937e6SScott Wood         return NULL;
844d85937e6SScott Wood     }
845d85937e6SScott Wood 
846bdc44640SAndreas Färber     CPU_FOREACH(cs) {
847d85937e6SScott Wood         if (kvm_openpic_connect_vcpu(dev, cs)) {
848d85937e6SScott Wood             fprintf(stderr, "%s: failed to connect vcpu to irqchip\n",
849d85937e6SScott Wood                     __func__);
850d85937e6SScott Wood             abort();
851d85937e6SScott Wood         }
852d85937e6SScott Wood     }
853d85937e6SScott Wood 
854d85937e6SScott Wood     return dev;
855d85937e6SScott Wood }
856d85937e6SScott Wood 
85703f04809SIgor Mammedov static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms,
858c91c187fSMichael Davidsaver                                       MemoryRegion *ccsr,
8592104d4f5SGreg Kurz                                       IrqLines *irqs)
860d85937e6SScott Wood {
86103f04809SIgor Mammedov     const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
862d85937e6SScott Wood     DeviceState *dev = NULL;
863d85937e6SScott Wood     SysBusDevice *s;
864d85937e6SScott Wood 
865d85937e6SScott Wood     if (kvm_enabled()) {
866fe656ebdSMarkus Armbruster         Error *err = NULL;
867d85937e6SScott Wood 
8684376c40dSPaolo Bonzini         if (kvm_kernel_irqchip_allowed()) {
86903f04809SIgor Mammedov             dev = ppce500_init_mpic_kvm(pmc, irqs, &err);
870d85937e6SScott Wood         }
8714376c40dSPaolo Bonzini         if (kvm_kernel_irqchip_required() && !dev) {
872c29b77f9SMarkus Armbruster             error_reportf_err(err,
873c29b77f9SMarkus Armbruster                               "kernel_irqchip requested but unavailable: ");
874fe656ebdSMarkus Armbruster             exit(1);
875d85937e6SScott Wood         }
876d85937e6SScott Wood     }
877d85937e6SScott Wood 
878d85937e6SScott Wood     if (!dev) {
87903f04809SIgor Mammedov         dev = ppce500_init_mpic_qemu(pms, irqs);
880d85937e6SScott Wood     }
881d85937e6SScott Wood 
882d85937e6SScott Wood     s = SYS_BUS_DEVICE(dev);
88382fc73b6SScott Wood     memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET,
88482fc73b6SScott Wood                                 s->mmio[0].memory);
88582fc73b6SScott Wood 
886c91c187fSMichael Davidsaver     return dev;
88782fc73b6SScott Wood }
88882fc73b6SScott Wood 
889016f7758SAlexander Graf static void ppce500_power_off(void *opaque, int line, int on)
890016f7758SAlexander Graf {
891016f7758SAlexander Graf     if (on) {
892cf83f140SEric Blake         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
893016f7758SAlexander Graf     }
894016f7758SAlexander Graf }
895016f7758SAlexander Graf 
89603f04809SIgor Mammedov void ppce500_init(MachineState *machine)
8971db09b84Saurel32 {
89839186d8aSRichard Henderson     MemoryRegion *address_space_mem = get_system_memory();
89903f04809SIgor Mammedov     PPCE500MachineState *pms = PPCE500_MACHINE(machine);
90003f04809SIgor Mammedov     const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(machine);
9011db09b84Saurel32     PCIBus *pci_bus;
902e2684c0bSAndreas Färber     CPUPPCState *env = NULL;
9033812c71fSAlexander Graf     uint64_t loadaddr;
9043812c71fSAlexander Graf     hwaddr kernel_base = -1LL;
9053812c71fSAlexander Graf     int kernel_size = 0;
9063812c71fSAlexander Graf     hwaddr dt_base = 0;
9073812c71fSAlexander Graf     hwaddr initrd_base = 0;
9083812c71fSAlexander Graf     int initrd_size = 0;
9093812c71fSAlexander Graf     hwaddr cur_base = 0;
9103812c71fSAlexander Graf     char *filename;
9118d622594SDavid Engraf     const char *payload_name;
9128d622594SDavid Engraf     bool kernel_as_payload;
9133812c71fSAlexander Graf     hwaddr bios_entry = 0;
9148d622594SDavid Engraf     target_long payload_size;
915a80fc80eSBernhard Beschow     struct boot_info *boot_info = NULL;
9163812c71fSAlexander Graf     int dt_size;
91782fc73b6SScott Wood     int i;
918fe6b6346SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
919d575a6ceSBharat Bhushan     /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and
920d575a6ceSBharat Bhushan      * 4 respectively */
921d575a6ceSBharat Bhushan     unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4};
9222104d4f5SGreg Kurz     IrqLines *irqs;
923c91c187fSMichael Davidsaver     DeviceState *dev, *mpicdev;
92463e4bf8eSBernhard Beschow     DriveInfo *dinfo;
925e2684c0bSAndreas Färber     CPUPPCState *firstenv = NULL;
9263eddc1beSBharat Bhushan     MemoryRegion *ccsr_addr_space;
927dffb1dc2SBharat Bhushan     SysBusDevice *s;
9283eddc1beSBharat Bhushan     PPCE500CCSRState *ccsr;
9297abb479cSAndrew Randrianasulu     I2CBus *i2c;
9301db09b84Saurel32 
9312104d4f5SGreg Kurz     irqs = g_new0(IrqLines, smp_cpus);
932e61c36d5SAlexander Graf     for (i = 0; i < smp_cpus; i++) {
933397b457dSAndreas Färber         PowerPCCPU *cpu;
93455e5c285SAndreas Färber         CPUState *cs;
935397b457dSAndreas Färber 
936a2c93f06SThiago Jung Bauermann         cpu = POWERPC_CPU(object_new(machine->cpu_type));
937397b457dSAndreas Färber         env = &cpu->env;
93855e5c285SAndreas Färber         cs = CPU(cpu);
9391db09b84Saurel32 
94000469dc3SValentin Plotkin         if (env->mmu_model != POWERPC_MMU_BOOKE206) {
9416f76b817SAlistair Francis             error_report("MMU model %i not supported by this machine",
94200469dc3SValentin Plotkin                          env->mmu_model);
94300469dc3SValentin Plotkin             exit(1);
94400469dc3SValentin Plotkin         }
94500469dc3SValentin Plotkin 
946a2c93f06SThiago Jung Bauermann         /*
947a2c93f06SThiago Jung Bauermann          * Secondary CPU starts in halted state for now. Needs to change
948a2c93f06SThiago Jung Bauermann          * when implementing non-kernel boot.
949a2c93f06SThiago Jung Bauermann          */
950a2c93f06SThiago Jung Bauermann         object_property_set_bool(OBJECT(cs), "start-powered-off", i != 0,
951a2c93f06SThiago Jung Bauermann                                  &error_fatal);
952a2c93f06SThiago Jung Bauermann         qdev_realize_and_unref(DEVICE(cs), NULL, &error_fatal);
953a2c93f06SThiago Jung Bauermann 
954e61c36d5SAlexander Graf         if (!firstenv) {
955e61c36d5SAlexander Graf             firstenv = env;
956e61c36d5SAlexander Graf         }
957e61c36d5SAlexander Graf 
9585e66cd0cSCédric Le Goater         irqs[i].irq[OPENPIC_OUTPUT_INT] =
9595e66cd0cSCédric Le Goater             qdev_get_gpio_in(DEVICE(cpu), PPCE500_INPUT_INT);
9605e66cd0cSCédric Le Goater         irqs[i].irq[OPENPIC_OUTPUT_CINT] =
9615e66cd0cSCédric Le Goater             qdev_get_gpio_in(DEVICE(cpu), PPCE500_INPUT_CINT);
9626a450df9SAlexander Graf         env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
96303f04809SIgor Mammedov         env->mpic_iack = pmc->ccsrbar_base + MPC8544_MPIC_REGS_OFFSET + 0xa0;
964e61c36d5SAlexander Graf 
9650c36ab71SBin Meng         ppc_booke_timers_init(cpu, PLATFORM_CLK_FREQ_HZ, PPC_TIMER_E500);
9663b989d49SAlexander Graf 
9673b989d49SAlexander Graf         /* Register reset handler */
9685c145dacSAlexander Graf         if (!i) {
9695c145dacSAlexander Graf             /* Primary CPU */
970b21e2380SMarkus Armbruster             boot_info = g_new0(struct boot_info, 1);
971b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset, cpu);
972e61c36d5SAlexander Graf             env->load_info = boot_info;
9735c145dacSAlexander Graf         } else {
9745c145dacSAlexander Graf             /* Secondary CPUs */
975b3305981SScott Wood             qemu_register_reset(ppce500_cpu_reset_sec, cpu);
9765c145dacSAlexander Graf         }
977e61c36d5SAlexander Graf     }
978e61c36d5SAlexander Graf 
979e61c36d5SAlexander Graf     env = firstenv;
9803b989d49SAlexander Graf 
9813538e846SIgor Mammedov     if (!QEMU_IS_ALIGNED(machine->ram_size, RAM_SIZES_ALIGN)) {
9823538e846SIgor Mammedov         error_report("RAM size must be multiple of %" PRIu64, RAM_SIZES_ALIGN);
9833538e846SIgor Mammedov         exit(EXIT_FAILURE);
9843538e846SIgor Mammedov     }
9851db09b84Saurel32 
9861db09b84Saurel32     /* Register Memory */
98797316645SIgor Mammedov     memory_region_add_subregion(address_space_mem, 0, machine->ram);
9881db09b84Saurel32 
9893e80f690SMarkus Armbruster     dev = qdev_new("e500-ccsr");
9901a3e6528SBernhard Beschow     object_property_add_child(OBJECT(machine), "e500-ccsr", OBJECT(dev));
9913c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
9923eddc1beSBharat Bhushan     ccsr = CCSR(dev);
9933eddc1beSBharat Bhushan     ccsr_addr_space = &ccsr->ccsr_space;
99403f04809SIgor Mammedov     memory_region_add_subregion(address_space_mem, pmc->ccsrbar_base,
9953eddc1beSBharat Bhushan                                 ccsr_addr_space);
996dffb1dc2SBharat Bhushan 
99703f04809SIgor Mammedov     mpicdev = ppce500_init_mpic(pms, ccsr_addr_space, irqs);
998ef0efa1aSGan Qixin     g_free(irqs);
9991db09b84Saurel32 
10001db09b84Saurel32     /* Serial */
10019bca0edbSPeter Maydell     if (serial_hd(0)) {
10023eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
1003c91c187fSMichael Davidsaver                        0, qdev_get_gpio_in(mpicdev, 42), 399193,
10049bca0edbSPeter Maydell                        serial_hd(0), DEVICE_BIG_ENDIAN);
10052d48377aSBlue Swirl     }
10061db09b84Saurel32 
10079bca0edbSPeter Maydell     if (serial_hd(1)) {
10083eddc1beSBharat Bhushan         serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
1009c91c187fSMichael Davidsaver                        0, qdev_get_gpio_in(mpicdev, 42), 399193,
10109bca0edbSPeter Maydell                        serial_hd(1), DEVICE_BIG_ENDIAN);
10112d48377aSBlue Swirl     }
10123f288c4bSPhilippe Mathieu-Daudé 
10137abb479cSAndrew Randrianasulu     /* I2C */
10143e80f690SMarkus Armbruster     dev = qdev_new("mpc-i2c");
10157abb479cSAndrew Randrianasulu     s = SYS_BUS_DEVICE(dev);
10163c6ef471SMarkus Armbruster     sysbus_realize_and_unref(s, &error_fatal);
10177abb479cSAndrew Randrianasulu     sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8544_I2C_IRQ));
10187abb479cSAndrew Randrianasulu     memory_region_add_subregion(ccsr_addr_space, MPC8544_I2C_REGS_OFFSET,
10197abb479cSAndrew Randrianasulu                                 sysbus_mmio_get_region(s, 0));
10207abb479cSAndrew Randrianasulu     i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
10211373b15bSPhilippe Mathieu-Daudé     i2c_slave_create_simple(i2c, "ds1338", RTC_REGS_OFFSET);
10227abb479cSAndrew Randrianasulu 
10233f288c4bSPhilippe Mathieu-Daudé     /* eSDHC */
10243f288c4bSPhilippe Mathieu-Daudé     if (pmc->has_esdhc) {
10253f288c4bSPhilippe Mathieu-Daudé         create_unimplemented_device("esdhc",
10263f288c4bSPhilippe Mathieu-Daudé                                     pmc->ccsrbar_base + MPC85XX_ESDHC_REGS_OFFSET,
10273f288c4bSPhilippe Mathieu-Daudé                                     MPC85XX_ESDHC_REGS_SIZE);
10283f288c4bSPhilippe Mathieu-Daudé 
10293f288c4bSPhilippe Mathieu-Daudé         /*
10303f288c4bSPhilippe Mathieu-Daudé          * Compatible with:
10313f288c4bSPhilippe Mathieu-Daudé          * - SD Host Controller Specification Version 2.0 Part A2
10323f288c4bSPhilippe Mathieu-Daudé          * (See MPC8569E Reference Manual)
10333f288c4bSPhilippe Mathieu-Daudé          */
10343f288c4bSPhilippe Mathieu-Daudé         dev = qdev_new(TYPE_SYSBUS_SDHCI);
10353f288c4bSPhilippe Mathieu-Daudé         qdev_prop_set_uint8(dev, "sd-spec-version", 2);
10363f288c4bSPhilippe Mathieu-Daudé         qdev_prop_set_uint8(dev, "endianness", DEVICE_BIG_ENDIAN);
10373f288c4bSPhilippe Mathieu-Daudé         s = SYS_BUS_DEVICE(dev);
10383f288c4bSPhilippe Mathieu-Daudé         sysbus_realize_and_unref(s, &error_fatal);
10393f288c4bSPhilippe Mathieu-Daudé         sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC85XX_ESDHC_IRQ));
10403f288c4bSPhilippe Mathieu-Daudé         memory_region_add_subregion(ccsr_addr_space, MPC85XX_ESDHC_REGS_OFFSET,
10413f288c4bSPhilippe Mathieu-Daudé                                     sysbus_mmio_get_region(s, 0));
10423f288c4bSPhilippe Mathieu-Daudé     }
10431db09b84Saurel32 
1044b0fb8423SAlexander Graf     /* General Utility device */
10453e80f690SMarkus Armbruster     dev = qdev_new("mpc8544-guts");
1046dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
10473c6ef471SMarkus Armbruster     sysbus_realize_and_unref(s, &error_fatal);
10483eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,
1049dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
1050b0fb8423SAlexander Graf 
10511db09b84Saurel32     /* PCI */
10523e80f690SMarkus Armbruster     dev = qdev_new("e500-pcihost");
10531a3e6528SBernhard Beschow     object_property_add_child(OBJECT(machine), "pci-host", OBJECT(dev));
105403f04809SIgor Mammedov     qdev_prop_set_uint32(dev, "first_slot", pmc->pci_first_slot);
10553016dca0SBharat Bhushan     qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]);
1056dffb1dc2SBharat Bhushan     s = SYS_BUS_DEVICE(dev);
10573c6ef471SMarkus Armbruster     sysbus_realize_and_unref(s, &error_fatal);
1058d575a6ceSBharat Bhushan     for (i = 0; i < PCI_NUM_PINS; i++) {
1059c91c187fSMichael Davidsaver         sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, pci_irq_nrs[i]));
1060d575a6ceSBharat Bhushan     }
1061d575a6ceSBharat Bhushan 
10623eddc1beSBharat Bhushan     memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
1063dffb1dc2SBharat Bhushan                                 sysbus_mmio_get_region(s, 0));
1064dffb1dc2SBharat Bhushan 
1065d461e3b9SAlexander Graf     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
10661db09b84Saurel32     if (!pci_bus)
10671db09b84Saurel32         printf("couldn't create PCI controller!\n");
10681db09b84Saurel32 
10691db09b84Saurel32     if (pci_bus) {
10701db09b84Saurel32         /* Register network interfaces. */
10711db09b84Saurel32         for (i = 0; i < nb_nics; i++) {
107252310c3fSPaolo Bonzini             pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio-net-pci", NULL);
10731db09b84Saurel32         }
10741db09b84Saurel32     }
10751db09b84Saurel32 
10765c145dacSAlexander Graf     /* Register spinning region */
107703f04809SIgor Mammedov     sysbus_create_simple("e500-spin", pmc->spin_base, NULL);
10785c145dacSAlexander Graf 
107903f04809SIgor Mammedov     if (pmc->has_mpc8xxx_gpio) {
1080016f7758SAlexander Graf         qemu_irq poweroff_irq;
1081016f7758SAlexander Graf 
10823e80f690SMarkus Armbruster         dev = qdev_new("mpc8xxx_gpio");
1083b88e77f4SAlexander Graf         s = SYS_BUS_DEVICE(dev);
10843c6ef471SMarkus Armbruster         sysbus_realize_and_unref(s, &error_fatal);
1085c91c187fSMichael Davidsaver         sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8XXX_GPIO_IRQ));
1086b88e77f4SAlexander Graf         memory_region_add_subregion(ccsr_addr_space, MPC8XXX_GPIO_OFFSET,
1087b88e77f4SAlexander Graf                                     sysbus_mmio_get_region(s, 0));
1088016f7758SAlexander Graf 
1089016f7758SAlexander Graf         /* Power Off GPIO at Pin 0 */
1090016f7758SAlexander Graf         poweroff_irq = qemu_allocate_irq(ppce500_power_off, NULL, 0);
1091016f7758SAlexander Graf         qdev_connect_gpio_out(dev, 0, poweroff_irq);
1092b88e77f4SAlexander Graf     }
1093b88e77f4SAlexander Graf 
1094f7087343SAlexander Graf     /* Platform Bus Device */
10953e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
1096163f3847SKevin Wolf     dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
109703f04809SIgor Mammedov     qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs);
109803f04809SIgor Mammedov     qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size);
10993c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1100a3fc8396SIgor Mammedov     pms->pbus_dev = PLATFORM_BUS_DEVICE(dev);
1101f7087343SAlexander Graf 
1102a3fc8396SIgor Mammedov     s = SYS_BUS_DEVICE(pms->pbus_dev);
110303f04809SIgor Mammedov     for (i = 0; i < pmc->platform_bus_num_irqs; i++) {
110403f04809SIgor Mammedov         int irqn = pmc->platform_bus_first_irq + i;
1105c91c187fSMichael Davidsaver         sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn));
1106f7087343SAlexander Graf     }
1107f7087343SAlexander Graf 
1108f7087343SAlexander Graf     memory_region_add_subregion(address_space_mem,
110903f04809SIgor Mammedov                                 pmc->platform_bus_base,
1110bacb4eb8SBernhard Beschow                                 &pms->pbus_dev->mmio);
1111f7087343SAlexander Graf 
111263e4bf8eSBernhard Beschow     dinfo = drive_get(IF_PFLASH, 0, 0);
111363e4bf8eSBernhard Beschow     if (dinfo) {
111463e4bf8eSBernhard Beschow         BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
111563e4bf8eSBernhard Beschow         BlockDriverState *bs = blk_bs(blk);
111663e4bf8eSBernhard Beschow         uint64_t mmio_size = memory_region_size(&pms->pbus_dev->mmio);
111763e4bf8eSBernhard Beschow         uint64_t size = bdrv_getlength(bs);
111863e4bf8eSBernhard Beschow         uint32_t sector_len = 64 * KiB;
111963e4bf8eSBernhard Beschow 
112063e4bf8eSBernhard Beschow         if (!is_power_of_2(size)) {
112163e4bf8eSBernhard Beschow             error_report("Size of pflash file must be a power of two.");
112263e4bf8eSBernhard Beschow             exit(1);
112363e4bf8eSBernhard Beschow         }
112463e4bf8eSBernhard Beschow 
112563e4bf8eSBernhard Beschow         if (size > mmio_size) {
112663e4bf8eSBernhard Beschow             error_report("Size of pflash file must not be bigger than %" PRIu64
112763e4bf8eSBernhard Beschow                          " bytes.", mmio_size);
112863e4bf8eSBernhard Beschow             exit(1);
112963e4bf8eSBernhard Beschow         }
113063e4bf8eSBernhard Beschow 
113163e4bf8eSBernhard Beschow         if (!QEMU_IS_ALIGNED(size, sector_len)) {
113263e4bf8eSBernhard Beschow             error_report("Size of pflash file must be a multiple of %" PRIu32
113363e4bf8eSBernhard Beschow                          ".", sector_len);
113463e4bf8eSBernhard Beschow             exit(1);
113563e4bf8eSBernhard Beschow         }
113663e4bf8eSBernhard Beschow 
113763e4bf8eSBernhard Beschow         dev = qdev_new(TYPE_PFLASH_CFI01);
113863e4bf8eSBernhard Beschow         qdev_prop_set_drive(dev, "drive", blk);
113963e4bf8eSBernhard Beschow         qdev_prop_set_uint32(dev, "num-blocks", size / sector_len);
114063e4bf8eSBernhard Beschow         qdev_prop_set_uint64(dev, "sector-length", sector_len);
114163e4bf8eSBernhard Beschow         qdev_prop_set_uint8(dev, "width", 2);
114263e4bf8eSBernhard Beschow         qdev_prop_set_bit(dev, "big-endian", true);
114363e4bf8eSBernhard Beschow         qdev_prop_set_uint16(dev, "id0", 0x89);
114463e4bf8eSBernhard Beschow         qdev_prop_set_uint16(dev, "id1", 0x18);
114563e4bf8eSBernhard Beschow         qdev_prop_set_uint16(dev, "id2", 0x0000);
114663e4bf8eSBernhard Beschow         qdev_prop_set_uint16(dev, "id3", 0x0);
114763e4bf8eSBernhard Beschow         qdev_prop_set_string(dev, "name", "e500.flash");
114863e4bf8eSBernhard Beschow         sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
114963e4bf8eSBernhard Beschow 
115063e4bf8eSBernhard Beschow         memory_region_add_subregion(&pms->pbus_dev->mmio, 0,
115163e4bf8eSBernhard Beschow                                     pflash_cfi01_get_memory(PFLASH_CFI01(dev)));
115263e4bf8eSBernhard Beschow     }
115363e4bf8eSBernhard Beschow 
11548d622594SDavid Engraf     /*
11558d622594SDavid Engraf      * Smart firmware defaults ahead!
11568d622594SDavid Engraf      *
11578d622594SDavid Engraf      * We follow the following table to select which payload we execute.
11588d622594SDavid Engraf      *
11598d622594SDavid Engraf      *  -kernel | -bios | payload
11608d622594SDavid Engraf      * ---------+-------+---------
11618d622594SDavid Engraf      *     N    |   Y   | u-boot
11628d622594SDavid Engraf      *     N    |   N   | u-boot
11638d622594SDavid Engraf      *     Y    |   Y   | u-boot
11648d622594SDavid Engraf      *     Y    |   N   | kernel
11658d622594SDavid Engraf      *
11668d622594SDavid Engraf      * This ensures backwards compatibility with how we used to expose
11678d622594SDavid Engraf      * -kernel to users but allows them to run through u-boot as well.
11688d622594SDavid Engraf      */
11698d622594SDavid Engraf     kernel_as_payload = false;
1170cd7b9498SPaolo Bonzini     if (machine->firmware == NULL) {
11713ef96221SMarcel Apfelbaum         if (machine->kernel_filename) {
11728d622594SDavid Engraf             payload_name = machine->kernel_filename;
11738d622594SDavid Engraf             kernel_as_payload = true;
11748d622594SDavid Engraf         } else {
11758d622594SDavid Engraf             payload_name = "u-boot.e500";
11768d622594SDavid Engraf         }
11778d622594SDavid Engraf     } else {
1178cd7b9498SPaolo Bonzini         payload_name = machine->firmware;
11798d622594SDavid Engraf     }
11808d622594SDavid Engraf 
11818d622594SDavid Engraf     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name);
11823b4f50bdSPeter Maydell     if (!filename) {
11833b4f50bdSPeter Maydell         error_report("could not find firmware/kernel file '%s'", payload_name);
11843b4f50bdSPeter Maydell         exit(1);
11853b4f50bdSPeter Maydell     }
11868d622594SDavid Engraf 
11874366e1dbSLiam Merwick     payload_size = load_elf(filename, NULL, NULL, NULL,
11886cdda0ffSAleksandar Markovic                             &bios_entry, &loadaddr, NULL, NULL,
11898d622594SDavid Engraf                             1, PPC_ELF_MACHINE, 0, 0);
11908d622594SDavid Engraf     if (payload_size < 0) {
11918d622594SDavid Engraf         /*
11928d622594SDavid Engraf          * Hrm. No ELF image? Try a uImage, maybe someone is giving us an
11938d622594SDavid Engraf          * ePAPR compliant kernel
11948d622594SDavid Engraf          */
1195f831f955SNick Hudson         loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
11968d622594SDavid Engraf         payload_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
11978d622594SDavid Engraf                                    NULL, NULL);
11988d622594SDavid Engraf         if (payload_size < 0) {
1199371b74e2SMao Zhongyi             error_report("could not load firmware '%s'", filename);
12008d622594SDavid Engraf             exit(1);
12018d622594SDavid Engraf         }
12028d622594SDavid Engraf     }
12038d622594SDavid Engraf 
12048d622594SDavid Engraf     g_free(filename);
12058d622594SDavid Engraf 
12068d622594SDavid Engraf     if (kernel_as_payload) {
12078d622594SDavid Engraf         kernel_base = loadaddr;
12088d622594SDavid Engraf         kernel_size = payload_size;
12098d622594SDavid Engraf     }
12108d622594SDavid Engraf 
12118d622594SDavid Engraf     cur_base = loadaddr + payload_size;
1212ab3dd749SPhilippe Mathieu-Daudé     if (cur_base < 32 * MiB) {
1213b4a5f24aSDavid Engraf         /* u-boot occupies memory up to 32MB, so load blobs above */
1214ab3dd749SPhilippe Mathieu-Daudé         cur_base = 32 * MiB;
1215b4a5f24aSDavid Engraf     }
12168d622594SDavid Engraf 
12178d622594SDavid Engraf     /* Load bare kernel only if no bios/u-boot has been provided */
12188d622594SDavid Engraf     if (machine->kernel_filename && !kernel_as_payload) {
12193812c71fSAlexander Graf         kernel_base = cur_base;
12203812c71fSAlexander Graf         kernel_size = load_image_targphys(machine->kernel_filename,
12213812c71fSAlexander Graf                                           cur_base,
12223538e846SIgor Mammedov                                           machine->ram_size - cur_base);
12231db09b84Saurel32         if (kernel_size < 0) {
12246f76b817SAlistair Francis             error_report("could not load kernel '%s'",
12253ef96221SMarcel Apfelbaum                          machine->kernel_filename);
12261db09b84Saurel32             exit(1);
12271db09b84Saurel32         }
1228528e536eSAlexander Graf 
12293812c71fSAlexander Graf         cur_base += kernel_size;
12301db09b84Saurel32     }
12311db09b84Saurel32 
12321db09b84Saurel32     /* Load initrd. */
12333ef96221SMarcel Apfelbaum     if (machine->initrd_filename) {
1234528e536eSAlexander Graf         initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
12353ef96221SMarcel Apfelbaum         initrd_size = load_image_targphys(machine->initrd_filename, initrd_base,
12363538e846SIgor Mammedov                                           machine->ram_size - initrd_base);
12371db09b84Saurel32 
12381db09b84Saurel32         if (initrd_size < 0) {
12396f76b817SAlistair Francis             error_report("could not load initial ram disk '%s'",
12403ef96221SMarcel Apfelbaum                          machine->initrd_filename);
12411db09b84Saurel32             exit(1);
12421db09b84Saurel32         }
1243528e536eSAlexander Graf 
1244528e536eSAlexander Graf         cur_base = initrd_base + initrd_size;
12451db09b84Saurel32     }
12461db09b84Saurel32 
12473812c71fSAlexander Graf     /*
12488d622594SDavid Engraf      * Reserve space for dtb behind the kernel image because Linux has a bug
12498d622594SDavid Engraf      * where it can only handle the dtb if it's within the first 64MB of where
12508d622594SDavid Engraf      * <kernel> starts. dtb cannot not reach initrd_base because INITRD_LOAD_PAD
12518d622594SDavid Engraf      * ensures enough space between kernel and initrd.
12523812c71fSAlexander Graf      */
12538d622594SDavid Engraf     dt_base = (loadaddr + payload_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
12543538e846SIgor Mammedov     if (dt_base + DTB_MAX_SIZE > machine->ram_size) {
1255371b74e2SMao Zhongyi             error_report("not enough memory for device tree");
12563812c71fSAlexander Graf             exit(1);
12573812c71fSAlexander Graf     }
12585c145dacSAlexander Graf 
125903f04809SIgor Mammedov     dt_size = ppce500_prep_device_tree(pms, dt_base,
1260903585deSAlexander Graf                                        initrd_base, initrd_size,
12613812c71fSAlexander Graf                                        kernel_base, kernel_size);
1262cba2026aSAlexander Graf     if (dt_size < 0) {
12636f76b817SAlistair Francis         error_report("couldn't load device tree");
12641db09b84Saurel32         exit(1);
12651db09b84Saurel32     }
1266b8dec144SAlexander Graf     assert(dt_size < DTB_MAX_SIZE);
12671db09b84Saurel32 
12683812c71fSAlexander Graf     boot_info->entry = bios_entry;
12693b989d49SAlexander Graf     boot_info->dt_base = dt_base;
1270cba2026aSAlexander Graf     boot_info->dt_size = dt_size;
12711db09b84Saurel32 }
12723eddc1beSBharat Bhushan 
1273d0c2b0d0Sxiaoqiang zhao static void e500_ccsr_initfn(Object *obj)
12743eddc1beSBharat Bhushan {
1275d0c2b0d0Sxiaoqiang zhao     PPCE500CCSRState *ccsr = CCSR(obj);
1276d0c2b0d0Sxiaoqiang zhao     memory_region_init(&ccsr->ccsr_space, obj, "e500-ccsr",
12773eddc1beSBharat Bhushan                        MPC8544_CCSRBAR_SIZE);
12783eddc1beSBharat Bhushan }
12793eddc1beSBharat Bhushan 
12803eddc1beSBharat Bhushan static const TypeInfo e500_ccsr_info = {
12813eddc1beSBharat Bhushan     .name          = TYPE_CCSR,
12823eddc1beSBharat Bhushan     .parent        = TYPE_SYS_BUS_DEVICE,
12833eddc1beSBharat Bhushan     .instance_size = sizeof(PPCE500CCSRState),
1284d0c2b0d0Sxiaoqiang zhao     .instance_init = e500_ccsr_initfn,
12853eddc1beSBharat Bhushan };
12863eddc1beSBharat Bhushan 
128703f04809SIgor Mammedov static const TypeInfo ppce500_info = {
128803f04809SIgor Mammedov     .name          = TYPE_PPCE500_MACHINE,
128903f04809SIgor Mammedov     .parent        = TYPE_MACHINE,
129003f04809SIgor Mammedov     .abstract      = true,
1291a3fc8396SIgor Mammedov     .instance_size = sizeof(PPCE500MachineState),
129203f04809SIgor Mammedov     .class_size    = sizeof(PPCE500MachineClass),
129303f04809SIgor Mammedov };
129403f04809SIgor Mammedov 
12953eddc1beSBharat Bhushan static void e500_register_types(void)
12963eddc1beSBharat Bhushan {
12973eddc1beSBharat Bhushan     type_register_static(&e500_ccsr_info);
129803f04809SIgor Mammedov     type_register_static(&ppce500_info);
12993eddc1beSBharat Bhushan }
13003eddc1beSBharat Bhushan 
13013eddc1beSBharat Bhushan type_init(e500_register_types)
1302