All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/12] refactor OMAP implementation
@ 2010-05-28 17:43 cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 01/12] hw/omap1.c : separate gpio module cmchao
                   ` (11 more replies)
  0 siblings, 12 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel

 The following changes since commit 29f91781bd300b228d9c38b9f6c1e0b6a38f25fb:
 Jes Sorensen (1):
         vhost_net.c: v2 Fix build failure introduced by 0bfcd599e3f5c5679cc7d0165a0a1822e2f60de2
	
 The patches almostly base on http://meego.gitorious.org/qemu-maemo/qemu work and 
 act as preparatory work to merge their OMAP3 and beagleboard support. All the 
 work are to separate modules, which will be shared or extended in OMAP3 implementation 
 and make certain local function static


 [PATCH 01/12] hw/omap1.c : separate gpio module
 [PATCH 02/12] hw/omap2.c : separate gpio module
 [PATCH 03/12] hw/omap2.c : separate gptimer module
 [PATCH 04/12] hw/omap2.c : separate synctimer module
 [PATCH 05/12] hw/omap2.c : separate gpmc(general purpose memory controller)
 [PATCH 06/12] hw/omap2.c : separate sdrc (sdram controller)
 [PATCH 07/12] hw/omap1.c : separate interrupt controller module
 [PATCH 08/12] hw/omap2.c : separate spi module
 [PATCH 09/12] hw/omap2.c : separate tap module(Test-Chip-level)
 [PATCH 10/12] hw/omwp2.c : separate l4 interconnect module
 [PATCH 11/12] hw/omap1.c : separate uart module
 [PATCH 12/12] hw/omap : make local function static and remove declaration from header

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 01/12] hw/omap1.c : separate gpio module
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 02/12] hw/omap2.c " cmchao
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    2 +-
 hw/omap.h       |    1 +
 hw/omap1.c      |  181 -------------------------------------------------
 hw/omap_gpio.c  |  202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 204 insertions(+), 182 deletions(-)
 create mode 100644 hw/omap_gpio.c

diff --git a/Makefile.target b/Makefile.target
index fda5bf3..eb5c84a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -263,7 +263,7 @@ 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
+obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o omap_gpio.o
 obj-arm-y += omap2.o omap_dss.o soc_dma.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
diff --git a/hw/omap.h b/hw/omap.h
index d305779..ebd166f 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -671,6 +671,7 @@ void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
 struct omap_gpio_s;
 struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk clk);
+void omap_gpio_reset(struct omap_gpio_s *s);
 qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
 void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
 
diff --git a/hw/omap1.c b/hw/omap1.c
index 8649dbd..8b78c05 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -2804,187 +2804,6 @@ void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
     omap_mpuio_kbd_update(s);
 }
 
-/* General-Purpose I/O */
-struct omap_gpio_s {
-    qemu_irq irq;
-    qemu_irq *in;
-    qemu_irq handler[16];
-
-    uint16_t inputs;
-    uint16_t outputs;
-    uint16_t dir;
-    uint16_t edge;
-    uint16_t mask;
-    uint16_t ints;
-    uint16_t pins;
-};
-
-static void omap_gpio_set(void *opaque, int line, int level)
-{
-    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
-    uint16_t prev = s->inputs;
-
-    if (level)
-        s->inputs |= 1 << line;
-    else
-        s->inputs &= ~(1 << line);
-
-    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
-                    (1 << line) & s->dir & ~s->mask) {
-        s->ints |= 1 << line;
-        qemu_irq_raise(s->irq);
-    }
-}
-
-static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    switch (offset) {
-    case 0x00:	/* DATA_INPUT */
-        return s->inputs & s->pins;
-
-    case 0x04:	/* DATA_OUTPUT */
-        return s->outputs;
-
-    case 0x08:	/* DIRECTION_CONTROL */
-        return s->dir;
-
-    case 0x0c:	/* INTERRUPT_CONTROL */
-        return s->edge;
-
-    case 0x10:	/* INTERRUPT_MASK */
-        return s->mask;
-
-    case 0x14:	/* INTERRUPT_STATUS */
-        return s->ints;
-
-    case 0x18:	/* PIN_CONTROL (not in OMAP310) */
-        OMAP_BAD_REG(addr);
-        return s->pins;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint16_t diff;
-    int ln;
-
-    switch (offset) {
-    case 0x00:	/* DATA_INPUT */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x04:	/* DATA_OUTPUT */
-        diff = (s->outputs ^ value) & ~s->dir;
-        s->outputs = value;
-        while ((ln = ffs(diff))) {
-            ln --;
-            if (s->handler[ln])
-                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
-            diff &= ~(1 << ln);
-        }
-        break;
-
-    case 0x08:	/* DIRECTION_CONTROL */
-        diff = s->outputs & (s->dir ^ value);
-        s->dir = value;
-
-        value = s->outputs & ~s->dir;
-        while ((ln = ffs(diff))) {
-            ln --;
-            if (s->handler[ln])
-                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
-            diff &= ~(1 << ln);
-        }
-        break;
-
-    case 0x0c:	/* INTERRUPT_CONTROL */
-        s->edge = value;
-        break;
-
-    case 0x10:	/* INTERRUPT_MASK */
-        s->mask = value;
-        break;
-
-    case 0x14:	/* INTERRUPT_STATUS */
-        s->ints &= ~value;
-        if (!s->ints)
-            qemu_irq_lower(s->irq);
-        break;
-
-    case 0x18:	/* PIN_CONTROL (not in OMAP310 TRM) */
-        OMAP_BAD_REG(addr);
-        s->pins = value;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-/* *Some* sources say the memory region is 32-bit.  */
-static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
-    omap_badwidth_read16,
-    omap_gpio_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
-    omap_badwidth_write16,
-    omap_gpio_write,
-    omap_badwidth_write16,
-};
-
-static void omap_gpio_reset(struct omap_gpio_s *s)
-{
-    s->inputs = 0;
-    s->outputs = ~0;
-    s->dir = ~0;
-    s->edge = ~0;
-    s->mask = ~0;
-    s->ints = 0;
-    s->pins = ~0;
-}
-
-struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk)
-{
-    int iomemtype;
-    struct omap_gpio_s *s = (struct omap_gpio_s *)
-            qemu_mallocz(sizeof(struct omap_gpio_s));
-
-    s->irq = irq;
-    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
-    omap_gpio_reset(s);
-
-    iomemtype = cpu_register_io_memory(omap_gpio_readfn,
-                    omap_gpio_writefn, s);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
-
-    return s;
-}
-
-qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
-{
-    return s->in;
-}
-
-void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
-{
-    if (line >= 16 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->handler[line] = handler;
-}
-
 /* MicroWire Interface */
 struct omap_uwire_s {
     qemu_irq txirq;
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
new file mode 100644
index 0000000..a162c1d
--- /dev/null
+++ b/hw/omap_gpio.c
@@ -0,0 +1,202 @@
+/*
+ * TI OMAP processors GPIO emulation.
+ *
+ * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
+ * Copyright (C) 2007-2009 Nokia Corporation
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw.h"
+#include "omap.h"
+/* General-Purpose I/O */
+struct omap_gpio_s {
+    qemu_irq irq;
+    qemu_irq *in;
+    qemu_irq handler[16];
+
+    uint16_t inputs;
+    uint16_t outputs;
+    uint16_t dir;
+    uint16_t edge;
+    uint16_t mask;
+    uint16_t ints;
+    uint16_t pins;
+};
+
+static void omap_gpio_set(void *opaque, int line, int level)
+{
+    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    uint16_t prev = s->inputs;
+
+    if (level)
+        s->inputs |= 1 << line;
+    else
+        s->inputs &= ~(1 << line);
+
+    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
+                    (1 << line) & s->dir & ~s->mask) {
+        s->ints |= 1 << line;
+        qemu_irq_raise(s->irq);
+    }
+}
+
+static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    switch (offset) {
+    case 0x00:	/* DATA_INPUT */
+        return s->inputs & s->pins;
+
+    case 0x04:	/* DATA_OUTPUT */
+        return s->outputs;
+
+    case 0x08:	/* DIRECTION_CONTROL */
+        return s->dir;
+
+    case 0x0c:	/* INTERRUPT_CONTROL */
+        return s->edge;
+
+    case 0x10:	/* INTERRUPT_MASK */
+        return s->mask;
+
+    case 0x14:	/* INTERRUPT_STATUS */
+        return s->ints;
+
+    case 0x18:	/* PIN_CONTROL (not in OMAP310) */
+        OMAP_BAD_REG(addr);
+        return s->pins;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint16_t diff;
+    int ln;
+
+    switch (offset) {
+    case 0x00:	/* DATA_INPUT */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x04:	/* DATA_OUTPUT */
+        diff = (s->outputs ^ value) & ~s->dir;
+        s->outputs = value;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x08:	/* DIRECTION_CONTROL */
+        diff = s->outputs & (s->dir ^ value);
+        s->dir = value;
+
+        value = s->outputs & ~s->dir;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x0c:	/* INTERRUPT_CONTROL */
+        s->edge = value;
+        break;
+
+    case 0x10:	/* INTERRUPT_MASK */
+        s->mask = value;
+        break;
+
+    case 0x14:	/* INTERRUPT_STATUS */
+        s->ints &= ~value;
+        if (!s->ints)
+            qemu_irq_lower(s->irq);
+        break;
+
+    case 0x18:	/* PIN_CONTROL (not in OMAP310 TRM) */
+        OMAP_BAD_REG(addr);
+        s->pins = value;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+/* *Some* sources say the memory region is 32-bit.  */
+static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
+    omap_badwidth_read16,
+    omap_gpio_read,
+    omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
+    omap_badwidth_write16,
+    omap_gpio_write,
+    omap_badwidth_write16,
+};
+
+void omap_gpio_reset(struct omap_gpio_s *s)
+{
+    s->inputs = 0;
+    s->outputs = ~0;
+    s->dir = ~0;
+    s->edge = ~0;
+    s->mask = ~0;
+    s->ints = 0;
+    s->pins = ~0;
+}
+
+struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
+                qemu_irq irq, omap_clk clk)
+{
+    int iomemtype;
+    struct omap_gpio_s *s = (struct omap_gpio_s *)
+            qemu_mallocz(sizeof(struct omap_gpio_s));
+
+    s->irq = irq;
+    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
+    omap_gpio_reset(s);
+
+    iomemtype = cpu_register_io_memory(omap_gpio_readfn,
+                    omap_gpio_writefn, s);
+    cpu_register_physical_memory(base, 0x1000, iomemtype);
+
+    return s;
+}
+
+qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
+{
+    return s->in;
+}
+
+void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
+{
+    if (line >= 16 || line < 0)
+        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
+    s->handler[line] = handler;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 02/12] hw/omap2.c : separate gpio module
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 01/12] hw/omap1.c : separate gpio module cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 03/12] hw/omap2.c : separate gptimer module cmchao
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 hw/omap.h      |    3 +
 hw/omap2.c     |  523 --------------------------------------------------------
 hw/omap_gpio.c |  523 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 526 insertions(+), 523 deletions(-)

diff --git a/hw/omap.h b/hw/omap.h
index ebd166f..a37ee54 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -668,6 +668,7 @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
 void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
 void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
 
+/* omap1 gpio module interface */
 struct omap_gpio_s;
 struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk clk);
@@ -675,9 +676,11 @@ void omap_gpio_reset(struct omap_gpio_s *s);
 qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
 void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
 
+/* omap2 gpio interface */
 struct omap_gpif_s;
 struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
                 qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
+void omap_gpif_reset(struct omap_gpif_s *s);
 qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
 void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
 
diff --git a/hw/omap2.c b/hw/omap2.c
index bd1b35e..bf5539d 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -557,529 +557,6 @@ void omap_synctimer_init(struct omap_target_agent_s *ta,
                       omap_synctimer_readfn, omap_synctimer_writefn, s));
 }
 
-/* General-Purpose Interface of OMAP2 */
-struct omap2_gpio_s {
-    qemu_irq irq[2];
-    qemu_irq wkup;
-    qemu_irq *in;
-    qemu_irq handler[32];
-
-    uint8_t config[2];
-    uint32_t inputs;
-    uint32_t outputs;
-    uint32_t dir;
-    uint32_t level[2];
-    uint32_t edge[2];
-    uint32_t mask[2];
-    uint32_t wumask;
-    uint32_t ints[2];
-    uint32_t debounce;
-    uint8_t delay;
-};
-
-static inline void omap_gpio_module_int_update(struct omap2_gpio_s *s,
-                int line)
-{
-    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
-}
-
-static void omap_gpio_module_wake(struct omap2_gpio_s *s, int line)
-{
-    if (!(s->config[0] & (1 << 2)))			/* ENAWAKEUP */
-        return;
-    if (!(s->config[0] & (3 << 3)))			/* Force Idle */
-        return;
-    if (!(s->wumask & (1 << line)))
-        return;
-
-    qemu_irq_raise(s->wkup);
-}
-
-static inline void omap_gpio_module_out_update(struct omap2_gpio_s *s,
-                uint32_t diff)
-{
-    int ln;
-
-    s->outputs ^= diff;
-    diff &= ~s->dir;
-    while ((ln = ffs(diff))) {
-        ln --;
-        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
-        diff &= ~(1 << ln);
-    }
-}
-
-static void omap_gpio_module_level_update(struct omap2_gpio_s *s, int line)
-{
-    s->ints[line] |= s->dir &
-            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
-    omap_gpio_module_int_update(s, line);
-}
-
-static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line)
-{
-    s->ints[0] |= 1 << line;
-    omap_gpio_module_int_update(s, 0);
-    s->ints[1] |= 1 << line;
-    omap_gpio_module_int_update(s, 1);
-    omap_gpio_module_wake(s, line);
-}
-
-static void omap_gpio_module_set(void *opaque, int line, int level)
-{
-    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
-
-    if (level) {
-        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
-            omap_gpio_module_int(s, line);
-        s->inputs |= 1 << line;
-    } else {
-        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
-            omap_gpio_module_int(s, line);
-        s->inputs &= ~(1 << line);
-    }
-}
-
-static void omap_gpio_module_reset(struct omap2_gpio_s *s)
-{
-    s->config[0] = 0;
-    s->config[1] = 2;
-    s->ints[0] = 0;
-    s->ints[1] = 0;
-    s->mask[0] = 0;
-    s->mask[1] = 0;
-    s->wumask = 0;
-    s->dir = ~0;
-    s->level[0] = 0;
-    s->level[1] = 0;
-    s->edge[0] = 0;
-    s->edge[1] = 0;
-    s->debounce = 0;
-    s->delay = 0;
-}
-
-static uint32_t omap_gpio_module_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* GPIO_REVISION */
-        return 0x18;
-
-    case 0x10:	/* GPIO_SYSCONFIG */
-        return s->config[0];
-
-    case 0x14:	/* GPIO_SYSSTATUS */
-        return 0x01;
-
-    case 0x18:	/* GPIO_IRQSTATUS1 */
-        return s->ints[0];
-
-    case 0x1c:	/* GPIO_IRQENABLE1 */
-    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
-    case 0x64:	/* GPIO_SETIRQENABLE1 */
-        return s->mask[0];
-
-    case 0x20:	/* GPIO_WAKEUPENABLE */
-    case 0x80:	/* GPIO_CLEARWKUENA */
-    case 0x84:	/* GPIO_SETWKUENA */
-        return s->wumask;
-
-    case 0x28:	/* GPIO_IRQSTATUS2 */
-        return s->ints[1];
-
-    case 0x2c:	/* GPIO_IRQENABLE2 */
-    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
-    case 0x74:	/* GPIO_SETIREQNEABLE2 */
-        return s->mask[1];
-
-    case 0x30:	/* GPIO_CTRL */
-        return s->config[1];
-
-    case 0x34:	/* GPIO_OE */
-        return s->dir;
-
-    case 0x38:	/* GPIO_DATAIN */
-        return s->inputs;
-
-    case 0x3c:	/* GPIO_DATAOUT */
-    case 0x90:	/* GPIO_CLEARDATAOUT */
-    case 0x94:	/* GPIO_SETDATAOUT */
-        return s->outputs;
-
-    case 0x40:	/* GPIO_LEVELDETECT0 */
-        return s->level[0];
-
-    case 0x44:	/* GPIO_LEVELDETECT1 */
-        return s->level[1];
-
-    case 0x48:	/* GPIO_RISINGDETECT */
-        return s->edge[0];
-
-    case 0x4c:	/* GPIO_FALLINGDETECT */
-        return s->edge[1];
-
-    case 0x50:	/* GPIO_DEBOUNCENABLE */
-        return s->debounce;
-
-    case 0x54:	/* GPIO_DEBOUNCINGTIME */
-        return s->delay;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
-    uint32_t diff;
-    int ln;
-
-    switch (addr) {
-    case 0x00:	/* GPIO_REVISION */
-    case 0x14:	/* GPIO_SYSSTATUS */
-    case 0x38:	/* GPIO_DATAIN */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x10:	/* GPIO_SYSCONFIG */
-        if (((value >> 3) & 3) == 3)
-            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
-        if (value & 2)
-            omap_gpio_module_reset(s);
-        s->config[0] = value & 0x1d;
-        break;
-
-    case 0x18:	/* GPIO_IRQSTATUS1 */
-        if (s->ints[0] & value) {
-            s->ints[0] &= ~value;
-            omap_gpio_module_level_update(s, 0);
-        }
-        break;
-
-    case 0x1c:	/* GPIO_IRQENABLE1 */
-        s->mask[0] = value;
-        omap_gpio_module_int_update(s, 0);
-        break;
-
-    case 0x20:	/* GPIO_WAKEUPENABLE */
-        s->wumask = value;
-        break;
-
-    case 0x28:	/* GPIO_IRQSTATUS2 */
-        if (s->ints[1] & value) {
-            s->ints[1] &= ~value;
-            omap_gpio_module_level_update(s, 1);
-        }
-        break;
-
-    case 0x2c:	/* GPIO_IRQENABLE2 */
-        s->mask[1] = value;
-        omap_gpio_module_int_update(s, 1);
-        break;
-
-    case 0x30:	/* GPIO_CTRL */
-        s->config[1] = value & 7;
-        break;
-
-    case 0x34:	/* GPIO_OE */
-        diff = s->outputs & (s->dir ^ value);
-        s->dir = value;
-
-        value = s->outputs & ~s->dir;
-        while ((ln = ffs(diff))) {
-            diff &= ~(1 <<-- ln);
-            qemu_set_irq(s->handler[ln], (value >> ln) & 1);
-        }
-
-        omap_gpio_module_level_update(s, 0);
-        omap_gpio_module_level_update(s, 1);
-        break;
-
-    case 0x3c:	/* GPIO_DATAOUT */
-        omap_gpio_module_out_update(s, s->outputs ^ value);
-        break;
-
-    case 0x40:	/* GPIO_LEVELDETECT0 */
-        s->level[0] = value;
-        omap_gpio_module_level_update(s, 0);
-        omap_gpio_module_level_update(s, 1);
-        break;
-
-    case 0x44:	/* GPIO_LEVELDETECT1 */
-        s->level[1] = value;
-        omap_gpio_module_level_update(s, 0);
-        omap_gpio_module_level_update(s, 1);
-        break;
-
-    case 0x48:	/* GPIO_RISINGDETECT */
-        s->edge[0] = value;
-        break;
-
-    case 0x4c:	/* GPIO_FALLINGDETECT */
-        s->edge[1] = value;
-        break;
-
-    case 0x50:	/* GPIO_DEBOUNCENABLE */
-        s->debounce = value;
-        break;
-
-    case 0x54:	/* GPIO_DEBOUNCINGTIME */
-        s->delay = value;
-        break;
-
-    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
-        s->mask[0] &= ~value;
-        omap_gpio_module_int_update(s, 0);
-        break;
-
-    case 0x64:	/* GPIO_SETIRQENABLE1 */
-        s->mask[0] |= value;
-        omap_gpio_module_int_update(s, 0);
-        break;
-
-    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
-        s->mask[1] &= ~value;
-        omap_gpio_module_int_update(s, 1);
-        break;
-
-    case 0x74:	/* GPIO_SETIREQNEABLE2 */
-        s->mask[1] |= value;
-        omap_gpio_module_int_update(s, 1);
-        break;
-
-    case 0x80:	/* GPIO_CLEARWKUENA */
-        s->wumask &= ~value;
-        break;
-
-    case 0x84:	/* GPIO_SETWKUENA */
-        s->wumask |= value;
-        break;
-
-    case 0x90:	/* GPIO_CLEARDATAOUT */
-        omap_gpio_module_out_update(s, s->outputs & value);
-        break;
-
-    case 0x94:	/* GPIO_SETDATAOUT */
-        omap_gpio_module_out_update(s, ~s->outputs & value);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static uint32_t omap_gpio_module_readp(void *opaque, target_phys_addr_t addr)
-{
-    return omap_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
-}
-
-static void omap_gpio_module_writep(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    uint32_t cur = 0;
-    uint32_t mask = 0xffff;
-
-    switch (addr & ~3) {
-    case 0x00:	/* GPIO_REVISION */
-    case 0x14:	/* GPIO_SYSSTATUS */
-    case 0x38:	/* GPIO_DATAIN */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x10:	/* GPIO_SYSCONFIG */
-    case 0x1c:	/* GPIO_IRQENABLE1 */
-    case 0x20:	/* GPIO_WAKEUPENABLE */
-    case 0x2c:	/* GPIO_IRQENABLE2 */
-    case 0x30:	/* GPIO_CTRL */
-    case 0x34:	/* GPIO_OE */
-    case 0x3c:	/* GPIO_DATAOUT */
-    case 0x40:	/* GPIO_LEVELDETECT0 */
-    case 0x44:	/* GPIO_LEVELDETECT1 */
-    case 0x48:	/* GPIO_RISINGDETECT */
-    case 0x4c:	/* GPIO_FALLINGDETECT */
-    case 0x50:	/* GPIO_DEBOUNCENABLE */
-    case 0x54:	/* GPIO_DEBOUNCINGTIME */
-        cur = omap_gpio_module_read(opaque, addr & ~3) &
-                ~(mask << ((addr & 3) << 3));
-
-        /* Fall through.  */
-    case 0x18:	/* GPIO_IRQSTATUS1 */
-    case 0x28:	/* GPIO_IRQSTATUS2 */
-    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
-    case 0x64:	/* GPIO_SETIRQENABLE1 */
-    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
-    case 0x74:	/* GPIO_SETIREQNEABLE2 */
-    case 0x80:	/* GPIO_CLEARWKUENA */
-    case 0x84:	/* GPIO_SETWKUENA */
-    case 0x90:	/* GPIO_CLEARDATAOUT */
-    case 0x94:	/* GPIO_SETDATAOUT */
-        value <<= (addr & 3) << 3;
-        omap_gpio_module_write(opaque, addr, cur | value);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static CPUReadMemoryFunc * const omap_gpio_module_readfn[] = {
-    omap_gpio_module_readp,
-    omap_gpio_module_readp,
-    omap_gpio_module_read,
-};
-
-static CPUWriteMemoryFunc * const omap_gpio_module_writefn[] = {
-    omap_gpio_module_writep,
-    omap_gpio_module_writep,
-    omap_gpio_module_write,
-};
-
-static void omap_gpio_module_init(struct omap2_gpio_s *s,
-                struct omap_target_agent_s *ta, int region,
-                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
-                omap_clk fclk, omap_clk iclk)
-{
-    int iomemtype;
-
-    s->irq[0] = mpu;
-    s->irq[1] = dsp;
-    s->wkup = wkup;
-    s->in = qemu_allocate_irqs(omap_gpio_module_set, s, 32);
-
-    iomemtype = l4_register_io_memory(omap_gpio_module_readfn,
-                    omap_gpio_module_writefn, s);
-    omap_l4_attach(ta, region, iomemtype);
-}
-
-struct omap_gpif_s {
-    struct omap2_gpio_s module[5];
-    int modules;
-
-    int autoidle;
-    int gpo;
-};
-
-static void omap_gpif_reset(struct omap_gpif_s *s)
-{
-    int i;
-
-    for (i = 0; i < s->modules; i ++)
-        omap_gpio_module_reset(s->module + i);
-
-    s->autoidle = 0;
-    s->gpo = 0;
-}
-
-static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* IPGENERICOCPSPL_REVISION */
-        return 0x18;
-
-    case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */
-        return s->autoidle;
-
-    case 0x14:	/* IPGENERICOCPSPL_SYSSTATUS */
-        return 0x01;
-
-    case 0x18:	/* IPGENERICOCPSPL_IRQSTATUS */
-        return 0x00;
-
-    case 0x40:	/* IPGENERICOCPSPL_GPO */
-        return s->gpo;
-
-    case 0x50:	/* IPGENERICOCPSPL_GPI */
-        return 0x00;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* IPGENERICOCPSPL_REVISION */
-    case 0x14:	/* IPGENERICOCPSPL_SYSSTATUS */
-    case 0x18:	/* IPGENERICOCPSPL_IRQSTATUS */
-    case 0x50:	/* IPGENERICOCPSPL_GPI */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */
-        if (value & (1 << 1))					/* SOFTRESET */
-            omap_gpif_reset(s);
-        s->autoidle = value & 1;
-        break;
-
-    case 0x40:	/* IPGENERICOCPSPL_GPO */
-        s->gpo = value & 1;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
-    omap_gpif_top_read,
-    omap_gpif_top_read,
-    omap_gpif_top_read,
-};
-
-static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
-    omap_gpif_top_write,
-    omap_gpif_top_write,
-    omap_gpif_top_write,
-};
-
-struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
-                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
-{
-    int iomemtype, i;
-    struct omap_gpif_s *s = (struct omap_gpif_s *)
-            qemu_mallocz(sizeof(struct omap_gpif_s));
-    int region[4] = { 0, 2, 4, 5 };
-
-    s->modules = modules;
-    for (i = 0; i < modules; i ++)
-        omap_gpio_module_init(s->module + i, ta, region[i],
-                              irq[i], NULL, NULL, fclk[i], iclk);
-
-    omap_gpif_reset(s);
-
-    iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
-                    omap_gpif_top_writefn, s);
-    omap_l4_attach(ta, 1, iomemtype);
-
-    return s;
-}
-
-qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
-{
-    if (start >= s->modules * 32 || start < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
-    return s->module[start >> 5].in + (start & 31);
-}
-
-void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
-{
-    if (line >= s->modules * 32 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->module[line >> 5].handler[line & 31] = handler;
-}
-
 /* Multichannel SPI */
 struct omap_mcspi_s {
     qemu_irq irq;
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index a162c1d..d978c7a 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -200,3 +200,526 @@ void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
         hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
     s->handler[line] = handler;
 }
+
+/* General-Purpose Interface of OMAP2 */
+struct omap2_gpio_s {
+    qemu_irq irq[2];
+    qemu_irq wkup;
+    qemu_irq *in;
+    qemu_irq handler[32];
+
+    uint8_t config[2];
+    uint32_t inputs;
+    uint32_t outputs;
+    uint32_t dir;
+    uint32_t level[2];
+    uint32_t edge[2];
+    uint32_t mask[2];
+    uint32_t wumask;
+    uint32_t ints[2];
+    uint32_t debounce;
+    uint8_t delay;
+};
+
+static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
+                int line)
+{
+    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
+}
+
+static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
+{
+    if (!(s->config[0] & (1 << 2)))			/* ENAWAKEUP */
+        return;
+    if (!(s->config[0] & (3 << 3)))			/* Force Idle */
+        return;
+    if (!(s->wumask & (1 << line)))
+        return;
+
+    qemu_irq_raise(s->wkup);
+}
+
+static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
+                uint32_t diff)
+{
+    int ln;
+
+    s->outputs ^= diff;
+    diff &= ~s->dir;
+    while ((ln = ffs(diff))) {
+        ln --;
+        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
+        diff &= ~(1 << ln);
+    }
+}
+
+static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
+{
+    s->ints[line] |= s->dir &
+            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
+    omap2_gpio_module_int_update(s, line);
+}
+
+static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
+{
+    s->ints[0] |= 1 << line;
+    omap2_gpio_module_int_update(s, 0);
+    s->ints[1] |= 1 << line;
+    omap2_gpio_module_int_update(s, 1);
+    omap2_gpio_module_wake(s, line);
+}
+
+static void omap2_gpio_module_set(void *opaque, int line, int level)
+{
+    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
+
+    if (level) {
+        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
+            omap2_gpio_module_int(s, line);
+        s->inputs |= 1 << line;
+    } else {
+        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
+            omap2_gpio_module_int(s, line);
+        s->inputs &= ~(1 << line);
+    }
+}
+
+static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
+{
+    s->config[0] = 0;
+    s->config[1] = 2;
+    s->ints[0] = 0;
+    s->ints[1] = 0;
+    s->mask[0] = 0;
+    s->mask[1] = 0;
+    s->wumask = 0;
+    s->dir = ~0;
+    s->level[0] = 0;
+    s->level[1] = 0;
+    s->edge[0] = 0;
+    s->edge[1] = 0;
+    s->debounce = 0;
+    s->delay = 0;
+}
+
+static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* GPIO_REVISION */
+        return 0x18;
+
+    case 0x10:	/* GPIO_SYSCONFIG */
+        return s->config[0];
+
+    case 0x14:	/* GPIO_SYSSTATUS */
+        return 0x01;
+
+    case 0x18:	/* GPIO_IRQSTATUS1 */
+        return s->ints[0];
+
+    case 0x1c:	/* GPIO_IRQENABLE1 */
+    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
+    case 0x64:	/* GPIO_SETIRQENABLE1 */
+        return s->mask[0];
+
+    case 0x20:	/* GPIO_WAKEUPENABLE */
+    case 0x80:	/* GPIO_CLEARWKUENA */
+    case 0x84:	/* GPIO_SETWKUENA */
+        return s->wumask;
+
+    case 0x28:	/* GPIO_IRQSTATUS2 */
+        return s->ints[1];
+
+    case 0x2c:	/* GPIO_IRQENABLE2 */
+    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
+    case 0x74:	/* GPIO_SETIREQNEABLE2 */
+        return s->mask[1];
+
+    case 0x30:	/* GPIO_CTRL */
+        return s->config[1];
+
+    case 0x34:	/* GPIO_OE */
+        return s->dir;
+
+    case 0x38:	/* GPIO_DATAIN */
+        return s->inputs;
+
+    case 0x3c:	/* GPIO_DATAOUT */
+    case 0x90:	/* GPIO_CLEARDATAOUT */
+    case 0x94:	/* GPIO_SETDATAOUT */
+        return s->outputs;
+
+    case 0x40:	/* GPIO_LEVELDETECT0 */
+        return s->level[0];
+
+    case 0x44:	/* GPIO_LEVELDETECT1 */
+        return s->level[1];
+
+    case 0x48:	/* GPIO_RISINGDETECT */
+        return s->edge[0];
+
+    case 0x4c:	/* GPIO_FALLINGDETECT */
+        return s->edge[1];
+
+    case 0x50:	/* GPIO_DEBOUNCENABLE */
+        return s->debounce;
+
+    case 0x54:	/* GPIO_DEBOUNCINGTIME */
+        return s->delay;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
+    uint32_t diff;
+    int ln;
+
+    switch (addr) {
+    case 0x00:	/* GPIO_REVISION */
+    case 0x14:	/* GPIO_SYSSTATUS */
+    case 0x38:	/* GPIO_DATAIN */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x10:	/* GPIO_SYSCONFIG */
+        if (((value >> 3) & 3) == 3)
+            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
+        if (value & 2)
+            omap2_gpio_module_reset(s);
+        s->config[0] = value & 0x1d;
+        break;
+
+    case 0x18:	/* GPIO_IRQSTATUS1 */
+        if (s->ints[0] & value) {
+            s->ints[0] &= ~value;
+            omap2_gpio_module_level_update(s, 0);
+        }
+        break;
+
+    case 0x1c:	/* GPIO_IRQENABLE1 */
+        s->mask[0] = value;
+        omap2_gpio_module_int_update(s, 0);
+        break;
+
+    case 0x20:	/* GPIO_WAKEUPENABLE */
+        s->wumask = value;
+        break;
+
+    case 0x28:	/* GPIO_IRQSTATUS2 */
+        if (s->ints[1] & value) {
+            s->ints[1] &= ~value;
+            omap2_gpio_module_level_update(s, 1);
+        }
+        break;
+
+    case 0x2c:	/* GPIO_IRQENABLE2 */
+        s->mask[1] = value;
+        omap2_gpio_module_int_update(s, 1);
+        break;
+
+    case 0x30:	/* GPIO_CTRL */
+        s->config[1] = value & 7;
+        break;
+
+    case 0x34:	/* GPIO_OE */
+        diff = s->outputs & (s->dir ^ value);
+        s->dir = value;
+
+        value = s->outputs & ~s->dir;
+        while ((ln = ffs(diff))) {
+            diff &= ~(1 <<-- ln);
+            qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+        }
+
+        omap2_gpio_module_level_update(s, 0);
+        omap2_gpio_module_level_update(s, 1);
+        break;
+
+    case 0x3c:	/* GPIO_DATAOUT */
+        omap2_gpio_module_out_update(s, s->outputs ^ value);
+        break;
+
+    case 0x40:	/* GPIO_LEVELDETECT0 */
+        s->level[0] = value;
+        omap2_gpio_module_level_update(s, 0);
+        omap2_gpio_module_level_update(s, 1);
+        break;
+
+    case 0x44:	/* GPIO_LEVELDETECT1 */
+        s->level[1] = value;
+        omap2_gpio_module_level_update(s, 0);
+        omap2_gpio_module_level_update(s, 1);
+        break;
+
+    case 0x48:	/* GPIO_RISINGDETECT */
+        s->edge[0] = value;
+        break;
+
+    case 0x4c:	/* GPIO_FALLINGDETECT */
+        s->edge[1] = value;
+        break;
+
+    case 0x50:	/* GPIO_DEBOUNCENABLE */
+        s->debounce = value;
+        break;
+
+    case 0x54:	/* GPIO_DEBOUNCINGTIME */
+        s->delay = value;
+        break;
+
+    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
+        s->mask[0] &= ~value;
+        omap2_gpio_module_int_update(s, 0);
+        break;
+
+    case 0x64:	/* GPIO_SETIRQENABLE1 */
+        s->mask[0] |= value;
+        omap2_gpio_module_int_update(s, 0);
+        break;
+
+    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
+        s->mask[1] &= ~value;
+        omap2_gpio_module_int_update(s, 1);
+        break;
+
+    case 0x74:	/* GPIO_SETIREQNEABLE2 */
+        s->mask[1] |= value;
+        omap2_gpio_module_int_update(s, 1);
+        break;
+
+    case 0x80:	/* GPIO_CLEARWKUENA */
+        s->wumask &= ~value;
+        break;
+
+    case 0x84:	/* GPIO_SETWKUENA */
+        s->wumask |= value;
+        break;
+
+    case 0x90:	/* GPIO_CLEARDATAOUT */
+        omap2_gpio_module_out_update(s, s->outputs & value);
+        break;
+
+    case 0x94:	/* GPIO_SETDATAOUT */
+        omap2_gpio_module_out_update(s, ~s->outputs & value);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
+{
+    return omap2_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
+}
+
+static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    uint32_t cur = 0;
+    uint32_t mask = 0xffff;
+
+    switch (addr & ~3) {
+    case 0x00:	/* GPIO_REVISION */
+    case 0x14:	/* GPIO_SYSSTATUS */
+    case 0x38:	/* GPIO_DATAIN */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x10:	/* GPIO_SYSCONFIG */
+    case 0x1c:	/* GPIO_IRQENABLE1 */
+    case 0x20:	/* GPIO_WAKEUPENABLE */
+    case 0x2c:	/* GPIO_IRQENABLE2 */
+    case 0x30:	/* GPIO_CTRL */
+    case 0x34:	/* GPIO_OE */
+    case 0x3c:	/* GPIO_DATAOUT */
+    case 0x40:	/* GPIO_LEVELDETECT0 */
+    case 0x44:	/* GPIO_LEVELDETECT1 */
+    case 0x48:	/* GPIO_RISINGDETECT */
+    case 0x4c:	/* GPIO_FALLINGDETECT */
+    case 0x50:	/* GPIO_DEBOUNCENABLE */
+    case 0x54:	/* GPIO_DEBOUNCINGTIME */
+        cur = omap2_gpio_module_read(opaque, addr & ~3) &
+                ~(mask << ((addr & 3) << 3));
+
+        /* Fall through.  */
+    case 0x18:	/* GPIO_IRQSTATUS1 */
+    case 0x28:	/* GPIO_IRQSTATUS2 */
+    case 0x60:	/* GPIO_CLEARIRQENABLE1 */
+    case 0x64:	/* GPIO_SETIRQENABLE1 */
+    case 0x70:	/* GPIO_CLEARIRQENABLE2 */
+    case 0x74:	/* GPIO_SETIREQNEABLE2 */
+    case 0x80:	/* GPIO_CLEARWKUENA */
+    case 0x84:	/* GPIO_SETWKUENA */
+    case 0x90:	/* GPIO_CLEARDATAOUT */
+    case 0x94:	/* GPIO_SETDATAOUT */
+        value <<= (addr & 3) << 3;
+        omap2_gpio_module_write(opaque, addr, cur | value);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
+    omap2_gpio_module_readp,
+    omap2_gpio_module_readp,
+    omap2_gpio_module_read,
+};
+
+static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
+    omap2_gpio_module_writep,
+    omap2_gpio_module_writep,
+    omap2_gpio_module_write,
+};
+
+static void omap2_gpio_module_init(struct omap2_gpio_s *s,
+                struct omap_target_agent_s *ta, int region,
+                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
+                omap_clk fclk, omap_clk iclk)
+{
+    int iomemtype;
+
+    s->irq[0] = mpu;
+    s->irq[1] = dsp;
+    s->wkup = wkup;
+    s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
+
+    iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
+                    omap2_gpio_module_writefn, s);
+    omap_l4_attach(ta, region, iomemtype);
+}
+
+struct omap_gpif_s {
+    struct omap2_gpio_s module[5];
+    int modules;
+
+    int autoidle;
+    int gpo;
+};
+
+void omap_gpif_reset(struct omap_gpif_s *s)
+{
+    int i;
+
+    for (i = 0; i < s->modules; i ++)
+        omap2_gpio_module_reset(s->module + i);
+
+    s->autoidle = 0;
+    s->gpo = 0;
+}
+
+static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* IPGENERICOCPSPL_REVISION */
+        return 0x18;
+
+    case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */
+        return s->autoidle;
+
+    case 0x14:	/* IPGENERICOCPSPL_SYSSTATUS */
+        return 0x01;
+
+    case 0x18:	/* IPGENERICOCPSPL_IRQSTATUS */
+        return 0x00;
+
+    case 0x40:	/* IPGENERICOCPSPL_GPO */
+        return s->gpo;
+
+    case 0x50:	/* IPGENERICOCPSPL_GPI */
+        return 0x00;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* IPGENERICOCPSPL_REVISION */
+    case 0x14:	/* IPGENERICOCPSPL_SYSSTATUS */
+    case 0x18:	/* IPGENERICOCPSPL_IRQSTATUS */
+    case 0x50:	/* IPGENERICOCPSPL_GPI */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */
+        if (value & (1 << 1))					/* SOFTRESET */
+            omap_gpif_reset(s);
+        s->autoidle = value & 1;
+        break;
+
+    case 0x40:	/* IPGENERICOCPSPL_GPO */
+        s->gpo = value & 1;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
+    omap_gpif_top_read,
+    omap_gpif_top_read,
+    omap_gpif_top_read,
+};
+
+static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
+    omap_gpif_top_write,
+    omap_gpif_top_write,
+    omap_gpif_top_write,
+};
+
+struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
+                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
+{
+    int iomemtype, i;
+    struct omap_gpif_s *s = (struct omap_gpif_s *)
+            qemu_mallocz(sizeof(struct omap_gpif_s));
+    int region[4] = { 0, 2, 4, 5 };
+
+    s->modules = modules;
+    for (i = 0; i < modules; i ++)
+        omap2_gpio_module_init(s->module + i, ta, region[i],
+                              irq[i], NULL, NULL, fclk[i], iclk);
+
+    omap_gpif_reset(s);
+
+    iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
+                    omap_gpif_top_writefn, s);
+    omap_l4_attach(ta, 1, iomemtype);
+
+    return s;
+}
+
+qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
+{
+    if (start >= s->modules * 32 || start < 0)
+        hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
+    return s->module[start >> 5].in + (start & 31);
+}
+
+void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
+{
+    if (line >= s->modules * 32 || line < 0)
+        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
+    s->module[line >> 5].handler[line & 31] = handler;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 03/12] hw/omap2.c : separate gptimer module
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 01/12] hw/omap1.c : separate gpio module cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 02/12] hw/omap2.c " cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 04/12] hw/omap2.c : separate synctimer module cmchao
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target   |    2 +-
 hw/omap.h         |    2 +
 hw/omap2.c        |  462 --------------------------------------------------
 hw/omap_gptimer.c |  484 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 487 insertions(+), 463 deletions(-)
 create mode 100644 hw/omap_gptimer.c

diff --git a/Makefile.target b/Makefile.target
index eb5c84a..c29dee0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -264,7 +264,7 @@ 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
-obj-arm-y += omap2.o omap_dss.o soc_dma.o
+obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
diff --git a/hw/omap.h b/hw/omap.h
index a37ee54..14fdb6f 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -631,9 +631,11 @@ struct omap_mpu_timer_s;
 struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk clk);
 
+/* OMAP2 gp timer */
 struct omap_gp_timer_s;
 struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk);
+void omap_gp_timer_reset(struct omap_gp_timer_s *s);
 
 struct omap_watchdog_timer_s;
 struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
diff --git a/hw/omap2.c b/hw/omap2.c
index bf5539d..890397b 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -27,468 +27,6 @@
 #include "soc_dma.h"
 #include "audio/audio.h"
 
-/* GP timers */
-struct omap_gp_timer_s {
-    qemu_irq irq;
-    qemu_irq wkup;
-    qemu_irq in;
-    qemu_irq out;
-    omap_clk clk;
-    QEMUTimer *timer;
-    QEMUTimer *match;
-    struct omap_target_agent_s *ta;
-
-    int in_val;
-    int out_val;
-    int64_t time;
-    int64_t rate;
-    int64_t ticks_per_sec;
-
-    int16_t config;
-    int status;
-    int it_ena;
-    int wu_ena;
-    int enable;
-    int inout;
-    int capt2;
-    int pt;
-    enum {
-        gpt_trigger_none, gpt_trigger_overflow, gpt_trigger_both
-    } trigger;
-    enum {
-        gpt_capture_none, gpt_capture_rising,
-        gpt_capture_falling, gpt_capture_both
-    } capture;
-    int scpwm;
-    int ce;
-    int pre;
-    int ptv;
-    int ar;
-    int st;
-    int posted;
-    uint32_t val;
-    uint32_t load_val;
-    uint32_t capture_val[2];
-    uint32_t match_val;
-    int capt_num;
-
-    uint16_t writeh;	/* LSB */
-    uint16_t readh;	/* MSB */
-};
-
-#define GPT_TCAR_IT	(1 << 2)
-#define GPT_OVF_IT	(1 << 1)
-#define GPT_MAT_IT	(1 << 0)
-
-static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it)
-{
-    if (timer->it_ena & it) {
-        if (!timer->status)
-            qemu_irq_raise(timer->irq);
-
-        timer->status |= it;
-        /* Or are the status bits set even when masked?
-         * i.e. is masking applied before or after the status register?  */
-    }
-
-    if (timer->wu_ena & it)
-        qemu_irq_pulse(timer->wkup);
-}
-
-static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level)
-{
-    if (!timer->inout && timer->out_val != level) {
-        timer->out_val = level;
-        qemu_set_irq(timer->out, level);
-    }
-}
-
-static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer)
-{
-    uint64_t distance;
-
-    if (timer->st && timer->rate) {
-        distance = qemu_get_clock(vm_clock) - timer->time;
-        distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
-
-        if (distance >= 0xffffffff - timer->val)
-            return 0xffffffff;
-        else
-            return timer->val + distance;
-    } else
-        return timer->val;
-}
-
-static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer)
-{
-    if (timer->st) {
-        timer->val = omap_gp_timer_read(timer);
-        timer->time = qemu_get_clock(vm_clock);
-    }
-}
-
-static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer)
-{
-    int64_t expires, matches;
-
-    if (timer->st && timer->rate) {
-        expires = muldiv64(0x100000000ll - timer->val,
-                        timer->ticks_per_sec, timer->rate);
-        qemu_mod_timer(timer->timer, timer->time + expires);
-
-        if (timer->ce && timer->match_val >= timer->val) {
-            matches = muldiv64(timer->match_val - timer->val,
-                            timer->ticks_per_sec, timer->rate);
-            qemu_mod_timer(timer->match, timer->time + matches);
-        } else
-            qemu_del_timer(timer->match);
-    } else {
-        qemu_del_timer(timer->timer);
-        qemu_del_timer(timer->match);
-        omap_gp_timer_out(timer, timer->scpwm);
-    }
-}
-
-static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer)
-{
-    if (timer->pt)
-        /* TODO in overflow-and-match mode if the first event to
-         * occur is the match, don't toggle.  */
-        omap_gp_timer_out(timer, !timer->out_val);
-    else
-        /* TODO inverted pulse on timer->out_val == 1?  */
-        qemu_irq_pulse(timer->out);
-}
-
-static void omap_gp_timer_tick(void *opaque)
-{
-    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-
-    if (!timer->ar) {
-        timer->st = 0;
-        timer->val = 0;
-    } else {
-        timer->val = timer->load_val;
-        timer->time = qemu_get_clock(vm_clock);
-    }
-
-    if (timer->trigger == gpt_trigger_overflow ||
-                    timer->trigger == gpt_trigger_both)
-        omap_gp_timer_trigger(timer);
-
-    omap_gp_timer_intr(timer, GPT_OVF_IT);
-    omap_gp_timer_update(timer);
-}
-
-static void omap_gp_timer_match(void *opaque)
-{
-    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-
-    if (timer->trigger == gpt_trigger_both)
-        omap_gp_timer_trigger(timer);
-
-    omap_gp_timer_intr(timer, GPT_MAT_IT);
-}
-
-static void omap_gp_timer_input(void *opaque, int line, int on)
-{
-    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-    int trigger;
-
-    switch (s->capture) {
-    default:
-    case gpt_capture_none:
-        trigger = 0;
-        break;
-    case gpt_capture_rising:
-        trigger = !s->in_val && on;
-        break;
-    case gpt_capture_falling:
-        trigger = s->in_val && !on;
-        break;
-    case gpt_capture_both:
-        trigger = (s->in_val == !on);
-        break;
-    }
-    s->in_val = on;
-
-    if (s->inout && trigger && s->capt_num < 2) {
-        s->capture_val[s->capt_num] = omap_gp_timer_read(s);
-
-        if (s->capt2 == s->capt_num ++)
-            omap_gp_timer_intr(s, GPT_TCAR_IT);
-    }
-}
-
-static void omap_gp_timer_clk_update(void *opaque, int line, int on)
-{
-    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-
-    omap_gp_timer_sync(timer);
-    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
-    omap_gp_timer_update(timer);
-}
-
-static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
-{
-    omap_clk_adduser(timer->clk,
-                    qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]);
-    timer->rate = omap_clk_getrate(timer->clk);
-}
-
-static void omap_gp_timer_reset(struct omap_gp_timer_s *s)
-{
-    s->config = 0x000;
-    s->status = 0;
-    s->it_ena = 0;
-    s->wu_ena = 0;
-    s->inout = 0;
-    s->capt2 = 0;
-    s->capt_num = 0;
-    s->pt = 0;
-    s->trigger = gpt_trigger_none;
-    s->capture = gpt_capture_none;
-    s->scpwm = 0;
-    s->ce = 0;
-    s->pre = 0;
-    s->ptv = 0;
-    s->ar = 0;
-    s->st = 0;
-    s->posted = 1;
-    s->val = 0x00000000;
-    s->load_val = 0x00000000;
-    s->capture_val[0] = 0x00000000;
-    s->capture_val[1] = 0x00000000;
-    s->match_val = 0x00000000;
-    omap_gp_timer_update(s);
-}
-
-static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* TIDR */
-        return 0x21;
-
-    case 0x10:	/* TIOCP_CFG */
-        return s->config;
-
-    case 0x14:	/* TISTAT */
-        /* ??? When's this bit reset? */
-        return 1;						/* RESETDONE */
-
-    case 0x18:	/* TISR */
-        return s->status;
-
-    case 0x1c:	/* TIER */
-        return s->it_ena;
-
-    case 0x20:	/* TWER */
-        return s->wu_ena;
-
-    case 0x24:	/* TCLR */
-        return (s->inout << 14) |
-                (s->capt2 << 13) |
-                (s->pt << 12) |
-                (s->trigger << 10) |
-                (s->capture << 8) |
-                (s->scpwm << 7) |
-                (s->ce << 6) |
-                (s->pre << 5) |
-                (s->ptv << 2) |
-                (s->ar << 1) |
-                (s->st << 0);
-
-    case 0x28:	/* TCRR */
-        return omap_gp_timer_read(s);
-
-    case 0x2c:	/* TLDR */
-        return s->load_val;
-
-    case 0x30:	/* TTGR */
-        return 0xffffffff;
-
-    case 0x34:	/* TWPS */
-        return 0x00000000;	/* No posted writes pending.  */
-
-    case 0x38:	/* TMAR */
-        return s->match_val;
-
-    case 0x3c:	/* TCAR1 */
-        return s->capture_val[0];
-
-    case 0x40:	/* TSICR */
-        return s->posted << 2;
-
-    case 0x44:	/* TCAR2 */
-        return s->capture_val[1];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-    uint32_t ret;
-
-    if (addr & 2)
-        return s->readh;
-    else {
-        ret = omap_gp_timer_readw(opaque, addr);
-        s->readh = ret >> 16;
-        return ret & 0xffff;
-    }
-}
-
-static CPUReadMemoryFunc * const omap_gp_timer_readfn[] = {
-    omap_badwidth_read32,
-    omap_gp_timer_readh,
-    omap_gp_timer_readw,
-};
-
-static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* TIDR */
-    case 0x14:	/* TISTAT */
-    case 0x34:	/* TWPS */
-    case 0x3c:	/* TCAR1 */
-    case 0x44:	/* TCAR2 */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x10:	/* TIOCP_CFG */
-        s->config = value & 0x33d;
-        if (((value >> 3) & 3) == 3)				/* IDLEMODE */
-            fprintf(stderr, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
-                            __FUNCTION__);
-        if (value & 2)						/* SOFTRESET */
-            omap_gp_timer_reset(s);
-        break;
-
-    case 0x18:	/* TISR */
-        if (value & GPT_TCAR_IT)
-            s->capt_num = 0;
-        if (s->status && !(s->status &= ~value))
-            qemu_irq_lower(s->irq);
-        break;
-
-    case 0x1c:	/* TIER */
-        s->it_ena = value & 7;
-        break;
-
-    case 0x20:	/* TWER */
-        s->wu_ena = value & 7;
-        break;
-
-    case 0x24:	/* TCLR */
-        omap_gp_timer_sync(s);
-        s->inout = (value >> 14) & 1;
-        s->capt2 = (value >> 13) & 1;
-        s->pt = (value >> 12) & 1;
-        s->trigger = (value >> 10) & 3;
-        if (s->capture == gpt_capture_none &&
-                        ((value >> 8) & 3) != gpt_capture_none)
-            s->capt_num = 0;
-        s->capture = (value >> 8) & 3;
-        s->scpwm = (value >> 7) & 1;
-        s->ce = (value >> 6) & 1;
-        s->pre = (value >> 5) & 1;
-        s->ptv = (value >> 2) & 7;
-        s->ar = (value >> 1) & 1;
-        s->st = (value >> 0) & 1;
-        if (s->inout && s->trigger != gpt_trigger_none)
-            fprintf(stderr, "%s: GP timer pin must be an output "
-                            "for this trigger mode\n", __FUNCTION__);
-        if (!s->inout && s->capture != gpt_capture_none)
-            fprintf(stderr, "%s: GP timer pin must be an input "
-                            "for this capture mode\n", __FUNCTION__);
-        if (s->trigger == gpt_trigger_none)
-            omap_gp_timer_out(s, s->scpwm);
-        /* TODO: make sure this doesn't overflow 32-bits */
-        s->ticks_per_sec = get_ticks_per_sec() << (s->pre ? s->ptv + 1 : 0);
-        omap_gp_timer_update(s);
-        break;
-
-    case 0x28:	/* TCRR */
-        s->time = qemu_get_clock(vm_clock);
-        s->val = value;
-        omap_gp_timer_update(s);
-        break;
-
-    case 0x2c:	/* TLDR */
-        s->load_val = value;
-        break;
-
-    case 0x30:	/* TTGR */
-        s->time = qemu_get_clock(vm_clock);
-        s->val = s->load_val;
-        omap_gp_timer_update(s);
-        break;
-
-    case 0x38:	/* TMAR */
-        omap_gp_timer_sync(s);
-        s->match_val = value;
-        omap_gp_timer_update(s);
-        break;
-
-    case 0x40:	/* TSICR */
-        s->posted = (value >> 2) & 1;
-        if (value & 2)	/* How much exactly are we supposed to reset? */
-            omap_gp_timer_reset(s);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-
-    if (addr & 2)
-        return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
-    else
-        s->writeh = (uint16_t) value;
-}
-
-static CPUWriteMemoryFunc * const omap_gp_timer_writefn[] = {
-    omap_badwidth_write32,
-    omap_gp_timer_writeh,
-    omap_gp_timer_write,
-};
-
-struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
-                qemu_irq irq, omap_clk fclk, omap_clk iclk)
-{
-    int iomemtype;
-    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)
-            qemu_mallocz(sizeof(struct omap_gp_timer_s));
-
-    s->ta = ta;
-    s->irq = irq;
-    s->clk = fclk;
-    s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s);
-    s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s);
-    s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
-    omap_gp_timer_reset(s);
-    omap_gp_timer_clk_setup(s);
-
-    iomemtype = l4_register_io_memory(omap_gp_timer_readfn,
-                    omap_gp_timer_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
-
-    return s;
-}
-
 /* 32-kHz Sync Timer of the OMAP2 */
 static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
     return muldiv64(qemu_get_clock(vm_clock), 0x8000, get_ticks_per_sec());
diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c
new file mode 100644
index 0000000..9c0f9f2
--- /dev/null
+++ b/hw/omap_gptimer.c
@@ -0,0 +1,484 @@
+/*
+ * TI OMAP2 general purpose timers emulation.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "qemu-timer.h"
+#include "omap.h"
+
+/* GP timers */
+struct omap_gp_timer_s {
+    qemu_irq irq;
+    qemu_irq wkup;
+    qemu_irq in;
+    qemu_irq out;
+    omap_clk clk;
+    QEMUTimer *timer;
+    QEMUTimer *match;
+    struct omap_target_agent_s *ta;
+
+    int in_val;
+    int out_val;
+    int64_t time;
+    int64_t rate;
+    int64_t ticks_per_sec;
+
+    int16_t config;
+    int status;
+    int it_ena;
+    int wu_ena;
+    int enable;
+    int inout;
+    int capt2;
+    int pt;
+    enum {
+        gpt_trigger_none, gpt_trigger_overflow, gpt_trigger_both
+    } trigger;
+    enum {
+        gpt_capture_none, gpt_capture_rising,
+        gpt_capture_falling, gpt_capture_both
+    } capture;
+    int scpwm;
+    int ce;
+    int pre;
+    int ptv;
+    int ar;
+    int st;
+    int posted;
+    uint32_t val;
+    uint32_t load_val;
+    uint32_t capture_val[2];
+    uint32_t match_val;
+    int capt_num;
+
+    uint16_t writeh;	/* LSB */
+    uint16_t readh;	/* MSB */
+};
+
+#define GPT_TCAR_IT	(1 << 2)
+#define GPT_OVF_IT	(1 << 1)
+#define GPT_MAT_IT	(1 << 0)
+
+static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it)
+{
+    if (timer->it_ena & it) {
+        if (!timer->status)
+            qemu_irq_raise(timer->irq);
+
+        timer->status |= it;
+        /* Or are the status bits set even when masked?
+         * i.e. is masking applied before or after the status register?  */
+    }
+
+    if (timer->wu_ena & it)
+        qemu_irq_pulse(timer->wkup);
+}
+
+static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level)
+{
+    if (!timer->inout && timer->out_val != level) {
+        timer->out_val = level;
+        qemu_set_irq(timer->out, level);
+    }
+}
+
+static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer)
+{
+    uint64_t distance;
+
+    if (timer->st && timer->rate) {
+        distance = qemu_get_clock(vm_clock) - timer->time;
+        distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
+
+        if (distance >= 0xffffffff - timer->val)
+            return 0xffffffff;
+        else
+            return timer->val + distance;
+    } else
+        return timer->val;
+}
+
+static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer)
+{
+    if (timer->st) {
+        timer->val = omap_gp_timer_read(timer);
+        timer->time = qemu_get_clock(vm_clock);
+    }
+}
+
+static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer)
+{
+    int64_t expires, matches;
+
+    if (timer->st && timer->rate) {
+        expires = muldiv64(0x100000000ll - timer->val,
+                        timer->ticks_per_sec, timer->rate);
+        qemu_mod_timer(timer->timer, timer->time + expires);
+
+        if (timer->ce && timer->match_val >= timer->val) {
+            matches = muldiv64(timer->match_val - timer->val,
+                            timer->ticks_per_sec, timer->rate);
+            qemu_mod_timer(timer->match, timer->time + matches);
+        } else
+            qemu_del_timer(timer->match);
+    } else {
+        qemu_del_timer(timer->timer);
+        qemu_del_timer(timer->match);
+        omap_gp_timer_out(timer, timer->scpwm);
+    }
+}
+
+static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer)
+{
+    if (timer->pt)
+        /* TODO in overflow-and-match mode if the first event to
+         * occur is the match, don't toggle.  */
+        omap_gp_timer_out(timer, !timer->out_val);
+    else
+        /* TODO inverted pulse on timer->out_val == 1?  */
+        qemu_irq_pulse(timer->out);
+}
+
+static void omap_gp_timer_tick(void *opaque)
+{
+    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
+
+    if (!timer->ar) {
+        timer->st = 0;
+        timer->val = 0;
+    } else {
+        timer->val = timer->load_val;
+        timer->time = qemu_get_clock(vm_clock);
+    }
+
+    if (timer->trigger == gpt_trigger_overflow ||
+                    timer->trigger == gpt_trigger_both)
+        omap_gp_timer_trigger(timer);
+
+    omap_gp_timer_intr(timer, GPT_OVF_IT);
+    omap_gp_timer_update(timer);
+}
+
+static void omap_gp_timer_match(void *opaque)
+{
+    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
+
+    if (timer->trigger == gpt_trigger_both)
+        omap_gp_timer_trigger(timer);
+
+    omap_gp_timer_intr(timer, GPT_MAT_IT);
+}
+
+static void omap_gp_timer_input(void *opaque, int line, int on)
+{
+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
+    int trigger;
+
+    switch (s->capture) {
+    default:
+    case gpt_capture_none:
+        trigger = 0;
+        break;
+    case gpt_capture_rising:
+        trigger = !s->in_val && on;
+        break;
+    case gpt_capture_falling:
+        trigger = s->in_val && !on;
+        break;
+    case gpt_capture_both:
+        trigger = (s->in_val == !on);
+        break;
+    }
+    s->in_val = on;
+
+    if (s->inout && trigger && s->capt_num < 2) {
+        s->capture_val[s->capt_num] = omap_gp_timer_read(s);
+
+        if (s->capt2 == s->capt_num ++)
+            omap_gp_timer_intr(s, GPT_TCAR_IT);
+    }
+}
+
+static void omap_gp_timer_clk_update(void *opaque, int line, int on)
+{
+    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
+
+    omap_gp_timer_sync(timer);
+    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
+    omap_gp_timer_update(timer);
+}
+
+static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
+{
+    omap_clk_adduser(timer->clk,
+                    qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]);
+    timer->rate = omap_clk_getrate(timer->clk);
+}
+
+void omap_gp_timer_reset(struct omap_gp_timer_s *s)
+{
+    s->config = 0x000;
+    s->status = 0;
+    s->it_ena = 0;
+    s->wu_ena = 0;
+    s->inout = 0;
+    s->capt2 = 0;
+    s->capt_num = 0;
+    s->pt = 0;
+    s->trigger = gpt_trigger_none;
+    s->capture = gpt_capture_none;
+    s->scpwm = 0;
+    s->ce = 0;
+    s->pre = 0;
+    s->ptv = 0;
+    s->ar = 0;
+    s->st = 0;
+    s->posted = 1;
+    s->val = 0x00000000;
+    s->load_val = 0x00000000;
+    s->capture_val[0] = 0x00000000;
+    s->capture_val[1] = 0x00000000;
+    s->match_val = 0x00000000;
+    omap_gp_timer_update(s);
+}
+
+static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* TIDR */
+        return 0x21;
+
+    case 0x10:	/* TIOCP_CFG */
+        return s->config;
+
+    case 0x14:	/* TISTAT */
+        /* ??? When's this bit reset? */
+        return 1;						/* RESETDONE */
+
+    case 0x18:	/* TISR */
+        return s->status;
+
+    case 0x1c:	/* TIER */
+        return s->it_ena;
+
+    case 0x20:	/* TWER */
+        return s->wu_ena;
+
+    case 0x24:	/* TCLR */
+        return (s->inout << 14) |
+                (s->capt2 << 13) |
+                (s->pt << 12) |
+                (s->trigger << 10) |
+                (s->capture << 8) |
+                (s->scpwm << 7) |
+                (s->ce << 6) |
+                (s->pre << 5) |
+                (s->ptv << 2) |
+                (s->ar << 1) |
+                (s->st << 0);
+
+    case 0x28:	/* TCRR */
+        return omap_gp_timer_read(s);
+
+    case 0x2c:	/* TLDR */
+        return s->load_val;
+
+    case 0x30:	/* TTGR */
+        return 0xffffffff;
+
+    case 0x34:	/* TWPS */
+        return 0x00000000;	/* No posted writes pending.  */
+
+    case 0x38:	/* TMAR */
+        return s->match_val;
+
+    case 0x3c:	/* TCAR1 */
+        return s->capture_val[0];
+
+    case 0x40:	/* TSICR */
+        return s->posted << 2;
+
+    case 0x44:	/* TCAR2 */
+        return s->capture_val[1];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
+    uint32_t ret;
+
+    if (addr & 2)
+        return s->readh;
+    else {
+        ret = omap_gp_timer_readw(opaque, addr);
+        s->readh = ret >> 16;
+        return ret & 0xffff;
+    }
+}
+
+static CPUReadMemoryFunc * const omap_gp_timer_readfn[] = {
+    omap_badwidth_read32,
+    omap_gp_timer_readh,
+    omap_gp_timer_readw,
+};
+
+static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* TIDR */
+    case 0x14:	/* TISTAT */
+    case 0x34:	/* TWPS */
+    case 0x3c:	/* TCAR1 */
+    case 0x44:	/* TCAR2 */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x10:	/* TIOCP_CFG */
+        s->config = value & 0x33d;
+        if (((value >> 3) & 3) == 3)				/* IDLEMODE */
+            fprintf(stderr, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
+                            __FUNCTION__);
+        if (value & 2)						/* SOFTRESET */
+            omap_gp_timer_reset(s);
+        break;
+
+    case 0x18:	/* TISR */
+        if (value & GPT_TCAR_IT)
+            s->capt_num = 0;
+        if (s->status && !(s->status &= ~value))
+            qemu_irq_lower(s->irq);
+        break;
+
+    case 0x1c:	/* TIER */
+        s->it_ena = value & 7;
+        break;
+
+    case 0x20:	/* TWER */
+        s->wu_ena = value & 7;
+        break;
+
+    case 0x24:	/* TCLR */
+        omap_gp_timer_sync(s);
+        s->inout = (value >> 14) & 1;
+        s->capt2 = (value >> 13) & 1;
+        s->pt = (value >> 12) & 1;
+        s->trigger = (value >> 10) & 3;
+        if (s->capture == gpt_capture_none &&
+                        ((value >> 8) & 3) != gpt_capture_none)
+            s->capt_num = 0;
+        s->capture = (value >> 8) & 3;
+        s->scpwm = (value >> 7) & 1;
+        s->ce = (value >> 6) & 1;
+        s->pre = (value >> 5) & 1;
+        s->ptv = (value >> 2) & 7;
+        s->ar = (value >> 1) & 1;
+        s->st = (value >> 0) & 1;
+        if (s->inout && s->trigger != gpt_trigger_none)
+            fprintf(stderr, "%s: GP timer pin must be an output "
+                            "for this trigger mode\n", __FUNCTION__);
+        if (!s->inout && s->capture != gpt_capture_none)
+            fprintf(stderr, "%s: GP timer pin must be an input "
+                            "for this capture mode\n", __FUNCTION__);
+        if (s->trigger == gpt_trigger_none)
+            omap_gp_timer_out(s, s->scpwm);
+        /* TODO: make sure this doesn't overflow 32-bits */
+        s->ticks_per_sec = get_ticks_per_sec() << (s->pre ? s->ptv + 1 : 0);
+        omap_gp_timer_update(s);
+        break;
+
+    case 0x28:	/* TCRR */
+        s->time = qemu_get_clock(vm_clock);
+        s->val = value;
+        omap_gp_timer_update(s);
+        break;
+
+    case 0x2c:	/* TLDR */
+        s->load_val = value;
+        break;
+
+    case 0x30:	/* TTGR */
+        s->time = qemu_get_clock(vm_clock);
+        s->val = s->load_val;
+        omap_gp_timer_update(s);
+        break;
+
+    case 0x38:	/* TMAR */
+        omap_gp_timer_sync(s);
+        s->match_val = value;
+        omap_gp_timer_update(s);
+        break;
+
+    case 0x40:	/* TSICR */
+        s->posted = (value >> 2) & 1;
+        if (value & 2)	/* How much exactly are we supposed to reset? */
+            omap_gp_timer_reset(s);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
+
+    if (addr & 2)
+        return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
+    else
+        s->writeh = (uint16_t) value;
+}
+
+static CPUWriteMemoryFunc * const omap_gp_timer_writefn[] = {
+    omap_badwidth_write32,
+    omap_gp_timer_writeh,
+    omap_gp_timer_write,
+};
+
+struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
+                qemu_irq irq, omap_clk fclk, omap_clk iclk)
+{
+    int iomemtype;
+    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)
+            qemu_mallocz(sizeof(struct omap_gp_timer_s));
+
+    s->ta = ta;
+    s->irq = irq;
+    s->clk = fclk;
+    s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s);
+    s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s);
+    s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
+    omap_gp_timer_reset(s);
+    omap_gp_timer_clk_setup(s);
+
+    iomemtype = l4_register_io_memory(omap_gp_timer_readfn,
+                    omap_gp_timer_writefn, s);
+    omap_l4_attach(ta, 0, iomemtype);
+
+    return s;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 04/12] hw/omap2.c : separate synctimer module
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (2 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 03/12] hw/omap2.c : separate gptimer module cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 05/12] hw/omap2.c : separate gpmc(general purpose memory controller) cmchao
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target     |    2 +-
 hw/omap.h           |   11 +++---
 hw/omap2.c          |   72 +-------------------------------------
 hw/omap_synctimer.c |   96 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 104 insertions(+), 77 deletions(-)
 create mode 100644 hw/omap_synctimer.c

diff --git a/Makefile.target b/Makefile.target
index c29dee0..43c1708 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -264,7 +264,7 @@ 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
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o
+obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
diff --git a/hw/omap.h b/hw/omap.h
index 14fdb6f..b898230 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -645,8 +645,11 @@ struct omap_32khz_timer_s;
 struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk clk);
 
-void omap_synctimer_init(struct omap_target_agent_s *ta,
+/* OMAP2 sysctimer */
+struct omap_synctimer_s;
+struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk);
+void omap_synctimer_reset(struct omap_synctimer_s *s);
 
 struct omap_tipb_bridge_s;
 struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
@@ -939,11 +942,7 @@ struct omap_mpu_state_s {
     struct omap_l4_s *l4;
 
     struct omap_gp_timer_s *gptimer[12];
-
-    struct omap_synctimer_s {
-        uint32_t val;
-        uint16_t readh;
-    } synctimer;
+    struct omap_synctimer_s *synctimer;
 
     struct omap_prcm_s *prcm;
     struct omap_sdrc_s *sdrc;
diff --git a/hw/omap2.c b/hw/omap2.c
index 890397b..e310eef 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -27,74 +27,6 @@
 #include "soc_dma.h"
 #include "audio/audio.h"
 
-/* 32-kHz Sync Timer of the OMAP2 */
-static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
-    return muldiv64(qemu_get_clock(vm_clock), 0x8000, get_ticks_per_sec());
-}
-
-static void omap_synctimer_reset(struct omap_synctimer_s *s)
-{
-    s->val = omap_synctimer_read(s);
-}
-
-static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* 32KSYNCNT_REV */
-        return 0x21;
-
-    case 0x10:	/* CR */
-        return omap_synctimer_read(s) - s->val;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
-    uint32_t ret;
-
-    if (addr & 2)
-        return s->readh;
-    else {
-        ret = omap_synctimer_readw(opaque, addr);
-        s->readh = ret >> 16;
-        return ret & 0xffff;
-    }
-}
-
-static CPUReadMemoryFunc * const omap_synctimer_readfn[] = {
-    omap_badwidth_read32,
-    omap_synctimer_readh,
-    omap_synctimer_readw,
-};
-
-static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    OMAP_BAD_REG(addr);
-}
-
-static CPUWriteMemoryFunc * const omap_synctimer_writefn[] = {
-    omap_badwidth_write32,
-    omap_synctimer_write,
-    omap_synctimer_write,
-};
-
-void omap_synctimer_init(struct omap_target_agent_s *ta,
-                struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
-{
-    struct omap_synctimer_s *s = &mpu->synctimer;
-
-    omap_synctimer_reset(s);
-    omap_l4_attach(ta, 0, l4_register_io_memory(
-                      omap_synctimer_readfn, omap_synctimer_writefn, s));
-}
-
 /* Multichannel SPI */
 struct omap_mcspi_s {
     qemu_irq irq;
@@ -3473,7 +3405,7 @@ static void omap2_mpu_reset(void *opaque)
     omap_gp_timer_reset(mpu->gptimer[9]);
     omap_gp_timer_reset(mpu->gptimer[10]);
     omap_gp_timer_reset(mpu->gptimer[11]);
-    omap_synctimer_reset(&mpu->synctimer);
+    omap_synctimer_reset(mpu->synctimer);
     omap_sdrc_reset(mpu->sdrc);
     omap_gpmc_reset(mpu->gpmc);
     omap_dss_reset(mpu->dss);
@@ -3634,7 +3566,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
 
     omap_tap_init(omap_l4ta(s->l4, 2), s);
 
-    omap_synctimer_init(omap_l4tao(s->l4, 2), s,
+    s->synctimer = omap_synctimer_init(omap_l4tao(s->l4, 2), s,
                     omap_findclk(s, "clk32-kHz"),
                     omap_findclk(s, "core_l4_iclk"));
 
diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c
new file mode 100644
index 0000000..118668a
--- /dev/null
+++ b/hw/omap_synctimer.c
@@ -0,0 +1,96 @@
+/*
+ * TI OMAP2 32kHz sync timer emulation.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "qemu-timer.h"
+#include "omap.h"
+struct omap_synctimer_s {
+    uint32_t val;
+    uint16_t readh;
+};
+
+/* 32-kHz Sync Timer of the OMAP2 */
+static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
+    return muldiv64(qemu_get_clock(vm_clock), 0x8000, get_ticks_per_sec());
+}
+
+void omap_synctimer_reset(struct omap_synctimer_s *s)
+{
+    s->val = omap_synctimer_read(s);
+}
+
+static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* 32KSYNCNT_REV */
+        return 0x21;
+
+    case 0x10:	/* CR */
+        return omap_synctimer_read(s) - s->val;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
+    uint32_t ret;
+
+    if (addr & 2)
+        return s->readh;
+    else {
+        ret = omap_synctimer_readw(opaque, addr);
+        s->readh = ret >> 16;
+        return ret & 0xffff;
+    }
+}
+
+static CPUReadMemoryFunc * const omap_synctimer_readfn[] = {
+    omap_badwidth_read32,
+    omap_synctimer_readh,
+    omap_synctimer_readw,
+};
+
+static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    OMAP_BAD_REG(addr);
+}
+
+static CPUWriteMemoryFunc * const omap_synctimer_writefn[] = {
+    omap_badwidth_write32,
+    omap_synctimer_write,
+    omap_synctimer_write,
+};
+
+struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
+                struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
+{
+    struct omap_synctimer_s *s = qemu_mallocz(sizeof(*s));
+
+    omap_synctimer_reset(s);
+    omap_l4_attach(ta, 0, l4_register_io_memory(
+                      omap_synctimer_readfn, omap_synctimer_writefn, s));
+
+    return s;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 05/12] hw/omap2.c : separate gpmc(general purpose memory controller)
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (3 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 04/12] hw/omap2.c : separate synctimer module cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 06/12] hw/omap2.c : separate sdrc (sdram controller) cmchao
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 27214 bytes --]


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    2 +-
 hw/omap.h       |    2 +
 hw/omap2.c      |  396 ----------------------------------------------------
 hw/omap_gpmc.c  |  419 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 422 insertions(+), 397 deletions(-)
 create mode 100644 hw/omap_gpmc.c

diff --git a/Makefile.target b/Makefile.target
index 43c1708..e6abaa7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -264,7 +264,7 @@ 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
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o
+obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
diff --git a/hw/omap.h b/hw/omap.h
index b898230..c596953 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -93,8 +93,10 @@ struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
 struct omap_sdrc_s;
 struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
 
+/* OMAP2 general purpose memory controller */
 struct omap_gpmc_s;
 struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq);
+void omap_gpmc_reset(struct omap_gpmc_s *s);
 void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
                 void (*base_upd)(void *opaque, target_phys_addr_t new),
                 void (*unmap)(void *opaque), void *opaque);
diff --git a/hw/omap2.c b/hw/omap2.c
index e310eef..b1e5aae 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2988,402 +2988,6 @@ struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
     return s;
 }
 
-/* General-Purpose Memory Controller */
-struct omap_gpmc_s {
-    qemu_irq irq;
-
-    uint8_t sysconfig;
-    uint16_t irqst;
-    uint16_t irqen;
-    uint16_t timeout;
-    uint16_t config;
-    uint32_t prefconfig[2];
-    int prefcontrol;
-    int preffifo;
-    int prefcount;
-    struct omap_gpmc_cs_file_s {
-        uint32_t config[7];
-        target_phys_addr_t base;
-        size_t size;
-        int iomemtype;
-        void (*base_update)(void *opaque, target_phys_addr_t new);
-        void (*unmap)(void *opaque);
-        void *opaque;
-    } cs_file[8];
-    int ecc_cs;
-    int ecc_ptr;
-    uint32_t ecc_cfg;
-    ECCState ecc[9];
-};
-
-static void omap_gpmc_int_update(struct omap_gpmc_s *s)
-{
-    qemu_set_irq(s->irq, s->irqen & s->irqst);
-}
-
-static void omap_gpmc_cs_map(struct omap_gpmc_cs_file_s *f, int base, int mask)
-{
-    /* TODO: check for overlapping regions and report access errors */
-    if ((mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf) ||
-                    (base < 0 || base >= 0x40) ||
-                    (base & 0x0f & ~mask)) {
-        fprintf(stderr, "%s: wrong cs address mapping/decoding!\n",
-                        __FUNCTION__);
-        return;
-    }
-
-    if (!f->opaque)
-        return;
-
-    f->base = base << 24;
-    f->size = (0x0fffffff & ~(mask << 24)) + 1;
-    /* TODO: rather than setting the size of the mapping (which should be
-     * constant), the mask should cause wrapping of the address space, so
-     * that the same memory becomes accessible at every <i>size</i> bytes
-     * starting from <i>base</i>.  */
-    if (f->iomemtype)
-        cpu_register_physical_memory(f->base, f->size, f->iomemtype);
-
-    if (f->base_update)
-        f->base_update(f->opaque, f->base);
-}
-
-static void omap_gpmc_cs_unmap(struct omap_gpmc_cs_file_s *f)
-{
-    if (f->size) {
-        if (f->unmap)
-            f->unmap(f->opaque);
-        if (f->iomemtype)
-            cpu_register_physical_memory(f->base, f->size, IO_MEM_UNASSIGNED);
-        f->base = 0;
-        f->size = 0;
-    }
-}
-
-static void omap_gpmc_reset(struct omap_gpmc_s *s)
-{
-    int i;
-
-    s->sysconfig = 0;
-    s->irqst = 0;
-    s->irqen = 0;
-    omap_gpmc_int_update(s);
-    s->timeout = 0;
-    s->config = 0xa00;
-    s->prefconfig[0] = 0x00004000;
-    s->prefconfig[1] = 0x00000000;
-    s->prefcontrol = 0;
-    s->preffifo = 0;
-    s->prefcount = 0;
-    for (i = 0; i < 8; i ++) {
-        if (s->cs_file[i].config[6] & (1 << 6))			/* CSVALID */
-            omap_gpmc_cs_unmap(s->cs_file + i);
-        s->cs_file[i].config[0] = i ? 1 << 12 : 0;
-        s->cs_file[i].config[1] = 0x101001;
-        s->cs_file[i].config[2] = 0x020201;
-        s->cs_file[i].config[3] = 0x10031003;
-        s->cs_file[i].config[4] = 0x10f1111;
-        s->cs_file[i].config[5] = 0;
-        s->cs_file[i].config[6] = 0xf00 | (i ? 0 : 1 << 6);
-        if (s->cs_file[i].config[6] & (1 << 6))			/* CSVALID */
-            omap_gpmc_cs_map(&s->cs_file[i],
-                            s->cs_file[i].config[6] & 0x1f,	/* MASKADDR */
-                        (s->cs_file[i].config[6] >> 8 & 0xf));	/* BASEADDR */
-    }
-    omap_gpmc_cs_map(s->cs_file, 0, 0xf);
-    s->ecc_cs = 0;
-    s->ecc_ptr = 0;
-    s->ecc_cfg = 0x3fcff000;
-    for (i = 0; i < 9; i ++)
-        ecc_reset(&s->ecc[i]);
-}
-
-static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
-    int cs;
-    struct omap_gpmc_cs_file_s *f;
-
-    switch (addr) {
-    case 0x000:	/* GPMC_REVISION */
-        return 0x20;
-
-    case 0x010:	/* GPMC_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x014:	/* GPMC_SYSSTATUS */
-        return 1;						/* RESETDONE */
-
-    case 0x018:	/* GPMC_IRQSTATUS */
-        return s->irqst;
-
-    case 0x01c:	/* GPMC_IRQENABLE */
-        return s->irqen;
-
-    case 0x040:	/* GPMC_TIMEOUT_CONTROL */
-        return s->timeout;
-
-    case 0x044:	/* GPMC_ERR_ADDRESS */
-    case 0x048:	/* GPMC_ERR_TYPE */
-        return 0;
-
-    case 0x050:	/* GPMC_CONFIG */
-        return s->config;
-
-    case 0x054:	/* GPMC_STATUS */
-        return 0x001;
-
-    case 0x060 ... 0x1d4:
-        cs = (addr - 0x060) / 0x30;
-        addr -= cs * 0x30;
-        f = s->cs_file + cs;
-        switch (addr) {
-            case 0x60:	/* GPMC_CONFIG1 */
-                return f->config[0];
-            case 0x64:	/* GPMC_CONFIG2 */
-                return f->config[1];
-            case 0x68:	/* GPMC_CONFIG3 */
-                return f->config[2];
-            case 0x6c:	/* GPMC_CONFIG4 */
-                return f->config[3];
-            case 0x70:	/* GPMC_CONFIG5 */
-                return f->config[4];
-            case 0x74:	/* GPMC_CONFIG6 */
-                return f->config[5];
-            case 0x78:	/* GPMC_CONFIG7 */
-                return f->config[6];
-            case 0x84:	/* GPMC_NAND_DATA */
-                return 0;
-        }
-        break;
-
-    case 0x1e0:	/* GPMC_PREFETCH_CONFIG1 */
-        return s->prefconfig[0];
-    case 0x1e4:	/* GPMC_PREFETCH_CONFIG2 */
-        return s->prefconfig[1];
-    case 0x1ec:	/* GPMC_PREFETCH_CONTROL */
-        return s->prefcontrol;
-    case 0x1f0:	/* GPMC_PREFETCH_STATUS */
-        return (s->preffifo << 24) |
-                ((s->preffifo >
-                  ((s->prefconfig[0] >> 8) & 0x7f) ? 1 : 0) << 16) |
-                s->prefcount;
-
-    case 0x1f4:	/* GPMC_ECC_CONFIG */
-        return s->ecc_cs;
-    case 0x1f8:	/* GPMC_ECC_CONTROL */
-        return s->ecc_ptr;
-    case 0x1fc:	/* GPMC_ECC_SIZE_CONFIG */
-        return s->ecc_cfg;
-    case 0x200 ... 0x220:	/* GPMC_ECC_RESULT */
-        cs = (addr & 0x1f) >> 2;
-        /* TODO: check correctness */
-        return
-                ((s->ecc[cs].cp    &  0x07) <<  0) |
-                ((s->ecc[cs].cp    &  0x38) << 13) |
-                ((s->ecc[cs].lp[0] & 0x1ff) <<  3) |
-                ((s->ecc[cs].lp[1] & 0x1ff) << 19);
-
-    case 0x230:	/* GPMC_TESTMODE_CTRL */
-        return 0;
-    case 0x234:	/* GPMC_PSA_LSB */
-    case 0x238:	/* GPMC_PSA_MSB */
-        return 0x00000000;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
-    int cs;
-    struct omap_gpmc_cs_file_s *f;
-
-    switch (addr) {
-    case 0x000:	/* GPMC_REVISION */
-    case 0x014:	/* GPMC_SYSSTATUS */
-    case 0x054:	/* GPMC_STATUS */
-    case 0x1f0:	/* GPMC_PREFETCH_STATUS */
-    case 0x200 ... 0x220:	/* GPMC_ECC_RESULT */
-    case 0x234:	/* GPMC_PSA_LSB */
-    case 0x238:	/* GPMC_PSA_MSB */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x010:	/* GPMC_SYSCONFIG */
-        if ((value >> 3) == 0x3)
-            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
-                            __FUNCTION__, value >> 3);
-        if (value & 2)
-            omap_gpmc_reset(s);
-        s->sysconfig = value & 0x19;
-        break;
-
-    case 0x018:	/* GPMC_IRQSTATUS */
-        s->irqen = ~value;
-        omap_gpmc_int_update(s);
-        break;
-
-    case 0x01c:	/* GPMC_IRQENABLE */
-        s->irqen = value & 0xf03;
-        omap_gpmc_int_update(s);
-        break;
-
-    case 0x040:	/* GPMC_TIMEOUT_CONTROL */
-        s->timeout = value & 0x1ff1;
-        break;
-
-    case 0x044:	/* GPMC_ERR_ADDRESS */
-    case 0x048:	/* GPMC_ERR_TYPE */
-        break;
-
-    case 0x050:	/* GPMC_CONFIG */
-        s->config = value & 0xf13;
-        break;
-
-    case 0x060 ... 0x1d4:
-        cs = (addr - 0x060) / 0x30;
-        addr -= cs * 0x30;
-        f = s->cs_file + cs;
-        switch (addr) {
-            case 0x60:	/* GPMC_CONFIG1 */
-                f->config[0] = value & 0xffef3e13;
-                break;
-            case 0x64:	/* GPMC_CONFIG2 */
-                f->config[1] = value & 0x001f1f8f;
-                break;
-            case 0x68:	/* GPMC_CONFIG3 */
-                f->config[2] = value & 0x001f1f8f;
-                break;
-            case 0x6c:	/* GPMC_CONFIG4 */
-                f->config[3] = value & 0x1f8f1f8f;
-                break;
-            case 0x70:	/* GPMC_CONFIG5 */
-                f->config[4] = value & 0x0f1f1f1f;
-                break;
-            case 0x74:	/* GPMC_CONFIG6 */
-                f->config[5] = value & 0x00000fcf;
-                break;
-            case 0x78:	/* GPMC_CONFIG7 */
-                if ((f->config[6] ^ value) & 0xf7f) {
-                    if (f->config[6] & (1 << 6))		/* CSVALID */
-                        omap_gpmc_cs_unmap(f);
-                    if (value & (1 << 6))			/* CSVALID */
-                        omap_gpmc_cs_map(f, value & 0x1f,	/* MASKADDR */
-                                        (value >> 8 & 0xf));	/* BASEADDR */
-                }
-                f->config[6] = value & 0x00000f7f;
-                break;
-            case 0x7c:	/* GPMC_NAND_COMMAND */
-            case 0x80:	/* GPMC_NAND_ADDRESS */
-            case 0x84:	/* GPMC_NAND_DATA */
-                break;
-
-            default:
-                goto bad_reg;
-        }
-        break;
-
-    case 0x1e0:	/* GPMC_PREFETCH_CONFIG1 */
-        s->prefconfig[0] = value & 0x7f8f7fbf;
-        /* TODO: update interrupts, fifos, dmas */
-        break;
-
-    case 0x1e4:	/* GPMC_PREFETCH_CONFIG2 */
-        s->prefconfig[1] = value & 0x3fff;
-        break;
-
-    case 0x1ec:	/* GPMC_PREFETCH_CONTROL */
-        s->prefcontrol = value & 1;
-        if (s->prefcontrol) {
-            if (s->prefconfig[0] & 1)
-                s->preffifo = 0x40;
-            else
-                s->preffifo = 0x00;
-        }
-        /* TODO: start */
-        break;
-
-    case 0x1f4:	/* GPMC_ECC_CONFIG */
-        s->ecc_cs = 0x8f;
-        break;
-    case 0x1f8:	/* GPMC_ECC_CONTROL */
-        if (value & (1 << 8))
-            for (cs = 0; cs < 9; cs ++)
-                ecc_reset(&s->ecc[cs]);
-        s->ecc_ptr = value & 0xf;
-        if (s->ecc_ptr == 0 || s->ecc_ptr > 9) {
-            s->ecc_ptr = 0;
-            s->ecc_cs &= ~1;
-        }
-        break;
-    case 0x1fc:	/* GPMC_ECC_SIZE_CONFIG */
-        s->ecc_cfg = value & 0x3fcff1ff;
-        break;
-    case 0x230:	/* GPMC_TESTMODE_CTRL */
-        if (value & 7)
-            fprintf(stderr, "%s: test mode enable attempt\n", __FUNCTION__);
-        break;
-
-    default:
-    bad_reg:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static CPUReadMemoryFunc * const omap_gpmc_readfn[] = {
-    omap_badwidth_read32,	/* TODO */
-    omap_badwidth_read32,	/* TODO */
-    omap_gpmc_read,
-};
-
-static CPUWriteMemoryFunc * const omap_gpmc_writefn[] = {
-    omap_badwidth_write32,	/* TODO */
-    omap_badwidth_write32,	/* TODO */
-    omap_gpmc_write,
-};
-
-struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq)
-{
-    int iomemtype;
-    struct omap_gpmc_s *s = (struct omap_gpmc_s *)
-            qemu_mallocz(sizeof(struct omap_gpmc_s));
-
-    omap_gpmc_reset(s);
-
-    iomemtype = cpu_register_io_memory(omap_gpmc_readfn,
-                    omap_gpmc_writefn, s);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
-
-    return s;
-}
-
-void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
-                void (*base_upd)(void *opaque, target_phys_addr_t new),
-                void (*unmap)(void *opaque), void *opaque)
-{
-    struct omap_gpmc_cs_file_s *f;
-
-    if (cs < 0 || cs >= 8) {
-        fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs);
-        exit(-1);
-    }
-    f = &s->cs_file[cs];
-
-    f->iomemtype = iomemtype;
-    f->base_update = base_upd;
-    f->unmap = unmap;
-    f->opaque = opaque;
-
-    if (f->config[6] & (1 << 6))				/* CSVALID */
-        omap_gpmc_cs_map(f, f->config[6] & 0x1f,		/* MASKADDR */
-                        (f->config[6] >> 8 & 0xf));		/* BASEADDR */
-}
-
 /* General chip reset */
 static void omap2_mpu_reset(void *opaque)
 {
diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c
new file mode 100644
index 0000000..72cfecc
--- /dev/null
+++ b/hw/omap_gpmc.c
@@ -0,0 +1,419 @@
+/*
+ * TI OMAP general purpose memory controller emulation.
+ *
+ * Copyright (C) 2007-2009 Nokia Corporation
+ * Original code written by Andrzej Zaborowski <andrew@openedhand.com>
+ * Enhancements for OMAP3 and NAND support written by Juha Riihimäki
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "flash.h"
+#include "omap.h"
+
+/* General-Purpose Memory Controller */
+struct omap_gpmc_s {
+    qemu_irq irq;
+
+    uint8_t sysconfig;
+    uint16_t irqst;
+    uint16_t irqen;
+    uint16_t timeout;
+    uint16_t config;
+    uint32_t prefconfig[2];
+    int prefcontrol;
+    int preffifo;
+    int prefcount;
+    struct omap_gpmc_cs_file_s {
+        uint32_t config[7];
+        target_phys_addr_t base;
+        size_t size;
+        int iomemtype;
+        void (*base_update)(void *opaque, target_phys_addr_t new);
+        void (*unmap)(void *opaque);
+        void *opaque;
+    } cs_file[8];
+    int ecc_cs;
+    int ecc_ptr;
+    uint32_t ecc_cfg;
+    ECCState ecc[9];
+};
+
+static void omap_gpmc_int_update(struct omap_gpmc_s *s)
+{
+    qemu_set_irq(s->irq, s->irqen & s->irqst);
+}
+
+static void omap_gpmc_cs_map(struct omap_gpmc_cs_file_s *f, int base, int mask)
+{
+    /* TODO: check for overlapping regions and report access errors */
+    if ((mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf) ||
+                    (base < 0 || base >= 0x40) ||
+                    (base & 0x0f & ~mask)) {
+        fprintf(stderr, "%s: wrong cs address mapping/decoding!\n",
+                        __FUNCTION__);
+        return;
+    }
+
+    if (!f->opaque)
+        return;
+
+    f->base = base << 24;
+    f->size = (0x0fffffff & ~(mask << 24)) + 1;
+    /* TODO: rather than setting the size of the mapping (which should be
+     * constant), the mask should cause wrapping of the address space, so
+     * that the same memory becomes accessible at every <i>size</i> bytes
+     * starting from <i>base</i>.  */
+    if (f->iomemtype)
+        cpu_register_physical_memory(f->base, f->size, f->iomemtype);
+
+    if (f->base_update)
+        f->base_update(f->opaque, f->base);
+}
+
+static void omap_gpmc_cs_unmap(struct omap_gpmc_cs_file_s *f)
+{
+    if (f->size) {
+        if (f->unmap)
+            f->unmap(f->opaque);
+        if (f->iomemtype)
+            cpu_register_physical_memory(f->base, f->size, IO_MEM_UNASSIGNED);
+        f->base = 0;
+        f->size = 0;
+    }
+}
+
+void omap_gpmc_reset(struct omap_gpmc_s *s)
+{
+    int i;
+
+    s->sysconfig = 0;
+    s->irqst = 0;
+    s->irqen = 0;
+    omap_gpmc_int_update(s);
+    s->timeout = 0;
+    s->config = 0xa00;
+    s->prefconfig[0] = 0x00004000;
+    s->prefconfig[1] = 0x00000000;
+    s->prefcontrol = 0;
+    s->preffifo = 0;
+    s->prefcount = 0;
+    for (i = 0; i < 8; i ++) {
+        if (s->cs_file[i].config[6] & (1 << 6))			/* CSVALID */
+            omap_gpmc_cs_unmap(s->cs_file + i);
+        s->cs_file[i].config[0] = i ? 1 << 12 : 0;
+        s->cs_file[i].config[1] = 0x101001;
+        s->cs_file[i].config[2] = 0x020201;
+        s->cs_file[i].config[3] = 0x10031003;
+        s->cs_file[i].config[4] = 0x10f1111;
+        s->cs_file[i].config[5] = 0;
+        s->cs_file[i].config[6] = 0xf00 | (i ? 0 : 1 << 6);
+        if (s->cs_file[i].config[6] & (1 << 6))			/* CSVALID */
+            omap_gpmc_cs_map(&s->cs_file[i],
+                            s->cs_file[i].config[6] & 0x1f,	/* MASKADDR */
+                        (s->cs_file[i].config[6] >> 8 & 0xf));	/* BASEADDR */
+    }
+    omap_gpmc_cs_map(s->cs_file, 0, 0xf);
+    s->ecc_cs = 0;
+    s->ecc_ptr = 0;
+    s->ecc_cfg = 0x3fcff000;
+    for (i = 0; i < 9; i ++)
+        ecc_reset(&s->ecc[i]);
+}
+
+static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
+    int cs;
+    struct omap_gpmc_cs_file_s *f;
+
+    switch (addr) {
+    case 0x000:	/* GPMC_REVISION */
+        return 0x20;
+
+    case 0x010:	/* GPMC_SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x014:	/* GPMC_SYSSTATUS */
+        return 1;						/* RESETDONE */
+
+    case 0x018:	/* GPMC_IRQSTATUS */
+        return s->irqst;
+
+    case 0x01c:	/* GPMC_IRQENABLE */
+        return s->irqen;
+
+    case 0x040:	/* GPMC_TIMEOUT_CONTROL */
+        return s->timeout;
+
+    case 0x044:	/* GPMC_ERR_ADDRESS */
+    case 0x048:	/* GPMC_ERR_TYPE */
+        return 0;
+
+    case 0x050:	/* GPMC_CONFIG */
+        return s->config;
+
+    case 0x054:	/* GPMC_STATUS */
+        return 0x001;
+
+    case 0x060 ... 0x1d4:
+        cs = (addr - 0x060) / 0x30;
+        addr -= cs * 0x30;
+        f = s->cs_file + cs;
+        switch (addr) {
+            case 0x60:	/* GPMC_CONFIG1 */
+                return f->config[0];
+            case 0x64:	/* GPMC_CONFIG2 */
+                return f->config[1];
+            case 0x68:	/* GPMC_CONFIG3 */
+                return f->config[2];
+            case 0x6c:	/* GPMC_CONFIG4 */
+                return f->config[3];
+            case 0x70:	/* GPMC_CONFIG5 */
+                return f->config[4];
+            case 0x74:	/* GPMC_CONFIG6 */
+                return f->config[5];
+            case 0x78:	/* GPMC_CONFIG7 */
+                return f->config[6];
+            case 0x84:	/* GPMC_NAND_DATA */
+                return 0;
+        }
+        break;
+
+    case 0x1e0:	/* GPMC_PREFETCH_CONFIG1 */
+        return s->prefconfig[0];
+    case 0x1e4:	/* GPMC_PREFETCH_CONFIG2 */
+        return s->prefconfig[1];
+    case 0x1ec:	/* GPMC_PREFETCH_CONTROL */
+        return s->prefcontrol;
+    case 0x1f0:	/* GPMC_PREFETCH_STATUS */
+        return (s->preffifo << 24) |
+                ((s->preffifo >
+                  ((s->prefconfig[0] >> 8) & 0x7f) ? 1 : 0) << 16) |
+                s->prefcount;
+
+    case 0x1f4:	/* GPMC_ECC_CONFIG */
+        return s->ecc_cs;
+    case 0x1f8:	/* GPMC_ECC_CONTROL */
+        return s->ecc_ptr;
+    case 0x1fc:	/* GPMC_ECC_SIZE_CONFIG */
+        return s->ecc_cfg;
+    case 0x200 ... 0x220:	/* GPMC_ECC_RESULT */
+        cs = (addr & 0x1f) >> 2;
+        /* TODO: check correctness */
+        return
+                ((s->ecc[cs].cp    &  0x07) <<  0) |
+                ((s->ecc[cs].cp    &  0x38) << 13) |
+                ((s->ecc[cs].lp[0] & 0x1ff) <<  3) |
+                ((s->ecc[cs].lp[1] & 0x1ff) << 19);
+
+    case 0x230:	/* GPMC_TESTMODE_CTRL */
+        return 0;
+    case 0x234:	/* GPMC_PSA_LSB */
+    case 0x238:	/* GPMC_PSA_MSB */
+        return 0x00000000;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
+    int cs;
+    struct omap_gpmc_cs_file_s *f;
+
+    switch (addr) {
+    case 0x000:	/* GPMC_REVISION */
+    case 0x014:	/* GPMC_SYSSTATUS */
+    case 0x054:	/* GPMC_STATUS */
+    case 0x1f0:	/* GPMC_PREFETCH_STATUS */
+    case 0x200 ... 0x220:	/* GPMC_ECC_RESULT */
+    case 0x234:	/* GPMC_PSA_LSB */
+    case 0x238:	/* GPMC_PSA_MSB */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x010:	/* GPMC_SYSCONFIG */
+        if ((value >> 3) == 0x3)
+            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
+                            __FUNCTION__, value >> 3);
+        if (value & 2)
+            omap_gpmc_reset(s);
+        s->sysconfig = value & 0x19;
+        break;
+
+    case 0x018:	/* GPMC_IRQSTATUS */
+        s->irqen = ~value;
+        omap_gpmc_int_update(s);
+        break;
+
+    case 0x01c:	/* GPMC_IRQENABLE */
+        s->irqen = value & 0xf03;
+        omap_gpmc_int_update(s);
+        break;
+
+    case 0x040:	/* GPMC_TIMEOUT_CONTROL */
+        s->timeout = value & 0x1ff1;
+        break;
+
+    case 0x044:	/* GPMC_ERR_ADDRESS */
+    case 0x048:	/* GPMC_ERR_TYPE */
+        break;
+
+    case 0x050:	/* GPMC_CONFIG */
+        s->config = value & 0xf13;
+        break;
+
+    case 0x060 ... 0x1d4:
+        cs = (addr - 0x060) / 0x30;
+        addr -= cs * 0x30;
+        f = s->cs_file + cs;
+        switch (addr) {
+            case 0x60:	/* GPMC_CONFIG1 */
+                f->config[0] = value & 0xffef3e13;
+                break;
+            case 0x64:	/* GPMC_CONFIG2 */
+                f->config[1] = value & 0x001f1f8f;
+                break;
+            case 0x68:	/* GPMC_CONFIG3 */
+                f->config[2] = value & 0x001f1f8f;
+                break;
+            case 0x6c:	/* GPMC_CONFIG4 */
+                f->config[3] = value & 0x1f8f1f8f;
+                break;
+            case 0x70:	/* GPMC_CONFIG5 */
+                f->config[4] = value & 0x0f1f1f1f;
+                break;
+            case 0x74:	/* GPMC_CONFIG6 */
+                f->config[5] = value & 0x00000fcf;
+                break;
+            case 0x78:	/* GPMC_CONFIG7 */
+                if ((f->config[6] ^ value) & 0xf7f) {
+                    if (f->config[6] & (1 << 6))		/* CSVALID */
+                        omap_gpmc_cs_unmap(f);
+                    if (value & (1 << 6))			/* CSVALID */
+                        omap_gpmc_cs_map(f, value & 0x1f,	/* MASKADDR */
+                                        (value >> 8 & 0xf));	/* BASEADDR */
+                }
+                f->config[6] = value & 0x00000f7f;
+                break;
+            case 0x7c:	/* GPMC_NAND_COMMAND */
+            case 0x80:	/* GPMC_NAND_ADDRESS */
+            case 0x84:	/* GPMC_NAND_DATA */
+                break;
+
+            default:
+                goto bad_reg;
+        }
+        break;
+
+    case 0x1e0:	/* GPMC_PREFETCH_CONFIG1 */
+        s->prefconfig[0] = value & 0x7f8f7fbf;
+        /* TODO: update interrupts, fifos, dmas */
+        break;
+
+    case 0x1e4:	/* GPMC_PREFETCH_CONFIG2 */
+        s->prefconfig[1] = value & 0x3fff;
+        break;
+
+    case 0x1ec:	/* GPMC_PREFETCH_CONTROL */
+        s->prefcontrol = value & 1;
+        if (s->prefcontrol) {
+            if (s->prefconfig[0] & 1)
+                s->preffifo = 0x40;
+            else
+                s->preffifo = 0x00;
+        }
+        /* TODO: start */
+        break;
+
+    case 0x1f4:	/* GPMC_ECC_CONFIG */
+        s->ecc_cs = 0x8f;
+        break;
+    case 0x1f8:	/* GPMC_ECC_CONTROL */
+        if (value & (1 << 8))
+            for (cs = 0; cs < 9; cs ++)
+                ecc_reset(&s->ecc[cs]);
+        s->ecc_ptr = value & 0xf;
+        if (s->ecc_ptr == 0 || s->ecc_ptr > 9) {
+            s->ecc_ptr = 0;
+            s->ecc_cs &= ~1;
+        }
+        break;
+    case 0x1fc:	/* GPMC_ECC_SIZE_CONFIG */
+        s->ecc_cfg = value & 0x3fcff1ff;
+        break;
+    case 0x230:	/* GPMC_TESTMODE_CTRL */
+        if (value & 7)
+            fprintf(stderr, "%s: test mode enable attempt\n", __FUNCTION__);
+        break;
+
+    default:
+    bad_reg:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc * const omap_gpmc_readfn[] = {
+    omap_badwidth_read32,	/* TODO */
+    omap_badwidth_read32,	/* TODO */
+    omap_gpmc_read,
+};
+
+static CPUWriteMemoryFunc * const omap_gpmc_writefn[] = {
+    omap_badwidth_write32,	/* TODO */
+    omap_badwidth_write32,	/* TODO */
+    omap_gpmc_write,
+};
+
+struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq)
+{
+    int iomemtype;
+    struct omap_gpmc_s *s = (struct omap_gpmc_s *)
+            qemu_mallocz(sizeof(struct omap_gpmc_s));
+
+    omap_gpmc_reset(s);
+
+    iomemtype = cpu_register_io_memory(omap_gpmc_readfn,
+                    omap_gpmc_writefn, s);
+    cpu_register_physical_memory(base, 0x1000, iomemtype);
+
+    return s;
+}
+
+void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
+                void (*base_upd)(void *opaque, target_phys_addr_t new),
+                void (*unmap)(void *opaque), void *opaque)
+{
+    struct omap_gpmc_cs_file_s *f;
+
+    if (cs < 0 || cs >= 8) {
+        fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs);
+        exit(-1);
+    }
+    f = &s->cs_file[cs];
+
+    f->iomemtype = iomemtype;
+    f->base_update = base_upd;
+    f->unmap = unmap;
+    f->opaque = opaque;
+
+    if (f->config[6] & (1 << 6))				/* CSVALID */
+        omap_gpmc_cs_map(f, f->config[6] & 0x1f,		/* MASKADDR */
+                        (f->config[6] >> 8 & 0xf));		/* BASEADDR */
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 06/12] hw/omap2.c : separate sdrc (sdram controller)
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (4 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 05/12] hw/omap2.c : separate gpmc(general purpose memory controller) cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 07/12] hw/omap1.c : separate interrupt controller module cmchao
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    2 +-
 hw/omap.h       |    2 +
 hw/omap2.c      |  144 ------------------------------------------------
 hw/omap_sdrc.c  |  165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 168 insertions(+), 145 deletions(-)
 create mode 100644 hw/omap_sdrc.c

diff --git a/Makefile.target b/Makefile.target
index e6abaa7..59dd0d4 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -264,7 +264,7 @@ 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
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o
+obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o omap_sdrc.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
diff --git a/hw/omap.h b/hw/omap.h
index c596953..ad4a465 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -90,8 +90,10 @@ struct omap_sysctl_s;
 struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
                 omap_clk iclk, struct omap_mpu_state_s *mpu);
 
+/* OMAP2 SDRAM controller */
 struct omap_sdrc_s;
 struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
+void omap_sdrc_reset(struct omap_sdrc_s *s);
 
 /* OMAP2 general purpose memory controller */
 struct omap_gpmc_s;
diff --git a/hw/omap2.c b/hw/omap2.c
index b1e5aae..e6d1b52 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2844,150 +2844,6 @@ struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
     return s;
 }
 
-/* SDRAM Controller Subsystem */
-struct omap_sdrc_s {
-    uint8_t config;
-};
-
-static void omap_sdrc_reset(struct omap_sdrc_s *s)
-{
-    s->config = 0x10;
-}
-
-static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* SDRC_REVISION */
-        return 0x20;
-
-    case 0x10:	/* SDRC_SYSCONFIG */
-        return s->config;
-
-    case 0x14:	/* SDRC_SYSSTATUS */
-        return 1;						/* RESETDONE */
-
-    case 0x40:	/* SDRC_CS_CFG */
-    case 0x44:	/* SDRC_SHARING */
-    case 0x48:	/* SDRC_ERR_ADDR */
-    case 0x4c:	/* SDRC_ERR_TYPE */
-    case 0x60:	/* SDRC_DLLA_SCTRL */
-    case 0x64:	/* SDRC_DLLA_STATUS */
-    case 0x68:	/* SDRC_DLLB_CTRL */
-    case 0x6c:	/* SDRC_DLLB_STATUS */
-    case 0x70:	/* SDRC_POWER */
-    case 0x80:	/* SDRC_MCFG_0 */
-    case 0x84:	/* SDRC_MR_0 */
-    case 0x88:	/* SDRC_EMR1_0 */
-    case 0x8c:	/* SDRC_EMR2_0 */
-    case 0x90:	/* SDRC_EMR3_0 */
-    case 0x94:	/* SDRC_DCDL1_CTRL */
-    case 0x98:	/* SDRC_DCDL2_CTRL */
-    case 0x9c:	/* SDRC_ACTIM_CTRLA_0 */
-    case 0xa0:	/* SDRC_ACTIM_CTRLB_0 */
-    case 0xa4:	/* SDRC_RFR_CTRL_0 */
-    case 0xa8:	/* SDRC_MANUAL_0 */
-    case 0xb0:	/* SDRC_MCFG_1 */
-    case 0xb4:	/* SDRC_MR_1 */
-    case 0xb8:	/* SDRC_EMR1_1 */
-    case 0xbc:	/* SDRC_EMR2_1 */
-    case 0xc0:	/* SDRC_EMR3_1 */
-    case 0xc4:	/* SDRC_ACTIM_CTRLA_1 */
-    case 0xc8:	/* SDRC_ACTIM_CTRLB_1 */
-    case 0xd4:	/* SDRC_RFR_CTRL_1 */
-    case 0xd8:	/* SDRC_MANUAL_1 */
-        return 0x00;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* SDRC_REVISION */
-    case 0x14:	/* SDRC_SYSSTATUS */
-    case 0x48:	/* SDRC_ERR_ADDR */
-    case 0x64:	/* SDRC_DLLA_STATUS */
-    case 0x6c:	/* SDRC_DLLB_STATUS */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x10:	/* SDRC_SYSCONFIG */
-        if ((value >> 3) != 0x2)
-            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
-                            __FUNCTION__, value >> 3);
-        if (value & 2)
-            omap_sdrc_reset(s);
-        s->config = value & 0x18;
-        break;
-
-    case 0x40:	/* SDRC_CS_CFG */
-    case 0x44:	/* SDRC_SHARING */
-    case 0x4c:	/* SDRC_ERR_TYPE */
-    case 0x60:	/* SDRC_DLLA_SCTRL */
-    case 0x68:	/* SDRC_DLLB_CTRL */
-    case 0x70:	/* SDRC_POWER */
-    case 0x80:	/* SDRC_MCFG_0 */
-    case 0x84:	/* SDRC_MR_0 */
-    case 0x88:	/* SDRC_EMR1_0 */
-    case 0x8c:	/* SDRC_EMR2_0 */
-    case 0x90:	/* SDRC_EMR3_0 */
-    case 0x94:	/* SDRC_DCDL1_CTRL */
-    case 0x98:	/* SDRC_DCDL2_CTRL */
-    case 0x9c:	/* SDRC_ACTIM_CTRLA_0 */
-    case 0xa0:	/* SDRC_ACTIM_CTRLB_0 */
-    case 0xa4:	/* SDRC_RFR_CTRL_0 */
-    case 0xa8:	/* SDRC_MANUAL_0 */
-    case 0xb0:	/* SDRC_MCFG_1 */
-    case 0xb4:	/* SDRC_MR_1 */
-    case 0xb8:	/* SDRC_EMR1_1 */
-    case 0xbc:	/* SDRC_EMR2_1 */
-    case 0xc0:	/* SDRC_EMR3_1 */
-    case 0xc4:	/* SDRC_ACTIM_CTRLA_1 */
-    case 0xc8:	/* SDRC_ACTIM_CTRLB_1 */
-    case 0xd4:	/* SDRC_RFR_CTRL_1 */
-    case 0xd8:	/* SDRC_MANUAL_1 */
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static CPUReadMemoryFunc * const omap_sdrc_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_sdrc_read,
-};
-
-static CPUWriteMemoryFunc * const omap_sdrc_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_sdrc_write,
-};
-
-struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
-{
-    int iomemtype;
-    struct omap_sdrc_s *s = (struct omap_sdrc_s *)
-            qemu_mallocz(sizeof(struct omap_sdrc_s));
-
-    omap_sdrc_reset(s);
-
-    iomemtype = cpu_register_io_memory(omap_sdrc_readfn,
-                    omap_sdrc_writefn, s);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
-
-    return s;
-}
-
 /* General chip reset */
 static void omap2_mpu_reset(void *opaque)
 {
diff --git a/hw/omap_sdrc.c b/hw/omap_sdrc.c
new file mode 100644
index 0000000..aefaebe
--- /dev/null
+++ b/hw/omap_sdrc.c
@@ -0,0 +1,165 @@
+/*
+ * TI OMAP SDRAM controller emulation.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "omap.h"
+
+/* SDRAM Controller Subsystem */
+struct omap_sdrc_s {
+    uint8_t config;
+};
+
+void omap_sdrc_reset(struct omap_sdrc_s *s)
+{
+    s->config = 0x10;
+}
+
+static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* SDRC_REVISION */
+        return 0x20;
+
+    case 0x10:	/* SDRC_SYSCONFIG */
+        return s->config;
+
+    case 0x14:	/* SDRC_SYSSTATUS */
+        return 1;						/* RESETDONE */
+
+    case 0x40:	/* SDRC_CS_CFG */
+    case 0x44:	/* SDRC_SHARING */
+    case 0x48:	/* SDRC_ERR_ADDR */
+    case 0x4c:	/* SDRC_ERR_TYPE */
+    case 0x60:	/* SDRC_DLLA_SCTRL */
+    case 0x64:	/* SDRC_DLLA_STATUS */
+    case 0x68:	/* SDRC_DLLB_CTRL */
+    case 0x6c:	/* SDRC_DLLB_STATUS */
+    case 0x70:	/* SDRC_POWER */
+    case 0x80:	/* SDRC_MCFG_0 */
+    case 0x84:	/* SDRC_MR_0 */
+    case 0x88:	/* SDRC_EMR1_0 */
+    case 0x8c:	/* SDRC_EMR2_0 */
+    case 0x90:	/* SDRC_EMR3_0 */
+    case 0x94:	/* SDRC_DCDL1_CTRL */
+    case 0x98:	/* SDRC_DCDL2_CTRL */
+    case 0x9c:	/* SDRC_ACTIM_CTRLA_0 */
+    case 0xa0:	/* SDRC_ACTIM_CTRLB_0 */
+    case 0xa4:	/* SDRC_RFR_CTRL_0 */
+    case 0xa8:	/* SDRC_MANUAL_0 */
+    case 0xb0:	/* SDRC_MCFG_1 */
+    case 0xb4:	/* SDRC_MR_1 */
+    case 0xb8:	/* SDRC_EMR1_1 */
+    case 0xbc:	/* SDRC_EMR2_1 */
+    case 0xc0:	/* SDRC_EMR3_1 */
+    case 0xc4:	/* SDRC_ACTIM_CTRLA_1 */
+    case 0xc8:	/* SDRC_ACTIM_CTRLB_1 */
+    case 0xd4:	/* SDRC_RFR_CTRL_1 */
+    case 0xd8:	/* SDRC_MANUAL_1 */
+        return 0x00;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* SDRC_REVISION */
+    case 0x14:	/* SDRC_SYSSTATUS */
+    case 0x48:	/* SDRC_ERR_ADDR */
+    case 0x64:	/* SDRC_DLLA_STATUS */
+    case 0x6c:	/* SDRC_DLLB_STATUS */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x10:	/* SDRC_SYSCONFIG */
+        if ((value >> 3) != 0x2)
+            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
+                            __FUNCTION__, value >> 3);
+        if (value & 2)
+            omap_sdrc_reset(s);
+        s->config = value & 0x18;
+        break;
+
+    case 0x40:	/* SDRC_CS_CFG */
+    case 0x44:	/* SDRC_SHARING */
+    case 0x4c:	/* SDRC_ERR_TYPE */
+    case 0x60:	/* SDRC_DLLA_SCTRL */
+    case 0x68:	/* SDRC_DLLB_CTRL */
+    case 0x70:	/* SDRC_POWER */
+    case 0x80:	/* SDRC_MCFG_0 */
+    case 0x84:	/* SDRC_MR_0 */
+    case 0x88:	/* SDRC_EMR1_0 */
+    case 0x8c:	/* SDRC_EMR2_0 */
+    case 0x90:	/* SDRC_EMR3_0 */
+    case 0x94:	/* SDRC_DCDL1_CTRL */
+    case 0x98:	/* SDRC_DCDL2_CTRL */
+    case 0x9c:	/* SDRC_ACTIM_CTRLA_0 */
+    case 0xa0:	/* SDRC_ACTIM_CTRLB_0 */
+    case 0xa4:	/* SDRC_RFR_CTRL_0 */
+    case 0xa8:	/* SDRC_MANUAL_0 */
+    case 0xb0:	/* SDRC_MCFG_1 */
+    case 0xb4:	/* SDRC_MR_1 */
+    case 0xb8:	/* SDRC_EMR1_1 */
+    case 0xbc:	/* SDRC_EMR2_1 */
+    case 0xc0:	/* SDRC_EMR3_1 */
+    case 0xc4:	/* SDRC_ACTIM_CTRLA_1 */
+    case 0xc8:	/* SDRC_ACTIM_CTRLB_1 */
+    case 0xd4:	/* SDRC_RFR_CTRL_1 */
+    case 0xd8:	/* SDRC_MANUAL_1 */
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc * const omap_sdrc_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap_sdrc_read,
+};
+
+static CPUWriteMemoryFunc * const omap_sdrc_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap_sdrc_write,
+};
+
+struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
+{
+    int iomemtype;
+    struct omap_sdrc_s *s = (struct omap_sdrc_s *)
+            qemu_mallocz(sizeof(struct omap_sdrc_s));
+
+    omap_sdrc_reset(s);
+
+    iomemtype = cpu_register_io_memory(omap_sdrc_readfn,
+                    omap_sdrc_writefn, s);
+    cpu_register_physical_memory(base, 0x1000, iomemtype);
+
+    return s;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 07/12] hw/omap1.c : separate interrupt controller module
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (5 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 06/12] hw/omap2.c : separate sdrc (sdram controller) cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 08/12] hw/omap2.c : separate spi module cmchao
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    2 +-
 hw/omap.h       |    2 +
 hw/omap1.c      |  576 +----------------------------------------------------
 hw/omap_intc.c  |  598 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 603 insertions(+), 575 deletions(-)
 create mode 100644 hw/omap_intc.c

diff --git a/Makefile.target b/Makefile.target
index 59dd0d4..9a309e2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -263,7 +263,7 @@ 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
+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
 obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o omap_sdrc.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
diff --git a/hw/omap.h b/hw/omap.h
index ad4a465..ea23ec9 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -71,6 +71,7 @@ target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
                 int iotype);
 # define l4_register_io_memory	cpu_register_io_memory
 
+/* OMAP interrupt controller */
 struct omap_intr_handler_s;
 struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
                 unsigned long size, unsigned char nbanks, qemu_irq **pins,
@@ -80,6 +81,7 @@ struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
                 qemu_irq parent_irq, qemu_irq parent_fiq,
                 omap_clk fclk, omap_clk iclk);
 void omap_inth_reset(struct omap_intr_handler_s *s);
+qemu_irq omap_inth_get_pin(struct omap_intr_handler_s *s, int n);
 
 struct omap_prcm_s;
 struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
diff --git a/hw/omap1.c b/hw/omap1.c
index 8b78c05..21c53fe 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -79,578 +79,6 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
     cpu_physical_memory_write(addr, (void *) &value, 4);
 }
 
-/* Interrupt Handlers */
-struct omap_intr_handler_bank_s {
-    uint32_t irqs;
-    uint32_t inputs;
-    uint32_t mask;
-    uint32_t fiq;
-    uint32_t sens_edge;
-    uint32_t swi;
-    unsigned char priority[32];
-};
-
-struct omap_intr_handler_s {
-    qemu_irq *pins;
-    qemu_irq parent_intr[2];
-    unsigned char nbanks;
-    int level_only;
-
-    /* state */
-    uint32_t new_agr[2];
-    int sir_intr[2];
-    int autoidle;
-    uint32_t mask;
-    struct omap_intr_handler_bank_s bank[];
-};
-
-static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
-{
-    int i, j, sir_intr, p_intr, p, f;
-    uint32_t level;
-    sir_intr = 0;
-    p_intr = 255;
-
-    /* Find the interrupt line with the highest dynamic priority.
-     * Note: 0 denotes the hightest priority.
-     * If all interrupts have the same priority, the default order is IRQ_N,
-     * IRQ_N-1,...,IRQ_0. */
-    for (j = 0; j < s->nbanks; ++j) {
-        level = s->bank[j].irqs & ~s->bank[j].mask &
-                (is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq);
-        for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f,
-                        level >>= f) {
-            p = s->bank[j].priority[i];
-            if (p <= p_intr) {
-                p_intr = p;
-                sir_intr = 32 * j + i;
-            }
-            f = ffs(level >> 1);
-        }
-    }
-    s->sir_intr[is_fiq] = sir_intr;
-}
-
-static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
-{
-    int i;
-    uint32_t has_intr = 0;
-
-    for (i = 0; i < s->nbanks; ++i)
-        has_intr |= s->bank[i].irqs & ~s->bank[i].mask &
-                (is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq);
-
-    if (s->new_agr[is_fiq] & has_intr & s->mask) {
-        s->new_agr[is_fiq] = 0;
-        omap_inth_sir_update(s, is_fiq);
-        qemu_set_irq(s->parent_intr[is_fiq], 1);
-    }
-}
-
-#define INT_FALLING_EDGE	0
-#define INT_LOW_LEVEL		1
-
-static void omap_set_intr(void *opaque, int irq, int req)
-{
-    struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
-    uint32_t rise;
-
-    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
-    int n = irq & 31;
-
-    if (req) {
-        rise = ~bank->irqs & (1 << n);
-        if (~bank->sens_edge & (1 << n))
-            rise &= ~bank->inputs;
-
-        bank->inputs |= (1 << n);
-        if (rise) {
-            bank->irqs |= rise;
-            omap_inth_update(ih, 0);
-            omap_inth_update(ih, 1);
-        }
-    } else {
-        rise = bank->sens_edge & bank->irqs & (1 << n);
-        bank->irqs &= ~rise;
-        bank->inputs &= ~(1 << n);
-    }
-}
-
-/* Simplified version with no edge detection */
-static void omap_set_intr_noedge(void *opaque, int irq, int req)
-{
-    struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
-    uint32_t rise;
-
-    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
-    int n = irq & 31;
-
-    if (req) {
-        rise = ~bank->inputs & (1 << n);
-        if (rise) {
-            bank->irqs |= bank->inputs |= rise;
-            omap_inth_update(ih, 0);
-            omap_inth_update(ih, 1);
-        }
-    } else
-        bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi;
-}
-
-static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-    int i, offset = addr;
-    int bank_no = offset >> 8;
-    int line_no;
-    struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
-    offset &= 0xff;
-
-    switch (offset) {
-    case 0x00:	/* ITR */
-        return bank->irqs;
-
-    case 0x04:	/* MIR */
-        return bank->mask;
-
-    case 0x10:	/* SIR_IRQ_CODE */
-    case 0x14:  /* SIR_FIQ_CODE */
-        if (bank_no != 0)
-            break;
-        line_no = s->sir_intr[(offset - 0x10) >> 2];
-        bank = &s->bank[line_no >> 5];
-        i = line_no & 31;
-        if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE)
-            bank->irqs &= ~(1 << i);
-        return line_no;
-
-    case 0x18:	/* CONTROL_REG */
-        if (bank_no != 0)
-            break;
-        return 0;
-
-    case 0x1c:	/* ILR0 */
-    case 0x20:	/* ILR1 */
-    case 0x24:	/* ILR2 */
-    case 0x28:	/* ILR3 */
-    case 0x2c:	/* ILR4 */
-    case 0x30:	/* ILR5 */
-    case 0x34:	/* ILR6 */
-    case 0x38:	/* ILR7 */
-    case 0x3c:	/* ILR8 */
-    case 0x40:	/* ILR9 */
-    case 0x44:	/* ILR10 */
-    case 0x48:	/* ILR11 */
-    case 0x4c:	/* ILR12 */
-    case 0x50:	/* ILR13 */
-    case 0x54:	/* ILR14 */
-    case 0x58:	/* ILR15 */
-    case 0x5c:	/* ILR16 */
-    case 0x60:	/* ILR17 */
-    case 0x64:	/* ILR18 */
-    case 0x68:	/* ILR19 */
-    case 0x6c:	/* ILR20 */
-    case 0x70:	/* ILR21 */
-    case 0x74:	/* ILR22 */
-    case 0x78:	/* ILR23 */
-    case 0x7c:	/* ILR24 */
-    case 0x80:	/* ILR25 */
-    case 0x84:	/* ILR26 */
-    case 0x88:	/* ILR27 */
-    case 0x8c:	/* ILR28 */
-    case 0x90:	/* ILR29 */
-    case 0x94:	/* ILR30 */
-    case 0x98:	/* ILR31 */
-        i = (offset - 0x1c) >> 2;
-        return (bank->priority[i] << 2) |
-                (((bank->sens_edge >> i) & 1) << 1) |
-                ((bank->fiq >> i) & 1);
-
-    case 0x9c:	/* ISR */
-        return 0x00000000;
-
-    }
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_inth_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-    int i, offset = addr;
-    int bank_no = offset >> 8;
-    struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
-    offset &= 0xff;
-
-    switch (offset) {
-    case 0x00:	/* ITR */
-        /* Important: ignore the clearing if the IRQ is level-triggered and
-           the input bit is 1 */
-        bank->irqs &= value | (bank->inputs & bank->sens_edge);
-        return;
-
-    case 0x04:	/* MIR */
-        bank->mask = value;
-        omap_inth_update(s, 0);
-        omap_inth_update(s, 1);
-        return;
-
-    case 0x10:	/* SIR_IRQ_CODE */
-    case 0x14:	/* SIR_FIQ_CODE */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x18:	/* CONTROL_REG */
-        if (bank_no != 0)
-            break;
-        if (value & 2) {
-            qemu_set_irq(s->parent_intr[1], 0);
-            s->new_agr[1] = ~0;
-            omap_inth_update(s, 1);
-        }
-        if (value & 1) {
-            qemu_set_irq(s->parent_intr[0], 0);
-            s->new_agr[0] = ~0;
-            omap_inth_update(s, 0);
-        }
-        return;
-
-    case 0x1c:	/* ILR0 */
-    case 0x20:	/* ILR1 */
-    case 0x24:	/* ILR2 */
-    case 0x28:	/* ILR3 */
-    case 0x2c:	/* ILR4 */
-    case 0x30:	/* ILR5 */
-    case 0x34:	/* ILR6 */
-    case 0x38:	/* ILR7 */
-    case 0x3c:	/* ILR8 */
-    case 0x40:	/* ILR9 */
-    case 0x44:	/* ILR10 */
-    case 0x48:	/* ILR11 */
-    case 0x4c:	/* ILR12 */
-    case 0x50:	/* ILR13 */
-    case 0x54:	/* ILR14 */
-    case 0x58:	/* ILR15 */
-    case 0x5c:	/* ILR16 */
-    case 0x60:	/* ILR17 */
-    case 0x64:	/* ILR18 */
-    case 0x68:	/* ILR19 */
-    case 0x6c:	/* ILR20 */
-    case 0x70:	/* ILR21 */
-    case 0x74:	/* ILR22 */
-    case 0x78:	/* ILR23 */
-    case 0x7c:	/* ILR24 */
-    case 0x80:	/* ILR25 */
-    case 0x84:	/* ILR26 */
-    case 0x88:	/* ILR27 */
-    case 0x8c:	/* ILR28 */
-    case 0x90:	/* ILR29 */
-    case 0x94:	/* ILR30 */
-    case 0x98:	/* ILR31 */
-        i = (offset - 0x1c) >> 2;
-        bank->priority[i] = (value >> 2) & 0x1f;
-        bank->sens_edge &= ~(1 << i);
-        bank->sens_edge |= ((value >> 1) & 1) << i;
-        bank->fiq &= ~(1 << i);
-        bank->fiq |= (value & 1) << i;
-        return;
-
-    case 0x9c:	/* ISR */
-        for (i = 0; i < 32; i ++)
-            if (value & (1 << i)) {
-                omap_set_intr(s, 32 * bank_no + i, 1);
-                return;
-            }
-        return;
-    }
-    OMAP_BAD_REG(addr);
-}
-
-static CPUReadMemoryFunc * const omap_inth_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_inth_read,
-};
-
-static CPUWriteMemoryFunc * const omap_inth_writefn[] = {
-    omap_inth_write,
-    omap_inth_write,
-    omap_inth_write,
-};
-
-void omap_inth_reset(struct omap_intr_handler_s *s)
-{
-    int i;
-
-    for (i = 0; i < s->nbanks; ++i){
-        s->bank[i].irqs = 0x00000000;
-        s->bank[i].mask = 0xffffffff;
-        s->bank[i].sens_edge = 0x00000000;
-        s->bank[i].fiq = 0x00000000;
-        s->bank[i].inputs = 0x00000000;
-        s->bank[i].swi = 0x00000000;
-        memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority));
-
-        if (s->level_only)
-            s->bank[i].sens_edge = 0xffffffff;
-    }
-
-    s->new_agr[0] = ~0;
-    s->new_agr[1] = ~0;
-    s->sir_intr[0] = 0;
-    s->sir_intr[1] = 0;
-    s->autoidle = 0;
-    s->mask = ~0;
-
-    qemu_set_irq(s->parent_intr[0], 0);
-    qemu_set_irq(s->parent_intr[1], 0);
-}
-
-struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
-                unsigned long size, unsigned char nbanks, qemu_irq **pins,
-                qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk)
-{
-    int iomemtype;
-    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
-            qemu_mallocz(sizeof(struct omap_intr_handler_s) +
-                            sizeof(struct omap_intr_handler_bank_s) * nbanks);
-
-    s->parent_intr[0] = parent_irq;
-    s->parent_intr[1] = parent_fiq;
-    s->nbanks = nbanks;
-    s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32);
-    if (pins)
-        *pins = s->pins;
-
-    omap_inth_reset(s);
-
-    iomemtype = cpu_register_io_memory(omap_inth_readfn,
-                    omap_inth_writefn, s);
-    cpu_register_physical_memory(base, size, iomemtype);
-
-    return s;
-}
-
-static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-    int offset = addr;
-    int bank_no, line_no;
-    struct omap_intr_handler_bank_s *bank = NULL;
-
-    if ((offset & 0xf80) == 0x80) {
-        bank_no = (offset & 0x60) >> 5;
-        if (bank_no < s->nbanks) {
-            offset &= ~0x60;
-            bank = &s->bank[bank_no];
-        }
-    }
-
-    switch (offset) {
-    case 0x00:	/* INTC_REVISION */
-        return 0x21;
-
-    case 0x10:	/* INTC_SYSCONFIG */
-        return (s->autoidle >> 2) & 1;
-
-    case 0x14:	/* INTC_SYSSTATUS */
-        return 1;						/* RESETDONE */
-
-    case 0x40:	/* INTC_SIR_IRQ */
-        return s->sir_intr[0];
-
-    case 0x44:	/* INTC_SIR_FIQ */
-        return s->sir_intr[1];
-
-    case 0x48:	/* INTC_CONTROL */
-        return (!s->mask) << 2;					/* GLOBALMASK */
-
-    case 0x4c:	/* INTC_PROTECTION */
-        return 0;
-
-    case 0x50:	/* INTC_IDLE */
-        return s->autoidle & 3;
-
-    /* Per-bank registers */
-    case 0x80:	/* INTC_ITR */
-        return bank->inputs;
-
-    case 0x84:	/* INTC_MIR */
-        return bank->mask;
-
-    case 0x88:	/* INTC_MIR_CLEAR */
-    case 0x8c:	/* INTC_MIR_SET */
-        return 0;
-
-    case 0x90:	/* INTC_ISR_SET */
-        return bank->swi;
-
-    case 0x94:	/* INTC_ISR_CLEAR */
-        return 0;
-
-    case 0x98:	/* INTC_PENDING_IRQ */
-        return bank->irqs & ~bank->mask & ~bank->fiq;
-
-    case 0x9c:	/* INTC_PENDING_FIQ */
-        return bank->irqs & ~bank->mask & bank->fiq;
-
-    /* Per-line registers */
-    case 0x100 ... 0x300:	/* INTC_ILR */
-        bank_no = (offset - 0x100) >> 7;
-        if (bank_no > s->nbanks)
-            break;
-        bank = &s->bank[bank_no];
-        line_no = (offset & 0x7f) >> 2;
-        return (bank->priority[line_no] << 2) |
-                ((bank->fiq >> line_no) & 1);
-    }
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
-    int offset = addr;
-    int bank_no, line_no;
-    struct omap_intr_handler_bank_s *bank = NULL;
-
-    if ((offset & 0xf80) == 0x80) {
-        bank_no = (offset & 0x60) >> 5;
-        if (bank_no < s->nbanks) {
-            offset &= ~0x60;
-            bank = &s->bank[bank_no];
-        }
-    }
-
-    switch (offset) {
-    case 0x10:	/* INTC_SYSCONFIG */
-        s->autoidle &= 4;
-        s->autoidle |= (value & 1) << 2;
-        if (value & 2)						/* SOFTRESET */
-            omap_inth_reset(s);
-        return;
-
-    case 0x48:	/* INTC_CONTROL */
-        s->mask = (value & 4) ? 0 : ~0;				/* GLOBALMASK */
-        if (value & 2) {					/* NEWFIQAGR */
-            qemu_set_irq(s->parent_intr[1], 0);
-            s->new_agr[1] = ~0;
-            omap_inth_update(s, 1);
-        }
-        if (value & 1) {					/* NEWIRQAGR */
-            qemu_set_irq(s->parent_intr[0], 0);
-            s->new_agr[0] = ~0;
-            omap_inth_update(s, 0);
-        }
-        return;
-
-    case 0x4c:	/* INTC_PROTECTION */
-        /* TODO: Make a bitmap (or sizeof(char)map) of access privileges
-         * for every register, see Chapter 3 and 4 for privileged mode.  */
-        if (value & 1)
-            fprintf(stderr, "%s: protection mode enable attempt\n",
-                            __FUNCTION__);
-        return;
-
-    case 0x50:	/* INTC_IDLE */
-        s->autoidle &= ~3;
-        s->autoidle |= value & 3;
-        return;
-
-    /* Per-bank registers */
-    case 0x84:	/* INTC_MIR */
-        bank->mask = value;
-        omap_inth_update(s, 0);
-        omap_inth_update(s, 1);
-        return;
-
-    case 0x88:	/* INTC_MIR_CLEAR */
-        bank->mask &= ~value;
-        omap_inth_update(s, 0);
-        omap_inth_update(s, 1);
-        return;
-
-    case 0x8c:	/* INTC_MIR_SET */
-        bank->mask |= value;
-        return;
-
-    case 0x90:	/* INTC_ISR_SET */
-        bank->irqs |= bank->swi |= value;
-        omap_inth_update(s, 0);
-        omap_inth_update(s, 1);
-        return;
-
-    case 0x94:	/* INTC_ISR_CLEAR */
-        bank->swi &= ~value;
-        bank->irqs = bank->swi & bank->inputs;
-        return;
-
-    /* Per-line registers */
-    case 0x100 ... 0x300:	/* INTC_ILR */
-        bank_no = (offset - 0x100) >> 7;
-        if (bank_no > s->nbanks)
-            break;
-        bank = &s->bank[bank_no];
-        line_no = (offset & 0x7f) >> 2;
-        bank->priority[line_no] = (value >> 2) & 0x3f;
-        bank->fiq &= ~(1 << line_no);
-        bank->fiq |= (value & 1) << line_no;
-        return;
-
-    case 0x00:	/* INTC_REVISION */
-    case 0x14:	/* INTC_SYSSTATUS */
-    case 0x40:	/* INTC_SIR_IRQ */
-    case 0x44:	/* INTC_SIR_FIQ */
-    case 0x80:	/* INTC_ITR */
-    case 0x98:	/* INTC_PENDING_IRQ */
-    case 0x9c:	/* INTC_PENDING_FIQ */
-        OMAP_RO_REG(addr);
-        return;
-    }
-    OMAP_BAD_REG(addr);
-}
-
-static CPUReadMemoryFunc * const omap2_inth_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap2_inth_read,
-};
-
-static CPUWriteMemoryFunc * const omap2_inth_writefn[] = {
-    omap2_inth_write,
-    omap2_inth_write,
-    omap2_inth_write,
-};
-
-struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
-                int size, int nbanks, qemu_irq **pins,
-                qemu_irq parent_irq, qemu_irq parent_fiq,
-                omap_clk fclk, omap_clk iclk)
-{
-    int iomemtype;
-    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
-            qemu_mallocz(sizeof(struct omap_intr_handler_s) +
-                            sizeof(struct omap_intr_handler_bank_s) * nbanks);
-
-    s->parent_intr[0] = parent_irq;
-    s->parent_intr[1] = parent_fiq;
-    s->nbanks = nbanks;
-    s->level_only = 1;
-    s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32);
-    if (pins)
-        *pins = s->pins;
-
-    omap_inth_reset(s);
-
-    iomemtype = cpu_register_io_memory(omap2_inth_readfn,
-                    omap2_inth_writefn, s);
-    cpu_register_physical_memory(base, size, iomemtype);
-
-    return s;
-}
-
 /* MPU OS timers */
 struct omap_mpu_timer_s {
     qemu_irq irq;
@@ -4485,8 +3913,8 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
                     cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
                     omap_findclk(s, "arminth_ck"));
     s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, &s->irq[1],
-                    s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], NULL,
-                    omap_findclk(s, "arminth_ck"));
+                    omap_inth_get_pin(s->ih[0], OMAP_INT_15XX_IH2_IRQ),
+		    NULL, omap_findclk(s, "arminth_ck"));
 
     for (i = 0; i < 6; i ++)
         dma_irqs[i] =
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
new file mode 100644
index 0000000..59893b7
--- /dev/null
+++ b/hw/omap_intc.c
@@ -0,0 +1,598 @@
+/*
+ * TI OMAP interrupt controller emulation.
+ *
+ * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "omap.h"
+
+/* Interrupt Handlers */
+struct omap_intr_handler_bank_s {
+    uint32_t irqs;
+    uint32_t inputs;
+    uint32_t mask;
+    uint32_t fiq;
+    uint32_t sens_edge;
+    uint32_t swi;
+    unsigned char priority[32];
+};
+
+struct omap_intr_handler_s {
+    qemu_irq *pins;
+    qemu_irq parent_intr[2];
+    unsigned char nbanks;
+    int level_only;
+
+    /* state */
+    uint32_t new_agr[2];
+    int sir_intr[2];
+    int autoidle;
+    uint32_t mask;
+    struct omap_intr_handler_bank_s bank[];
+};
+
+inline qemu_irq omap_inth_get_pin(struct omap_intr_handler_s *s, int n)
+{
+    return s->pins[n];
+}
+
+static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
+{
+    int i, j, sir_intr, p_intr, p, f;
+    uint32_t level;
+    sir_intr = 0;
+    p_intr = 255;
+
+    /* Find the interrupt line with the highest dynamic priority.
+     * Note: 0 denotes the hightest priority.
+     * If all interrupts have the same priority, the default order is IRQ_N,
+     * IRQ_N-1,...,IRQ_0. */
+    for (j = 0; j < s->nbanks; ++j) {
+        level = s->bank[j].irqs & ~s->bank[j].mask &
+                (is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq);
+        for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f,
+                        level >>= f) {
+            p = s->bank[j].priority[i];
+            if (p <= p_intr) {
+                p_intr = p;
+                sir_intr = 32 * j + i;
+            }
+            f = ffs(level >> 1);
+        }
+    }
+    s->sir_intr[is_fiq] = sir_intr;
+}
+
+static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
+{
+    int i;
+    uint32_t has_intr = 0;
+
+    for (i = 0; i < s->nbanks; ++i)
+        has_intr |= s->bank[i].irqs & ~s->bank[i].mask &
+                (is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq);
+
+    if (s->new_agr[is_fiq] & has_intr & s->mask) {
+        s->new_agr[is_fiq] = 0;
+        omap_inth_sir_update(s, is_fiq);
+        qemu_set_irq(s->parent_intr[is_fiq], 1);
+    }
+}
+
+#define INT_FALLING_EDGE	0
+#define INT_LOW_LEVEL		1
+
+static void omap_set_intr(void *opaque, int irq, int req)
+{
+    struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
+    uint32_t rise;
+
+    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
+    int n = irq & 31;
+
+    if (req) {
+        rise = ~bank->irqs & (1 << n);
+        if (~bank->sens_edge & (1 << n))
+            rise &= ~bank->inputs;
+
+        bank->inputs |= (1 << n);
+        if (rise) {
+            bank->irqs |= rise;
+            omap_inth_update(ih, 0);
+            omap_inth_update(ih, 1);
+        }
+    } else {
+        rise = bank->sens_edge & bank->irqs & (1 << n);
+        bank->irqs &= ~rise;
+        bank->inputs &= ~(1 << n);
+    }
+}
+
+/* Simplified version with no edge detection */
+static void omap_set_intr_noedge(void *opaque, int irq, int req)
+{
+    struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
+    uint32_t rise;
+
+    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
+    int n = irq & 31;
+
+    if (req) {
+        rise = ~bank->inputs & (1 << n);
+        if (rise) {
+            bank->irqs |= bank->inputs |= rise;
+            omap_inth_update(ih, 0);
+            omap_inth_update(ih, 1);
+        }
+    } else
+        bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi;
+}
+
+static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
+    int i, offset = addr;
+    int bank_no = offset >> 8;
+    int line_no;
+    struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
+    offset &= 0xff;
+
+    switch (offset) {
+    case 0x00:	/* ITR */
+        return bank->irqs;
+
+    case 0x04:	/* MIR */
+        return bank->mask;
+
+    case 0x10:	/* SIR_IRQ_CODE */
+    case 0x14:  /* SIR_FIQ_CODE */
+        if (bank_no != 0)
+            break;
+        line_no = s->sir_intr[(offset - 0x10) >> 2];
+        bank = &s->bank[line_no >> 5];
+        i = line_no & 31;
+        if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE)
+            bank->irqs &= ~(1 << i);
+        return line_no;
+
+    case 0x18:	/* CONTROL_REG */
+        if (bank_no != 0)
+            break;
+        return 0;
+
+    case 0x1c:	/* ILR0 */
+    case 0x20:	/* ILR1 */
+    case 0x24:	/* ILR2 */
+    case 0x28:	/* ILR3 */
+    case 0x2c:	/* ILR4 */
+    case 0x30:	/* ILR5 */
+    case 0x34:	/* ILR6 */
+    case 0x38:	/* ILR7 */
+    case 0x3c:	/* ILR8 */
+    case 0x40:	/* ILR9 */
+    case 0x44:	/* ILR10 */
+    case 0x48:	/* ILR11 */
+    case 0x4c:	/* ILR12 */
+    case 0x50:	/* ILR13 */
+    case 0x54:	/* ILR14 */
+    case 0x58:	/* ILR15 */
+    case 0x5c:	/* ILR16 */
+    case 0x60:	/* ILR17 */
+    case 0x64:	/* ILR18 */
+    case 0x68:	/* ILR19 */
+    case 0x6c:	/* ILR20 */
+    case 0x70:	/* ILR21 */
+    case 0x74:	/* ILR22 */
+    case 0x78:	/* ILR23 */
+    case 0x7c:	/* ILR24 */
+    case 0x80:	/* ILR25 */
+    case 0x84:	/* ILR26 */
+    case 0x88:	/* ILR27 */
+    case 0x8c:	/* ILR28 */
+    case 0x90:	/* ILR29 */
+    case 0x94:	/* ILR30 */
+    case 0x98:	/* ILR31 */
+        i = (offset - 0x1c) >> 2;
+        return (bank->priority[i] << 2) |
+                (((bank->sens_edge >> i) & 1) << 1) |
+                ((bank->fiq >> i) & 1);
+
+    case 0x9c:	/* ISR */
+        return 0x00000000;
+
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_inth_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
+    int i, offset = addr;
+    int bank_no = offset >> 8;
+    struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
+    offset &= 0xff;
+
+    switch (offset) {
+    case 0x00:	/* ITR */
+        /* Important: ignore the clearing if the IRQ is level-triggered and
+           the input bit is 1 */
+        bank->irqs &= value | (bank->inputs & bank->sens_edge);
+        return;
+
+    case 0x04:	/* MIR */
+        bank->mask = value;
+        omap_inth_update(s, 0);
+        omap_inth_update(s, 1);
+        return;
+
+    case 0x10:	/* SIR_IRQ_CODE */
+    case 0x14:	/* SIR_FIQ_CODE */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x18:	/* CONTROL_REG */
+        if (bank_no != 0)
+            break;
+        if (value & 2) {
+            qemu_set_irq(s->parent_intr[1], 0);
+            s->new_agr[1] = ~0;
+            omap_inth_update(s, 1);
+        }
+        if (value & 1) {
+            qemu_set_irq(s->parent_intr[0], 0);
+            s->new_agr[0] = ~0;
+            omap_inth_update(s, 0);
+        }
+        return;
+
+    case 0x1c:	/* ILR0 */
+    case 0x20:	/* ILR1 */
+    case 0x24:	/* ILR2 */
+    case 0x28:	/* ILR3 */
+    case 0x2c:	/* ILR4 */
+    case 0x30:	/* ILR5 */
+    case 0x34:	/* ILR6 */
+    case 0x38:	/* ILR7 */
+    case 0x3c:	/* ILR8 */
+    case 0x40:	/* ILR9 */
+    case 0x44:	/* ILR10 */
+    case 0x48:	/* ILR11 */
+    case 0x4c:	/* ILR12 */
+    case 0x50:	/* ILR13 */
+    case 0x54:	/* ILR14 */
+    case 0x58:	/* ILR15 */
+    case 0x5c:	/* ILR16 */
+    case 0x60:	/* ILR17 */
+    case 0x64:	/* ILR18 */
+    case 0x68:	/* ILR19 */
+    case 0x6c:	/* ILR20 */
+    case 0x70:	/* ILR21 */
+    case 0x74:	/* ILR22 */
+    case 0x78:	/* ILR23 */
+    case 0x7c:	/* ILR24 */
+    case 0x80:	/* ILR25 */
+    case 0x84:	/* ILR26 */
+    case 0x88:	/* ILR27 */
+    case 0x8c:	/* ILR28 */
+    case 0x90:	/* ILR29 */
+    case 0x94:	/* ILR30 */
+    case 0x98:	/* ILR31 */
+        i = (offset - 0x1c) >> 2;
+        bank->priority[i] = (value >> 2) & 0x1f;
+        bank->sens_edge &= ~(1 << i);
+        bank->sens_edge |= ((value >> 1) & 1) << i;
+        bank->fiq &= ~(1 << i);
+        bank->fiq |= (value & 1) << i;
+        return;
+
+    case 0x9c:	/* ISR */
+        for (i = 0; i < 32; i ++)
+            if (value & (1 << i)) {
+                omap_set_intr(s, 32 * bank_no + i, 1);
+                return;
+            }
+        return;
+    }
+    OMAP_BAD_REG(addr);
+}
+
+static CPUReadMemoryFunc * const omap_inth_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap_inth_read,
+};
+
+static CPUWriteMemoryFunc * const omap_inth_writefn[] = {
+    omap_inth_write,
+    omap_inth_write,
+    omap_inth_write,
+};
+
+void omap_inth_reset(struct omap_intr_handler_s *s)
+{
+    int i;
+
+    for (i = 0; i < s->nbanks; ++i){
+        s->bank[i].irqs = 0x00000000;
+        s->bank[i].mask = 0xffffffff;
+        s->bank[i].sens_edge = 0x00000000;
+        s->bank[i].fiq = 0x00000000;
+        s->bank[i].inputs = 0x00000000;
+        s->bank[i].swi = 0x00000000;
+        memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority));
+
+        if (s->level_only)
+            s->bank[i].sens_edge = 0xffffffff;
+    }
+
+    s->new_agr[0] = ~0;
+    s->new_agr[1] = ~0;
+    s->sir_intr[0] = 0;
+    s->sir_intr[1] = 0;
+    s->autoidle = 0;
+    s->mask = ~0;
+
+    qemu_set_irq(s->parent_intr[0], 0);
+    qemu_set_irq(s->parent_intr[1], 0);
+}
+
+struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
+                unsigned long size, unsigned char nbanks, qemu_irq **pins,
+                qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk)
+{
+    int iomemtype;
+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
+            qemu_mallocz(sizeof(struct omap_intr_handler_s) +
+                            sizeof(struct omap_intr_handler_bank_s) * nbanks);
+
+    s->parent_intr[0] = parent_irq;
+    s->parent_intr[1] = parent_fiq;
+    s->nbanks = nbanks;
+    s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32);
+    if (pins)
+        *pins = s->pins;
+
+    omap_inth_reset(s);
+
+    iomemtype = cpu_register_io_memory(omap_inth_readfn,
+                    omap_inth_writefn, s);
+    cpu_register_physical_memory(base, size, iomemtype);
+
+    return s;
+}
+
+static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
+    int offset = addr;
+    int bank_no, line_no;
+    struct omap_intr_handler_bank_s *bank = NULL;
+
+    if ((offset & 0xf80) == 0x80) {
+        bank_no = (offset & 0x60) >> 5;
+        if (bank_no < s->nbanks) {
+            offset &= ~0x60;
+            bank = &s->bank[bank_no];
+        }
+    }
+
+    switch (offset) {
+    case 0x00:	/* INTC_REVISION */
+        return 0x21;
+
+    case 0x10:	/* INTC_SYSCONFIG */
+        return (s->autoidle >> 2) & 1;
+
+    case 0x14:	/* INTC_SYSSTATUS */
+        return 1;						/* RESETDONE */
+
+    case 0x40:	/* INTC_SIR_IRQ */
+        return s->sir_intr[0];
+
+    case 0x44:	/* INTC_SIR_FIQ */
+        return s->sir_intr[1];
+
+    case 0x48:	/* INTC_CONTROL */
+        return (!s->mask) << 2;					/* GLOBALMASK */
+
+    case 0x4c:	/* INTC_PROTECTION */
+        return 0;
+
+    case 0x50:	/* INTC_IDLE */
+        return s->autoidle & 3;
+
+    /* Per-bank registers */
+    case 0x80:	/* INTC_ITR */
+        return bank->inputs;
+
+    case 0x84:	/* INTC_MIR */
+        return bank->mask;
+
+    case 0x88:	/* INTC_MIR_CLEAR */
+    case 0x8c:	/* INTC_MIR_SET */
+        return 0;
+
+    case 0x90:	/* INTC_ISR_SET */
+        return bank->swi;
+
+    case 0x94:	/* INTC_ISR_CLEAR */
+        return 0;
+
+    case 0x98:	/* INTC_PENDING_IRQ */
+        return bank->irqs & ~bank->mask & ~bank->fiq;
+
+    case 0x9c:	/* INTC_PENDING_FIQ */
+        return bank->irqs & ~bank->mask & bank->fiq;
+
+    /* Per-line registers */
+    case 0x100 ... 0x300:	/* INTC_ILR */
+        bank_no = (offset - 0x100) >> 7;
+        if (bank_no > s->nbanks)
+            break;
+        bank = &s->bank[bank_no];
+        line_no = (offset & 0x7f) >> 2;
+        return (bank->priority[line_no] << 2) |
+                ((bank->fiq >> line_no) & 1);
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
+    int offset = addr;
+    int bank_no, line_no;
+    struct omap_intr_handler_bank_s *bank = NULL;
+
+    if ((offset & 0xf80) == 0x80) {
+        bank_no = (offset & 0x60) >> 5;
+        if (bank_no < s->nbanks) {
+            offset &= ~0x60;
+            bank = &s->bank[bank_no];
+        }
+    }
+
+    switch (offset) {
+    case 0x10:	/* INTC_SYSCONFIG */
+        s->autoidle &= 4;
+        s->autoidle |= (value & 1) << 2;
+        if (value & 2)						/* SOFTRESET */
+            omap_inth_reset(s);
+        return;
+
+    case 0x48:	/* INTC_CONTROL */
+        s->mask = (value & 4) ? 0 : ~0;				/* GLOBALMASK */
+        if (value & 2) {					/* NEWFIQAGR */
+            qemu_set_irq(s->parent_intr[1], 0);
+            s->new_agr[1] = ~0;
+            omap_inth_update(s, 1);
+        }
+        if (value & 1) {					/* NEWIRQAGR */
+            qemu_set_irq(s->parent_intr[0], 0);
+            s->new_agr[0] = ~0;
+            omap_inth_update(s, 0);
+        }
+        return;
+
+    case 0x4c:	/* INTC_PROTECTION */
+        /* TODO: Make a bitmap (or sizeof(char)map) of access privileges
+         * for every register, see Chapter 3 and 4 for privileged mode.  */
+        if (value & 1)
+            fprintf(stderr, "%s: protection mode enable attempt\n",
+                            __FUNCTION__);
+        return;
+
+    case 0x50:	/* INTC_IDLE */
+        s->autoidle &= ~3;
+        s->autoidle |= value & 3;
+        return;
+
+    /* Per-bank registers */
+    case 0x84:	/* INTC_MIR */
+        bank->mask = value;
+        omap_inth_update(s, 0);
+        omap_inth_update(s, 1);
+        return;
+
+    case 0x88:	/* INTC_MIR_CLEAR */
+        bank->mask &= ~value;
+        omap_inth_update(s, 0);
+        omap_inth_update(s, 1);
+        return;
+
+    case 0x8c:	/* INTC_MIR_SET */
+        bank->mask |= value;
+        return;
+
+    case 0x90:	/* INTC_ISR_SET */
+        bank->irqs |= bank->swi |= value;
+        omap_inth_update(s, 0);
+        omap_inth_update(s, 1);
+        return;
+
+    case 0x94:	/* INTC_ISR_CLEAR */
+        bank->swi &= ~value;
+        bank->irqs = bank->swi & bank->inputs;
+        return;
+
+    /* Per-line registers */
+    case 0x100 ... 0x300:	/* INTC_ILR */
+        bank_no = (offset - 0x100) >> 7;
+        if (bank_no > s->nbanks)
+            break;
+        bank = &s->bank[bank_no];
+        line_no = (offset & 0x7f) >> 2;
+        bank->priority[line_no] = (value >> 2) & 0x3f;
+        bank->fiq &= ~(1 << line_no);
+        bank->fiq |= (value & 1) << line_no;
+        return;
+
+    case 0x00:	/* INTC_REVISION */
+    case 0x14:	/* INTC_SYSSTATUS */
+    case 0x40:	/* INTC_SIR_IRQ */
+    case 0x44:	/* INTC_SIR_FIQ */
+    case 0x80:	/* INTC_ITR */
+    case 0x98:	/* INTC_PENDING_IRQ */
+    case 0x9c:	/* INTC_PENDING_FIQ */
+        OMAP_RO_REG(addr);
+        return;
+    }
+    OMAP_BAD_REG(addr);
+}
+
+static CPUReadMemoryFunc * const omap2_inth_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap2_inth_read,
+};
+
+static CPUWriteMemoryFunc * const omap2_inth_writefn[] = {
+    omap2_inth_write,
+    omap2_inth_write,
+    omap2_inth_write,
+};
+
+struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
+                int size, int nbanks, qemu_irq **pins,
+                qemu_irq parent_irq, qemu_irq parent_fiq,
+                omap_clk fclk, omap_clk iclk)
+{
+    int iomemtype;
+    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
+            qemu_mallocz(sizeof(struct omap_intr_handler_s) +
+                            sizeof(struct omap_intr_handler_bank_s) * nbanks);
+
+    s->parent_intr[0] = parent_irq;
+    s->parent_intr[1] = parent_fiq;
+    s->nbanks = nbanks;
+    s->level_only = 1;
+    s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32);
+    if (pins)
+        *pins = s->pins;
+
+    omap_inth_reset(s);
+
+    iomemtype = cpu_register_io_memory(omap2_inth_readfn,
+                    omap2_inth_writefn, s);
+    cpu_register_physical_memory(base, size, iomemtype);
+
+    return s;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 08/12] hw/omap2.c : separate spi module
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (6 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 07/12] hw/omap1.c : separate interrupt controller module cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 09/12] hw/omap2.c : separate tap module(Test-Chip-level) cmchao
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    2 +-
 hw/omap.h       |    2 +
 hw/omap2.c      |  323 ---------------------------------------------------
 hw/omap_spi.c   |  346 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 349 insertions(+), 324 deletions(-)
 create mode 100644 hw/omap_spi.c

diff --git a/Makefile.target b/Makefile.target
index 9a309e2..1edec6f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -264,7 +264,7 @@ 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
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o omap_sdrc.o
+obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o omap_sdrc.o omap_spi.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
diff --git a/hw/omap.h b/hw/omap.h
index ea23ec9..fef495a 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -706,12 +706,14 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
 void omap_uwire_attach(struct omap_uwire_s *s,
                 uWireSlave *slave, int chipselect);
 
+/* OMAP2 spi */
 struct omap_mcspi_s;
 struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
                 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk);
 void omap_mcspi_attach(struct omap_mcspi_s *s,
                 uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque,
                 int chipselect);
+void omap_mcspi_reset(struct omap_mcspi_s *s);
 
 struct omap_rtc_s;
 struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
diff --git a/hw/omap2.c b/hw/omap2.c
index e6d1b52..ae6394e 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -27,329 +27,6 @@
 #include "soc_dma.h"
 #include "audio/audio.h"
 
-/* Multichannel SPI */
-struct omap_mcspi_s {
-    qemu_irq irq;
-    int chnum;
-
-    uint32_t sysconfig;
-    uint32_t systest;
-    uint32_t irqst;
-    uint32_t irqen;
-    uint32_t wken;
-    uint32_t control;
-
-    struct omap_mcspi_ch_s {
-        qemu_irq txdrq;
-        qemu_irq rxdrq;
-        uint32_t (*txrx)(void *opaque, uint32_t, int);
-        void *opaque;
-
-        uint32_t tx;
-        uint32_t rx;
-
-        uint32_t config;
-        uint32_t status;
-        uint32_t control;
-    } ch[4];
-};
-
-static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s)
-{
-    qemu_set_irq(s->irq, s->irqst & s->irqen);
-}
-
-static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch)
-{
-    qemu_set_irq(ch->txdrq,
-                    (ch->control & 1) &&		/* EN */
-                    (ch->config & (1 << 14)) &&		/* DMAW */
-                    (ch->status & (1 << 1)) &&		/* TXS */
-                    ((ch->config >> 12) & 3) != 1);	/* TRM */
-    qemu_set_irq(ch->rxdrq,
-                    (ch->control & 1) &&		/* EN */
-                    (ch->config & (1 << 15)) &&		/* DMAW */
-                    (ch->status & (1 << 0)) &&		/* RXS */
-                    ((ch->config >> 12) & 3) != 2);	/* TRM */
-}
-
-static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
-{
-    struct omap_mcspi_ch_s *ch = s->ch + chnum;
-
-    if (!(ch->control & 1))				/* EN */
-        return;
-    if ((ch->status & (1 << 0)) &&			/* RXS */
-                    ((ch->config >> 12) & 3) != 2 &&	/* TRM */
-                    !(ch->config & (1 << 19)))		/* TURBO */
-        goto intr_update;
-    if ((ch->status & (1 << 1)) &&			/* TXS */
-                    ((ch->config >> 12) & 3) != 1)	/* TRM */
-        goto intr_update;
-
-    if (!(s->control & 1) ||				/* SINGLE */
-                    (ch->config & (1 << 20))) {		/* FORCE */
-        if (ch->txrx)
-            ch->rx = ch->txrx(ch->opaque, ch->tx,	/* WL */
-                            1 + (0x1f & (ch->config >> 7)));
-    }
-
-    ch->tx = 0;
-    ch->status |= 1 << 2;				/* EOT */
-    ch->status |= 1 << 1;				/* TXS */
-    if (((ch->config >> 12) & 3) != 2)			/* TRM */
-        ch->status |= 1 << 0;				/* RXS */
-
-intr_update:
-    if ((ch->status & (1 << 0)) &&			/* RXS */
-                    ((ch->config >> 12) & 3) != 2 &&	/* TRM */
-                    !(ch->config & (1 << 19)))		/* TURBO */
-        s->irqst |= 1 << (2 + 4 * chnum);		/* RX_FULL */
-    if ((ch->status & (1 << 1)) &&			/* TXS */
-                    ((ch->config >> 12) & 3) != 1)	/* TRM */
-        s->irqst |= 1 << (0 + 4 * chnum);		/* TX_EMPTY */
-    omap_mcspi_interrupt_update(s);
-    omap_mcspi_dmarequest_update(ch);
-}
-
-static void omap_mcspi_reset(struct omap_mcspi_s *s)
-{
-    int ch;
-
-    s->sysconfig = 0;
-    s->systest = 0;
-    s->irqst = 0;
-    s->irqen = 0;
-    s->wken = 0;
-    s->control = 4;
-
-    for (ch = 0; ch < 4; ch ++) {
-        s->ch[ch].config = 0x060000;
-        s->ch[ch].status = 2;				/* TXS */
-        s->ch[ch].control = 0;
-
-        omap_mcspi_dmarequest_update(s->ch + ch);
-    }
-
-    omap_mcspi_interrupt_update(s);
-}
-
-static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
-    int ch = 0;
-    uint32_t ret;
-
-    switch (addr) {
-    case 0x00:	/* MCSPI_REVISION */
-        return 0x91;
-
-    case 0x10:	/* MCSPI_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x14:	/* MCSPI_SYSSTATUS */
-        return 1;					/* RESETDONE */
-
-    case 0x18:	/* MCSPI_IRQSTATUS */
-        return s->irqst;
-
-    case 0x1c:	/* MCSPI_IRQENABLE */
-        return s->irqen;
-
-    case 0x20:	/* MCSPI_WAKEUPENABLE */
-        return s->wken;
-
-    case 0x24:	/* MCSPI_SYST */
-        return s->systest;
-
-    case 0x28:	/* MCSPI_MODULCTRL */
-        return s->control;
-
-    case 0x68: ch ++;
-    case 0x54: ch ++;
-    case 0x40: ch ++;
-    case 0x2c:	/* MCSPI_CHCONF */
-        return s->ch[ch].config;
-
-    case 0x6c: ch ++;
-    case 0x58: ch ++;
-    case 0x44: ch ++;
-    case 0x30:	/* MCSPI_CHSTAT */
-        return s->ch[ch].status;
-
-    case 0x70: ch ++;
-    case 0x5c: ch ++;
-    case 0x48: ch ++;
-    case 0x34:	/* MCSPI_CHCTRL */
-        return s->ch[ch].control;
-
-    case 0x74: ch ++;
-    case 0x60: ch ++;
-    case 0x4c: ch ++;
-    case 0x38:	/* MCSPI_TX */
-        return s->ch[ch].tx;
-
-    case 0x78: ch ++;
-    case 0x64: ch ++;
-    case 0x50: ch ++;
-    case 0x3c:	/* MCSPI_RX */
-        s->ch[ch].status &= ~(1 << 0);			/* RXS */
-        ret = s->ch[ch].rx;
-        omap_mcspi_transfer_run(s, ch);
-        return ret;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
-    int ch = 0;
-
-    switch (addr) {
-    case 0x00:	/* MCSPI_REVISION */
-    case 0x14:	/* MCSPI_SYSSTATUS */
-    case 0x30:	/* MCSPI_CHSTAT0 */
-    case 0x3c:	/* MCSPI_RX0 */
-    case 0x44:	/* MCSPI_CHSTAT1 */
-    case 0x50:	/* MCSPI_RX1 */
-    case 0x58:	/* MCSPI_CHSTAT2 */
-    case 0x64:	/* MCSPI_RX2 */
-    case 0x6c:	/* MCSPI_CHSTAT3 */
-    case 0x78:	/* MCSPI_RX3 */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x10:	/* MCSPI_SYSCONFIG */
-        if (value & (1 << 1))				/* SOFTRESET */
-            omap_mcspi_reset(s);
-        s->sysconfig = value & 0x31d;
-        break;
-
-    case 0x18:	/* MCSPI_IRQSTATUS */
-        if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) {
-            s->irqst &= ~value;
-            omap_mcspi_interrupt_update(s);
-        }
-        break;
-
-    case 0x1c:	/* MCSPI_IRQENABLE */
-        s->irqen = value & 0x1777f;
-        omap_mcspi_interrupt_update(s);
-        break;
-
-    case 0x20:	/* MCSPI_WAKEUPENABLE */
-        s->wken = value & 1;
-        break;
-
-    case 0x24:	/* MCSPI_SYST */
-        if (s->control & (1 << 3))			/* SYSTEM_TEST */
-            if (value & (1 << 11)) {			/* SSB */
-                s->irqst |= 0x1777f;
-                omap_mcspi_interrupt_update(s);
-            }
-        s->systest = value & 0xfff;
-        break;
-
-    case 0x28:	/* MCSPI_MODULCTRL */
-        if (value & (1 << 3))				/* SYSTEM_TEST */
-            if (s->systest & (1 << 11)) {		/* SSB */
-                s->irqst |= 0x1777f;
-                omap_mcspi_interrupt_update(s);
-            }
-        s->control = value & 0xf;
-        break;
-
-    case 0x68: ch ++;
-    case 0x54: ch ++;
-    case 0x40: ch ++;
-    case 0x2c:	/* MCSPI_CHCONF */
-        if ((value ^ s->ch[ch].config) & (3 << 14))	/* DMAR | DMAW */
-            omap_mcspi_dmarequest_update(s->ch + ch);
-        if (((value >> 12) & 3) == 3)			/* TRM */
-            fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);
-        if (((value >> 7) & 0x1f) < 3)			/* WL */
-            fprintf(stderr, "%s: invalid WL value (%i)\n",
-                            __FUNCTION__, (value >> 7) & 0x1f);
-        s->ch[ch].config = value & 0x7fffff;
-        break;
-
-    case 0x70: ch ++;
-    case 0x5c: ch ++;
-    case 0x48: ch ++;
-    case 0x34:	/* MCSPI_CHCTRL */
-        if (value & ~s->ch[ch].control & 1) {		/* EN */
-            s->ch[ch].control |= 1;
-            omap_mcspi_transfer_run(s, ch);
-        } else
-            s->ch[ch].control = value & 1;
-        break;
-
-    case 0x74: ch ++;
-    case 0x60: ch ++;
-    case 0x4c: ch ++;
-    case 0x38:	/* MCSPI_TX */
-        s->ch[ch].tx = value;
-        s->ch[ch].status &= ~(1 << 1);			/* TXS */
-        omap_mcspi_transfer_run(s, ch);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static CPUReadMemoryFunc * const omap_mcspi_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_mcspi_read,
-};
-
-static CPUWriteMemoryFunc * const omap_mcspi_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_mcspi_write,
-};
-
-struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
-                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
-{
-    int iomemtype;
-    struct omap_mcspi_s *s = (struct omap_mcspi_s *)
-            qemu_mallocz(sizeof(struct omap_mcspi_s));
-    struct omap_mcspi_ch_s *ch = s->ch;
-
-    s->irq = irq;
-    s->chnum = chnum;
-    while (chnum --) {
-        ch->txdrq = *drq ++;
-        ch->rxdrq = *drq ++;
-        ch ++;
-    }
-    omap_mcspi_reset(s);
-
-    iomemtype = l4_register_io_memory(omap_mcspi_readfn,
-                    omap_mcspi_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
-
-    return s;
-}
-
-void omap_mcspi_attach(struct omap_mcspi_s *s,
-                uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque,
-                int chipselect)
-{
-    if (chipselect < 0 || chipselect >= s->chnum)
-        hw_error("%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
-
-    s->ch[chipselect].txrx = txrx;
-    s->ch[chipselect].opaque = opaque;
-}
-
 /* Enhanced Audio Controller (CODEC only) */
 struct omap_eac_s {
     qemu_irq irq;
diff --git a/hw/omap_spi.c b/hw/omap_spi.c
new file mode 100644
index 0000000..a6b0349
--- /dev/null
+++ b/hw/omap_spi.c
@@ -0,0 +1,346 @@
+/*
+ * TI OMAP processor's Multichannel SPI emulation.
+ *
+ * Copyright (C) 2007-2009 Nokia Corporation
+ *
+ * Original code for OMAP2 by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "hw.h"
+#include "omap.h"
+
+/* Multichannel SPI */
+struct omap_mcspi_s {
+    qemu_irq irq;
+    int chnum;
+
+    uint32_t sysconfig;
+    uint32_t systest;
+    uint32_t irqst;
+    uint32_t irqen;
+    uint32_t wken;
+    uint32_t control;
+
+    struct omap_mcspi_ch_s {
+        qemu_irq txdrq;
+        qemu_irq rxdrq;
+        uint32_t (*txrx)(void *opaque, uint32_t, int);
+        void *opaque;
+
+        uint32_t tx;
+        uint32_t rx;
+
+        uint32_t config;
+        uint32_t status;
+        uint32_t control;
+    } ch[4];
+};
+
+static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s)
+{
+    qemu_set_irq(s->irq, s->irqst & s->irqen);
+}
+
+static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch)
+{
+    qemu_set_irq(ch->txdrq,
+                    (ch->control & 1) &&		/* EN */
+                    (ch->config & (1 << 14)) &&		/* DMAW */
+                    (ch->status & (1 << 1)) &&		/* TXS */
+                    ((ch->config >> 12) & 3) != 1);	/* TRM */
+    qemu_set_irq(ch->rxdrq,
+                    (ch->control & 1) &&		/* EN */
+                    (ch->config & (1 << 15)) &&		/* DMAW */
+                    (ch->status & (1 << 0)) &&		/* RXS */
+                    ((ch->config >> 12) & 3) != 2);	/* TRM */
+}
+
+static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
+{
+    struct omap_mcspi_ch_s *ch = s->ch + chnum;
+
+    if (!(ch->control & 1))				/* EN */
+        return;
+    if ((ch->status & (1 << 0)) &&			/* RXS */
+                    ((ch->config >> 12) & 3) != 2 &&	/* TRM */
+                    !(ch->config & (1 << 19)))		/* TURBO */
+        goto intr_update;
+    if ((ch->status & (1 << 1)) &&			/* TXS */
+                    ((ch->config >> 12) & 3) != 1)	/* TRM */
+        goto intr_update;
+
+    if (!(s->control & 1) ||				/* SINGLE */
+                    (ch->config & (1 << 20))) {		/* FORCE */
+        if (ch->txrx)
+            ch->rx = ch->txrx(ch->opaque, ch->tx,	/* WL */
+                            1 + (0x1f & (ch->config >> 7)));
+    }
+
+    ch->tx = 0;
+    ch->status |= 1 << 2;				/* EOT */
+    ch->status |= 1 << 1;				/* TXS */
+    if (((ch->config >> 12) & 3) != 2)			/* TRM */
+        ch->status |= 1 << 0;				/* RXS */
+
+intr_update:
+    if ((ch->status & (1 << 0)) &&			/* RXS */
+                    ((ch->config >> 12) & 3) != 2 &&	/* TRM */
+                    !(ch->config & (1 << 19)))		/* TURBO */
+        s->irqst |= 1 << (2 + 4 * chnum);		/* RX_FULL */
+    if ((ch->status & (1 << 1)) &&			/* TXS */
+                    ((ch->config >> 12) & 3) != 1)	/* TRM */
+        s->irqst |= 1 << (0 + 4 * chnum);		/* TX_EMPTY */
+    omap_mcspi_interrupt_update(s);
+    omap_mcspi_dmarequest_update(ch);
+}
+
+void omap_mcspi_reset(struct omap_mcspi_s *s)
+{
+    int ch;
+
+    s->sysconfig = 0;
+    s->systest = 0;
+    s->irqst = 0;
+    s->irqen = 0;
+    s->wken = 0;
+    s->control = 4;
+
+    for (ch = 0; ch < 4; ch ++) {
+        s->ch[ch].config = 0x060000;
+        s->ch[ch].status = 2;				/* TXS */
+        s->ch[ch].control = 0;
+
+        omap_mcspi_dmarequest_update(s->ch + ch);
+    }
+
+    omap_mcspi_interrupt_update(s);
+}
+
+static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
+    int ch = 0;
+    uint32_t ret;
+
+    switch (addr) {
+    case 0x00:	/* MCSPI_REVISION */
+        return 0x91;
+
+    case 0x10:	/* MCSPI_SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x14:	/* MCSPI_SYSSTATUS */
+        return 1;					/* RESETDONE */
+
+    case 0x18:	/* MCSPI_IRQSTATUS */
+        return s->irqst;
+
+    case 0x1c:	/* MCSPI_IRQENABLE */
+        return s->irqen;
+
+    case 0x20:	/* MCSPI_WAKEUPENABLE */
+        return s->wken;
+
+    case 0x24:	/* MCSPI_SYST */
+        return s->systest;
+
+    case 0x28:	/* MCSPI_MODULCTRL */
+        return s->control;
+
+    case 0x68: ch ++;
+    case 0x54: ch ++;
+    case 0x40: ch ++;
+    case 0x2c:	/* MCSPI_CHCONF */
+        return s->ch[ch].config;
+
+    case 0x6c: ch ++;
+    case 0x58: ch ++;
+    case 0x44: ch ++;
+    case 0x30:	/* MCSPI_CHSTAT */
+        return s->ch[ch].status;
+
+    case 0x70: ch ++;
+    case 0x5c: ch ++;
+    case 0x48: ch ++;
+    case 0x34:	/* MCSPI_CHCTRL */
+        return s->ch[ch].control;
+
+    case 0x74: ch ++;
+    case 0x60: ch ++;
+    case 0x4c: ch ++;
+    case 0x38:	/* MCSPI_TX */
+        return s->ch[ch].tx;
+
+    case 0x78: ch ++;
+    case 0x64: ch ++;
+    case 0x50: ch ++;
+    case 0x3c:	/* MCSPI_RX */
+        s->ch[ch].status &= ~(1 << 0);			/* RXS */
+        ret = s->ch[ch].rx;
+        omap_mcspi_transfer_run(s, ch);
+        return ret;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
+    int ch = 0;
+
+    switch (addr) {
+    case 0x00:	/* MCSPI_REVISION */
+    case 0x14:	/* MCSPI_SYSSTATUS */
+    case 0x30:	/* MCSPI_CHSTAT0 */
+    case 0x3c:	/* MCSPI_RX0 */
+    case 0x44:	/* MCSPI_CHSTAT1 */
+    case 0x50:	/* MCSPI_RX1 */
+    case 0x58:	/* MCSPI_CHSTAT2 */
+    case 0x64:	/* MCSPI_RX2 */
+    case 0x6c:	/* MCSPI_CHSTAT3 */
+    case 0x78:	/* MCSPI_RX3 */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x10:	/* MCSPI_SYSCONFIG */
+        if (value & (1 << 1))				/* SOFTRESET */
+            omap_mcspi_reset(s);
+        s->sysconfig = value & 0x31d;
+        break;
+
+    case 0x18:	/* MCSPI_IRQSTATUS */
+        if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) {
+            s->irqst &= ~value;
+            omap_mcspi_interrupt_update(s);
+        }
+        break;
+
+    case 0x1c:	/* MCSPI_IRQENABLE */
+        s->irqen = value & 0x1777f;
+        omap_mcspi_interrupt_update(s);
+        break;
+
+    case 0x20:	/* MCSPI_WAKEUPENABLE */
+        s->wken = value & 1;
+        break;
+
+    case 0x24:	/* MCSPI_SYST */
+        if (s->control & (1 << 3))			/* SYSTEM_TEST */
+            if (value & (1 << 11)) {			/* SSB */
+                s->irqst |= 0x1777f;
+                omap_mcspi_interrupt_update(s);
+            }
+        s->systest = value & 0xfff;
+        break;
+
+    case 0x28:	/* MCSPI_MODULCTRL */
+        if (value & (1 << 3))				/* SYSTEM_TEST */
+            if (s->systest & (1 << 11)) {		/* SSB */
+                s->irqst |= 0x1777f;
+                omap_mcspi_interrupt_update(s);
+            }
+        s->control = value & 0xf;
+        break;
+
+    case 0x68: ch ++;
+    case 0x54: ch ++;
+    case 0x40: ch ++;
+    case 0x2c:	/* MCSPI_CHCONF */
+        if ((value ^ s->ch[ch].config) & (3 << 14))	/* DMAR | DMAW */
+            omap_mcspi_dmarequest_update(s->ch + ch);
+        if (((value >> 12) & 3) == 3)			/* TRM */
+            fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);
+        if (((value >> 7) & 0x1f) < 3)			/* WL */
+            fprintf(stderr, "%s: invalid WL value (%i)\n",
+                            __FUNCTION__, (value >> 7) & 0x1f);
+        s->ch[ch].config = value & 0x7fffff;
+        break;
+
+    case 0x70: ch ++;
+    case 0x5c: ch ++;
+    case 0x48: ch ++;
+    case 0x34:	/* MCSPI_CHCTRL */
+        if (value & ~s->ch[ch].control & 1) {		/* EN */
+            s->ch[ch].control |= 1;
+            omap_mcspi_transfer_run(s, ch);
+        } else
+            s->ch[ch].control = value & 1;
+        break;
+
+    case 0x74: ch ++;
+    case 0x60: ch ++;
+    case 0x4c: ch ++;
+    case 0x38:	/* MCSPI_TX */
+        s->ch[ch].tx = value;
+        s->ch[ch].status &= ~(1 << 1);			/* TXS */
+        omap_mcspi_transfer_run(s, ch);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc * const omap_mcspi_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap_mcspi_read,
+};
+
+static CPUWriteMemoryFunc * const omap_mcspi_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap_mcspi_write,
+};
+
+struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
+                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
+{
+    int iomemtype;
+    struct omap_mcspi_s *s = (struct omap_mcspi_s *)
+            qemu_mallocz(sizeof(struct omap_mcspi_s));
+    struct omap_mcspi_ch_s *ch = s->ch;
+
+    s->irq = irq;
+    s->chnum = chnum;
+    while (chnum --) {
+        ch->txdrq = *drq ++;
+        ch->rxdrq = *drq ++;
+        ch ++;
+    }
+    omap_mcspi_reset(s);
+
+    iomemtype = l4_register_io_memory(omap_mcspi_readfn,
+                    omap_mcspi_writefn, s);
+    omap_l4_attach(ta, 0, iomemtype);
+
+    return s;
+}
+
+void omap_mcspi_attach(struct omap_mcspi_s *s,
+                uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque,
+                int chipselect)
+{
+    if (chipselect < 0 || chipselect >= s->chnum)
+        hw_error("%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
+
+    s->ch[chipselect].txrx = txrx;
+    s->ch[chipselect].opaque = opaque;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 09/12] hw/omap2.c : separate tap module(Test-Chip-level)
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (7 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 08/12] hw/omap2.c : separate spi module cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 10/12] hw/omwp2.c : separate l4 interconnect module cmchao
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    2 +-
 hw/omap2.c      |   90 --------------------------------------------
 hw/omap_tap.c   |  112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 91 deletions(-)
 create mode 100644 hw/omap_tap.c

diff --git a/Makefile.target b/Makefile.target
index 1edec6f..39d2858 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -264,7 +264,7 @@ 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
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o omap_sdrc.o omap_spi.o
+obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
diff --git a/hw/omap2.c b/hw/omap2.c
index ae6394e..7403077 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -1245,96 +1245,6 @@ target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
     return base;
 }
 
-/* TEST-Chip-level TAP */
-static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    switch (addr) {
-    case 0x204:	/* IDCODE_reg */
-        switch (s->mpu_model) {
-        case omap2420:
-        case omap2422:
-        case omap2423:
-            return 0x5b5d902f;	/* ES 2.2 */
-        case omap2430:
-            return 0x5b68a02f;	/* ES 2.2 */
-        case omap3430:
-            return 0x1b7ae02f;	/* ES 2 */
-        default:
-            hw_error("%s: Bad mpu model\n", __FUNCTION__);
-        }
-
-    case 0x208:	/* PRODUCTION_ID_reg for OMAP2 */
-    case 0x210:	/* PRODUCTION_ID_reg for OMAP3 */
-        switch (s->mpu_model) {
-        case omap2420:
-            return 0x000254f0;	/* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */
-        case omap2422:
-            return 0x000400f0;
-        case omap2423:
-            return 0x000800f0;
-        case omap2430:
-            return 0x000000f0;
-        case omap3430:
-            return 0x000000f0;
-        default:
-            hw_error("%s: Bad mpu model\n", __FUNCTION__);
-        }
-
-    case 0x20c:
-        switch (s->mpu_model) {
-        case omap2420:
-        case omap2422:
-        case omap2423:
-            return 0xcafeb5d9;	/* ES 2.2 */
-        case omap2430:
-            return 0xcafeb68a;	/* ES 2.2 */
-        case omap3430:
-            return 0xcafeb7ae;	/* ES 2 */
-        default:
-            hw_error("%s: Bad mpu model\n", __FUNCTION__);
-        }
-
-    case 0x218:	/* DIE_ID_reg */
-        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    case 0x21c:	/* DIE_ID_reg */
-        return 0x54 << 24;
-    case 0x220:	/* DIE_ID_reg */
-        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    case 0x224:	/* DIE_ID_reg */
-        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_tap_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    OMAP_BAD_REG(addr);
-}
-
-static CPUReadMemoryFunc * const omap_tap_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_tap_read,
-};
-
-static CPUWriteMemoryFunc * const omap_tap_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_tap_write,
-};
-
-void omap_tap_init(struct omap_target_agent_s *ta,
-                struct omap_mpu_state_s *mpu)
-{
-    omap_l4_attach(ta, 0, l4_register_io_memory(
-                            omap_tap_readfn, omap_tap_writefn, mpu));
-}
-
 /* Power, Reset, and Clock Management */
 struct omap_prcm_s {
     qemu_irq irq[3];
diff --git a/hw/omap_tap.c b/hw/omap_tap.c
new file mode 100644
index 0000000..1f18ddd
--- /dev/null
+++ b/hw/omap_tap.c
@@ -0,0 +1,112 @@
+/*
+ * TI OMAP TEST-Chip-level TAP emulation.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw.h"
+#include "omap.h"
+
+/* TEST-Chip-level TAP */
+static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    switch (addr) {
+    case 0x204:	/* IDCODE_reg */
+        switch (s->mpu_model) {
+        case omap2420:
+        case omap2422:
+        case omap2423:
+            return 0x5b5d902f;	/* ES 2.2 */
+        case omap2430:
+            return 0x5b68a02f;	/* ES 2.2 */
+        case omap3430:
+            return 0x1b7ae02f;	/* ES 2 */
+        default:
+            hw_error("%s: Bad mpu model\n", __FUNCTION__);
+        }
+
+    case 0x208:	/* PRODUCTION_ID_reg for OMAP2 */
+    case 0x210:	/* PRODUCTION_ID_reg for OMAP3 */
+        switch (s->mpu_model) {
+        case omap2420:
+            return 0x000254f0;	/* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */
+        case omap2422:
+            return 0x000400f0;
+        case omap2423:
+            return 0x000800f0;
+        case omap2430:
+            return 0x000000f0;
+        case omap3430:
+            return 0x000000f0;
+        default:
+            hw_error("%s: Bad mpu model\n", __FUNCTION__);
+        }
+
+    case 0x20c:
+        switch (s->mpu_model) {
+        case omap2420:
+        case omap2422:
+        case omap2423:
+            return 0xcafeb5d9;	/* ES 2.2 */
+        case omap2430:
+            return 0xcafeb68a;	/* ES 2.2 */
+        case omap3430:
+            return 0xcafeb7ae;	/* ES 2 */
+        default:
+            hw_error("%s: Bad mpu model\n", __FUNCTION__);
+        }
+
+    case 0x218:	/* DIE_ID_reg */
+        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
+    case 0x21c:	/* DIE_ID_reg */
+        return 0x54 << 24;
+    case 0x220:	/* DIE_ID_reg */
+        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
+    case 0x224:	/* DIE_ID_reg */
+        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_tap_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    OMAP_BAD_REG(addr);
+}
+
+static CPUReadMemoryFunc * const omap_tap_readfn[] = {
+    omap_badwidth_read32,
+    omap_badwidth_read32,
+    omap_tap_read,
+};
+
+static CPUWriteMemoryFunc * const omap_tap_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap_tap_write,
+};
+
+void omap_tap_init(struct omap_target_agent_s *ta,
+                struct omap_mpu_state_s *mpu)
+{
+    omap_l4_attach(ta, 0, l4_register_io_memory(
+                            omap_tap_readfn, omap_tap_writefn, mpu));
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 10/12] hw/omwp2.c : separate l4 interconnect module
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (8 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 09/12] hw/omap2.c : separate tap module(Test-Chip-level) cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 11/12] hw/omap1.c : separate uart module cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 12/12] hw/omap : make local function static and remove declaration from header cmchao
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    3 +-
 hw/omap.h       |   37 ++++++--
 hw/omap2.c      |  269 ++-----------------------------------------------------
 hw/omap_l4.c    |  271 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 307 insertions(+), 273 deletions(-)
 create mode 100644 hw/omap_l4.c

diff --git a/Makefile.target b/Makefile.target
index 39d2858..20bcb8a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -264,7 +264,8 @@ 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
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o
+obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
+		omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
diff --git a/hw/omap.h b/hw/omap.h
index fef495a..34443b4 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -61,15 +61,40 @@ void omap_clk_setrate(omap_clk clk, int divide, int multiply);
 int64_t omap_clk_getrate(omap_clk clk);
 void omap_clk_reparent(omap_clk clk, omap_clk parent);
 
-/* omap[123].c */
+/* OMAP2 l4 Interconnect */
 struct omap_l4_s;
+struct omap_l4_region_s {
+    target_phys_addr_t offset;
+    size_t size;
+    int access;
+};
+struct omap_l4_agent_info_s {
+    int ta;
+    int region;
+    int regions;
+    int ta_region;
+};
+struct omap_target_agent_s {
+    struct omap_l4_s *bus;
+    int regions;
+    const struct omap_l4_region_s *start;
+    target_phys_addr_t base;
+    uint32_t component;
+    uint32_t control;
+    uint32_t status;
+};
 struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num);
 
 struct omap_target_agent_s;
-struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs);
+struct omap_target_agent_s *omap_l4ta_get(
+    struct omap_l4_s *bus,
+    const struct omap_l4_region_s *regions,
+    const struct omap_l4_agent_info_s *agents,
+    int cs);
 target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
                 int iotype);
-# define l4_register_io_memory	cpu_register_io_memory
+int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
+                CPUWriteMemoryFunc * const *mem_write, void *opaque);
 
 /* OMAP interrupt controller */
 struct omap_intr_handler_s;
@@ -1146,10 +1171,4 @@ inline static int debug_register_io_memory(CPUReadMemoryFunc * const *mem_read,
 /* Define when we want to reduce the number of IO regions registered.  */
 /*# define L4_MUX_HACK*/
 
-# ifdef L4_MUX_HACK
-#  undef l4_register_io_memory
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                          CPUWriteMemoryFunc * const *mem_write, void *opaque);
-# endif
-
 #endif /* hw_omap_h */
diff --git a/hw/omap2.c b/hw/omap2.c
index 7403077..9bac954 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -795,195 +795,10 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
 }
 
 /* L4 Interconnect */
-struct omap_target_agent_s {
-    struct omap_l4_s *bus;
-    int regions;
-    struct omap_l4_region_s *start;
-    target_phys_addr_t base;
-    uint32_t component;
-    uint32_t control;
-    uint32_t status;
-};
-
-struct omap_l4_s {
-    target_phys_addr_t base;
-    int ta_num;
-    struct omap_target_agent_s ta[0];
-};
-
-#ifdef L4_MUX_HACK
-static int omap_l4_io_entries;
-static int omap_cpu_io_entry;
-static struct omap_l4_entry {
-        CPUReadMemoryFunc * const *mem_read;
-        CPUWriteMemoryFunc * const *mem_write;
-        void *opaque;
-} *omap_l4_io_entry;
-static CPUReadMemoryFunc * const *omap_l4_io_readb_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readh_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readw_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeb_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeh_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writew_fn;
-static void **omap_l4_io_opaque;
-
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                CPUWriteMemoryFunc * const *mem_write, void *opaque)
-{
-    omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read;
-    omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write;
-    omap_l4_io_entry[omap_l4_io_entries].opaque = opaque;
-
-    return omap_l4_io_entries ++;
-}
-
-static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static CPUReadMemoryFunc * const omap_l4_io_readfn[] = {
-    omap_l4_io_readb,
-    omap_l4_io_readh,
-    omap_l4_io_readw,
-};
-
-static CPUWriteMemoryFunc * const omap_l4_io_writefn[] = {
-    omap_l4_io_writeb,
-    omap_l4_io_writeh,
-    omap_l4_io_writew,
-};
-#endif
-
-struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
-{
-    struct omap_l4_s *bus = qemu_mallocz(
-                    sizeof(*bus) + ta_num * sizeof(*bus->ta));
-
-    bus->ta_num = ta_num;
-    bus->base = base;
-
-#ifdef L4_MUX_HACK
-    omap_l4_io_entries = 1;
-    omap_l4_io_entry = qemu_mallocz(125 * sizeof(*omap_l4_io_entry));
-
-    omap_cpu_io_entry =
-            cpu_register_io_memory(omap_l4_io_readfn,
-                            omap_l4_io_writefn, bus);
-# define L4_PAGES	(0xb4000 / TARGET_PAGE_SIZE)
-    omap_l4_io_readb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readw_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writew_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_opaque = qemu_mallocz(sizeof(void *) * L4_PAGES);
-#endif
-
-    return bus;
-}
-
-static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* COMPONENT */
-        return s->component;
-
-    case 0x20:	/* AGENT_CONTROL */
-        return s->control;
-
-    case 0x28:	/* AGENT_STATUS */
-        return s->status;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* COMPONENT */
-    case 0x28:	/* AGENT_STATUS */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x20:	/* AGENT_CONTROL */
-        s->control = value & 0x01000700;
-        if (value & 1)					/* OCP_RESET */
-            s->status &= ~1;				/* REQ_TIMEOUT */
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static CPUReadMemoryFunc * const omap_l4ta_readfn[] = {
-    omap_badwidth_read16,
-    omap_l4ta_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_l4ta_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_l4ta_write,
-};
-
 #define L4TA(n)		(n)
 #define L4TAO(n)	((n) + 39)
 
-static struct omap_l4_region_s {
-    target_phys_addr_t offset;
-    size_t size;
-    int access;
-} omap_l4_region[125] = {
+static const struct omap_l4_region_s omap_l4_region[125] = {
     [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
     [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
     [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
@@ -1111,12 +926,7 @@ static struct omap_l4_region_s {
     [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
 };
 
-static struct omap_l4_agent_info_s {
-    int ta;
-    int region;
-    int regions;
-    int ta_region;
-} omap_l4_agent_info[54] = {
+static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
     { 0,           0, 3, 2 }, /* L4IA initiatior agent */
     { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
     { L4TAO(2),    5, 2, 1 }, /* 32K timer */
@@ -1173,77 +983,10 @@ static struct omap_l4_agent_info_s {
     { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
 };
 
-#define omap_l4ta(bus, cs)	omap_l4ta_get(bus, L4TA(cs))
-#define omap_l4tao(bus, cs)	omap_l4ta_get(bus, L4TAO(cs))
-
-struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs)
-{
-    int i, iomemtype;
-    struct omap_target_agent_s *ta = NULL;
-    struct omap_l4_agent_info_s *info = NULL;
-
-    for (i = 0; i < bus->ta_num; i ++)
-        if (omap_l4_agent_info[i].ta == cs) {
-            ta = &bus->ta[i];
-            info = &omap_l4_agent_info[i];
-            break;
-        }
-    if (!ta) {
-        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
-        exit(-1);
-    }
-
-    ta->bus = bus;
-    ta->start = &omap_l4_region[info->region];
-    ta->regions = info->regions;
-
-    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    ta->status = 0x00000000;
-    ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
-
-    iomemtype = l4_register_io_memory(omap_l4ta_readfn,
-                    omap_l4ta_writefn, ta);
-    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
-
-    return ta;
-}
-
-target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-                int iotype)
-{
-    target_phys_addr_t base;
-    ssize_t size;
-#ifdef L4_MUX_HACK
-    int i;
-#endif
-
-    if (region < 0 || region >= ta->regions) {
-        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
-        exit(-1);
-    }
-
-    base = ta->bus->base + ta->start[region].offset;
-    size = ta->start[region].size;
-    if (iotype) {
-#ifndef L4_MUX_HACK
-        cpu_register_physical_memory(base, size, iotype);
-#else
-        cpu_register_physical_memory(base, size, omap_cpu_io_entry);
-        i = (base - ta->bus->base) / TARGET_PAGE_SIZE;
-        for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) {
-            omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0];
-            omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1];
-            omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2];
-            omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0];
-            omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1];
-            omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2];
-            omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque;
-        }
-#endif
-    }
-
-    return base;
-}
+#define omap_l4ta(bus, cs)	\
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs))
+#define omap_l4tao(bus, cs)	\
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs))
 
 /* Power, Reset, and Clock Management */
 struct omap_prcm_s {
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
new file mode 100644
index 0000000..bf8ba36
--- /dev/null
+++ b/hw/omap_l4.c
@@ -0,0 +1,271 @@
+/*
+ * TI OMAP L4 interconnect emulation.
+ *
+ * Copyright (C) 2007-2009 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "omap.h"
+
+#ifdef L4_MUX_HACK
+static int omap_l4_io_entries;
+static int omap_cpu_io_entry;
+static struct omap_l4_entry {
+        CPUReadMemoryFunc * const *mem_read;
+        CPUWriteMemoryFunc * const *mem_write;
+        void *opaque;
+} *omap_l4_io_entry;
+static CPUReadMemoryFunc * const *omap_l4_io_readb_fn;
+static CPUReadMemoryFunc * const *omap_l4_io_readh_fn;
+static CPUReadMemoryFunc * const *omap_l4_io_readw_fn;
+static CPUWriteMemoryFunc * const *omap_l4_io_writeb_fn;
+static CPUWriteMemoryFunc * const *omap_l4_io_writeh_fn;
+static CPUWriteMemoryFunc * const *omap_l4_io_writew_fn;
+static void **omap_l4_io_opaque;
+
+int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
+                CPUWriteMemoryFunc * const *mem_write, void *opaque)
+{
+    omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read;
+    omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write;
+    omap_l4_io_entry[omap_l4_io_entries].opaque = opaque;
+
+    return omap_l4_io_entries ++;
+}
+
+static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr);
+}
+
+static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr);
+}
+
+static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr);
+}
+
+static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value);
+}
+
+static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value);
+}
+
+static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value);
+}
+
+static CPUReadMemoryFunc * const omap_l4_io_readfn[] = {
+    omap_l4_io_readb,
+    omap_l4_io_readh,
+    omap_l4_io_readw,
+};
+
+static CPUWriteMemoryFunc * const omap_l4_io_writefn[] = {
+    omap_l4_io_writeb,
+    omap_l4_io_writeh,
+    omap_l4_io_writew,
+};
+#else
+int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
+                          CPUWriteMemoryFunc * const *mem_write,
+                          void *opaque)
+{
+    return cpu_register_io_memory(mem_read, mem_write, opaque);
+}
+#endif
+
+struct omap_l4_s {
+    target_phys_addr_t base;
+    int ta_num;
+    struct omap_target_agent_s ta[0];
+};
+
+struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
+{
+    struct omap_l4_s *bus = qemu_mallocz(
+                    sizeof(*bus) + ta_num * sizeof(*bus->ta));
+
+    bus->ta_num = ta_num;
+    bus->base = base;
+
+#ifdef L4_MUX_HACK
+    omap_l4_io_entries = 1;
+    omap_l4_io_entry = qemu_mallocz(125 * sizeof(*omap_l4_io_entry));
+
+    omap_cpu_io_entry =
+            cpu_register_io_memory(omap_l4_io_readfn,
+                            omap_l4_io_writefn, bus);
+# define L4_PAGES	(0xb4000 / TARGET_PAGE_SIZE)
+    omap_l4_io_readb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_readh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_readw_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_writeb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_writeh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_writew_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_opaque = qemu_mallocz(sizeof(void *) * L4_PAGES);
+#endif
+
+    return bus;
+}
+
+static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* COMPONENT */
+        return s->component;
+
+    case 0x20:	/* AGENT_CONTROL */
+        return s->control;
+
+    case 0x28:	/* AGENT_STATUS */
+        return s->status;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* COMPONENT */
+    case 0x28:	/* AGENT_STATUS */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x20:	/* AGENT_CONTROL */
+        s->control = value & 0x01000700;
+        if (value & 1)					/* OCP_RESET */
+            s->status &= ~1;				/* REQ_TIMEOUT */
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static CPUReadMemoryFunc * const omap_l4ta_readfn[] = {
+    omap_badwidth_read16,
+    omap_l4ta_read,
+    omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc * const omap_l4ta_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap_l4ta_write,
+};
+
+struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
+        const struct omap_l4_region_s *regions,
+	const struct omap_l4_agent_info_s *agents,
+	int cs)
+{
+    int i, iomemtype;
+    struct omap_target_agent_s *ta = NULL;
+    const struct omap_l4_agent_info_s *info = NULL;
+
+    for (i = 0; i < bus->ta_num; i ++)
+        if (agents[i].ta == cs) {
+            ta = &bus->ta[i];
+            info = &agents[i];
+            break;
+        }
+    if (!ta) {
+        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
+        exit(-1);
+    }
+
+    ta->bus = bus;
+    ta->start = &regions[info->region];
+    ta->regions = info->regions;
+
+    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
+    ta->status = 0x00000000;
+    ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
+
+    iomemtype = l4_register_io_memory(omap_l4ta_readfn,
+                    omap_l4ta_writefn, ta);
+    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
+
+    return ta;
+}
+
+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
+                int iotype)
+{
+    target_phys_addr_t base;
+    ssize_t size;
+#ifdef L4_MUX_HACK
+    int i;
+#endif
+
+    if (region < 0 || region >= ta->regions) {
+        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
+        exit(-1);
+    }
+
+    base = ta->bus->base + ta->start[region].offset;
+    size = ta->start[region].size;
+    if (iotype) {
+#ifndef L4_MUX_HACK
+        cpu_register_physical_memory(base, size, iotype);
+#else
+        cpu_register_physical_memory(base, size, omap_cpu_io_entry);
+        i = (base - ta->bus->base) / TARGET_PAGE_SIZE;
+        for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) {
+            omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0];
+            omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1];
+            omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2];
+            omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0];
+            omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1];
+            omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2];
+            omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque;
+        }
+#endif
+    }
+
+    return base;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 11/12] hw/omap1.c : separate uart module
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (9 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 10/12] hw/omwp2.c : separate l4 interconnect module cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 12/12] hw/omap : make local function static and remove declaration from header cmchao
  11 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    3 +-
 hw/omap1.c      |  170 ------------------------------------------------
 hw/omap_uart.c  |  194 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 196 insertions(+), 171 deletions(-)
 create mode 100644 hw/omap_uart.c

diff --git a/Makefile.target b/Makefile.target
index 20bcb8a..a01daa4 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -263,7 +263,8 @@ 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
+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
 obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
 		omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
diff --git a/hw/omap1.c b/hw/omap1.c
index 21c53fe..301eec5 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -1378,176 +1378,6 @@ static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
     cpu_register_physical_memory(base, 0x100, iomemtype);
 }
 
-/* UARTs */
-struct omap_uart_s {
-    target_phys_addr_t base;
-    SerialState *serial; /* TODO */
-    struct omap_target_agent_s *ta;
-    omap_clk fclk;
-    qemu_irq irq;
-
-    uint8_t eblr;
-    uint8_t syscontrol;
-    uint8_t wkup;
-    uint8_t cfps;
-    uint8_t mdr[2];
-    uint8_t scr;
-    uint8_t clksel;
-};
-
-void omap_uart_reset(struct omap_uart_s *s)
-{
-    s->eblr = 0x00;
-    s->syscontrol = 0;
-    s->wkup = 0x3f;
-    s->cfps = 0x69;
-    s->clksel = 0;
-}
-
-struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk fclk, omap_clk iclk,
-                qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
-{
-    struct omap_uart_s *s = (struct omap_uart_s *)
-            qemu_mallocz(sizeof(struct omap_uart_s));
-
-    s->base = base;
-    s->fclk = fclk;
-    s->irq = irq;
-#ifdef TARGET_WORDS_BIGENDIAN
-    s->serial = serial_mm_init(base, 2, irq, omap_clk_getrate(fclk)/16,
-                               chr ?: qemu_chr_open("null", "null", NULL), 1,
-                               1);
-#else
-    s->serial = serial_mm_init(base, 2, irq, omap_clk_getrate(fclk)/16,
-                               chr ?: qemu_chr_open("null", "null", NULL), 1,
-                               0);
-#endif
-    return s;
-}
-
-static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
-
-    addr &= 0xff;
-    switch (addr) {
-    case 0x20:	/* MDR1 */
-        return s->mdr[0];
-    case 0x24:	/* MDR2 */
-        return s->mdr[1];
-    case 0x40:	/* SCR */
-        return s->scr;
-    case 0x44:	/* SSR */
-        return 0x0;
-    case 0x48:	/* EBLR (OMAP2) */
-        return s->eblr;
-    case 0x4C:	/* OSC_12M_SEL (OMAP1) */
-        return s->clksel;
-    case 0x50:	/* MVR */
-        return 0x30;
-    case 0x54:	/* SYSC (OMAP2) */
-        return s->syscontrol;
-    case 0x58:	/* SYSS (OMAP2) */
-        return 1;
-    case 0x5c:	/* WER (OMAP2) */
-        return s->wkup;
-    case 0x60:	/* CFPS (OMAP2) */
-        return s->cfps;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_uart_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
-
-    addr &= 0xff;
-    switch (addr) {
-    case 0x20:	/* MDR1 */
-        s->mdr[0] = value & 0x7f;
-        break;
-    case 0x24:	/* MDR2 */
-        s->mdr[1] = value & 0xff;
-        break;
-    case 0x40:	/* SCR */
-        s->scr = value & 0xff;
-        break;
-    case 0x48:	/* EBLR (OMAP2) */
-        s->eblr = value & 0xff;
-        break;
-    case 0x4C:	/* OSC_12M_SEL (OMAP1) */
-        s->clksel = value & 1;
-        break;
-    case 0x44:	/* SSR */
-    case 0x50:	/* MVR */
-    case 0x58:	/* SYSS (OMAP2) */
-        OMAP_RO_REG(addr);
-        break;
-    case 0x54:	/* SYSC (OMAP2) */
-        s->syscontrol = value & 0x1d;
-        if (value & 2)
-            omap_uart_reset(s);
-        break;
-    case 0x5c:	/* WER (OMAP2) */
-        s->wkup = value & 0x7f;
-        break;
-    case 0x60:	/* CFPS (OMAP2) */
-        s->cfps = value & 0xff;
-        break;
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static CPUReadMemoryFunc * const omap_uart_readfn[] = {
-    omap_uart_read,
-    omap_uart_read,
-    omap_badwidth_read8,
-};
-
-static CPUWriteMemoryFunc * const omap_uart_writefn[] = {
-    omap_uart_write,
-    omap_uart_write,
-    omap_badwidth_write8,
-};
-
-struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
-                qemu_irq irq, omap_clk fclk, omap_clk iclk,
-                qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
-{
-    target_phys_addr_t base = omap_l4_attach(ta, 0, 0);
-    struct omap_uart_s *s = omap_uart_init(base, irq,
-                    fclk, iclk, txdma, rxdma, chr);
-    int iomemtype = cpu_register_io_memory(omap_uart_readfn,
-                    omap_uart_writefn, s);
-
-    s->ta = ta;
-
-    cpu_register_physical_memory(base + 0x20, 0x100, iomemtype);
-
-    return s;
-}
-
-void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr)
-{
-    /* TODO: Should reuse or destroy current s->serial */
-#ifdef TARGET_WORDS_BIGENDIAN
-    s->serial = serial_mm_init(s->base, 2, s->irq,
-                               omap_clk_getrate(s->fclk) / 16,
-                               chr ?: qemu_chr_open("null", "null", NULL), 1,
-                               1);
-#else
-    s->serial = serial_mm_init(s->base, 2, s->irq,
-                               omap_clk_getrate(s->fclk) / 16,
-                               chr ?: qemu_chr_open("null", "null", NULL), 1,
-                               0);
-#endif
-}
-
 /* MPU Clock/Reset/Power Mode Control */
 static uint32_t omap_clkm_read(void *opaque, target_phys_addr_t addr)
 {
diff --git a/hw/omap_uart.c b/hw/omap_uart.c
new file mode 100644
index 0000000..395bf0c
--- /dev/null
+++ b/hw/omap_uart.c
@@ -0,0 +1,194 @@
+/*
+ * TI OMAP processors UART emulation.
+ *
+ * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
+ * Copyright (C) 2007-2009 Nokia Corporation
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qemu-char.h"
+#include "hw.h"
+#include "omap.h"
+/* We use pc-style serial ports.  */
+#include "pc.h"
+
+/* UARTs */
+struct omap_uart_s {
+    target_phys_addr_t base;
+    SerialState *serial; /* TODO */
+    struct omap_target_agent_s *ta;
+    omap_clk fclk;
+    qemu_irq irq;
+
+    uint8_t eblr;
+    uint8_t syscontrol;
+    uint8_t wkup;
+    uint8_t cfps;
+    uint8_t mdr[2];
+    uint8_t scr;
+    uint8_t clksel;
+};
+
+void omap_uart_reset(struct omap_uart_s *s)
+{
+    s->eblr = 0x00;
+    s->syscontrol = 0;
+    s->wkup = 0x3f;
+    s->cfps = 0x69;
+    s->clksel = 0;
+}
+
+struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
+                qemu_irq irq, omap_clk fclk, omap_clk iclk,
+                qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
+{
+    struct omap_uart_s *s = (struct omap_uart_s *)
+            qemu_mallocz(sizeof(struct omap_uart_s));
+
+    s->base = base;
+    s->fclk = fclk;
+    s->irq = irq;
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->serial = serial_mm_init(base, 2, irq, omap_clk_getrate(fclk)/16,
+                               chr ?: qemu_chr_open("null", "null", NULL), 1,
+                               1);
+#else
+    s->serial = serial_mm_init(base, 2, irq, omap_clk_getrate(fclk)/16,
+                               chr ?: qemu_chr_open("null", "null", NULL), 1,
+                               0);
+#endif
+    return s;
+}
+
+static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
+
+    addr &= 0xff;
+    switch (addr) {
+    case 0x20:	/* MDR1 */
+        return s->mdr[0];
+    case 0x24:	/* MDR2 */
+        return s->mdr[1];
+    case 0x40:	/* SCR */
+        return s->scr;
+    case 0x44:	/* SSR */
+        return 0x0;
+    case 0x48:	/* EBLR (OMAP2) */
+        return s->eblr;
+    case 0x4C:	/* OSC_12M_SEL (OMAP1) */
+        return s->clksel;
+    case 0x50:	/* MVR */
+        return 0x30;
+    case 0x54:	/* SYSC (OMAP2) */
+        return s->syscontrol;
+    case 0x58:	/* SYSS (OMAP2) */
+        return 1;
+    case 0x5c:	/* WER (OMAP2) */
+        return s->wkup;
+    case 0x60:	/* CFPS (OMAP2) */
+        return s->cfps;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_uart_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_uart_s *s = (struct omap_uart_s *) opaque;
+
+    addr &= 0xff;
+    switch (addr) {
+    case 0x20:	/* MDR1 */
+        s->mdr[0] = value & 0x7f;
+        break;
+    case 0x24:	/* MDR2 */
+        s->mdr[1] = value & 0xff;
+        break;
+    case 0x40:	/* SCR */
+        s->scr = value & 0xff;
+        break;
+    case 0x48:	/* EBLR (OMAP2) */
+        s->eblr = value & 0xff;
+        break;
+    case 0x4C:	/* OSC_12M_SEL (OMAP1) */
+        s->clksel = value & 1;
+        break;
+    case 0x44:	/* SSR */
+    case 0x50:	/* MVR */
+    case 0x58:	/* SYSS (OMAP2) */
+        OMAP_RO_REG(addr);
+        break;
+    case 0x54:	/* SYSC (OMAP2) */
+        s->syscontrol = value & 0x1d;
+        if (value & 2)
+            omap_uart_reset(s);
+        break;
+    case 0x5c:	/* WER (OMAP2) */
+        s->wkup = value & 0x7f;
+        break;
+    case 0x60:	/* CFPS (OMAP2) */
+        s->cfps = value & 0xff;
+        break;
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static CPUReadMemoryFunc * const omap_uart_readfn[] = {
+    omap_uart_read,
+    omap_uart_read,
+    omap_badwidth_read8,
+};
+
+static CPUWriteMemoryFunc * const omap_uart_writefn[] = {
+    omap_uart_write,
+    omap_uart_write,
+    omap_badwidth_write8,
+};
+
+struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
+                qemu_irq irq, omap_clk fclk, omap_clk iclk,
+                qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
+{
+    target_phys_addr_t base = omap_l4_attach(ta, 0, 0);
+    struct omap_uart_s *s = omap_uart_init(base, irq,
+                    fclk, iclk, txdma, rxdma, chr);
+    int iomemtype = cpu_register_io_memory(omap_uart_readfn,
+                    omap_uart_writefn, s);
+
+    s->ta = ta;
+
+    cpu_register_physical_memory(base + 0x20, 0x100, iomemtype);
+
+    return s;
+}
+
+void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr)
+{
+    /* TODO: Should reuse or destroy current s->serial */
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->serial = serial_mm_init(s->base, 2, s->irq,
+                               omap_clk_getrate(s->fclk) / 16,
+                               chr ?: qemu_chr_open("null", "null", NULL), 1,
+                               1);
+#else
+    s->serial = serial_mm_init(s->base, 2, s->irq,
+                               omap_clk_getrate(s->fclk) / 16,
+                               chr ?: qemu_chr_open("null", "null", NULL), 1,
+                               0);
+#endif
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 12/12] hw/omap : make local function static and remove declaration from header
  2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
                   ` (10 preceding siblings ...)
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 11/12] hw/omap1.c : separate uart module cmchao
@ 2010-05-28 17:43 ` cmchao
  2010-05-30 10:30   ` [Qemu-devel] " Chih-Min Chao
  11 siblings, 1 reply; 16+ messages in thread
