Skip to content

Commit 5489358

Browse files
committed
[ot] hw/opentitan: ot_spi_host: rework SPI event management
Should be closer to real HW. Signed-off-by: Emmanuel Blot <eblot@rivosinc.com> (cherry picked from commit 938395d0deb06df0f73f9062abd2c94d5817b844)
1 parent 1412aec commit 5489358

File tree

2 files changed

+45
-38
lines changed

2 files changed

+45
-38
lines changed

hw/opentitan/ot_spi_host.c

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
/* ------------------------------------------------------------------------ */
5959

6060
/* undef to get all the repeated, identical status query traces */
61-
#define DISCARD_REPEATED_STATUS_TRACES
61+
#undef DISCARD_REPEATED_STATUS_TRACES
6262

6363
/* fake delayed completion of HW commands */
6464
#define FSM_TRIGGER_DELAY_NS 100U /* nanoseconds */
@@ -249,17 +249,21 @@ static void ot_spi_host_trace_status(const char *ot_id, const char *msg,
249249
unsigned rxd = FIELD_EX32(status, STATUS, RXQD);
250250
unsigned txd = FIELD_EX32(status, STATUS, TXQD);
251251
char str[64u];
252-
(void)snprintf(str, sizeof(str), "%s%s%s%s%s%s%s%s%s%s",
253-
FIELD_EX32(status, STATUS, RXWM) ? "RXM|" : "",
254-
FIELD_EX32(status, STATUS, RXSTALL) ? "RXS|" : "",
255-
FIELD_EX32(status, STATUS, RXEMPTY) ? "RXE|" : "",
256-
FIELD_EX32(status, STATUS, RXFULL) ? "RXF|" : "",
257-
FIELD_EX32(status, STATUS, TXWM) ? "TXM|" : "",
258-
FIELD_EX32(status, STATUS, TXSTALL) ? "TXS|" : "",
259-
FIELD_EX32(status, STATUS, TXEMPTY) ? "TXE|" : "",
260-
FIELD_EX32(status, STATUS, TXFULL) ? "TXF|" : "",
261-
FIELD_EX32(status, STATUS, ACTIVE) ? "ACT|" : "",
262-
FIELD_EX32(status, STATUS, READY) ? "RDY|" : "");
252+
int last =
253+
snprintf(str, sizeof(str), "%s%s%s%s%s%s%s%s%s%s",
254+
FIELD_EX32(status, STATUS, RXWM) ? "RXM|" : "",
255+
FIELD_EX32(status, STATUS, RXSTALL) ? "RXS|" : "",
256+
FIELD_EX32(status, STATUS, RXEMPTY) ? "RXE|" : "",
257+
FIELD_EX32(status, STATUS, RXFULL) ? "RXF|" : "",
258+
FIELD_EX32(status, STATUS, TXWM) ? "TXM|" : "",
259+
FIELD_EX32(status, STATUS, TXSTALL) ? "TXS|" : "",
260+
FIELD_EX32(status, STATUS, TXEMPTY) ? "TXE|" : "",
261+
FIELD_EX32(status, STATUS, TXFULL) ? "TXF|" : "",
262+
FIELD_EX32(status, STATUS, ACTIVE) ? "ACT|" : "",
263+
FIELD_EX32(status, STATUS, READY) ? "RDY|" : "");
264+
if (str[last - 1] == '|') {
265+
str[last - 1] = '\0';
266+
}
263267
trace_ot_spi_host_status(ot_id, msg, status, str, cmd, rxd, txd);
264268
}
265269

