PPC: E500: Implement reboot controller
authorAlexander Graf <agraf@suse.de>
Thu, 2 Jun 2011 11:53:40 +0000 (13:53 +0200)
committerAlexander Graf <agraf@suse.de>
Fri, 17 Jun 2011 00:58:23 +0000 (02:58 +0200)
When Linux reboots an e500 VM, it writes to a magic register in the
"global-utilities" device indicated by the device tree. We were not
emulating that device so far, rendering the VM reboot-less.

This patch implements that device with only the reboot functionality
implemented and adds it to the device tree. With this patch applied,
I can successfully reboot a -M mpc8544ds VM.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Andreas Färber <andreas.faerber@web.de>
Makefile.target
hw/mpc8544_guts.c [new file with mode: 0644]
hw/ppce500_mpc8544ds.c
pc-bios/mpc8544ds.dtb
pc-bios/mpc8544ds.dts

index b1a0f6d28b87d60705f45adb2b4fe29b9839f685..d3ebe579eb7888482b416e6be519ad0ce4dc7e1c 100644 (file)
@@ -256,7 +256,7 @@ endif
 obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
 obj-ppc-y += ppc440.o ppc440_bamboo.o
 # PowerPC E500 boards
-obj-ppc-y += ppce500_mpc8544ds.o
+obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-ppc-y += virtex_ml507.o
 obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
