Send commitlog mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://lists.openmoko.org/mailman/listinfo/commitlog
or, via email, send a message with subject or body 'help' to
        [EMAIL PROTECTED]

You can reach the person managing the list at
        [EMAIL PROTECTED]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of commitlog digest..."
Today's Topics:

   1. r3750 - trunk/src/host/qemu-neo1973/hw ([EMAIL PROTECTED])
   2. r3751 - trunk/src/host/qemu-neo1973/hw ([EMAIL PROTECTED])
   3. r3752 - trunk/src/host/qemu-neo1973/hw ([EMAIL PROTECTED])
   4. r3753 - trunk/src/host/qemu-neo1973/hw ([EMAIL PROTECTED])
--- Begin Message ---
Author: andrew
Date: 2007-12-28 19:13:57 +0100 (Fri, 28 Dec 2007)
New Revision: 3750

Modified:
   trunk/src/host/qemu-neo1973/hw/neo1973.c
Log:
Preliminary LIS302DL accelerometers in the GTA02F.


Modified: trunk/src/host/qemu-neo1973/hw/neo1973.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/neo1973.c    2007-12-28 07:16:20 UTC (rev 
3749)
+++ trunk/src/host/qemu-neo1973/hw/neo1973.c    2007-12-28 18:13:57 UTC (rev 
3750)
@@ -87,6 +87,7 @@
     i2c_slave *pmu;
     i2c_slave *wm;
     i2c_slave *lcm;
+    i2c_slave *accel[2];
     CharDriverState *modem;
     CharDriverState *gps;
     QEMUTimer *modem_timer;
@@ -344,9 +345,207 @@
     return &s->i2c;
 }
 
+/* LIS302DL "piccolo" motion sensor/accelerometer */
+struct piccolo_s {
+    i2c_slave i2c;
+    int firstbyte;
+
+    qemu_irq intr[2];
+
+    uint8_t regs[0x40];
+    int reg;
+
+    QEMUTimer *sample;
+};
+
+void piccolo_reset(i2c_slave *i2c)
+{
+    struct piccolo_s *s = (struct piccolo_s *) i2c;
+
+    memset(s->regs, 0, sizeof(s->regs));
+    s->regs[0x0f] = 0x3b;      /* Who_Am_I */
+    s->regs[0x20] = 0x07;      /* Ctrl_Reg1 */
+}
+
+static void piccolo_sample_sched(struct piccolo_s *s)
+{
+    int rate = (s->regs[0x20] & (1 << 7)) ? 400 : 100; /* DR */
+
+    qemu_mod_timer(s->sample,
+                    qemu_get_clock(vm_clock) + ticks_per_sec / rate);
+}
+
+static void piccolo_sample_tick(void *opaque)
+{
+    struct piccolo_s *s = (struct piccolo_s *) opaque;
+
+    /* TODO */
+    piccolo_sample_sched(s);
+}
+
+static void piccolo_sample_update(struct piccolo_s *s)
+{
+    if (!(s->regs[0x20] & 7))                          /* Xen | Yen | Zen */
+        qemu_del_timer(s->sample);
+    else if (!qemu_timer_pending(s->sample))
+        piccolo_sample_sched(s);
+}
+
+static void piccolo_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct piccolo_s *s = (struct piccolo_s *) i2c;
+
+    if (event == I2C_START_SEND)
+        s->firstbyte = 1;
+}
+
+static int piccolo_rx(i2c_slave *i2c)
+{
+    struct piccolo_s *s = (struct piccolo_s *) i2c;
+    int reg = s->reg;
+
+    if (reg >= 0x80) {
+        reg -= 0x80;
+        s->reg ++;
+    } else
+        s->reg = -1;
+
+    switch (reg) {
+    case 0x00 ... 0x0e:
+    case 0x10 ... 0x1f:
+    case 0x2e ... 0x2f:
+    case 0x0f: /* Who_Am_I */
+    case 0x20: /* Ctrl_Reg1 */
+    case 0x21: /* Ctrl_Reg2 */
+    case 0x22: /* Ctrl_Reg3 */
+    case 0x23: /* HP_filter_reset */
+    case 0x27: /* Status_Reg */
+    case 0x29: /* OutX */
+    case 0x2b: /* OutY */
+    case 0x2d: /* OutZ */
+    case 0x30: /* FF_WU_CFG_1 */
+    case 0x31: /* FF_WU_SRC_1 */
+    case 0x32: /* FF_WU_THS_1 */
+    case 0x33: /* FF_WU_DURATION_1 */
+    case 0x34: /* FF_WU_CFG_2 */
+    case 0x35: /* FF_WU_SRC_2 */
+    case 0x36: /* FF_WU_THS_2 */
+    case 0x37: /* FF_WU_DURATION_2 */
+    case 0x38: /* CLICK_CFG */
+    case 0x39: /* CLICK_SRC */
+    case 0x3b: /* CLICK_THSY_X */
+    case 0x3c: /* CLICK_THSZ */
+    case 0x3d: /* CLICK_timelimit */
+    case 0x3e: /* CLICK_latency */
+    case 0x3f: /* CLICK_window */
+        break;
+    default:
+        fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);
+        return 0x00;
+    }
+
+    return s->regs[reg];
+}
+
+static int piccolo_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct piccolo_s *s = (struct piccolo_s *) i2c;
+    int reg = s->reg;
+
+    if (s->firstbyte) {
+        s->firstbyte = 0;
+        s->reg = data;
+        return 0;
+    }
+
+    if (reg >= 0x80) {
+        reg -= 0x80;
+        s->reg ++;
+    }
+
+    switch (reg) {
+    case 0x00 ... 0x0e:
+    case 0x10 ... 0x1f:
+    case 0x2e ... 0x2f:
+        fprintf(stderr, "%s: write to a \"do not modify\" register %02x\n",
+                        __FUNCTION__, s->reg);
+        fprintf(stderr, "%s: may cause permanent damage!\n", __FUNCTION__);
+        s->regs[reg] = data;
+        break;
+    case 0x20: /* Ctrl_Reg1 */
+        s->regs[reg] = data;
+        if (data & (3 << 3))
+            fprintf(stderr, "%s: Self-Test Enable attempt\n", __FUNCTION__);
+        piccolo_sample_update(s);
+        break;
+
+    case 0x21: /* Ctrl_Reg2 */
+    case 0x22: /* Ctrl_Reg3 */
+    case 0x30: /* FF_WU_CFG_1 */
+    case 0x32: /* FF_WU_THS_1 */
+    case 0x33: /* FF_WU_DURATION_1 */
+    case 0x34: /* FF_WU_CFG_2 */
+    case 0x36: /* FF_WU_THS_2 */
+    case 0x37: /* FF_WU_DURATION_2 */
+    case 0x38: /* CLICK_CFG */
+    case 0x39: /* CLICK_SRC */
+    case 0x3b: /* CLICK_THSY_X */
+    case 0x3c: /* CLICK_THSZ */
+    case 0x3d: /* CLICK_timelimit */
+    case 0x3e: /* CLICK_latency */
+    case 0x3f: /* CLICK_window */
+        /* TODO */
+        s->regs[reg] = data;
+        break;
+
+    default:
+        fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);
+        return 1;
+    }
+
+    return 0;
+}
+
+static void piccolo_save(QEMUFile *f, void *opaque)
+{
+    struct piccolo_s *s = (struct piccolo_s *) opaque;
+
+    qemu_put_buffer(f, s->regs, sizeof(s->regs));
+    i2c_slave_save(f, &s->i2c);
+}
+
+static int piccolo_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct piccolo_s *s = (struct piccolo_s *) opaque;
+
+    qemu_get_buffer(f, s->regs, sizeof(s->regs));
+    i2c_slave_load(f, &s->i2c);
+    return 0;
+}
+
+i2c_slave *lis302dl_init(i2c_bus *bus, qemu_irq int1, qemu_irq int2)
+{
+    struct piccolo_s *s = (struct piccolo_s *)
+            i2c_slave_init(bus, 0, sizeof(struct piccolo_s));
+    s->i2c.event = piccolo_event;
+    s->i2c.send = piccolo_tx;
+    s->i2c.recv = piccolo_rx;
+
+    s->intr[0] = int1;
+    s->intr[1] = int2;
+    s->sample = qemu_new_timer(vm_clock, piccolo_sample_tick, s);
+
+    piccolo_reset(&s->i2c);
+    register_savevm("lis302dl", 0, 0, piccolo_save, piccolo_load, s);
+
+    return &s->i2c;
+}
+
 /* I2C bus */
 #define NEO_PMU_ADDR   0x08
 #define NEO_WM_ADDR    0x1a
