summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMulin Chao <mlchao@nuvoton.com>2016-04-29 13:35:54 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-05-06 18:58:20 -0700
commit3391ef950a0ba7daf069fb760daadb872ca71cfe (patch)
tree1580a7acf7993076fdd408a8c56b87c7e865f983
parentb13f300ca3a322a3d20d1f27270924d50113b643 (diff)
downloadchrome-ec-3391ef950a0ba7daf069fb760daadb872ca71cfe.tar.gz
npcx: shi: Improve reliability of SPI host command interface
- Fix output buffer filling races - Limit response size to 256 bytes to work-around forced low bit on 257th byte - Modify CS glitch to handle CS-to-clock delay - Make CS GPIO interrupt pri 0 to ensure SHI interrupts aren't serviced first TEST=`while true; do ectool version; done > /usr/local/log` on kevin, verify failure occurs about every ~72000 commands (~360000 host commands) BRANCH=None BUG=chrome-os-partner:52372 Change-Id: I5c3d90bf510ed782973b57c2b7497441434c1708 Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/341492 Commit-Ready: Shawn N <shawnn@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/kevin/board.h1
-rw-r--r--board/npcx_evb_arm/board.h4
-rw-r--r--chip/npcx/gpio.c7
-rw-r--r--chip/npcx/shi.c360
4 files changed, 246 insertions, 126 deletions
diff --git a/board/kevin/board.h b/board/kevin/board.h
index 3ecff9ff64..b7735015d3 100644
--- a/board/kevin/board.h
+++ b/board/kevin/board.h
@@ -88,6 +88,7 @@
#define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */
/* Enable SHI PU on transition to S0. Disable the PU otherwise for leakage. */
#define NPCX_SHI_CS_PU
+#define NPCX_SHI_BYPASS_OVER_256B
/* Optional for testing */
#undef CONFIG_PECI
diff --git a/board/npcx_evb_arm/board.h b/board/npcx_evb_arm/board.h
index ca572b8a0b..bc0e748bdd 100644
--- a/board/npcx_evb_arm/board.h
+++ b/board/npcx_evb_arm/board.h
@@ -42,6 +42,10 @@
#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */
#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/
#define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */
+/* Enable SHI PU on transition to S0. Disable the PU otherwise for leakage. */
+#define NPCX_SHI_CS_PU
+/* Enable bypass since shi outputs invalid data when across 256B boundary */
+#define NPCX_SHI_BYPASS_OVER_256B
/* Optional for testing */
#undef CONFIG_PECI
diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c
index 1bca7b7d03..1e7c5b9b35 100644
--- a/chip/npcx/gpio.c
+++ b/chip/npcx/gpio.c
@@ -827,7 +827,12 @@ DECLARE_IRQ(NPCX_IRQ_WKINTA_1, __gpio_wk1a_interrupt, 1);
DECLARE_IRQ(NPCX_IRQ_WKINTB_1, __gpio_wk1b_interrupt, 1);
DECLARE_IRQ(NPCX_IRQ_WKINTD_1, __gpio_wk1d_interrupt, 1);
DECLARE_IRQ(NPCX_IRQ_WKINTE_1, __gpio_wk1e_interrupt, 1);
-DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 1);
+/*
+ * HACK: Make CS GPIO P0 to improve SHI reliability.
+ * TODO: Increase CS-assertion-to-transaction-start delay on host to
+ * accommodate P1 CS interrupt.
+ */
+DECLARE_IRQ(NPCX_IRQ_WKINTF_1, __gpio_wk1f_interrupt, 0);
DECLARE_IRQ(NPCX_IRQ_WKINTG_1, __gpio_wk1g_interrupt, 1);
DECLARE_IRQ(NPCX_IRQ_WKINTH_1, __gpio_wk1h_interrupt, 1);
diff --git a/chip/npcx/shi.c b/chip/npcx/shi.c
index a907d88173..ca5c4ac774 100644
--- a/chip/npcx/shi.c
+++ b/chip/npcx/shi.c
@@ -72,15 +72,7 @@
#define SHI_CMD_RX_TIMEOUT_US 8192
/* Timeout for glitch case. Make sure it will exceed 8 SPI clocks */
-#define SHI_GLITCH_TIMEOUT_US 10
-
-/*
- * Max data size for a version 3 request/response packet. This is big enough
- * to handle a request/response header, flash write offset/size, and 512 bytes
- * of flash data.
- */
-#define SHI_MAX_REQUEST_SIZE 0x220
-#define SHI_MAX_RESPONSE_SIZE 0x220
+#define SHI_GLITCH_TIMEOUT_US 500
/*
* The AP blindly clocks back bytes over the SPI interface looking for a
@@ -107,6 +99,31 @@
*/
#define SHI_PROTO3_OVERHEAD (EC_SPI_PAST_END_LENGTH + EC_SPI_FRAME_START_LENGTH)
+
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+/* The boundary which SHI will output invalid data on MISO. */
+#define SHI_BYPASS_BOUNDARY 256
+/* Increase FRAME_START_LENGTH in case shi outputs invalid FRAME_START byte */
+#undef EC_SPI_FRAME_START_LENGTH
+#define EC_SPI_FRAME_START_LENGTH 2
+#endif
+
+/*
+ * Max data size for a version 3 request/response packet. This is big enough
+ * to handle a request/response header, flash write offset/size, and 512 bytes
+ * of flash data.
+ */
+#define SHI_MAX_REQUEST_SIZE 0x220
+
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+/* Make sure SHI_MAX_RESPONSE_SIZE won't exceed 256 bytes */
+#define SHI_MAX_RESPONSE_SIZE (160 + EC_SPI_PAST_END_LENGTH + \
+ EC_SPI_FRAME_START_LENGTH + sizeof(struct ec_host_response))
+BUILD_ASSERT(SHI_MAX_RESPONSE_SIZE <= SHI_BYPASS_BOUNDARY);
+#else
+#define SHI_MAX_RESPONSE_SIZE 0x220
+#endif
+
/*
* Our input and output msg buffers. These must be large enough for our largest
* message, including protocol overhead, and must be 32-bit aligned.
@@ -122,17 +139,23 @@ enum shi_state {
SHI_STATE_DISABLED = 0,
/* Ready to receive next request */
SHI_STATE_READY_TO_RECV,
- /* Complete transaction but need to initialize */
- SHI_STATE_NOT_READY,
/* Receiving request */
SHI_STATE_RECEIVING,
/* Processing request */
SHI_STATE_PROCESSING,
+ /* Canceling response since CS deasserted and output NOT_READY byte */
+ SHI_STATE_CNL_RESP_NOT_RDY,
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ /* Keep output buffer as PROCESSING byte until reaching 256B boundary */
+ SHI_STATE_WAIT_ALIGNMENT,
+#endif
/* Sending response */
SHI_STATE_SENDING,
- /* State machine mismatch, timeout, or protocol we can't handle. */
- SHI_STATE_ERROR,
-} state;
+ /* Received data is valid. */
+ SHI_STATE_BAD_RECEIVED_DATA,
+};
+
+volatile enum shi_state state;
/* SHI bus parameters */
struct shi_bus_parameters {
@@ -146,14 +169,17 @@ struct shi_bus_parameters {
uint16_t sz_response; /* response bytes need to receive */
timestamp_t rx_deadline; /* deadline of receiving */
uint8_t pre_ibufstat; /* Previous IBUFSTAT value */
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ uint16_t bytes_in_256b; /* Sent bytes in 256 bytes boundary */
+#endif
} shi_params;
/* Forward declaraction */
static void shi_reset_prepare(void);
-static void shi_error(int need_reset);
+static void shi_bad_received_data(void);
static void shi_fill_out_status(uint8_t status);
static void shi_write_half_outbuf(void);
-static void shi_write_outbuf_wait(uint16_t szbytes);
+static void shi_write_first_pkg_outbuf(uint16_t szbytes);
static int shi_read_inbuf_wait(uint16_t szbytes);
/*****************************************************************************/
@@ -180,28 +206,47 @@ static void shi_send_response_packet(struct host_packet *pkt)
*/
if (state == SHI_STATE_PROCESSING) {
/*
+ * Disable interrupts. This routine is not called from interrupt
+ * context and buffer underrun will likely occur if it is
+ * preempted after writing its initial reply byte.
+ */
+ interrupt_disable();
+ /*
* Disable SHI interrupt until we have prepared
* the first package to output
*/
task_disable_irq(NPCX_IRQ_SHI);
- /* Transmit the reply */
- state = SHI_STATE_SENDING;
- DEBUG_CPRINTF("SND-");
+
/* Start to fill output buffer with msg buffer */
- shi_write_outbuf_wait(shi_params.sz_response);
+ shi_write_first_pkg_outbuf(shi_params.sz_response);
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ /*
+ * If response package is over 256B boundary,
+ * keep sending PROCESSING byte
+ */
+ if (state != SHI_STATE_WAIT_ALIGNMENT) {
+#endif
+ /* Transmit the reply */
+ state = SHI_STATE_SENDING;
+ DEBUG_CPRINTF("SND-");
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ }
+#endif
+
/* Enable SHI interrupt */
task_enable_irq(NPCX_IRQ_SHI);
+ interrupt_enable();
}
/*
* If we're not processing, then the AP has already terminated the
* transaction, and won't be listening for a response.
+ * Reset state machine for next transaction.
*/
- else {
- /* Reset SHI and prepare to next transaction again */
+ else if (state == SHI_STATE_CNL_RESP_NOT_RDY) {
shi_reset_prepare();
DEBUG_CPRINTF("END\n");
- return;
- }
+ } else
+ CPRINTS("Unexpected state %d in response handler\n", state);
}
void shi_handle_host_package(void)
@@ -214,12 +259,13 @@ void shi_handle_host_package(void)
else {
uint16_t remain_bytes = shi_params.sz_request
- shi_params.sz_received;
+
+ /* Read remaining bytes from input buffer directly */
+ if (!shi_read_inbuf_wait(remain_bytes))
+ return shi_bad_received_data();
/* Move to processing state immediately */
state = SHI_STATE_PROCESSING;
DEBUG_CPRINTF("PRC-");
- /* Read remaining bytes from input buffer directly */
- if (!shi_read_inbuf_wait(remain_bytes))
- return shi_error(1);
}
/* Fill output buffer to indicate we`re processing request */
shi_fill_out_status(EC_SPI_PROCESSING);
@@ -232,9 +278,16 @@ void shi_handle_host_package(void)
shi_packet.request_max = sizeof(in_msg);
shi_packet.request_size = shi_params.sz_request;
+
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ /* Move FRAME_START to second byte */
+ out_msg[0] = EC_SPI_PROCESSING;
+ out_msg[1] = EC_SPI_FRAME_START;
+#else
/* Put FRAME_START in first byte */
out_msg[0] = EC_SPI_FRAME_START;
- shi_packet.response = out_msg + 1;
+#endif
+ shi_packet.response = out_msg + EC_SPI_FRAME_START_LENGTH;
/* Reserve space for frame start and trailing past-end byte */
shi_packet.response_max = sizeof(out_msg) - SHI_PROTO3_OVERHEAD;
@@ -248,9 +301,20 @@ void shi_handle_host_package(void)
/* Parse header for version of spi-protocol */
static void shi_parse_header(void)
{
+ /* Disable SHI interrupt until we're sure the size of request package.*/
+ task_disable_irq(NPCX_IRQ_SHI);
+
+ /* We're now inside a transaction */
+ state = SHI_STATE_RECEIVING;
+ DEBUG_CPRINTF("RV-");
+
+ /* Setup deadline time for receiving */
+ shi_params.rx_deadline = get_time();
+ shi_params.rx_deadline.val += SHI_CMD_RX_TIMEOUT_US;
+
/* Wait for version, command, length bytes */
if (!shi_read_inbuf_wait(3))
- return shi_error(1);
+ return shi_bad_received_data();
if (in_msg[0] == EC_HOST_REQUEST_VERSION) {
/* Protocol version 3 */
@@ -264,20 +328,23 @@ static void shi_parse_header(void)
/* Wait for the rest of the command header */
if (!shi_read_inbuf_wait(sizeof(*r) - 3))
- return shi_error(1);
+ return shi_bad_received_data();
/* Check how big the packet should be */
pkt_size = host_request_expected_size(r);
if (pkt_size == 0 || pkt_size > sizeof(in_msg))
- return shi_error(0);
+ return shi_bad_received_data();
/* Computing total bytes need to receive */
shi_params.sz_request = pkt_size;
+ /* Enable SHI interrupt & handle request package */
+ task_enable_irq(NPCX_IRQ_SHI);
+
shi_handle_host_package();
} else {
/* Invalid version number */
- return shi_error(0);
+ return shi_bad_received_data();
}
}
@@ -288,13 +355,38 @@ static void shi_parse_header(void)
static void shi_fill_out_status(uint8_t status)
{
uint16_t i;
- uint16_t offset = SHI_OBUF_VALID_OFFSET;
+ uint16_t offset = NPCX_IBUFSTAT + SHI_OUT_PREAMBLE_LENGTH;
+
+ /* Disable interrupts in case the interfere by the other interrupts */
+ interrupt_disable();
/* Fill out all output buffer with status byte */
for (i = offset; i < SHI_OBUF_FULL_SIZE; i++)
NPCX_OBUF(i) = status;
for (i = 0; i < offset; i++)
NPCX_OBUF(i) = status;
+
+ /* End of critical section */
+ interrupt_enable();
+}
+
+/*
+ * This routine makes sure it's valid transaction or glitch on CS bus.
+ */
+static int shi_is_cs_glitch(void)
+{
+ timestamp_t deadline;
+
+ deadline.val = get_time().val + SHI_GLITCH_TIMEOUT_US;
+ /*
+ * If input buffer pointer is no changed after timeout, it will
+ * return true
+ */
+ while (shi_params.pre_ibufstat == NPCX_IBUFSTAT)
+ if (timestamp_expired(deadline, NULL))
+ return 1;
+ /* valid package */
+ return 0;
}
/*
@@ -311,16 +403,31 @@ static void shi_write_half_outbuf(void)
}
/*
- * This routine write SHI output buffer from msg buffer until
- * we have sent a certain number of bytes or output buffer is full
+ * This routine write SHI output buffer from msg buffer over halt of it.
+ * It make sure we have enought time to handle next operations.
*/
-static void shi_write_outbuf_wait(uint16_t szbytes)
+static void shi_write_first_pkg_outbuf(uint16_t szbytes)
{
uint16_t i;
- static uint16_t offset, size;
+ uint16_t offset, size;
+
offset = SHI_OBUF_VALID_OFFSET;
- shi_params.tx_buf = SHI_OBUF_START_ADDR + offset;
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ /*
+ * If response package is across 256 bytes boundary,
+ * bypass needs to extend PROCESSING bytes after reaching the boundary.
+ */
+ if (shi_params.bytes_in_256b + offset + szbytes > SHI_BYPASS_BOUNDARY) {
+ state = SHI_STATE_WAIT_ALIGNMENT;
+ /* Set pointer of output buffer to the start address */
+ shi_params.tx_buf = SHI_OBUF_START_ADDR;
+ DEBUG_CPRINTF("WAT-");
+ return;
+ }
+#endif
+
+ shi_params.tx_buf = SHI_OBUF_START_ADDR + offset;
/* Fill half output buffer */
size = MIN(SHI_OBUF_HALF_SIZE - (offset % SHI_OBUF_HALF_SIZE),
szbytes - shi_params.sz_sending);
@@ -353,25 +460,6 @@ static void shi_read_half_inbuf(void)
}
/*
- * This routine make sure input buffer status register is valid or it will
- * return flase after timeout
- */
-static int shi_check_inbuf_valid(void)
-{
- timestamp_t deadline = get_time();
- deadline.val += SHI_GLITCH_TIMEOUT_US;
- /*
- * If input buffer pointer is no changed after timeout, it will
- * return false
- */
- while (NPCX_IBUFSTAT == shi_params.pre_ibufstat)
- if (timestamp_expired(deadline, NULL))
- return 0;
- /* valid package */
- return 1;
-}
-
-/*
* This routine read SHI input buffer to msg buffer until
* we have received a certain number of bytes
*/
@@ -394,26 +482,26 @@ static int shi_read_inbuf_wait(uint16_t szbytes)
return 1;
}
-/* This routine handles bus error condition */
-static void shi_error(int need_reset)
+/* This routine handles shi recevied unexcepted data */
+static void shi_bad_received_data(void)
{
uint16_t i;
+
/* State machine mismatch, timeout, or protocol we can't handle. */
shi_fill_out_status(EC_SPI_RX_BAD_DATA);
- state = SHI_STATE_ERROR;
+ state = SHI_STATE_BAD_RECEIVED_DATA;
- CPRINTS("ERR-[");
+ CPRINTS("BAD-");
CPRINTF("in_msg=[");
for (i = 0; i < shi_params.sz_received; i++)
CPRINTF("%02x ", in_msg[i]);
CPRINTF("]\n");
/*
- * If glitch occurred or losing clocks, EVSTAT_EOR/W
- * will not generate. We need to reset SHI bus here.
+ * Enable SHI interrupt again since we disable it
+ * at the begin of SHI_STATE_RECEIVING state
*/
- if (need_reset)
- shi_reset_prepare();
+ task_enable_irq(NPCX_IRQ_SHI);
}
/* This routine handles all interrupts of this module */
@@ -430,27 +518,33 @@ void shi_int_handler(void)
* Host completed or aborted transaction
*/
if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_EOR)) {
- /* Already reset in shi_error or not */
- if (state != SHI_STATE_READY_TO_RECV)
- /*
- * Mark not ready to prevent the other
- * transaction immediately
- */
- NPCX_OBUF(0) = EC_SPI_NOT_READY;
+ /*
+ * We're not in proper state.
+ * Mark not ready to abort next transaction
+ */
DEBUG_CPRINTF("CSH-");
/*
* If the buffer is still used by the host command.
- * Change tx buffer to NOT_READY
+ * Change state machine for response handler.
*/
if (state == SHI_STATE_PROCESSING) {
/*
- * Mark state to NOT_READY for waiting host executes
- * response function
+ * Mark not ready to prevent the other
+ * transaction immediately
*/
- state = SHI_STATE_NOT_READY;
- DEBUG_CPRINTF("WAIT-");
+ shi_fill_out_status(EC_SPI_NOT_READY);
+
+ state = SHI_STATE_CNL_RESP_NOT_RDY;
+ DEBUG_CPRINTF("CNL-");
return;
- }
+ /* Next transaction but we're not ready */
+ } else if (state == SHI_STATE_CNL_RESP_NOT_RDY)
+ return;
+
+ /* Error state for checking*/
+ if (state != SHI_STATE_SENDING)
+ CPRINTS("Unexpected state %d in IBEOR ISR\n", state);
+
/* reset SHI and prepare to next transaction again */
shi_reset_prepare();
DEBUG_CPRINTF("END\n");
@@ -467,16 +561,34 @@ void shi_int_handler(void)
shi_read_half_inbuf();
return shi_handle_host_package();
} else if (state == SHI_STATE_SENDING) {
- /* Write data from bottom address again */
- shi_params.tx_buf = SHI_OBUF_START_ADDR;
/* Write data from msg buffer to output buffer */
- return shi_write_half_outbuf();
+ if (shi_params.tx_buf == SHI_OBUF_START_ADDR +
+ SHI_OBUF_FULL_SIZE) {
+ /* Write data from bottom address again */
+ shi_params.tx_buf = SHI_OBUF_START_ADDR;
+ return shi_write_half_outbuf();
+ } else /* ignore it */
+ return;
} else if (state == SHI_STATE_PROCESSING)
/* Wait for host handles request */
return;
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ else if (state == SHI_STATE_WAIT_ALIGNMENT) {
+ /*
+ * If pointer of output buffer will reach 256 bytes
+ * boundary soon, start to fill response data.
+ */
+ if (shi_params.bytes_in_256b == SHI_BYPASS_BOUNDARY -
+ SHI_OBUF_FULL_SIZE) {
+ state = SHI_STATE_SENDING;
+ DEBUG_CPRINTF("SND-");
+ return shi_write_half_outbuf();
+ }
+ }
+#endif
else
/* Unexpected status */
- return shi_error(1);
+ CPRINTS("Unexpected state %d in IBHF ISR\n", state);
}
/*
@@ -484,6 +596,11 @@ void shi_int_handler(void)
* Transaction is processing.
*/
if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_IBF)) {
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ /* Record the sent bytes within 256B boundary */
+ shi_params.bytes_in_256b = (shi_params.bytes_in_256b +
+ SHI_OBUF_FULL_SIZE) % SHI_BYPASS_BOUNDARY;
+#endif
if (state == SHI_STATE_RECEIVING) {
/* read data from input to msg buffer */
shi_read_half_inbuf();
@@ -492,13 +609,21 @@ void shi_int_handler(void)
return shi_handle_host_package();
} else if (state == SHI_STATE_SENDING)
/* Write data from msg buffer to output buffer */
- return shi_write_half_outbuf();
- else if (state == SHI_STATE_PROCESSING)
+ if (shi_params.tx_buf == SHI_OBUF_START_ADDR +
+ SHI_OBUF_HALF_SIZE)
+ return shi_write_half_outbuf();
+ else /* ignore it */
+ return;
+ else if (state == SHI_STATE_PROCESSING
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ || state == SHI_STATE_WAIT_ALIGNMENT
+#endif
+ )
/* Wait for host handles request */
return;
else
/* Unexpected status */
- return shi_error(1);
+ CPRINTS("Unexpected state %d in IBF ISR\n", state);
}
}
/*
@@ -515,50 +640,29 @@ void shi_cs_event(enum gpio_signal signal)
return;
/*
- * TODO (ML): Glitches on SHI_CS_L will cause SHI doesn`t generate
- * 'End of data for read/write transaction interrupt' and IBUFSTAT will
- * keep previous value without clocks. (Workaround) Need to reset it
- * manually in CS assert ISR.
+ * IBUFSTAT resets on the 7th clock cycle after CS assertion, which
+ * may not have happened yet. We use NPCX_IBUFSTAT for calculating
+ * buffer fill depth, so make sure it's valid before proceeding.
*/
- if (NPCX_IBUFSTAT == shi_params.pre_ibufstat) {
- if (!shi_check_inbuf_valid()) {
- CPRINTS("ERR-GTH");
- shi_reset_prepare();
- CPRINTS("END\n");
- return;
- }
+ if (shi_is_cs_glitch()) {
+ CPRINTS("ERR-GTH");
+ shi_reset_prepare();
+ DEBUG_CPRINTF("END\n");
+ return;
}
+ /* NOT_READY should be sent and there're no spi transaction now. */
+ if (state == SHI_STATE_CNL_RESP_NOT_RDY)
+ return;
+
/* Chip select is low = asserted */
if (state != SHI_STATE_READY_TO_RECV) {
- /*
- * AP started a transaction but we weren't ready for it.
- * Tell AP we weren't ready, and ignore the received data.
- * The driver should change status later when complete handling
- * response from host
- */
- NPCX_OBUF(0) = EC_SPI_NOT_READY;
- CPRINTS("CSL-NRDY");
- /*
- * If status still is error, reset SHI Bus and
- * abort this transaction.
- */
- if (state == SHI_STATE_ERROR) {
- CPRINTS("ERR-");
- shi_reset_prepare();
- CPRINTS("END\n");
- return;
- }
+ /* State machine should be reset in EVSTAT_EOR ISR */
+ CPRINTS("Unexpected state %d in CS ISR\n", state);
return;
}
- /* We're now inside a transaction */
- state = SHI_STATE_RECEIVING;
- DEBUG_CPRINTF("CSL-RV-");
-
- /* Setup deadline time for receiving */
- shi_params.rx_deadline = get_time();
- shi_params.rx_deadline.val += SHI_CMD_RX_TIMEOUT_US;
+ DEBUG_CPRINTF("CSL-");
/* Read first three bytes to parse which protocol is receiving */
shi_parse_header();
@@ -567,11 +671,13 @@ void shi_cs_event(enum gpio_signal signal)
/*****************************************************************************/
/* Hook functions for chipset and initialization */
-/* Reset SHI bus and prepare next transaction */
+/*
+ * Reset SHI bus and prepare next transaction
+ * Please make sure it is executed when there're no spi transactions
+ */
static void shi_reset_prepare(void)
{
uint16_t i;
- state = SHI_STATE_NOT_READY;
/* Initialize parameters of next transaction */
shi_params.rx_msg = in_msg;
@@ -582,12 +688,15 @@ static void shi_reset_prepare(void)
shi_params.sz_sending = 0;
shi_params.sz_request = 0;
shi_params.sz_response = 0;
+#ifdef NPCX_SHI_BYPASS_OVER_256B
+ shi_params.bytes_in_256b = 0;
+#endif
/* Record last IBUFSTAT for glitch case */
shi_params.pre_ibufstat = NPCX_IBUFSTAT;
/*
* Fill output buffer to indicate we`re
- * ready to receive next transaction
+ * ready to receive next transaction.
*/
for (i = 1; i < SHI_OBUF_FULL_SIZE; i++)
NPCX_OBUF(i) = EC_SPI_RECEIVING;
@@ -695,7 +804,8 @@ static void shi_init(void)
#if !(DEBUG_SHI)
if (chipset_in_state(CHIPSET_STATE_ON))
#endif
- shi_reset_prepare();
+ shi_enable();
+
}
DECLARE_HOOK(HOOK_INIT, shi_init, HOOK_PRIO_DEFAULT);