diff options
author | Mary Ruthven <mruthven@chromium.org> | 2017-06-05 20:24:10 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-02-07 23:09:55 +0000 |
commit | 341cc2da402e23dc9ff09072058f79d5ec0c40c6 (patch) | |
tree | 512c995b1c86a6d1dc3bff45eeb58bc6e483b4e4 | |
parent | ca4bec7b0eab93cc3a0ccd5437e96f650c0274d5 (diff) | |
download | chrome-ec-341cc2da402e23dc9ff09072058f79d5ec0c40c6.tar.gz |
g: add gpio_set_wakepin() to configure wake pins
Cr50 needs a cleaner way to enable and disable wakepins. This change
adds gpio_set_wakepin() to enable the wake pin or disable.
The gpio_set_flags() or gpio_set_flags_by_mask() remain unaffecting
wake-pin configuration.
This patch increases the flash usage by 16 bytes.
BUG=b:35587259
BRANCH=cr50
TEST=verify pinmux has the same output before and after the change on
octopus.
Signed-off-by: Mary Ruthven <mruthven@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/533674
Tested-by: Namyoon Woo <namyoon@chromium.org>
Reviewed-by: Namyoon Woo <namyoon@chromium.org>
Commit-Queue: Namyoon Woo <namyoon@chromium.org>
Change-Id: I0387c673aedc046ce9cf6b5f0d683c40f3079281
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2044355
-rw-r--r-- | chip/g/gpio.c | 99 | ||||
-rw-r--r-- | common/gpio.c | 6 | ||||
-rw-r--r-- | include/gpio.h | 20 |
3 files changed, 104 insertions, 21 deletions
diff --git a/chip/g/gpio.c b/chip/g/gpio.c index d8ebe42d0d..f55e0fad35 100644 --- a/chip/g/gpio.c +++ b/chip/g/gpio.c @@ -51,6 +51,34 @@ void gpio_set_level(enum gpio_signal signal, int value) set_one_gpio_bit(g->port, g->mask, value); } +static void configure_wakepin(int bitmask, uint32_t flags) +{ + /* not VIOn ! */ + if (bitmask > GC_PINMUX_EXITEN0_DIOB7_MASK) + return; + + if (!(flags & DIO_WAKE_EN0)) { + /* Disable the pin */ + GREG32(PINMUX, EXITEN0) &= ~bitmask; + return; + } + + /* level (0) or edge sensitive (1) */ + if (flags & DIO_WAKE_EDGE0) + GREG32(PINMUX, EXITEDGE0) |= bitmask; + else + GREG32(PINMUX, EXITEDGE0) &= ~bitmask; + + /* high/rising (0) or low/falling (1) */ + if (flags & DIO_WAKE_INV0) + GREG32(PINMUX, EXITINV0) |= bitmask; + else + GREG32(PINMUX, EXITINV0) &= ~bitmask; + + /* Enable the pin */ + GREG32(PINMUX, EXITEN0) |= bitmask; +} + int gpio_get_flags_by_mask(uint32_t port, uint32_t mask) { uint32_t flags = 0; @@ -123,6 +151,50 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) /* No way to trigger on both rising and falling edges, darn it. */ } +void gpio_set_wakepin(enum gpio_signal signal, uint32_t flags) +{ + const struct gpio_info *g = gpio_list + signal; + const int gpio_bitnum = GPIO_MASK_TO_NUM(g->mask); + const int dio_val = GET_GPIO_SEL_REG(g->port, gpio_bitnum); + int dio_mask; + int dio_wake_flags; + + /* Can't do anything if the gpio is not connected to a pin */ + if (!dio_val) + return; + + /* Convert the gpio wake flags to the dio wake pin configuration */ + flags &= GPIO_HIB_WAKE_MASK; + switch (flags) { + case 0: /* Disable Wakepin */ + dio_wake_flags = 0; + break; + case GPIO_HIB_WAKE_HIGH: + dio_wake_flags = DIO_WAKE_HIGH; + break; + case GPIO_HIB_WAKE_LOW: + dio_wake_flags = DIO_WAKE_LOW; + break; + case GPIO_HIB_WAKE_RISING: + dio_wake_flags = DIO_WAKE_RISING; + break; + case GPIO_HIB_WAKE_FALLING: + dio_wake_flags = DIO_WAKE_FALLING; + break; + default: + /* Wake contions cannot be more than one. */ + return; + } + + /* + * GC_PINMUX_{PIN}_SEL values start from 0x1e (DIOM0) + * down to 0x03 (DIOB7). Meanwhile, GC_PINMUX_{wake_cond}_{pin}_MASK + * has BIT(0) for DIOM0 and BIT(27) for DIOB7. + */ + dio_mask = 1 << (GC_PINMUX_DIOM0_SEL - dio_val); + configure_wakepin(dio_mask, dio_wake_flags); +} + void gpio_set_alternate_function(uint32_t port, uint32_t mask, enum gpio_alternate_func func) { @@ -231,7 +303,6 @@ static int connect_dio_to_gpio(struct pinmux const *p) static void connect_pinmux(struct pinmux const *p) { - uint32_t bitmask; int is_input; if (p->flags & DIO_ENABLE_DIRECT_INPUT) { @@ -265,24 +336,14 @@ static void connect_pinmux(struct pinmux const *p) DIO_CTL_PD_LSB, 1); /* Enable any wake pins needed to exit low-power modes */ - if ((p->flags & DIO_WAKE_EN0) && - (p->dio.offset <= GC_PINMUX_DIOB7_SEL_OFFSET)) { /* not VIOn ! */ - bitmask = (1 << (p->dio.offset / 8)); - - /* enable pad as wake source */ - GREG32(PINMUX, EXITEN0) |= bitmask; - - /* level (0) or edge sensitive (1) */ - if (p->flags & DIO_WAKE_EDGE0) - GREG32(PINMUX, EXITEDGE0) |= bitmask; - else - GREG32(PINMUX, EXITEDGE0) &= ~bitmask; - - /* high/rising (0) or low/falling (1) */ - if (p->flags & DIO_WAKE_INV0) - GREG32(PINMUX, EXITINV0) |= bitmask; - else - GREG32(PINMUX, EXITINV0) &= ~bitmask; + if (p->flags & DIO_WAKE_EN0) { + /* + * p->dio.offset is the offset of GC_PINMUX_*_SEL register. + * The next GC_PINMUX_*_SEL register is 8 byte away. + */ + const uint32_t dio_mask = (1 << (p->dio.offset / 8)); + + configure_wakepin(dio_mask, p->flags); } } diff --git a/common/gpio.c b/common/gpio.c index 69aae0572e..c59065a60c 100644 --- a/common/gpio.c +++ b/common/gpio.c @@ -218,4 +218,10 @@ int signal_is_gpio(int signal) && (signal < GPIO_SIGNAL_START + GPIO_COUNT)); } +__attribute__((weak)) void gpio_set_wakepin(enum gpio_signal signal, + uint32_t flags) +{ + /* Some chips may need their own implementations */ +} + /*****************************************************************************/ diff --git a/include/gpio.h b/include/gpio.h index 61329ad758..e1957813e0 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -34,9 +34,12 @@ #define GPIO_SEL_1P8V BIT(16) /* Support 1.8v */ #define GPIO_ALTERNATE BIT(17) /* GPIO used for alternate function. */ #define GPIO_LOCKED BIT(18) /* Lock GPIO output and configuration */ -#define GPIO_HIB_WAKE_HIGH BIT(19) /* Hibernate wake on high level */ +#define GPIO_HIB_WAKE_HIGH BIT(19) /* Hibernate wake on high level */ +#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 */ #ifdef CONFIG_GPIO_POWER_DOWN -#define GPIO_POWER_DOWN BIT(20) /* Pin and pad is powered off */ +#define GPIO_POWER_DOWN BIT(23) /* Pin and pad is powered off */ #endif /* Common flag combinations */ @@ -53,6 +56,8 @@ #define GPIO_INT_LEVEL (GPIO_INT_LOW | GPIO_INT_HIGH) #define GPIO_INT_ANY (GPIO_INT_BOTH | GPIO_INT_LEVEL) #define GPIO_INT_BOTH_DSLEEP (GPIO_INT_BOTH | GPIO_INT_DSLEEP) +#define GPIO_HIB_WAKE_MASK (GPIO_HIB_WAKE_HIGH | GPIO_HIB_WAKE_LOW | \ + GPIO_HIB_WAKE_RISING|GPIO_HIB_WAKE_FALLING) /* Convert GPIO mask to GPIO number / index. */ #define GPIO_MASK_TO_NUM(mask) (__fls(mask)) @@ -343,4 +348,15 @@ int gpio_power_down_module(enum module_id id); */ int signal_is_gpio(int signal); +/** + * Configure a GPIO as wake source on a given condition and enable it, or + * disable it. + * + * @param signal GPIO to enable to wake Cr50 up + * @param flags Wake condition. Should be one among + * GPIO_HIB_WAKE_{HIGH, LOW, RISING, FALLING} to enable it + * as a wake pin. 0 to disable it. + */ +void gpio_set_wakepin(enum gpio_signal signal, uint32_t flags); + #endif /* __CROS_EC_GPIO_H */ |