aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2014-10-01 16:00:49 +0200
committerAlexander Graf <agraf@suse.de>2014-11-04 23:26:12 +0100
commitb88e77f49331f1187118b7ce2494ec169d3a865a (patch)
treef36415c20f485bb94f61fbb27888ad33e6542fb7
parent228aa992fc5be408888c423b6a5b30daf18a96cf (diff)
PPC: E500: Instantiate MPC8XXX gpio controller on virt machine
With the e500 virt machine, we don't have to adhere to the exact hardware layout of an mpc8544ds board. So there we can just add a qoriq compatible GPIO controller into the system that we can add a power off hook to. Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--hw/ppc/e500.c32
-rw-r--r--hw/ppc/e500.h1
-rw-r--r--hw/ppc/e500plat.c1
3 files changed, 34 insertions, 0 deletions
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 2157d87c19..304c124ffd 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -61,6 +61,8 @@
#define MPC8544_PCI_IO 0xE1000000ULL
#define MPC8544_UTIL_OFFSET 0xe0000ULL
#define MPC8544_SPIN_BASE 0xEF000000ULL
+#define MPC8XXX_GPIO_OFFSET 0x000FF000ULL
+#define MPC8XXX_GPIO_IRQ 43
struct boot_info
{
@@ -122,6 +124,23 @@ static void dt_serial_create(void *fdt, unsigned long long offset,
}
}
+static void create_dt_mpc8xxx_gpio(void *fdt, const char *soc, const char *mpic)
+{
+ hwaddr mmio0 = MPC8XXX_GPIO_OFFSET;
+ int irq0 = MPC8XXX_GPIO_IRQ;
+ gchar *node = g_strdup_printf("%s/gpio@%"PRIx64, soc, mmio0);
+
+ qemu_fdt_add_subnode(fdt, node);
+ qemu_fdt_setprop_string(fdt, node, "compatible", "fsl,qoriq-gpio");
+ qemu_fdt_setprop_cells(fdt, node, "reg", mmio0, 0x1000);
+ qemu_fdt_setprop_cells(fdt, node, "interrupts", irq0, 0x2);
+ qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic);
+ qemu_fdt_setprop_cells(fdt, node, "#gpio-cells", 2);
+ qemu_fdt_setprop(fdt, node, "gpio-controller", NULL, 0);
+
+ g_free(node);
+}
+
static int ppce500_load_device_tree(MachineState *machine,
PPCE500Params *params,
hwaddr addr,
@@ -379,6 +398,10 @@ static int ppce500_load_device_tree(MachineState *machine,
qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3);
qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci);
+ if (params->has_mpc8xxx_gpio) {
+ create_dt_mpc8xxx_gpio(fdt, soc, mpic);
+ }
+
params->fixup_devtree(params, fdt);
if (toplevel_compat) {
@@ -769,6 +792,15 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
cur_base = (32 * 1024 * 1024);
}
+ if (params->has_mpc8xxx_gpio) {
+ dev = qdev_create(NULL, "mpc8xxx_gpio");
+ s = SYS_BUS_DEVICE(dev);
+ qdev_init_nofail(dev);
+ sysbus_connect_irq(s, 0, mpic[MPC8XXX_GPIO_IRQ]);
+ memory_region_add_subregion(ccsr_addr_space, MPC8XXX_GPIO_OFFSET,
+ sysbus_mmio_get_region(s, 0));
+ }
+
/* Load kernel. */
if (machine->kernel_filename) {
kernel_base = cur_base;
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index 08b25fab49..83c5b8bf0f 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -11,6 +11,7 @@ typedef struct PPCE500Params {
void (*fixup_devtree)(struct PPCE500Params *params, void *fdt);
int mpic_version;
+ bool has_mpc8xxx_gpio;
} PPCE500Params;
void ppce500_init(MachineState *machine, PPCE500Params *params);
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 27df31ddb0..bafb56d9ff 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -35,6 +35,7 @@ static void e500plat_init(MachineState *machine)
.pci_nr_slots = PCI_SLOT_MAX - 1,
.fixup_devtree = e500plat_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_42,
+ .has_mpc8xxx_gpio = true,
};
/* Older KVM versions don't support EPR which breaks guests when we announce