summaryrefslogtreecommitdiff
path: root/code/fe310/eos/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/fe310/eos/spi.c')
-rw-r--r--code/fe310/eos/spi.c231
1 files changed, 89 insertions, 142 deletions
diff --git a/code/fe310/eos/spi.c b/code/fe310/eos/spi.c
index ae12f40..725db13 100644
--- a/code/fe310/eos/spi.c
+++ b/code/fe310/eos/spi.c
@@ -23,14 +23,14 @@ static uint8_t spi_dev_cs_pin;
static uint8_t spi_state_flags;
static unsigned char spi_in_xchg;
-uint32_t _eos_spi_state_len = 0;
-uint32_t _eos_spi_state_idx_tx = 0;
-uint32_t _eos_spi_state_idx_rx = 0;
-unsigned char *_eos_spi_state_buf = NULL;
+static uint32_t spi_state_len = 0;
+static uint32_t spi_state_idx_tx = 0;
+static uint32_t spi_state_idx_rx = 0;
+static unsigned char *spi_state_buf = NULL;
-static eos_evt_fptr_t evt_handler[EOS_SPI_MAX_DEV];
+static eos_evt_handler_t evt_handler[EOS_SPI_MAX_DEV];
-static void spi_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void spi_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
unsigned char idx = (type & ~EOS_EVT_MASK) - 1;
if (idx < EOS_SPI_MAX_DEV) {
evt_handler[idx](type, buffer, len);
@@ -39,39 +39,15 @@ static void spi_handler_evt(unsigned char type, unsigned char *buffer, uint16_t
}
}
-static void spi_flush(void) {
- SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(1);
- while (!(SPI1_REG(SPI_REG_IP) & SPI_IP_TXWM));
- while (!(SPI1_REG(SPI_REG_RXFIFO) & SPI_RXFIFO_EMPTY));
-}
-
-static void spi_xchg_wait(void) {
- volatile uint8_t done = 0;
-
- while (!done) {
- clear_csr(mstatus, MSTATUS_MIE);
- done = !(spi_state_flags & SPI_FLAG_XCHG);
- if (!done) asm volatile ("wfi");
- set_csr(mstatus, MSTATUS_MIE);
- }
- spi_in_xchg = 0;
-}
-
void eos_spi_init(void) {
int i;
for (i=0; i<EOS_SPI_MAX_DEV; i++) {
evt_handler[i] = eos_evtq_bad_handler;
}
- eos_evtq_set_handler(EOS_EVT_SPI, spi_handler_evt, 0);
+ eos_evtq_set_handler(EOS_EVT_SPI, spi_handle_evt);
eos_intr_set(INT_SPI1_BASE, IRQ_PRIORITY_SPI_XCHG, NULL);
- GPIO_REG(GPIO_INPUT_EN) &= ~(1 << SPI_CS_PIN_CAM);
- GPIO_REG(GPIO_OUTPUT_EN) |= (1 << SPI_CS_PIN_CAM);
- GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << SPI_CS_PIN_CAM);
- GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << SPI_CS_PIN_CAM);
- GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << SPI_CS_PIN_CAM);
-
SPI1_REG(SPI_REG_SCKMODE) = SPI_MODE0;
SPI1_REG(SPI_REG_FMT) = SPI_FMT_PROTO(SPI_PROTO_S) |
SPI_FMT_ENDIAN(SPI_ENDIAN_MSB) |
@@ -85,102 +61,88 @@ void eos_spi_init(void) {
// SPI1_REG(SPI_REG_CSDEF) = 0xFFFF;
}
-void eos_spi_dev_start(unsigned char dev) {
- eos_net_stop();
+void eos_spi_start(unsigned char dev, uint32_t div, uint32_t csid, uint8_t pin) {
spi_dev = dev;
- spi_state_flags = SPI_FLAG_CS;
- switch (dev) {
- case EOS_SPI_DEV_DISP:
- SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_DISP;
- SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
- SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_DISP;
- break;
- case EOS_SPI_DEV_CARD:
- SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_CARD;
- SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
- SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_CARD;
- break;
- case EOS_SPI_DEV_CAM:
- spi_dev_cs_pin = SPI_CS_PIN_CAM;
- SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_CAM;
- SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_OFF;
- SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_NONE;
- break;
+ spi_state_flags = 0;
+ SPI1_REG(SPI_REG_SCKDIV) = div;
+ SPI1_REG(SPI_REG_CSID) = csid;
+ if (csid != SPI_CSID_NONE) {
+ SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
+ } else {
+ SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_OFF;
+ spi_dev_cs_pin = pin;
}
- eos_intr_set_handler(INT_SPI1_BASE, eos_spi_xchg_handler);
+ eos_intr_set_handler(INT_SPI1_BASE, eos_spi_handle_xchg);
}
-void eos_spi_dev_stop(void) {
- if (spi_in_xchg) spi_xchg_wait();
- if (spi_state_flags & EOS_SPI_FLAG_TX) spi_flush();
- if (!(spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_clear();
+void eos_spi_stop(void) {
+ eos_spi_flush();
+ spi_dev = 0;
+}
- spi_dev = EOS_SPI_DEV_NET;
- eos_net_start();
+void eos_spi_set_handler(unsigned char dev, eos_evt_handler_t handler) {
+ if (handler == NULL) handler = eos_evtq_bad_handler;
+ if (dev && (dev <= EOS_NET_MAX_MTYPE)) evt_handler[dev - 1] = handler;
}
-void eos_spi_set_handler(unsigned char dev, eos_evt_fptr_t handler, uint8_t flags) {
- if (dev && (dev <= EOS_SPI_MAX_DEV)) {
- dev--;
- } else {
- return;
- }
- evt_handler[dev] = handler;
+void _eos_spi_xchg_init(unsigned char *buffer, uint16_t len, uint8_t flags) {
+ spi_state_flags &= 0xF0;
+ spi_state_flags |= (SPI_FLAG_XCHG | flags);
+ spi_state_buf = buffer;
+ spi_state_len = len;
+ spi_state_idx_tx = 0;
+ spi_state_idx_rx = 0;
+}
+
+static void spi_xchg_wait(void) {
+ volatile uint8_t done = 0;
- eos_evtq_set_hflags(EOS_EVT_SPI | dev + 1, flags);
+ while (!done) {
+ clear_csr(mstatus, MSTATUS_MIE);
+ done = !(spi_state_flags & SPI_FLAG_XCHG);
+ if (!done) asm volatile ("wfi");
+ set_csr(mstatus, MSTATUS_MIE);
+ }
+ spi_in_xchg = 0;
}
void eos_spi_xchg(unsigned char *buffer, uint16_t len, uint8_t flags) {
if (spi_in_xchg) spi_xchg_wait();
- if (!(flags & EOS_SPI_FLAG_TX) && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
spi_in_xchg=1;
- spi_state_flags &= 0xF0;
- spi_state_flags |= (SPI_FLAG_XCHG | flags);
- _eos_spi_state_buf = buffer;
- _eos_spi_state_len = len;
- _eos_spi_state_idx_tx = 0;
- _eos_spi_state_idx_rx = 0;
+ _eos_spi_xchg_init(buffer, len, flags);
- if (spi_state_flags & SPI_FLAG_CS) eos_spi_cs_set();
+ eos_spi_cs_set();
SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(SPI_SIZE_WM);
SPI1_REG(SPI_REG_IE) = SPI_IP_TXWM;
}
-static void spi_xchg_done(void) {
- SPI1_REG(SPI_REG_IE) = 0x0;
- if (spi_dev == EOS_SPI_DEV_NET) {
- eos_net_xchg_done();
- } else {
- spi_state_flags &= ~SPI_FLAG_XCHG;
- if (!(spi_state_flags & (EOS_SPI_FLAG_MORE | SPI_FLAG_CS))) eos_spi_cs_clear();
- eos_evtq_push_isr(EOS_EVT_SPI | spi_dev, _eos_spi_state_buf, _eos_spi_state_len);
- }
-}
-
-void eos_spi_xchg_handler(void) {
+void eos_spi_handle_xchg(void) {
int i;
- uint16_t sz_chunk = MIN(_eos_spi_state_len - _eos_spi_state_idx_tx, SPI_SIZE_CHUNK);
+ uint16_t sz_chunk = MIN(spi_state_len - spi_state_idx_tx, SPI_SIZE_CHUNK);
for (i=0; i<sz_chunk; i++) {
volatile uint32_t x = SPI1_REG(SPI_REG_TXFIFO);
if (x & SPI_TXFIFO_FULL) break;
- SPI1_REG(SPI_REG_TXFIFO) = _eos_spi_state_buf[_eos_spi_state_idx_tx+i];
+ SPI1_REG(SPI_REG_TXFIFO) = spi_state_buf[spi_state_idx_tx+i];
}
- _eos_spi_state_idx_tx += i;
+ spi_state_idx_tx += i;
- for (i=0; i<_eos_spi_state_idx_tx - _eos_spi_state_idx_rx; i++) {
+ for (i=0; i<spi_state_idx_tx - spi_state_idx_rx; i++) {
volatile uint32_t x = SPI1_REG(SPI_REG_RXFIFO);
if (x & SPI_RXFIFO_EMPTY) break;
- _eos_spi_state_buf[_eos_spi_state_idx_rx+i] = x & 0xFF;
+ spi_state_buf[spi_state_idx_rx+i] = x & 0xFF;
}
- _eos_spi_state_idx_rx += i;
-
- if (_eos_spi_state_idx_tx == _eos_spi_state_len) {
- if ((_eos_spi_state_idx_rx == _eos_spi_state_len) || (spi_state_flags & EOS_SPI_FLAG_TX)) {
- spi_xchg_done();
+ spi_state_idx_rx += i;
+
+ if (spi_state_idx_tx == spi_state_len) {
+ if ((spi_state_idx_rx == spi_state_len) || (spi_state_flags & EOS_SPI_FLAG_TX)) {
+ spi_state_flags &= ~SPI_FLAG_XCHG;
+ if (!(spi_state_flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
+ SPI1_REG(SPI_REG_IE) = 0x0;
+ if (spi_dev) eos_evtq_push_isr(EOS_EVT_SPI | spi_dev, spi_state_buf, spi_state_len);
} else {
- SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(MIN(_eos_spi_state_len - _eos_spi_state_idx_rx - 1, SPI_SIZE_WM - 1));
+ SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(MIN(spi_state_len - spi_state_idx_rx - 1, SPI_SIZE_WM - 1));
SPI1_REG(SPI_REG_IE) = SPI_IP_RXWM;
}
}
@@ -193,7 +155,6 @@ void eos_spi_cs_set(void) {
} else {
SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD;
}
- spi_state_flags &= ~SPI_FLAG_CS;
}
void eos_spi_cs_clear(void) {
@@ -203,29 +164,22 @@ void eos_spi_cs_clear(void) {
} else {
SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
}
- spi_state_flags |= SPI_FLAG_CS;
}
uint8_t eos_spi_xchg8(uint8_t data, uint8_t flags) {
volatile uint32_t x = 0;
uint8_t rx = !(flags & EOS_SPI_FLAG_TX);
- if (spi_in_xchg) spi_xchg_wait();
- if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
-
spi_state_flags &= 0xF0;
spi_state_flags |= flags;
- if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set();
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = data;
if (rx) {
while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY);
}
- if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
-
return x & 0xFF;
}
@@ -234,22 +188,18 @@ uint16_t eos_spi_xchg16(uint16_t data, uint8_t flags) {
uint8_t rx = !(flags & EOS_SPI_FLAG_TX);
uint16_t r = 0;
- if (spi_in_xchg) spi_xchg_wait();
- if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
-
spi_state_flags &= 0xF0;
spi_state_flags |= flags;
- if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set();
if (flags & EOS_SPI_FLAG_BSWAP) {
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF);
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF00) >> 8;
} else {
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF00) >> 8;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF);
}
@@ -267,8 +217,6 @@ uint16_t eos_spi_xchg16(uint16_t data, uint8_t flags) {
}
}
- if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
-
return r;
}
@@ -277,26 +225,22 @@ uint32_t eos_spi_xchg24(uint32_t data, uint8_t flags) {
uint8_t rx = !(flags & EOS_SPI_FLAG_TX);
uint32_t r = 0;
- if (spi_in_xchg) spi_xchg_wait();
- if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
-
spi_state_flags &= 0xF0;
spi_state_flags |= flags;
- if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set();
if (flags & EOS_SPI_FLAG_BSWAP) {
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF);
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16;
} else {
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF);
}
@@ -318,8 +262,6 @@ uint32_t eos_spi_xchg24(uint32_t data, uint8_t flags) {
}
}
- if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
-
return r;
}
@@ -328,30 +270,26 @@ uint32_t eos_spi_xchg32(uint32_t data, uint8_t flags) {
uint8_t rx = !(flags & EOS_SPI_FLAG_TX);
uint32_t r = 0;
- if (spi_in_xchg) spi_xchg_wait();
- if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
-
spi_state_flags &= 0xF0;
spi_state_flags |= flags;
- if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set();
if (flags & EOS_SPI_FLAG_BSWAP) {
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF);
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF000000) >> 24;
} else {
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF000000) >> 24;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8;
- while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+ while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF);
}
@@ -377,7 +315,16 @@ uint32_t eos_spi_xchg32(uint32_t data, uint8_t flags) {
}
}
- if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
-
return r;
}
+
+void eos_spi_flush(void) {
+ volatile uint32_t x = 0;
+
+ if (spi_in_xchg) spi_xchg_wait();
+
+ SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(1);
+ while (!x) {
+ if (SPI1_REG(SPI_REG_IP) & SPI_IP_TXWM) x = SPI1_REG(SPI_REG_RXFIFO) & SPI_RXFIFO_EMPTY;
+ }
+}