58
58
/* ------------------------------------------------------------------------ */
59
59
60
60
/* undef to get all the repeated, identical status query traces */
61
- #define DISCARD_REPEATED_STATUS_TRACES
61
+ #undef DISCARD_REPEATED_STATUS_TRACES
62
62
63
63
/* fake delayed completion of HW commands */
64
64
#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,
249
249
unsigned rxd = FIELD_EX32 (status , STATUS , RXQD );
250
250
unsigned txd = FIELD_EX32 (status , STATUS , TXQD );
251
251
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
+ }
263
267
trace_ot_spi_host_status (ot_id , msg , status , str , cmd , rxd , txd );
264
268
}
265
269
@@ -325,6 +329,7 @@ struct OtSPIHostState {
325
329
IbexIRQ alert ; /**< OpenTitan alert */
326
330
uint32_t events ; /**< Active events */
327
331
uint32_t last_events ; /**< Last detected events */
332
+ uint64_t total_transfer ; /**< Transfered bytes since reset */
328
333
329
334
OtSPIHostFsm fsm ;
330
335
bool on_reset ;
@@ -617,26 +622,19 @@ static bool ot_spi_host_update_event(OtSPIHostState *s)
617
622
/* new events' state */
618
623
uint32_t events = ot_spi_host_build_event_bits (s );
619
624
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 );
624
627
s -> last_events = events ;
625
628
626
- /* pick up changes */
627
- events &= changes ;
628
-
629
629
/* accumulate events */
630
- s -> events |= events ;
630
+ s -> events |= raised_events ;
631
631
632
632
/* 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 );
635
636
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 ;
640
638
event |= (bool )(s -> regs [R_INTR_TEST ] & INTR_SPI_EVENT_MASK );
641
639
s -> regs [R_INTR_TEST ] &= ~INTR_SPI_EVENT_MASK ;
642
640
if (event ) {
@@ -645,7 +643,6 @@ static bool ot_spi_host_update_event(OtSPIHostState *s)
645
643
s -> regs [R_INTR_STATE ] &= ~INTR_SPI_EVENT_MASK ;
646
644
}
647
645
648
- /* now update the IRQ signal (event could have been already signalled) */
649
646
bool event_level = (bool )(s -> regs [R_INTR_STATE ] & s -> regs [R_INTR_ENABLE ] &
650
647
INTR_SPI_EVENT_MASK );
651
648
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)
737
734
738
735
ot_spi_host_update_regs (s );
739
736
ot_spi_host_update_alert (s );
737
+
738
+ s -> total_transfer = 0 ;
740
739
}
741
740
742
741
/**
@@ -807,7 +806,8 @@ static void ot_spi_host_step_fsm(OtSPIHostState *s, const char *cause)
807
806
fifo8_push (s -> rx_fifo , rx );
808
807
}
809
808
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 ;
811
811
812
812
length -- ;
813
813
}
@@ -834,6 +834,8 @@ static void ot_spi_host_step_fsm(OtSPIHostState *s, const char *cause)
834
834
headcmd -> command = (uint16_t )command ;
835
835
headcmd -> ongoing = ongoing ;
836
836
837
+ ot_spi_host_update_regs (s );
838
+
837
839
timer_mod_anticipate (s -> fsm_delay , qemu_clock_get_ns (OT_VIRTUAL_CLOCK ) +
838
840
FSM_TRIGGER_DELAY_NS );
839
841
@@ -901,7 +903,7 @@ static void ot_spi_host_post_fsm(void *opaque)
901
903
/* more commands have been scheduled */
902
904
trace_ot_spi_host_debug (s -> ot_id , "Next cmd" );
903
905
if (!ot_spi_host_is_on_error (s )) {
904
- qemu_bh_schedule ( s -> fsm_bh );
906
+ ot_spi_host_step_fsm ( s , "post" );
905
907
} else {
906
908
trace_ot_spi_host_debug (s -> ot_id , "no resched: on err" );
907
909
}
@@ -962,6 +964,8 @@ static uint64_t ot_spi_host_io_read(void *opaque, hwaddr addr,
962
964
case R_RXDATA : {
963
965
/* here, size != 4 is illegal, what to do in this case? */
964
966
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 ));
965
969
REG_UPDATE (s , ERROR_STATUS , UNDERFLOW , 1 );
966
970
ot_spi_host_update_regs (s );
967
971
val32 = 0u ;
@@ -972,6 +976,7 @@ static uint64_t ot_spi_host_io_read(void *opaque, hwaddr addr,
972
976
val32 <<= 8u ;
973
977
val32 |= (uint32_t )fifo8_pop (s -> rx_fifo );
974
978
}
979
+ ot_spi_host_trace_status (s -> ot_id , "rxd" , ot_spi_host_get_status (s ));
975
980
val32 = bswap32 (val32 );
976
981
bool resume = false;
977
982
if (!cmdfifo_is_empty (s -> cmd_fifo )) {
@@ -1009,7 +1014,9 @@ static uint64_t ot_spi_host_io_read(void *opaque, hwaddr addr,
1009
1014
if (trace_cache .pc != pc || trace_cache .addr != addr ||
1010
1015
trace_cache .value != val32 ) {
1011
1016
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 );
1013
1020
}
1014
1021
#endif /* DISCARD_REPEATED_STATUS_TRACES */
1015
1022
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,
1055
1062
val32 &= INTR_MASK ;
1056
1063
s -> regs [R_INTR_STATE ] &= ~val32 ;
1057
1064
if (val32 & INTR_SPI_EVENT_MASK ) {
1058
- /* store current state */
1059
- s -> last_events = ot_spi_host_build_event_bits (s );
1060
1065
/* clear up all signalled events */
1061
1066
s -> events = 0u ;
1062
1067
}
1068
+ /* this call also regenerates all raised events */
1063
1069
ot_spi_host_update_regs (s );
1064
1070
break ;
1065
1071
case R_INTR_ENABLE :
0 commit comments