From eb1d3ad5e8d77e9a925268ce048a27b6aea9da9e Mon Sep 17 00:00:00 2001 From: Mary Ruthven Date: Mon, 5 Jun 2017 20:24:10 -0700 Subject: 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. Change-Id: I0387c673aedc046ce9cf6b5f0d683c40f3079281 Signed-off-by: Mary Ruthven Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/533674 Tested-by: Namyoon Woo Reviewed-by: Namyoon Woo Commit-Queue: Namyoon Woo --- chip/g/gpio.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 19 deletions(-) (limited to 'chip/g') 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); } } -- cgit v1.2.1