summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-01-17 14:25:20 -0800
committerRandall Spangler <rspangler@chromium.org>2012-01-17 15:21:20 -0800
commit37dcc1ab56c6817aae90e244f42ebff1d62bbfcb (patch)
tree02c6e80aa593dcfc9abd9d2dd202ac2c1727e982
parent002bc4278bcfe26ae9c3b6fb5cdd3ddc2d07403e (diff)
downloadchrome-ec-37dcc1ab56c6817aae90e244f42ebff1d62bbfcb.tar.gz
Handle all GPIO IRQs. Interrupts no longer enabled by default.
Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=chrome-os-partner:7456 TEST=if it runs, it works Change-Id: Ib82afab7d53203af31eefc9887feb98679266ac1
-rw-r--r--board/bds/board.h5
-rw-r--r--board/link/board.h4
-rw-r--r--chip/lm4/gpio.c85
-rw-r--r--chip/lm4/i2c.c8
-rw-r--r--chip/lm4/keyboard_scan.c75
-rw-r--r--chip/lm4/lpc.c3
-rw-r--r--chip/lm4/task.c4
-rw-r--r--chip/lm4/timer.c6
-rw-r--r--chip/lm4/uart.c4
-rw-r--r--chip/lm4/watchdog.c3
-rw-r--r--include/task.h6
11 files changed, 134 insertions, 69 deletions
diff --git a/board/bds/board.h b/board/bds/board.h
index dabad57e55..18e1c7b8b9 100644
--- a/board/bds/board.h
+++ b/board/bds/board.h
@@ -53,6 +53,11 @@
#define I2C_SPEED_CHARGER 100
#define I2C_SPEED_THERMAL 400 /* TODO: TMP007 supports 3.4Mbps
operation; use faster speed? */
+
+/* Keyboard scanner uses an entire GPIO bank for row inputs */
+#define KB_SCAN_ROW_IRQ LM4_IRQ_GPIOH
+#define KB_SCAN_ROW_GPIO LM4_GPIO_H
+
/* GPIO signal list */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/link/board.h b/board/link/board.h
index 430b8995b5..e8d4a68424 100644
--- a/board/link/board.h
+++ b/board/link/board.h
@@ -54,6 +54,10 @@
#define I2C_SPEED_THERMAL 400 /* TODO: TMP007 supports 3.4Mbps
operation; use faster speed? */
+/* Keyboard scanner uses an entire GPIO bank for row inputs */
+#define KB_SCAN_ROW_IRQ LM4_IRQ_GPION
+#define KB_SCAN_ROW_GPIO LM4_GPIO_N
+
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/chip/lm4/gpio.c b/chip/lm4/gpio.c
index 71c7803bf5..7836cb776e 100644
--- a/chip/lm4/gpio.c
+++ b/chip/lm4/gpio.c
@@ -116,6 +116,27 @@ int gpio_pre_init(void)
/* Interrupt is enabled by gpio_enable_interrupt() */
}
+ /* Enable IRQs now that pins are set up */
+ task_enable_irq(LM4_IRQ_GPIOA);
+ task_enable_irq(LM4_IRQ_GPIOB);
+ task_enable_irq(LM4_IRQ_GPIOC);
+ task_enable_irq(LM4_IRQ_GPIOD);
+ task_enable_irq(LM4_IRQ_GPIOE);
+ task_enable_irq(LM4_IRQ_GPIOF);
+ task_enable_irq(LM4_IRQ_GPIOG);
+#if (KB_SCAN_ROW_IRQ != LM4_IRQ_GPIOH)
+ task_enable_irq(LM4_IRQ_GPIOH);
+#endif
+ task_enable_irq(LM4_IRQ_GPIOJ);
+ task_enable_irq(LM4_IRQ_GPIOK);
+ task_enable_irq(LM4_IRQ_GPIOL);
+ task_enable_irq(LM4_IRQ_GPIOM);
+#if (KB_SCAN_ROW_IRQ != LM4_IRQ_GPION)
+ task_enable_irq(LM4_IRQ_GPION);
+#endif
+ task_enable_irq(LM4_IRQ_GPIOP);
+ task_enable_irq(LM4_IRQ_GPIOQ);
+
return EC_SUCCESS;
}
@@ -203,24 +224,58 @@ static void gpio_interrupt(int port, uint32_t mis)
/* Handlers for each GPIO port. These read and clear the interrupt bits for
* the port, then call the master handler above. */
+#define GPIO_IRQ_FUNC(irqfunc, gpiobase) \
+ static void irqfunc(void) \
+ { \
+ uint32_t mis = LM4_GPIO_MIS(gpiobase); \
+ LM4_GPIO_ICR(gpiobase) = mis; \
+ gpio_interrupt(gpiobase, mis); \
+ }
-static void __gpio_c_interrupt(void)
-{
- /* Read and clear the interrupt status */
- uint32_t mis = LM4_GPIO_MIS(LM4_GPIO_C);
- LM4_GPIO_ICR(LM4_GPIO_C) = mis;
- gpio_interrupt(LM4_GPIO_C, mis);
-}
+GPIO_IRQ_FUNC(__gpio_a_interrupt, LM4_GPIO_A);
+GPIO_IRQ_FUNC(__gpio_b_interrupt, LM4_GPIO_B);
+GPIO_IRQ_FUNC(__gpio_c_interrupt, LM4_GPIO_C);
+GPIO_IRQ_FUNC(__gpio_d_interrupt, LM4_GPIO_D);
+GPIO_IRQ_FUNC(__gpio_e_interrupt, LM4_GPIO_E);
+GPIO_IRQ_FUNC(__gpio_f_interrupt, LM4_GPIO_F);
+GPIO_IRQ_FUNC(__gpio_g_interrupt, LM4_GPIO_G);
+#if (KB_SCAN_ROW_GPIO != LM4_GPIO_H)
+GPIO_IRQ_FUNC(__gpio_h_interrupt, LM4_GPIO_H);
+#endif
+GPIO_IRQ_FUNC(__gpio_j_interrupt, LM4_GPIO_J);
+GPIO_IRQ_FUNC(__gpio_k_interrupt, LM4_GPIO_K);
+GPIO_IRQ_FUNC(__gpio_l_interrupt, LM4_GPIO_L);
+GPIO_IRQ_FUNC(__gpio_m_interrupt, LM4_GPIO_M);
+#if (KB_SCAN_ROW_GPIO != LM4_GPIO_N)
+GPIO_IRQ_FUNC(__gpio_n_interrupt, LM4_GPIO_N);
+#endif
+GPIO_IRQ_FUNC(__gpio_p_interrupt, LM4_GPIO_P);
+GPIO_IRQ_FUNC(__gpio_q_interrupt, LM4_GPIO_Q);
+
+#undef GPIO_IRQ_FUNC
+
+/* Declare IRQs */
+/* TODO: nesting this macro inside the GPIO_IRQ_FUNC macro works poorly because
+ * DECLARE_IRQ() stringizes its inputs. */
+DECLARE_IRQ(LM4_IRQ_GPIOA, __gpio_a_interrupt, 1);
+DECLARE_IRQ(LM4_IRQ_GPIOB, __gpio_b_interrupt, 1);
DECLARE_IRQ(LM4_IRQ_GPIOC, __gpio_c_interrupt, 1);
-
-static void __gpio_k_interrupt(void)
-{
- /* Read and clear the interrupt status */
- uint32_t mis = LM4_GPIO_MIS(LM4_GPIO_K);
- LM4_GPIO_ICR(LM4_GPIO_K) = mis;
- gpio_interrupt(LM4_GPIO_K, mis);
-}
+DECLARE_IRQ(LM4_IRQ_GPIOD, __gpio_d_interrupt, 1);
+DECLARE_IRQ(LM4_IRQ_GPIOE, __gpio_e_interrupt, 1);
+DECLARE_IRQ(LM4_IRQ_GPIOF, __gpio_f_interrupt, 1);
+DECLARE_IRQ(LM4_IRQ_GPIOG, __gpio_g_interrupt, 1);
+#if (KB_SCAN_ROW_IRQ != LM4_IRQ_GPIOH)
+DECLARE_IRQ(LM4_IRQ_GPIOH, __gpio_h_interrupt, 1);
+#endif
+DECLARE_IRQ(LM4_IRQ_GPIOJ, __gpio_j_interrupt, 1);
DECLARE_IRQ(LM4_IRQ_GPIOK, __gpio_k_interrupt, 1);
+DECLARE_IRQ(LM4_IRQ_GPIOL, __gpio_l_interrupt, 1);
+DECLARE_IRQ(LM4_IRQ_GPIOM, __gpio_m_interrupt, 1);
+#if (KB_SCAN_ROW_IRQ != LM4_IRQ_GPION)
+DECLARE_IRQ(LM4_IRQ_GPION, __gpio_n_interrupt, 1);
+#endif
+DECLARE_IRQ(LM4_IRQ_GPIOP, __gpio_p_interrupt, 1);
+DECLARE_IRQ(LM4_IRQ_GPIOQ, __gpio_q_interrupt, 1);
/*****************************************************************************/
/* Console commands */
diff --git a/chip/lm4/i2c.c b/chip/lm4/i2c.c
index 56e1be0398..8a9e74ec52 100644
--- a/chip/lm4/i2c.c
+++ b/chip/lm4/i2c.c
@@ -258,6 +258,14 @@ int i2c_init(void)
LM4_I2C_MTPR(I2C_PORT_CHARGER) =
(CPU_CLOCK / (I2C_SPEED_CHARGER * 10 * 2)) - 1;
+ /* Enable irqs */
+ task_enable_irq(LM4_IRQ_I2C0);
+ task_enable_irq(LM4_IRQ_I2C1);
+ task_enable_irq(LM4_IRQ_I2C2);
+ task_enable_irq(LM4_IRQ_I2C3);
+ task_enable_irq(LM4_IRQ_I2C4);
+ task_enable_irq(LM4_IRQ_I2C5);
+
console_register_commands(&command_group);
return EC_SUCCESS;
}
diff --git a/chip/lm4/keyboard_scan.c b/chip/lm4/keyboard_scan.c
index f7a5872a16..d3a134d2e3 100644
--- a/chip/lm4/keyboard_scan.c
+++ b/chip/lm4/keyboard_scan.c
@@ -5,6 +5,7 @@
/* Keyboard scanner module for Chrome EC */
+#include "board.h"
#include "console.h"
#include "keyboard.h"
#include "keyboard_scan.h"
@@ -17,7 +18,7 @@
/* Notes:
*
- * EVT board:
+ * Link proto0 board:
*
* Columns (outputs):
* KSO0 - KSO7 = PP0:7
@@ -30,7 +31,7 @@
* PWR_BTN# = PK7
*
*
- * Hacked board:
+ * BDS board:
*
* Columns (outputs):
* KSO0 - KSO7 = PQ0:7
@@ -53,8 +54,6 @@ enum COLUMN_INDEX {
#define POLLING_MODE_TIMEOUT 1000000 /* 1 sec */
#define SCAN_LOOP_DELAY 10000 /* 10 ms */
-#undef EVT /* FIXME: define this for EVT board. */
-
#define KB_COLS 13
static uint8_t raw_state[KB_COLS];
@@ -76,7 +75,7 @@ static const uint8_t actual_key_masks[4][KB_COLS] = {
/* Drives the specified column low; other columns are tri-stated */
static void select_column(int col)
{
-#if defined(EVT)
+#ifdef BOARD_link
if (col == COLUMN_ASSERT_ALL) {
LM4_GPIO_DIR(LM4_GPIO_P) = 0xff;
LM4_GPIO_DIR(LM4_GPIO_Q) |= 0x1f;
@@ -142,7 +141,7 @@ int keyboard_scan_init(void)
int i;
/* Enable GPIOs */
-#if defined(EVT)
+#ifdef BOARD_link
/* Enable clock to GPIO modules C,H,K,N,P,Q */
LM4_SYSTEM_RCGCGPIO |= 0x7284;
#else
@@ -155,7 +154,7 @@ int keyboard_scan_init(void)
* PK0:3, PN2, PQ0:7. */
LM4_GPIO_AFSEL(LM4_GPIO_C) &= ~0x20;
LM4_GPIO_DEN(LM4_GPIO_C) |= 0x20;
-#if defined(EVT)
+#ifdef BOARD_link
LM4_GPIO_AFSEL(LM4_GPIO_N) &= 0xff; /* KSI[7:0] */
LM4_GPIO_DEN(LM4_GPIO_N) |= 0xff;
LM4_GPIO_AFSEL(LM4_GPIO_P) &= 0xff; /* KSO[7:0] */
@@ -173,15 +172,9 @@ int keyboard_scan_init(void)
LM4_GPIO_DEN(LM4_GPIO_Q) = 0xff;
#endif
-#if defined(EVT)
- /* Set PN0:7 as inputs with pull-up */
- LM4_GPIO_DIR(LM4_GPIO_N) = 0;
- LM4_GPIO_PUR(LM4_GPIO_N) = 0xff;
-#else
- /* Set PH0:7 as inputs with pull-up */
- LM4_GPIO_DIR(LM4_GPIO_H) = 0;
- LM4_GPIO_PUR(LM4_GPIO_H) = 0xff;
-#endif
+ /* Set row inputs with pull-up */
+ LM4_GPIO_DIR(KB_SCAN_ROW_GPIO) = 0;
+ LM4_GPIO_PUR(KB_SCAN_ROW_GPIO) = 0xff;
/* Set PC5 as input with pull-up. */
/* TODO: no need for pull-up on real circuit, since it'll be
@@ -200,18 +193,16 @@ int keyboard_scan_init(void)
* key mask properly */
actual_key_mask = actual_key_masks[0];
+ /* Enable interrupts, now that we're set up */
+ task_enable_irq(KB_SCAN_ROW_IRQ);
+
return EC_SUCCESS;
}
static uint32_t clear_matrix_interrupt_status(void) {
-#if defined(EVT)
- uint32_t port = LM4_GPIO_N;
-#else
- uint32_t port = LM4_GPIO_H;
-#endif
- uint32_t ris = LM4_GPIO_RIS(port);
- LM4_GPIO_ICR(port) = ris;
+ uint32_t ris = LM4_GPIO_RIS(KB_SCAN_ROW_GPIO);
+ LM4_GPIO_ICR(KB_SCAN_ROW_GPIO) = ris;
return ris;
}
@@ -219,33 +210,23 @@ static uint32_t clear_matrix_interrupt_status(void) {
void wait_for_interrupt(void)
{
- uart_printf("Enter %s() ...\n", __func__);
+ uart_printf("[kbscan %s()]\n", __func__);
/* Assert all outputs would trigger un-wanted interrupts.
* Clear them before enable interrupt. */
select_column(COLUMN_ASSERT_ALL);
clear_matrix_interrupt_status();
-#if defined(EVT)
- LM4_GPIO_IS(LM4_GPIO_N) = 0; /* 0: edge-sensitive */
- LM4_GPIO_IBE(LM4_GPIO_N) = 0xff; /* 1: both edge */
- LM4_GPIO_IM(LM4_GPIO_N) = 0xff; /* 1: enable interrupt */
-#else
- LM4_GPIO_IS(LM4_GPIO_H) = 0; /* 0: edge-sensitive */
- LM4_GPIO_IBE(LM4_GPIO_H) = 0xff; /* 1: both edge */
- LM4_GPIO_IM(LM4_GPIO_H) = 0xff; /* 1: enable interrupt */
-#endif
+ LM4_GPIO_IS(KB_SCAN_ROW_GPIO) = 0; /* 0: edge-sensitive */
+ LM4_GPIO_IBE(KB_SCAN_ROW_GPIO) = 0xff; /* 1: both edge */
+ LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0xff; /* 1: enable interrupt */
}
void enter_polling_mode(void)
{
- uart_printf("Enter %s() ...\n", __func__);
-#if defined(EVT)
- LM4_GPIO_IM(LM4_GPIO_N) = 0; /* 0: disable interrupt */
-#else
- LM4_GPIO_IM(LM4_GPIO_H) = 0; /* 0: disable interrupt */
-#endif
+ uart_printf("[kbscan %s()]\n", __func__);
+ LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0; /* 0: disable interrupt */
select_column(COLUMN_TRI_STATE_ALL);
}
@@ -263,11 +244,7 @@ static int check_keys_changed(void)
select_column(c);
usleep(20);
/* Read the row state */
-#if defined(EVT)
- r = LM4_GPIO_DATA(LM4_GPIO_N, 0xff);
-#else
- r = LM4_GPIO_DATA(LM4_GPIO_H, 0xff);
-#endif
+ r = LM4_GPIO_DATA(KB_SCAN_ROW_GPIO, 0xff);
/* Invert it so 0=not pressed, 1=pressed */
r ^= 0xff;
/* Mask off keys that don't exist so they never show
@@ -361,8 +338,14 @@ static void matrix_interrupt(void)
}
}
-#if defined(EVT)
+/* TODO: DECLARE_IRQ stringizing plays poorly with other macros, so need this
+ * ugly workaround */
+#if (KB_SCAN_ROW_IRQ == LM4_IRQ_GPIOH)
+DECLARE_IRQ(LM4_IRQ_GPIOH, matrix_interrupt, 3);
+#elif (KB_SCAN_ROW_IRQ == LM4_IRQ_GPION)
DECLARE_IRQ(LM4_IRQ_GPION, matrix_interrupt, 3);
#else
-DECLARE_IRQ(LM4_IRQ_GPIOH, matrix_interrupt, 3);
+#error "Unsupported KB_SCAN_ROW_IRQ"
+/* If you add a board with different GPIO, also make sure supporting code in
+ * gpio.c is changed so the interrupts don't fight... */
#endif
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index 91b1c52b00..00fdca02a2 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -115,6 +115,9 @@ int lpc_init(void)
(1 << LPC_CH_USER) |
(1 << LPC_CH_COMX);
+ /* Enable LPC interrupt */
+ task_enable_irq(LM4_IRQ_LPC);
+
return EC_SUCCESS;
}
diff --git a/chip/lm4/task.c b/chip/lm4/task.c
index 85976e07ab..e01be96bdd 100644
--- a/chip/lm4/task.c
+++ b/chip/lm4/task.c
@@ -289,10 +289,6 @@ static void __nvic_init_irqs(void)
(LM4_NVIC_PRI(irq / 4) &
~(0x7 << prio_shift)) |
(prio << prio_shift);
-
- /* TODO: enabling all interrupts here causes a race condition
- between an interrupt and setting up the handler for it. */
- task_enable_irq(irq);
}
}
diff --git a/chip/lm4/timer.c b/chip/lm4/timer.c
index 65f30b3fb7..7c105a9ca7 100644
--- a/chip/lm4/timer.c
+++ b/chip/lm4/timer.c
@@ -125,7 +125,8 @@ static void __hw_clock_source_init(void)
{
volatile uint32_t scratch __attribute__((unused));
- /* use WTIMER0 configured as a free running counter with 1us period */
+ /* Use WTIMER0 (timer 6) configured as a free running counter with 1 us
+ * period */
/* Enable WTIMER0 clock */
LM4_SYSTEM_RCGCWTIMER |= 1;
@@ -146,6 +147,9 @@ static void __hw_clock_source_init(void)
LM4_TIMER_TAILR(6) = 0xffffffff;
/* Starts counting in timer A */
LM4_TIMER_CTL(6) |= 0x1;
+
+ /* Enable interrupt */
+ task_enable_irq(LM4_IRQ_TIMERW0A);
}
diff --git a/chip/lm4/uart.c b/chip/lm4/uart.c
index a8387809bd..c91742f64f 100644
--- a/chip/lm4/uart.c
+++ b/chip/lm4/uart.c
@@ -205,6 +205,10 @@ int uart_init(void)
LM4_UART_CTL(ch) |= 0x0001;
}
+ /* Enable interrupts */
+ task_enable_irq(LM4_IRQ_UART0);
+ task_enable_irq(LM4_IRQ_UART1);
+
/* Print hello on UART1 for debugging */
/* TODO: remove in production */
{
diff --git a/chip/lm4/watchdog.c b/chip/lm4/watchdog.c
index 86d9087a26..b0aa258bfd 100644
--- a/chip/lm4/watchdog.c
+++ b/chip/lm4/watchdog.c
@@ -130,5 +130,8 @@ int watchdog_init(int period_ms)
/* lock watchdog registers against unintended accesses */
LM4_WATCHDOG_LOCK(0) = 0xdeaddead;
+ /* Enable watchdog interrupt */
+ task_enable_irq(LM4_IRQ_WATCHDOG);
+
return EC_SUCCESS;
}
diff --git a/include/task.h b/include/task.h
index 52e42d3740..7e1d001f11 100644
--- a/include/task.h
+++ b/include/task.h
@@ -92,9 +92,9 @@ struct irq_priority {
* ensures it is enabled in the interrupt controller with the right priority.
*
* Note that you MUST pass irq using a LM4_IRQ_* constant from register.h, not
- * as a number, because it's stringized and matched up with a weak reference
- * from init.S. (This is still better than passing it as a raw number, because
- * that's more typo-prone.)
+ * as a number, and not as some other #defined constant, because it's
+ * stringized and matched up with a weak reference from init.S. (This is still
+ * better than passing it as a raw number, because that's more typo-prone.)
*/
#define DECLARE_IRQ(irq, routine, priority) \
void irq_##irq##_handler(void) \