[PATCH 4/5] qemu/kvm: Add MPC85xx support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



As E500 exists in various boards such as MPC8544ds, MPC8572ds, MPC8560ads, etc..
So I would like to implement a general virtual board MPC85xx to simplify the case.

When 'cat /proc/cpuinfo' in guest, it will show:
processor       : 0
cpu             : e500v2
clock           : 1499.985015MHz
revision        : 3.0 (pvr 8021 0030)
bogomips        : 285.69
timebase        : 74999250
platform        : MPC8572 DS     <---- Host platform
model           : KVM MPC85xx

The current method is that change guest dts /compatible="host model",
this seems somewhat dirty. It works for 8544, 8572 but not sure for others.
I'll change it to search a table next time.

Signed-off-by: Liu Yu <yu.liu@xxxxxxxxxxxxx>
---
 Makefile.target             |    2 +
 hw/boards.h                 |    1 +
 hw/ppc.c                    |   89 +++++++++++
 hw/ppc.h                    |    1 +
 hw/ppce500_mpc85xx.c        |  284 ++++++++++++++++++++++++++++++++++
 pc-bios/mpc85xx.dtb         |  Bin 0 -> 12288 bytes
 pc-bios/mpc85xx.dts         |  361 +++++++++++++++++++++++++++++++++++++++++++
 target-ppc/cpu.h            |   12 ++
 target-ppc/machine.c        |    1 +
 target-ppc/translate_init.c |    6 +-
 10 files changed, 755 insertions(+), 2 deletions(-)
 create mode 100644 hw/ppce500_mpc85xx.c
 create mode 100644 pc-bios/mpc85xx.dtb
 create mode 100644 pc-bios/mpc85xx.dts

diff --git a/Makefile.target b/Makefile.target
index b66b699..abf0d59 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -657,6 +657,8 @@ OBJS+= unin_pci.o ppc_chrp.o
 # PowerPC 4xx boards
 OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
 OBJS+= ppc440.o ppc440_bamboo.o
+# PowerPC E500 boards
+OBJS+= ppce500.o ppce500_mpc85xx.o ppce500_pci.o mpic.o
 ifdef FDT_LIBS
 OBJS+= device_tree.o
 LIBS+= $(FDT_LIBS)
diff --git a/hw/boards.h b/hw/boards.h
index bff1cf0..35bd5ae 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -39,6 +39,7 @@ extern QEMUMachine heathrow_machine;
 extern QEMUMachine ref405ep_machine;
 extern QEMUMachine taihu_machine;
 extern QEMUMachine bamboo_machine;
+extern QEMUMachine mpc85xx_machine;
 
 /* mips_r4k.c */
 extern QEMUMachine mips_machine;
diff --git a/hw/ppc.c b/hw/ppc.c
index 60d6e86..fbce211 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -421,6 +421,95 @@ void ppc40x_irq_init (CPUState *env)
                                                   env, PPC40x_INPUT_NB);
 }
 