From: cmchao @ 2010-05-28 17:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao


Signed-off-by: cmchao <cmchao@gmail.com>
---
 hw/omap.h  |   36 ------------------------------------
 hw/omap1.c |   10 +++++-----
 hw/omap2.c |    6 +++---
 3 files changed, 8 insertions(+), 44 deletions(-)

diff --git a/hw/omap.h b/hw/omap.h
index 34443b4..18eb72b 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -108,15 +108,6 @@ struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
 void omap_inth_reset(struct omap_intr_handler_s *s);
 qemu_irq omap_inth_get_pin(struct omap_intr_handler_s *s, int n);
 
-struct omap_prcm_s;
-struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
-                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
-                struct omap_mpu_state_s *mpu);
-
-struct omap_sysctl_s;
-struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
-                omap_clk iclk, struct omap_mpu_state_s *mpu);
-
 /* OMAP2 SDRAM controller */
 struct omap_sdrc_s;
 struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
@@ -658,34 +649,18 @@ struct omap_dma_lcd_channel_s {
 # define OMAP24XX_DMA_EXT_DMAREQ5	64
 
 /* omap[123].c */
-struct omap_mpu_timer_s;
-struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk);
-
 /* OMAP2 gp timer */
 struct omap_gp_timer_s;
 struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk);
 void omap_gp_timer_reset(struct omap_gp_timer_s *s);
 
