summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/board.c6
-rw-r--r--board/cr50/board.h2
-rw-r--r--board/cr50/gpio.inc3
-rw-r--r--chip/g/gpio.c44
-rw-r--r--include/config.h3
-rw-r--r--include/gpio.h7
-rw-r--r--include/system.h2
7 files changed, 62 insertions, 5 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index c5c88f82f2..bc19800758 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -593,9 +593,9 @@ DECLARE_IRQ(GC_IRQNUM_PMU_INTR_WAKEUP_INT, pmu_wakeup_interrupt, 1);
void board_configure_deep_sleep_wakepins(void)
{
/*
- * Eventually asserting AP_FLASH_SELECT will disable deep sleep. Until
- * that's enabled make sure cr50 doesn't enter deep sleep with
- * AP_FLASH_SELECT asserted.
+ * The AP_FLASH_SELECT gpio disables sleep when it's asserted, so it
+ * shouldn't be possible to get here with it asserted.
+ * Deassert it just to be safe.
*/
if (board_has_ec_cr50_comm_support())
gpio_set_level(GPIO_AP_FLASH_SELECT, 0);
diff --git a/board/cr50/board.h b/board/cr50/board.h
index a0586256d8..828b2d7d3d 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -48,6 +48,8 @@
/* Enable getting gpio flags to tell if open drain pins are asserted */
#define CONFIG_GPIO_GET_EXTENDED
+/* Disable sleep when gpios with GPIO_SLEEP_DIS flags are asserted. */
+#define CONFIG_GPIO_DISABLE_SLEEP
/* Flash configuration */
#undef CONFIG_FLASH_PSTATE
diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc
index 12ed576291..d224189042 100644
--- a/board/cr50/gpio.inc
+++ b/board/cr50/gpio.inc
@@ -154,8 +154,9 @@ GPIO(EC_FLASH_SELECT, PIN(0, 1), GPIO_OUT_LOW)
/*
* If this gpio is changed, you must update the AP_FLASH_SELECT pinmux
* setup in board.c accordingly.
+ * Disable sleep when the signal is set high.
*/
-GPIO(AP_FLASH_SELECT, PIN(0, 2), GPIO_OUT_LOW)
+GPIO(AP_FLASH_SELECT, PIN(0, 2), GPIO_OUT_LOW | GPIO_SLEEP_DIS_HIGH)
/*
* Pull this low to reset the AP. (We reset the EC with the RBOX.)
diff --git a/chip/g/gpio.c b/chip/g/gpio.c
index 3704d1b1bf..b37588453f 100644
--- a/chip/g/gpio.c
+++ b/chip/g/gpio.c
@@ -8,6 +8,7 @@
#include "gpio.h"
#include "hooks.h"
#include "registers.h"
+#include "system.h"
#include "task.h"
/*
@@ -35,10 +36,51 @@ static void set_one_gpio_bit(uint32_t port, uint16_t mask, int value)
GR_GPIO_MASKHIGHBYTE(port, mask >> 8) = value ? mask : 0;
}
+static uint32_t gpio_sleepmask;
+
+static void gpio_control_sleep(enum gpio_signal signal, int enable)
+{
+#ifdef CONFIG_GPIO_DISABLE_SLEEP
+ uint32_t signal_mask;
+
+ /* There are only 32 gpios, so this shouldn't be possible. */
+ if (signal > 31)
+ return;
+
+ signal_mask = BIT(signal);
+
+ if (enable) {
+ gpio_sleepmask |= signal_mask;
+ disable_sleep(SLEEP_MASK_GPIO);
+ return;
+ }
+ if (!(gpio_sleepmask & signal_mask))
+ return;
+
+ gpio_sleepmask &= ~signal_mask;
+ if (gpio_sleepmask)
+ return;
+
+ /* The last gpio disabling sleep was deasserted. Reenable sleep. */
+ enable_sleep(SLEEP_MASK_GPIO);
+ /*
+ * Give extra time for activity to finish up. These signals are rarely
+ * asserted, so 10 seconds won't affect normal activity.
+ */
+ delay_sleep_by(10 * SECOND);
+#endif /* CONFIG_GPIO_DISABLE_SLEEP */
+}
+
void gpio_set_level(enum gpio_signal signal, int value)
{
const struct gpio_info *g = gpio_list + signal;
+ if (g->flags & GPIO_OUTPUT) {
+ if (g->flags & GPIO_SLEEP_DIS_HIGH)
+ gpio_control_sleep(signal, value);
+ else if (g->flags & GPIO_SLEEP_DIS_LOW)
+ gpio_control_sleep(signal, !value);
+ }
if (g->flags & GPIO_OPEN_DRAIN) {
if (value) {
GR_GPIO_CLRDOUTEN(g->port) = g->mask;
@@ -614,6 +656,8 @@ static int command_gpiocfg(int argc, char **argv)
show_gpiocfg(0);
show_gpiocfg(1);
+ ccprintf("\ngpio sleepmask: %08x\n", gpio_sleepmask);
+
return EC_SUCCESS;
}
DECLARE_SAFE_CONSOLE_COMMAND(gpiocfg, command_gpiocfg,
diff --git a/include/config.h b/include/config.h
index b37144331f..f48a640d68 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1807,6 +1807,9 @@
/* Support getting gpio flags. */
#undef CONFIG_GPIO_GET_EXTENDED
+/* Support disabling sleep with GPIO flags. */
+#undef CONFIG_GPIO_DISABLE_SLEEP
+
/* Do we want to detect the lid angle? */
#undef CONFIG_LID_ANGLE
diff --git a/include/gpio.h b/include/gpio.h
index b0291b40f1..07d46dd055 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -37,6 +37,13 @@
#define GPIO_HIB_WAKE_LOW BIT(20) /* Hibernate wake on low level */
#define GPIO_HIB_WAKE_RISING BIT(21) /* Hibernate wake on rising edge */
#define GPIO_HIB_WAKE_FALLING BIT(22) /* Hibernate wake on falling edge */
+/*
+ * The SLEEP_DIS flags disable sleep when they're asserted. They disable regular
+ * and deep sleep, so they shouldn't be asserted as a part of normal operation.
+ * These flags should ONLY be used on debug signals.
+ */
+#define GPIO_SLEEP_DIS_LOW BIT(23) /* Disable sleep when set to 0. */
+#define GPIO_SLEEP_DIS_HIGH BIT(24) /* Disable sleep when set to 1. */
/* Common flag combinations */
#define GPIO_OUT_LOW (GPIO_OUTPUT | GPIO_LOW)
diff --git a/include/system.h b/include/system.h
index 9826dfa17f..49a85e6eb9 100644
--- a/include/system.h
+++ b/include/system.h
@@ -359,7 +359,7 @@ enum {
SLEEP_MASK_UART = BIT(1), /* UART communication ongoing */
SLEEP_MASK_I2C_CONTROLLER
= BIT(2), /* I2C communication ongoing */
- SLEEP_MASK_CHARGING = BIT(3), /* Charging loop ongoing */
+ SLEEP_MASK_GPIO = BIT(3), /* GPIO activity ongoing */
SLEEP_MASK_USB_PWR = BIT(4), /* USB power loop ongoing */
SLEEP_MASK_USB_PD = BIT(5), /* USB PD device connected */
SLEEP_MASK_SPI = BIT(6), /* SPI communications ongoing */