+/* PowerPC E500 internal IRQ controller */
+static void ppce500_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPCE500_INPUT_MCK:
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC system\n",
+                            __func__);
+                }
+#endif
+		fprintf(stderr,"PowerPC E500 reset core\n");
+		qemu_system_reset_request();
+            }
+            break;
+        case PPCE500_INPUT_RESET_CORE:
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
+                }
+#endif
+		ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
+            }
+            break;
+        case PPCE500_INPUT_CINT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
+            break;
+        case PPCE500_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the core IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPCE500_INPUT_DEBUG:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the debug pin state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppce500_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
+					env, PPCE500_INPUT_NB);
+}
 /*****************************************************************************/
 /* PowerPC time base and decrementer emulation */
 struct ppc_tb_t {
diff --git a/hw/ppc.h b/hw/ppc.h
index 297f550..c0c602d 100644
--- a/hw/ppc.h
+++ b/hw/ppc.h
@@ -31,5 +31,6 @@ extern CPUReadMemoryFunc *PPC_io_read[];
 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
 
 void ppc40x_irq_init (CPUState *env);
+void ppce500_irq_init (CPUState *env);
 void ppc6xx_irq_init (CPUState *env);
 void ppc970_irq_init (CPUState *env);
diff --git a/hw/ppce500_mpc85xx.c b/hw/ppce500_mpc85xx.c
new file mode 100644
index 0000000..a17131d
--- /dev/null
+++ b/hw/ppce500_mpc85xx.c
@@ -0,0 +1,284 @@
+/*
+ * Qemu PowerPC MPC85xx board emualtion
+ *
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu,     <yu.liu@xxxxxxxxxxxxx>
+ *
+ * This file is derived from hw/ppc440_bamboo.c,
+ * the copyright for that material belongs to the original owners.
+ *
+ * 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.
+ */
+
+#include <dirent.h>
+
+#include "config.h"
+#include "qemu-common.h"
+#include "net.h"
+#include "hw.h"
+#include "pci.h"
+#include "virtio-blk.h"
+#include "boards.h"
+#include "sysemu.h"
+#include "ppce500.h"
+#include "kvm.h"
+#include "kvm_ppc.h"
+#include "device_tree.h"
+
+#define BINARY_DEVICE_TREE_FILE  "mpc85xx.dtb"
+#define UIMAGE_LOAD_BASE         0
+#define DTB_LOAD_BASE            0x600000
+#define INITRD_LOAD_BASE         0x2000000
+
+#define PPCE500_CCSRBAR_BASE     0xE0000000
+#define PPCE500_PCI_REGS_BASE    (PPCE500_CCSRBAR_BASE + 0x8000)
+#define PPCE500_PCI_REGS_SIZE    0x1000
+#define PPCE500_PCI_IO           0xE1000000
+#define PPCE500_PCI_IOLEN	 0x10000
+
+static int mpc85xx_copy_host_cell(void *fdt, const char *node, const char *prop)
+{
+    uint32_t cell;
+    int ret;
+
+    ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell));
+    if (ret < 0) {
+	fprintf(stderr, "couldn't read host %s/%s\n", node, prop);
+	goto out;
+    }
+
+    ret = qemu_devtree_setprop_cell(fdt, "/cpus/PowerPC,85xx@0",
+				prop, cell);
+    if (ret < 0) {
+	fprintf(stderr, "couldn't set guest /cpus/PowerPC,85xx@0/%s\n", prop);
+	goto out;
+    }
+
+out:
+    return ret;
+}
+
+static void *mpc85xx_load_device_tree(void *addr,
+                                     uint32_t ramsize,
+                                     target_phys_addr_t initrd_base,
+                                     target_phys_addr_t initrd_size,
+                                     const char *kernel_cmdline)
+{
+    void *fdt = NULL;
+#ifdef HAVE_FDT
+    uint32_t mem_reg_property[] = {0, ramsize};
+    char *path;
+    int pathlen;
+    int ret;
+
+    pathlen = snprintf(NULL, 0, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE) + 1;
+    path = qemu_malloc(pathlen);
+    if (path == NULL)
+	goto out;
+
+    snprintf(path, pathlen, "%s/%s", bios_dir, BINARY_DEVICE_TREE_FILE);
+
+    fdt = load_device_tree(path, addr);
+    free(path);
+    if (fdt == NULL)
+	goto out;
+
+    /* Manipulate device tree in memory. */
+
+    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
+                               sizeof(mem_reg_property));
+    if (ret < 0)
+	fprintf(stderr, "couldn't set /memory/reg\n");
+
+    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                    initrd_base);
+    if (ret < 0)
+	fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+
+    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                                    (initrd_base + initrd_size));
+    if (ret < 0)
+	fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+
+    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                      kernel_cmdline);
+    if (ret < 0)
+	fprintf(stderr, "couldn't set /chosen/bootargs\n");
+
+    if (kvm_enabled()) {
+	FILE *fp;
+	char *model = NULL;
+	struct dirent *dirp;
+	DIR *dp;
+	char buf[128];
+
+	if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) {
+	    printf("Can't open file /proc/cpuinfo\n");
+	    goto out;
+	}
+	while (fgets(buf, 128, fp) != NULL) {
+	    if (strncmp(buf, "model", 5) == 0) {
+		model = buf + 9;
+		break;
+	    }
+	}
+	fclose(fp);
+	
+	if (model == NULL) {
+	    printf("unknow host\n");
+	    goto out;
+	}
+	
+	ret = qemu_devtree_setprop_string(fdt, "/", "compatible", model);
+	if (ret < 0)
+	    fprintf(stderr, "couldn't set /compatible = %s\n", model);
+
+	if ((dp = opendir("/proc/device-tree/cpus/")) == NULL) {
+	    printf("Can't open directory /proc/device-tree/cpus/\n");
+	    goto out;
+	}
+
+	buf[0] = '\0';
+	while ((dirp = readdir(dp)) != NULL) {
+	    if (strncmp(dirp->d_name, "PowerPC", 7) == 0) {
+		sprintf(buf, "/proc/device-tree/cpus/%s", dirp->d_name);
+		break;
+	    }
+	}
+	closedir(dp);
+	if (buf[0] == '\0') {
+	    printf("unknow host\n");
+	    goto out;
+	}
+	path = buf + 17;
+	
+	mpc85xx_copy_host_cell(fdt, path, "clock-frequency");
+	mpc85xx_copy_host_cell(fdt, path, "timebase-frequency");
+	
+    }
+
+out:
+#endif
+
+    return fdt;
+}
+
+static void mpc85xx_init(ram_addr_t ram_size, int vga_ram_size,
+    		const char *boot_device, DisplayState *ds,
+    		const char *kernel_filename,
+    		const char *kernel_cmdline,
+    		const char *initrd_filename,
+    		const char *cpu_model)
+{
+    NICInfo *nd;
+    PCIBus *pci_bus;
+    CPUState *env;
+    uint64_t elf_entry;
+    uint64_t elf_lowaddr;
+    target_ulong entry=0;
+    target_ulong loadaddr=UIMAGE_LOAD_BASE;
+    target_long kernel_size=0;
+    target_ulong dt_base=DTB_LOAD_BASE;
+    target_ulong initrd_base=INITRD_LOAD_BASE;
+    target_long initrd_size=0;
+    void *fdt;
+    int i=0;
+    unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
+    qemu_irq *mpic, *pci_irqs;
+
+    /* Setup CPU */
+    env = ppce500_init(&ram_size, &mpic, PPCE500_CCSRBAR_BASE);
+
+    /* PCI */
+    pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
+    pci_irqs[0] = mpic[pci_irq_nrs[0]];
+    pci_irqs[1] = mpic[pci_irq_nrs[1]];
+    pci_irqs[2] = mpic[pci_irq_nrs[2]];
+    pci_irqs[3] = mpic[pci_irq_nrs[3]];
+    pci_bus = ppce500_pci_init(pci_irqs, PPCE500_PCI_REGS_BASE);
+    if (!pci_bus)
+	printf("couldn't create PCI controller!\n");
+
+    isa_mmio_init(PPCE500_PCI_IO, PPCE500_PCI_IOLEN);
+
+    /* Register mem */
+    cpu_register_physical_memory(0, ram_size, 0);
+
+    if (pci_bus) {
+    	int unit_id = 0;
+
+    	/* Add virtio block devices. */
+    	while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
+    		virtio_blk_init(pci_bus, drives_table[i].bdrv);
+    		unit_id++;
+    	}
+
+    	/* Register network interfaces. */
+    	for (i = 0; i < nb_nics; i++) {
+    		nd = &nd_table[i];
+    		if (!nd->model)
+    			nd->model = "virtio";
+    		pci_nic_init(pci_bus, nd, -1);
+    	}
+    }
+
+    /* Load kernel. */
+    if (kernel_filename) {
+        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
+        if (kernel_size < 0) {
+            kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
+                                   NULL);
+            entry = elf_entry;
+            loadaddr = elf_lowaddr;
+        }
+        /* XXX try again as binary */
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* Load initrd. */
+    if (initrd_filename) {
+        initrd_size = load_image(initrd_filename, phys_ram_base + initrd_base);
+
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* If we're loading a kernel directly, we must load the device tree too. */
+    if (kernel_filename) {
+        fdt = mpc85xx_load_device_tree(phys_ram_base + dt_base, ram_size,
+                                      initrd_base, initrd_size, kernel_cmdline);
+        if (fdt == NULL) {
+            fprintf(stderr, "couldn't load device tree\n");
+            exit(1);
+        }
+
+        /* Set initial guest state. */
+        env->gpr[1] = (16<<20) - 8;
+        env->gpr[3] = dt_base;
+        env->nip = entry;
+        /* XXX we currently depend on KVM to create some initial TLB entries. */
+    }
+
+    if (kvm_enabled())
+	kvmppc_init();
+
+    return;
+}
+
+QEMUMachine mpc85xx_machine = {
+    .name = "mpc85xx",
+    .desc = "mpc85xx",
+    .init = mpc85xx_init,
+    .ram_require = 256<<20 | RAMSIZE_FIXED,
+};
diff --git a/pc-bios/mpc85xx.dtb b/pc-bios/mpc85xx.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..a10e29d5bd0d65add2faed921434ff3ac2d16cdd
GIT binary patch
literal 12288
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