-struct omap_watchdog_timer_s;
-struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk);
-
-struct omap_32khz_timer_s;
-struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
-                qemu_irq irq, omap_clk clk);
-
 /* OMAP2 sysctimer */
 struct omap_synctimer_s;
 struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk);
 void omap_synctimer_reset(struct omap_synctimer_s *s);
 
-struct omap_tipb_bridge_s;
-struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
-                qemu_irq abort_irq, omap_clk clk);
-
 struct omap_uart_s;
 struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk fclk, omap_clk iclk,
@@ -740,10 +715,6 @@ void omap_mcspi_attach(struct omap_mcspi_s *s,
                 int chipselect);
 void omap_mcspi_reset(struct omap_mcspi_s *s);
 
-struct omap_rtc_s;
-struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
-                qemu_irq *irq, omap_clk clk);
-
 struct I2SCodec {
     void *opaque;
 
@@ -773,16 +744,9 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
                 qemu_irq *irq, qemu_irq *dma, omap_clk clk);
 void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave);
 
-struct omap_lpg_s;
-struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk);
-
 void omap_tap_init(struct omap_target_agent_s *ta,
                 struct omap_mpu_state_s *mpu);
 
-struct omap_eac_s;
-struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
-                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk);
-
 /* omap_lcdc.c */
 struct omap_lcd_panel_s;
 void omap_lcdc_reset(struct omap_lcd_panel_s *s);
