All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Chubb <peterc@gelato.unsw.edu.au>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: Peter Chubb <peter.chubb@nicta.com.au>, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] imx.31 and KZM board support
Date: Tue, 22 Nov 2011 08:58:26 +1100	[thread overview]
Message-ID: <w4lir9m931.wl%peter@chubb.wattle.id.au> (raw)
In-Reply-To: <CAFEAcA8-iByH0xgjkMUo3hvkrLc8NV-Lq4GbHU-d7UoF8GSX-Q@mail.gmail.com>

Hi Peter,
   Please find appended a patch containing initial support for the
   FreeScale i.MX31 and the KZM Arm11 evaluation board.

   The implementation was originally written by Hans Jang and Adam
   Clench of OK-Labs; I've updated it to the current qdev and memory
   region paradigms and implemented enough extra that Linux will boot
   on the patched QEMU using a ram disk.

   The i.MX 31 Serial controller is found in most of the i.MX SoCs;
   the AVIC and timer implementations can also be shared, albeit with
   fewer chips.

Signed-off-by: Peter Chubb <peter.chubb@nicta.com.au>
Signed-off-by: Hans Jang <hsjang@ok-labs.com>
Signed-off-by: Adam Clench <adamc@ok-labs.com>
---
 Makefile.target |    1 
 hw/imx_avic.c   |  294 ++++++++++++++++++++++++++++++++++++++
 hw/imx_serial.c |  260 +++++++++++++++++++++++++++++++++
 hw/imx_timer.c  |  430 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/kzm.c        |  159 ++++++++++++++++++++
 5 files changed, 1144 insertions(+)
 create mode 100644 hw/imx_avic.c
 create mode 100644 hw/imx_serial.c
 create mode 100644 hw/imx_timer.c
 create mode 100644 hw/kzm.c

Index: qemu-working/Makefile.target
===================================================================
--- qemu-working.orig/Makefile.target	2011-11-22 08:40:56.380128155 +1100
+++ qemu-working/Makefile.target	2011-11-22 08:42:26.288661513 +1100
@@ -336,20 +336,21 @@ obj-sparc-y = sun4m.o lance.o tcx.o sun4
 obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o
 obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
 
 # GRLIB
 obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
 endif
 
 obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
 obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
 obj-arm-y += versatile_pci.o
+obj-arm-y += kzm.o imx_avic.o imx_serial.o imx_timer.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
 obj-arm-y += gumstix.o
 obj-arm-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
 obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
 		omap_gpio.o omap_intc.o omap_uart.o
