diff options
author | Ruibin Chang <ruibin.chang@ite.com.tw> | 2020-06-03 14:08:42 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-10-14 06:10:48 +0000 |
commit | a57076ce03b3aa43d5cf62371649a7e9a28667e2 (patch) | |
tree | 3de7bcd25f17068b0b58fa0667f188a5a806542f /chip/it83xx/gpio.c | |
parent | 11053f40043229b98ab7cb6be0325ab483a5d9e5 (diff) | |
download | chrome-ec-a57076ce03b3aa43d5cf62371649a7e9a28667e2.tar.gz |
it83xx/KB/GPIO: support keyboard GPIO output mode
These pins could be used as GPIO input, and they can
be configured as GPIO output as well. So we made this
patch to support it.
BRANCH=none
BUG=b:170699805
TEST=On board it8xxx2_evb
1.GPIO only: set/get level properly at GPIO mode.
2.GPIO and alternate mix: KSI input low and KSO GPIO level
not change
On board reef_it8320
1.keyboard scan function still work fine.
Change-Id: I2098812649f2e3ee9a8718d0d75e541ce3f14338
Signed-off-by: Dino Li <Dino.Li@ite.com.tw>
Signed-off-by: Ruibin Chang <ruibin.chang@ite.com.tw>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2182128
Tested-by: Ruibin Chang <Ruibin.Chang@ite.com.tw>
Reviewed-by: Diana Z <dzigterman@chromium.org>
Commit-Queue: Ruibin Chang <Ruibin.Chang@ite.com.tw>
Diffstat (limited to 'chip/it83xx/gpio.c')
-rw-r--r-- | chip/it83xx/gpio.c | 81 |
1 files changed, 74 insertions, 7 deletions
diff --git a/chip/it83xx/gpio.c b/chip/it83xx/gpio.c index 90d8b717b7..f15adb431a 100644 --- a/chip/it83xx/gpio.c +++ b/chip/it83xx/gpio.c @@ -19,6 +19,23 @@ #include "timer.h" #include "util.h" +/* Data structure to define KSI/KSO GPIO mode control registers. */ +struct kbs_gpio_ctrl_t { + /* GPIO mode control register. */ + volatile uint8_t *gpio_mode; + /* GPIO output enable register. */ + volatile uint8_t *gpio_out; +}; + +static const struct kbs_gpio_ctrl_t kbs_gpio_ctrl_regs[] = { + /* KSI pins 7:0 */ + {&IT83XX_KBS_KSIGCTRL, &IT83XX_KBS_KSIGOEN}, + /* KSO pins 15:8 */ + {&IT83XX_KBS_KSOHGCTRL, &IT83XX_KBS_KSOHGOEN}, + /* KSO pins 7:0 */ + {&IT83XX_KBS_KSOLGCTRL, &IT83XX_KBS_KSOLGOEN}, +}; + /** * Convert wake-up controller (WUC) group to the corresponding wake-up edge * sense register (WUESR). Return pointer to the register. @@ -425,6 +442,25 @@ void gpio_set_alternate_function(uint32_t port, uint32_t mask, { uint32_t pin = 0; + /* Alternate function configuration for KSI/KSO pins */ + if (port > GPIO_PORT_COUNT) { + port -= GPIO_KSI; + /* + * If func is non-negative, set for keyboard scan function. + * Otherwise, turn the pin into a GPIO input. + */ + if (func >= GPIO_ALT_FUNC_DEFAULT) { + /* KBS mode */ + *kbs_gpio_ctrl_regs[port].gpio_mode &= ~mask; + } else { + /* input */ + *kbs_gpio_ctrl_regs[port].gpio_out &= ~mask; + /* GPIO mode */ + *kbs_gpio_ctrl_regs[port].gpio_mode |= mask; + } + return; + } + /* For each bit high in the mask, set that pin to use alt. func. */ while (mask > 0) { if (mask & 1) @@ -457,12 +493,43 @@ void gpio_set_level(enum gpio_signal signal, int value) void gpio_kbs_pin_gpio_mode(uint32_t port, uint32_t mask, uint32_t flags) { - if (port == GPIO_KSO_H) - IT83XX_KBS_KSOHGCTRL |= mask; - else if (port == GPIO_KSO_L) - IT83XX_KBS_KSOLGCTRL |= mask; - else if (port == GPIO_KSI) - IT83XX_KBS_KSIGCTRL |= mask; + uint32_t idx = port - GPIO_KSI; + + /* Set GPIO mode */ + *kbs_gpio_ctrl_regs[idx].gpio_mode |= mask; + + /* Set input or output */ + if (flags & GPIO_OUTPUT) { + /* + * Select open drain first, so that we don't glitch the signal + * when changing the line to an output. + */ + if (flags & GPIO_OPEN_DRAIN) + /* + * it83xx: need external pullup for output data high + * it8xxx2: this pin is always internal pullup + */ + IT83XX_GPIO_GPOT(port) |= mask; + else + /* + * it8xxx2: this pin is not internal pullup + */ + IT83XX_GPIO_GPOT(port) &= ~mask; + + /* Set level before change to output. */ + if (flags & GPIO_HIGH) + IT83XX_GPIO_DATA(port) |= mask; + else if (flags & GPIO_LOW) + IT83XX_GPIO_DATA(port) &= ~mask; + *kbs_gpio_ctrl_regs[idx].gpio_out |= mask; + } else { + *kbs_gpio_ctrl_regs[idx].gpio_out &= ~mask; + if (flags & GPIO_PULL_UP) + IT83XX_GPIO_GPOT(port) |= mask; + else + /* No internal pullup and pulldown */ + IT83XX_GPIO_GPOT(port) &= ~mask; + } } #ifndef IT83XX_GPIO_INT_FLEXIBLE @@ -495,8 +562,8 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) uint32_t pin = 0; uint32_t mask_copy = mask; + /* Set GPIO mode for KSI/KSO pins */ if (port > GPIO_PORT_COUNT) { - /* set up GPIO of KSO/KSI pins (support input only). */ gpio_kbs_pin_gpio_mode(port, mask, flags); return; } |