mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-11 18:35:28 +00:00
Merge "stm32l: add external interrupt support for GPIOs"
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user