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....@freescale.com> --- 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....@freescale.com> + * + * 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,8...@0", + prop, cell); + if (ret < 0) { + fprintf(stderr, "couldn't set guest /cpus/PowerPC,8...@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 zcmeHL&5z_p6)%%8N%#m$L?XV`(sDpBW_xCPHjCiUD3D7O)Dj}6m59e(gh?mw...@d zgAkenLL5Qd(HuB&t5fp!{s1i$=g2=6!...@5rsyu-|tmDce!UaTC&m#B$xDD_3FKP zAHRC#uU9|*?mvt...@gw^umvomqdkdt>_y+|1#$3AG`7Y)HU+aJc9mX9KZ0=i=!83 z&t2a;J|@fgPl2{%ZZi4y_l%cf<mHc|XRfqGeexp^`6$V=q_GW#BKsox?JG^0(!tb@ zUAxlQI!p5DWN$1eu5~B(*1Z<$J_)<uyi%o^*t`z2^yut-0{yorvm*Su3K=V9&#z_4 zrtF2aY+q#`!kQ?pmXZ|4n)5{%Ky0E}`9oXJp4*n3U0}Lq20PSI{stK|<zL2l6!7&1 z|5Ia5G1ck+a)bXhg=lK;caH7&I~)9;!...@i3qvw};i?TiuE!ubtG~1Ya9CI2s6=mJ# z7e^$...@ei{i=m1^{w3-47qqvqroz?_o!2k^|}JNi#utYmv}_rj-T4p+#?r%oR&pf zmw9gM>8|cAbw3B%I%sn2*JKi(Q-;*V>GK|e73b>bO-v92jpg4MKjr5Hn|wD;lk~`L zMiA8O7ofk6;erK_v#F08;;|pcKI9{>!!!9aIhkvWFN%|iXzW-M(Z1G0v~fy(z7hA5 zjr?PvnbYG`7vEOV>|ER1lML4}o9{q{=0%S&h...@8%iqqk~k}<&D7A!R;e>VtY(t7$Y zV|pI$9xSHAyxdRnc-dxo)@hv...@q#c@i(#+eL-j;N*IIxNO6FiK{E#(boHkarAjy zB<Hj~soHXS6-DbyM(}$Ea<SXkboXmJh9xY+pst*4q9iGH`$L>#Z{K6s;jEZ)AGk-# z...@!b2mb1<cLRPNef3H1r^H-k>2$IVm^RR&pwvey!...@{r%socnaikliv62w3qy! z)pl9gB8CSMiM=N<ob{*GkJL2nN?eO3n@)Cm&yw!!x&6T{pveTx1zZTT_T%Fs^yU=A zTrd~?20dC=M^iAwcm-m+>pjta?_c...@~um@Bij|);ybH6`ldf<NTvfb$jRY5^Myu zH;%C`v^xuU=th5VVN*pK&k|!;LG~wOelC;#!el#KH)J}`wb1LW;~eGO*-aVeBtIwn z1-h=OKX0=qQ-9uOPp1C7-JWd2pJLcM3*2+=C2OBHXpejT7xZlJfjBn?t*F5EM^7A& zKnz~nT^+bdu4No|9(jBETlAin^FR%ik1$sM)aUu3jKmmktjsC8OCX2g`BxydB{ib9 z&)uK6jz-YbcUULz{Xt?Q?h>1i_x<rZg*J(81aeT3!(md!^%~=y=$*6gL#(`>8ShW_ z...@uxibh6v`k^<F`Sdha!Q<62^`5vT&^NguvIM*oy;T_B?^%6QIbGm<?UW90JSyLkAn zB?5oZJV)SZL;0{SXg}P$DfktY*-k;>m~$ggm|Qrf+zYvk<l^ofe...@ay&6(hjBfm z8asol`>!!-li0W_%=NAU<0ci``>C<dz?9|<vmdC&7*ZGxdD<j#epANyLOIy3X^l}w z);`P{JA+dO#&#yx^H^^t<Fo7X>F#6QCt0t?m>20G)!1#gy8jxZHc1+mg}L4qGmyBR zIdHG;r^firLVUP}R`J~CW2kF%L)kl!;xbz...@7{-&3%0H<YPOzE5HNS}3DE(np-^ z^-#vRDdV>r*8M${sXyNTAbaZ~8Sj6P{qucfd<1t*ZStKE>)!4j7^sz*v#p...@vmc zite8K&H#JO?SHh)vz@(X_oibfB%Tj?|DVFfiXgB(NNib?On0o9VO-qr8Rj_Q`QH0G z<s*>p1$mxNh7#oU7T9x*a=vS=KmwIqz_=!0X$)^-j^ijRT3gr4s_lPda|z{N0`WOY zQzMYn1^Tn~_|aGWnEGhlx60FCW*6BPwJv|jk5fLj9v(bT?%O5P&lb_scT0cXbZzhb z6WGZ&4DCwX+4b>ccY1A1XK3D^<Q4M7oB2{sJT?E9G3GpJ?tAJGSROK6!}|m0)qaQd zO?$FmCiUDGs><~}g}nu3sfud$-p...@m0+d*caupvc|#$;X3sht~&_UN#1pvPM>vI zZ~DNKfhNT!<JMd&jJa0UA68k(k5ce#v=QjCM9nEk^}{|&kikdtrfqs~u...@?|+ru ze@(UV#G;(r...@$5ao4@8cx8`y(pVzi&;?(aov...@kmm&?#_k`-*tmYj;Q2S^MMk?E zt{u...@*mu+lowf+8&y@|HYJNg^g*;wanm7rza...@%ea|83)g+P<>1MS5cJ=PlsU zyi9Kfd|{8<ijdwk?!1^f...@5cyre%q_#!7o@fk0tom...@cb9{!bh_in%?oz|$R` ziR-3KYvGFJB2J-LSU|)78lH&{vV#(s...@xxhjs4>);94XX>Q8g+%{>Q;de<L6B{pC zhqe9*Xf6k{f;+zZ<K$M7<q...@k9|uVshpqnI!p;rqU#fE+IhKbW9;*...@1#5eu{` v5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu{`5Eu~ne?Z_r$iQ#d 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,8...@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 + }; + + soc8...@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-control...@2000 { + compatible = "fsl,8544-memory-controller"; + reg = <0x2000 0x1000>; + interrupt-parent = <&mpic>; + interrupts = <18 2>; + }; + + L2: l2-cache-control...@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: ser...@4500 { + cell-index = <0>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4500 0x100>; + clock-frequency = <0>; + interrupts = <42 2>; + interrupt-parent = <&mpic>; + }; + + serial1: ser...@4600 { + cell-index = <1>; + device_type = "serial"; + compatible = "ns16550"; + reg = <0x4600 0x100>; + clock-frequency = <0>; + interrupts = <42 2>; + interrupt-parent = <&mpic>; + }; + + global-utilit...@e0000 { //global utilities block + compatible = "fsl,mpc8548-guts"; + reg = <0xe0000 0x1000>; + fsl,has-rstcr; + }; + + cry...@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: p...@40000 { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x40000 0x40000>; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + }; + + m...@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: p...@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: p...@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 + >; + p...@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: p...@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 + >; + p...@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: p...@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 + >; + + p...@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>; + + uli1...@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>; + i...@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-control...@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>; + }; + + i8...@60 { + #size-cells = <0>; + #address-cells = <1>; + reg = <0x1 0x60 0x1 0x1 0x64 0x1>; + interrupts = <1 3 12 3>; + interrupt-parent = <&i8259>; + + keybo...@0 { + reg = <0x0>; + compatible = "pnpPNP,303"; + }; + + mo...@1 { + reg = <0x1>; + compatible = "pnpPNP,f03"; + }; + }; + + r...@70 { + compatible = "pnpPNP,b00"; + reg = <0x1 0x70 0x2>; + }; + + g...@400 { + reg = <0x1 0x400 0x80>; + }; + }; + }; + }; + }; + chosen { + linux,stdout-path = "/soc8...@e0000000/ser...@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 majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html