Skip to content

Commit ea8242e

Browse files
committed
[ot] hw/opentitan: spi_device: discard all packets in failed transaction
If one packet in a transaction triggers an error and needs discarding, we must continue discarding the remaining packets until CS is released. Signed-off-by: James Wainwright <[email protected]>
1 parent 61c4166 commit ea8242e

File tree

1 file changed

+38
-6
lines changed

1 file changed

+38
-6
lines changed

hw/opentitan/ot_spi_device.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* QEMU OpenTitan SPI Device controller
33
*
44
* Copyright (c) 2023-2025 Rivos, Inc.
5+
* Copyright (c) 2025 lowRISC contributors.
56
*
67
* Author(s):
78
* Emmanuel Blot <[email protected]>
@@ -366,6 +367,7 @@ typedef enum {
366367
SPI_BUS_FLASH,
367368
SPI_BUS_DISCARD,
368369
SPI_BUS_ERROR,
370+
SPI_BUS_DISCARD_PACKET,
369371
} OtSpiBusState;
370372

371373
typedef enum {
@@ -601,6 +603,7 @@ static const char *BUS_STATE_NAMES[] = {
601603
STATE_NAME_ENTRY(SPI_BUS_FLASH),
602604
STATE_NAME_ENTRY(SPI_BUS_DISCARD),
603605
STATE_NAME_ENTRY(SPI_BUS_ERROR),
606+
STATE_NAME_ENTRY(SPI_BUS_DISCARD_PACKET),
604607
};
605608

606609
static const char *FLASH_STATE_NAMES[] = {
@@ -1924,6 +1927,12 @@ static void ot_spi_device_chr_handle_header(OtSPIDeviceState *s)
19241927
return;
19251928
}
19261929

1930+
/* discard the packet if we're within a failed transaction */
1931+
if (s->bus.state == SPI_BUS_DISCARD_PACKET) {
1932+
BUS_CHANGE_STATE(s, DISCARD);
1933+
return;
1934+
}
1935+
19271936
switch (ot_spi_device_get_mode(s)) {
19281937
case CTRL_MODE_FLASH:
19291938
BUS_CHANGE_STATE(s, FLASH);
@@ -1984,6 +1993,7 @@ static int ot_spi_device_chr_can_receive(void *opaque)
19841993
unsigned length;
19851994

19861995
switch (bus->state) {
1996+
case SPI_BUS_DISCARD_PACKET:
19871997
case SPI_BUS_IDLE:
19881998
length = fifo8_num_free(&bus->chr_fifo);
19891999
break;
@@ -2013,6 +2023,7 @@ static void ot_spi_device_chr_receive(void *opaque, const uint8_t *buf,
20132023

20142024
switch (bus->state) {
20152025
case SPI_BUS_IDLE:
2026+
case SPI_BUS_DISCARD_PACKET:
20162027
g_assert(size <= fifo8_num_free(&bus->chr_fifo));
20172028
while (size--) {
20182029
fifo8_push(&bus->chr_fifo, *buf++);
@@ -2034,12 +2045,33 @@ static void ot_spi_device_chr_receive(void *opaque, const uint8_t *buf,
20342045
break;
20352046
}
20362047

2037-
if (!bus->byte_count) {
2038-
if (bus->release) {
2039-
ot_spi_device_release(s);
2040-
} else {
2041-
BUS_CHANGE_STATE(s, IDLE);
2042-
}
2048+
if (bus->byte_count) {
2049+
/* there is more to process in this state */
2050+
return;
2051+
}
2052+
2053+
if (bus->release) {
2054+
/* final packet in transaction, release CS */
2055+
ot_spi_device_release(s);
2056+
return;
2057+
}
2058+
2059+
/*
2060+
* more packets to process in transaction, prepare to receive another header
2061+
*/
2062+
switch (bus->state) {
2063+
case SPI_BUS_IDLE:
2064+
case SPI_BUS_FLASH:
2065+
case SPI_BUS_DISCARD_PACKET:
2066+
BUS_CHANGE_STATE(s, IDLE);
2067+
break;
2068+
case SPI_BUS_DISCARD:
2069+
case SPI_BUS_ERROR:
2070+
BUS_CHANGE_STATE(s, DISCARD_PACKET);
2071+
break;
2072+
default:
2073+
g_assert_not_reached();
2074+
break;
20432075
}
20442076
}
20452077

0 commit comments

Comments
 (0)