commit d951f6ff3fff1121e8b20e7655cb88b2601b61e6
Author: balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Mon Oct 29 01:50:05 2007 +0000

    Implement OMAP MicroWire controller.
    Fix GPIO interrupt number.
    Reorder a couple of variables.
    
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3477 c046a42c-6fe2-441c-8c8c-71466251a162

diff --git a/hw/omap.c b/hw/omap.c
index a2a18a4..cfb7d2b 100644
--- a/hw/omap.c
+++ b/hw/omap.c
@@ -3101,7 +3101,6 @@ 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 - s->base;
-    uint16_t ret;
 
     switch (offset) {
     case 0x00:	/* DATA_INPUT */
@@ -3238,6 +3237,175 @@ void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
     s->handler[line] = handler;
 }
 
+/* MicroWire Interface */
+struct omap_uwire_s {
+    target_phys_addr_t base;
+    qemu_irq txirq;
+    qemu_irq rxirq;
+    qemu_irq txdrq;
+
+    uint16_t txbuf;
+    uint16_t rxbuf;
+    uint16_t control;
+    uint16_t setup[5];
+
+    struct uwire_slave_s *chip[4];
+};
+
+static void omap_uwire_transfer_start(struct omap_uwire_s *s)
+{
+    int chipselect = (s->control >> 10) & 3;		/* INDEX */
+    struct uwire_slave_s *slave = s->chip[chipselect];
+
+    if ((s->control >> 5) & 0x1f) {			/* NB_BITS_WR */
+        if (s->control & (1 << 12))			/* CS_CMD */
+            if (slave && slave->send)
+                slave->send(slave->opaque,
+                                s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
+        s->control &= ~(1 << 14);			/* CSRB */
+        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+         * a DRQ.  When is the level IRQ supposed to be reset?  */
+    }
+
+    if ((s->control >> 0) & 0x1f) {			/* NB_BITS_RD */
+        if (s->control & (1 << 12))			/* CS_CMD */
+            if (slave && slave->receive)
+                s->rxbuf = slave->receive(slave->opaque);
+        s->control |= 1 << 15;				/* RDRB */
+        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+         * a DRQ.  When is the level IRQ supposed to be reset?  */
+    }
+}
+
+static uint32_t omap_uwire_read(void *opaque, target_phys_addr_t addr)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+    int offset = addr - s->base;
+
+    switch (offset) {
+    case 0x00:	/* RDR */
+        s->control &= ~(1 << 15);			/* RDRB */
+        return s->rxbuf;
+
+    case 0x04:	/* CSR */
+        return s->control;
+
+    case 0x08:	/* SR1 */
+        return s->setup[0];
+    case 0x0c:	/* SR2 */
+        return s->setup[1];
+    case 0x10:	/* SR3 */
+        return s->setup[2];
+    case 0x14:	/* SR4 */
+        return s->setup[3];
+    case 0x18:	/* SR5 */
+        return s->setup[4];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_uwire_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+    int offset = addr - s->base;
+
+    switch (offset) {
+    case 0x00:	/* TDR */
+        s->txbuf = value;				/* TD */
+        s->control |= 1 << 14;				/* CSRB */
+        if ((s->setup[4] & (1 << 2)) &&			/* AUTO_TX_EN */
+                        ((s->setup[4] & (1 << 3)) ||	/* CS_TOGGLE_TX_EN */
+                         (s->control & (1 << 12))))	/* CS_CMD */
+            omap_uwire_transfer_start(s);
+        break;
+
+    case 0x04:	/* CSR */
+        s->control = value & 0x1fff;
+        if (value & (1 << 13))				/* START */
+            omap_uwire_transfer_start(s);
+        break;
+
+    case 0x08:	/* SR1 */
+        s->setup[0] = value & 0x003f;
+        break;
+
+    case 0x0c:	/* SR2 */
+        s->setup[1] = value & 0x0fc0;
+        break;
+
+    case 0x10:	/* SR3 */
+        s->setup[2] = value & 0x0003;
+        break;
+
+    case 0x14:	/* SR4 */
+        s->setup[3] = value & 0x0001;
+        break;
+
+    case 0x18:	/* SR5 */
+        s->setup[4] = value & 0x000f;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static CPUReadMemoryFunc *omap_uwire_readfn[] = {
+    omap_badwidth_read16,
+    omap_uwire_read,
+    omap_badwidth_read16,
+};
+
+static CPUWriteMemoryFunc *omap_uwire_writefn[] = {
+    omap_badwidth_write16,
+    omap_uwire_write,
+    omap_badwidth_write16,
+};
+
+void omap_uwire_reset(struct omap_uwire_s *s)
+{
+    s->control= 0;
+    s->setup[0] = 0;
+    s->setup[1] = 0;
+    s->setup[2] = 0;
+    s->setup[3] = 0;
+    s->setup[4] = 0;
+}
+
+struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
+                qemu_irq *irq, qemu_irq dma, omap_clk clk)
+{
+    int iomemtype;
+    struct omap_uwire_s *s = (struct omap_uwire_s *)
+            qemu_mallocz(sizeof(struct omap_uwire_s));
+
+    s->base = base;
+    s->txirq = irq[0];
+    s->rxirq = irq[1];
+    s->txdrq = dma;
+    omap_uwire_reset(s);
+
+    iomemtype = cpu_register_io_memory(0, omap_uwire_readfn,
+                    omap_uwire_writefn, s);
+    cpu_register_physical_memory(s->base, 0x800, iomemtype);
+
+    return s;
+}
+
+void omap_uwire_attach(struct omap_uwire_s *s,
+                struct uwire_slave_s *slave, int chipselect)
+{
+    if (chipselect < 0 || chipselect > 3)
+        cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
+                        chipselect);
+
+    s->chip[chipselect] = slave;
+}
+
 /* General chip reset */
 static void omap_mpu_reset(void *opaque)
 {
@@ -3261,12 +3429,13 @@ static void omap_mpu_reset(void *opaque)
     omap_dpll_reset(&mpu->dpll[0]);
     omap_dpll_reset(&mpu->dpll[1]);
     omap_dpll_reset(&mpu->dpll[2]);
-    omap_uart_reset(mpu->uart1);
-    omap_uart_reset(mpu->uart2);
-    omap_uart_reset(mpu->uart3);
+    omap_uart_reset(mpu->uart[0]);
+    omap_uart_reset(mpu->uart[1]);
+    omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
     omap_mpuio_reset(mpu->mpuio);
     omap_gpio_reset(mpu->gpio);
+    omap_uwire_reset(mpu->microwire);
     cpu_reset(mpu->env);
 }
 
@@ -3361,13 +3530,13 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
 
     omap_tcmi_init(0xfffecc00, s);
 
-    s->uart1 = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
+    s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
                     omap_findclk(s, "uart1_ck"),
                     serial_hds[0]);
