diff options
-rw-r--r-- | board/cr50/board.c | 6 | ||||
-rw-r--r-- | board/cr50/board.h | 2 | ||||
-rw-r--r-- | board/cr50/gpio.inc | 3 | ||||
-rw-r--r-- | chip/g/gpio.c | 44 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/gpio.h | 7 | ||||
-rw-r--r-- | include/system.h | 2 |
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 */ |