diff options
Diffstat (limited to 'chip/g/sps.c')
-rw-r--r-- | chip/g/sps.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/chip/g/sps.c b/chip/g/sps.c index 3a44a4fa0e..0387f8640e 100644 --- a/chip/g/sps.c +++ b/chip/g/sps.c @@ -12,7 +12,6 @@ #include "sps.h" #include "system.h" #include "task.h" -#include "timer.h" #include "watchdog.h" /* @@ -63,6 +62,8 @@ static uint32_t sps_tx_count, sps_rx_count, tx_empty_count, max_rx_batch; /* Flag indicating if there has been any data received while CS was asserted. */ static uint8_t seen_data; +static bool int_ap_extension_enabled_; + void sps_tx_status(uint8_t byte) { GREG32(SPS, DUMMY_WORD) = byte; @@ -212,6 +213,14 @@ static void sps_configure(enum sps_mode mode, enum spi_clock_mode clk_mode, GWRITE_FIELD(SPS, ICTRL, CS_DEASSERT, 1); } +static void enable_cs_assert_irq_(void) +{ + GWRITE_FIELD(SPS, ISTATE_CLR, CS_ASSERT, 1); + GWRITE_FIELD(SPS, ICTRL, CS_ASSERT, 1); + + task_enable_irq(GC_IRQNUM_SPS0_CS_ASSERT_INTR); +} + /* * Register and unregister rx_handler. Side effects of registering the handler * is reinitializing the interface. @@ -224,6 +233,11 @@ int sps_register_rx_handler(enum sps_mode mode, rx_handler_f rx_handler, task_disable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR); task_disable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR); + if (int_ap_extension_enabled_) { + task_disable_irq(GC_IRQNUM_SPS0_CS_ASSERT_INTR); + int_ap_extension_stop_pulse(); + } + if (!rx_handler) return 0; @@ -235,9 +249,20 @@ int sps_register_rx_handler(enum sps_mode mode, rx_handler_f rx_handler, task_enable_irq(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR); task_enable_irq(GC_IRQNUM_SPS0_CS_DEASSERT_INTR); + if (int_ap_extension_enabled_) + enable_cs_assert_irq_(); + return 0; } +/* Function that sets up for SPS to enable INT_AP_L extension. */ +static void sps_int_ap_extension_enable_(void) +{ + enable_cs_assert_irq_(); + + int_ap_extension_enabled_ = true; +} + static void sps_init(void) { /* @@ -257,6 +282,13 @@ static void sps_init(void) /* Configure the SPS_CS_L signal, DIOA12, as wake falling */ gpio_set_wakepin(GPIO_STRAP_B1, GPIO_HIB_WAKE_FALLING); + + int_ap_register(sps_int_ap_extension_enable_); + + /* + * TODO: if TPM_BOARD_CFG has INT_AP extension enabled, then call + * int_ap_extension_enable(). + */ } DECLARE_HOOK(HOOK_INIT, sps_init, HOOK_PRIO_DEFAULT); @@ -393,18 +425,19 @@ static void sps_cs_deassert_interrupt(uint32_t port) if (pulse_needed) { /* + * If assert_int_ap() returns 1, it generated a long + * pulse of INT_AP_L. Then, there is no need to generate + * a short pulse. + */ + if (assert_int_ap()) + return; + + /* * Signal the AP that this SPI frame processing is * completed. */ gpio_set_level(GPIO_INT_AP_L, 0); - /* - * This is to meet the AP requirement of minimum 4 usec - * duration of INT_AP_L assertion. - * - * TODO(b/130515803): Ideally, this should be improved - * to support any duration requirement in future. - */ tick_delay(2); gpio_set_level(GPIO_INT_AP_L, 1); @@ -423,6 +456,14 @@ void _sps0_cs_deassert_interrupt(void) DECLARE_IRQ(GC_IRQNUM_SPS0_CS_DEASSERT_INTR, _sps0_cs_deassert_interrupt, 1); DECLARE_IRQ(GC_IRQNUM_SPS0_RXFIFO_LVL_INTR, _sps0_interrupt, 1); +void sps0_cs_assert_interrupt_(void) +{ + GWRITE_FIELD(SPS, ISTATE_CLR, CS_ASSERT, 1); + + deassert_int_ap(); +} +DECLARE_IRQ(GC_IRQNUM_SPS0_CS_ASSERT_INTR, sps0_cs_assert_interrupt_, 1); + #ifdef CONFIG_SPS_TEST /* Function to test SPS driver. It expects the host to send SPI frames of size |