diff options
-rw-r--r-- | board/bds/board.h | 5 | ||||
-rw-r--r-- | board/link/board.h | 4 | ||||
-rw-r--r-- | chip/lm4/gpio.c | 85 | ||||
-rw-r--r-- | chip/lm4/i2c.c | 8 | ||||
-rw-r--r-- | chip/lm4/keyboard_scan.c | 75 | ||||
-rw-r--r-- | chip/lm4/lpc.c | 3 | ||||
-rw-r--r-- | chip/lm4/task.c | 4 | ||||
-rw-r--r-- | chip/lm4/timer.c | 6 | ||||
-rw-r--r-- | chip/lm4/uart.c | 4 | ||||
-rw-r--r-- | chip/lm4/watchdog.c | 3 | ||||
-rw-r--r-- | include/task.h | 6 |
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) \ |