Merge "stm32l: add external interrupt support for GPIOs"

This commit is contained in:
Gerrit
2012-02-15 16:06:36 -08:00
committed by Gerrit Code Review
2 changed files with 87 additions and 1 deletions

View File

@@ -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);

View File

@@ -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