diff --git a/hw/omap1.c b/hw/omap1.c
index 301eec5..e38fd83 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -247,7 +247,7 @@ static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
     s->it_ena = 1;
 }
 
-struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
+static struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk clk)
 {
     int iomemtype;
@@ -371,7 +371,7 @@ static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
     omap_timer_update(&s->timer);
 }
 
-struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
+static struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk clk)
 {
     int iomemtype;
@@ -473,7 +473,7 @@ static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
     s->timer.ar = 1;
 }
 
-struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
+static struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
                 qemu_irq irq, omap_clk clk)
 {
     int iomemtype;
@@ -1180,7 +1180,7 @@ static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
     s->enh_control = 0x000f;
 }
 
-struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
+static struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
                 qemu_irq abort_irq, omap_clk clk)
 {
     int iomemtype;
@@ -3506,7 +3506,7 @@ static void omap_lpg_clk_update(void *opaque, int line, int on)
     omap_lpg_update(s);
 }
 
-struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
+static struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
 {
     int iomemtype;
     struct omap_lpg_s *s = (struct omap_lpg_s *)
diff --git a/hw/omap2.c b/hw/omap2.c
index 9bac954..26e6da4 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -583,7 +583,7 @@ static CPUWriteMemoryFunc * const omap_eac_writefn[] = {
     omap_badwidth_write16,
 };
 
-struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
+static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
 {
     int iomemtype;
@@ -1783,7 +1783,7 @@ static void omap_prcm_coldreset(struct omap_prcm_s *s)
     omap_prcm_reset(s);
 }
 
-struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
+static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
                 qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
                 struct omap_mpu_state_s *mpu)
 {
@@ -2157,7 +2157,7 @@ static void omap_sysctl_reset(struct omap_sysctl_s *s)
     s->padconf[0x44] = 0x00000800;
 }
 
-struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
+static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
                 omap_clk iclk, struct omap_mpu_state_s *mpu)
 {
     int iomemtype;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] Re: [PATCH 12/12] hw/omap : make local function static and remove declaration from header
  2010-05-28 17:43 ` [Qemu-devel] [PATCH 12/12] hw/omap : make local function static and remove declaration from header cmchao
@ 2010-05-30 10:30   ` Chih-Min Chao
  2010-05-30 11:00     ` Andreas Färber
  0 siblings, 1 reply; 16+ messages in thread
From: Chih-Min Chao @ 2010-05-30 10:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: cmchao

[-- Attachment #1: Type: text/plain, Size: 7006 bytes --]

 On Sat, May 29, 2010 at 1:43 AM, cmchao <cmchao@gmail.com> wrote:

>
> Signed-off-by: cmchao <cmchao@gmail.com>
> ---
>  hw/omap.h  |   36 ------------------------------------
>  hw/omap1.c |   10 +++++-----
>  hw/omap2.c |    6 +++---
>  3 files changed, 8 insertions(+), 44 deletions(-)
>
> diff --git a/hw/omap.h b/hw/omap.h
> index 34443b4..18eb72b 100644
> --- a/hw/omap.h
> +++ b/hw/omap.h
> @@ -108,15 +108,6 @@ struct omap_intr_handler_s
> *omap2_inth_init(target_phys_addr_t base,
>  void omap_inth_reset(struct omap_intr_handler_s *s);
>  qemu_irq omap_inth_get_pin(struct omap_intr_handler_s *s, int n);
>
> -struct omap_prcm_s;
> -struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
> -                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
> -                struct omap_mpu_state_s *mpu);
> -
> -struct omap_sysctl_s;
> -struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
> -                omap_clk iclk, struct omap_mpu_state_s *mpu);
> -
>  /* OMAP2 SDRAM controller */
>  struct omap_sdrc_s;
>  struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
> @@ -658,34 +649,18 @@ struct omap_dma_lcd_channel_s {
>  # define OMAP24XX_DMA_EXT_DMAREQ5      64
>
>  /* omap[123].c */
> -struct omap_mpu_timer_s;
> -struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
> -                qemu_irq irq, omap_clk clk);
> -
>  /* OMAP2 gp timer */
>  struct omap_gp_timer_s;
>  struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
>                 qemu_irq irq, omap_clk fclk, omap_clk iclk);
>  void omap_gp_timer_reset(struct omap_gp_timer_s *s);
>
> -struct omap_watchdog_timer_s;
> -struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
> -                qemu_irq irq, omap_clk clk);
> -
> -struct omap_32khz_timer_s;
> -struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
> -                qemu_irq irq, omap_clk clk);
> -
>  /* OMAP2 sysctimer */
>  struct omap_synctimer_s;
>  struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s
> *ta,
>                 struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk
> iclk);
>  void omap_synctimer_reset(struct omap_synctimer_s *s);
>
> -struct omap_tipb_bridge_s;
> -struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
> -                qemu_irq abort_irq, omap_clk clk);
> -
>  struct omap_uart_s;
>  struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
>                 qemu_irq irq, omap_clk fclk, omap_clk iclk,
> @@ -740,10 +715,6 @@ void omap_mcspi_attach(struct omap_mcspi_s *s,
>                 int chipselect);
>  void omap_mcspi_reset(struct omap_mcspi_s *s);
>
> -struct omap_rtc_s;
> -struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
> -                qemu_irq *irq, omap_clk clk);
> -
>  struct I2SCodec {
>     void *opaque;
>
> @@ -773,16 +744,9 @@ struct omap_mcbsp_s
> *omap_mcbsp_init(target_phys_addr_t base,
>                 qemu_irq *irq, qemu_irq *dma, omap_clk clk);
>  void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave);
>
> -struct omap_lpg_s;
> -struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk);
> -
>  void omap_tap_init(struct omap_target_agent_s *ta,
>                 struct omap_mpu_state_s *mpu);
>
> -struct omap_eac_s;
> -struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
> -                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk
> iclk);
> -
>  /* omap_lcdc.c */
>  struct omap_lcd_panel_s;
>  void omap_lcdc_reset(struct omap_lcd_panel_s *s);
> diff --git a/hw/omap1.c b/hw/omap1.c
> index 301eec5..e38fd83 100644
> --- a/hw/omap1.c
> +++ b/hw/omap1.c
> @@ -247,7 +247,7 @@ static void omap_mpu_timer_reset(struct
> omap_mpu_timer_s *s)
>     s->it_ena = 1;
>  }
>
> -struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
> +static struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t
> base,
>                 qemu_irq irq, omap_clk clk)
>  {
>     int iomemtype;
> @@ -371,7 +371,7 @@ static void omap_wd_timer_reset(struct
> omap_watchdog_timer_s *s)
>     omap_timer_update(&s->timer);
>  }
>
> -struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
> +static struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t
> base,
>                 qemu_irq irq, omap_clk clk)
>  {
>     int iomemtype;
> @@ -473,7 +473,7 @@ static void omap_os_timer_reset(struct
> omap_32khz_timer_s *s)
>     s->timer.ar = 1;
>  }
>
> -struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
> +static struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t
> base,
>                 qemu_irq irq, omap_clk clk)
>  {
>     int iomemtype;
> @@ -1180,7 +1180,7 @@ static void omap_tipb_bridge_reset(struct
> omap_tipb_bridge_s *s)
>     s->enh_control = 0x000f;
>  }
>
> -struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
> +static struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t
> base,
>                 qemu_irq abort_irq, omap_clk clk)
>  {
>     int iomemtype;
> @@ -3506,7 +3506,7 @@ static void omap_lpg_clk_update(void *opaque, int
> line, int on)
>     omap_lpg_update(s);
>  }
>
> -struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
> +static struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk
> clk)
>  {
>     int iomemtype;
>     struct omap_lpg_s *s = (struct omap_lpg_s *)
> diff --git a/hw/omap2.c b/hw/omap2.c
> index 9bac954..26e6da4 100644
> --- a/hw/omap2.c
> +++ b/hw/omap2.c
> @@ -583,7 +583,7 @@ static CPUWriteMemoryFunc * const omap_eac_writefn[] =
> {
>     omap_badwidth_write16,
>  };
>
> -struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
> +static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
>                 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
>  {
>     int iomemtype;
> @@ -1783,7 +1783,7 @@ static void omap_prcm_coldreset(struct omap_prcm_s
> *s)
>     omap_prcm_reset(s);
>  }
>
> -struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
> +static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
>                 qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
>                 struct omap_mpu_state_s *mpu)
>  {
> @@ -2157,7 +2157,7 @@ static void omap_sysctl_reset(struct omap_sysctl_s
> *s)
>     s->padconf[0x44] = 0x00000800;
>  }
>
> -struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
> +static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s
> *ta,
>                 omap_clk iclk, struct omap_mpu_state_s *mpu)
>  {
>     int iomemtype;
> --
> 1.7.0.4
>
>
At first, sorry for sending duplicated patches

I found i missed one line modification in this patch that produce
compilation error
Should i
  1  re-send complete series patched
  2  re-send this patch only
  3  just provide a fix for it. (if they are acceptable)

[-- Attachment #2: Type: text/html, Size: 8279 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] Re: [PATCH 12/12] hw/omap : make local function static and remove declaration from header
  2010-05-30 10:30   ` [Qemu-devel] " Chih-Min Chao
