summaryrefslogtreecommitdiff
path: root/chip/it83xx/gpio.c
diff options
context:
space:
mode:
authorRuibin Chang <ruibin.chang@ite.com.tw>2020-06-03 14:08:42 +0800
committerCommit Bot <commit-bot@chromium.org>2020-10-14 06:10:48 +0000
commita57076ce03b3aa43d5cf62371649a7e9a28667e2 (patch)
tree3de7bcd25f17068b0b58fa0667f188a5a806542f /chip/it83xx/gpio.c
parent11053f40043229b98ab7cb6be0325ab483a5d9e5 (diff)
downloadchrome-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.c81
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;
}