+#define NEO_ACCEL_ADDR0        0x1c
+#define NEO_ACCEL_ADDR1        0x1d
 #define NEO_AMP_ADDR   0x7c    /* ADR wired to low */
 
 static void neo_i2c_setup(struct neo_board_s *s)
@@ -370,6 +569,14 @@
     s->lcm = lm4857_init(bus);
     i2c_set_slave_address(s->lcm, NEO_AMP_ADDR);
 
+    /* Attach two LIS302DL slaves to the bus */
+    if (s->id == NEO1973_GTA02 || s->id == NEO1973_GTA02F) {
+        s->accel[0] = lis302dl_init(bus, 0, 0);        /* TODO: connect IRQs */
+        s->accel[1] = lis302dl_init(bus, 0, 0);        /* TODO: connect IRQs */
+        i2c_set_slave_address(s->accel[0], NEO_ACCEL_ADDR0);
+        i2c_set_slave_address(s->accel[1], NEO_ACCEL_ADDR1);
+    }
+
 #ifdef HAS_AUDIO
     audio = AUD_init();
     if (!audio)




--- End Message ---
--- Begin Message ---
Author: andrew
Date: 2007-12-28 21:50:54 +0100 (Fri, 28 Dec 2007)
New Revision: 3751

Modified:
   trunk/src/host/qemu-neo1973/hw/ar6000.c
Log:
AR6000 interrupt logic.  Fix reset.


Modified: trunk/src/host/qemu-neo1973/hw/ar6000.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ar6000.c     2007-12-28 18:13:57 UTC (rev 
3750)
+++ trunk/src/host/qemu-neo1973/hw/ar6000.c     2007-12-28 20:50:54 UTC (rev 
3751)
@@ -26,6 +26,7 @@
 
 #include "hw.h"
 #include "net.h"
