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