diff options
-rw-r--r-- | hw/ssi/ibex_spi_host.c | 36 | ||||
-rw-r--r-- | include/hw/ssi/ibex_spi_host.h | 4 |
2 files changed, 35 insertions, 5 deletions
diff --git a/hw/ssi/ibex_spi_host.c b/hw/ssi/ibex_spi_host.c index d145a4cdbd..57df462e3c 100644 --- a/hw/ssi/ibex_spi_host.c +++ b/hw/ssi/ibex_spi_host.c @@ -342,7 +342,7 @@ static void ibex_spi_host_write(void *opaque, hwaddr addr, { IbexSPIHostState *s = opaque; uint32_t val32 = val64; - uint32_t shift_mask = 0xff, status = 0; + uint32_t shift_mask = 0xff, status = 0, data = 0; uint8_t txqd_len; trace_ibex_spi_host_write(addr, size, val64); @@ -352,7 +352,17 @@ static void ibex_spi_host_write(void *opaque, hwaddr addr, switch (addr) { /* Skipping any R/O registers */ - case IBEX_SPI_HOST_INTR_STATE...IBEX_SPI_HOST_INTR_ENABLE: + case IBEX_SPI_HOST_INTR_STATE: + /* rw1c status register */ + if (FIELD_EX32(val32, INTR_STATE, ERROR)) { + data = FIELD_DP32(data, INTR_STATE, ERROR, 0); + } + if (FIELD_EX32(val32, INTR_STATE, SPI_EVENT)) { + data = FIELD_DP32(data, INTR_STATE, SPI_EVENT, 0); + } + s->regs[addr] = data; + break; + case IBEX_SPI_HOST_INTR_ENABLE: s->regs[addr] = val32; break; case IBEX_SPI_HOST_INTR_TEST: @@ -495,7 +505,27 @@ static void ibex_spi_host_write(void *opaque, hwaddr addr, * When an error occurs, the corresponding bit must be cleared * here before issuing any further commands */ - s->regs[addr] = val32; + status = s->regs[addr]; + /* rw1c status register */ + if (FIELD_EX32(val32, ERROR_STATUS, CMDBUSY)) { + status = FIELD_DP32(status, ERROR_STATUS, CMDBUSY, 0); + } + if (FIELD_EX32(val32, ERROR_STATUS, OVERFLOW)) { + status = FIELD_DP32(status, ERROR_STATUS, OVERFLOW, 0); + } + if (FIELD_EX32(val32, ERROR_STATUS, UNDERFLOW)) { + status = FIELD_DP32(status, ERROR_STATUS, UNDERFLOW, 0); + } + if (FIELD_EX32(val32, ERROR_STATUS, CMDINVAL)) { + status = FIELD_DP32(status, ERROR_STATUS, CMDINVAL, 0); + } + if (FIELD_EX32(val32, ERROR_STATUS, CSIDINVAL)) { + status = FIELD_DP32(status, ERROR_STATUS, CSIDINVAL, 0); + } + if (FIELD_EX32(val32, ERROR_STATUS, ACCESSINVAL)) { + status = FIELD_DP32(status, ERROR_STATUS, ACCESSINVAL, 0); + } + s->regs[addr] = status; break; case IBEX_SPI_HOST_EVENT_ENABLE: /* Controls which classes of SPI events raise an interrupt. */ diff --git a/include/hw/ssi/ibex_spi_host.h b/include/hw/ssi/ibex_spi_host.h index 3fedcb6805..1f6d077766 100644 --- a/include/hw/ssi/ibex_spi_host.h +++ b/include/hw/ssi/ibex_spi_host.h @@ -40,7 +40,7 @@ OBJECT_CHECK(IbexSPIHostState, (obj), TYPE_IBEX_SPI_HOST) /* SPI Registers */ -#define IBEX_SPI_HOST_INTR_STATE (0x00 / 4) /* rw */ +#define IBEX_SPI_HOST_INTR_STATE (0x00 / 4) /* rw1c */ #define IBEX_SPI_HOST_INTR_ENABLE (0x04 / 4) /* rw */ #define IBEX_SPI_HOST_INTR_TEST (0x08 / 4) /* wo */ #define IBEX_SPI_HOST_ALERT_TEST (0x0c / 4) /* wo */ @@ -54,7 +54,7 @@ #define IBEX_SPI_HOST_TXDATA (0x28 / 4) #define IBEX_SPI_HOST_ERROR_ENABLE (0x2c / 4) /* rw */ -#define IBEX_SPI_HOST_ERROR_STATUS (0x30 / 4) /* rw */ +#define IBEX_SPI_HOST_ERROR_STATUS (0x30 / 4) /* rw1c */ #define IBEX_SPI_HOST_EVENT_ENABLE (0x34 / 4) /* rw */ /* FIFO Len in Bytes */ |