summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-06-18 11:14:25 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-06-19 03:25:12 +0000
commit94acd01e0c4e9cb9c31c6b6d332d24bb352d669c (patch)
treed60fb142648bac44a0b255112f5d36d1ad491cd5
parent6c8e451ff01d046a953ee99a2911b46732361b2b (diff)
downloadchrome-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>
-rw-r--r--board/keyborg/board.c26
-rw-r--r--board/keyborg/board.h3
-rw-r--r--board/keyborg/ec.irqlist3
-rw-r--r--board/keyborg/hardware.c4
-rw-r--r--board/keyborg/master_slave.c50
-rw-r--r--board/keyborg/master_slave.h11
-rw-r--r--board/keyborg/touch_scan.c47
-rw-r--r--board/keyborg/touch_scan.h13
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 */