Index: qemu-working/hw/imx_avic.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ qemu-working/hw/imx_avic.c	2011-11-22 08:51:09.733239638 +1100
@@ -0,0 +1,294 @@
+/*
+ * IMX31 Vectored Interrupt Controller
+ *
+ * Note this is NOT the PL192 provided by ARM, but
+ * a custom implementation by FreeScale.
+ *
+ * Copyright (c) 2008 OKL
+ * Written by Hans
+ *
+ * This code is licenced under the GPL.
+ *
+ * TODO: implement vectors and priorities.
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include <string.h> /* ffsll */
+
+#define DEBUG_INT 1
+#undef DEBUG_INT /* comment out for debugging */
+
+#ifdef DEBUG_INT
+#define DPRINTF(fmt, args...) \
+do { printf("imx_int: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while (0)
+#endif
+
+
+#define IMX_INT_NUM_IRQS 64
+
+/* Interrupt Control Bits */
+#define ABFLAG (1<<25)
+#define ABFEN (1<<24)
+#define NIDIS (1<<22) /* Normal Interrupt disable */
+#define FIDIS (1<<21) /* Fast interrupt disable */
+#define NIAD  (1<<20) /* Normal Interrupt Arbiter Rise ARM level */
+#define FIAD  (1<<19) /* Fast Interrupt Arbiter Rise ARM level */
+#define NM    (1<<18) /* Normal interrupt mode */
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint64_t pending;
+    uint64_t enabled;
+    uint64_t is_fiq;
+    uint32_t intcntl;
+    uint32_t intmask;
+    qemu_irq irq;
+    qemu_irq fiq;
+    uint32_t prio[IMX_INT_NUM_IRQS/(32/4)]; /* Priorities are 4-bits each */
+} imx_int_state;
+
+static inline int imx_int_prio(imx_int_state *s, int irq)
+{
+    uint32_t word = irq / (32/4);
+    uint32_t part = irq % (32/4);
+    return 0xff & (s->prio[word] >> (4 * part));
+}
+
+static inline void imx_int_set_prio(imx_int_state *s, int irq, int prio)
+{
+    uint32_t word = irq / (32/4);
+    uint32_t part = 4 * (irq % (32/4));
+    uint32_t mask = ~(0xff << part);
+    s->prio[word] &= mask;
+    s->prio[word] |= prio << part;
+}
+
+/* Update interrupts.  */
+static void imx_int_update(imx_int_state *s)
+{
+    int i;
+    uint64_t new = s->pending;
+    uint64_t flags;
+
+    flags = new & s->enabled & s->is_fiq;
+    qemu_set_irq(s->fiq, !!flags);
+
+    flags = new & s->enabled & ~s->is_fiq;
+    if (!flags || likely((s->intmask & 0x1f) == 0x1f)) {
+        qemu_set_irq(s->irq, !!flags);
+        return;
+    }
+    /* Take interrupt if  prio lower than the value of intmask */
+
+    for (i = 0; i < IMX_INT_NUM_IRQS; i++) {
+        if (flags & (1<<i)) {
+            if (imx_int_prio(s, i) > s->intmask) {
+                qemu_set_irq(s->irq, 1);
+                return;
+            }
+        }
+    }
+
+}
+
+static void imx_int_set_irq(void *opaque, int irq, int level)
+{
+    imx_int_state *s = (imx_int_state *)opaque;
+
+    if (level) {
+        s->pending |= (1ULL << irq);
+    } else {
+        s->pending &= ~(1ULL << irq);
+    }
+
+    imx_int_update(s);
+}
+
+
+static uint64_t imx_int_read(void *opaque,
+                             target_phys_addr_t offset, unsigned size)
+{
+    imx_int_state *s = (imx_int_state *)opaque;
+
+
+    DPRINTF("read(offset = 0x%x)\n", offset >> 2);
+    switch (offset >> 2) {
+    case 0: /* INTCNTL */
+        return s->intcntl;
+
+    case 1: /* Normal Interrupt Mask Register, NIMASK */
+        return s->intmask;
+
+    case 2: /* Interrupt Enable Number Register, INTENNUM */
+    case 3: /* Interrupt Disable Number Register, INTDISNUM */
+        return 0;
+
+    case 4: /* Interrupt Enabled Number Register High */
+        return s->enabled >> 32;
+    case 5: /* Interrupt Enabled Number Register Low */
+        return s->enabled & 0xffffffffULL;
+    case 6: /* Interrupt Type Register High */
+        return s->is_fiq >> 32;
+    case 7: /* Interrupt Type Register Low */
+        return s->is_fiq & 0xffffffffUll;
+    case 8: /* Normal Interrupt Priority Register 7 */
+    case 9: /* Normal Interrupt Priority Register 6 */
+    case 10:/* Normal Interrupt Priority Register 5 */
+    case 11:/* Normal Interrupt Priority Register 4 */
+    case 12:/* Normal Interrupt Priority Register 3 */
+    case 13:/* Normal Interrupt Priority Register 2 */
+    case 14:/* Normal Interrupt Priority Register 1 */
+    case 15:/* Normal Interrupt Priority Register 0 */
+        return s->prio[15-(offset>>2)];
+
+    case 16: /* Normal interrupt vector and status register */
+    {
+        uint64_t flags = s->pending & s->enabled & ~s->is_fiq;
+        int i = ffsll(flags);
+        if (i) {
+            imx_int_set_irq(opaque, i-1, 0);
+            return (i-1) << 16;
+        }
+        return 0xFFFF<<16;
+    }
+    case 17:/* Fast Interrupt vector and status register */
+    {
+        uint64_t flags = s->pending & s->enabled & s->is_fiq;
+        int i = ffsll(flags);
+        if (i) {
+            imx_int_set_irq(opaque, i-1, 0);
+            return (i-1) << 16;
+        }
+        return 0xFFFF<<16;
+    }
+    case 18:/* Interrupt source register high */
+        return s->pending >> 32;
+    case 19:/* Interrupt source register low */
+        return s->pending & 0xFFFFFFFFULL;
+    case 20:/* Interrupt Force Register high */
+    case 21:/* Interrupt Force Register low */
+        return 0;
+    case 22:/* Normal Interrupt Pending Register High */
+        return (s->pending & s->enabled & ~s->is_fiq) >> 32;
+    case 23:/* Normal Interrupt Pending Register Low */
+        return (s->pending & s->enabled & ~s->is_fiq) & 0XFFFFFFFFULL;
+    case 24: /* Fast Interrupt Pending Register High  */
+        return (s->pending & s->enabled & s->is_fiq) >> 32;
+    case 25: /* Fast Interrupt Pending Register Low  */
+        return (s->pending & s->enabled & s->is_fiq) & 0XFFFFFFFFULL;
+    case 0x40:            /* AVIC vector 0, use for WFI WAR */
+        return 0x4;
+    default:
+        printf("imx_int_read: Bad offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void imx_int_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t val, unsigned size)
+{
+    imx_int_state *s = (imx_int_state *)opaque;
+
+    /* Vector Registers not yet supported */
+    if (offset >= 0x100 && offset <= 0x2fc) {
+        DPRINTF("imx_int_write to vector register %d\n",
+                (offset - 0x100)>>2);
+        return;
+    }
+
+    DPRINTF("imx_int_write(0x%x) = %x\n",
+            (unsigned int)offset>>2, (unsigned int)val);
+    switch (offset >> 2) {
+    case 0: /* Interrupt Control Register, INTCNTL */
+        s->intcntl = val;
+        break;
+    case 1: /* Normal Interrupt Mask Register, NIMASK */
+        s->intmask = val;
+        break;
+    case 2: /* Interrupt Enable Number Register, INTENNUM */
+        DPRINTF("enable(%d)\n", (int)val);
+        s->enabled |= (1ULL << val);
+        break;
+    case 3: /* Interrupt Disable Number Register, INTDISNUM */
+        s->enabled &= ~(1ULL << val);
+        DPRINTF("disabled(%d)\n", (int)val);
+        break;
+    case 4: /* Interrupt Enable Number Register High */
+        s->enabled = (s->enabled & 0xffffffffULL) | (val << 32);
+        break;
+    case 5: /* Interrupt Enable Number Register Low */
+        s->enabled = (s->enabled & 0xffffffff00000000ULL) | val;
+        break;
+    case 6: /* Interrypt Type Register High */
+        s->is_fiq = (s->is_fiq & 0xffffffffULL) | (val << 32);
+        break;
+    case 7: /* Interrupt Type Register Low */
+        s->is_fiq = (s->is_fiq & 0xffffffff00000000ULL) | val;
+        break;
+    case 8: /* Normal Interrupt Priority Register 7 */
+    case 9: /* Normal Interrupt Priority Register 6 */
+    case 10:/* Normal Interrupt Priority Register 5 */
+    case 11:/* Normal Interrupt Priority Register 4 */
+    case 12:/* Normal Interrupt Priority Register 3 */
+    case 13:/* Normal Interrupt Priority Register 2 */
+    case 14:/* Normal Interrupt Priority Register 1 */
+    case 15:/* Normal Interrupt Priority Register 0 */
+        s->prio[15-(offset>>2)] = val;
+        return;
+        /* Read-only registers, writes ignored */
+    case 16:/* Normal Interrupt Vector and Status register */
+    case 17:/* Fast Interrupt vector and status register */
+    case 18:/* Interrupt source register high */
+    case 19:/* Interrupt source register low */
+        return;
+    case 20:/* Interrupt Force Register high */
+        s->pending = (s->pending & 0xffffffffULL) | (val << 32);
+        break;
+    case 21:/* Interrupt Force Register low */
+        s->pending = (s->pending & 0xffffffff00000000ULL) | val;
+        break;
+    case 22:/* Normal Interrupt Pending Register High */
+    case 23:/* Normal Interrupt Pending Register Low */
+    case 24: /* Fast Interrupt Pending Register High  */
+    case 25: /* Fast Interrupt Pending Register Low  */
+        return;
+    default:
+        hw_error("imx_int_write: Bad offset %x\n", (int)offset);
+    }
+    imx_int_update(s);
+}
+
+static const MemoryRegionOps imx_int_ops = {
+    .read = imx_int_read,
+    .write = imx_int_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int imx_int_init(SysBusDevice *dev)
+{
+    imx_int_state *s = FROM_SYSBUS(imx_int_state, dev);;
+
+    memory_region_init_io(&s->iomem, &imx_int_ops, s, "imx_int", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
+
+    qdev_init_gpio_in(&dev->qdev, imx_int_set_irq, IMX_INT_NUM_IRQS);
+    sysbus_init_irq(dev, &s->irq);
+    sysbus_init_irq(dev, &s->fiq);
+
+    s->intmask = 0x1f;
+    s->enabled = 0ULL;
+    return 0;
+}
+
+static void imx_int_register_devices(void)
+{
+    sysbus_register_dev("imx_int", sizeof(imx_int_state),
+                        imx_int_init);
+}
+
+device_init(imx_int_register_devices);
+
Index: qemu-working/hw/imx_serial.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ qemu-working/hw/imx_serial.c	2011-11-22 08:49:36.084276219 +1100
@@ -0,0 +1,260 @@
+/*
+ * IMX31 UARTS
+ *
+ * Copyright (c) 2008 OKL
+ * Written by Hans
+ *
+ * This code is licenced under the GPL.
+ * This is a `bare-bones' implementation of the IMX series serial ports.
+ * TODO:
+ *  -- implement FIFOs.  The real hardware has 32 word transmit
+ *                       and receive FIFOs
+ *  -- implement DMA
+ *  -- implement BAUD-rate and modem lines, for when the backend
+ *     is a real serial device.
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "qemu-char.h"
+
+#define DEBUG_SERIAL 1
+#undef DEBUG_SERIAL /* comment out for debugging */
+
+#ifdef DEBUG_SERIAL
+#define DPRINTF(fmt, args...) \
+do { printf("imx_serial: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while (0)
+#endif
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    int32_t readbuff;
+
+    uint32_t usr1;
+    uint32_t usr2;
+    uint32_t ucr1;
+    uint32_t uts1;
+
+    uint32_t ubrm;
+    uint32_t ubrc;
+
+    qemu_irq irq;
+    CharDriverState *chr;
+} imx_state;
+
+#define URXD_CHARRDY    (1<<15) /* character read is valid */
+
+#define USR1_TRDY       (1<<13)   /* Xmitter ready */
+#define USR1_RRDY       (1<<9)    /* receiver ready */
+
+#define USR2_TXFE       (1<<14)   /* Transmit FIFO empty */
+#define USR2_RDR        (1<<0)    /* Receiove data ready */
+#define USR2_TXDC       (1<<3)    /* Transmission complete */
+
+#define UCR1_UARTEN     (1<<0)
+#define UCR1_RRDYEN     (1<<9)
+#define UCR1_TRDYEN     (1<<13)
+#define UCR1_TXMPTYEN   (1<<6)
+
+#define UTS1_TXEMPTY    (1<<6)
+#define UTS1_RXEMPTY    (1<<5)
+#define UTS1_TXFULL     (1<<4)
+#define UTS1_RXFULL     (1<<3)
+
+static void imx_update(imx_state *s)
+{
+    uint32_t flags;
+
+    flags = ((s->usr1 & s->ucr1)) & (USR1_TRDY|USR1_RRDY);
+    if (0 == (s->ucr1 & UCR1_TXMPTYEN)) {
+        flags &= ~USR1_TRDY;
+    }
+
+    qemu_set_irq(s->irq, !!flags);
+}
+
+static uint64_t imx_serial_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
+{
+    imx_state *s = (imx_state *)opaque;
+    uint32_t c;
+
+    DPRINTF("read(offset=%x)\n", offset >> 2);
+    switch (offset >> 2) {
+    case 0x0: /* URXD */
+        c = s->readbuff;
+        s->usr1 &= ~USR1_RRDY;
+        s->usr2 &= ~USR2_RDR;
+        s->uts1 |= UTS1_RXEMPTY;
+        imx_update(s);
+        qemu_chr_accept_input(s->chr);
+        return c | URXD_CHARRDY;
+
+    case 0x20: /* UCR1 */
+        return s->ucr1;
+
+    case 0x21: /* UCR2 */
+        return 1; /* reset complete */
+
+    case 0x25: /* USR1 */
+        imx_update(s);
+        return s->usr1;
+
+    case 0x26: /* USR2 */
+        imx_update(s);
+        return s->usr2;
+
+
+    case 0x2A: /* BRM Modulator */
+        return s->ubrm;
+
+    case 0x2B: /* Baud Rate Count */
+        return s->ubrc;
+
+    case 0x2d: /* UTS1 */
+        return s->uts1;
+
+
+    case 0x22: /* UCR3 */
+    case 0x23: /* UCR4 */
+    case 0x24: /* UFCR */
+    case 0x29: /* BRM Incremental */
+        return 0x0; /* TODO */
+
+    default:
+        hw_error("imx_serial_read: bad offset: 0x%x\n", (int)offset);
+        /* Keep gcc happy: notreached */
+        return 0;
+    }
+}
+
+
+static void imx_serial_write(void *opaque, target_phys_addr_t offset,
+                      uint64_t value, unsigned size)
+{
+    imx_state *s = (imx_state *)opaque;
+    unsigned char ch;
+
+    DPRINTF("write(offset=%x, value = %x)\n", offset >> 2, (unsigned int)value);
+    switch (offset >> 2) {
+    case 0x10: /* UTXD */
+        ch = value;
+        if (s->chr) {
+            qemu_chr_fe_write(s->chr, &ch, 1);
+        }
+        s->usr1 &= ~USR1_TRDY;
+        imx_update(s);
+        s->usr1 |= USR1_TRDY;
+        imx_update(s);
+
+        break;
+
+    case 0x20: /* UCR1 */
+        s->ucr1 = value;
+        DPRINTF("write(ucr1=%x)\n", (unsigned int)value);
+        imx_update(s);
+        break;
+
+    case 0x26: /* USR2 */
+       /*
+        * Writing 1 to some bits clears them; all other
+        * values are ignored
+        */
+        value &= (1<<15)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|
+            (1<<8)|(1<<7)|(1<<6)|(1<<4)|(1<<2)|(1<<1);
+        s->usr2 &= ~value;
+        break;
+
+        /* Linux expects to see what it writes here. */
+        /* We don't currently alter the baud rate */
+    case 0x29: /* UBIR */
+        s->ubrc = value;
+        break;
+
+    case 0x2a: /* UBRM */
+        s->ubrm = value;
+        break;
+
+    case 0x21: /* UCR2 */
+    case 0x2d: /* UTS1 */
+    case 0x22: /* UCR3 */
+    case 0x23: /* UCR4 */
+    case 0x24: /* UFCR */
+    case 0x25: /* USR1 */
+    case 0x2c: /* BIPR1 */
+        /* TODO */
+        break;
+
+    default:
+        hw_error("imx_serial_write: Bad offset 0x%x\n", (int)offset);
+    }
+}
+
+static int imx_can_receive(void *opaque)
+{
+    imx_state *s = (imx_state *)opaque;
+    return !(s->usr1 & USR1_RRDY);
+}
+
+static void imx_put_data(void *opaque, uint32_t value)
+{
+    imx_state *s = (imx_state *)opaque;
+
+    s->usr1 |= USR1_RRDY;
+    s->usr2 |= USR2_RDR;
+    s->uts1 &= ~UTS1_RXEMPTY;
+    s->readbuff = value;
+    imx_update(s);
+}
+
+static void imx_receive(void *opaque, const uint8_t *buf, int size)
+{
+    imx_put_data(opaque, *buf);
+}
+
+static void imx_event(void *opaque, int event)
+{
+    if (event == CHR_EVENT_BREAK) {
+        imx_put_data(opaque, 0x400);
+    }
+}
+
+static const struct MemoryRegionOps imx_serial_ops = {
+    .read = imx_serial_read,
+    .write = imx_serial_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int imx_serial_init(SysBusDevice *dev)
+{
+    imx_state *s = FROM_SYSBUS(imx_state, dev);
+
+    memory_region_init_io(&s->iomem, &imx_serial_ops, s, "imx-serial", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+    s->chr = qdev_init_chardev(&dev->qdev);
+
+    s->usr1 = USR1_TRDY;
+    s->usr2 = USR2_TXFE | USR2_TXDC;
+    s->ucr1 = UCR1_TRDYEN | UCR1_RRDYEN | UCR1_UARTEN;
+    s->uts1 = UTS1_RXEMPTY;
+    s->readbuff = 0;
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
+                              imx_event, s);
+    }
+    return 0;
+    /* ??? Save/restore.  */
+}
+
+static void imx_serial_register_devices(void)
+{
+    DPRINTF("imx_serial_register_devices\n");
+    sysbus_register_dev("imx_serial", sizeof(imx_state),
+                        imx_serial_init);
+}
+
+device_init(imx_serial_register_devices);
Index: qemu-working/hw/imx_timer.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ qemu-working/hw/imx_timer.c	2011-11-22 08:51:12.589269454 +1100
@@ -0,0 +1,430 @@
+/*
+ * IMX31 Timer
+ *
+ * Copyright (c) 2008 OKL
+ * Written by Hans
+ * Updated by Peter Chubb
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "hw.h"
+#include "qemu-timer.h"
+#include "sysbus.h"
+
+#define DEBUG_TIMER 1
+#undef DEBUG_TIMER  /* comment out for debugging */
+
+#ifdef DEBUG_TIMER
+#   define DPRINTF(fmt, args...) \
+        do { printf("imx_timer: " fmt , ##args); } while (0)
+#else
+#   define DPRINTF(fmt, args...) do {} while (0)
+#endif
+
+/*
+ * GPT : General purpose timer
+ */
+
+#define TIMER_MAX  0xFFFFFFFFUL
+#define GPT_FREQ   50000000    /* Hz == 50 MHz */
+
+/* Control register.  Not all of these bits have any effect (yet) */
+#define GPT_CR_EN   (1 << 0)    /* GPT Enable */
+#define GPT_CR_ENMODE (1 << 1)  /* GPT Enable Mode */
+#define GPT_CR_DBGEN (1 << 2)   /* GPT Debug mode enable */
+#define GPT_CR_WAITEN (1 << 3)  /* GPT Wait Mode Enable  */
+#define GPT_CR_DOZEN (1 << 4)   /* GPT Doze mode enable */
+#define GPT_CR_STOPEN (1 << 5)  /* GPT Stop Mode Enable */
+#define GPT_CR_CLKSRC (7 << 6) /* Clock source select (3 bits) */
+#define GPT_CR_FRR  (1 << 9)    /* Freerun or Restart */
+#define GPT_CR_SWR  (1 << 15)
+#define GPT_CR_IM1  (3 << 16)   /* Input capture channel 1 mode (2 bits) */
+#define GPT_CR_IM2  (3 << 18)   /* Input capture channel 2 mode (2 bits) */
+#define GPT_CR_OM1  (7 << 20)   /* Output Compare Channel 1 Mode (3 bits) */
+#define GPT_CR_OM2  (7 << 23)   /* Output Compare Channel 2 Mode (3 bits) */
+#define GPT_CR_OM3  (7 << 26)   /* Output Compare Channel 3 Mode (3 bits) */
+#define GPT_CR_FO1  (1 << 29)   /* Force Output Compare Channel 1 */
+#define GPT_CR_FO2  (1 << 30)   /* Force Output Compare Channel 2 */
+#define GPT_CR_FO3  (1 << 31)   /* Force Output Compare Channel 3 */
+
+
+
+
+#define GPT_SR_OF1  (1 << 0)
+#define GPT_SR_ROV  (1 << 5)
+#define GPT_IR_OF1IE  (1 << 0)
+#define GPT_IR_ROVIE  (1 << 5)
+
+typedef struct {
+    SysBusDevice busdev;
+    QEMUTimer *timer;
+    MemoryRegion iomem;
+    uint32_t cr;
+    uint32_t sr;
+    uint32_t pr;
+    uint32_t ir;
+    uint32_t ocr1;
+    uint32_t cnt;
+
+    int waiting_rov;
+    qemu_irq irq;
+} imxg_timer_state;
+
+static const VMStateDescription vmstate_imxg_timer = {
+    .name = "imxg-timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(cr, imxg_timer_state),
+        VMSTATE_UINT32(sr, imxg_timer_state),
+        VMSTATE_UINT32(ir, imxg_timer_state),
+        VMSTATE_UINT32(cnt, imxg_timer_state),
+        VMSTATE_UINT32(ocr1, imxg_timer_state),
+        VMSTATE_TIMER(timer, imxg_timer_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+
+/* Check all active timers, and schedule the next timer interrupt.  */
+static void imxg_timer_update(imxg_timer_state *s)
+{
+    /* Update interrupts.  */
+    if ((s->cr & GPT_CR_EN)
+        && (((s->sr & GPT_SR_OF1) && (s->ir & GPT_IR_OF1IE)) ||
+            ((s->sr & GPT_SR_ROV) && (s->ir & GPT_IR_ROVIE)))) {
+        qemu_irq_raise(s->irq);
+    } else {
+        qemu_irq_lower(s->irq);
+    }
+}
+
+static uint64_t imxg_timer_update_count(imxg_timer_state *s)
+{
+    uint64_t clk = qemu_get_clock_ns(vm_clock);
+
+    s->cnt = ((uint32_t)muldiv64(clk, GPT_FREQ/1000000,
+                                 1000)) % TIMER_MAX;
+    return clk;
+}
+
+static void imxg_timer_run(imxg_timer_state *s, uint32_t timeout)
+{
+    uint64_t clk = imxg_timer_update_count(s);
+    uint32_t diff_cnt;
+    if (s->cnt < timeout) {
+        diff_cnt = (timeout - s->cnt);
+        s->waiting_rov = 0;
+    } else {
+        diff_cnt = (TIMER_MAX - s->cnt);
+        s->waiting_rov = 1;
+    }
+    qemu_mod_timer(s->timer, clk + diff_cnt * 1000 / (GPT_FREQ/1000000));
+/*
+                   clk + muldiv64(get_ticks_per_sec(),
+                                            diff_cnt, GPT_FREQ)
+*/
+}
+
+static uint64_t imxg_timer_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
+{
+    imxg_timer_state *s = (imxg_timer_state *)opaque;
+
+    DPRINTF("g-read(offset=%x)\n", offset >> 2);
+    switch (offset >> 2) {
+    case 0: /* CR */
+        return s->cr;
+
+    case 1: /* prescaler */
+        return s->pr;
+
+    case 2:
+        return s->sr;
+
+    case 3:
+        return s->ir;
+
+    case 4:
+        return s->ocr1;
+
+    case 9: /* cnt */
+        imxg_timer_update_count(s);
+        return s->cnt;
+    }
+
+    cpu_abort(cpu_single_env, "imxg_timer_read: Bad offset %x\n",
+               (int)offset >> 2);
+}
+
+static void imxg_timer_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
+{
+    imxg_timer_state *s = (imxg_timer_state *)opaque;
+    DPRINTF("g-write(offset=%x, value = %x)\n", (unsigned int)offset >> 2,
+            (unsigned int)value);
+
+    switch (offset >> 2) {
+    case 0: /* CR */
+        if (value & GPT_CR_SWR) { /* force reset */
+            value &= ~GPT_CR_SWR;
+            s->cr &= ~(GPT_CR_EN|GPT_CR_DOZEN|GPT_CR_WAITEN|GPT_CR_DBGEN);
+            s->sr = 0;
+            s->pr = 0;
+            s->ir = 0;
+            s->cnt = 0;
+            s->ocr1 = 0;
+        }
+        if (!(s->cr & GPT_CR_EN) && (value & GPT_CR_EN)) {
+            if (value & GPT_CR_ENMODE) {
+                s->cnt = 0;
+            }
+            imxg_timer_run(s, s->ocr1);
+        } else if ((s->cr & GPT_CR_EN) && !(value & GPT_CR_EN)) {
+            qemu_del_timer(s->timer);
+        };
+        s->cr = value;
+        return;
+
+    case 1:
+        s->pr = value;
+        return;
+
+    case 2:
+        if (value & GPT_SR_OF1) {
+            s->sr &= ~GPT_SR_OF1;
+        }
+        if (value & GPT_SR_ROV) {
+            s->sr &= ~GPT_SR_ROV;
+        }
+        imxg_timer_update(s);
+        return;
+
+    case 3:
+        s->ir = value;
+        imxg_timer_update(s);
+        return;
+
+    case 4:
+        s->ocr1 = value;
+        if (s->cr & GPT_CR_EN) {
+            imxg_timer_run(s, s->ocr1);
+        }
+        return;
+
+    default:
+        cpu_abort(cpu_single_env, "imxg_timer_write: Bad offset %x\n",
+                   (int)offset >> 2);
+    }
+}
+
+static void imxg_timer_timeout(void *opaque)
+{
+    imxg_timer_state *s = (imxg_timer_state *)opaque;
+
+    DPRINTF("imxg_timer_timeout\n");
+    if (s->waiting_rov) {
+        s->sr |= GPT_SR_ROV;
+        imxg_timer_run(s, s->ocr1);
+    } else {
+        s->sr |= GPT_SR_OF1;
+        imxg_timer_run(s, 0);
+    }
+    imxg_timer_update(s);
+}
+
+static const MemoryRegionOps imxg_timer_ops = {
+  .read = imxg_timer_read,
+  .write = imxg_timer_write,
+  .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+
+static int imxg_timer_init(SysBusDevice *dev)
+{
+    imxg_timer_state *s = FROM_SYSBUS(imxg_timer_state, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+    memory_region_init_io(&s->iomem, &imxg_timer_ops,
+                          s, "imxg-timer",
+                          0x00001000);
+    sysbus_init_mmio_region(dev, &s->iomem);
+
+    s->timer = qemu_new_timer_ns(vm_clock, imxg_timer_timeout, s);
+    s->cr = 0;
+    s->ir = 0;
+    s->pr = 0;
+    s->ocr1 = 0;
+    imxg_timer_update_count(s);
+
+    return 0;
+}
+
+
+
+/*
+ * EPIT :Enhanced periodic interrupt timer
+ */
+
+#define EPIT_FREQ   1000000
+#define TIMER_TICK_LENGTH 5000
+#define IMX31_TICKS_PER_TIMESLICE (72 * TIMER_TICK_LENGTH)
+#define CR_EN       (1 << 0)
+#define CR_SWR      (1 << 16)
+
+typedef struct {
+    SysBusDevice busdev;
+    ptimer_state *timer;
+    MemoryRegion iomem;
+    uint32_t cr;
+    uint32_t lr;
+    uint32_t cmp;
+    int int_level;
+    qemu_irq irq;
+} imxp_timer_state;
+
+/* Check all active timers, and schedule the next timer interrupt.  */
+static void imxp_timer_update(imxp_timer_state *s)
+{
+    /* Update interrupts.  */
+    if (s->int_level && (s->cr & CR_EN)) {
+        qemu_irq_raise(s->irq);
+    } else {
+        qemu_irq_lower(s->irq);
+    }
+}
+
+static uint64_t imxp_timer_read(void *opaque, target_phys_addr_t offset,
+                                unsigned size)
+{
+    imxp_timer_state *s = (imxp_timer_state *)opaque;
+
+    DPRINTF("p-read(offset=%x)\n", offset);
+    switch (offset >> 2) {
+    case 0: /* CR */
+        return s->cr;
+
+    case 1: /* SR */
+        return s->int_level;
+
+    case 2: /* LR - set ticks*/
+        return s->lr;
+
+    case 3: /* CMP */
+        return s->cmp;
+
+    case 4: /* CNT */
+        return ptimer_get_count(s->timer);
+    }
+    cpu_abort(cpu_single_env, "imxp_timer_read: Bad offset %x\n",
+               (int)offset >> 2);
+}
+
+static void imxp_timer_write(void *opaque, target_phys_addr_t offset,
+                             uint64_t value, unsigned size)
+{
+    imxp_timer_state *s = (imxp_timer_state *)opaque;
+    DPRINTF("p-write(offset=%x, value = %x)\n", (unsigned int)offset >> 2,
+            (unsigned int)value);
+
+    switch (offset >> 2) {
+    case 0: /* CR */
+        if (s->cr & CR_EN) {
+            ptimer_run(s->timer, 0);
+        } else {
+            ptimer_stop(s->timer);
+        }
+        if (s->cr & CR_SWR) {
+            s->cr = 0;
+            s->lr = 0;
+            ptimer_stop(s->timer);
+        }
+        break;
+
+    case 1: /* SR - ACK*/
+        s->int_level = 0;
+        imxp_timer_update(s);
+        break;
+
+    case 2: /* LR - set ticks*/
+        s->lr = value;
+        ptimer_set_freq(s->timer, EPIT_FREQ);
+        ptimer_set_limit(s->timer, value, 1);
+        break;
+
+    case 3: /* CMP */
+        s->cmp = value;
+        break;
+
+    default:
+        cpu_abort(cpu_single_env, "imxp_timer_write: Bad offset %x\n",
+                   (int)offset >> 2);
+    }
+}
+
+static void imxp_timer_tick(void *opaque)
+{
+    imxp_timer_state *s = (imxp_timer_state *)opaque;
+    s->int_level = 1;
+    imxp_timer_update(s);
+}
+
+static const MemoryRegionOps imxp_timer_ops = {
+  .read = imxp_timer_read,
+  .write = imxp_timer_write,
+  .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_imxp_timer = {
+    .name = "imxp-timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(cr, imxp_timer_state),
+        VMSTATE_UINT32(lr, imxp_timer_state),
+        VMSTATE_UINT32(cmp, imxp_timer_state),
+        VMSTATE_INT32(int_level, imxp_timer_state),
+        VMSTATE_PTIMER(timer, imxp_timer_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+
+
+static int imxp_timer_init(SysBusDevice *dev)
+{
+    imxp_timer_state *s = FROM_SYSBUS(imxp_timer_state, dev);
+    QEMUBH *bh;
+
+    DPRINTF("imxp_timer_init\n");
+
+    sysbus_init_irq(dev, &s->irq);
+    memory_region_init_io(&s->iomem, &imxp_timer_ops,
+                          s, "imxp-timer",
+                          0x00001000);
+    sysbus_init_mmio_region(dev, &s->iomem);
+
+    s->cr = 0;
+    s->lr = 0;
+
+    bh = qemu_bh_new(imxp_timer_tick, s);
+    s->timer = ptimer_init(bh);
+    vmstate_register(&dev->qdev, -1, &vmstate_imxp_timer, s);
+
+    return 0;
+}
+
+static void imx_timer_register_devices(void)
+{
+    DPRINTF("Registering Timers\n");
+    sysbus_register_dev("imx_timerp", sizeof(imxp_timer_state),
+                        imxp_timer_init);
+    sysbus_register_dev("imx_timerg", sizeof(imxg_timer_state),
+                        imxg_timer_init);
+}
+
+
+device_init(imx_timer_register_devices);
Index: qemu-working/hw/kzm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ qemu-working/hw/kzm.c	2011-11-22 08:42:26.292661540 +1100
@@ -0,0 +1,159 @@
+/*
+ * KZM Board System emulation.
+ *
+ * Copyright (c) 2008 OKL and 2011 NICTA
+ * Written by Hans
+ * Updated by Peter Chubb.
+ *
+ * This code is licenced under the GPL.
+ * It (partially) emulates a Kyoto Microcomputer
+ * KZM-ARM11-01 evaluation board, with a FreeScale
+ * I.MX31 SoC
+ */
+
+#include "sysbus.h"
+#include "exec-memory.h"
+#include "hw.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "pci.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "pc.h" /* for the FPGA UART that emulates a 16550 */
+
+    /* Memory map for Kzm Emulation Baseboard:
+     * 0x00000000-0x00003fff 16k secure ROM       IGNORED
+     * 0x00004000-0x00407fff Reserved             IGNORED
+     * 0x00404000-0x00407fff ROM                  IGNORED
+     * 0x00408000-0x0fffffff Reserved             IGNORED
+     * 0x10000000-0x1fffBfff RAM aliasing         IGNORED
+     * 0x1fffc000-0x1fffffff RAM                  EMULATED
+     * 0x20000000-0x2fffffff Reserved             IGNORED
+     * 0x30000000-0x7fffffff I.MX31 Internal Register Space
+     *   0x43f00000 IO_AREA0
+     *   0x43f90000 UART1                         EMULATED
+     *   0x43f94000 UART2                         EMULATED
+     *   0x68000000 PIC                           EMULATED
+     *   0x53f94000 PIT 1                         EMULATED
+     *   0x53f98000 PIT 2                         EMULATED
+     *   0x53f90000 GPT                           EMULATED
+     * 0x80000000-0x87ffffff RAM                  EMULATED
+     * 0x88000000-0x8fffffff RAM Aliasing         EMULATED
+     * 0xa0000000-0xafffffff NAND Flash           IGNORED
+     * 0xb0000000-0xb3ffffff Unavailable          IGNORED
+     * 0xb4000000-0xb4000fff 8-bit free space     IGNORED
+     * 0xb4001000-0xb400100f Board control        IGNORED
+     *  0xb4001003           DIP switch
+     * 0xb4001010-0xb400101f 7-segment LED        IGNORED
+     * 0xb4001020-0xb400102f LED                  IGNORED
+     * 0xb4001030-0xb400103f LED                  IGNORED
+     * 0xb4001040-0xb400104f FPGA, UART           EMULATED
+     * 0xb4001050-0xb400105f FPGA, UART           EMULATED
+     * 0xb4001060-0xb40fffff FPGA                 IGNORED
+     * 0xb6000000-0xb61fffff LAN controller       EMULATED
+     * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
+     * 0xb6300000-0xb7ffffff Free                 IGNORED
+     * 0xb8000000-0xb8004fff Memory control registers IGNORED
+     * 0xc0000000-0xc3ffffff PCMCIA/CF            IGNORED
+     * 0xc4000000-0xffffffff Reserved             IGNORED
+     */
+
+#define KZM_RAMADDRESS (0x80000000)
+#define KZM_FPGA       (0xb4001040)
+
+/* Board init.  */
+
+static struct arm_boot_info kzm_binfo = {
+    .loader_start = KZM_RAMADDRESS,
+    .board_id = 1722,
+};
+
+static void kzm_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_pic;
+    DeviceState *dev;
+
+    if (!cpu_model) {
+        cpu_model = "arm1136";
+    }
+
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+
+    /* On a real system, the first 16k is a `secure boot rom' */
+
+    memory_region_init_ram(ram, NULL, "kzm.ram", ram_size);
+    memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram);
+
+    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+    memory_region_add_subregion(address_space_mem, 0x88000000, ram_alias);
+
+    memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000);
+    memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
+
+
+    cpu_pic = arm_pic_init_cpu(env);
+    dev = sysbus_create_varargs("imx_int", 0x68000000,
+                               cpu_pic[ARM_PIC_CPU_IRQ],
+                               cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+
+
+    sysbus_create_simple("imx_serial", 0x43f90000, qdev_get_gpio_in(dev, 45));
+    sysbus_create_simple("imx_serial", 0x43f94000, qdev_get_gpio_in(dev, 32));
+    sysbus_create_simple("imx_timerp", 0x53f94000, qdev_get_gpio_in(dev, 28));
+    sysbus_create_simple("imx_timerp", 0x53f98000, qdev_get_gpio_in(dev, 27));
+    sysbus_create_simple("imx_timerg", 0x53f90000, qdev_get_gpio_in(dev, 29));
+
+    /*
+    if (nd_table[0].vlan) {
+        lan9118_init(&nd_table[0], 0xb6000000, qdev_get_gpio_in(dev, 51));
+    }
+    */
+    if (serial_hds[3]) {
+        printf("serial_hds[3]\n");
+        serial_mm_init(address_space_mem, KZM_FPGA, 0,
+                       qdev_get_gpio_in(dev, 52),
+                       14745600, serial_hds[3],
+                       DEVICE_NATIVE_ENDIAN);
+    }
+    if (serial_hds[2]) { /* touchscreen */
+        printf("serial_hds[2]\n");
+        serial_mm_init(address_space_mem, KZM_FPGA+0x10, 0,
+                       qdev_get_gpio_in(dev, 52),
+                       14745600, serial_hds[2],
+                       DEVICE_NATIVE_ENDIAN);
+    }
+
+    kzm_binfo.ram_size = ram_size;
+    kzm_binfo.kernel_filename = kernel_filename;
+    kzm_binfo.kernel_cmdline = kernel_cmdline;
+    kzm_binfo.initrd_filename = initrd_filename;
+    kzm_binfo.nb_cpus = 1;
+    arm_load_kernel(first_cpu, &kzm_binfo);
+}
+
+static QEMUMachine kzm_machine = {
+    .name = "kzm",
+    .desc = "ARM KZM Emulation Baseboard (ARM1136)",
+    .init = kzm_init,
+};
+
+static void kzm_machine_init(void)
+{
+    qemu_register_machine(&kzm_machine);
+}
+
+machine_init(kzm_machine_init);

--
Dr Peter Chubb  http://www.gelato.unsw.edu.au  peterc AT gelato.unsw.edu.au
http://www.ertos.nicta.com.au           ERTOS within National ICT Australia

  parent reply	other threads:[~2011-11-21 21:59 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-29  2:34 [Qemu-devel] [PATCH] [ARM] Fix sp804 dual-timer Peter Chubb
2011-09-29  9:58 ` Peter Maydell
2011-09-30  0:20   ` Peter Chubb
2011-09-30  9:04     ` Peter Maydell
2011-09-30  9:23       ` Peter Chubb
2011-09-30 10:07         ` Peter Maydell
     [not found]   ` <w4y5x6g8gk.wl%peter@chubb.wattle.id.au>
     [not found]     ` <CAFEAcA8-iByH0xgjkMUo3hvkrLc8NV-Lq4GbHU-d7UoF8GSX-Q@mail.gmail.com>
2011-11-21 21:58       ` Peter Chubb [this message]
2011-11-21 22:45         ` [Qemu-devel] [PATCH] imx.31 and KZM board support Andreas Färber
2011-11-21 23:04           ` Peter Chubb
2011-11-21 23:10             ` Peter Maydell
2011-11-21 23:41         ` Peter Maydell
2011-11-21 23:54           ` Peter Chubb
2011-11-22  0:12             ` Peter Maydell
2011-11-22  0:27               ` Peter Chubb
2011-11-22  0:32                 ` Peter Maydell
2011-11-22  4:31           ` [Qemu-devel] [PATCH V2 0/4] " Peter Chubb
2011-11-22  4:32             ` [Qemu-devel] [PATCH V2 1/4] imx.31 and KZM board support: UART support Peter Chubb
2011-11-24 18:53               ` Peter Maydell
2011-11-24 22:18                 ` Peter Chubb
2011-11-22  4:33             ` [Qemu-devel] [PATCH V2 2/4] imx.31 and KZM board support: Timer support Peter Chubb
2011-11-24 17:01               ` Peter Maydell
2011-11-24 19:06               ` Peter Maydell
2011-11-22  4:34             ` [Qemu-devel] [PATCH V2 3/4] imx.31 and KZM board support: interrupt controller Peter Chubb
2011-11-24 19:37               ` Peter Maydell
2011-11-22  4:34             ` [Qemu-devel] [PATCH V2 4/4] imx.31 and KZM board support: Makefile and board Peter Chubb
2011-11-24 19:41               ` Peter Maydell
2011-11-24 20:19                 ` Andreas Färber
2011-11-24 21:31                   ` Peter Maydell
2011-11-24 21:46                     ` Andreas Färber
2011-11-24 21:52                       ` Peter Maydell
2011-11-23  0:51             ` [Qemu-devel] [PATCH V2 0/4] imx.31 and KZM board support Peter Chubb
2011-11-24 19:07               ` Andreas Färber
2011-11-26  5:21                 ` Peter Chubb
2011-11-26 19:35                   ` Peter Maydell
2011-11-22 11:06         ` [Qemu-devel] [PATCH] " Juan Quintela
2011-11-22 11:14           ` Peter Maydell
2011-11-23 14:24             ` Juan Quintela
2011-11-23  0:48           ` Peter Chubb
2011-11-21 22:05   ` [Qemu-devel] [PATCH] [ARM] Fix sp804 dual-timer Peter Chubb
2011-11-21 23:01     ` Andreas Färber
2011-11-22  0:20       ` [Qemu-devel] [PATCH] [ARM] fix function names in error messages in arm_timer.c Peter Chubb
2011-11-22  3:20       ` [Qemu-devel] [PATCH] [ARM] Fix hw_error messages from arm_timer.c Peter Chubb
2011-12-05 19:53         ` andrzej zaborowski
2011-11-22  3:25       ` [Qemu-devel] [PATCH] [ARM] Fix sp804 dual-timer Peter Chubb
2011-11-24 17:46         ` Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=w4lir9m931.wl%peter@chubb.wattle.id.au \
    --to=peterc@gelato.unsw.edu.au \
    --cc=peter.chubb@nicta.com.au \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.