summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
Diffstat (limited to 'board')
-rw-r--r--board/cr50/board.c12
-rw-r--r--board/cr50/board.h7
-rw-r--r--board/cr50/power_button.c35
3 files changed, 54 insertions, 0 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 30e8fc8791..f9b36d8eed 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -943,10 +943,22 @@ void assert_ec_rst(void)
if (uart_bitbang_is_enabled())
task_disable_irq(bitbang_config.rx_irq);
+ /*
+ * If ec_rst was explicitly asserted, then do not let
+ * "power button release" deassert it if set earlier to do so.
+ */
+ power_button_release_enable_interrupt(0);
+
GWRITE(RBOX, ASSERT_EC_RST, 1);
}
void deassert_ec_rst(void)
{
+ /*
+ * If ec_rst was explicitly deasserted, then do not let
+ * "power button release" deassert it again if set earlier to do so.
+ */
+ power_button_release_enable_interrupt(0);
+
GWRITE(RBOX, ASSERT_EC_RST, 0);
if (uart_bitbang_is_enabled())
diff --git a/board/cr50/board.h b/board/cr50/board.h
index 140f230d02..9e8da8acb1 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -269,6 +269,13 @@ int board_deep_sleep_allowed(void);
void power_button_record(void);
+/**
+ * Enable/disable power button release interrupt.
+ *
+ * @param enable Enable (!=0) or disable (==0)
+ */
+void power_button_release_enable_interrupt(int enable);
+
/* Functions needed by CCD config */
int board_battery_is_present(void);
int board_fwmp_allows_unlock(void);
diff --git a/board/cr50/power_button.c b/board/cr50/power_button.c
index 96b3bb7774..efa402259a 100644
--- a/board/cr50/power_button.c
+++ b/board/cr50/power_button.c
@@ -17,6 +17,23 @@
#define CPRINTS(format, args...) cprints(CC_RBOX, format, ## args)
#define CPRINTF(format, args...) cprintf(CC_RBOX, format, ## args)
+DECLARE_DEFERRED(deassert_ec_rst);
+
+void power_button_release_enable_interrupt(int enable)
+{
+ /* Clear any leftover power button rising edge detection interrupts */
+ GWRITE_FIELD(RBOX, INT_STATE, INTR_PWRB_IN_RED, 1);
+
+ if (enable) {
+ /* Enable power button rising edge detection interrupt */
+ GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_RED, 1);
+ task_enable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_RED_INT);
+ } else {
+ GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_RED, 0);
+ task_disable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_RED_INT);
+ }
+}
+
/**
* Enable/disable power button interrupt.
*
@@ -53,6 +70,24 @@ static void power_button_handler(void)
}
DECLARE_IRQ(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT, power_button_handler, 1);
+static void power_button_release_handler(void)
+{
+#ifdef CR50_DEV
+ CPRINTS("power button released");
+#endif
+
+ /*
+ * Let deassert_ec_rst be called deferred rather than
+ * by interrupt handler.
+ */
+ hook_call_deferred(&deassert_ec_rst_data, 0);
+
+ /* Note that this is for one-time use through the current power on. */
+ power_button_release_enable_interrupt(0);
+}
+DECLARE_IRQ(GC_IRQNUM_RBOX0_INTR_PWRB_IN_RED_INT, power_button_release_handler,
+ 1);
+
#ifdef CONFIG_U2F
static void power_button_init(void)
{