@@ -325,6 +329,7 @@ struct OtSPIHostState {
325329
IbexIRQ alert; /**< OpenTitan alert */
326330
uint32_t events; /**< Active events */
327331
uint32_t last_events; /**< Last detected events */
332+
uint64_t total_transfer; /**< Transfered bytes since reset */
328333

329334
OtSPIHostFsm fsm;
330335
bool on_reset;
@@ -617,26 +622,19 @@ static bool ot_spi_host_update_event(OtSPIHostState *s)
617622
/* new events' state */
618623
uint32_t events = ot_spi_host_build_event_bits(s);
619624

620-
/* events that have changed since last call (detect rising/falling edges) */
621-
uint32_t changes = s->last_events ^ events;
622-
/* RXWM/TXWM are not edge events, but level ones */
623-
changes |= R_EVENT_ENABLE_RXWM_MASK | R_EVENT_ENABLE_TXWM_MASK;
625+
/* events that have been raised since last call */
626+
uint32_t raised_events = events & (s->last_events ^ events);
624627
s->last_events = events;
625628

626-
/* pick up changes */
627-
events &= changes;
628-
629629
/* accumulate events */
630-
s->events |= events;
630+
s->events |= raised_events;
631631

632632
/* mask disabled events to get the spi event state */
633-
bool event = (bool)(s->events & s->regs[R_EVENT_ENABLE]);
634-
trace_ot_spi_host_debug1(s->ot_id, "event", event);
633+
uint32_t eff_events = s->events & s->regs[R_EVENT_ENABLE];
634+
trace_ot_spi_host_events(s->ot_id, events, raised_events, s->events,
635+
s->regs[R_EVENT_ENABLE], eff_events);
635636

636-
/*
637-
* if the spi event test has been enabled, force event and clear its bit
638-
* right away
639-
*/
637+
bool event = (bool)eff_events;
640638
event |= (bool)(s->regs[R_INTR_TEST] & INTR_SPI_EVENT_MASK);
641639
s->regs[R_INTR_TEST] &= ~INTR_SPI_EVENT_MASK;
642640
if (event) {
@@ -645,7 +643,6 @@ static bool ot_spi_host_update_event(OtSPIHostState *s)
645643
s->regs[R_INTR_STATE] &= ~INTR_SPI_EVENT_MASK;
646644
}
647645

648-
/* now update the IRQ signal (event could have been already signalled) */
649646
bool event_level = (bool)(s->regs[R_INTR_STATE] & s->regs[R_INTR_ENABLE] &
650647
INTR_SPI_EVENT_MASK);
651648
if (event_level != (bool)ibex_irq_get_level(&s->irqs[IRQ_SPI_EVENT])) {
@@ -737,6 +734,8 @@ static void ot_spi_host_reset(OtSPIHostState *s)
737734

738735
ot_spi_host_update_regs(s);
739736
ot_spi_host_update_alert(s);
737+
738+
s->total_transfer = 0;
740739
}
741740

742741
/**
@@ -807,7 +806,8 @@ static void ot_spi_host_step_fsm(OtSPIHostState *s, const char *cause)
807806
fifo8_push(s->rx_fifo, rx);
808807
}
809808

810-
trace_ot_spi_host_transfer(s->ot_id, tx, rx);
809+
trace_ot_spi_host_transfer(s->ot_id, s->total_transfer, tx, rx);
810+
s->total_transfer += 1u;
811811

812812
length--;
813813
}
@@ -834,6 +834,8 @@ static void ot_spi_host_step_fsm(OtSPIHostState *s, const char *cause)
834834
headcmd->command = (uint16_t)command;
835835
headcmd->ongoing = ongoing;
836836

837+
ot_spi_host_update_regs(s);
838+
837839
timer_mod_anticipate(s->fsm_delay, qemu_clock_get_ns(OT_VIRTUAL_CLOCK) +
838840
FSM_TRIGGER_DELAY_NS);
839841

@@ -901,7 +903,7 @@ static void ot_spi_host_post_fsm(void *opaque)
901903
/* more commands have been scheduled */
902904
trace_ot_spi_host_debug(s->ot_id, "Next cmd");
903905
if (!ot_spi_host_is_on_error(s)) {
904-
qemu_bh_schedule(s->fsm_bh);
906+
ot_spi_host_step_fsm(s, "post");
905907
} else {
906908
trace_ot_spi_host_debug(s->ot_id, "no resched: on err");
907909
}
@@ -962,6 +964,8 @@ static uint64_t ot_spi_host_io_read(void *opaque, hwaddr addr,
962964
case R_RXDATA: {
963965
/* here, size != 4 is illegal, what to do in this case? */
964966
if (fifo8_num_used(s->rx_fifo) < sizeof(uint32_t)) {
967+
qemu_log_mask(LOG_GUEST_ERROR, "%s: %s: Read underflow: %u\n",
968+
__func__, s->ot_id, fifo8_num_used(s->rx_fifo));
965969
REG_UPDATE(s, ERROR_STATUS, UNDERFLOW, 1);
966970
ot_spi_host_update_regs(s);
967971
val32 = 0u;
@@ -972,6 +976,7 @@ static uint64_t ot_spi_host_io_read(void *opaque, hwaddr addr,
972976
val32 <<= 8u;
973977
val32 |= (uint32_t)fifo8_pop(s->rx_fifo);
974978
}
979+
ot_spi_host_trace_status(s->ot_id, "rxd", ot_spi_host_get_status(s));
975980
val32 = bswap32(val32);
976981
bool resume = false;
977982
if (!cmdfifo_is_empty(s->cmd_fifo)) {
@@ -1009,7 +1014,9 @@ static uint64_t ot_spi_host_io_read(void *opaque, hwaddr addr,
10091014
if (trace_cache.pc != pc || trace_cache.addr != addr ||
10101015
trace_cache.value != val32) {
10111016
if (trace_cache.count > 1u) {
1012-
trace_ot_spi_host_io_read_repeat(s->ot_id, trace_cache.count);
1017+
hwaddr rreg = R32_OFF(trace_cache.addr);
1018+
trace_ot_spi_host_io_read_repeat(s->ot_id, REG_NAME(rreg),
1019+
trace_cache.count);
10131020
}
10141021
#endif /* DISCARD_REPEATED_STATUS_TRACES */
10151022
trace_ot_spi_host_io_read(s->ot_id, (uint32_t)addr, REG_NAME(reg),
@@ -1055,11 +1062,10 @@ static void ot_spi_host_io_write(void *opaque, hwaddr addr, uint64_t val64,
10551062
val32 &= INTR_MASK;
10561063
s->regs[R_INTR_STATE] &= ~val32;
10571064
if (val32 & INTR_SPI_EVENT_MASK) {
1058-
/* store current state */
1059-
s->last_events = ot_spi_host_build_event_bits(s);
10601065
/* clear up all signalled events */
10611066
s->events = 0u;
10621067
}
1068+
/* this call also regenerates all raised events */
10631069
ot_spi_host_update_regs(s);
10641070
break;
10651071
case R_INTR_ENABLE:

hw/opentitan/trace-events

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -466,16 +466,17 @@ ot_spi_host_command(const char *id, const char *dir, const char *spd, uint32_t c
466466
ot_spi_host_cs(const char *id, uint32_t csid, const char *level) "%s: cs#:%u %sselected"
467467
ot_spi_host_debug(const char *id, const char *msg) "%s: %s"
468468
ot_spi_host_debug1(const char *id, const char *msg, uint32_t val) "%s: %s 0x%x"
469+
ot_spi_host_events(const char *id, uint32_t cur, uint32_t raised, uint32_t active, uint32_t mask, uint32_t eff) "%s: cur:0x%02x rsd:0x%02x act:0x%02x msk:0x%02x eff:0x%02x"
469470
ot_spi_host_fsm(const char *id, const char *cause) "%s: step %s"
470-
ot_spi_host_io_read(const char *id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr:0x%02x (%s), val:0x%x, pc:0x%x"
471-
ot_spi_host_io_read_repeat(const char *id, size_t count) "%s: last read repeated %zu times"
472-
ot_spi_host_io_write(const char *id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr:0x%02x (%s), val:0x%x, pc:0x%x"
471+
ot_spi_host_io_read(const char *id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr:0x%02x (%s), val:0x%08x, pc:0x%x"
472+
ot_spi_host_io_read_repeat(const char *id, const char * regname, size_t count) "%s: last %s read repeated %zu times"
473+
ot_spi_host_io_write(const char *id, uint32_t addr, const char * regname, uint32_t val, uint32_t pc) "%s: addr:0x%02x (%s), val:0x%08x, pc:0x%x"
473474
ot_spi_host_reject(const char *id, const char *msg) "%s: %s"
474475
ot_spi_host_reset(const char *id, const char *msg) "%s: %s"
475-
ot_spi_host_stall(const char *id, const char *msg, uint32_t val) "%s: %s %u"
476+
ot_spi_host_stall(const char *id, const char *msg, uint32_t val) "%s: %s rem %u"
476477
ot_spi_host_status(const char *id, const char *msg, uint32_t status, const char *str, unsigned cmd, unsigned rxd, unsigned txd) "%s: %s 0x%08x s:%s cq:%u rq:%u tq:%u"
477-
ot_spi_host_transfer(const char *id, uint32_t tx_data, uint32_t rx_data) "%s: tx_data: 0x%02x rx_data: 0x%02x"
478-
ot_spi_host_update_irq(const char *id, const char *channel, int level) "%s: %s: %d"
478+
ot_spi_host_transfer(const char *id, uint64_t transfer, uint32_t tx_data, uint32_t rx_data) "%s: {%" PRIu64 "} tx_data: 0x%02x rx_data: 0x%02x"
479+
ot_spi_host_update_irq(const char *id, const char *channel, int level) "%s: irq %s: %d"
479480

480481
# ot_sram_ctrl.c
481482

0 commit comments

Comments
 (0)