-    s->uart2 = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
+    s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
                     omap_findclk(s, "uart2_ck"),
                     serial_hds[0] ? serial_hds[1] : 0);
-    s->uart3 = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
+    s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
                     omap_findclk(s, "uart3_ck"),
                     serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
 
@@ -3382,9 +3551,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
                     s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
                     s->wakeup, omap_findclk(s, "clk32-kHz"));
 
-    s->gpio = omap_gpio_init(0xfffcf000, s->irq[1][OMAP_INT_KEYBOARD],
+    s->gpio = omap_gpio_init(0xfffcf000, s->irq[0][OMAP_INT_GPIO_BANK1],
                     omap_findclk(s, "mpuper_ck"));
 
+    s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
+                    s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
+
     qemu_register_reset(omap_mpu_reset, s);
 
     return s;
diff --git a/hw/omap.h b/hw/omap.h
index caaca9e..e19f8ac 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -464,6 +464,17 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
 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);
 
+struct uwire_slave_s {
+    uint16_t (*receive)(void *opaque);
+    void (*send)(void *opaque, uint16_t data);
+    void *opaque;
+};
+struct omap_uwire_s;
+struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
+                qemu_irq *irq, qemu_irq dma, omap_clk clk);
+void omap_uwire_attach(struct omap_uwire_s *s,
+                struct uwire_slave_s *slave, int chipselect);
+
 /* omap_lcdc.c */
 struct omap_lcd_panel_s;
 void omap_lcdc_reset(struct omap_lcd_panel_s *s);
@@ -510,16 +521,19 @@ struct omap_mpu_state_s {
     unsigned long sram_size;
 
     /* MPUI-TIPB peripherals */
-    struct omap_uart_s *uart3;
+    struct omap_uart_s *uart[3];
+
+    struct omap_gpio_s *gpio;
 
     /* MPU public TIPB peripherals */
     struct omap_32khz_timer_s *os_timer;
 
-    struct omap_uart_s *uart1;
-    struct omap_uart_s *uart2;
-
     struct omap_mmc_s *mmc;
 
+    struct omap_mpuio_s *mpuio;
+
+    struct omap_uwire_s *microwire;
+
     /* MPU private TIPB peripherals */
     struct omap_intr_handler_s *ih[2];
 
@@ -578,9 +592,6 @@ struct omap_mpu_state_s {
         uint16_t dsp_idlect2;
         uint16_t dsp_rstct2;
     } clkm;
-
-    struct omap_mpuio_s *mpuio;
-    struct omap_gpio_s *gpio;
 } *omap310_mpu_init(unsigned long sdram_size,
                 DisplayState *ds, const char *core);
 
diff --git a/hw/palm.c b/hw/palm.c
index 1ee05b8..7945745 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -37,7 +37,8 @@ static uint32_t static_readw(void *opaque, target_phys_addr_t offset) {
 }
 
 static void static_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value) {
+                uint32_t value)
+{
 #ifdef SPY
     printf("%s: value %08lx written at " PA_FMT "\n",
                     __FUNCTION__, value, offset);
