Skip to content

Commit e9150e4

Browse files
committed
[ot] hw/opentitan: ot_spi_host: refactor FSM scheduling
Command completion is handled in a dedicated function. Add a short delay on command push to yield execution back to the vCPU before kicking the FSM. Signed-off-by: Emmanuel Blot <[email protected]>
1 parent 63f1695 commit e9150e4

File tree

1 file changed

+60
-54
lines changed

1 file changed

+60
-54
lines changed

hw/opentitan/ot_spi_host.c

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@
5858
#define DISCARD_REPEATED_STATUS_TRACES
5959

6060
/* 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 */
6264

6365
#define TXFIFO_LEN 288U /* bytes */
6466
#define RXFIFO_LEN 256U /* bytes */
@@ -357,12 +359,6 @@ struct OtSPIHostState {
357359
uint32_t num_cs; /**< Supported CS line count */
358360
};
359361

360-
/* ------------------------------------------------------------------------ */
361-
/* Declarations */
362-
/* ------------------------------------------------------------------------ */
363-
364-
static void ot_spi_host_post_fsm(void *opaque);
365-
366362
/* ------------------------------------------------------------------------ */
367363
/* FIFOs */
368364
/* ------------------------------------------------------------------------ */
@@ -837,20 +833,11 @@ static void ot_spi_host_step_fsm(OtSPIHostState *s, const char *cause)
837833
ot_spi_host_trace_status(s, "S<", ot_spi_host_get_status(s));
838834
}
839835

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)
845837
{
846-
OtSPIHostState *s = opaque;
847-
848-
trace_ot_spi_host_fsm(s->ot_id, s->active.cmd.id, "post");
849-
850838
uint32_t command = s->active.cmd.command;
851-
bool retire = s->active.state == CMD_EXECUTED;
852839

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)) {
854841
int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK);
855842
int64_t elapsed = now - s->active.ts;
856843
if (s->active.size) {
@@ -861,51 +848,61 @@ static void ot_spi_host_post_fsm(void *opaque)
861848
}
862849
}
863850

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);
868852

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);
878861
}
862+
}
879863

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+
}
885869

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");
888885
}
889886

890887
ot_spi_host_update_regs(s);
888+
}
891889

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));
893899

894900
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);
908902
} else {
903+
ot_spi_host_update_regs(s);
904+
905+
uint32_t command = s->active.cmd.command;
909906
unsigned length = FIELD_EX32(command, COMMAND, LEN) + 1u;
910907
bool pending = timer_pending(s->fsm_delay);
911908
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)
914911
ot_spi_host_step_fsm(s, "pending");
915912
}
916913
}
914+
915+
ot_spi_host_trace_status(s, "P<", ot_spi_host_get_status(s));
917916
}
918917

919918
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,
11481147
s->active.state = CMD_ONGOING;
11491148
s->active.size = 0u;
11501149
}
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);
11521158
break;
11531159
}
11541160
ot_spi_host_update_regs(s);
@@ -1314,7 +1320,7 @@ static void ot_spi_host_instance_init(Object *obj)
13141320
txfifo_create(s->tx_fifo, TXFIFO_LEN);
13151321
cmdfifo_create(s->cmd_fifo, CMDFIFO_LEN);
13161322

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);
13181324
}
13191325

13201326
static void ot_spi_host_class_init(ObjectClass *klass, void *data)

0 commit comments

Comments
 (0)