summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorli feng <li1.feng@intel.com>2018-03-07 22:50:55 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-11-15 08:11:29 -0800
commitc9b5321774df82fa153644f0ef3bf05ed08dd48a (patch)
tree929912f7c5a10bb9964cfbbf577cc095bf81488f /chip
parentd67134434d7255adeb2effdc1246ee6ef37e4524 (diff)
downloadchrome-ec-c9b5321774df82fa153644f0ef3bf05ed08dd48a.tar.gz
ish gpio: GPIO functionality
BUG=b:116451255 BRANCH=none TEST=Tested on Atlas board, ISH GPIO is working. Change-Id: I29121dd143a5bf44a7431d12d9e05a3510fb4654 Signed-off-by: Sadashiva Rao Pv <sadashiva.rao.pv@intel.com> Signed-off-by: li feng <li1.feng@intel.com> Reviewed-on: https://chromium-review.googlesource.com/954718 Commit-Ready: Caveh Jalali <caveh@google.com> Tested-by: Li1 Feng <li1.feng@intel.com> Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/ish/gpio.c107
-rw-r--r--chip/ish/registers.h16
2 files changed, 120 insertions, 3 deletions
diff --git a/chip/ish/gpio.c b/chip/ish/gpio.c
index 1458240115..ce27165d57 100644
--- a/chip/ish/gpio.c
+++ b/chip/ish/gpio.c
@@ -14,27 +14,128 @@
#include "timer.h"
#include "util.h"
+#define ISH_TOTAL_GPIO_PINS 8
+
test_mockable int gpio_get_level(enum gpio_signal signal)
{
- return 0;
+ return !!(ISH_GPIO_GPLR & gpio_list[signal].mask);
}
void gpio_set_level(enum gpio_signal signal, int value)
{
+ const struct gpio_info *g = gpio_list + signal;
+ if (value)
+ ISH_GPIO_GPSR |= g->mask;
+ else
+ ISH_GPIO_GPCR |= g->mask;
+}
+
+void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
+{
+ /* GPSR/GPCR Output high/low */
+ if (flags & GPIO_HIGH) /* Output high */
+ ISH_GPIO_GPSR |= mask;
+ else if (flags & GPIO_LOW) /* output low */
+ ISH_GPIO_GPCR |= mask;
+
+ /* GPDR pin direction 1 = output, 0 = input*/
+ if (flags & GPIO_OUTPUT)
+ ISH_GPIO_GPDR |= mask;
+ else /* GPIO_INPUT or un-configured */
+ ISH_GPIO_GPDR &= ~mask;
+
+ /* GRER/GFER interrupt trigger */
+#ifdef CONFIG_ISH_30
+ /* ISH 3 can't support both rising and falling edge */
+ if (((flags & GPIO_INT_F_RISING) && (flags & GPIO_INT_F_FALLING)) ||
+ ((flags & GPIO_INT_F_HIGH) && (flags & GPIO_INT_F_LOW))) {
+ ccprintf("ISH 2/3 not support both rising&falling edge\n");
+ }
+#endif
+ /* Interrupt is asserted on rising edge/active high */
+ if (flags & GPIO_INT_F_RISING)
+ ISH_GPIO_GRER |= mask;
+ else
+ ISH_GPIO_GRER &= ~mask;
+
+ /* Interrupt is asserted on falling edge/active low */
+ if (flags & GPIO_INT_F_FALLING)
+ ISH_GPIO_GFER |= mask;
+ else
+ ISH_GPIO_GFER &= ~mask;
+}
+
+int gpio_enable_interrupt(enum gpio_signal signal)
+{
+ const struct gpio_info *g = gpio_list + signal;
+
+ ISH_GPIO_GIMR |= g->mask;
+ return EC_SUCCESS;
+}
+
+int gpio_disable_interrupt(enum gpio_signal signal)
+{
+ const struct gpio_info *g = gpio_list + signal;
+
+ ISH_GPIO_GIMR &= ~g->mask;
+ return EC_SUCCESS;
+}
+
+int gpio_clear_pending_interrupt(enum gpio_signal signal)
+{
+ const struct gpio_info *g = gpio_list + signal;
+
+ ISH_GPIO_GISR = g->mask;
+ return EC_SUCCESS;
}
void gpio_pre_init(void)
{
+ int i;
+ int flags;
+ int is_warm = system_is_reboot_warm();
+ const struct gpio_info *g = gpio_list;
+
+ for (i = 0; i < GPIO_COUNT; i++, g++) {
+
+ flags = g->flags;
+
+ if (flags & GPIO_DEFAULT)
+ continue;
+
+ /*
+ * If this is a warm reboot, don't set the output levels
+ * or we'll shut off the AP.
+ */
+ if (is_warm)
+ flags &= ~(GPIO_LOW | GPIO_HIGH);
+
+ gpio_set_flags_by_mask(g->port, g->mask, flags);
+ }
}
static void gpio_init(void)
{
- /* TBD */
+ task_enable_irq(ISH_GPIO_IRQ);
}
static void gpio_interrupt(void)
{
- /*TODO*/
+ int i;
+ const struct gpio_info *g = gpio_list;
+ uint32_t gisr = ISH_GPIO_GISR;
+ uint32_t gimr = ISH_GPIO_GIMR;
+
+ /* mask off any not enabled pins */
+ gisr &= gimr;
+
+ for (i = 0; i < GPIO_IH_COUNT; i++, g++) {
+ if (gisr & g->mask) {
+ /* write 1 to clear interrupt status bit */
+ ISH_GPIO_GISR = g->mask;
+ gpio_irq_handlers[i](i);
+ }
+ }
}
DECLARE_IRQ(ISH_GPIO_IRQ, gpio_interrupt);
diff --git a/chip/ish/registers.h b/chip/ish/registers.h
index 4ad9176a0e..d222f60b86 100644
--- a/chip/ish/registers.h
+++ b/chip/ish/registers.h
@@ -35,6 +35,7 @@ enum ish_i2c_port {
#define ISH_I2C1_BASE 0x00102000
#define ISH_I2C2_BASE 0x00105000
#define ISH_UART_BASE 0x00103000
+#define ISH_GPIO_BASE 0x001F0000
#define ISH_IPC_BASE 0x00B00000
#define ISH_IOAPIC_BASE 0xFEC00000
#define ISH_HPET_BASE 0xFED00000
@@ -60,6 +61,21 @@ enum ish_i2c_port {
/* Map IRQs to vectors after offset 10 for certain APIC interrupts */
#define IRQ_TO_VEC(irq) (irq + USER_VEC_START + 10)
+/* ISH GPIO Registers */
+#define ISH_GPIO_GCCR REG32(ISH_GPIO_BASE + 0x000) /* Direction lock */
+#define ISH_GPIO_GPLR REG32(ISH_GPIO_BASE + 0x004) /* Pin level */
+#define ISH_GPIO_GPDR REG32(ISH_GPIO_BASE + 0x01C) /* Pin direction */
+#define ISH_GPIO_GPSR REG32(ISH_GPIO_BASE + 0x034) /* Output set */
+#define ISH_GPIO_GPCR REG32(ISH_GPIO_BASE + 0x04C) /* Output clear */
+#define ISH_GPIO_GRER REG32(ISH_GPIO_BASE + 0x064) /* Rising edge detect */
+#define ISH_GPIO_GFER REG32(ISH_GPIO_BASE + 0x07C) /* Falling edge detect */
+#define ISH_GPIO_GFBR REG32(ISH_GPIO_BASE + 0x094) /* Glitch Filter disable */
+#define ISH_GPIO_GIMR REG32(ISH_GPIO_BASE + 0x0AC) /* Interrupt Enable */
+#define ISH_GPIO_GISR REG32(ISH_GPIO_BASE + 0x0C4) /* Interrupt Source */
+#define ISH_GPIO_GWMR REG32(ISH_GPIO_BASE + 0x100) /* Wake Enable */
+#define ISH_GPIO_GWSR REG32(ISH_GPIO_BASE + 0x118) /* Wake Source */
+#define ISH_GPIO_GSEC REG32(ISH_GPIO_BASE + 0x130) /* Secure Input */
+
/* APIC interrupt vectors */
#define ISH_TS_VECTOR 0x20 /* Task switch vector */
#define LAPIC_LVT_ERROR_VECTOR 0x21