r3745 - trunk/src/host/qemu-neo1973/hw
andrew at sita.openmoko.org
andrew at sita.openmoko.org
Thu Dec 27 21:44:03 CET 2007
Author: andrew
Date: 2007-12-27 21:44:01 +0100 (Thu, 27 Dec 2007)
New Revision: 3745
Modified:
trunk/src/host/qemu-neo1973/hw/ar6000.c
Log:
Fix CMD53 opcode bit no.
Implement basic HIF registers.
Implement basic BMI commands.
Modified: trunk/src/host/qemu-neo1973/hw/ar6000.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ar6000.c 2007-12-27 19:51:02 UTC (rev 3744)
+++ trunk/src/host/qemu-neo1973/hw/ar6000.c 2007-12-27 20:44:01 UTC (rev 3745)
@@ -414,7 +414,7 @@
}
sd->transfer.dir = (req.arg >> 31) & 1; /* R/W */
- sd->transfer.step = (req.arg >> 27) & 1; /* OPCode */
+ sd->transfer.step = (req.arg >> 26) & 1; /* OPCode */
sd->transfer.func = fun;
sd->transfer.data_start = addr;
sd->transfer.data_offset = 0;
@@ -944,9 +944,311 @@
struct ar6k_s {
struct sdio_s sd;
NICInfo *nd;
+ struct {
+ uint8_t host_int_stat;
+ uint8_t cpu_int_stat;
+ uint8_t error_int_stat;
+ uint8_t counter_int_stat;
+ uint8_t mbox_frame;
+ uint8_t rx_la_valid;
+ uint8_t rx_la[4];
+ uint8_t int_stat_ena;
+ 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 scratch[8];
+
+ uint8_t mbox[0x800 * 4];
+ int mbox_count[4];
+ } hif;
+ struct {
+ int done;
+ } bmi;
uint8_t cis[0];
};
+static void ar6k_bmi_reset(struct ar6k_s *s)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ s->hif.cnt[i] = 0x00;
+ s->hif.cnt_dec[i] = 0xff;
+ }
+
+ for (i = 0; i < 4; i ++)
+ s->hif.mbox_count[i] = 0;
+
+ s->bmi.done = 0;
+}
+
+enum {
+ bmi_no_command = 0,
+ bmi_done, /* Host is done using BMI */
+ bmi_read_memory, /* Host reads AR6K memory */
+ bmi_write_memory, /* Host writes AR6K memory */
+ bmi_execute, /* Causes AR6K to execute code */
+ bmi_set_app_start, /* Set Target application starting address */
+ bmi_read_soc_register, /* Read a 32-bit Target SOC register */
+ bmi_Write_soc_register, /* Write a 32-bit Target SOC register */
+ bmi_get_target_id, /* Fetch the 4-byte Target information */
+ bmi_rompatch_install, /* Install a ROM Patch */
+ bmi_rompatch_uninstall, /* Uninstall a previously-installed ROM Patch */
+ bmi_rompatch_activate, /* Activate a list of installed ROM Patches */
+ bmi_rompatch_deactivate, /* Deactivate a list of active ROM Patches */
+};
+
+#define BMI_TARGET_VERSION_SENTINAL 0xffffffff
+#define BMI_TARGET_VERSION_ID 0x11000044
+#define BMI_TARGET_TYPE_AR6001 1
+#define BMI_TARGET_TYPE_AR6002 2
+
+static void ar6k_bmi_write(struct ar6k_s *s, uint8_t *data, int len)
+{
+ uint32_t cmd;
+ uint32_t *cmdp, *resp;
+ int rlen = 0;
+
+ if (len < 4) {
+ fprintf(stderr, "%s: short command (%ib)\n", __FUNCTION__, len);
+ return;
+ }
+
+ cmdp = (void *) data + 0x800 - len;
+ cmd = le32_to_cpup(cmdp ++);
+
+ switch (cmd) {
+ case bmi_no_command:
+ break;
+ case bmi_done:
+ s->bmi.done = 1;
+ break;
+ case bmi_get_target_id:
+#ifndef NEW_FIRMWARE
+ rlen = 4;
+ resp = (void *) data + 0x800 - rlen;
+ cpu_to_le32wu(resp, BMI_TARGET_VERSION_ID);
+#else
+ rlen = 16;
+ resp = (void *) data + 0x800 - rlen;
+ cpu_to_le32wu(resp ++, BMI_TARGET_VERSION_SENTINAL);
+ cpu_to_le32wu(resp ++, 0x0000000c); /* target_info_byte_count */
+ cpu_to_le32wu(resp ++, BMI_TARGET_VERSION_ID); /* target_ver */
+ cpu_to_le32wu(resp ++, BMI_TARGET_TYPE_AR6001); /* target_type */
+#endif
+ break;
+ default:
+ fprintf(stderr, "%s: bad command (%i)\n", __FUNCTION__, cmd);
+ return;
+ }
+
+ s->hif.cnt_dec[4] = 0xff;
+ s->hif.cnt[4] = rlen;
+}
+
+#define AR6K_HOST_INT_STAT 0x400
+#define AR6K_CPU_INT_STAT 0x401
+#define AR6K_ERROR_INT_STAT 0x402
+#define AR6K_COUNTER_INT_STAT 0x403
+#define AR6K_MBOX_FRAME 0x404
+#define AR6K_RX_LOOKAHEAD_VALID 0x405
+#define AR6K_RX_LOOKAHEAD0 0x408
+#define AR6K_RX_LOOKAHEAD1 0x40c
+#define AR6K_RX_LOOKAHEAD2 0x410
+#define AR6K_RX_LOOKAHEAD3 0x414
+#define AR6K_INT_STAT_ENABLE 0x418
+#define AR6K_CPU_INT_STAT_ENABLE 0x419
+#define AR6K_ERROR_STAT_ENABLE 0x41a
+#define AR6K_COUNTER_INT_STAT_ENABLE 0x41b
+#define AR6K_COUNT 0x420
+#define AR6K_COUNT_DEC 0x440
+#define AR6K_SCRATCH 0x460
+#define AR6K_FIFO_TIMEOUT 0x468
+#define AR6K_FIFO_TIMEOUT_ENABLE 0x469
+#define AR6K_DISABLE_SLEEP 0x46a
+#define AR6K_LOCAL_BUS_ENDIAN 0x46e
+#define AR6K_LOCAL_BUS 0x470
+#define AR6K_INT_WLAN 0x472
+#define AR6K_WINDOW_DATA 0x474
+#define AR6K_WRITE_ADDR 0x478
+#define AR6K_READ_ADDR 0x47c
+#define AR6K_SPI_CONFIG 0x480
+#define AR6K_SPI_STATUS 0x481
+#define AR6K_CIS_WINDOW 0x600
+#define AR6K_HIF_MBOX_BASE 0x800
+#define AR6K_HIF_MBOX0_BASE 0x800
+#define AR6K_HIF_MBOX1_BASE 0x1000
+#define AR6K_HIF_MBOX2_BASE 0x1800
+#define AR6K_HIF_MBOX3_BASE 0x2000
+#define AR6K_HIF_MBOX_END 0x27ff
+
+static void ar6k_hif_write(struct ar6k_s *s, uint32_t addr, uint8_t value)
+{
+ int mbox;
+
+ switch (addr) {
+ 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:
+ s->hif.int_stat_ena = value;
+ break;
+ case AR6K_CPU_INT_STAT_ENABLE:
+ s->hif.cpu_int_stat_ena = value;
+ break;
+ case AR6K_ERROR_STAT_ENABLE:
+ s->hif.err_int_stat_ena = value;
+ break;
+ case AR6K_COUNTER_INT_STAT_ENABLE:
+ s->hif.cnt_int_stat_ena = value;
+ 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:
+ case AR6K_LOCAL_BUS_ENDIAN:
+ case AR6K_LOCAL_BUS:
+ case AR6K_INT_WLAN:
+ 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) {
+ ar6k_bmi_write(s, s->hif.mbox + (mbox << 11),
+ s->hif.mbox_count[0]);
+ s->hif.mbox_count[mbox] = 0;
+ }
+ }
+ break;
+ default:
+ bad_reg:
+ printf("%s: unknown register %02x\n", __FUNCTION__, addr);
+ break;
+ }
+}
+
+static uint8_t ar6k_hif_read(struct ar6k_s *s, uint32_t addr)
+{
+ switch (addr) {
+ case AR6K_HOST_INT_STAT:
+ return s->hif.host_int_stat;
+ case AR6K_CPU_INT_STAT:
+ return s->hif.cpu_int_stat;
+ case AR6K_ERROR_INT_STAT:
+ 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:
+ 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_INT_STAT_ENABLE:
+ return s->hif.int_stat_ena;
+ case AR6K_CPU_INT_STAT_ENABLE:
+ return s->hif.cpu_int_stat_ena;
+ case AR6K_ERROR_STAT_ENABLE:
+ 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_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:
+ case AR6K_INT_WLAN:
+ case AR6K_WINDOW_DATA:
+ case AR6K_WRITE_ADDR:
+ case AR6K_READ_ADDR:
+ case AR6K_SPI_CONFIG:
+ case AR6K_SPI_STATUS:
+ goto bad_reg;
+
+ case AR6K_CIS_WINDOW ... (AR6K_CIS_WINDOW + 0x1ff):
+ if (addr >= AR6K_CIS_WINDOW + s->sd.cislen)
+ goto bad_reg;
+
+ return s->sd.cis[addr - AR6K_CIS_WINDOW];
+
+ case AR6K_HIF_MBOX_BASE ... AR6K_HIF_MBOX_END:
+ return s->hif.mbox[addr - AR6K_HIF_MBOX_BASE];
+ default:
+ bad_reg:
+ printf("%s: unknown register %02x\n", __FUNCTION__, addr);
+ break;
+ }
+
+ return 0;
+}
+
+static void ar6k_fn1_write(struct sdio_s *sd,
+ uint32_t addr, uint8_t *data, int len)
+{
+ 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 ++);
+}
+
+static void ar6k_fn1_read(struct sdio_s *sd,
+ uint32_t addr, uint8_t *data, int len)
+{
+ 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);
+}
+
static void ar6k_set_ioocr(struct sdio_s *sd)
{
/* 2.9 - 3.6 V, No memory present, Two functions only */
@@ -956,6 +1258,7 @@
static void ar6k_reset(struct ar6k_s *s)
{
ar6k_set_ioocr(&s->sd);
+ ar6k_bmi_reset(s);
}
/* TODO: dump real values from an Atheros AR6001 - need hw access! */
@@ -1036,6 +1339,9 @@
memcpy(s->cis + s->sd.fbr[0].cis_offset,
ar6k_fn1_cis, sizeof(ar6k_fn1_cis));
+ s->sd.write[1] = ar6k_fn1_write;
+ s->sd.read[1] = ar6k_fn1_read;
+
ar6k_reset(s);
return ret;
More information about the commitlog
mailing list