diff --git a/arch/arm/include/efm32/efm32g_irq.h b/arch/arm/include/efm32/efm32g_irq.h index 9d98485ab8..0780d75b14 100644 --- a/arch/arm/include/efm32/efm32g_irq.h +++ b/arch/arm/include/efm32/efm32g_irq.h @@ -90,7 +90,6 @@ #define EFM32_IRQ_AES (EFM32_IRQ_INTERRUPTS+29) /* 29 AES */ #define NR_VECTORS (EFM32_IRQ_INTERRUPTS+30) -#define NR_IRQS (EFM32_IRQ_INTERRUPTS+30) /***************************************************************************** * Public Types diff --git a/arch/arm/include/efm32/efm32gg_irq.h b/arch/arm/include/efm32/efm32gg_irq.h index d52aa425d3..3d3f24b059 100644 --- a/arch/arm/include/efm32/efm32gg_irq.h +++ b/arch/arm/include/efm32/efm32gg_irq.h @@ -99,7 +99,6 @@ #define EFM32_IRQ_EMI (EFM32_IRQ_INTERRUPTS+38) #define NR_VECTORS (EFM32_IRQ_INTERRUPTS+39) -#define NR_IRQS (EFM32_IRQ_INTERRUPTS+39) /***************************************************************************** * Public Types diff --git a/arch/arm/include/efm32/efm32tg_irq.h b/arch/arm/include/efm32/efm32tg_irq.h index 5b21d404ef..b517872265 100644 --- a/arch/arm/include/efm32/efm32tg_irq.h +++ b/arch/arm/include/efm32/efm32tg_irq.h @@ -83,7 +83,6 @@ #define EFM32_IRQ_AES (EFM32_IRQ_INTERRUPTS+22) #define NR_VECTORS (EFM32_IRQ_INTERRUPTS+23) -#define NR_IRQS (EFM32_IRQ_INTERRUPTS+23) /***************************************************************************** * Public Types diff --git a/arch/arm/include/efm32/irq.h b/arch/arm/include/efm32/irq.h index fb348b1c5c..9b370afea4 100644 --- a/arch/arm/include/efm32/irq.h +++ b/arch/arm/include/efm32/irq.h @@ -50,7 +50,7 @@ #include /************************************************************************************ - * Definitions + * Pre-processor Definitions ************************************************************************************/ /* IRQ numbers. The IRQ number corresponds vector number and hence map directly to @@ -60,23 +60,23 @@ /* Processor Exceptions (vectors 0-15) */ -#define EFM32_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG) */ - /* Vector 0: Reset stack pointer value */ - /* Vector 1: Reset (not handler as an IRQ) */ -#define EFM32_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ -#define EFM32_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ -#define EFM32_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ -#define EFM32_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ -#define EFM32_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ -#define EFM32_IRQ_SVCALL (11) /* Vector 11: SVC call */ -#define EFM32_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ - /* Vector 13: Reserved */ -#define EFM32_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */ -#define EFM32_IRQ_SYSTICK (15) /* Vector 15: System tick */ +#define EFM32_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG) */ + /* Vector 0: Reset stack pointer value */ + /* Vector 1: Reset (not handler as an IRQ) */ +#define EFM32_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ +#define EFM32_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define EFM32_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define EFM32_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define EFM32_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ +#define EFM32_IRQ_SVCALL 11) /* Vector 11: SVC call */ +#define EFM32_IRQ_DBGMONITOR 12) /* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define EFM32_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */ +#define EFM32_IRQ_SYSTICK (15) /* Vector 15: System tick */ /* External interrupts (vectors >= 16). These definitions are chip-specific */ -#define EFM32_IRQ_INTERRUPTS (16) /* Vector number of the first external interrupt */ +#define EFM32_IRQ_INTERRUPTS (16) /* Vector number of the first external interrupt */ #if defined(CONFIG_EFM32_EFM32TG) # include @@ -88,6 +88,35 @@ # error "Unsupported EFM32 chip" #endif +#ifdef CONFIG_EFM32_GPIO_IRQ +/* If GPIO interrupt support is enabled then up to 16 additional GPIO interrupt + * sources are available. There are actually only two physical interrupt lines: + * GPIO_EVEN and GPIO_ODD. However, from the software point of view, there are + * 16-additional interrupts generated from a second level of decoding. + */ + +# define EFM32_IRQ_EXTI0 (NR_VECTORS+0) /* Port[n], pin0 external interrupt */ +# define EFM32_IRQ_EXTI1 (NR_VECTORS+1) /* Port[n], pin1 external interrupt */ +# define EFM32_IRQ_EXTI2 (NR_VECTORS+2) /* Port[n], pin2 external interrupt */ +# define EFM32_IRQ_EXTI3 (NR_VECTORS+3) /* Port[n], pin3 external interrupt */ +# define EFM32_IRQ_EXTI4 (NR_VECTORS+4) /* Port[n], pin4 external interrupt */ +# define EFM32_IRQ_EXTI5 (NR_VECTORS+5) /* Port[n], pin5 external interrupt */ +# define EFM32_IRQ_EXTI6 (NR_VECTORS+6) /* Port[n], pin6 external interrupt */ +# define EFM32_IRQ_EXTI7 (NR_VECTORS+7) /* Port[n], pin7 external interrupt */ +# define EFM32_IRQ_EXTI8 (NR_VECTORS+8) /* Port[n], pin8 external interrupt */ +# define EFM32_IRQ_EXTI9 (NR_VECTORS+9) /* Port[n], pin9 external interrupt */ +# define EFM32_IRQ_EXTI10 (NR_VECTORS+10) /* Port[n], pin10 external interrupt */ +# define EFM32_IRQ_EXTI11 (NR_VECTORS+11) /* Port[n], pin11 external interrupt */ +# define EFM32_IRQ_EXTI12 (NR_VECTORS+12) /* Port[n], pin12 external interrupt */ +# define EFM32_IRQ_EXTI13 (NR_VECTORS+13) /* Port[n], pin13 external interrupt */ +# define EFM32_IRQ_EXTI14 (NR_VECTORS+14) /* Port[n], pin14 external interrupt */ +# define EFM32_IRQ_EXTI15 (NR_VECTORS+15) /* Port[n], pin15 external interrupt */ + +# define NR_IRQS (NR_VECTORS+16) /* Total number of interrupts */ +#else +# define NR_IRQS NR_VECTORS /* Total number of interrupts */ +#endif + /************************************************************************************ * Public Types ************************************************************************************/ diff --git a/arch/arm/src/efm32/efm32_irq.c b/arch/arm/src/efm32/efm32_irq.c index 607d34ce88..ff4d4baf94 100644 --- a/arch/arm/src/efm32/efm32_irq.c +++ b/arch/arm/src/efm32/efm32_irq.c @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -53,6 +54,7 @@ #include "up_internal.h" #include "chip.h" +#include "efm32_gpio.h" /**************************************************************************** * Pre-processor Definitions @@ -119,15 +121,15 @@ static void efm32_dumpnvic(const char *msg, int irq) lldbg(" %08x %08x %08x %08x\n", getreg32(NVIC_IRQ16_19_PRIORITY), getreg32(NVIC_IRQ20_23_PRIORITY), getreg32(NVIC_IRQ24_27_PRIORITY), getreg32(NVIC_IRQ28_31_PRIORITY)); -#if NR_IRQS >= (EFM32_IRQ_INTERRUPTS + 32) +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 32) lldbg(" %08x %08x %08x %08x\n", getreg32(NVIC_IRQ32_35_PRIORITY), getreg32(NVIC_IRQ36_39_PRIORITY), getreg32(NVIC_IRQ40_43_PRIORITY), getreg32(NVIC_IRQ44_47_PRIORITY)); -#if NR_IRQS >= (EFM32_IRQ_INTERRUPTS + 48) +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 48) lldbg(" %08x %08x %08x %08x\n", getreg32(NVIC_IRQ48_51_PRIORITY), getreg32(NVIC_IRQ52_55_PRIORITY), getreg32(NVIC_IRQ56_59_PRIORITY), getreg32(NVIC_IRQ60_63_PRIORITY)); -#if NR_IRQS >= (EFM32_IRQ_INTERRUPTS + 64) +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 64) lldbg(" %08x\n", getreg32(NVIC_IRQ64_67_PRIORITY)); #endif @@ -237,32 +239,63 @@ static int efm32_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, { DEBUGASSERT(irq >= EFM32_IRQ_NMI && irq < NR_IRQS); - /* Check for external interrupt */ + /* Check for external interrupt or (a second level GPIO interrupt) */ if (irq >= EFM32_IRQ_INTERRUPTS) { - if (irq < EFM32_IRQ_INTERRUPTS + 32) + /* Is this an external interrupt? */ + + if (irq < NR_VECTORS) { - *regaddr = (NVIC_IRQ0_31_ENABLE + offset); - *bit = 1 << (irq - EFM32_IRQ_INTERRUPTS); - } -#if NR_IRQS >= (EFM32_IRQ_INTERRUPTS + 32) - else if (irq < EFM32_IRQ_INTERRUPTS + 64) - { - *regaddr = (NVIC_IRQ32_63_ENABLE + offset); - *bit = 1 << (irq - EFM32_IRQ_INTERRUPTS - 32); - } -#if NR_IRQS >= (EFM32_IRQ_INTERRUPTS + 64) - else if (irq < NR_IRQS) - { - *regaddr = (NVIC_IRQ64_95_ENABLE + offset); - *bit = 1 << (irq - EFM32_IRQ_INTERRUPTS - 64); - } + /* Yes.. We have support implemented for vectors 0-95 */ + + DEBUGASSERT(irq < (EFM32_IRQ_INTERRUPTS + 96)); + +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 32) + /* Check for vectors 0-31 */ + + if (irq < EFM32_IRQ_INTERRUPTS + 32) +#endif + { + *regaddr = (NVIC_IRQ0_31_ENABLE + offset); + *bit = 1 << (irq - EFM32_IRQ_INTERRUPTS); + } +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 32) + /* Yes.. Check for vectors 32-63 */ + + else +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 64) + if (irq < EFM32_IRQ_INTERRUPTS + 64) +#endif + { + *regaddr = (NVIC_IRQ32_63_ENABLE + offset); + *bit = 1 << (irq - EFM32_IRQ_INTERRUPTS - 32); + } +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 64) + /* Yes.. Check for vectors 64-95 */ + + else +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 96) + /* Yes.. Check for vectors 64-95 */ + + if (irq < NR_VECTORS) +#endif + { + *regaddr = (NVIC_IRQ64_95_ENABLE + offset); + *bit = 1 << (irq - EFM32_IRQ_INTERRUPTS - 64); + } +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 96) + else + { + return -EINVAL; /* We should never get here */ + } #endif #endif +#endif + } else { - return ERROR; /* Invalid interrupt */ + return -EINVAL; /* Invalid interrupt */ } } @@ -290,7 +323,7 @@ static int efm32_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, } else { - return ERROR; /* Invalid or unsupported exception */ + return -EINVAL; /* Invalid or unsupported exception */ } } @@ -313,9 +346,9 @@ void up_irqinitialize(void) /* Disable all interrupts */ putreg32(0, NVIC_IRQ0_31_ENABLE); -#if NR_IRQS >= (EFM32_IRQ_INTERRUPTS + 32) +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 32) putreg32(0, NVIC_IRQ32_63_ENABLE); -#if NR_IRQS >= (EFM32_IRQ_INTERRUPTS + 64) +#if NR_VECTORS >= (EFM32_IRQ_INTERRUPTS + 64) putreg32(0, NVIC_IRQ64_95_ENABLE); #endif #endif @@ -406,9 +439,16 @@ void up_irqinitialize(void) irq_attach(EFM32_IRQ_RESERVED, efm32_reserved); #endif - efm32_dumpnvic("initial", NR_IRQS); + efm32_dumpnvic("initial", NR_VECTORS); #ifndef CONFIG_SUPPRESS_INTERRUPTS +#ifdef CONFIG_EFM32_GPIO_IRQ + /* Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + */ + + efm32_gpioirqinitialize(); +#endif /* And finally, enable interrupts */ @@ -449,6 +489,14 @@ void up_disable_irq(int irq) putreg32(regval, regaddr); } } +#ifdef CONFIG_EFM32_GPIO_IRQ + else + { + /* Maybe it is a (derived) GPIO IRQ */ + + efm32_gpioirqdisable(irq); + } +#endif efm32_dumpnvic("disable", irq); } @@ -486,6 +534,14 @@ void up_enable_irq(int irq) putreg32(regval, regaddr); } } +#ifdef CONFIG_EFM32_GPIO_IRQ + else + { + /* Maybe it is a (derived) PIO IRQ */ + + efm32_gpioirqenable(irq); + } +#endif efm32_dumpnvic("enable", irq); } @@ -520,7 +576,7 @@ int up_prioritize_irq(int irq, int priority) uint32_t regval; int shift; - DEBUGASSERT(irq >= EFM32_IRQ_MEMFAULT && irq < NR_IRQS && + DEBUGASSERT(irq >= EFM32_IRQ_MEMFAULT && irq < NR_VECTORS && (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); if (irq < EFM32_IRQ_INTERRUPTS) @@ -532,13 +588,19 @@ int up_prioritize_irq(int irq, int priority) regaddr = NVIC_SYSH_PRIORITY(irq); irq -= 4; } - else + else (irq < NR_VECTORS) { /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */ irq -= EFM32_IRQ_INTERRUPTS; regaddr = NVIC_IRQ_PRIORITY(irq); } + else + { + /* Must be a GPIO interrupt */ + + return -EINVAL; + } regval = getreg32(regaddr); shift = ((irq & 3) << 3);