summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortim <tim2.lin@ite.corp-partner.google.com>2020-03-31 14:42:58 +0800
committerCommit Bot <commit-bot@chromium.org>2020-04-02 09:25:58 +0000
commit7dfdde8b60d02a350111552842db758fa1391307 (patch)
tree67b91d0632db631e833a8b701732028f80743c24
parent34dfe4c7df343eb656955c8f0ab230c1b450d7e7 (diff)
downloadchrome-ec-7dfdde8b60d02a350111552842db758fa1391307.tar.gz
it83xx/spi: enable auto reset rx fifo function
In this change, we enable IT83XX_SPI_AUTO_RESET_RX_FIFO. When CS# deasserted, the rx fifo and fifo count can auto reset in time by the hardware way to avoid the time delay caused. And we removed the spi_chipset_startup and shutdown. we don't need to disable the interrupt of GPIO_SPI0_CS via hook during chipset suspend and enable it during chipset resume. Instead, when the interrupt of GPIO_SPI0_CS occurs, we judge whether the chipset state is enabled and then to disable deep sleep. BUG=none BRANCH=none TEST=boot to kernel with it81202 on elm board. Press the button to shutdown and resume testing 10 times are normal. Signed-off-by: tim <tim2.lin@ite.corp-partner.google.com> Change-Id: I263d63fa5c22ef430d8f807c694317b7496f238f Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2100372 Reviewed-by: Jett Rink <jettrink@chromium.org> Commit-Queue: Dino Li <Dino.Li@ite.com.tw>
-rw-r--r--chip/it83xx/config_chip_it8xxx2.h2
-rw-r--r--chip/it83xx/registers.h4
-rw-r--r--chip/it83xx/spi.c146
3 files changed, 69 insertions, 83 deletions
diff --git a/chip/it83xx/config_chip_it8xxx2.h b/chip/it83xx/config_chip_it8xxx2.h
index b1a620895a..d9c351e760 100644
--- a/chip/it83xx/config_chip_it8xxx2.h
+++ b/chip/it83xx/config_chip_it8xxx2.h
@@ -109,6 +109,8 @@
#define IT83XX_INTC_PLUG_IN_SUPPORT
/* Wake up CPU from low power mode even if interrupts are disabled */
#define IT83XX_RISCV_WAKEUP_CPU_WITHOUT_INT_ENABLED
+/* Auto reset rx fifo while CS# deasserted. */
+#define IT83XX_SPI_AUTO_RESET_RX_FIFO
/* Individual setting CC1 and CC2 resistance. */
#define IT83XX_USBPD_CC1_CC2_RESISTANCE_SEPARATE
/* Chip actually has TCPC physical port count. */
diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h
index 8eb7d20cb8..febf5093c9 100644
--- a/chip/it83xx/registers.h
+++ b/chip/it83xx/registers.h
@@ -1288,6 +1288,10 @@ REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 5 : 8) + (ch << 4))
#define IT83XX_SPI_TXFCMR BIT(2)
#define IT83XX_SPI_TXFR BIT(1)
#define IT83XX_SPI_TXFS BIT(0)
+#define IT83XX_SPI_GCR2 REG8(IT83XX_SPI_BASE+0x03)
+#define IT83XX_SPI_RXF2OC BIT(4)
+#define IT83XX_SPI_RXF1OC BIT(3)
+#define IT83XX_SPI_RXFAR BIT(0)
#define IT83XX_SPI_IMR REG8(IT83XX_SPI_BASE+0x04)
#define IT83XX_SPI_RFFIM BIT(7)
#define IT83XX_SPI_EDIM BIT(2)
diff --git a/chip/it83xx/spi.c b/chip/it83xx/spi.c
index a187243413..3c3e323a7e 100644
--- a/chip/it83xx/spi.c
+++ b/chip/it83xx/spi.c
@@ -49,8 +49,6 @@ static uint8_t out_msg[SPI_TX_MAX_FIFO_SIZE] __aligned(4);
static struct host_packet spi_packet;
enum spi_slave_state_machine {
- /* SPI not enabled */
- SPI_STATE_DISABLED,
/* Ready to receive next request */
SPI_STATE_READY_TO_RECV,
/* Receiving request */
@@ -64,7 +62,6 @@ enum spi_slave_state_machine {
} spi_slv_state;
static const int spi_response_state[] = {
- [SPI_STATE_DISABLED] = EC_SPI_NOT_READY,
[SPI_STATE_READY_TO_RECV] = EC_SPI_OLD_READY,
[SPI_STATE_RECEIVING] = EC_SPI_RECEIVING,
[SPI_STATE_PROCESSING] = EC_SPI_PROCESSING,
@@ -86,8 +83,6 @@ static void reset_rx_fifo(void)
IT83XX_SPI_TXRXFAR = 0x00;
/* Rx FIFO reset and count monitor reset */
IT83XX_SPI_FCR = IT83XX_SPI_RXFR | IT83XX_SPI_RXFCMR;
- /* Enable Rx FIFO full interrupt */
- IT83XX_SPI_IMR &= ~IT83XX_SPI_RFFIM;
}
/* This routine handles spi received unexcepted data */
@@ -228,21 +223,39 @@ static void spi_parse_header(void)
void spi_event(enum gpio_signal signal)
{
- /* If SPI slave is not enabled */
- if (spi_slv_state == SPI_STATE_DISABLED)
- return;
-
- /* EC has started receiving the request from the AP */
- spi_set_state(SPI_STATE_RECEIVING);
-
- /* Disable idle task deep sleep bit of SPI in S0. */
- disable_sleep(SLEEP_MASK_SPI);
+ if (chipset_in_state(CHIPSET_STATE_ON)) {
+ /* EC has started receiving the request from the AP */
+ spi_set_state(SPI_STATE_RECEIVING);
+ /* Disable idle task deep sleep bit of SPI in S0. */
+ disable_sleep(SLEEP_MASK_SPI);
+ }
}
void spi_slv_int_handler(void)
{
- /* Interrupt status register */
- int spi_status = IT83XX_SPI_ISR;
+ /*
+ * The status of SPI end detection interrupt bit is set, it
+ * means that host command parse has been completed and AP
+ * has received the last byte which is EC_SPI_PAST_END from
+ * EC responded data, then AP ended the transaction.
+ */
+ if (IT83XX_SPI_ISR & IT83XX_SPI_ENDDETECTINT) {
+#ifndef IT83XX_SPI_AUTO_RESET_RX_FIFO
+ /* Reset fifo and prepare to receive next transaction */
+ reset_rx_fifo();
+#endif
+ /* Enable Rx FIFO full interrupt */
+ IT83XX_SPI_IMR &= ~IT83XX_SPI_RFFIM;
+ /* Ready to receive */
+ spi_set_state(SPI_STATE_READY_TO_RECV);
+ /*
+ * Once there is no SPI active, enable idle task deep
+ * sleep bit of SPI in S3 or lower.
+ */
+ enable_sleep(SLEEP_MASK_SPI);
+ /* CS# is deasserted, so write clear all slave status */
+ IT83XX_SPI_ISR = 0xff;
+ }
/*
* The status of Rx FIFO full interrupt bit is set,
@@ -254,78 +267,23 @@ void spi_slv_int_handler(void)
* generate clock that is not the bytes sent from
* the host.
*/
- if (spi_status & IT83XX_SPI_RXFIFOFULL &&
- spi_slv_state == SPI_STATE_RECEIVING) {
+ if (IT83XX_SPI_ISR & IT83XX_SPI_RXFIFOFULL) {
/* Disable Rx FIFO full interrupt */
IT83XX_SPI_IMR |= IT83XX_SPI_RFFIM;
+ /* write clear slave status */
+ IT83XX_SPI_ISR = IT83XX_SPI_RXFIFOFULL;
/* Parse header for version of spi-protocol */
spi_parse_header();
}
- /*
- * The status of SPI end detection interrupt bit is set,
- * the AP ended the transaction data.
- */
- if (spi_status & IT83XX_SPI_ENDDETECTINT) {
- /* Reset fifo and prepare to receive next transaction */
- reset_rx_fifo();
- /* Ready to receive */
- spi_set_state(SPI_STATE_READY_TO_RECV);
- /*
- * Once there is no SPI active, enable idle task deep
- * sleep bit of SPI in S3 or lower.
- */
- enable_sleep(SLEEP_MASK_SPI);
- }
- /* Write clear the slave status */
- IT83XX_SPI_ISR = spi_status;
/* Clear the interrupt status */
task_clear_pending_irq(IT83XX_IRQ_SPI_SLAVE);
}
-static void spi_chipset_startup(void)
+static void spi_init(void)
{
/* Set SPI pins to alternate function */
gpio_config_module(MODULE_SPI, 1);
- /* Reset fifo and prepare to for next transaction */
- reset_rx_fifo();
- /* Ready to receive */
- spi_set_state(SPI_STATE_READY_TO_RECV);
- /* Interrupt status register(write one to clear) */
- IT83XX_SPI_ISR = 0xff;
- /*
- * Interrupt mask register (0b:Enable, 1b:Mask)
- * bit7 : Rx FIFO full interrupt mask
- * bit2 : SPI end detection interrupt mask
- */
- IT83XX_SPI_IMR &= ~(IT83XX_SPI_RFFIM | IT83XX_SPI_EDIM);
- /* Enable SPI chip select pin interrupt */
- gpio_clear_pending_interrupt(GPIO_SPI0_CS);
- gpio_enable_interrupt(GPIO_SPI0_CS);
- /* Enable SPI slave interrupt */
- task_clear_pending_irq(IT83XX_IRQ_SPI_SLAVE);
- task_enable_irq(IT83XX_IRQ_SPI_SLAVE);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, spi_chipset_startup, HOOK_PRIO_FIRST);
-
-static void spi_chipset_shutdown(void)
-{
- /* SPI not enabled */
- spi_set_state(SPI_STATE_DISABLED);
- /* Disable SPI interrupt */
- gpio_disable_interrupt(GPIO_SPI0_CS);
- /* Set SPI pins to inputs so we don't leak power when AP is off */
- gpio_config_module(MODULE_SPI, 0);
- /*
- * Once there is no SPI active, enable idle task deep
- * sleep bit of SPI in S3 or lower.
- */
- enable_sleep(SLEEP_MASK_SPI);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, spi_chipset_shutdown, HOOK_PRIO_FIRST);
-
-static void spi_init(void)
-{
/*
* Memory controller configuration register 3.
* bit6 : SPI pin function select (0b:Enable, 1b:Mask)
@@ -338,14 +296,36 @@ static void spi_init(void)
IT83XX_SPI_FTCB0R = SPI_RX_MAX_FIFO_SIZE;
/* SPI slave controller enable */
IT83XX_SPI_SPISGCR = IT83XX_SPI_SPISCEN;
-
- if (system_jumped_to_this_image() &&
- chipset_in_state(CHIPSET_STATE_ON)) {
- spi_chipset_startup();
- } else {
- /* SPI not enabled */
- spi_set_state(SPI_STATE_DISABLED);
- }
+#ifdef IT83XX_SPI_AUTO_RESET_RX_FIFO
+ /*
+ * General control register2
+ * bit4 : Rx FIFO2 will not be overwrited once it's full.
+ * bit3 : Rx FIFO1 will not be overwrited once it's full.
+ * bit0 : Rx FIFO1/FIFO2 will reset after each CS_N goes high.
+ */
+ IT83XX_SPI_GCR2 = IT83XX_SPI_RXF2OC | IT83XX_SPI_RXF1OC
+ | IT83XX_SPI_RXFAR;
+#endif
+ /*
+ * Interrupt mask register (0b:Enable, 1b:Mask)
+ * bit7 : Rx FIFO full interrupt mask
+ * bit2 : SPI end detection interrupt mask
+ */
+ IT83XX_SPI_IMR &= ~IT83XX_SPI_EDIM;
+ /* Reset fifo and prepare to for next transaction */
+ reset_rx_fifo();
+ /* Enable Rx FIFO full interrupt */
+ IT83XX_SPI_IMR &= ~IT83XX_SPI_RFFIM;
+ /* Ready to receive */
+ spi_set_state(SPI_STATE_READY_TO_RECV);
+ /* Interrupt status register(write one to clear) */
+ IT83XX_SPI_ISR = 0xff;
+ /* Enable SPI slave interrupt */
+ task_clear_pending_irq(IT83XX_IRQ_SPI_SLAVE);
+ task_enable_irq(IT83XX_IRQ_SPI_SLAVE);
+ /* Enable SPI chip select pin interrupt */
+ gpio_clear_pending_interrupt(GPIO_SPI0_CS);
+ gpio_enable_interrupt(GPIO_SPI0_CS);
}
DECLARE_HOOK(HOOK_INIT, spi_init, HOOK_PRIO_INIT_SPI);