literal 0
HcmV?d00001

diff --git a/pc-bios/mpc85xx.dts b/pc-bios/mpc85xx.dts
new file mode 100644
index 0000000..45a9c3d
--- /dev/null
+++ b/pc-bios/mpc85xx.dts
@@ -0,0 +1,361 @@
+/*
+ * MPC85xx DS Device Tree Source
+ *
+ * Copyright 2007-2009 Freescale Semiconductor Inc.
+ *
+ * This program 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.
+ */
+
+/dts-v1/;
+/ {
+	model = "KVM MPC85xx";
+	compatible = "MPC8544DS", "MPC85xxDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		pci3 = &pci3;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,85xx@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0>;	// Filled by U-Boot
+	};
+
+	soc85xx@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+
+		ranges = <0x0 0xe0000000 0x100000>;
+		reg = <0xe0000000 0x1000>;	// CCSRBAR 1M
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		memory-controller@2000 {
+			compatible = "fsl,8544-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,8544-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x40000>;	// L2, 256K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8548-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0xfe>;
+			fsl,descriptor-types-mask = <0x12b0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8544-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	pci0: pci@e0008000 {
+		cell-index = <0>;
+		compatible = "fsl,mpc8540-pci";
+		device_type = "pci";
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+
+			/* IDSEL 0x11 J17 Slot 1 */
+			0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x12 J16 Slot 2 */
+
+			0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x9000 0x0 0x0 0x4 &mpic 0x1 0x1>;
+
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
+			  0x1000000 0x0 0x0 0xe1000000 0x0 0x10000>;
+		clock-frequency = <66666666>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe0008000 0x1000>;
+	};
+
+	pci1: pcie@e0009000 {
+		cell-index = <1>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe0009000 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x0 0xe1010000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x4 0x1
+			0000 0x0 0x0 0x2 &mpic 0x5 0x1
+			0000 0x0 0x0 0x3 &mpic 0x6 0x1
+			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+		};
+	};
+
+	pci2: pcie@e000a000 {
+		cell-index = <2>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe000a000 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
+			  0x1000000 0x0 0x0 0xe1020000 0x0 0x10000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0000 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xa0000000
+				  0x2000000 0x0 0xa0000000
+				  0x0 0x10000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+		};
+	};
+
+	pci3: pcie@e000b000 {
+		cell-index = <3>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe000b000 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xb0000000 0xb0000000 0x0 0x100000
+			  0x1000000 0x0 0x0 0xb0100000 0x0 0x100000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <27 2>;
+		interrupt-map-mask = <0xff00 0x0 0x0 0x1>;
+		interrupt-map = <
+			// IDSEL 0x1c  USB
+			0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
+			0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
+			0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
+			0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+
+			// IDSEL 0x1d  Audio
+			0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+
+			// IDSEL 0x1e Legacy
+			0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
+			0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+
+			// IDSEL 0x1f IDE/SATA
+			0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
+			0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+		>;
+
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xb0000000
+				  0x2000000 0x0 0xb0000000
+				  0x0 0x100000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+
+			uli1575@0 {
+				reg = <0x0 0x0 0x0 0x0 0x0>;
+				#size-cells = <2>;
+				#address-cells = <3>;
+				ranges = <0x2000000 0x0 0xb0000000
+					  0x2000000 0x0 0xb0000000
+					  0x0 0x100000
+
+					  0x1000000 0x0 0x0
+					  0x1000000 0x0 0x0
+					  0x0 0x100000>;
+				isa@1e {
+					device_type = "isa";
+					#interrupt-cells = <2>;
+					#size-cells = <1>;
+					#address-cells = <2>;
+					reg = <0xf000 0x0 0x0 0x0 0x0>;
+					ranges = <0x1 0x0
+						  0x1000000 0x0 0x0
+						  0x1000>;
+					interrupt-parent = <&i8259>;
+
+					i8259: interrupt-controller@20 {
+						reg = <0x1 0x20 0x2
+						       0x1 0xa0 0x2
+						       0x1 0x4d0 0x2>;
+						interrupt-controller;
+						device_type = "interrupt-controller";
+						#address-cells = <0>;
+						#interrupt-cells = <2>;
+						compatible = "chrp,iic";
+						interrupts = <9 2>;
+						interrupt-parent = <&mpic>;
+					};
+
+					i8042@60 {
+						#size-cells = <0>;
+						#address-cells = <1>;
+						reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
+						interrupts = <1 3 12 3>;
+						interrupt-parent = <&i8259>;
+
+						keyboard@0 {
+							reg = <0x0>;
+							compatible = "pnpPNP,303";
+						};
+
+						mouse@1 {
+							reg = <0x1>;
+							compatible = "pnpPNP,f03";
+						};
+					};
+
+					rtc@70 {
+						compatible = "pnpPNP,b00";
+						reg = <0x1 0x70 0x2>;
+					};
+
+					gpio@400 {
+						reg = <0x1 0x400 0x80>;
+					};
+				};
+			};
+		};
+	};
+	chosen {
+		linux,stdout-path = "/soc85xx@e0000000/serial@4500";
+	};
+};
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index f7600c4..d64f882 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1345,6 +1345,18 @@ enum {
 };
 
 enum {
+    /* PowerPC E500 input pins */
+    PPCE500_INPUT_RESET_CORE = 0,
+    PPCE500_INPUT_MCK        = 1,
+    PPCE500_INPUT_RESET_SYS  = 2,      // in order same with 440
+    PPCE500_INPUT_CINT       = 3,
+    PPCE500_INPUT_INT        = 4,
+    PPCE500_INPUT_HALT       = 5,      // in order same with 440
+    PPCE500_INPUT_DEBUG      = 6,
+    PPCE500_INPUT_NB,
+};
+
+enum {
     /* PowerPC 40x input pins */
     PPC40x_INPUT_RESET_CORE = 0,
     PPC40x_INPUT_RESET_CHIP = 1,
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index ea2257b..97a7ee8 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -9,6 +9,7 @@ void register_machines(void)
     qemu_register_machine(&ref405ep_machine);
     qemu_register_machine(&taihu_machine);
     qemu_register_machine(&bamboo_machine);
+    qemu_register_machine(&mpc85xx_machine);
 }
 
 void cpu_save(QEMUFile *f, void *opaque)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 3f01e66..f20e857 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -4154,7 +4154,8 @@ static void init_proc_e300 (CPUPPCState *env)
                               POWERPC_FLAG_BUS_CLK)
 #define check_pow_e500       check_pow_hid0
 
-__attribute__ (( unused ))
+extern void ppce500_irq_init (CPUState *env);
+
 static void init_proc_e500 (CPUPPCState *env)
 {
     /* Time base */
@@ -4256,7 +4257,8 @@ static void init_proc_e500 (CPUPPCState *env)
     init_excp_e200(env);
     env->dcache_line_size = 32;
     env->icache_line_size = 32;
-    /* XXX: TODO: allocate internal IRQ controller */
+    /* Allocate hardware IRQ controller */
+    ppce500_irq_init(env);
 }
 
 /* Non-embedded PowerPC                                                      */
-- 
1.5.4

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux