summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerrit <chrome-bot@google.com>2012-02-15 16:06:36 -0800
committerGerrit Code Review <gerrit@gerrit.golo.chromium.org>2012-02-15 16:06:36 -0800
commit9e50c75cdbef825696072871cb439917cf15c2c8 (patch)
tree4be883755f55812af52a3d231ec02dceea8e5881
parent274cbf3cc0c6015b699ecca6ca9ec6281b7c4c17 (diff)
parent9a242f6840e3844d9b79630de59d8304cbc2c74d (diff)
downloadchrome-ec-9e50c75cdbef825696072871cb439917cf15c2c8.tar.gz
Merge "stm32l: add external interrupt support for GPIOs"
-rw-r--r--chip/stm32l/gpio.c77
-rw-r--r--chip/stm32l/registers.h11
2 files changed, 87 insertions, 1 deletions
diff --git a/chip/stm32l/gpio.c b/chip/stm32l/gpio.c
index 56d22abf62..f581868104 100644
--- a/chip/stm32l/gpio.c
+++ b/chip/stm32l/gpio.c
@@ -9,10 +9,14 @@
#include "gpio.h"
#include "registers.h"
#include "task.h"
+#include "uart.h"
+#include "util.h"
/* Signal information from board.c. Must match order from enum gpio_signal. */
extern const struct gpio_info gpio_list[GPIO_COUNT];
+/* For each EXTI bit, record which GPIO entry is using it */
+static const struct gpio_info *exti_events[16];
int gpio_pre_init(void)
{
@@ -47,8 +51,25 @@ int gpio_pre_init(void)
0xaaaaaaaa & mask2;
}
}
+
+ /* Set up interrupts if necessary */
+ ASSERT(!(g->flags & GPIO_INT_LEVEL));
+ if (g->flags & (GPIO_INT_RISING | GPIO_INT_BOTH))
+ STM32L_EXTI_RTSR |= g->mask;
+ if (g->flags & (GPIO_INT_FALLING | GPIO_INT_BOTH))
+ STM32L_EXTI_FTSR |= g->mask;
+ /* Interrupt is enabled by gpio_enable_interrupt() */
}
+ /* Enable IRQs now that pins are set up */
+ task_enable_irq(STM32L_IRQ_EXTI0);
+ task_enable_irq(STM32L_IRQ_EXTI1);
+ task_enable_irq(STM32L_IRQ_EXTI2);
+ task_enable_irq(STM32L_IRQ_EXTI3);
+ task_enable_irq(STM32L_IRQ_EXTI4);
+ task_enable_irq(STM32L_IRQ_EXTI9_5);
+ task_enable_irq(STM32L_IRQ_EXTI15_10);
+
return EC_SUCCESS;
}
@@ -67,3 +88,59 @@ int gpio_set_level(enum gpio_signal signal, int value)
return EC_SUCCESS;
}
+
+int gpio_enable_interrupt(enum gpio_signal signal)
+{
+ const struct gpio_info *g = gpio_list + signal;
+ uint32_t bit, group, shift, bank;
+
+ /* Fail if not implemented or no interrupt handler */
+ if (!g->mask || !g->irq_handler)
+ return EC_ERROR_INVAL;
+
+ bit = 31 - __builtin_clz(g->mask);
+
+#ifdef CONFIG_DEBUG
+ if (exti_events[bit]) {
+ uart_printf("Overriding %s with %s on EXTI%d\n",
+ exti_events[bit]->name, g->name, bit);
+ }
+#endif
+ exti_events[bit] = g;
+
+ group = bit / 4;
+ shift = (bit % 4) * 4;
+ bank = (g->port - STM32L_GPIOA_BASE) / 0x400;
+ STM32L_SYSCFG_EXTICR(group) = (STM32L_SYSCFG_EXTICR(group) &
+ ~(0xF << shift)) | (bank << shift);
+ STM32L_EXTI_IMR |= g->mask;
+
+ return EC_SUCCESS;
+}
+
+/*****************************************************************************/
+/* Interrupt handler */
+
+static void gpio_interrupt(void)
+{
+ int bit;
+ const struct gpio_info *g;
+ uint32_t pending = STM32L_EXTI_PR;
+
+ STM32L_EXTI_PR = pending;
+
+ while (pending) {
+ bit = 31 - __builtin_clz(pending);
+ g = exti_events[bit];
+ if (g && g->irq_handler)
+ g->irq_handler(g - gpio_list);
+ pending &= ~(1 << bit);
+ }
+}
+DECLARE_IRQ(STM32L_IRQ_EXTI0, gpio_interrupt, 1);
+DECLARE_IRQ(STM32L_IRQ_EXTI1, gpio_interrupt, 1);
+DECLARE_IRQ(STM32L_IRQ_EXTI2, gpio_interrupt, 1);
+DECLARE_IRQ(STM32L_IRQ_EXTI3, gpio_interrupt, 1);
+DECLARE_IRQ(STM32L_IRQ_EXTI4, gpio_interrupt, 1);
+DECLARE_IRQ(STM32L_IRQ_EXTI9_5, gpio_interrupt, 1);
+DECLARE_IRQ(STM32L_IRQ_EXTI15_10, gpio_interrupt, 1);
diff --git a/chip/stm32l/registers.h b/chip/stm32l/registers.h
index 23bad85a44..d9c24a4d6d 100644
--- a/chip/stm32l/registers.h
+++ b/chip/stm32l/registers.h
@@ -254,10 +254,19 @@
#define STM32L_FLASH_ACR REG32(STM32L_FLASH_REGS_BASE + 0x00)
+/* --- External Interrupts --- */
+#define STM32L_EXTI_BASE 0x40010400
+
+#define STM32L_EXTI_IMR REG32(STM32L_EXTI_BASE + 0x00)
+#define STM32L_EXTI_EMR REG32(STM32L_EXTI_BASE + 0x04)
+#define STM32L_EXTI_RTSR REG32(STM32L_EXTI_BASE + 0x08)
+#define STM32L_EXTI_FTSR REG32(STM32L_EXTI_BASE + 0x0c)
+#define STM32L_EXTI_SWIER REG32(STM32L_EXTI_BASE + 0x10)
+#define STM32L_EXTI_PR REG32(STM32L_EXTI_BASE + 0x14)
+
/* --- MISC --- */
#define STM32L_RI_BASE 0x40007C04
-#define STM32L_EXTI_BASE 0x40010400
#define STM32L_ADC1_BASE 0x40012400
#define STM32L_ADC_BASE 0x40012700
#define STM32L_COMP_BASE 0x40007C00