* [Qemu-devel] powerpc/kvm: Add MPC8544DS board support
@ 2009-02-17 9:59 Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Liu Yu
0 siblings, 1 reply; 19+ messages in thread
From: Liu Yu @ 2009-02-17 9:59 UTC (permalink / raw)
To: qemu-devel, aurelien, hollisb; +Cc: kvm-ppc
patch 1: enable mpic for E500 platform.
patch 2: add E500 pci controller emulation.
patch 3: add E500 irq support.
patch 4: add MPC8544DS board emulation.
patch 5: FDT of MPC8544DS
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform.
2009-02-17 9:59 [Qemu-devel] powerpc/kvm: Add MPC8544DS board support Liu Yu
@ 2009-02-17 9:59 ` Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Liu Yu
` (2 more replies)
0 siblings, 3 replies; 19+ messages in thread
From: Liu Yu @ 2009-02-17 9:59 UTC (permalink / raw)
To: qemu-devel, aurelien, hollisb; +Cc: Liu Yu, kvm-ppc
MPIC and OpenPIC have very similar design.
So a lot of code can be reused.
Modification mainly include:
1. keep struct openpic_t to the maximum size of both MPIC and OpenPIC.
2. endianess swap.
MPIC has the same endianess as target, so no need to swap for MPIC.
3. using different init functions and function pointers for reset and irq raise.
Haven't test OpenPIC.
Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
hw/openpic.c | 480 +++++++++++++++++++++++++++++++++++++++++++++--------
hw/ppc_mac.h | 13 --
hw/ppc_newworld.c | 1 +
3 files changed, 412 insertions(+), 82 deletions(-)
diff --git a/hw/openpic.c b/hw/openpic.c
index 6dfb590..0f687e4 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -35,6 +35,7 @@
#include "hw.h"
#include "ppc_mac.h"
#include "pci.h"
+#include "openpic.h"
//#define DEBUG_OPENPIC
@@ -60,14 +61,10 @@
#define VID (0x00000000)
-#define OPENPIC_LITTLE_ENDIAN 1
-#define OPENPIC_BIG_ENDIAN 0
-
#elif defined(USE_MPCxxx)
#define MAX_CPU 2
-#define MAX_IRQ 64
-#define EXT_IRQ 48
+#define MAX_IRQ 128
#define MAX_DBL 0
#define MAX_MBX 0
#define MAX_TMR 4
@@ -81,28 +78,55 @@ enum {
IRQ_IDE,
};
-#define OPENPIC_LITTLE_ENDIAN 1
-#define OPENPIC_BIG_ENDIAN 0
+/* OpenPIC */
+#define OPENPIC_MAX_CPU 2
+#define OPENPIC_MAX_IRQ 64
+#define OPENPIC_EXT_IRQ 48
+#define OPENPIC_MAX_TMR MAX_TMR
+#define OPENPIC_MAX_IPI MAX_IPI
+/* Interrupt definitions */
+#define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */
+#define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
+#define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
+#if OPENPIC_MAX_IPI > 0
+#define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
+#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
#else
-#error "Please select which OpenPic implementation is to be emulated"
+#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
+#define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
#endif
-#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
- (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN)
-#define OPENPIC_SWAP
-#endif
+/* MPIC */
+#define MPIC_MAX_CPU 1
+#define MPIC_MAX_EXT 12
+#define MPIC_MAX_INT 64
+#define MPIC_MAX_MSG 4
+#define MPIC_MAX_MSI 8
+#define MPIC_MAX_TMR MAX_TMR
+#define MPIC_MAX_IPI MAX_IPI
+#define MPIC_MAX_IRQ (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR + MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU))
/* Interrupt definitions */
-#define IRQ_FE (EXT_IRQ) /* Internal functional IRQ */
-#define IRQ_ERR (EXT_IRQ + 1) /* Error IRQ */
-#define IRQ_TIM0 (EXT_IRQ + 2) /* First timer IRQ */
-#if MAX_IPI > 0
-#define IRQ_IPI0 (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */
-#define IRQ_DBL0 (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell IRQ */
+#define MPIC_EXT_IRQ 0
+#define MPIC_INT_IRQ (MPIC_EXT_IRQ + MPIC_MAX_EXT)
+#define MPIC_TMR_IRQ (MPIC_INT_IRQ + MPIC_MAX_INT)
+#define MPIC_MSG_IRQ (MPIC_TMR_IRQ + MPIC_MAX_TMR)
+#define MPIC_MSI_IRQ (MPIC_MSG_IRQ + MPIC_MAX_MSG)
+#define MPIC_IPI_IRQ (MPIC_MSI_IRQ + MPIC_MAX_MSI)
+
+#define MPIC_MAP_SIZE 0x40000
+
+enum mpic_ide_bits {
+ IDR_EP = 0,
+ IDR_CI0 = 1,
+ IDR_CI1 = 2,
+ IDR_P1 = 30,
+ IDR_P0 = 31,
+};
+
#else
-#define IRQ_DBL0 (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */
-#define IRQ_MBX0 (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */
+#error "Please select which OpenPic implementation is to be emulated"
#endif
#define BF_WIDTH(_bits_) \
@@ -157,6 +181,7 @@ enum IPVP_bits {
#define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
typedef struct IRQ_dst_t {
+ uint32_t tfrr;
uint32_t pctp; /* CPU current task priority */
uint32_t pcsr; /* CPU sensitivity register */
IRQ_queue_t raised;
@@ -200,8 +225,22 @@ typedef struct openpic_t {
#endif
/* IRQ out is used when in bypass mode (not implemented) */
qemu_irq irq_out;
+ int max_irq;
+ int irq_ipi0;
+ int irq_tim0;
+ int need_swap;
+ void (*reset) (void *);
+ void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
} openpic_t;
+static inline uint32_t openpic_swap32(openpic_t *opp, uint32_t val)
+{
+ if (opp->need_swap)
+ return bswap32(val);
+
+ return val;
+}
+
static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
{
set_bit(q->queue, n_IRQ);
@@ -224,7 +263,7 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
next = -1;
priority = -1;
- for (i = 0; i < MAX_IRQ; i++) {
+ for (i = 0; i < opp->max_irq; i++) {
if (IRQ_testbit(q, i)) {
DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
@@ -286,7 +325,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
return;
}
DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
- qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+ opp->irq_raise(opp, n_CPU, src);
}
/* update pic state because registers for n_IRQ have changed value */
@@ -374,7 +413,7 @@ static void openpic_reset (void *opaque)
opp->glbc = 0x80000000;
/* Initialise controller registers */
- opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
+ opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
opp->veni = VENI;
opp->pint = 0x00000000;
opp->spve = 0x000000FF;
@@ -382,7 +421,7 @@ static void openpic_reset (void *opaque)
/* ? */
opp->micr = 0x00000000;
/* Initialise IRQ sources */
- for (i = 0; i < MAX_IRQ; i++) {
+ for (i = 0; i < opp->max_irq; i++) {
opp->src[i].ipvp = 0xA0000000;
opp->src[i].ide = 0x00000000;
}
@@ -544,16 +583,16 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
if (addr & 0xF)
return;
-#if defined OPENPIC_SWAP
- val = bswap32(val);
+#if defined TARGET_WORDS_BIGENDIAN
+ val = openpic_swap32(opp, val);
#endif
addr &= 0xFF;
switch (addr) {
case 0x00: /* FREP */
break;
case 0x20: /* GLBC */
- if (val & 0x80000000)
- openpic_reset(opp);
+ if (val & 0x80000000 && opp->reset)
+ opp->reset(opp);
opp->glbc = val & ~0x80000000;
break;
case 0x80: /* VENI */
@@ -580,7 +619,7 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
{
int idx;
idx = (addr - 0xA0) >> 4;
- write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);
+ write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val);
}
break;
#endif
@@ -626,7 +665,7 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_t addr)
{
int idx;
idx = (addr - 0xA0) >> 4;
- retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);
+ retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP);
}
break;
#endif
@@ -640,8 +679,8 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_t addr)
break;
}
DPRINTF("%s: => %08x\n", __func__, retval);
-#if defined OPENPIC_SWAP
- retval = bswap32(retval);
+#if defined TARGET_WORDS_BIGENDIAN
+ retval = openpic_swap32(opp, retval);
#endif
return retval;
@@ -655,8 +694,8 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
if (addr & 0xF)
return;
-#if defined OPENPIC_SWAP
- val = bswap32(val);
+#if defined TARGET_WORDS_BIGENDIAN
+ val = openpic_swap32(opp, val);
#endif
addr -= 0x1100;
addr &= 0xFFFF;
@@ -673,10 +712,10 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
opp->timers[idx].tibc = val;
break;
case 0x20: /* TIVP */
- write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);
+ write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP, val);
break;
case 0x30: /* TIDE */
- write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
+ write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE, val);
break;
}
}
@@ -703,15 +742,15 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
retval = opp->timers[idx].tibc;
break;
case 0x20: /* TIPV */
- retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);
+ retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP);
break;
case 0x30: /* TIDE */
- retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);
+ retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE);
break;
}
DPRINTF("%s: => %08x\n", __func__, retval);
-#if defined OPENPIC_SWAP
- retval = bswap32(retval);
+#if defined TARGET_WORDS_BIGENDIAN
+ retval = openpic_swap32(opp, retval);
#endif
return retval;
@@ -725,8 +764,8 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
if (addr & 0xF)
return;
-#if defined OPENPIC_SWAP
- val = tswap32(val);
+#if defined TARGET_WORDS_BIGENDIAN
+ val = openpic_swap32(opp, val);
#endif
addr = addr & 0xFFF0;
idx = addr >> 5;
@@ -759,8 +798,8 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr)
retval = read_IRQreg(opp, idx, IRQ_IPVP);
}
DPRINTF("%s: => %08x\n", __func__, retval);
-#if defined OPENPIC_SWAP
- retval = tswap32(retval);
+#if defined TARGET_WORDS_BIGENDIAN
+ retval = openpic_swap32(opp, retval);
#endif
return retval;
@@ -776,8 +815,8 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
if (addr & 0xF)
return;
-#if defined OPENPIC_SWAP
- val = bswap32(val);
+#if defined TARGET_WORDS_BIGENDIAN
+ val = openpic_swap32(opp, val);
#endif
addr &= 0x1FFF0;
idx = addr / 0x1000;
@@ -790,9 +829,9 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
case 0x60:
case 0x70:
idx = (addr - 0x40) >> 4;
- write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
- openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
- openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
+ write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
+ openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
+ openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
break;
#endif
case 0x80: /* PCTP */
@@ -819,7 +858,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
idx, n_IRQ);
- qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+ opp->irq_raise(opp, idx, src);
}
break;
default:
@@ -889,15 +928,15 @@ static uint32_t openpic_cpu_read (void *opaque, uint32_t addr)
case 0x40: /* IDE */
case 0x50:
idx = (addr - 0x40) >> 4;
- retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);
+ retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE);
break;
#endif
default:
break;
}
DPRINTF("%s: => %08x\n", __func__, retval);
-#if defined OPENPIC_SWAP
- retval= bswap32(retval);
+#if defined TARGET_WORDS_BIGENDIAN
+ retval = openpic_swap32(opp, retval);
#endif
return retval;
@@ -989,7 +1028,7 @@ static void openpic_map(PCIDevice *pci_dev, int region_num,
addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
/* Interrupt source registers */
DPRINTF("Register OPENPIC src %08x => %08x\n",
- addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));
+ addr + 0x10000, addr + 0x10000 + 0x20 * (OPENPIC_EXT_IRQ + 2));
/* Per CPU registers */
DPRINTF("Register OPENPIC dst %08x => %08x\n",
addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
@@ -1026,7 +1065,7 @@ static void openpic_save(QEMUFile* f, void *opaque)
qemu_put_be32s(f, &opp->spve);
qemu_put_be32s(f, &opp->tifr);
- for (i = 0; i < MAX_IRQ; i++) {
+ for (i = 0; i < opp->max_irq; i++) {
qemu_put_be32s(f, &opp->src[i].ipvp);
qemu_put_be32s(f, &opp->src[i].ide);
qemu_put_sbe32s(f, &opp->src[i].type);
@@ -1034,15 +1073,16 @@ static void openpic_save(QEMUFile* f, void *opaque)
qemu_put_sbe32s(f, &opp->src[i].pending);
}
- for (i = 0; i < MAX_IRQ; i++) {
+ qemu_put_sbe32s(f, &opp->nb_cpus);
+
+ for (i = 0; i < opp->nb_cpus; i++) {
+ qemu_put_be32s(f, &opp->dst[i].tfrr);
qemu_put_be32s(f, &opp->dst[i].pctp);
qemu_put_be32s(f, &opp->dst[i].pcsr);
openpic_save_IRQ_queue(f, &opp->dst[i].raised);
openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
}
- qemu_put_sbe32s(f, &opp->nb_cpus);
-
for (i = 0; i < MAX_TMR; i++) {
qemu_put_be32s(f, &opp->timers[i].ticc);
qemu_put_be32s(f, &opp->timers[i].tibc);
@@ -1092,7 +1132,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
qemu_get_be32s(f, &opp->spve);
qemu_get_be32s(f, &opp->tifr);
- for (i = 0; i < MAX_IRQ; i++) {
+ for (i = 0; i < opp->max_irq; i++) {
qemu_get_be32s(f, &opp->src[i].ipvp);
qemu_get_be32s(f, &opp->src[i].ide);
qemu_get_sbe32s(f, &opp->src[i].type);
@@ -1100,15 +1140,16 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
qemu_get_sbe32s(f, &opp->src[i].pending);
}
- for (i = 0; i < MAX_IRQ; i++) {
+ qemu_get_sbe32s(f, &opp->nb_cpus);
+
+ for (i = 0; i < opp->nb_cpus; i++) {
+ qemu_get_be32s(f, &opp->dst[i].tfrr);
qemu_get_be32s(f, &opp->dst[i].pctp);
qemu_get_be32s(f, &opp->dst[i].pcsr);
openpic_load_IRQ_queue(f, &opp->dst[i].raised);
openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
}
- qemu_get_sbe32s(f, &opp->nb_cpus);
-
for (i = 0; i < MAX_TMR; i++) {
qemu_get_be32s(f, &opp->timers[i].ticc);
qemu_get_be32s(f, &opp->timers[i].tibc);
@@ -1131,6 +1172,11 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
return pci_device_load(&opp->pci_dev, f);
}
+static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
+{
+ qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+}
+
qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
qemu_irq **irqs, qemu_irq irq_out)
{
@@ -1164,33 +1210,329 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
// isu_base &= 0xFFFC0000;
opp->nb_cpus = nb_cpus;
+ opp->max_irq = OPENPIC_MAX_IRQ;
+ opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
+ opp->irq_tim0 = OPENPIC_IRQ_TIM0;
/* Set IRQ types */
- for (i = 0; i < EXT_IRQ; i++) {
+ for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
opp->src[i].type = IRQ_EXTERNAL;
}
- for (; i < IRQ_TIM0; i++) {
+ for (; i < OPENPIC_IRQ_TIM0; i++) {
opp->src[i].type = IRQ_SPECIAL;
}
#if MAX_IPI > 0
- m = IRQ_IPI0;
+ m = OPENPIC_IRQ_IPI0;
#else
- m = IRQ_DBL0;
+ m = OPENPIC_IRQ_DBL0;
#endif
for (; i < m; i++) {
opp->src[i].type = IRQ_TIMER;
}
- for (; i < MAX_IRQ; i++) {
+ for (; i < OPENPIC_MAX_IRQ; i++) {
opp->src[i].type = IRQ_INTERNAL;
}
for (i = 0; i < nb_cpus; i++)
opp->dst[i].irqs = irqs[i];
opp->irq_out = irq_out;
+ opp->need_swap = 1;
register_savevm("openpic", 0, 1, openpic_save, openpic_load, opp);
qemu_register_reset(openpic_reset, opp);
- openpic_reset(opp);
+
+ opp->irq_raise = openpic_irq_raise;
+ opp->reset = openpic_reset;
+
+ opp->reset(opp);
if (pmem_index)
*pmem_index = opp->mem_index;
- return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
+ return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
+}
+
+static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
+{
+ int n_ci = IDR_CI0 - n_CPU;
+ DPRINTF("%s: cpu:%d irq:%d (testbit idr:%x ci:%d)\n", __func__,
+ n_CPU, n_IRQ, mpp->src[n_IRQ].ide, n_ci);
+ if(test_bit(&src->ide, n_ci)) {
+ qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
+ }
+ else {
+ qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+ }
+}
+
+static void mpic_reset (void *opaque)
+{
+ openpic_t *mpp = (openpic_t *)opaque;
+ int i;
+
+ mpp->glbc = 0x80000000;
+ /* Initialise controller registers */
+ mpp->frep = 0x004f0002;
+ mpp->veni = VENI;
+ mpp->pint = 0x00000000;
+ mpp->spve = 0x0000FFFF;
+ /* Initialise IRQ sources */
+ for (i = 0; i < mpp->max_irq; i++) {
+ mpp->src[i].ipvp = 0x80800000;
+ mpp->src[i].ide = 0x00000001;
+ }
+ /* Initialise IRQ destinations */
+ for (i = 0; i < MAX_CPU; i++) {
+ mpp->dst[i].pctp = 0x0000000F;
+ mpp->dst[i].tfrr = 0x00000000;
+ memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
+ mpp->dst[i].raised.next = -1;
+ memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
+ mpp->dst[i].servicing.next = -1;
+ }
+ /* Initialise timers */
+ for (i = 0; i < MAX_TMR; i++) {
+ mpp->timers[i].ticc = 0x00000000;
+ mpp->timers[i].tibc = 0x80000000;
+ }
+ /* Go out of RESET state */
+ mpp->glbc = 0x00000000;
+}
+
+static void mpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ openpic_t *mpp = opaque;
+ int idx, cpu;
+
+ DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+ if (addr & 0xF)
+ return;
+ addr &= 0xFFFF;
+ cpu = addr >> 12;
+ idx = (addr >> 6) & 0x3;
+ switch (addr & 0x30) {
+ case 0x00: /* gtccr */
+ break;
+ case 0x10: /* gtbcr */
+ if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
+ (val & 0x80000000) == 0 &&
+ (mpp->timers[idx].tibc & 0x80000000) != 0)
+ mpp->timers[idx].ticc &= ~0x80000000;
+ mpp->timers[idx].tibc = val;
+ break;
+ case 0x20: /* GTIVPR */
+ write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP, val);
+ break;
+ case 0x30: /* GTIDR & TFRR */
+ if ((addr & 0xF0) == 0xF0)
+ mpp->dst[cpu].tfrr = val;
+ else
+ write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE, val);
+ break;
+ }
+}
+
+static uint32_t mpic_timer_read (void *opaque, uint32_t addr)
+{
+ openpic_t *mpp = opaque;
+ uint32_t retval;
+ int idx, cpu;
+
+ DPRINTF("%s: addr %08x\n", __func__, addr);
+ retval = 0xFFFFFFFF;
+ if (addr & 0xF)
+ return retval;
+ addr &= 0xFFFF;
+ cpu = addr >> 12;
+ idx = (addr >> 6) & 0x3;
+ switch (addr & 0x30) {
+ case 0x00: /* gtccr */
+ retval = mpp->timers[idx].ticc;
+ break;
+ case 0x10: /* gtbcr */
+ retval = mpp->timers[idx].tibc;
+ break;
+ case 0x20: /* TIPV */
+ retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP);
+ break;
+ case 0x30: /* TIDR */
+ if ((addr &0xF0) == 0XF0)
+ retval = mpp->dst[cpu].tfrr;
+ else
+ retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE);
+ break;
+ }
+ DPRINTF("%s: => %08x\n", __func__, retval);
+
+ return retval;
+}
+
+static void mpic_src_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ openpic_t *mpp = opaque;
+ int idx;
+
+ DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+ if (addr & 0xF)
+ return;
+ addr = addr & 0xFFF0;
+ if (addr < 0x180) {
+ idx = MPIC_EXT_IRQ;
+ } else if (addr >= 0x200 && addr < 0xa00) {
+ idx = MPIC_INT_IRQ;
+ addr -= 0x200;
+ } else if (addr >= 0x1600 && addr < 0x1700) {
+ idx = MPIC_MSG_IRQ;
+ addr -= 0x1600;
+ } else if (addr >= 0x1C00 && addr < 0x1D00) {
+ idx = MPIC_MSI_IRQ;
+ addr -= 0x1C00;
+ } else {
+ return;
+ }
+ idx += addr >> 5;
+ if (addr & 0x10) {
+ /* EXDE / IFEDE / IEEDE */
+ write_IRQreg(mpp, idx, IRQ_IDE, val);
+ } else {
+ /* EXVP / IFEVP / IEEVP */
+ write_IRQreg(mpp, idx, IRQ_IPVP, val);
+ }
+}
+
+static uint32_t mpic_src_read (void *opaque, uint32_t addr)
+{
+ openpic_t *mpp = opaque;
+ uint32_t retval;
+ int idx;
+
+ DPRINTF("%s: addr %08x\n", __func__, addr);
+ retval = 0xFFFFFFFF;
+ if (addr & 0xF)
+ return retval;
+ addr = addr & 0xFFF0;
+ if (addr < 0x180) {
+ idx = MPIC_EXT_IRQ;
+ } else if (addr >= 0x200 && addr < 0xa00) {
+ idx = MPIC_INT_IRQ;
+ addr -= 0x200;
+ } else if (addr >= 0x1600 && addr < 0x1700) {
+ idx = MPIC_MSG_IRQ;
+ addr -= 0x1600;
+ } else if (addr >= 0x1C00 && addr < 0x1D00) {
+ idx = MPIC_MSI_IRQ;
+ addr -= 0x1C00;
+ } else {
+ return retval;
+ }
+ idx += addr >> 5;
+ if (addr & 0x10) {
+ /* EXDE / IFEDE / IEEDE */
+ retval = read_IRQreg(mpp, idx, IRQ_IDE);
+ } else {
+ /* EXVP / IFEVP / IEEVP */
+ retval = read_IRQreg(mpp, idx, IRQ_IPVP);
+ }
+ DPRINTF("%s: => %08x\n", __func__, retval);
+
+ return retval;
+}
+
+static void mpic_writel (void *opaque,
+ target_phys_addr_t addr, uint32_t val)
+{
+ openpic_t *mpp = opaque;
+
+ addr &= 0x3FFFF;
+ DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
+ if (addr < 0x10F0) {
+ /* Global registers */
+ openpic_gbl_write(mpp, addr, val);
+ } else if (addr < 0x10000) {
+ /* Timers registers */
+ mpic_timer_write(mpp, addr, val);
+ } else if (addr < 0x20000) {
+ /* Source registers */
+ mpic_src_write(mpp, addr, val);
+ } else if (addr < 0x30000){
+ /* CPU registers */
+ openpic_cpu_write(mpp, addr, val);
+ } else {
+ DPRINTF("wrong mpic write addr %p\n",addr);
+ }
+}
+
+static uint32_t mpic_readl (void *opaque,target_phys_addr_t addr)
+{
+ openpic_t *mpp = opaque;
+ uint32_t retval = 0;
+
+ addr &= 0x3FFFF;
+ DPRINTF("%s: offset %08x\n", __func__, (int)addr);
+ if (addr < 0x10F0) {
+ /* Global registers */
+ retval = openpic_gbl_read(mpp, addr);
+ } else if (addr < 0x10000) {
+ /* Timers registers */
+ retval = mpic_timer_read(mpp, addr);
+ } else if (addr < 0x20000) {
+ /* Source registers */
+ retval = mpic_src_read(mpp, addr);
+ } else if (addr < 0x30000){
+ /* CPU registers */
+ retval = openpic_cpu_read(mpp, addr);
+ } else {
+ DPRINTF("wrong mpic read addr %p\n",addr);
+ }
+
+ return retval;
+}
+
+static CPUWriteMemoryFunc *mpic_write[] = {
+ &openpic_buggy_write,
+ &openpic_buggy_write,
+ &mpic_writel,
+};
+
+static CPUReadMemoryFunc *mpic_read[] = {
+ &openpic_buggy_read,
+ &openpic_buggy_read,
+ &mpic_readl,
+};
+
+qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
+ qemu_irq **irqs, qemu_irq irq_out)
+{
+ openpic_t *mpp;
+ int i;
+
+ /* XXX: for now, only one CPU is supported */
+ if (nb_cpus != 1)
+ return NULL;
+
+ mpp = qemu_mallocz(sizeof(openpic_t));
+
+ mpp->mem_index = cpu_register_io_memory(0, mpic_read, mpic_write, mpp);
+ if (mpp->mem_index < 0)
+ goto free;
+ cpu_register_physical_memory(base, MPIC_MAP_SIZE, mpp->mem_index);
+
+ mpp->nb_cpus = nb_cpus;
+ mpp->max_irq = MPIC_MAX_IRQ;
+ mpp->irq_ipi0 = MPIC_IPI_IRQ;
+ mpp->irq_tim0 = MPIC_TMR_IRQ;
+
+ for (i = 0; i < nb_cpus; i++)
+ mpp->dst[i].irqs = irqs[i];
+ mpp->irq_out = irq_out;
+ mpp->need_swap = 0; /* MPIC has the same endian as target */
+
+ mpp->irq_raise = mpic_irq_raise;
+ mpp->reset = mpic_reset;
+
+ register_savevm("mpic", 0, 1, openpic_save, openpic_load, mpp);
+ mpp->reset(mpp);
+
+ return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
+
+free:
+ qemu_free(mpp);
+ return NULL;
}
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index 5851a5e..df148b2 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -112,17 +112,4 @@ void adb_mouse_init(ADBBusState *bus);
extern ADBBusState adb_bus;
-/* openpic.c */
-/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */
-enum {
- OPENPIC_OUTPUT_INT = 0, /* IRQ */
- OPENPIC_OUTPUT_CINT, /* critical IRQ */
- OPENPIC_OUTPUT_MCK, /* Machine check event */
- OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */
- OPENPIC_OUTPUT_RESET, /* Core reset event */
- OPENPIC_OUTPUT_NB,
-};
-qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
- qemu_irq **irqs, qemu_irq irq_out);
-
#endif /* !defined(__PPC_MAC_H__) */
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 6f60e49..b285864 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -34,6 +34,7 @@
#include "boards.h"
#include "fw_cfg.h"
#include "escc.h"
+#include "openpic.h"
#define MAX_IDE_BUS 2
#define VGA_BIOS_SIZE 65536
--
1.5.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support
2009-02-17 9:59 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Liu Yu
@ 2009-02-17 9:59 ` Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 3/5] kvm/powerpc: Add irq support for E500 core Liu Yu
2009-02-17 15:09 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Blue Swirl
2009-02-17 14:55 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Blue Swirl
2009-02-19 23:09 ` Paulev
2 siblings, 2 replies; 19+ messages in thread
From: Liu Yu @ 2009-02-17 9:59 UTC (permalink / raw)
To: qemu-devel, aurelien, hollisb; +Cc: Liu Yu, kvm-ppc
This patch add the emulation of freescale's pci controller for E500 platform.
Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
Makefile.target | 2 +
hw/ppce500_pci.c | 370 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 372 insertions(+), 0 deletions(-)
create mode 100644 hw/ppce500_pci.c
diff --git a/Makefile.target b/Makefile.target
index 9e7a1bb..90b5eb7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -602,6 +602,8 @@ OBJS+= unin_pci.o ppc_newworld.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_pci.o
ifdef FDT_LIBS
OBJS+= device_tree.o
LIBS+= $(FDT_LIBS)
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
new file mode 100644
index 0000000..a81c6e5
--- /dev/null
+++ b/hw/ppce500_pci.c
@@ -0,0 +1,370 @@
+/*
+ * QEMU PowerPC E500 embedded processors pci controller emulation
+ *
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu, <yu.liu@freescale.com>
+ *
+ * This file is derived from hw/ppc4xx_pci.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 "hw.h"
+#include "ppc.h"
+#include "ppce500.h"
+typedef target_phys_addr_t pci_addr_t;
+#include "pci.h"
+#include "pci_host.h"
+#include "bswap.h"
+#include "qemu-log.h"
+
+#ifdef DEBUG_PCI
+#define pci_debug(fmt, arg...) fprintf(stderr, fmt, ##arg)
+#else
+#define pci_debug(fmt, arg...)
+#endif
+
+#define PCIE500_CFGADDR 0x0
+#define PCIE500_CFGDATA 0x4
+#define PCIE500_REG_BASE 0xC00
+#define PCIE500_REG_SIZE (0x1000 - PCIE500_REG_BASE)
+
+#define PPCE500_PCI_CONFIG_ADDR 0x0
+#define PPCE500_PCI_CONFIG_DATA 0x4
+#define PPCE500_PCI_INTACK 0x8
+
+#define PPCE500_PCI_OW1 (0xC20 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW2 (0xC40 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW3 (0xC60 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW4 (0xC80 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW3 (0xDA0 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW2 (0xDC0 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW1 (0xDE0 - PCIE500_REG_BASE)
+
+#define PPCE500_PCI_GASKET_TIMR (0xE20 - PCIE500_REG_BASE)
+
+#define PCI_POTAR 0x0
+#define PCI_POTEAR 0x4
+#define PCI_POWBAR 0x8
+#define PCI_POWAR 0x10
+
+#define PCI_PITAR 0x0
+#define PCI_PIWBAR 0x8
+#define PCI_PIWBEAR 0xC
+#define PCI_PIWAR 0x10
+
+#define PPCE500_PCI_NR_POBS 5
+#define PPCE500_PCI_NR_PIBS 3
+
+struct pci_outbound {
+ uint32_t potar;
+ uint32_t potear;
+ uint32_t powbar;
+ uint32_t powar;
+};
+
+struct pci_inbound {
+ uint32_t pitar;
+ uint32_t piwbar;
+ uint32_t piwbear;
+ uint32_t piwar;
+};
+
+struct PPCE500PCIState {
+ struct pci_outbound pob[PPCE500_PCI_NR_POBS];
+ struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
+ uint32_t gasket_time;
+ PCIHostState pci_state;
+ PCIDevice *pci_dev;
+};
+
+typedef struct PPCE500PCIState PPCE500PCIState;
+
+static uint32_t pcie500_cfgaddr_readl(void *opaque, target_phys_addr_t addr)
+{
+ PPCE500PCIState *pci = opaque;
+
+ pci_debug("%s: (addr:%Lx) -> value:%x\n", __func__, addr,
+ pci->pci_state.config_reg);
+ return pci->pci_state.config_reg;
+}
+
+static CPUReadMemoryFunc *pcie500_cfgaddr_read[] = {
+ &pcie500_cfgaddr_readl,
+ &pcie500_cfgaddr_readl,
+ &pcie500_cfgaddr_readl,
+};
+
+static void pcie500_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ PPCE500PCIState *controller = opaque;
+
+ pci_debug("%s: value:%x -> (addr%Lx)\n", __func__, value, addr);
+ controller->pci_state.config_reg = value & ~0x3;
+}
+
+static CPUWriteMemoryFunc *pcie500_cfgaddr_write[] = {
+ &pcie500_cfgaddr_writel,
+ &pcie500_cfgaddr_writel,
+ &pcie500_cfgaddr_writel,
+};
+
+static CPUReadMemoryFunc *pcie500_cfgdata_read[] = {
+ &pci_host_data_readb,
+ &pci_host_data_readw,
+ &pci_host_data_readl,
+};
+
+static CPUWriteMemoryFunc *pcie500_cfgdata_write[] = {
+ &pci_host_data_writeb,
+ &pci_host_data_writew,
+ &pci_host_data_writel,
+};
+
+static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
+{
+ PPCE500PCIState *pci = opaque;
+ unsigned long win;
+ uint32_t value = 0;
+
+ win = addr & 0xfe0;
+
+ switch (win) {
+ case PPCE500_PCI_OW1:
+ case PPCE500_PCI_OW2:
+ case PPCE500_PCI_OW3:
+ case PPCE500_PCI_OW4:
+ switch (addr & 0xC) {
+ case PCI_POTAR: value = pci->pob[(addr >> 5) & 0x7].potar; break;
+ case PCI_POTEAR: value = pci->pob[(addr >> 5) & 0x7].potear; break;
+ case PCI_POWBAR: value = pci->pob[(addr >> 5) & 0x7].powbar; break;
+ case PCI_POWAR: value = pci->pob[(addr >> 5) & 0x7].powar; break;
+ default: break;
+ }
+ break;
+
+ case PPCE500_PCI_IW3:
+ case PPCE500_PCI_IW2:
+ case PPCE500_PCI_IW1:
+ switch (addr & 0xC) {
+ case PCI_PITAR: value = pci->pib[(addr >> 5) & 0x3].pitar; break;
+ case PCI_PIWBAR: value = pci->pib[(addr >> 5) & 0x3].piwbar; break;
+ case PCI_PIWBEAR: value = pci->pib[(addr >> 5) & 0x3].piwbear; break;
+ case PCI_PIWAR: value = pci->pib[(addr >> 5) & 0x3].piwar; break;
+ default: break;
+ };
+ break;
+
+ case PPCE500_PCI_GASKET_TIMR:
+ value = pci->gasket_time;
+ break;
+
+ default:
+ break;
+ }
+
+ pci_debug("%s: win:%lx(addr:%Lx) -> value:%x\n",__func__,win,addr,value);
+ return value;
+}
+
+static CPUReadMemoryFunc *e500_pci_reg_read[] = {
+ &pci_reg_read4,
+ &pci_reg_read4,
+ &pci_reg_read4,
+};
+
+static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ PPCE500PCIState *pci = opaque;
+ unsigned long win;
+
+ win = addr & 0xfe0;
+
+ pci_debug("%s: value:%x -> win:%lx(addr:%Lx)\n",__func__,value,win,addr);
+
+ switch (win) {
+ case PPCE500_PCI_OW1:
+ case PPCE500_PCI_OW2:
+ case PPCE500_PCI_OW3:
+ case PPCE500_PCI_OW4:
+ switch (addr & 0xC) {
+ case PCI_POTAR: pci->pob[(addr >> 5) & 0x7].potar = value; break;
+ case PCI_POTEAR: pci->pob[(addr >> 5) & 0x7].potear = value; break;
+ case PCI_POWBAR: pci->pob[(addr >> 5) & 0x7].powbar = value; break;
+ case PCI_POWAR: pci->pob[(addr >> 5) & 0x7].powar = value; break;
+ default: break;
+ };
+ break;
+
+ case PPCE500_PCI_IW3:
+ case PPCE500_PCI_IW2:
+ case PPCE500_PCI_IW1:
+ switch (addr & 0xC) {
+ case PCI_PITAR: pci->pib[(addr >> 5) & 0x3].pitar = value; break;
+ case PCI_PIWBAR: pci->pib[(addr >> 5) & 0x3].piwbar = value; break;
+ case PCI_PIWBEAR: pci->pib[(addr >> 5) & 0x3].piwbear = value; break;
+ case PCI_PIWAR: pci->pib[(addr >> 5) & 0x3].piwar = value; break;
+ default: break;
+ };
+ break;
+
+ case PPCE500_PCI_GASKET_TIMR:
+ pci->gasket_time = value;
+ break;
+
+ default:
+ break;
+ };
+}
+
+static CPUWriteMemoryFunc *e500_pci_reg_write[] = {
+ &pci_reg_write4,
+ &pci_reg_write4,
+ &pci_reg_write4,
+};
+
+static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+ int devno = pci_dev->devfn >> 3, ret = 0;
+
+ switch (devno) {
+ /* Two PCI slot */
+ case 0x11:
+ case 0x12:
+ ret = (irq_num + devno - 0x10) % 4;
+ break;
+ default:
+ printf("Error:%s:unknow dev number\n", __func__);
+ }
+
+ pci_debug("%s: devfn %x irq %d -> %d devno:%x\n", __func__,
+ pci_dev->devfn, irq_num, ret, devno);
+
+ return ret;
+}
+
+static void mpc85xx_pci_set_irq(qemu_irq *pic, int irq_num, int level)
+{
+ pci_debug("%s: PCI irq %d, level:%d\n", __func__, irq_num, level);
+
+ qemu_set_irq(pic[irq_num], level);
+}
+
+static void ppce500_pci_save(QEMUFile *f, void *opaque)
+{
+ PPCE500PCIState *controller = opaque;
+ int i;
+
+ pci_device_save(controller->pci_dev, f);
+
+ for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
+ qemu_put_be32s(f, &controller->pob[i].potar);
+ qemu_put_be32s(f, &controller->pob[i].potear);
+ qemu_put_be32s(f, &controller->pob[i].powbar);
+ qemu_put_be32s(f, &controller->pob[i].powar);
+ }
+
+ for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
+ qemu_put_be32s(f, &controller->pib[i].pitar);
+ qemu_put_be32s(f, &controller->pib[i].piwbar);
+ qemu_put_be32s(f, &controller->pib[i].piwbear);
+ qemu_put_be32s(f, &controller->pib[i].piwar);
+ }
+ qemu_put_be32s(f, &controller->gasket_time);
+}
+
+static int ppce500_pci_load(QEMUFile *f, void *opaque, int version_id)
+{
+ PPCE500PCIState *controller = opaque;
+ int i;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ pci_device_load(controller->pci_dev, f);
+
+ for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
+ qemu_get_be32s(f, &controller->pob[i].potar);
+ qemu_get_be32s(f, &controller->pob[i].potear);
+ qemu_get_be32s(f, &controller->pob[i].powbar);
+ qemu_get_be32s(f, &controller->pob[i].powar);
+ }
+
+ for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
+ qemu_get_be32s(f, &controller->pib[i].pitar);
+ qemu_get_be32s(f, &controller->pib[i].piwbar);
+ qemu_get_be32s(f, &controller->pib[i].piwbear);
+ qemu_get_be32s(f, &controller->pib[i].piwar);
+ }
+ qemu_get_be32s(f, &controller->gasket_time);
+
+ return 0;
+}
+
+PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
+{
+ PPCE500PCIState *controller;
+ PCIDevice *d;
+ int index;
+ static int ppce500_pci_id;
+
+ controller = qemu_mallocz(sizeof(PPCE500PCIState));
+ if (!controller)
+ return NULL;
+
+ controller->pci_state.bus = pci_register_bus(mpc85xx_pci_set_irq,
+ mpc85xx_pci_map_irq,
+ pci_irqs, 0x88, 4);
+ d = pci_register_device(controller->pci_state.bus,
+ "host bridge", sizeof(PCIDevice),
+ 0, NULL, NULL);
+
+ d->config[0x00] = 0x57; // vendor_id
+ d->config[0x01] = 0x19;
+ d->config[0x02] = 0x30; // device_id
+ d->config[0x03] = 0x00;
+ d->config[0x0a] = 0x20; // class_sub = other bridge type
+ d->config[0x0b] = 0x0B; // class_base = PCI_bridge
+
+ controller->pci_dev = d;
+
+ /* CFGADDR */
+ index = cpu_register_io_memory(0, pcie500_cfgaddr_read,
+ pcie500_cfgaddr_write, controller);
+ if (index < 0)
+ goto free;
+ cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
+
+ /* CFGDATA */
+ index = cpu_register_io_memory(0, pcie500_cfgdata_read,
+ pcie500_cfgdata_write,
+ &controller->pci_state);
+ if (index < 0)
+ goto free;
+ cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
+
+ index = cpu_register_io_memory(0, e500_pci_reg_read,
+ e500_pci_reg_write, controller);
+ if (index < 0)
+ goto free;
+ cpu_register_physical_memory(registers + PCIE500_REG_BASE,
+ PCIE500_REG_SIZE, index);
+
+ /* XXX load/save code not tested. */
+ register_savevm("ppce500_pci", ppce500_pci_id++, 1,
+ ppce500_pci_save, ppce500_pci_load, controller);
+
+ return controller->pci_state.bus;
+
+free:
+ printf("%s error\n", __func__);
+ qemu_free(controller);
+ return NULL;
+}
--
1.5.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH 3/5] kvm/powerpc: Add irq support for E500 core
2009-02-17 9:59 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Liu Yu
@ 2009-02-17 9:59 ` Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Liu Yu
2009-02-17 15:09 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Blue Swirl
1 sibling, 1 reply; 19+ messages in thread
From: Liu Yu @ 2009-02-17 9:59 UTC (permalink / raw)
To: qemu-devel, aurelien, hollisb; +Cc: Liu Yu, kvm-ppc
Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
hw/ppc.c | 60 +++++++++++++++++++++++++++++++++++++++++++
hw/ppc.h | 1 +
target-ppc/cpu.h | 10 +++++++
target-ppc/translate_init.c | 5 ++-
4 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/hw/ppc.c b/hw/ppc.c
index 9a01c01..b534e39 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -314,6 +314,66 @@ 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;
+
+ LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+ env, pin, level);
+ 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) {
+ LOG_IRQ("%s: reset the PowerPC system\n",
+ __func__);
+ qemu_system_reset_request();
+ }
+ break;
+ case PPCE500_INPUT_RESET_CORE:
+ if (level) {
+ LOG_IRQ("%s: reset the PowerPC core\n", __func__);
+ ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
+ }
+ break;
+ case PPCE500_INPUT_CINT:
+ /* Level sensitive - active high */
+ LOG_IRQ("%s: set the critical IRQ state to %d\n",
+ __func__, level);
+ ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
+ break;
+ case PPCE500_INPUT_INT:
+ /* Level sensitive - active high */
+ LOG_IRQ("%s: set the core IRQ state to %d\n",
+ __func__, level);
+ ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+ break;
+ case PPCE500_INPUT_DEBUG:
+ /* Level sensitive - active high */
+ LOG_IRQ("%s: set the debug pin state to %d\n",
+ __func__, level);
+ ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
+ break;
+ default:
+ /* Unknown pin - do nothing */
+ LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
+ 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 75eb11a..2ec4680 100644
--- a/hw/ppc.h
+++ b/hw/ppc.h
@@ -31,6 +31,7 @@ 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/target-ppc/cpu.h b/target-ppc/cpu.h
index 80ee76c..bdc3cf9 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1356,6 +1356,16 @@ enum {
};
enum {
+ /* PowerPC E500 input pins */
+ PPCE500_INPUT_RESET_CORE = 0,
+ PPCE500_INPUT_MCK = 1,
+ PPCE500_INPUT_CINT = 3,
+ PPCE500_INPUT_INT = 4,
+ 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/translate_init.c b/target-ppc/translate_init.c
index 889708f..5d1c0b4 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -63,6 +63,7 @@ void glue(glue(ppc, name),_irq_init) (CPUPPCState *env);
PPC_IRQ_INIT_FN(40x);
PPC_IRQ_INIT_FN(6xx);
PPC_IRQ_INIT_FN(970);
+PPC_IRQ_INIT_FN(e500);
/* Generic callbacks:
* do nothing but store/retrieve spr value
@@ -4185,7 +4186,6 @@ static void init_proc_e300 (CPUPPCState *env)
#define check_pow_e500v2 check_pow_hid0
#define init_proc_e500v2 init_proc_e500
-__attribute__ (( unused ))
static void init_proc_e500 (CPUPPCState *env)
{
/* Time base */
@@ -4287,7 +4287,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
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support
2009-02-17 9:59 ` [Qemu-devel] [PATCH 3/5] kvm/powerpc: Add irq support for E500 core Liu Yu
@ 2009-02-17 9:59 ` Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 5/5] kvm/powerpc: flat device tree files for MPC8544DS Liu Yu
2009-02-17 15:28 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Blue Swirl
0 siblings, 2 replies; 19+ messages in thread
From: Liu Yu @ 2009-02-17 9:59 UTC (permalink / raw)
To: qemu-devel, aurelien, hollisb; +Cc: Liu Yu, kvm-ppc
This patch add emulation of MPC8544DS board.
And it can work on All E500 platforms.
Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
Makefile.target | 2 +-
hw/boards.h | 1 +
hw/ppce500.h | 22 ++++
hw/ppce500_mpc8544ds.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++++
target-ppc/machine.c | 1 +
5 files changed, 311 insertions(+), 1 deletions(-)
create mode 100644 hw/ppce500.h
create mode 100644 hw/ppce500_mpc8544ds.c
diff --git a/Makefile.target b/Makefile.target
index 90b5eb7..f33f762 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -603,7 +603,7 @@ OBJS+= unin_pci.o ppc_newworld.o
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_pci.o
+OBJS+= ppce500_pci.o ppce500_mpc8544ds.o
ifdef FDT_LIBS
OBJS+= device_tree.o
LIBS+= $(FDT_LIBS)
diff --git a/hw/boards.h b/hw/boards.h
index 7384817..1e62594 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -42,6 +42,7 @@ extern QEMUMachine heathrow_machine;
extern QEMUMachine ref405ep_machine;
extern QEMUMachine taihu_machine;
extern QEMUMachine bamboo_machine;
+extern QEMUMachine mpc8544ds_machine;
/* mips_r4k.c */
extern QEMUMachine mips_machine;
diff --git a/hw/ppce500.h b/hw/ppce500.h
new file mode 100644
index 0000000..24d49bb
--- /dev/null
+++ b/hw/ppce500.h
@@ -0,0 +1,22 @@
+/*
+ * QEMU PowerPC E500 emulation shared definitions
+ *
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu, <yu.liu@freescale.com>
+ *
+ * This file is derived from hw/ppc440.h
+ * 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.
+ */
+
+#if !defined(PPC_E500_H)
+#define PPC_E500_H
+
+PCIBus *ppce500_pci_init(qemu_irq *pic, target_phys_addr_t registers);
+
+#endif /* !defined(PPC_E500_H) */
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
new file mode 100644
index 0000000..3691698
--- /dev/null
+++ b/hw/ppce500_mpc8544ds.c
@@ -0,0 +1,286 @@
+/*
+ * Qemu PowerPC MPC8544DS board emualtion
+ *
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu, <yu.liu@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 "pc.h"
+#include "pci.h"
+#include "virtio-blk.h"
+#include "boards.h"
+#include "sysemu.h"
+#include "kvm.h"
+#include "kvm_ppc.h"
+#include "device_tree.h"
+#include "openpic.h"
+#include "ppce500.h"
+
+#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
+#define UIMAGE_LOAD_BASE 0
+#define DTB_LOAD_BASE 0x600000
+#define INITRD_LOAD_BASE 0x2000000
+
+#define RAM_SIZES_ALIGN (64UL << 20)
+
+#define MPC8544_CCSRBAR_BASE 0xE0000000
+#define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000)
+#define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500)
+#define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600)
+#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000)
+#define MPC8544_PCI_REGS_SIZE 0x1000
+#define MPC8544_PCI_IO 0xE1000000
+#define MPC8544_PCI_IOLEN 0x10000
+
+static int mpc8544_copy_soc_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,8544@0",
+ prop, cell);
+ if (ret < 0) {
+ fprintf(stderr, "couldn't set guest /cpus/PowerPC,8544@0/%s\n", prop);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void *mpc8544_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()) {
+ struct dirent *dirp;
+ DIR *dp;
+ char buf[128];
+
+ 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, "/cpus/%s", dirp->d_name);
+ break;
+ }
+ }
+ closedir(dp);
+ if (buf[0] == '\0') {
+ printf("Unknow host!\n");
+ goto out;
+ }
+
+ mpc8544_copy_soc_cell(fdt, buf, "clock-frequency");
+ mpc8544_copy_soc_cell(fdt, buf, "timebase-frequency");
+ }
+
+out:
+#endif
+
+ return fdt;
+}
+
+static void mpc8544ds_init(ram_addr_t ram_size, int vga_ram_size,
+ const char *boot_device,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *cpu_model)
+{
+ 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 *irqs, *mpic, *pci_irqs;
+ SerialState * serial[2];
+
+ /* Setup CPU */
+ env = cpu_ppc_init("e500v2_v30");
+ if (!env) {
+ fprintf(stderr, "Unable to initialize CPU!\n");
+ exit(1);
+ }
+
+ /* Fixup Memory size on a alignment boundary */
+ ram_size &= ~(RAM_SIZES_ALIGN - 1);
+
+ /* Register Memory */
+ cpu_register_physical_memory(0, ram_size, 0);
+
+ /* MPIC */
+ irqs = qemu_mallocz(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
+ irqs[OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_INT];
+ irqs[OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_CINT];
+ mpic = mpic_init(MPC8544_MPIC_REGS_BASE, 1, &irqs, NULL);
+
+ /* Serial */
+ if (serial_hds[0])
+ serial[0] = serial_mm_init(MPC8544_SERIAL0_REGS_BASE,
+ 0, mpic[12+26], 399193,
+ serial_hds[0], 1);
+
+ if (serial_hds[1])
+ serial[0] = serial_mm_init(MPC8544_SERIAL1_REGS_BASE,
+ 0, mpic[12+26], 399193,
+ serial_hds[0], 1);
+
+ /* 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, MPC8544_PCI_REGS_BASE);
+ if (!pci_bus)
+ printf("couldn't create PCI controller!\n");
+
+ isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN);
+
+ 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++) {
+ pci_nic_init(pci_bus, &nd_table[i], -1, "virtio");
+ }
+ }
+
+ /* 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 = mpc8544_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 mpc8544ds_machine = {
+ .name = "mpc8544ds",
+ .desc = "mpc8544ds",
+ .init = mpc8544ds_init,
+ .ram_require = RAM_SIZES_ALIGN | RAMSIZE_FIXED,
+};
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 4f9a191..02eecb8 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(&mpc8544ds_machine);
}
void cpu_save(QEMUFile *f, void *opaque)
--
1.5.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH 5/5] kvm/powerpc: flat device tree files for MPC8544DS
2009-02-17 9:59 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Liu Yu
@ 2009-02-17 9:59 ` Liu Yu
2009-02-17 15:28 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Blue Swirl
1 sibling, 0 replies; 19+ messages in thread
From: Liu Yu @ 2009-02-17 9:59 UTC (permalink / raw)
To: qemu-devel, aurelien, hollisb; +Cc: Liu Yu, kvm-ppc
mpc8544ds.dts is copied from kerenl.
Non-supported devices has been removed.
Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
pc-bios/mpc8544ds.dtb | Bin 0 -> 12288 bytes
pc-bios/mpc8544ds.dts | 122 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 122 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/mpc8544ds.dtb
create mode 100644 pc-bios/mpc8544ds.dts
diff --git a/pc-bios/mpc8544ds.dtb b/pc-bios/mpc8544ds.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..3299546696bf21f53f8ce2c9eba7fcb740c547da
GIT binary patch
literal 12288
zcmeHIJ8u&~5Z)um5MBxr1r@SLgOE>gBs)q$VJkovDTp5sUCx{MlzVY^28Sx5qJ!T+
zNtKd<A{{NFM>0PEYG{D@_IA$pB`MM&G$W079^cH)ez$l2eEs)#rP_+*gHo3YTJMqG
zBwZpUakiCed@SvM>esQ;EYNxd_U6{cdbiVg__RzQev7m*jT>t`E)mFIB*j_Li~Xkc
z9WM;LT<7GP+#On5D|zB$lb&vuvXbj8@WNiF+cqptv7NKAYqQuJ)c3(k>IbIhI<>`)
zN?jmz{B&dnAe-kqZC>D=t>lHywl-R3zOo6|^r;Up>~F#$VgCu)%^BaX`BZ#Jp$h-1
z=D$Ibg!{cK-O4|*KF(y$73nC+4onm^mq`1y*ky|GoB*1-I{iqH@V=*UGy81&RL}UU
zWHj<1N<;1LSeDV}8tE~qn&4*%Kc>H#XJT9v<URSUPVFXe{*x&wdzf>UI1>d1eH(GU
zy4LNQhsH5F`y)!3YtFrxN5*_1z<pA1!<etOsN~DuPJ81RgPE9@bI$bGmR9?nd!{t-
zdmX$z)QJQ$L4J_(e0Yu!>pNKajOD$+n+q*5c!wJPFiTrWs$-XSFey{NNM?UNT=m8G
z0X(3$;p^mU$XGS|9G3{+*v-RMl;U&HcBzg+6}CU)6V|z_)KBDDz&Xw|p<Gv~*Br-+
zd3YvT=W=F7%A>ZPvoXU;JqM=H)9PC?E8)1UpUd%nwtg<h`&rCfuC`yr3*SxD;yL2}
z-X=v48*?_uhWsH#tWA0h0OZ&z>?SFOXZglP8AL7SI9mACdrzzN&0PY5^G&jOf8cTV
zkb|1LHc^LUE|D6X;}4Tu$8ZgX{ui9hv%mG#{{r@aE=I{fhssZ))GLCWP^)EcFvxVC
zyS@&?TrKCpOKt7)ThUhKx~k}2wbejB4}85{9Hd%hdQS~p-}8ss4TD&_C|1FV2xI2b
z#wmhG@6aEeyPN4}BOUt(iav)ko*yRu{*0e_@gDsxVpunb2YRf6xX@WPN{f7Ix~Z4x
zxR?p}NnB(}80t(dR~7c0H2P@VN{3!NAVQ|u$V=VG%lGF)W<WEBDhu;skc<l2vKZpA
zhzJA1fG{8o2m``^Fdz&F1HynXAPfit!hkR!3<v|lfG{8o2m``^Fdz&F1HynXAPfit
W!hkR!3<v|lfG{8o2m}8&1AhU`J`#BV
literal 0
HcmV?d00001
diff --git a/pc-bios/mpc8544ds.dts b/pc-bios/mpc8544ds.dts
new file mode 100644
index 0000000..872152d
--- /dev/null
+++ b/pc-bios/mpc8544ds.dts
@@ -0,0 +1,122 @@
+/*
+ * MPC8544 DS Device Tree Source
+ *
+ * Copyright 2007, 2008 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 = "MPC8544DS";
+ compatible = "MPC8544DS", "MPC85xxDS";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ pci0 = &pci0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8544@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>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x0>; // Filled by U-Boot
+ };
+
+ soc8544@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.
+
+ 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>;
+ };
+
+ mpic: pic@40000 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ };
+ };
+
+ 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>;
+ };
+
+ chosen {
+ linux,stdout-path = "/soc8544@e0000000/serial@4500";
+ };
+};
--
1.5.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform.
2009-02-17 9:59 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Liu Yu
@ 2009-02-17 14:55 ` Blue Swirl
2009-02-18 7:17 ` Liu Yu-B13201
2009-02-19 22:41 ` Aurelien Jarno
2009-02-19 23:09 ` Paulev
2 siblings, 2 replies; 19+ messages in thread
From: Blue Swirl @ 2009-02-17 14:55 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm-ppc, Liu Yu, hollisb, aurelien
On 2/17/09, Liu Yu <yu.liu@freescale.com> wrote:
> MPIC and OpenPIC have very similar design.
> So a lot of code can be reused.
>
> Modification mainly include:
> 1. keep struct openpic_t to the maximum size of both MPIC and OpenPIC.
> 2. endianess swap.
> MPIC has the same endianess as target, so no need to swap for MPIC.
I don't think this is correct, the host can still be different endian
from target.
> 3. using different init functions and function pointers for reset and irq raise.
You didn't register the reset handler with qemu_register_reset.
> Haven't test OpenPIC.
>
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> +static void mpic_src_write (void *opaque, uint32_t addr, uint32_t val)
> + if (addr < 0x180) {
> + idx = MPIC_EXT_IRQ;
> + } else if (addr >= 0x200 && addr < 0xa00) {
> + idx = MPIC_INT_IRQ;
> + addr -= 0x200;
> + } else if (addr >= 0x1600 && addr < 0x1700) {
> + idx = MPIC_MSG_IRQ;
> + addr -= 0x1600;
> + } else if (addr >= 0x1C00 && addr < 0x1D00) {
> + idx = MPIC_MSI_IRQ;
> + addr -= 0x1C00;
> + } else {
> + return;
It would be faster and simpler to register different handlers for
these memory areas, same goes for mpic_src_read, mpic_writel and
mpic_readl.
> + register_savevm("mpic", 0, 1, openpic_save, openpic_load, mpp);
When the save format changes, the version number should be bumped.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support
2009-02-17 9:59 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 3/5] kvm/powerpc: Add irq support for E500 core Liu Yu
@ 2009-02-17 15:09 ` Blue Swirl
2009-02-17 16:08 ` M. Warner Losh
2009-02-18 6:04 ` Liu Yu-B13201
1 sibling, 2 replies; 19+ messages in thread
From: Blue Swirl @ 2009-02-17 15:09 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm-ppc, Liu Yu, hollisb, aurelien
On 2/17/09, Liu Yu <yu.liu@freescale.com> wrote:
> This patch add the emulation of freescale's pci controller for E500 platform.
>
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
A reset function (registered with qemu_register_reset) would be nice.
> + * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
"All rights reserved" conflicts with GPL.
> + d->config[0x00] = 0x57; // vendor_id
> + d->config[0x01] = 0x19;
> + d->config[0x02] = 0x30; // device_id
> + d->config[0x03] = 0x00;
Please use pci_config_set_vendor_id and pci_config_set_device_id
functions and add the ID #defines to hw/pci.h.
> + d->config[0x0a] = 0x20; // class_sub = other bridge type
> + d->config[0x0b] = 0x0B; // class_base = PCI_bridge
I'd think these should be 0x06 (PCI_BASE_CLASS_BRIDGE) and 0x04
(PCI_CLASS_BRIDGE_PCI). Are these correct?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support
2009-02-17 9:59 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 5/5] kvm/powerpc: flat device tree files for MPC8544DS Liu Yu
@ 2009-02-17 15:28 ` Blue Swirl
2009-02-18 7:01 ` Liu Yu-B13201
1 sibling, 1 reply; 19+ messages in thread
From: Blue Swirl @ 2009-02-17 15:28 UTC (permalink / raw)
To: qemu-devel; +Cc: kvm-ppc, Liu Yu, hollisb, aurelien
On 2/17/09, Liu Yu <yu.liu@freescale.com> wrote:
> This patch add emulation of MPC8544DS board.
> And it can work on All E500 platforms.
>
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> + * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
Again, "All rights reserved" is not what GPL says.
> + 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;
> + }
For the Qemu case, the host CPU or system may be different from the
emulated target CPU or system. These should be moved to
target-ppc/kvm_ppc.c.
> + path = qemu_malloc(pathlen);
> + if (path == NULL)
> + goto out;
qemu_malloc will not return NULL anymore, please remove the check.
> + free(path);
s/free/qemu_free/g
> + sprintf(buf, "/cpus/%s", dirp->d_name);
Please use snprintf.
> + /* Register Memory */
> + cpu_register_physical_memory(0, ram_size, 0);
This was the old way. Please use qemu_ram_alloc instead.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support
2009-02-17 15:09 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Blue Swirl
@ 2009-02-17 16:08 ` M. Warner Losh
2009-02-17 16:23 ` M. Warner Losh
2009-02-18 6:04 ` Liu Yu-B13201
1 sibling, 1 reply; 19+ messages in thread
From: M. Warner Losh @ 2009-02-17 16:08 UTC (permalink / raw)
To: qemu-devel, blauwirbel; +Cc: aurelien, yu.liu, hollisb, kvm-ppc
In message: <f43fc5580902170709n3ba3f5f6o71a46769d1449c00@mail.gmail.com>
Blue Swirl <blauwirbel@gmail.com> writes:
: > + * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
:
: "All rights reserved" conflicts with GPL.
"All rights reserved" is a phrase used to invoke one's copyright in
Latin America prior to the some of the more recent rounds of IP
treaties.
It isn't needed any more, but it definitely does not conflict with the
GPL. The author reserves all rights, and then grants you from those
rights the rights to distribute with the GPL. It never has conflicted
with the GPL. Ever.
Warner
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support
2009-02-17 16:08 ` M. Warner Losh
@ 2009-02-17 16:23 ` M. Warner Losh
2009-02-17 17:41 ` Jamie Lokier
0 siblings, 1 reply; 19+ messages in thread
From: M. Warner Losh @ 2009-02-17 16:23 UTC (permalink / raw)
To: qemu-devel, blauwirbel; +Cc: kvm-ppc, yu.liu, hollisb, aurelien
In message: <20090217.090852.-292225365.imp@bsdimp.com>
"M. Warner Losh" <imp@bsdimp.com> writes:
: In message: <f43fc5580902170709n3ba3f5f6o71a46769d1449c00@mail.gmail.com>
: Blue Swirl <blauwirbel@gmail.com> writes:
: : > + * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
: :
: : "All rights reserved" conflicts with GPL.
:
: "All rights reserved" is a phrase used to invoke one's copyright in
: Latin America prior to the some of the more recent rounds of IP
: treaties.
Specifically, this was the Buenos Aires Convention from 1910.
: It isn't needed any more, but it definitely does not conflict with the
: GPL. The author reserves all rights, and then grants you from those
: rights the rights to distribute with the GPL. It never has conflicted
: with the GPL. Ever.
There's one web page[1] that suggests that this might be useful to
preserve moral rights in some countries. Moral rights are the right
to take one's name off something that someone else has changed
contrary to your wishes. I don't know the extent that this matter
these days.
Warner
[1] http://www.templetons.com/brad/copymyths.html
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support
2009-02-17 16:23 ` M. Warner Losh
@ 2009-02-17 17:41 ` Jamie Lokier
0 siblings, 0 replies; 19+ messages in thread
From: Jamie Lokier @ 2009-02-17 17:41 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel, aurelien, yu.liu, hollisb, kvm-ppc
M. Warner Losh wrote:
> There's one web page[1] that suggests that this might be useful to
> preserve moral rights in some countries. Moral rights are the right
> to take one's name off something that someone else has changed
> contrary to your wishes. I don't know the extent that this matter
> these days.
Moral rights can include the right to be named as an author if you
want. But last time I looked at UK law, there was a specific
exemption that you don't have that right with computer programs.
-- Jamie
^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support
2009-02-17 15:09 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Blue Swirl
2009-02-17 16:08 ` M. Warner Losh
@ 2009-02-18 6:04 ` Liu Yu-B13201
1 sibling, 0 replies; 19+ messages in thread
From: Liu Yu-B13201 @ 2009-02-18 6:04 UTC (permalink / raw)
To: Blue Swirl, qemu-devel; +Cc: kvm-ppc, hollisb, aurelien
> -----Original Message-----
> From: kvm-ppc-owner@vger.kernel.org
> [mailto:kvm-ppc-owner@vger.kernel.org] On Behalf Of Blue Swirl
> Sent: Tuesday, February 17, 2009 11:09 PM
> To: qemu-devel@nongnu.org
> Cc: aurelien@aurel32.net; hollisb@us.ibm.com; Liu Yu-B13201;
> kvm-ppc@vger.kernel.org
> Subject: Re: [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add
> freescale pci controller's support
>
> On 2/17/09, Liu Yu <yu.liu@freescale.com> wrote:
> > This patch add the emulation of freescale's pci controller
> for E500 platform.
> >
> > Signed-off-by: Liu Yu <yu.liu@freescale.com>
>
> A reset function (registered with qemu_register_reset) would be nice.
>
> > + * Copyright (C) 2009 Freescale Semiconductor, Inc. All
> rights reserved.
>
> "All rights reserved" conflicts with GPL.
It's our company's policy, all the patches submitted to kernel comply with this as well.
>
> > + d->config[0x00] = 0x57; // vendor_id
> > + d->config[0x01] = 0x19;
> > + d->config[0x02] = 0x30; // device_id
> > + d->config[0x03] = 0x00;
>
> Please use pci_config_set_vendor_id and pci_config_set_device_id
> functions and add the ID #defines to hw/pci.h.
Fixed.
>
> > + d->config[0x0a] = 0x20; // class_sub = other bridge type
> > + d->config[0x0b] = 0x0B; // class_base = PCI_bridge
>
> I'd think these should be 0x06 (PCI_BASE_CLASS_BRIDGE) and 0x04
> (PCI_CLASS_BRIDGE_PCI). Are these correct?
Sorry for the wrong comments.
I confirmed it from user manual, and I also print the header out on MPC8544 board.
it shows that these value are correct.
0x20 represent PowerPC and 0x0B represent processor.
Like "#define PCI_CLASS_PROCESSOR_CO 0x0b40" in hw/pci.h
^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support
2009-02-17 15:28 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Blue Swirl
@ 2009-02-18 7:01 ` Liu Yu-B13201
0 siblings, 0 replies; 19+ messages in thread
From: Liu Yu-B13201 @ 2009-02-18 7:01 UTC (permalink / raw)
To: Blue Swirl, qemu-devel; +Cc: kvm-ppc, hollisb, aurelien
> -----Original Message-----
> From: Blue Swirl [mailto:blauwirbel@gmail.com]
> Sent: Tuesday, February 17, 2009 11:28 PM
> To: qemu-devel@nongnu.org
> Cc: aurelien@aurel32.net; hollisb@us.ibm.com; Liu Yu-B13201;
> kvm-ppc@vger.kernel.org
> Subject: Re: [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add
> MPC8544DS board support
>
> On 2/17/09, Liu Yu <yu.liu@freescale.com> wrote:
> > This patch add emulation of MPC8544DS board.
> > And it can work on All E500 platforms.
> >
> > Signed-off-by: Liu Yu <yu.liu@freescale.com>
>
> > + * Copyright (C) 2009 Freescale Semiconductor, Inc. All
> rights reserved.
>
> Again, "All rights reserved" is not what GPL says.
>
> > + 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;
> > + }
>
> For the Qemu case, the host CPU or system may be different from the
> emulated target CPU or system. These should be moved to
> target-ppc/kvm_ppc.c.
>
kvmppc_read_host_property() is already in target-ppc/kvm_ppc.c.
Move these to target-ppc/kvm_ppc.c then still need a interface to copy the cell value out.
And the these code is only called under the condition kvm_enabled().
> > + path = qemu_malloc(pathlen);
> > + if (path == NULL)
> > + goto out;
>
> qemu_malloc will not return NULL anymore, please remove the check.
>
Fixed.
> > + free(path);
>
> s/free/qemu_free/g
>
> > + sprintf(buf, "/cpus/%s", dirp->d_name);
>
> Please use snprintf.
>
Fixed.
> > + /* Register Memory */
> > + cpu_register_physical_memory(0, ram_size, 0);
>
> This was the old way. Please use qemu_ram_alloc instead.
>
Does it work for kvm case?
I failed when use qemu_ram_alloc.
^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform.
2009-02-17 14:55 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Blue Swirl
@ 2009-02-18 7:17 ` Liu Yu-B13201
2009-02-19 22:41 ` Aurelien Jarno
1 sibling, 0 replies; 19+ messages in thread
From: Liu Yu-B13201 @ 2009-02-18 7:17 UTC (permalink / raw)
To: Blue Swirl, qemu-devel; +Cc: kvm-ppc, hollisb, aurelien
> -----Original Message-----
> From: Blue Swirl [mailto:blauwirbel@gmail.com]
> Sent: Tuesday, February 17, 2009 10:56 PM
> To: qemu-devel@nongnu.org
> Cc: aurelien@aurel32.net; hollisb@us.ibm.com; Liu Yu-B13201;
> kvm-ppc@vger.kernel.org
> Subject: Re: [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable
> MPIC for E500 platform.
>
> On 2/17/09, Liu Yu <yu.liu@freescale.com> wrote:
> > MPIC and OpenPIC have very similar design.
> > So a lot of code can be reused.
> >
> > Modification mainly include:
> > 1. keep struct openpic_t to the maximum size of both MPIC
> and OpenPIC.
> > 2. endianess swap.
> > MPIC has the same endianess as target, so no need to
> swap for MPIC.
>
> I don't think this is correct, the host can still be different endian
> from target.
>
How does host endian involve?
Test a certain bit written by guest?
> > 3. using different init functions and function pointers
> for reset and irq raise.
>
> You didn't register the reset handler with qemu_register_reset.
>
Fixed.
> > Haven't test OpenPIC.
> >
> > Signed-off-by: Liu Yu <yu.liu@freescale.com>
>
> > +static void mpic_src_write (void *opaque, uint32_t addr,
> uint32_t val)
>
> > + if (addr < 0x180) {
> > + idx = MPIC_EXT_IRQ;
> > + } else if (addr >= 0x200 && addr < 0xa00) {
> > + idx = MPIC_INT_IRQ;
> > + addr -= 0x200;
> > + } else if (addr >= 0x1600 && addr < 0x1700) {
> > + idx = MPIC_MSG_IRQ;
> > + addr -= 0x1600;
> > + } else if (addr >= 0x1C00 && addr < 0x1D00) {
> > + idx = MPIC_MSI_IRQ;
> > + addr -= 0x1C00;
> > + } else {
> > + return;
>
> It would be faster and simpler to register different handlers for
> these memory areas, same goes for mpic_src_read, mpic_writel and
> mpic_readl.
>
Hmmm, will fix.
> > + register_savevm("mpic", 0, 1, openpic_save,
> openpic_load, mpp);
>
> When the save format changes, the version number should be bumped.
>
Fixed.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform.
2009-02-17 14:55 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Blue Swirl
2009-02-18 7:17 ` Liu Yu-B13201
@ 2009-02-19 22:41 ` Aurelien Jarno
2009-02-20 17:20 ` Blue Swirl
1 sibling, 1 reply; 19+ messages in thread
From: Aurelien Jarno @ 2009-02-19 22:41 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Liu Yu, hollisb, kvm-ppc
On Tue, Feb 17, 2009 at 04:55:51PM +0200, Blue Swirl wrote:
> On 2/17/09, Liu Yu <yu.liu@freescale.com> wrote:
> > MPIC and OpenPIC have very similar design.
> > So a lot of code can be reused.
> >
> > Modification mainly include:
> > 1. keep struct openpic_t to the maximum size of both MPIC and OpenPIC.
> > 2. endianess swap.
> > MPIC has the same endianess as target, so no need to swap for MPIC.
>
> I don't think this is correct, the host can still be different endian
> from target.
>
I do not agree. As long as we don't manipulate host memory, the host
endianess has nothing to do. The values are simply passed by value, they
don't need to be swapped.
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform.
2009-02-17 9:59 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Liu Yu
2009-02-17 14:55 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Blue Swirl
@ 2009-02-19 23:09 ` Paulev
2 siblings, 0 replies; 19+ messages in thread
From: Paulev @ 2009-02-19 23:09 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 27159 bytes --]
How do I remove myself from the QEMU list?
On Tue, Feb 17, 2009 at 3:59 AM, Liu Yu <yu.liu@freescale.com> wrote:
> MPIC and OpenPIC have very similar design.
> So a lot of code can be reused.
>
> Modification mainly include:
> 1. keep struct openpic_t to the maximum size of both MPIC and OpenPIC.
> 2. endianess swap.
> MPIC has the same endianess as target, so no need to swap for MPIC.
> 3. using different init functions and function pointers for reset and irq
> raise.
>
> Haven't test OpenPIC.
>
> Signed-off-by: Liu Yu <yu.liu@freescale.com>
> ---
> hw/openpic.c | 480
> +++++++++++++++++++++++++++++++++++++++++++++--------
> hw/ppc_mac.h | 13 --
> hw/ppc_newworld.c | 1 +
> 3 files changed, 412 insertions(+), 82 deletions(-)
>
> diff --git a/hw/openpic.c b/hw/openpic.c
> index 6dfb590..0f687e4 100644
> --- a/hw/openpic.c
> +++ b/hw/openpic.c
> @@ -35,6 +35,7 @@
> #include "hw.h"
> #include "ppc_mac.h"
> #include "pci.h"
> +#include "openpic.h"
>
> //#define DEBUG_OPENPIC
>
> @@ -60,14 +61,10 @@
>
> #define VID (0x00000000)
>
> -#define OPENPIC_LITTLE_ENDIAN 1
> -#define OPENPIC_BIG_ENDIAN 0
> -
> #elif defined(USE_MPCxxx)
>
> #define MAX_CPU 2
> -#define MAX_IRQ 64
> -#define EXT_IRQ 48
> +#define MAX_IRQ 128
> #define MAX_DBL 0
> #define MAX_MBX 0
> #define MAX_TMR 4
> @@ -81,28 +78,55 @@ enum {
> IRQ_IDE,
> };
>
> -#define OPENPIC_LITTLE_ENDIAN 1
> -#define OPENPIC_BIG_ENDIAN 0
> +/* OpenPIC */
> +#define OPENPIC_MAX_CPU 2
> +#define OPENPIC_MAX_IRQ 64
> +#define OPENPIC_EXT_IRQ 48
> +#define OPENPIC_MAX_TMR MAX_TMR
> +#define OPENPIC_MAX_IPI MAX_IPI
>
> +/* Interrupt definitions */
> +#define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional
> IRQ */
> +#define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
> +#define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
> +#if OPENPIC_MAX_IPI > 0
> +#define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First
> IPI IRQ */
> +#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU *
> OPENPIC_MAX_IPI)) /* First doorbell IRQ */
> #else
> -#error "Please select which OpenPic implementation is to be emulated"
> +#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First
> doorbell IRQ */
> +#define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First
> mailbox IRQ */
> #endif
>
> -#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
> - (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN)
> -#define OPENPIC_SWAP
> -#endif
> +/* MPIC */
> +#define MPIC_MAX_CPU 1
> +#define MPIC_MAX_EXT 12
> +#define MPIC_MAX_INT 64
> +#define MPIC_MAX_MSG 4
> +#define MPIC_MAX_MSI 8
> +#define MPIC_MAX_TMR MAX_TMR
> +#define MPIC_MAX_IPI MAX_IPI
> +#define MPIC_MAX_IRQ (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR +
> MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU))
>
> /* Interrupt definitions */
> -#define IRQ_FE (EXT_IRQ) /* Internal functional IRQ */
> -#define IRQ_ERR (EXT_IRQ + 1) /* Error IRQ */
> -#define IRQ_TIM0 (EXT_IRQ + 2) /* First timer IRQ */
> -#if MAX_IPI > 0
> -#define IRQ_IPI0 (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */
> -#define IRQ_DBL0 (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell IRQ
> */
> +#define MPIC_EXT_IRQ 0
> +#define MPIC_INT_IRQ (MPIC_EXT_IRQ + MPIC_MAX_EXT)
> +#define MPIC_TMR_IRQ (MPIC_INT_IRQ + MPIC_MAX_INT)
> +#define MPIC_MSG_IRQ (MPIC_TMR_IRQ + MPIC_MAX_TMR)
> +#define MPIC_MSI_IRQ (MPIC_MSG_IRQ + MPIC_MAX_MSG)
> +#define MPIC_IPI_IRQ (MPIC_MSI_IRQ + MPIC_MAX_MSI)
> +
> +#define MPIC_MAP_SIZE 0x40000
> +
> +enum mpic_ide_bits {
> + IDR_EP = 0,
> + IDR_CI0 = 1,
> + IDR_CI1 = 2,
> + IDR_P1 = 30,
> + IDR_P0 = 31,
> +};
> +
> #else
> -#define IRQ_DBL0 (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */
> -#define IRQ_MBX0 (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */
> +#error "Please select which OpenPic implementation is to be emulated"
> #endif
>
> #define BF_WIDTH(_bits_) \
> @@ -157,6 +181,7 @@ enum IPVP_bits {
> #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
>
> typedef struct IRQ_dst_t {
> + uint32_t tfrr;
> uint32_t pctp; /* CPU current task priority */
> uint32_t pcsr; /* CPU sensitivity register */
> IRQ_queue_t raised;
> @@ -200,8 +225,22 @@ typedef struct openpic_t {
> #endif
> /* IRQ out is used when in bypass mode (not implemented) */
> qemu_irq irq_out;
> + int max_irq;
> + int irq_ipi0;
> + int irq_tim0;
> + int need_swap;
> + void (*reset) (void *);
> + void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
> } openpic_t;
>
> +static inline uint32_t openpic_swap32(openpic_t *opp, uint32_t val)
> +{
> + if (opp->need_swap)
> + return bswap32(val);
> +
> + return val;
> +}
> +
> static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
> {
> set_bit(q->queue, n_IRQ);
> @@ -224,7 +263,7 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
>
> next = -1;
> priority = -1;
> - for (i = 0; i < MAX_IRQ; i++) {
> + for (i = 0; i < opp->max_irq; i++) {
> if (IRQ_testbit(q, i)) {
> DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
> i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
> @@ -286,7 +325,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU,
> int n_IRQ)
> return;
> }
> DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
> - qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
> + opp->irq_raise(opp, n_CPU, src);
> }
>
> /* update pic state because registers for n_IRQ have changed value */
> @@ -374,7 +413,7 @@ static void openpic_reset (void *opaque)
>
> opp->glbc = 0x80000000;
> /* Initialise controller registers */
> - opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
> + opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) |
> VID;
> opp->veni = VENI;
> opp->pint = 0x00000000;
> opp->spve = 0x000000FF;
> @@ -382,7 +421,7 @@ static void openpic_reset (void *opaque)
> /* ? */
> opp->micr = 0x00000000;
> /* Initialise IRQ sources */
> - for (i = 0; i < MAX_IRQ; i++) {
> + for (i = 0; i < opp->max_irq; i++) {
> opp->src[i].ipvp = 0xA0000000;
> opp->src[i].ide = 0x00000000;
> }
> @@ -544,16 +583,16 @@ static void openpic_gbl_write (void *opaque, uint32_t
> addr, uint32_t val)
> DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
> if (addr & 0xF)
> return;
> -#if defined OPENPIC_SWAP
> - val = bswap32(val);
> +#if defined TARGET_WORDS_BIGENDIAN
> + val = openpic_swap32(opp, val);
> #endif
> addr &= 0xFF;
> switch (addr) {
> case 0x00: /* FREP */
> break;
> case 0x20: /* GLBC */
> - if (val & 0x80000000)
> - openpic_reset(opp);
> + if (val & 0x80000000 && opp->reset)
> + opp->reset(opp);
> opp->glbc = val & ~0x80000000;
> break;
> case 0x80: /* VENI */
> @@ -580,7 +619,7 @@ static void openpic_gbl_write (void *opaque, uint32_t
> addr, uint32_t val)
> {
> int idx;
> idx = (addr - 0xA0) >> 4;
> - write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);
> + write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val);
> }
> break;
> #endif
> @@ -626,7 +665,7 @@ static uint32_t openpic_gbl_read (void *opaque,
> uint32_t addr)
> {
> int idx;
> idx = (addr - 0xA0) >> 4;
> - retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);
> + retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP);
> }
> break;
> #endif
> @@ -640,8 +679,8 @@ static uint32_t openpic_gbl_read (void *opaque,
> uint32_t addr)
> break;
> }
> DPRINTF("%s: => %08x\n", __func__, retval);
> -#if defined OPENPIC_SWAP
> - retval = bswap32(retval);
> +#if defined TARGET_WORDS_BIGENDIAN
> + retval = openpic_swap32(opp, retval);
> #endif
>
> return retval;
> @@ -655,8 +694,8 @@ static void openpic_timer_write (void *opaque, uint32_t
> addr, uint32_t val)
> DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
> if (addr & 0xF)
> return;
> -#if defined OPENPIC_SWAP
> - val = bswap32(val);
> +#if defined TARGET_WORDS_BIGENDIAN
> + val = openpic_swap32(opp, val);
> #endif
> addr -= 0x1100;
> addr &= 0xFFFF;
> @@ -673,10 +712,10 @@ static void openpic_timer_write (void *opaque,
> uint32_t addr, uint32_t val)
> opp->timers[idx].tibc = val;
> break;
> case 0x20: /* TIVP */
> - write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);
> + write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP, val);
> break;
> case 0x30: /* TIDE */
> - write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
> + write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE, val);
> break;
> }
> }
> @@ -703,15 +742,15 @@ static uint32_t openpic_timer_read (void *opaque,
> uint32_t addr)
> retval = opp->timers[idx].tibc;
> break;
> case 0x20: /* TIPV */
> - retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);
> + retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP);
> break;
> case 0x30: /* TIDE */
> - retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);
> + retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE);
> break;
> }
> DPRINTF("%s: => %08x\n", __func__, retval);
> -#if defined OPENPIC_SWAP
> - retval = bswap32(retval);
> +#if defined TARGET_WORDS_BIGENDIAN
> + retval = openpic_swap32(opp, retval);
> #endif
>
> return retval;
> @@ -725,8 +764,8 @@ static void openpic_src_write (void *opaque, uint32_t
> addr, uint32_t val)
> DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
> if (addr & 0xF)
> return;
> -#if defined OPENPIC_SWAP
> - val = tswap32(val);
> +#if defined TARGET_WORDS_BIGENDIAN
> + val = openpic_swap32(opp, val);
> #endif
> addr = addr & 0xFFF0;
> idx = addr >> 5;
> @@ -759,8 +798,8 @@ static uint32_t openpic_src_read (void *opaque,
> uint32_t addr)
> retval = read_IRQreg(opp, idx, IRQ_IPVP);
> }
> DPRINTF("%s: => %08x\n", __func__, retval);
> -#if defined OPENPIC_SWAP
> - retval = tswap32(retval);
> +#if defined TARGET_WORDS_BIGENDIAN
> + retval = openpic_swap32(opp, retval);
> #endif
>
> return retval;
> @@ -776,8 +815,8 @@ static void openpic_cpu_write (void *opaque, uint32_t
> addr, uint32_t val)
> DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
> if (addr & 0xF)
> return;
> -#if defined OPENPIC_SWAP
> - val = bswap32(val);
> +#if defined TARGET_WORDS_BIGENDIAN
> + val = openpic_swap32(opp, val);
> #endif
> addr &= 0x1FFF0;
> idx = addr / 0x1000;
> @@ -790,9 +829,9 @@ static void openpic_cpu_write (void *opaque, uint32_t
> addr, uint32_t val)
> case 0x60:
> case 0x70:
> idx = (addr - 0x40) >> 4;
> - write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
> - openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
> - openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
> + write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
> + openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
> + openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
> break;
> #endif
> case 0x80: /* PCTP */
> @@ -819,7 +858,7 @@ static void openpic_cpu_write (void *opaque, uint32_t
> addr, uint32_t val)
> IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
> DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
> idx, n_IRQ);
> - qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
> + opp->irq_raise(opp, idx, src);
> }
> break;
> default:
> @@ -889,15 +928,15 @@ static uint32_t openpic_cpu_read (void *opaque,
> uint32_t addr)
> case 0x40: /* IDE */
> case 0x50:
> idx = (addr - 0x40) >> 4;
> - retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);
> + retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE);
> break;
> #endif
> default:
> break;
> }
> DPRINTF("%s: => %08x\n", __func__, retval);
> -#if defined OPENPIC_SWAP
> - retval= bswap32(retval);
> +#if defined TARGET_WORDS_BIGENDIAN
> + retval = openpic_swap32(opp, retval);
> #endif
>
> return retval;
> @@ -989,7 +1028,7 @@ static void openpic_map(PCIDevice *pci_dev, int
> region_num,
> addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
> /* Interrupt source registers */
> DPRINTF("Register OPENPIC src %08x => %08x\n",
> - addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));
> + addr + 0x10000, addr + 0x10000 + 0x20 * (OPENPIC_EXT_IRQ +
> 2));
> /* Per CPU registers */
> DPRINTF("Register OPENPIC dst %08x => %08x\n",
> addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
> @@ -1026,7 +1065,7 @@ static void openpic_save(QEMUFile* f, void *opaque)
> qemu_put_be32s(f, &opp->spve);
> qemu_put_be32s(f, &opp->tifr);
>
> - for (i = 0; i < MAX_IRQ; i++) {
> + for (i = 0; i < opp->max_irq; i++) {
> qemu_put_be32s(f, &opp->src[i].ipvp);
> qemu_put_be32s(f, &opp->src[i].ide);
> qemu_put_sbe32s(f, &opp->src[i].type);
> @@ -1034,15 +1073,16 @@ static void openpic_save(QEMUFile* f, void *opaque)
> qemu_put_sbe32s(f, &opp->src[i].pending);
> }
>
> - for (i = 0; i < MAX_IRQ; i++) {
> + qemu_put_sbe32s(f, &opp->nb_cpus);
> +
> + for (i = 0; i < opp->nb_cpus; i++) {
> + qemu_put_be32s(f, &opp->dst[i].tfrr);
> qemu_put_be32s(f, &opp->dst[i].pctp);
> qemu_put_be32s(f, &opp->dst[i].pcsr);
> openpic_save_IRQ_queue(f, &opp->dst[i].raised);
> openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
> }
>
> - qemu_put_sbe32s(f, &opp->nb_cpus);
> -
> for (i = 0; i < MAX_TMR; i++) {
> qemu_put_be32s(f, &opp->timers[i].ticc);
> qemu_put_be32s(f, &opp->timers[i].tibc);
> @@ -1092,7 +1132,7 @@ static int openpic_load(QEMUFile* f, void *opaque,
> int version_id)
> qemu_get_be32s(f, &opp->spve);
> qemu_get_be32s(f, &opp->tifr);
>
> - for (i = 0; i < MAX_IRQ; i++) {
> + for (i = 0; i < opp->max_irq; i++) {
> qemu_get_be32s(f, &opp->src[i].ipvp);
> qemu_get_be32s(f, &opp->src[i].ide);
> qemu_get_sbe32s(f, &opp->src[i].type);
> @@ -1100,15 +1140,16 @@ static int openpic_load(QEMUFile* f, void *opaque,
> int version_id)
> qemu_get_sbe32s(f, &opp->src[i].pending);
> }
>
> - for (i = 0; i < MAX_IRQ; i++) {
> + qemu_get_sbe32s(f, &opp->nb_cpus);
> +
> + for (i = 0; i < opp->nb_cpus; i++) {
> + qemu_get_be32s(f, &opp->dst[i].tfrr);
> qemu_get_be32s(f, &opp->dst[i].pctp);
> qemu_get_be32s(f, &opp->dst[i].pcsr);
> openpic_load_IRQ_queue(f, &opp->dst[i].raised);
> openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
> }
>
> - qemu_get_sbe32s(f, &opp->nb_cpus);
> -
> for (i = 0; i < MAX_TMR; i++) {
> qemu_get_be32s(f, &opp->timers[i].ticc);
> qemu_get_be32s(f, &opp->timers[i].tibc);
> @@ -1131,6 +1172,11 @@ static int openpic_load(QEMUFile* f, void *opaque,
> int version_id)
> return pci_device_load(&opp->pci_dev, f);
> }
>
> +static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
> +{
> + qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
> +}
> +
> qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
> qemu_irq **irqs, qemu_irq irq_out)
> {
> @@ -1164,33 +1210,329 @@ qemu_irq *openpic_init (PCIBus *bus, int
> *pmem_index, int nb_cpus,
>
> // isu_base &= 0xFFFC0000;
> opp->nb_cpus = nb_cpus;
> + opp->max_irq = OPENPIC_MAX_IRQ;
> + opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
> + opp->irq_tim0 = OPENPIC_IRQ_TIM0;
> /* Set IRQ types */
> - for (i = 0; i < EXT_IRQ; i++) {
> + for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
> opp->src[i].type = IRQ_EXTERNAL;
> }
> - for (; i < IRQ_TIM0; i++) {
> + for (; i < OPENPIC_IRQ_TIM0; i++) {
> opp->src[i].type = IRQ_SPECIAL;
> }
> #if MAX_IPI > 0
> - m = IRQ_IPI0;
> + m = OPENPIC_IRQ_IPI0;
> #else
> - m = IRQ_DBL0;
> + m = OPENPIC_IRQ_DBL0;
> #endif
> for (; i < m; i++) {
> opp->src[i].type = IRQ_TIMER;
> }
> - for (; i < MAX_IRQ; i++) {
> + for (; i < OPENPIC_MAX_IRQ; i++) {
> opp->src[i].type = IRQ_INTERNAL;
> }
> for (i = 0; i < nb_cpus; i++)
> opp->dst[i].irqs = irqs[i];
> opp->irq_out = irq_out;
> + opp->need_swap = 1;
>
> register_savevm("openpic", 0, 1, openpic_save, openpic_load, opp);
> qemu_register_reset(openpic_reset, opp);
> - openpic_reset(opp);
> +
> + opp->irq_raise = openpic_irq_raise;
> + opp->reset = openpic_reset;
> +
> + opp->reset(opp);
> if (pmem_index)
> *pmem_index = opp->mem_index;
>
> - return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
> + return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
> +}
> +
> +static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
> +{
> + int n_ci = IDR_CI0 - n_CPU;
> + DPRINTF("%s: cpu:%d irq:%d (testbit idr:%x ci:%d)\n", __func__,
> + n_CPU, n_IRQ, mpp->src[n_IRQ].ide, n_ci);
> + if(test_bit(&src->ide, n_ci)) {
> + qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
> + }
> + else {
> + qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
> + }
> +}
> +
> +static void mpic_reset (void *opaque)
> +{
> + openpic_t *mpp = (openpic_t *)opaque;
> + int i;
> +
> + mpp->glbc = 0x80000000;
> + /* Initialise controller registers */
> + mpp->frep = 0x004f0002;
> + mpp->veni = VENI;
> + mpp->pint = 0x00000000;
> + mpp->spve = 0x0000FFFF;
> + /* Initialise IRQ sources */
> + for (i = 0; i < mpp->max_irq; i++) {
> + mpp->src[i].ipvp = 0x80800000;
> + mpp->src[i].ide = 0x00000001;
> + }
> + /* Initialise IRQ destinations */
> + for (i = 0; i < MAX_CPU; i++) {
> + mpp->dst[i].pctp = 0x0000000F;
> + mpp->dst[i].tfrr = 0x00000000;
> + memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
> + mpp->dst[i].raised.next = -1;
> + memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
> + mpp->dst[i].servicing.next = -1;
> + }
> + /* Initialise timers */
> + for (i = 0; i < MAX_TMR; i++) {
> + mpp->timers[i].ticc = 0x00000000;
> + mpp->timers[i].tibc = 0x80000000;
> + }
> + /* Go out of RESET state */
> + mpp->glbc = 0x00000000;
> +}
> +
> +static void mpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
> +{
> + openpic_t *mpp = opaque;
> + int idx, cpu;
> +
> + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
> + if (addr & 0xF)
> + return;
> + addr &= 0xFFFF;
> + cpu = addr >> 12;
> + idx = (addr >> 6) & 0x3;
> + switch (addr & 0x30) {
> + case 0x00: /* gtccr */
> + break;
> + case 0x10: /* gtbcr */
> + if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
> + (val & 0x80000000) == 0 &&
> + (mpp->timers[idx].tibc & 0x80000000) != 0)
> + mpp->timers[idx].ticc &= ~0x80000000;
> + mpp->timers[idx].tibc = val;
> + break;
> + case 0x20: /* GTIVPR */
> + write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP, val);
> + break;
> + case 0x30: /* GTIDR & TFRR */
> + if ((addr & 0xF0) == 0xF0)
> + mpp->dst[cpu].tfrr = val;
> + else
> + write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE, val);
> + break;
> + }
> +}
> +
> +static uint32_t mpic_timer_read (void *opaque, uint32_t addr)
> +{
> + openpic_t *mpp = opaque;
> + uint32_t retval;
> + int idx, cpu;
> +
> + DPRINTF("%s: addr %08x\n", __func__, addr);
> + retval = 0xFFFFFFFF;
> + if (addr & 0xF)
> + return retval;
> + addr &= 0xFFFF;
> + cpu = addr >> 12;
> + idx = (addr >> 6) & 0x3;
> + switch (addr & 0x30) {
> + case 0x00: /* gtccr */
> + retval = mpp->timers[idx].ticc;
> + break;
> + case 0x10: /* gtbcr */
> + retval = mpp->timers[idx].tibc;
> + break;
> + case 0x20: /* TIPV */
> + retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP);
> + break;
> + case 0x30: /* TIDR */
> + if ((addr &0xF0) == 0XF0)
> + retval = mpp->dst[cpu].tfrr;
> + else
> + retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE);
> + break;
> + }
> + DPRINTF("%s: => %08x\n", __func__, retval);
> +
> + return retval;
> +}
> +
> +static void mpic_src_write (void *opaque, uint32_t addr, uint32_t val)
> +{
> + openpic_t *mpp = opaque;
> + int idx;
> +
> + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
> + if (addr & 0xF)
> + return;
> + addr = addr & 0xFFF0;
> + if (addr < 0x180) {
> + idx = MPIC_EXT_IRQ;
> + } else if (addr >= 0x200 && addr < 0xa00) {
> + idx = MPIC_INT_IRQ;
> + addr -= 0x200;
> + } else if (addr >= 0x1600 && addr < 0x1700) {
> + idx = MPIC_MSG_IRQ;
> + addr -= 0x1600;
> + } else if (addr >= 0x1C00 && addr < 0x1D00) {
> + idx = MPIC_MSI_IRQ;
> + addr -= 0x1C00;
> + } else {
> + return;
> + }
> + idx += addr >> 5;
> + if (addr & 0x10) {
> + /* EXDE / IFEDE / IEEDE */
> + write_IRQreg(mpp, idx, IRQ_IDE, val);
> + } else {
> + /* EXVP / IFEVP / IEEVP */
> + write_IRQreg(mpp, idx, IRQ_IPVP, val);
> + }
> +}
> +
> +static uint32_t mpic_src_read (void *opaque, uint32_t addr)
> +{
> + openpic_t *mpp = opaque;
> + uint32_t retval;
> + int idx;
> +
> + DPRINTF("%s: addr %08x\n", __func__, addr);
> + retval = 0xFFFFFFFF;
> + if (addr & 0xF)
> + return retval;
> + addr = addr & 0xFFF0;
> + if (addr < 0x180) {
> + idx = MPIC_EXT_IRQ;
> + } else if (addr >= 0x200 && addr < 0xa00) {
> + idx = MPIC_INT_IRQ;
> + addr -= 0x200;
> + } else if (addr >= 0x1600 && addr < 0x1700) {
> + idx = MPIC_MSG_IRQ;
> + addr -= 0x1600;
> + } else if (addr >= 0x1C00 && addr < 0x1D00) {
> + idx = MPIC_MSI_IRQ;
> + addr -= 0x1C00;
> + } else {
> + return retval;
> + }
> + idx += addr >> 5;
> + if (addr & 0x10) {
> + /* EXDE / IFEDE / IEEDE */
> + retval = read_IRQreg(mpp, idx, IRQ_IDE);
> + } else {
> + /* EXVP / IFEVP / IEEVP */
> + retval = read_IRQreg(mpp, idx, IRQ_IPVP);
> + }
> + DPRINTF("%s: => %08x\n", __func__, retval);
> +
> + return retval;
> +}
> +
> +static void mpic_writel (void *opaque,
> + target_phys_addr_t addr, uint32_t val)
> +{
> + openpic_t *mpp = opaque;
> +
> + addr &= 0x3FFFF;
> + DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
> + if (addr < 0x10F0) {
> + /* Global registers */
> + openpic_gbl_write(mpp, addr, val);
> + } else if (addr < 0x10000) {
> + /* Timers registers */
> + mpic_timer_write(mpp, addr, val);
> + } else if (addr < 0x20000) {
> + /* Source registers */
> + mpic_src_write(mpp, addr, val);
> + } else if (addr < 0x30000){
> + /* CPU registers */
> + openpic_cpu_write(mpp, addr, val);
> + } else {
> + DPRINTF("wrong mpic write addr %p\n",addr);
> + }
> +}
> +
> +static uint32_t mpic_readl (void *opaque,target_phys_addr_t addr)
> +{
> + openpic_t *mpp = opaque;
> + uint32_t retval = 0;
> +
> + addr &= 0x3FFFF;
> + DPRINTF("%s: offset %08x\n", __func__, (int)addr);
> + if (addr < 0x10F0) {
> + /* Global registers */
> + retval = openpic_gbl_read(mpp, addr);
> + } else if (addr < 0x10000) {
> + /* Timers registers */
> + retval = mpic_timer_read(mpp, addr);
> + } else if (addr < 0x20000) {
> + /* Source registers */
> + retval = mpic_src_read(mpp, addr);
> + } else if (addr < 0x30000){
> + /* CPU registers */
> + retval = openpic_cpu_read(mpp, addr);
> + } else {
> + DPRINTF("wrong mpic read addr %p\n",addr);
> + }
> +
> + return retval;
> +}
> +
> +static CPUWriteMemoryFunc *mpic_write[] = {
> + &openpic_buggy_write,
> + &openpic_buggy_write,
> + &mpic_writel,
> +};
> +
> +static CPUReadMemoryFunc *mpic_read[] = {
> + &openpic_buggy_read,
> + &openpic_buggy_read,
> + &mpic_readl,
> +};
> +
> +qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
> + qemu_irq **irqs, qemu_irq irq_out)
> +{
> + openpic_t *mpp;
> + int i;
> +
> + /* XXX: for now, only one CPU is supported */
> + if (nb_cpus != 1)
> + return NULL;
> +
> + mpp = qemu_mallocz(sizeof(openpic_t));
> +
> + mpp->mem_index = cpu_register_io_memory(0, mpic_read, mpic_write,
> mpp);
> + if (mpp->mem_index < 0)
> + goto free;
> + cpu_register_physical_memory(base, MPIC_MAP_SIZE, mpp->mem_index);
> +
> + mpp->nb_cpus = nb_cpus;
> + mpp->max_irq = MPIC_MAX_IRQ;
> + mpp->irq_ipi0 = MPIC_IPI_IRQ;
> + mpp->irq_tim0 = MPIC_TMR_IRQ;
> +
> + for (i = 0; i < nb_cpus; i++)
> + mpp->dst[i].irqs = irqs[i];
> + mpp->irq_out = irq_out;
> + mpp->need_swap = 0; /* MPIC has the same endian as target */
> +
> + mpp->irq_raise = mpic_irq_raise;
> + mpp->reset = mpic_reset;
> +
> + register_savevm("mpic", 0, 1, openpic_save, openpic_load, mpp);
> + mpp->reset(mpp);
> +
> + return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
> +
> +free:
> + qemu_free(mpp);
> + return NULL;
> }
> diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
> index 5851a5e..df148b2 100644
> --- a/hw/ppc_mac.h
> +++ b/hw/ppc_mac.h
> @@ -112,17 +112,4 @@ void adb_mouse_init(ADBBusState *bus);
>
> extern ADBBusState adb_bus;
>
> -/* openpic.c */
> -/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output
> */
> -enum {
> - OPENPIC_OUTPUT_INT = 0, /* IRQ */
> - OPENPIC_OUTPUT_CINT, /* critical IRQ */
> - OPENPIC_OUTPUT_MCK, /* Machine check event */
> - OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */
> - OPENPIC_OUTPUT_RESET, /* Core reset event */
> - OPENPIC_OUTPUT_NB,
> -};
> -qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
> - qemu_irq **irqs, qemu_irq irq_out);
> -
> #endif /* !defined(__PPC_MAC_H__) */
> diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
> index 6f60e49..b285864 100644
> --- a/hw/ppc_newworld.c
> +++ b/hw/ppc_newworld.c
> @@ -34,6 +34,7 @@
> #include "boards.h"
> #include "fw_cfg.h"
> #include "escc.h"
> +#include "openpic.h"
>
> #define MAX_IDE_BUS 2
> #define VGA_BIOS_SIZE 65536
> --
> 1.5.4
>
>
>
>
[-- Attachment #2: Type: text/html, Size: 40006 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform.
2009-02-19 22:41 ` Aurelien Jarno
@ 2009-02-20 17:20 ` Blue Swirl
0 siblings, 0 replies; 19+ messages in thread
From: Blue Swirl @ 2009-02-20 17:20 UTC (permalink / raw)
To: Aurelien Jarno; +Cc: hollisb, Liu Yu, qemu-devel, kvm-ppc
On 2/20/09, Aurelien Jarno <aurelien@aurel32.net> wrote:
> On Tue, Feb 17, 2009 at 04:55:51PM +0200, Blue Swirl wrote:
> > On 2/17/09, Liu Yu <yu.liu@freescale.com> wrote:
> > > MPIC and OpenPIC have very similar design.
> > > So a lot of code can be reused.
> > >
> > > Modification mainly include:
> > > 1. keep struct openpic_t to the maximum size of both MPIC and OpenPIC.
> > > 2. endianess swap.
> > > MPIC has the same endianess as target, so no need to swap for MPIC.
> >
> > I don't think this is correct, the host can still be different endian
> > from target.
> >
>
>
> I do not agree. As long as we don't manipulate host memory, the host
> endianess has nothing to do. The values are simply passed by value, they
> don't need to be swapped.
Sorry, I stand corrected.
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH 5/5] kvm/powerpc: flat device tree files for MPC8544DS
2009-02-26 10:35 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Liu Yu
@ 2009-02-26 10:35 ` Liu Yu
0 siblings, 0 replies; 19+ messages in thread
From: Liu Yu @ 2009-02-26 10:35 UTC (permalink / raw)
To: qemu-devel, aurelien, hollisb, blauwirbel; +Cc: Liu Yu, kvm-ppc
mpc8544ds.dts is copied from kerenl.
Non-supported devices has been removed.
Signed-off-by: Liu Yu <yu.liu@freescale.com>
---
pc-bios/mpc8544ds.dtb | Bin 0 -> 12288 bytes
pc-bios/mpc8544ds.dts | 122 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 122 insertions(+), 0 deletions(-)
create mode 100644 pc-bios/mpc8544ds.dtb
create mode 100644 pc-bios/mpc8544ds.dts
diff --git a/pc-bios/mpc8544ds.dtb b/pc-bios/mpc8544ds.dtb
new file mode 100644
index 0000000000000000000000000000000000000000..3299546696bf21f53f8ce2c9eba7fcb740c547da
GIT binary patch
literal 12288
zcmeHIJ8u&~5Z)um5MBxr1r@SLgOE>gBs)q$VJkovDTp5sUCx{MlzVY^28Sx5qJ!T+
zNtKd<A{{NFM>0PEYG{D@_IA$pB`MM&G$W079^cH)ez$l2eEs)#rP_+*gHo3YTJMqG
zBwZpUakiCed@SvM>esQ;EYNxd_U6{cdbiVg__RzQev7m*jT>t`E)mFIB*j_Li~Xkc
z9WM;LT<7GP+#On5D|zB$lb&vuvXbj8@WNiF+cqptv7NKAYqQuJ)c3(k>IbIhI<>`)
zN?jmz{B&dnAe-kqZC>D=t>lHywl-R3zOo6|^r;Up>~F#$VgCu)%^BaX`BZ#Jp$h-1
z=D$Ibg!{cK-O4|*KF(y$73nC+4onm^mq`1y*ky|GoB*1-I{iqH@V=*UGy81&RL}UU
zWHj<1N<;1LSeDV}8tE~qn&4*%Kc>H#XJT9v<URSUPVFXe{*x&wdzf>UI1>d1eH(GU
zy4LNQhsH5F`y)!3YtFrxN5*_1z<pA1!<etOsN~DuPJ81RgPE9@bI$bGmR9?nd!{t-
zdmX$z)QJQ$L4J_(e0Yu!>pNKajOD$+n+q*5c!wJPFiTrWs$-XSFey{NNM?UNT=m8G
z0X(3$;p^mU$XGS|9G3{+*v-RMl;U&HcBzg+6}CU)6V|z_)KBDDz&Xw|p<Gv~*Br-+
zd3YvT=W=F7%A>ZPvoXU;JqM=H)9PC?E8)1UpUd%nwtg<h`&rCfuC`yr3*SxD;yL2}
z-X=v48*?_uhWsH#tWA0h0OZ&z>?SFOXZglP8AL7SI9mACdrzzN&0PY5^G&jOf8cTV
zkb|1LHc^LUE|D6X;}4Tu$8ZgX{ui9hv%mG#{{r@aE=I{fhssZ))GLCWP^)EcFvxVC
zyS@&?TrKCpOKt7)ThUhKx~k}2wbejB4}85{9Hd%hdQS~p-}8ss4TD&_C|1FV2xI2b
z#wmhG@6aEeyPN4}BOUt(iav)ko*yRu{*0e_@gDsxVpunb2YRf6xX@WPN{f7Ix~Z4x
zxR?p}NnB(}80t(dR~7c0H2P@VN{3!NAVQ|u$V=VG%lGF)W<WEBDhu;skc<l2vKZpA
zhzJA1fG{8o2m``^Fdz&F1HynXAPfit!hkR!3<v|lfG{8o2m``^Fdz&F1HynXAPfit
W!hkR!3<v|lfG{8o2m}8&1AhU`J`#BV
literal 0
HcmV?d00001
diff --git a/pc-bios/mpc8544ds.dts b/pc-bios/mpc8544ds.dts
new file mode 100644
index 0000000..872152d
--- /dev/null
+++ b/pc-bios/mpc8544ds.dts
@@ -0,0 +1,122 @@
+/*
+ * MPC8544 DS Device Tree Source
+ *
+ * Copyright 2007, 2008 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 = "MPC8544DS";
+ compatible = "MPC8544DS", "MPC85xxDS";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ pci0 = &pci0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8544@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>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x0>; // Filled by U-Boot
+ };
+
+ soc8544@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.
+
+ 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>;
+ };
+
+ mpic: pic@40000 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ };
+ };
+
+ 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>;
+ };
+
+ chosen {
+ linux,stdout-path = "/soc8544@e0000000/serial@4500";
+ };
+};
--
1.5.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
end of thread, other threads:[~2009-02-26 10:48 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-17 9:59 [Qemu-devel] powerpc/kvm: Add MPC8544DS board support Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 3/5] kvm/powerpc: Add irq support for E500 core Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Liu Yu
2009-02-17 9:59 ` [Qemu-devel] [PATCH 5/5] kvm/powerpc: flat device tree files for MPC8544DS Liu Yu
2009-02-17 15:28 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Blue Swirl
2009-02-18 7:01 ` Liu Yu-B13201
2009-02-17 15:09 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Blue Swirl
2009-02-17 16:08 ` M. Warner Losh
2009-02-17 16:23 ` M. Warner Losh
2009-02-17 17:41 ` Jamie Lokier
2009-02-18 6:04 ` Liu Yu-B13201
2009-02-17 14:55 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Blue Swirl
2009-02-18 7:17 ` Liu Yu-B13201
2009-02-19 22:41 ` Aurelien Jarno
2009-02-20 17:20 ` Blue Swirl
2009-02-19 23:09 ` Paulev
-- strict thread matches above, loose matches on Subject: below --
2009-02-26 10:35 [Qemu-devel] [PATCH v4 0/5] powerpc/kvm: Add MPC8544DS board support Liu Yu
2009-02-26 10:35 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Liu Yu
2009-02-26 10:35 ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Liu Yu
2009-02-26 10:35 ` [Qemu-devel] [PATCH 3/5] kvm/powerpc: Add irq support for E500 core Liu Yu
2009-02-26 10:35 ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Liu Yu
2009-02-26 10:35 ` [Qemu-devel] [PATCH 5/5] kvm/powerpc: flat device tree files for MPC8544DS Liu Yu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).