diff options
author | Vic Yang <victoryang@chromium.org> | 2014-06-18 11:14:25 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-06-19 03:25:12 +0000 |
commit | 94acd01e0c4e9cb9c31c6b6d332d24bb352d669c (patch) | |
tree | d60fb142648bac44a0b255112f5d36d1ad491cd5 /board/keyborg | |
parent | 6c8e451ff01d046a953ee99a2911b46732361b2b (diff) | |
download | chrome-ec-94acd01e0c4e9cb9c31c6b6d332d24bb352d669c.tar.gz |
Keyborg: implement methods needed for touch wake
In order to wake the chips from STOP/SLEEP mode with a touch, we need to
put the two chips in correct state before going into STOP/SLEEP mode.
Also, when one of the chips wakes up, it needs to wake the other chip
with GPIO interrupt.
This CL implements the necessary methods and also adds a sample routine
that put the chips in STOP mode and wait for a touch using the
implemented methods.
BUG=None
TEST=Build and boot. Touch the panel and see the response in console.
BRANCH=None
Change-Id: Ia5f7df8b550ee2459bcae1840f8a2717c8d947ce
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/204482
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'board/keyborg')
-rw-r--r-- | board/keyborg/board.c | 26 | ||||
-rw-r--r-- | board/keyborg/board.h | 3 | ||||
-rw-r--r-- | board/keyborg/ec.irqlist | 3 | ||||
-rw-r--r-- | board/keyborg/hardware.c | 4 | ||||
-rw-r--r-- | board/keyborg/master_slave.c | 50 | ||||
-rw-r--r-- | board/keyborg/master_slave.h | 11 | ||||
-rw-r--r-- | board/keyborg/touch_scan.c | 47 | ||||
-rw-r--r-- | board/keyborg/touch_scan.h | 13 |
8 files changed, 154 insertions, 3 deletions
diff --git a/board/keyborg/board.c b/board/keyborg/board.c index 6db3d5cd66..e5491a90f4 100644 --- a/board/keyborg/board.c +++ b/board/keyborg/board.c @@ -5,6 +5,7 @@ /* Keyborg board-specific configuration */ #include "common.h" +#include "cpu.h" #include "debug.h" #include "master_slave.h" #include "registers.h" @@ -130,6 +131,27 @@ static const char *get_version(void) return version_data.version; } +static void low_power(void) +{ + touch_scan_enable_interrupt(); + master_slave_enable_interrupt(); + + CPU_SCB_SYSCTRL |= 0x4; + asm volatile("wfi"); + CPU_SCB_SYSCTRL &= ~0x4; + + hardware_clock_init(); + + touch_scan_disable_interrupt(); + master_slave_disable_interrupt(); + master_slave_wake_other(); + + /* Wait for the other chip to wake */ + udelay(2 * MSEC); + + master_slave_sync(5); +} + int main(void) { int i = 0; @@ -151,6 +173,10 @@ int main(void) master_slave_sync(100); + debug_printf("Touch to start..."); + low_power(); + debug_printf("\n"); + while (1) { i++; task_wait_event(SECOND); diff --git a/board/keyborg/board.h b/board/keyborg/board.h index ed67aabd5a..27c48088b6 100644 --- a/board/keyborg/board.h +++ b/board/keyborg/board.h @@ -41,6 +41,9 @@ enum gpio_signal; /* Initialize all useful registers */ void hardware_init(void); +/* Re-initialize clock */ +void hardware_clock_init(void); + /* On the master, reboot both chips. On the slave, reboot itself. */ void system_reboot(void); diff --git a/board/keyborg/ec.irqlist b/board/keyborg/ec.irqlist index 670978c5c5..47bf98c21e 100644 --- a/board/keyborg/ec.irqlist +++ b/board/keyborg/ec.irqlist @@ -9,4 +9,7 @@ */ ENABLE_IRQ(STM32_IRQ_EXTI0) +ENABLE_IRQ(STM32_IRQ_EXTI1) +ENABLE_IRQ(STM32_IRQ_EXTI2) +ENABLE_IRQ(STM32_IRQ_EXTI3) ENABLE_IRQ(STM32_IRQ_TIM2) diff --git a/board/keyborg/hardware.c b/board/keyborg/hardware.c index 3bc04ae653..589fa12d5a 100644 --- a/board/keyborg/hardware.c +++ b/board/keyborg/hardware.c @@ -12,7 +12,7 @@ #include "touch_scan.h" #include "util.h" -static void clock_init(void) +void hardware_clock_init(void) { /* Turn on HSE */ if (!(STM32_RCC_CR & (1 << 17))) { @@ -183,7 +183,7 @@ static void pmse_init(void) void hardware_init(void) { power_init(); - clock_init(); + hardware_clock_init(); pins_init(); timers_init(); adc_init(); diff --git a/board/keyborg/master_slave.c b/board/keyborg/master_slave.c index cc3c15d5a3..c494d24277 100644 --- a/board/keyborg/master_slave.c +++ b/board/keyborg/master_slave.c @@ -8,6 +8,7 @@ #include "debug.h" #include "master_slave.h" #include "registers.h" +#include "task.h" #include "timer.h" #include "util.h" @@ -55,6 +56,55 @@ int master_slave_sync_impl(const char *filename, int line, int timeout_ms) return err; } +void master_slave_enable_interrupt(void) +{ + if (is_master) { + /* Interrupt on EXTI2 on port I */ + STM32_EXTI_RTSR |= 1 << 2; + STM32_AFIO_EXTICR(0) = (STM32_AFIO_EXTICR(0) & ~0xf00) | + (8 << 8); + STM32_EXTI_IMR |= 1 << 2; + task_clear_pending_irq(STM32_IRQ_EXTI2); + task_enable_irq(STM32_IRQ_EXTI2); + } else { + /* Interrupt on EXTI1 on port I */ + STM32_EXTI_RTSR |= 1 << 1; + STM32_AFIO_EXTICR(0) = (STM32_AFIO_EXTICR(0) & ~0xf0) | + (8 << 4); + STM32_EXTI_IMR |= 1 << 1; + task_clear_pending_irq(STM32_IRQ_EXTI1); + task_enable_irq(STM32_IRQ_EXTI1); + } +} + +void master_slave_disable_interrupt(void) +{ + if (is_master) + task_disable_irq(STM32_IRQ_EXTI2); + else + task_disable_irq(STM32_IRQ_EXTI1); +} + +void master_slave_wake_other(void) +{ + if (is_master) { + STM32_GPIO_BSRR(GPIO_I) = SYNC1 << 0; + udelay(MSEC); + STM32_GPIO_BSRR(GPIO_I) = SYNC1 << 16; + } else { + STM32_GPIO_BSRR(GPIO_I) = SYNC2 << 0; + udelay(MSEC); + STM32_GPIO_BSRR(GPIO_I) = SYNC2 << 16; + } +} + +void master_slave_interrupt(void) +{ + STM32_EXTI_PR = STM32_EXTI_PR; +} +DECLARE_IRQ(STM32_IRQ_EXTI1, master_slave_interrupt, 1); +DECLARE_IRQ(STM32_IRQ_EXTI2, master_slave_interrupt, 1); + static int master_handshake(void) { uint32_t val; diff --git a/board/keyborg/master_slave.h b/board/keyborg/master_slave.h index 8cc1c8ce64..7312799158 100644 --- a/board/keyborg/master_slave.h +++ b/board/keyborg/master_slave.h @@ -29,6 +29,17 @@ int master_slave_is_master(void); int master_slave_sync_impl(const char *filename, int line, int timeout_ms); /** + * Enable/disable master-slave interrupt. Master-slave interrupt is + * implemented using SYNC1/SYNC2 signal, so this is assuming the master + * and the slave are in sync waiting for interrupt. + */ +void master_slave_enable_interrupt(void); +void master_slave_disable_interrupt(void); + +/* Interrupt the other chip with a 1-ms pulse. */ +void master_slave_wake_other(void); + +/** * Identify this chip and shake hands with the other chip. * * @return EC_SUCCESS, or non-zero if any error. diff --git a/board/keyborg/touch_scan.c b/board/keyborg/touch_scan.c index 83e58f219c..a8b8ed75f5 100644 --- a/board/keyborg/touch_scan.c +++ b/board/keyborg/touch_scan.c @@ -7,6 +7,7 @@ #include "common.h" #include "console.h" +#include "cpu.h" #include "debug.h" #include "dma.h" #include "encode.h" @@ -15,6 +16,7 @@ #include "master_slave.h" #include "registers.h" #include "spi_comm.h" +#include "task.h" #include "timer.h" #include "touch_scan.h" #include "util.h" @@ -61,6 +63,8 @@ static void set_gpio(const struct ts_pin pin, enum pin_type type) } else if (type == PIN_PD) { mask |= 0x88888888 & mode; STM32_GPIO_BSRR(port) = pmask << 16; + } else if (type == PIN_Z) { + mask |= 0x44444444 & mode; } else if (type == PIN_ROW) { /* Nothing for PIN_ROW. Already analog input. */ } @@ -73,7 +77,7 @@ void touch_scan_init(void) int i; for (i = 0; i < ROW_COUNT; ++i) { - set_gpio(col_pins[i], PIN_ROW); + set_gpio(row_pins[i], PIN_ROW); STM32_PMSE_PxPMR(row_pins[i].port_id) |= 1 << row_pins[i].pin; } for (i = 0; i < COL_COUNT; ++i) @@ -85,6 +89,47 @@ void touch_scan_init(void) mccr_list[i] = TS_PIN_TO_CR(col_pins[i]); } +void touch_scan_enable_interrupt(void) +{ + int i; + + /* Set ALLROW and ALLCOL */ + for (i = 0; i < ROW_COUNT; ++i) + set_gpio(row_pins[i], PIN_Z); + for (i = 0; i < COL_COUNT; ++i) { + set_gpio(col_pins[i], PIN_COL); + STM32_PMSE_PxPMR(col_pins[i].port_id) |= 1 << col_pins[i].pin; + } + STM32_PMSE_MCCR = (1 << 31) | (0 << 20); + STM32_PMSE_MRCR = 1 << 31; + + /* Enable external interrupt. EXTI3 on port E. Rising edge */ + STM32_EXTI_RTSR |= 1 << 3; + STM32_AFIO_EXTICR(0) = (STM32_AFIO_EXTICR(0) & ~0xf000) | (4 << 12); + STM32_EXTI_IMR |= 1 << 3; + task_clear_pending_irq(STM32_IRQ_EXTI3); + task_enable_irq(STM32_IRQ_EXTI3); +} + +void touch_scan_disable_interrupt(void) +{ + int i; + + for (i = 0; i < ROW_COUNT; ++i) + set_gpio(row_pins[i], PIN_ROW); + for (i = 0; i < COL_COUNT; ++i) { + set_gpio(col_pins[i], PIN_PD); + STM32_PMSE_PxPMR(col_pins[i].port_id) &= + ~(1 << col_pins[i].pin); + } +} + +void touch_scan_interrupt(void) +{ + STM32_EXTI_PR = STM32_EXTI_PR; +} +DECLARE_IRQ(STM32_IRQ_EXTI3, touch_scan_interrupt, 1); + static void discharge(void) { int i; diff --git a/board/keyborg/touch_scan.h b/board/keyborg/touch_scan.h index b2d23023fa..88f41560b6 100644 --- a/board/keyborg/touch_scan.h +++ b/board/keyborg/touch_scan.h @@ -12,6 +12,7 @@ enum pin_type { PIN_ROW, PIN_COL, PIN_PD, + PIN_Z, }; /* 8-bit window */ @@ -55,10 +56,22 @@ extern const struct ts_pin col_pins[]; #define ROW_COUNT 41 #define COL_COUNT 60 +/* Initialize touch scan module */ void touch_scan_init(void); +/* Start scanning on the slave. This is called by SPI command handler. */ void touch_scan_slave_start(void); +/** + * Initiate full matrix scan on the master. This also sends SPI command + * to the slave. + */ int touch_scan_full_matrix(void); +/* Configure touch scan module to interrupt on touch. */ +void touch_scan_enable_interrupt(void); + +/* Disable touch scan interrupt. */ +void touch_scan_disable_interrupt(void); + #endif /* __BOARD_KEYBORG_TOUCH_SCAN_H */ |