new file mode 100644 (file)
index 0000000..c685f3e
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * QEMU PowerPC MPC8544 global util pseudo-device
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Alexander Graf, <alex@csgraf.de>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of  the GNU General  Public License as published by
+ * the Free Software Foundation;  either version 2 of the  License, or
+ * (at your option) any later version.
+ *
+ * *****************************************************************
+ *
+ * The documentation for this device is noted in the MPC8544 documentation,
+ * file name "MPC8544ERM.pdf". You can easily find it on the web.
+ *
+ */
+
+#include "hw.h"
+#include "sysemu.h"
+#include "sysbus.h"
+
+#define MPC8544_GUTS_MMIO_SIZE        0x1000
+#define MPC8544_GUTS_RSTCR_RESET      0x02
+
+#define MPC8544_GUTS_ADDR_PORPLLSR    0x00
+#define MPC8544_GUTS_ADDR_PORBMSR     0x04
+#define MPC8544_GUTS_ADDR_PORIMPSCR   0x08
+#define MPC8544_GUTS_ADDR_PORDEVSR    0x0C
+#define MPC8544_GUTS_ADDR_PORDBGMSR   0x10
+#define MPC8544_GUTS_ADDR_PORDEVSR2   0x14
+#define MPC8544_GUTS_ADDR_GPPORCR     0x20
+#define MPC8544_GUTS_ADDR_GPIOCR      0x30
+#define MPC8544_GUTS_ADDR_GPOUTDR     0x40
+#define MPC8544_GUTS_ADDR_GPINDR      0x50
+#define MPC8544_GUTS_ADDR_PMUXCR      0x60
+#define MPC8544_GUTS_ADDR_DEVDISR     0x70
+#define MPC8544_GUTS_ADDR_POWMGTCSR   0x80
+#define MPC8544_GUTS_ADDR_MCPSUMR     0x90
+#define MPC8544_GUTS_ADDR_RSTRSCR     0x94
+#define MPC8544_GUTS_ADDR_PVR         0xA0
+#define MPC8544_GUTS_ADDR_SVR         0xA4
+#define MPC8544_GUTS_ADDR_RSTCR       0xB0
+#define MPC8544_GUTS_ADDR_IOVSELSR    0xC0
+#define MPC8544_GUTS_ADDR_DDRCSR      0xB20
+#define MPC8544_GUTS_ADDR_DDRCDR      0xB24
+#define MPC8544_GUTS_ADDR_DDRCLKDR    0xB28
+#define MPC8544_GUTS_ADDR_CLKOCR      0xE00
+#define MPC8544_GUTS_ADDR_SRDS1CR1    0xF04
+#define MPC8544_GUTS_ADDR_SRDS2CR1    0xF10
+#define MPC8544_GUTS_ADDR_SRDS2CR3    0xF18
+
+struct GutsState {
+    SysBusDevice busdev;
+};
+
+typedef struct GutsState GutsState;
+
+static uint32_t mpc8544_guts_read32(void *opaque, target_phys_addr_t addr)
+{
+    uint32_t value = 0;
+    CPUState *env = cpu_single_env;
+
+    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
+    switch (addr) {
+    case MPC8544_GUTS_ADDR_PVR:
+        value = env->spr[SPR_PVR];
+        break;
+    case MPC8544_GUTS_ADDR_SVR:
+        value = env->spr[SPR_E500_SVR];
+        break;
+    default:
+        fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr);
+        break;
+    }
+
+    return value;
+}
+
+static CPUReadMemoryFunc * const mpc8544_guts_read[] = {
+    NULL,
+    NULL,
+    &mpc8544_guts_read32,
+};
+
+static void mpc8544_guts_write32(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
+
+    switch (addr) {
+    case MPC8544_GUTS_ADDR_RSTCR:
+        if (value & MPC8544_GUTS_RSTCR_RESET) {
+            qemu_system_reset_request();
+        }
+        break;
+    default:
+        fprintf(stderr, "guts: Unknown register write: %x = %x\n",
+                (int)addr, value);
+        break;
+    }
+}
+
+static CPUWriteMemoryFunc * const mpc8544_guts_write[] = {
+    NULL,
+    NULL,
+    &mpc8544_guts_write32,
+};
+
+static int mpc8544_guts_initfn(SysBusDevice *dev)
+{
+    GutsState *s;
+    int iomem;
+
+    s = FROM_SYSBUS(GutsState, sysbus_from_qdev(dev));
+
+    iomem = cpu_register_io_memory(mpc8544_guts_read, mpc8544_guts_write, s,
+                                   DEVICE_BIG_ENDIAN);
+    sysbus_init_mmio(dev, MPC8544_GUTS_MMIO_SIZE, iomem);
+
+    return 0;
+}
+
+static SysBusDeviceInfo mpc8544_guts_info = {
+    .init         = mpc8544_guts_initfn,
+    .qdev.name    = "mpc8544-guts",
+    .qdev.size    = sizeof(GutsState),
+};
+
+static void mpc8544_guts_register(void)
+{
+    sysbus_register_withprop(&mpc8544_guts_info);
+}
+device_init(mpc8544_guts_register);
index 6b57fbf597c97f04f394c0c1c5e9bc3241effd96..3ba8e75e2b38729fb52a225475ce160c7727da7f 100644 (file)
@@ -50,6 +50,7 @@
 #define MPC8544_PCI_REGS_SIZE      0x1000
 #define MPC8544_PCI_IO             0xE1000000
 #define MPC8544_PCI_IOLEN          0x10000
+#define MPC8544_UTIL_BASE          (MPC8544_CCSRBAR_BASE + 0xe0000)
 
 struct boot_info
 {
@@ -270,6 +271,9 @@ static void mpc8544ds_init(ram_addr_t ram_size,
                        serial_hds[0], 1, 1);
     }
 
+    /* General Utility device */
+    sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL);
+
     /* PCI */
     dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
                                 mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
index 3299546696bf21f53f8ce2c9eba7fcb740c547da..189224e5875e9dd0d9195c22624b85bfb29dd820 100644 (file)
Binary files a/pc-bios/mpc8544ds.dtb and b/pc-bios/mpc8544ds.dtb differ
index 872152df93dc36c18d2009629e5f0b9ba1b2f4cf..fd792d5f88ddcc4d23a601d93c814fa43bfce96c 100644 (file)
                        compatible = "chrp,open-pic";
                        device_type = "open-pic";
                };
+
+                global-utilities@e0000 {        //global utilities block
+                        compatible = "fsl,mpc8544-guts";
+                        reg = <0xe0000 0x1000>;
+                        fsl,has-rstcr;
+                };
        };
 
        pci0: pci@e0008000 {