summaryrefslogtreecommitdiff
path: root/chip/g/sps.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/g/sps.c')
-rw-r--r--chip/g/sps.c57
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