@ 2010-05-30 11:00     ` Andreas Färber
  0 siblings, 0 replies; 16+ messages in thread
From: Andreas Färber @ 2010-05-30 11:00 UTC (permalink / raw)
  To: Chih-Min Chao; +Cc: qemu-devel

Am 30.05.2010 um 12:30 schrieb Chih-Min Chao:

> I found i missed one line modification in this patch that produce  
> compilation error
> Should i
>   1  re-send complete series patched
>   2  re-send this patch only
>   3  just provide a fix for it. (if they are acceptable)

Committing known-broken patches is bad for bisecting, so resending a  
new version of the patch or the series is preferred.

Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 10/12] hw/omwp2.c : separate l4 interconnect module
  2010-05-29  1:54 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
@ 2010-05-29  1:54 ` cmchao
  0 siblings, 0 replies; 16+ messages in thread
From: cmchao @ 2010-05-29  1:54 UTC (permalink / raw)
  To: qemu-devel


Signed-off-by: cmchao <cmchao@gmail.com>
---
 Makefile.target |    3 +-
 hw/omap.h       |   37 ++++++--
 hw/omap2.c      |  269 ++-----------------------------------------------------
 hw/omap_l4.c    |  271 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 307 insertions(+), 273 deletions(-)
 create mode 100644 hw/omap_l4.c

