58
58
#define DISCARD_REPEATED_STATUS_TRACES
59
59
60
60
/* fake delayed completion of HW commands */
61
- #define FSM_COMPLETION_DELAY_NS 100U /* nanoseconds */
61
+ #define FSM_COMPLETION_DELAY_NS 100U /* 100 ns (~ BH) */
62
+ /* initial FSM start up delay */
63
+ #define FSM_START_DELAY_NS 10000U /* 10 uS */
62
64
63
65
#define TXFIFO_LEN 288U /* bytes */
64
66
#define RXFIFO_LEN 256U /* bytes */
@@ -357,12 +359,6 @@ struct OtSPIHostState {
357
359
uint32_t num_cs ; /**< Supported CS line count */
358
360
};
359
361
360
- /* ------------------------------------------------------------------------ */
361
- /* Declarations */
362
- /* ------------------------------------------------------------------------ */
363
-
364
- static void ot_spi_host_post_fsm (void * opaque );
365
-
366
362
/* ------------------------------------------------------------------------ */
367
363
/* FIFOs */
368
364
/* ------------------------------------------------------------------------ */
@@ -837,20 +833,11 @@ static void ot_spi_host_step_fsm(OtSPIHostState *s, const char *cause)
837
833
ot_spi_host_trace_status (s , "S<" , ot_spi_host_get_status (s ));
838
834
}
839
835
840
- /**
841
- * Called only from the timer once a command step is over (either completed or
842
- * stalled)
843
- */
844
- static void ot_spi_host_post_fsm (void * opaque )
836
+ static void ot_spi_host_retire (OtSPIHostState * s )
845
837
{
846
- OtSPIHostState * s = opaque ;
847
-
848
- trace_ot_spi_host_fsm (s -> ot_id , s -> active .cmd .id , "post" );
849
-
850
838
uint32_t command = s -> active .cmd .command ;
851
- bool retire = s -> active .state == CMD_EXECUTED ;
852
839
853
- if (retire && trace_event_get_state (TRACE_OT_SPI_HOST_CMD_STAT )) {
840
+ if (trace_event_get_state (TRACE_OT_SPI_HOST_CMD_STAT )) {
854
841
int64_t now = qemu_clock_get_ns (OT_VIRTUAL_CLOCK );
855
842
int64_t elapsed = now - s -> active .ts ;
856
843
if (s -> active .size ) {
@@ -861,51 +848,61 @@ static void ot_spi_host_post_fsm(void *opaque)
861
848
}
862
849
}
863
850
864
- ot_spi_host_trace_status (s , "P>" , ot_spi_host_get_status (s ));
865
-
866
- if (retire ) {
867
- trace_ot_spi_host_retire_command (s -> ot_id , s -> active .cmd .id );
851
+ trace_ot_spi_host_retire_command (s -> ot_id , s -> active .cmd .id );
868
852
869
- if (ot_spi_host_is_rx (command )) {
870
- /*
871
- * transfer has been completed, RX FIFO may need padding up to a
872
- * word
873
- */
874
- while (!fifo8_is_full (s -> rx_fifo ) &&
875
- fifo8_num_used (s -> rx_fifo ) & 0x3u ) {
876
- fifo8_push (s -> rx_fifo , 0u );
877
- }
853
+ if (ot_spi_host_is_rx (command )) {
854
+ /*
855
+ * transfer has been completed, RX FIFO may need padding up to a
856
+ * word
857
+ */
858
+ while (!fifo8_is_full (s -> rx_fifo ) &&
859
+ fifo8_num_used (s -> rx_fifo ) & 0x3u ) {
860
+ fifo8_push (s -> rx_fifo , 0u );
878
861
}
862
+ }
879
863
880
- /* release /CS if this is the last command of the current transaction */
881
- if (!FIELD_EX32 (command , COMMAND , CSAAT )) {
882
- s -> fsm .transaction = false;
883
- ot_spi_host_chip_select (s , s -> active .cmd .cs , s -> fsm .transaction );
884
- }
864
+ /* release /CS if this is the last command of the current transaction */
865
+ if (!FIELD_EX32 (command , COMMAND , CSAAT )) {
866
+ s -> fsm .transaction = false;
867
+ ot_spi_host_chip_select (s , s -> active .cmd .cs , s -> fsm .transaction );
868
+ }
885
869
886
- /* retire command */
887
- s -> active .state = CMD_NONE ;
870
+ /* retire command */
871
+ s -> active .state = CMD_NONE ;
872
+
873
+ /* last command has completed */
874
+ if (!cmdfifo_is_empty (s -> cmd_fifo )) {
875
+ /* more commands have been scheduled */
876
+ trace_ot_spi_host_debug (s -> ot_id , "next cmd" );
877
+ if (s -> active .state == CMD_NONE ) {
878
+ cmdfifo_pop (s -> cmd_fifo , & s -> active .cmd );
879
+ s -> active .state = CMD_ONGOING ;
880
+ s -> active .size = 0u ;
881
+ }
882
+ ot_spi_host_step_fsm (s , "post" );
883
+ } else {
884
+ trace_ot_spi_host_debug (s -> ot_id , "no resched: no cmd" );
888
885
}
889
886
890
887
ot_spi_host_update_regs (s );
888
+ }
891
889
892
- ot_spi_host_trace_status (s , "P<" , ot_spi_host_get_status (s ));
890
+ static void ot_spi_host_schedule_fsm (void * opaque )
891
+ {
892
+ OtSPIHostState * s = opaque ;
893
+
894
+ trace_ot_spi_host_fsm (s -> ot_id , s -> active .cmd .id , "sched" );
895
+
896
+ bool retire = s -> active .state == CMD_EXECUTED ;
897
+
898
+ ot_spi_host_trace_status (s , "P>" , ot_spi_host_get_status (s ));
893
899
894
900
if (retire ) {
895
- /* last command has completed */
896
- if (!cmdfifo_is_empty (s -> cmd_fifo )) {
897
- /* more commands have been scheduled */
898
- trace_ot_spi_host_debug (s -> ot_id , "next cmd" );
899
- if (s -> active .state == CMD_NONE ) {
900
- cmdfifo_pop (s -> cmd_fifo , & s -> active .cmd );
901
- s -> active .state = CMD_ONGOING ;
902
- s -> active .size = 0u ;
903
- }
904
- ot_spi_host_step_fsm (s , "post" );
905
- } else {
906
- trace_ot_spi_host_debug (s -> ot_id , "no resched: no cmd" );
907
- }
901
+ ot_spi_host_retire (s );
908
902
} else {
903
+ ot_spi_host_update_regs (s );
904
+
905
+ uint32_t command = s -> active .cmd .command ;
909
906
unsigned length = FIELD_EX32 (command , COMMAND , LEN ) + 1u ;
910
907
bool pending = timer_pending (s -> fsm_delay );
911
908
trace_ot_spi_host_cmd_ongoing (s -> ot_id , s -> active .cmd .id , length ,
@@ -914,6 +911,8 @@ static void ot_spi_host_post_fsm(void *opaque)
914
911
ot_spi_host_step_fsm (s , "pending" );
915
912
}
916
913
}
914
+
915
+ ot_spi_host_trace_status (s , "P<" , ot_spi_host_get_status (s ));
917
916
}
918
917
919
918
static uint64_t ot_spi_host_io_read (void * opaque , hwaddr addr ,
@@ -1148,7 +1147,14 @@ static void ot_spi_host_io_write(void *opaque, hwaddr addr, uint64_t val64,
1148
1147
s -> active .state = CMD_ONGOING ;
1149
1148
s -> active .size = 0u ;
1150
1149
}
1151
- ot_spi_host_step_fsm (s , "cmd" );
1150
+ /*
1151
+ * add a small delay before kicking of the command FSM. This yield
1152
+ * execution back to the vCPU (releasing the IO thread), so the
1153
+ * guest can check the SPI Host status, etc. This very short delay
1154
+ * does not seem to slow down execution.
1155
+ */
1156
+ timer_mod (s -> fsm_delay ,
1157
+ qemu_clock_get_ns (OT_VIRTUAL_CLOCK ) + FSM_START_DELAY_NS );
1152
1158
break ;
1153
1159
}
1154
1160
ot_spi_host_update_regs (s );
@@ -1314,7 +1320,7 @@ static void ot_spi_host_instance_init(Object *obj)
1314
1320
txfifo_create (s -> tx_fifo , TXFIFO_LEN );
1315
1321
cmdfifo_create (s -> cmd_fifo , CMDFIFO_LEN );
1316
1322
1317
- s -> fsm_delay = timer_new_ns (OT_VIRTUAL_CLOCK , & ot_spi_host_post_fsm , s );
1323
+ s -> fsm_delay = timer_new_ns (OT_VIRTUAL_CLOCK , & ot_spi_host_schedule_fsm , s );
1318
1324
}
1319
1325
1320
1326
static void ot_spi_host_class_init (ObjectClass * klass , void * data )
0 commit comments