diff options
author | Dino Li <Dino.Li@ite.com.tw> | 2016-08-18 11:38:35 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-08-22 23:27:05 -0700 |
commit | f729672b66ee6667d3266d7f43216d1cd6f5f412 (patch) | |
tree | 743a134b5da49dcf15363d944f7da981e636f177 /chip/it83xx/lpc.c | |
parent | 0913208116137ceb6e4d399d3c4c3503b1ad1363 (diff) | |
download | chrome-ec-f729672b66ee6667d3266d7f43216d1cd6f5f412.tar.gz |
it83xx: lpc: add support 'CONFIG_KEYBOARD_IRQ_GPIO' and fix lpc_init()
1. To assert keyboard IRQ GPIO pin instead of SERIRQ if keyboard data
ready to send.
2. Clear STATUS_PROCESSING bit in lpc_init() to avoid host waiting after
a sysjump.
3. Save and restore event masks while doing a sysjump.
Signed-off-by: Dino Li <dino.li@ite.com.tw>
BRANCH=none
BUG=none
TEST=1. keyboard work normally if host support this keyboard interrupt.
2. Software sync done and jumping to RW and boot to kernel.
3. EC generate SCI normally after a sysjump.
Change-Id: Ib0d9785106d4d4d21f8e9a6d1f0548f187fa7976
Reviewed-on: https://chromium-review.googlesource.com/372499
Commit-Ready: Dino Li <Dino.Li@ite.com.tw>
Tested-by: Dino Li <Dino.Li@ite.com.tw>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'chip/it83xx/lpc.c')
-rw-r--r-- | chip/it83xx/lpc.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/chip/it83xx/lpc.c b/chip/it83xx/lpc.c index 519df6731a..1127e93576 100644 --- a/chip/it83xx/lpc.c +++ b/chip/it83xx/lpc.c @@ -29,6 +29,8 @@ #define CPUTS(outstr) cputs(CC_LPC, outstr) #define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define LPC_SYSJUMP_TAG 0x4c50 /* "LP" */ + /* LPC PM channels */ enum lpc_pm_ch { LPC_PM1 = 0, @@ -107,6 +109,26 @@ static void pm_clear_ibf(enum lpc_pm_ch ch) IT83XX_PMC_PMIE(ch) |= (1 << 7); } +#ifdef CONFIG_KEYBOARD_IRQ_GPIO +static void keyboard_irq_assert(void) +{ + /* + * Enforce signal-high for long enough for the signal to be pulled high + * by the external pullup resistor. This ensures the host will see the + * following falling edge, regardless of the line state before this + * function call. + */ + gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1); + udelay(4); + /* Generate a falling edge */ + gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 0); + udelay(4); + + /* Set signal high, now that we've generated the edge */ + gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1); +} +#endif + /** * Generate SMI pulse to the host chipset via GPIO. * @@ -273,6 +295,14 @@ void lpc_keyboard_put_char(uint8_t chr, int send_irq) /* keyboard */ IT83XX_KBC_KBHISR |= 0x10; +#ifdef CONFIG_KEYBOARD_IRQ_GPIO + task_clear_pending_irq(IT83XX_IRQ_KBC_OUT); + /* The data output to the KBC Data Output Register. */ + IT83XX_KBC_KBHIKDOR = chr; + task_enable_irq(IT83XX_IRQ_KBC_OUT); + if (send_irq) + keyboard_irq_assert(); +#else /* * bit0 = 0, The IRQ1 is controlled by the IRQ1B bit in KBIRQR. * bit1 = 0, The IRQ12 is controlled by the IRQ12B bit in KBIRQR. @@ -292,6 +322,7 @@ void lpc_keyboard_put_char(uint8_t chr, int send_irq) /* The data output to the KBC Data Output Register. */ IT83XX_KBC_KBHIKDOR = chr; task_enable_irq(IT83XX_IRQ_KBC_OUT); +#endif } void lpc_keyboard_clear_buffer(void) @@ -307,6 +338,9 @@ void lpc_keyboard_clear_buffer(void) void lpc_keyboard_resume_irq(void) { if (lpc_keyboard_has_char()) { +#ifdef CONFIG_KEYBOARD_IRQ_GPIO + keyboard_irq_assert(); +#else /* The IRQ1 is controlled by the IRQ1B bit in KBIRQR. */ IT83XX_KBC_KBHICR &= ~0x01; @@ -315,6 +349,7 @@ void lpc_keyboard_resume_irq(void) * (KBHICR) is 0, the bit directly controls the IRQ1 signal. */ IT83XX_KBC_KBIRQR |= 0x01; +#endif task_clear_pending_irq(IT83XX_IRQ_KBC_OUT); @@ -409,11 +444,13 @@ void lpc_kbc_obe_interrupt(void) task_clear_pending_irq(IT83XX_IRQ_KBC_OUT); +#ifndef CONFIG_KEYBOARD_IRQ_GPIO if (!(IT83XX_KBC_KBHICR & 0x01)) { IT83XX_KBC_KBIRQR &= ~0x01; IT83XX_KBC_KBHICR |= 0x01; } +#endif #ifdef HAS_TASK_KEYPROTO task_wake(TASK_ID_KEYPROTO); @@ -562,6 +599,32 @@ void pm5_ibf_interrupt(void) task_clear_pending_irq(IT83XX_IRQ_PMC5_IN); } +/** + * Preserve event masks across a sysjump. + */ +static void lpc_sysjump(void) +{ + system_add_jump_tag(LPC_SYSJUMP_TAG, 1, + sizeof(event_mask), event_mask); +} +DECLARE_HOOK(HOOK_SYSJUMP, lpc_sysjump, HOOK_PRIO_DEFAULT); + +/** + * Restore event masks after a sysjump. + */ +static void lpc_post_sysjump(void) +{ + const uint32_t *prev_mask; + int size, version; + + prev_mask = (const uint32_t *)system_get_jump_tag(LPC_SYSJUMP_TAG, + &version, &size); + if (!prev_mask || version != 1 || size != sizeof(event_mask)) + return; + + memcpy(event_mask, prev_mask, sizeof(event_mask)); +} + static void lpc_init(void) { enum ec2i_message ec2i_r; @@ -687,14 +750,19 @@ static void lpc_init(void) task_enable_irq(IT83XX_IRQ_KBC_IN); task_clear_pending_irq(IT83XX_IRQ_PMC_IN); + pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_PROCESSING, 0); task_enable_irq(IT83XX_IRQ_PMC_IN); task_clear_pending_irq(IT83XX_IRQ_PMC2_IN); + pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 0); task_enable_irq(IT83XX_IRQ_PMC2_IN); task_clear_pending_irq(IT83XX_IRQ_PMC3_IN); task_enable_irq(IT83XX_IRQ_PMC3_IN); + /* Restore event masks if needed */ + lpc_post_sysjump(); + /* Sufficiently initialized */ init_done = 1; |