diff options
author | li feng <li1.feng@intel.com> | 2018-03-07 22:50:55 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-11-15 08:11:29 -0800 |
commit | c9b5321774df82fa153644f0ef3bf05ed08dd48a (patch) | |
tree | 929912f7c5a10bb9964cfbbf577cc095bf81488f | |
parent | d67134434d7255adeb2effdc1246ee6ef37e4524 (diff) | |
download | chrome-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>
-rw-r--r-- | chip/ish/gpio.c | 107 | ||||
-rw-r--r-- | chip/ish/registers.h | 16 |
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 |