diff options
author | tim <tim2.lin@ite.corp-partner.google.com> | 2020-03-31 14:42:58 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-04-02 09:25:58 +0000 |
commit | 7dfdde8b60d02a350111552842db758fa1391307 (patch) | |
tree | 67b91d0632db631e833a8b701732028f80743c24 | |
parent | 34dfe4c7df343eb656955c8f0ab230c1b450d7e7 (diff) | |
download | chrome-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.h | 2 | ||||
-rw-r--r-- | chip/it83xx/registers.h | 4 | ||||
-rw-r--r-- | chip/it83xx/spi.c | 146 |
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); |