Skip to content

Commit d5144c4

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 9866c9a commit d5144c4

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]>
@@ -379,6 +380,7 @@ typedef enum {
379380
SPI_BUS_TPM,
380381
SPI_BUS_DISCARD,
381382
SPI_BUS_ERROR,
383+
SPI_BUS_DISCARD_PACKET,
382384
} OtSpiBusState;
383385

384386
typedef enum {
@@ -641,6 +643,7 @@ static const char *BUS_STATE_NAMES[] = {
641643
STATE_NAME_ENTRY(SPI_BUS_TPM),
642644
STATE_NAME_ENTRY(SPI_BUS_DISCARD),
643645
STATE_NAME_ENTRY(SPI_BUS_ERROR),
646+
STATE_NAME_ENTRY(SPI_BUS_DISCARD_PACKET),
644647
};
645648

646649
static const char *FLASH_STATE_NAMES[] = {
@@ -2028,6 +2031,12 @@ static void ot_spi_device_chr_handle_header(OtSPIDeviceState *s)
20282031
return;
20292032
}
20302033

2034+
/* discard the packet if we're within a failed transaction */
2035+
if (s->bus.state == SPI_BUS_DISCARD_PACKET) {
2036+
BUS_CHANGE_STATE(s, DISCARD);
2037+
return;
2038+
}
2039+
20312040
/* @todo: Check that the tpm chip-select was assigned.*/
20322041
if (ot_spi_device_is_tpm_enabled(s)) {
20332042
ot_spi_device_tpm_init_buffers(s);
@@ -2242,6 +2251,7 @@ static int ot_spi_device_chr_can_receive(void *opaque)
22422251
unsigned length = 0u;
22432252

22442253
switch (bus->state) {
2254+
case SPI_BUS_DISCARD_PACKET:
22452255
case SPI_BUS_IDLE:
22462256
length = fifo8_num_free(&bus->chr_fifo);
22472257
break;
@@ -2274,6 +2284,7 @@ static void ot_spi_device_chr_receive(void *opaque, const uint8_t *buf,
22742284

22752285
switch (bus->state) {
22762286
case SPI_BUS_IDLE:
2287+
case SPI_BUS_DISCARD_PACKET:
22772288
g_assert(size <= fifo8_num_free(&bus->chr_fifo));
22782289
while (size--) {
22792290
fifo8_push(&bus->chr_fifo, *buf++);
@@ -2298,12 +2309,33 @@ static void ot_spi_device_chr_receive(void *opaque, const uint8_t *buf,
22982309
break;
22992310
}
23002311

2301-
if (!bus->byte_count) {
2302-
if (bus->release) {
2303-
ot_spi_device_release(s);
2304-
} else {
2305-
BUS_CHANGE_STATE(s, IDLE);
2306-
}
2312+
if (bus->byte_count) {
2313+
/* there is more to process in this state */
2314+
return;
2315+
}
2316+
2317+
if (bus->release) {
2318+
/* final packet in transaction, release CS */
2319+
ot_spi_device_release(s);
2320+
return;
2321+
}
2322+
2323+
/*
2324+
* more packets to process in transaction, prepare to receive another header
2325+
*/
2326+
switch (bus->state) {
2327+
case SPI_BUS_IDLE:
2328+
case SPI_BUS_FLASH:
2329+
case SPI_BUS_DISCARD_PACKET:
2330+
BUS_CHANGE_STATE(s, IDLE);
2331+
break;
2332+
case SPI_BUS_DISCARD:
2333+
case SPI_BUS_ERROR:
2334+
BUS_CHANGE_STATE(s, DISCARD_PACKET);
2335+
break;
2336+
default:
2337+
g_assert_not_reached();
2338+
break;
23072339
}
23082340
}
23092341

0 commit comments

Comments
 (0)