+#include "qemu-timer.h"
 #include "sd.h"
 #include "pcmcia.h"
 
@@ -944,6 +945,7 @@
 struct ar6k_s {
     struct sdio_s sd;
     NICInfo *nd;
+
     struct {
         uint8_t host_int_stat;
         uint8_t cpu_int_stat;
@@ -956,9 +958,10 @@
         uint8_t cpu_int_stat_ena;
         uint8_t err_int_stat_ena;
         uint8_t cnt_int_stat_ena;
-        uint8_t cnt[8];
-        uint32_t cnt_dec[8];
+        uint8_t cnt[4];
+        uint32_t cnt_tx[4];
         uint8_t scratch[8];
+        uint8_t wlan_int;
 
         uint8_t mbox[0x800 * 4];
         int mbox_count[4];
@@ -966,22 +969,94 @@
     struct {
         int done;
     } bmi;
+
+    QEMUTimer *cnt_irq_update;
+
     uint8_t cis[0];
 };
 
+static inline void ar6k_hif_intr_update(struct ar6k_s *s)
+{
+    qemu_set_irq(s->sd.func_irq[0],
+                    !!(s->hif.host_int_stat & s->hif.int_stat_ena));
+}
+
+static void ar6k_hif_error_intr_update(struct ar6k_s *s)
+{
+    uint8_t orig = s->hif.host_int_stat;
+
+    if (s->hif.error_int_stat & s->hif.err_int_stat_ena)
+        s->hif.host_int_stat |= 1 << 7;                        /* STATUS_ERROR 
*/
+    else
+        s->hif.host_int_stat &= ~(1 << 7);             /* STATUS_ERROR */
+
+    if (orig != s->hif.host_int_stat)
+        ar6k_hif_intr_update(s);
+}
+
+static void ar6k_hif_cpu_intr_update(struct ar6k_s *s)
+{
+    uint8_t orig = s->hif.host_int_stat;
+
+    if (s->hif.cpu_int_stat & s->hif.cpu_int_stat_ena)
+        s->hif.host_int_stat |= 1 << 6;                        /* STATUS_CPU */
+    else
+        s->hif.host_int_stat &= ~(1 << 6);             /* STATUS_CPU */
+
+    if (orig != s->hif.host_int_stat)
+        ar6k_hif_intr_update(s);
+}
+
+static void ar6k_hif_counter_intr_update(struct ar6k_s *s)
+{
+    uint8_t orig = s->hif.host_int_stat;
+
+    if (s->hif.counter_int_stat & s->hif.cnt_int_stat_ena)
+        s->hif.host_int_stat |= 1 << 4;                        /* 
STATUS_COUNTER */
+    else
+        s->hif.host_int_stat &= ~(1 << 4);             /* STATUS_COUNTER */
+
+    if (orig != s->hif.host_int_stat)
+        ar6k_hif_intr_update(s);
+}
+
+static void ar6k_hif_counter_intr_sched(struct ar6k_s *s)
+{
+    qemu_mod_timer(s->cnt_irq_update, qemu_get_clock(vm_clock) +
+                    (ticks_per_sec >> 6));
+}
+
+static void ar6k_hif_cnt_irq_tick(void *opaque)
+{
+    struct ar6k_s *s = (void *) opaque;
+
+    ar6k_hif_counter_intr_update(s);
+}
+
 static void ar6k_bmi_reset(struct ar6k_s *s)
 {
     int i;
 
-    for (i = 0; i < 8; i ++) {
+    for (i = 0; i < 4; i ++) {
         s->hif.cnt[i] = 0x00;
-        s->hif.cnt_dec[i] = 0xff;
+        s->hif.cnt_tx[i] = 0xff;
+        s->hif.mbox_count[i] = 0;
     }
 
-    for (i = 0; i < 4; i ++)
-        s->hif.mbox_count[i] = 0;
+    s->bmi.done = 0;
 
-    s->bmi.done = 0;
+    s->hif.host_int_stat = 0x00;
+    s->hif.cpu_int_stat = 0x00;
+    s->hif.error_int_stat = 0x00;
+    s->hif.counter_int_stat = 0xf0;
+    s->hif.int_stat_ena = 0x00;
+    s->hif.cpu_int_stat_ena = 0x00;
+    s->hif.err_int_stat_ena = 0x00;
+    s->hif.cnt_int_stat_ena = 0x00;
+
+    ar6k_hif_cpu_intr_update(s);
+    ar6k_hif_error_intr_update(s);
+    ar6k_hif_counter_intr_update(s);
 }
 
 enum {
@@ -1044,10 +1119,27 @@
         return;
     }
 
-    s->hif.cnt_dec[4] = 0xff;
-    s->hif.cnt[4] = rlen;
+    s->hif.cnt[0] = rlen;
 }
 
+static void ar6k_hif_txcredit_reset(struct ar6k_s *s, int mbox)
+{
+    s->hif.cnt_tx[mbox] = 0;
+    if (!(s->hif.counter_int_stat & (1 << mbox))) {
+        s->hif.counter_int_stat |= 1 << mbox;
+        ar6k_hif_counter_intr_sched(s);
+    }
+}
+
+static void ar6k_hif_txcredit_grant(struct ar6k_s *s, int mbox)
+{
+    s->hif.cnt_tx[mbox] = 0xff;
+    if (!(s->hif.counter_int_stat & (1 << (mbox + 4)))) {
+        s->hif.counter_int_stat |= 1 << (mbox + 4);
+        ar6k_hif_counter_intr_sched(s);
+    }
+}
+
 #define AR6K_HOST_INT_STAT             0x400
 #define AR6K_CPU_INT_STAT              0x401
 #define AR6K_ERROR_INT_STAT            0x402
@@ -1063,7 +1155,8 @@
 #define AR6K_ERROR_STAT_ENABLE         0x41a
 #define AR6K_COUNTER_INT_STAT_ENABLE   0x41b
 #define AR6K_COUNT                     0x420
-#define AR6K_COUNT_DEC                 0x440
+#define AR6K_COUNT_RESET               0x440
+#define AR6K_COUNT_DEC                 0x450
 #define AR6K_SCRATCH                   0x460
 #define AR6K_FIFO_TIMEOUT              0x468
 #define AR6K_FIFO_TIMEOUT_ENABLE       0x469
@@ -1089,6 +1182,30 @@
     int mbox;
 
     switch (addr) {
+    case AR6K_HOST_INT_STAT:
+        if (s->hif.host_int_stat & value) {
+            s->hif.host_int_stat &= ~value;
+            ar6k_hif_intr_update(s);
+        }
+        break;
+    case AR6K_CPU_INT_STAT:
+        if (s->hif.cpu_int_stat & value) {
+            s->hif.cpu_int_stat &= ~value;
+            ar6k_hif_cpu_intr_update(s);
+        }
+        break;
+    case AR6K_ERROR_INT_STAT:
+        if (s->hif.error_int_stat & value) {
+            s->hif.error_int_stat &= ~value;
+            ar6k_hif_error_intr_update(s);
+        }
+        break;
+    case AR6K_COUNTER_INT_STAT:
+        if (s->hif.counter_int_stat & value) {
+            s->hif.counter_int_stat &= ~value;
+            ar6k_hif_counter_intr_update(s);
+        }
+        break;
     case AR6K_MBOX_FRAME:
         s->hif.mbox_frame = value;
         break;
@@ -1108,16 +1225,28 @@
         s->hif.rx_la[3] = value;
         break;
     case AR6K_INT_STAT_ENABLE:
-        s->hif.int_stat_ena = value;
+        if (s->hif.int_stat_ena ^ value) {
+            s->hif.int_stat_ena = value;
+            ar6k_hif_intr_update(s);
+        }
         break;
     case AR6K_CPU_INT_STAT_ENABLE:
-        s->hif.cpu_int_stat_ena = value;
+        if (s->hif.cpu_int_stat_ena ^ value) {
+            s->hif.cpu_int_stat_ena = value;
+            ar6k_hif_cpu_intr_update(s);
+        }
         break;
     case AR6K_ERROR_STAT_ENABLE:
-        s->hif.err_int_stat_ena = value;
+        if (s->hif.err_int_stat_ena ^ value) {
+            s->hif.err_int_stat_ena = value;
+            ar6k_hif_error_intr_update(s);
+        }
         break;
     case AR6K_COUNTER_INT_STAT_ENABLE:
-        s->hif.cnt_int_stat_ena = value;
+        if (s->hif.cnt_int_stat_ena ^ value) {
+            s->hif.cnt_int_stat_ena = value;
+            ar6k_hif_counter_intr_sched(s);
+        }
         break;
     case AR6K_SCRATCH ... (AR6K_SCRATCH + 7):
         s->hif.scratch[addr - AR6K_SCRATCH] = value;
@@ -1127,25 +1256,35 @@
     case AR6K_DISABLE_SLEEP:
     case AR6K_LOCAL_BUS_ENDIAN:
     case AR6K_LOCAL_BUS:
+        goto bad_reg;
+
     case AR6K_INT_WLAN:
+        s->hif.wlan_int = value;
+        if (value)
+            fprintf(stderr, "%s: WLAN interrupt\n", __FUNCTION__);
+        break;
+
     case AR6K_WINDOW_DATA:
     case AR6K_WRITE_ADDR:
     case AR6K_READ_ADDR:
     case AR6K_SPI_CONFIG:
         goto bad_reg;
+
     case AR6K_HIF_MBOX_BASE ... AR6K_HIF_MBOX_END:
         mbox = (addr - AR6K_HIF_MBOX_BASE) >> 11;
         s->hif.mbox[addr - AR6K_HIF_MBOX_BASE] = value;
         s->hif.mbox_count[mbox] ++;
-        /* XXX how do we know when a BMI command is executed?  */
-        if (mbox == 0 && !s->bmi.done) {
-            s->hif.cnt_dec[4] = 0x00;
-            s->hif.cnt[4] = 0x00;
-            if ((addr & 0x7ff) == 0x7ff) {
+        /* XXX how else do we know when a command is executed?  */
+        if ((addr & 0x7ff) == 0x7ff) {
+            ar6k_hif_txcredit_reset(s, mbox);
+            if (mbox == 0 && !s->bmi.done) {
                 ar6k_bmi_write(s, s->hif.mbox + (mbox << 11),
-                                s->hif.mbox_count[0]);
-                s->hif.mbox_count[mbox] = 0;
+                                s->hif.mbox_count[mbox]);
+            } else {
+                /* TODO */
             }
+            s->hif.mbox_count[mbox] = 0;
+            ar6k_hif_txcredit_grant(s, mbox);
         }
         break;
     default:
@@ -1157,6 +1296,8 @@
 
 static uint8_t ar6k_hif_read(struct ar6k_s *s, uint32_t addr)
 {
+    int mbox = 0;
+
     switch (addr) {
     case AR6K_HOST_INT_STAT:
         return s->hif.host_int_stat;
@@ -1166,8 +1307,10 @@
         return s->hif.error_int_stat;
     case AR6K_COUNTER_INT_STAT:
         return s->hif.counter_int_stat;
+
     case AR6K_MBOX_FRAME:
         return s->hif.mbox_frame;
+
     case AR6K_RX_LOOKAHEAD_VALID:
         return s->hif.rx_la_valid;
     case AR6K_RX_LOOKAHEAD0:
@@ -1178,6 +1321,7 @@
         return s->hif.rx_la[2];
     case AR6K_RX_LOOKAHEAD3:
         return s->hif.rx_la[3];
+
     case AR6K_INT_STAT_ENABLE:
         return s->hif.int_stat_ena;
     case AR6K_CPU_INT_STAT_ENABLE:
@@ -1186,25 +1330,41 @@
         return s->hif.err_int_stat_ena;
     case AR6K_COUNTER_INT_STAT_ENABLE:
         return s->hif.cnt_int_stat_ena;
-    case AR6K_COUNT ... (AR6K_COUNT + 0x7):
-        return s->hif.cnt[addr - AR6K_COUNT];
-    case AR6K_COUNT_DEC + 0x00:
-    case AR6K_COUNT_DEC + 0x04:
-    case AR6K_COUNT_DEC + 0x08:
-    case AR6K_COUNT_DEC + 0x0c:
-    case AR6K_COUNT_DEC + 0x10:
-    case AR6K_COUNT_DEC + 0x14:
-    case AR6K_COUNT_DEC + 0x18:
-    case AR6K_COUNT_DEC + 0x1c:
-        return s->hif.cnt_dec[(addr - AR6K_COUNT_DEC) >> 2];
+
+    case (AR6K_COUNT + 0x4) ... (AR6K_COUNT + 0x7):
+        /* XXX What's at (AR6K_COUNT + 0x0) ... (AR6K_COUNT + 0x3)? */
+        /* FIXME clear some interrupts etc */
+        return s->hif.cnt[addr - AR6K_COUNT - 4];
+
+    case AR6K_COUNT_RESET + 0xc: mbox ++;
+    case AR6K_COUNT_RESET + 0x8: mbox ++;
+    case AR6K_COUNT_RESET + 0x4: mbox ++;
+    case AR6K_COUNT_RESET + 0x0:
+        if (s->hif.counter_int_stat & (1 << mbox)) {
+            s->hif.counter_int_stat &= ~(1 << mbox);
+            ar6k_hif_counter_intr_update(s);
+        }
+        return s->hif.cnt_tx[mbox];
+
+    case AR6K_COUNT_DEC + 0xc: mbox ++;
+    case AR6K_COUNT_DEC + 0x8: mbox ++;
+    case AR6K_COUNT_DEC + 0x4: mbox ++;
+    case AR6K_COUNT_DEC + 0x0:
+        return s->hif.cnt_tx[mbox];
+
     case AR6K_SCRATCH ... (AR6K_SCRATCH + 7):
         return s->hif.scratch[addr - AR6K_SCRATCH];
+
     case AR6K_FIFO_TIMEOUT:
     case AR6K_FIFO_TIMEOUT_ENABLE:
     case AR6K_DISABLE_SLEEP:
     case AR6K_LOCAL_BUS_ENDIAN:
     case AR6K_LOCAL_BUS:
+        goto bad_reg;
+
     case AR6K_INT_WLAN:
+        return s->hif.wlan_int;
+
     case AR6K_WINDOW_DATA:
     case AR6K_WRITE_ADDR:
     case AR6K_READ_ADDR:
@@ -1326,6 +1486,7 @@
     struct sd_card_s *ret = sdio_init(&s->sd);
 
     s->nd = nd;
+    s->cnt_irq_update = qemu_new_timer(vm_clock, ar6k_hif_cnt_irq_tick, s);
     s->sd.reset = (void *) ar6k_reset;
     s->sd.fbr[0].stdfn = 0 | sdio_fn_none;
     s->sd.fbr[0].ext_stdfn = sdio_ext_fn_none;




--- End Message ---
--- Begin Message ---
Author: andrew
Date: 2007-12-29 03:11:33 +0100 (Sat, 29 Dec 2007)
New Revision: 3752

Modified:
   trunk/src/host/qemu-neo1973/hw/ar6000.c
Log:
Add Atheros WMI events framework - we get a correct MAC addr now.


Modified: trunk/src/host/qemu-neo1973/hw/ar6000.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ar6000.c     2007-12-28 20:50:54 UTC (rev 
3751)
+++ trunk/src/host/qemu-neo1973/hw/ar6000.c     2007-12-29 02:11:33 UTC (rev 
3752)
@@ -1,5 +1,5 @@
 /*
- * Atheros AR600X Wireless Ethernet SDIO cards.  Firmware 1.3.
+ * ROCm Atheros AR600X Wireless Ethernet SDIO cards.  Firmware 1.3.
  *
  * Copyright (c) 2007 OpenMoko, Inc.
  * Author: Andrzej Zaborowski <[EMAIL PROTECTED]>
@@ -942,6 +942,115 @@
     return &s->card;
 }
 
+/* WMI (Wireless Module Interface) */
+
+struct wmi_s {
+    NICInfo *nd;
+
+    void (*send)(void *opaque, const uint8_t *buffer, int len);
+    void *opaque;
+
+    QEMUTimer *alive;
+};
+
+#define WMI_MSG        __attribute__((packed))
+
+struct wmi_msg_s {
+    uint16_t id;
+    uint8_t data[128];
+} WMI_MSG;
+
+static void wmi_make_event(struct wmi_s *s, uint16_t id,
+               uint8_t *data, int len)
+{
+    struct wmi_msg_s msg;
+
+    msg.id = id;
+    memcpy(msg.data, data, len);
+
+    s->send(s->opaque, (void *) &msg, sizeof(msg.id) + len);
+}
+
+enum {
+    WMI_READY_EVENTID          = 0x1001,
+    WMI_CONNECT_EVENTID,
+    WMI_DISCONNECT_EVENTID,
+    WMI_BSSINFO_EVENTID,
+    WMI_CMDERROR_EVENTID,
+    WMI_REGDOMAIN_EVENTID,
+    WMI_PSTREAM_TIMEOUT_EVENTID,
+    WMI_NEIGHBOR_REPORT_EVENTID,
+    WMI_TKIP_MICERR_EVENTID,
+    WMI_SCAN_COMPLETE_EVENTID,
+    WMI_REPORT_STATISTICS_EVENTID,
+    WMI_RSSI_THRESHOLD_EVENTID,
+    WMI_ERROR_REPORT_EVENTID,
+    WMI_OPT_RX_FRAME_EVENTID,
+    WMI_REPORT_ROAM_TBL_EVENTID,
+    WMI_EXTENSION_EVENTID,
+    WMI_CAC_EVENTID,
+    WMI_SNR_THRESHOLD_EVENTID,
+    WMI_LQ_THRESHOLD_EVENTID,
+    WMI_TX_RETRY_ERR_EVENTID,
+    WMI_REPORT_ROAM_DATA_EVENTID,
+};
+
+enum {
+    WMI_11A_CAPABILITY = 1,
+    WMI_11G_CAPABILITY = 2,
+    WMI_11AG_CAPABILITY        = 3,
+};
+
+struct wmi_ready_event_s {
+    uint8_t macaddr[6];
+    uint8_t phy_capability;
+} WMI_MSG;
+
+static void wmi_ready_event(struct wmi_s *s)
+{
+    struct wmi_ready_event_s ev;
+
+    memcpy(ev.macaddr, s->nd->macaddr, 6);
+    ev.phy_capability = WMI_11AG_CAPABILITY;
+
+    /* TODO: request buf, fill in, submit */
+    wmi_make_event(s, WMI_READY_EVENTID, (void *) &ev, sizeof(ev));
+}
+
+/* The interface is alive */
+static void wmi_alive_tick(void *opaque)
+{
+    struct wmi_s *s = (void *) opaque;
+
+    qemu_free_timer(s->alive);
+
+    /* Send the initial event */
+    wmi_ready_event(s);
+}
+
+static __attribute__((malloc)) struct wmi_s *wmi_init(NICInfo *nd,
+                void *opaque,
+                void (*send)(void *opaque, const uint8_t *buffer, int len))
+{
+    struct wmi_s *s = qemu_mallocz(sizeof(*s));
+
+    s->nd = nd;
+    s->opaque = opaque;
+    s->send = send;
+
+    s->alive = qemu_new_timer(vm_clock, wmi_alive_tick, s);
+    qemu_mod_timer(s->alive, qemu_get_clock(vm_clock) + (ticks_per_sec << 1));
+
+    return s;
+}
+
+static void wmi_done(struct wmi_s *wmi)
+{
+    free(wmi);
+}
+
+/* Atheros AR600x */
+
 struct ar6k_s {
     struct sdio_s sd;
     NICInfo *nd;
@@ -953,7 +1062,7 @@
         uint8_t counter_int_stat;
         uint8_t mbox_frame;
         uint8_t rx_la_valid;
-        uint8_t rx_la[4];
+        uint32_t rx_la[4];
         uint8_t int_stat_ena;
         uint8_t cpu_int_stat_ena;
         uint8_t err_int_stat_ena;
@@ -970,6 +1079,8 @@
         int done;
     } bmi;
 
+    struct wmi_s *wmi;
+
     QEMUTimer *cnt_irq_update;
 
     uint8_t cis[0];
@@ -1033,10 +1144,17 @@
     ar6k_hif_counter_intr_update(s);
 }
 
+/* Atheros BMI (Bootloader Messaging Interface) */
+
 static void ar6k_bmi_reset(struct ar6k_s *s)
 {
     int i;
 
+    if (s->wmi) {
+        wmi_done(s->wmi);
+        s->wmi = 0;
+    }
+
     for (i = 0; i < 4; i ++) {
         s->hif.cnt[i] = 0x00;
         s->hif.cnt_tx[i] = 0xff;
@@ -1122,6 +1240,15 @@
     s->hif.cnt[0] = rlen;
 }
 
+/* Atheros HTC/HIF */
+
+enum {
+    WMI_CONTROL_MBOX = 0,
+    WMI_BEST_EFFORT_MBOX,
+    WMI_LOW_PRIORITY_MBOX,
+    WMI_HIGH_PRIORITY_MBOX,
+};
+
 static void ar6k_hif_txcredit_reset(struct ar6k_s *s, int mbox)
 {
     s->hif.cnt_tx[mbox] = 0;
@@ -1140,6 +1267,33 @@
     }
 }
 
+#define AR6K_HTC_HEADER_LEN    2
+
+static void ar6k_hif_wmi_event(void *opaque, const uint8_t *buffer, int len)
+{
+    struct ar6k_s *s = (void *) opaque;
+
+    int mbox = WMI_CONTROL_MBOX;
+    uint16_t *datap;
+
+    s->hif.rx_la[mbox] = len;
+    s->hif.rx_la_valid |= 1 << mbox;
+
+    datap = (void *) s->hif.mbox + ((mbox + 1) << 11) -
+            (len + AR6K_HTC_HEADER_LEN);
+
+    /* Prepend the HTC frame header */
+    cpu_to_le16wu(datap ++, len);
+
+    memcpy(datap, buffer, len);
+
+    if (!(s->hif.host_int_stat & (1 << mbox))) {       /* STATUS_MBOX_DATA */
+        s->hif.host_int_stat |= 1 << mbox;             /* STATUS_MBOX_DATA */
+
+        ar6k_hif_intr_update(s);
+    }
+}
+
 #define AR6K_HOST_INT_STAT             0x400
 #define AR6K_CPU_INT_STAT              0x401
 #define AR6K_ERROR_INT_STAT            0x402
@@ -1206,24 +1360,11 @@
             ar6k_hif_counter_intr_update(s);
         }
         break;
+
     case AR6K_MBOX_FRAME:
         s->hif.mbox_frame = value;
         break;
-    case AR6K_RX_LOOKAHEAD_VALID:
-        s->hif.rx_la_valid = value;
-        break;
-    case AR6K_RX_LOOKAHEAD0:
-        s->hif.rx_la[0] = value;
-        break;
-    case AR6K_RX_LOOKAHEAD1:
-        s->hif.rx_la[1] = value;
-        break;
-    case AR6K_RX_LOOKAHEAD2:
-        s->hif.rx_la[2] = value;
-        break;
-    case AR6K_RX_LOOKAHEAD3:
-        s->hif.rx_la[3] = value;
-        break;
+
     case AR6K_INT_STAT_ENABLE:
         if (s->hif.int_stat_ena ^ value) {
             s->hif.int_stat_ena = value;
@@ -1248,9 +1389,11 @@
             ar6k_hif_counter_intr_sched(s);
         }
         break;
+
     case AR6K_SCRATCH ... (AR6K_SCRATCH + 7):
         s->hif.scratch[addr - AR6K_SCRATCH] = value;
         break;
+
     case AR6K_FIFO_TIMEOUT:
     case AR6K_FIFO_TIMEOUT_ENABLE:
     case AR6K_DISABLE_SLEEP:
@@ -1260,8 +1403,10 @@
 
     case AR6K_INT_WLAN:
         s->hif.wlan_int = value;
-        if (value)
-            fprintf(stderr, "%s: WLAN interrupt\n", __FUNCTION__);
+        if (value && !s->wmi) {
+            /* Initialisation sequence is complete (?).  */
+            s->wmi = wmi_init(s->nd, s, ar6k_hif_wmi_event);
+        }
         break;
 
     case AR6K_WINDOW_DATA:
@@ -1313,15 +1458,18 @@
 
     case AR6K_RX_LOOKAHEAD_VALID:
         return s->hif.rx_la_valid;
-    case AR6K_RX_LOOKAHEAD0:
-        return s->hif.rx_la[0];
-    case AR6K_RX_LOOKAHEAD1:
-        return s->hif.rx_la[1];
-    case AR6K_RX_LOOKAHEAD2:
-        return s->hif.rx_la[2];
-    case AR6K_RX_LOOKAHEAD3:
-        return s->hif.rx_la[3];
+    case AR6K_RX_LOOKAHEAD3 ... (AR6K_RX_LOOKAHEAD3 + 3): mbox ++;
+    case AR6K_RX_LOOKAHEAD2 ... (AR6K_RX_LOOKAHEAD2 + 3): mbox ++;
+    case AR6K_RX_LOOKAHEAD1 ... (AR6K_RX_LOOKAHEAD1 + 3): mbox ++;
+    case AR6K_RX_LOOKAHEAD0 ... (AR6K_RX_LOOKAHEAD0 + 3):
+        /* XXX when is the bit reset? */
+        s->hif.rx_la_valid &= ~(1 << mbox);
+        /* XXX when is the bit reset? */
+        s->hif.host_int_stat &= ~(1 << mbox);          /* STATUS_MBOX_DATA */
 
+        ar6k_hif_intr_update(s);
+        return (s->hif.rx_la[mbox] >> ((addr & 3) << 3)) & 0xff;
+
     case AR6K_INT_STAT_ENABLE:
         return s->hif.int_stat_ena;
     case AR6K_CPU_INT_STAT_ENABLE:
@@ -1394,7 +1542,6 @@
 {
     struct ar6k_s *s = (void *) sd;
 
-    fprintf(stderr, "%s: writing %i bytes at %x\n", __FUNCTION__, len, addr);
     for (; len; len --, addr += sd->transfer.step)
         ar6k_hif_write(s, addr, *data ++);
 }
@@ -1404,7 +1551,6 @@
 {
     struct ar6k_s *s = (void *) sd;
 
-    fprintf(stderr, "%s: reading %i bytes at %x\n", __FUNCTION__, len, addr);
     for (; len; len --, addr += sd->transfer.step)
         *data ++ = ar6k_hif_read(s, addr);
 }




--- End Message ---
--- Begin Message ---
Author: andrew
Date: 2007-12-29 03:55:56 +0100 (Sat, 29 Dec 2007)
New Revision: 3753

Modified:
   trunk/src/host/qemu-neo1973/hw/ar6000.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c
Log:
Teach CMD52 to preserve concurrently executing transfers.
Fix commands without data in S3C24xx mmc/sd host.
Decrement tx-credits on COUNTER_DEC read.


Modified: trunk/src/host/qemu-neo1973/hw/ar6000.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ar6000.c     2007-12-29 02:11:33 UTC (rev 
3752)
+++ trunk/src/host/qemu-neo1973/hw/ar6000.c     2007-12-29 02:55:56 UTC (rev 
3753)
@@ -76,6 +76,7 @@
     int spi;
     int sdio_ok;
     int current_cmd;
+    int next_cmd;
     uint16_t blk_len[8];
     struct {
         uint8_t func;
@@ -370,10 +371,13 @@
 
     /* I/O mode commands (Class 9) */
     case 52:   /* CMD52:  IO_RW_DIRECT */
-        /* XXX In some situations this must preserve cmdNo and restore later */
         switch (sd->state) {
+        case sd_transfer_state:
+            /* A transfer is active on DAT lines, don't break it.  */
+            sd->next_cmd = sd->current_cmd;
+
+            /* Fall through.  */
         case sd_command_state:
-        case sd_transfer_state:
             fun = (req.arg >> 28) & 7;
             addr = (req.arg >> 9) & SDIO_ADDR_MASK;
             sd->transfer.data_offset = 0;
@@ -475,9 +479,10 @@
 
     sd->card_status &= ~(COM_CRC_ERROR | ILLEGAL_COMMAND);     /* B type */
 
+    sd->next_cmd = req->cmd;
     rtype = sdio_normal_command(sd, *req);
 
-    sd->current_cmd = req->cmd;
+    sd->current_cmd = sd->next_cmd;
 
     switch (rtype) {
     case sd_r1:
@@ -699,10 +704,11 @@
         return sd->cccr.bus;
 
     case 0x08: /* Card Capability */
-        /* XXX: set SDC (01) when CMD52 learns to preserve current_cmd */
-        /* XXX: need to addr ReadWait support too (RWC (04)) */
-        return 0x12 | sd->cccr.e4mi;   /* SMB | S4MI | E4MI | Full-Speed */
+        /* XXX: need to add ReadWait support too (RWC (04)) */
 
+        /* SDC | SMB | S4MI | E4MI | Full-Speed */
+        return 0x13 | sd->cccr.e4mi;
+
     case 0x09: /* Common CIS Pointer */
         return (SDIO_CIS_START >>  0) & 0xff;
     case 0x0a: /* Common CIS Pointer */
@@ -1022,6 +1028,8 @@
 {
     struct wmi_s *s = (void *) opaque;
 
+    /* TODO: reschedule if we're in the middle of a transfer or other
+     * activity.  Do the same for other timers we may need in WMI.  */
     qemu_free_timer(s->alive);
 
     /* Send the initial event */
@@ -1498,7 +1506,7 @@
     case AR6K_COUNT_DEC + 0x8: mbox ++;
     case AR6K_COUNT_DEC + 0x4: mbox ++;
     case AR6K_COUNT_DEC + 0x0:
-        return s->hif.cnt_tx[mbox];
+        return s->hif.cnt_tx[mbox] --;
 
     case AR6K_SCRATCH ... (AR6K_SCRATCH + 7):
         return s->hif.scratch[addr - AR6K_SCRATCH];

Modified: trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c       2007-12-29 02:11:33 UTC 
(rev 3752)
+++ trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c       2007-12-29 02:55:56 UTC 
(rev 3753)
@@ -170,6 +170,7 @@
     s->blklen_cnt = s->blklen;
     s->blknum_cnt = s->blknum;
 
+    s->data = 0;
     if (((s->dcontrol >> 12) & 3) == 1) {                      /* DatMode */
         if (s->dcontrol & (1 << 18))                           /* BACMD */
             s->data = 1;
@@ -179,6 +180,7 @@
     } else if (((s->dcontrol >> 12) & 3) == 3)                 /* DatMode */
         if (s->dcontrol & (1 << 20))                           /* RACMD */
             s->data = 1;
+    s->data &= s->ccontrol >> 11;                              /* WithData */
     return;
 
 timeout:




--- End Message ---
_______________________________________________
commitlog mailing list
[email protected]
http://lists.openmoko.org/mailman/listinfo/commitlog

Reply via email to