diff options
Diffstat (limited to 'chip/g/gpio.c')
-rw-r--r-- | chip/g/gpio.c | 44 |
1 files changed, 44 insertions, 0 deletions
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, |