diff --git a/Makefile.target b/Makefile.target
index 39d2858..20bcb8a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -264,7 +264,8 @@ 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
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o
+obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
+		omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
 obj-arm-y += omap_sx1.o palm.o tsc210x.o
 obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 obj-arm-y += mst_fpga.o mainstone.o
diff --git a/hw/omap.h b/hw/omap.h
index fef495a..34443b4 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -61,15 +61,40 @@ void omap_clk_setrate(omap_clk clk, int divide, int multiply);
 int64_t omap_clk_getrate(omap_clk clk);
 void omap_clk_reparent(omap_clk clk, omap_clk parent);
 
-/* omap[123].c */
+/* OMAP2 l4 Interconnect */
 struct omap_l4_s;
+struct omap_l4_region_s {
+    target_phys_addr_t offset;
+    size_t size;
+    int access;
+};
+struct omap_l4_agent_info_s {
+    int ta;
+    int region;
+    int regions;
+    int ta_region;
+};
+struct omap_target_agent_s {
+    struct omap_l4_s *bus;
+    int regions;
+    const struct omap_l4_region_s *start;
+    target_phys_addr_t base;
+    uint32_t component;
+    uint32_t control;
+    uint32_t status;
+};
 struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num);
 
 struct omap_target_agent_s;
-struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs);
+struct omap_target_agent_s *omap_l4ta_get(
+    struct omap_l4_s *bus,
+    const struct omap_l4_region_s *regions,
+    const struct omap_l4_agent_info_s *agents,
+    int cs);
 target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
                 int iotype);
-# define l4_register_io_memory	cpu_register_io_memory
+int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
+                CPUWriteMemoryFunc * const *mem_write, void *opaque);
 
 /* OMAP interrupt controller */
 struct omap_intr_handler_s;
@@ -1146,10 +1171,4 @@ inline static int debug_register_io_memory(CPUReadMemoryFunc * const *mem_read,
 /* Define when we want to reduce the number of IO regions registered.  */
 /*# define L4_MUX_HACK*/
 
-# ifdef L4_MUX_HACK
-#  undef l4_register_io_memory
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                          CPUWriteMemoryFunc * const *mem_write, void *opaque);
-# endif
-
 #endif /* hw_omap_h */
diff --git a/hw/omap2.c b/hw/omap2.c
index 7403077..9bac954 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -795,195 +795,10 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
 }
 
 /* L4 Interconnect */
-struct omap_target_agent_s {
-    struct omap_l4_s *bus;
-    int regions;
-    struct omap_l4_region_s *start;
-    target_phys_addr_t base;
-    uint32_t component;
-    uint32_t control;
-    uint32_t status;
-};
-
-struct omap_l4_s {
-    target_phys_addr_t base;
-    int ta_num;
-    struct omap_target_agent_s ta[0];
-};
-
-#ifdef L4_MUX_HACK
-static int omap_l4_io_entries;
-static int omap_cpu_io_entry;
-static struct omap_l4_entry {
-        CPUReadMemoryFunc * const *mem_read;
-        CPUWriteMemoryFunc * const *mem_write;
-        void *opaque;
-} *omap_l4_io_entry;
-static CPUReadMemoryFunc * const *omap_l4_io_readb_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readh_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readw_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeb_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeh_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writew_fn;
-static void **omap_l4_io_opaque;
-
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                CPUWriteMemoryFunc * const *mem_write, void *opaque)
-{
-    omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read;
-    omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write;
-    omap_l4_io_entry[omap_l4_io_entries].opaque = opaque;
-
-    return omap_l4_io_entries ++;
-}
-
-static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static CPUReadMemoryFunc * const omap_l4_io_readfn[] = {
-    omap_l4_io_readb,
-    omap_l4_io_readh,
-    omap_l4_io_readw,
-};
-
-static CPUWriteMemoryFunc * const omap_l4_io_writefn[] = {
-    omap_l4_io_writeb,
-    omap_l4_io_writeh,
-    omap_l4_io_writew,
-};
-#endif
-
-struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
-{
-    struct omap_l4_s *bus = qemu_mallocz(
-                    sizeof(*bus) + ta_num * sizeof(*bus->ta));
-
-    bus->ta_num = ta_num;
-    bus->base = base;
-
-#ifdef L4_MUX_HACK
-    omap_l4_io_entries = 1;
-    omap_l4_io_entry = qemu_mallocz(125 * sizeof(*omap_l4_io_entry));
-
-    omap_cpu_io_entry =
-            cpu_register_io_memory(omap_l4_io_readfn,
-                            omap_l4_io_writefn, bus);
-# define L4_PAGES	(0xb4000 / TARGET_PAGE_SIZE)
-    omap_l4_io_readb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readw_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writew_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_opaque = qemu_mallocz(sizeof(void *) * L4_PAGES);
-#endif
-
-    return bus;
-}
-
-static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* COMPONENT */
-        return s->component;
-
-    case 0x20:	/* AGENT_CONTROL */
-        return s->control;
-
-    case 0x28:	/* AGENT_STATUS */
-        return s->status;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-
-    switch (addr) {
-    case 0x00:	/* COMPONENT */
-    case 0x28:	/* AGENT_STATUS */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x20:	/* AGENT_CONTROL */
-        s->control = value & 0x01000700;
-        if (value & 1)					/* OCP_RESET */
-            s->status &= ~1;				/* REQ_TIMEOUT */
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static CPUReadMemoryFunc * const omap_l4ta_readfn[] = {
-    omap_badwidth_read16,
-    omap_l4ta_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_l4ta_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_l4ta_write,
-};
-
 #define L4TA(n)		(n)
 #define L4TAO(n)	((n) + 39)
 
-static struct omap_l4_region_s {
-    target_phys_addr_t offset;
-    size_t size;
-    int access;
-} omap_l4_region[125] = {
+static const struct omap_l4_region_s omap_l4_region[125] = {
     [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
     [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
     [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
@@ -1111,12 +926,7 @@ static struct omap_l4_region_s {
     [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
 };
 
-static struct omap_l4_agent_info_s {
-    int ta;
-    int region;
-    int regions;
-    int ta_region;
-} omap_l4_agent_info[54] = {
+static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
     { 0,           0, 3, 2 }, /* L4IA initiatior agent */
     { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
     { L4TAO(2),    5, 2, 1 }, /* 32K timer */
@@ -1173,77 +983,10 @@ static struct omap_l4_agent_info_s {
     { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
 };
 
-#define omap_l4ta(bus, cs)	omap_l4ta_get(bus, L4TA(cs))
-#define omap_l4tao(bus, cs)	omap_l4ta_get(bus, L4TAO(cs))
-
-struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs)
-{
-    int i, iomemtype;
-    struct omap_target_agent_s *ta = NULL;
-    struct omap_l4_agent_info_s *info = NULL;
-
-    for (i = 0; i < bus->ta_num; i ++)
-        if (omap_l4_agent_info[i].ta == cs) {
-            ta = &bus->ta[i];
-            info = &omap_l4_agent_info[i];
-            break;
-        }
-    if (!ta) {
-        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
-        exit(-1);
-    }
-
-    ta->bus = bus;
-    ta->start = &omap_l4_region[info->region];
-    ta->regions = info->regions;
-
-    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    ta->status = 0x00000000;
-    ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
-
-    iomemtype = l4_register_io_memory(omap_l4ta_readfn,
-                    omap_l4ta_writefn, ta);
-    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
-
-    return ta;
-}
-
-target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-                int iotype)
-{
-    target_phys_addr_t base;
-    ssize_t size;
-#ifdef L4_MUX_HACK
-    int i;
-#endif
-
-    if (region < 0 || region >= ta->regions) {
-        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
-        exit(-1);
-    }
-
-    base = ta->bus->base + ta->start[region].offset;
-    size = ta->start[region].size;
-    if (iotype) {
-#ifndef L4_MUX_HACK
-        cpu_register_physical_memory(base, size, iotype);
-#else
-        cpu_register_physical_memory(base, size, omap_cpu_io_entry);
-        i = (base - ta->bus->base) / TARGET_PAGE_SIZE;
-        for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) {
-            omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0];
-            omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1];
-            omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2];
-            omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0];
-            omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1];
-            omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2];
-            omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque;
-        }
-#endif
-    }
-
-    return base;
-}
+#define omap_l4ta(bus, cs)	\
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs))
+#define omap_l4tao(bus, cs)	\
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs))
 
 /* Power, Reset, and Clock Management */
 struct omap_prcm_s {
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
new file mode 100644
index 0000000..bf8ba36
--- /dev/null
+++ b/hw/omap_l4.c
@@ -0,0 +1,271 @@
+/*
+ * TI OMAP L4 interconnect emulation.
+ *
+ * Copyright (C) 2007-2009 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * 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 or
+ * (at your option) any later version of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "omap.h"
+
+#ifdef L4_MUX_HACK
+static int omap_l4_io_entries;
+static int omap_cpu_io_entry;
+static struct omap_l4_entry {
+        CPUReadMemoryFunc * const *mem_read;
+        CPUWriteMemoryFunc * const *mem_write;
+        void *opaque;
+} *omap_l4_io_entry;
+static CPUReadMemoryFunc * const *omap_l4_io_readb_fn;
+static CPUReadMemoryFunc * const *omap_l4_io_readh_fn;
+static CPUReadMemoryFunc * const *omap_l4_io_readw_fn;
+static CPUWriteMemoryFunc * const *omap_l4_io_writeb_fn;
+static CPUWriteMemoryFunc * const *omap_l4_io_writeh_fn;
+static CPUWriteMemoryFunc * const *omap_l4_io_writew_fn;
+static void **omap_l4_io_opaque;
+
+int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
+                CPUWriteMemoryFunc * const *mem_write, void *opaque)
+{
+    omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read;
+    omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write;
+    omap_l4_io_entry[omap_l4_io_entries].opaque = opaque;
+
+    return omap_l4_io_entries ++;
+}
+
+static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr);
+}
+
+static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr);
+}
+
+static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr);
+}
+
+static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value);
+}
+
+static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value);
+}
+
+static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
+
+    return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value);
+}
+
+static CPUReadMemoryFunc * const omap_l4_io_readfn[] = {
+    omap_l4_io_readb,
+    omap_l4_io_readh,
+    omap_l4_io_readw,
+};
+
+static CPUWriteMemoryFunc * const omap_l4_io_writefn[] = {
+    omap_l4_io_writeb,
+    omap_l4_io_writeh,
+    omap_l4_io_writew,
+};
+#else
+int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
+                          CPUWriteMemoryFunc * const *mem_write,
+                          void *opaque)
+{
+    return cpu_register_io_memory(mem_read, mem_write, opaque);
+}
+#endif
+
+struct omap_l4_s {
+    target_phys_addr_t base;
+    int ta_num;
+    struct omap_target_agent_s ta[0];
+};
+
+struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
+{
+    struct omap_l4_s *bus = qemu_mallocz(
+                    sizeof(*bus) + ta_num * sizeof(*bus->ta));
+
+    bus->ta_num = ta_num;
+    bus->base = base;
+
+#ifdef L4_MUX_HACK
+    omap_l4_io_entries = 1;
+    omap_l4_io_entry = qemu_mallocz(125 * sizeof(*omap_l4_io_entry));
+
+    omap_cpu_io_entry =
+            cpu_register_io_memory(omap_l4_io_readfn,
+                            omap_l4_io_writefn, bus);
+# define L4_PAGES	(0xb4000 / TARGET_PAGE_SIZE)
+    omap_l4_io_readb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_readh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_readw_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_writeb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_writeh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_writew_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
+    omap_l4_io_opaque = qemu_mallocz(sizeof(void *) * L4_PAGES);
+#endif
+
+    return bus;
+}
+
+static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* COMPONENT */
+        return s->component;
+
+    case 0x20:	/* AGENT_CONTROL */
+        return s->control;
+
+    case 0x28:	/* AGENT_STATUS */
+        return s->status;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
+
+    switch (addr) {
+    case 0x00:	/* COMPONENT */
+    case 0x28:	/* AGENT_STATUS */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x20:	/* AGENT_CONTROL */
+        s->control = value & 0x01000700;
+        if (value & 1)					/* OCP_RESET */
+            s->status &= ~1;				/* REQ_TIMEOUT */
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static CPUReadMemoryFunc * const omap_l4ta_readfn[] = {
+    omap_badwidth_read16,
+    omap_l4ta_read,
+    omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc * const omap_l4ta_writefn[] = {
+    omap_badwidth_write32,
+    omap_badwidth_write32,
+    omap_l4ta_write,
+};
+
+struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
+        const struct omap_l4_region_s *regions,
+	const struct omap_l4_agent_info_s *agents,
+	int cs)
+{
+    int i, iomemtype;
+    struct omap_target_agent_s *ta = NULL;
+    const struct omap_l4_agent_info_s *info = NULL;
+
+    for (i = 0; i < bus->ta_num; i ++)
+        if (agents[i].ta == cs) {
+            ta = &bus->ta[i];
+            info = &agents[i];
+            break;
+        }
+    if (!ta) {
+        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
+        exit(-1);
+    }
+
+    ta->bus = bus;
+    ta->start = &regions[info->region];
+    ta->regions = info->regions;
+
+    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
+    ta->status = 0x00000000;
+    ta->control = 0x00000200;	/* XXX 01000200 for L4TAO */
+
+    iomemtype = l4_register_io_memory(omap_l4ta_readfn,
+                    omap_l4ta_writefn, ta);
+    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
+
+    return ta;
+}
+
+target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
+                int iotype)
+{
+    target_phys_addr_t base;
+    ssize_t size;
+#ifdef L4_MUX_HACK
+    int i;
+#endif
+
+    if (region < 0 || region >= ta->regions) {
+        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
+        exit(-1);
+    }
+
+    base = ta->bus->base + ta->start[region].offset;
+    size = ta->start[region].size;
+    if (iotype) {
+#ifndef L4_MUX_HACK
+        cpu_register_physical_memory(base, size, iotype);
+#else
+        cpu_register_physical_memory(base, size, omap_cpu_io_entry);
+        i = (base - ta->bus->base) / TARGET_PAGE_SIZE;
+        for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) {
+            omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0];
+            omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1];
+            omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2];
+            omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0];
+            omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1];
+            omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2];
+            omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque;
+        }
+#endif
+    }
+
+    return base;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2010-05-30 11:00 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-28 17:43 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 01/12] hw/omap1.c : separate gpio module cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 02/12] hw/omap2.c " cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 03/12] hw/omap2.c : separate gptimer module cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 04/12] hw/omap2.c : separate synctimer module cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 05/12] hw/omap2.c : separate gpmc(general purpose memory controller) cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 06/12] hw/omap2.c : separate sdrc (sdram controller) cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 07/12] hw/omap1.c : separate interrupt controller module cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 08/12] hw/omap2.c : separate spi module cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 09/12] hw/omap2.c : separate tap module(Test-Chip-level) cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 10/12] hw/omwp2.c : separate l4 interconnect module cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 11/12] hw/omap1.c : separate uart module cmchao
2010-05-28 17:43 ` [Qemu-devel] [PATCH 12/12] hw/omap : make local function static and remove declaration from header cmchao
2010-05-30 10:30   ` [Qemu-devel] " Chih-Min Chao
2010-05-30 11:00     ` Andreas Färber
2010-05-29  1:54 [Qemu-devel] [PATCH 00/12] refactor OMAP implementation cmchao
2010-05-29  1:54 ` [Qemu-devel] [PATCH 10/12] hw/omwp2.c : separate l4 interconnect module cmchao

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.