diff --git a/arch/arm/src/armv7-a/arm_gicv2.c b/arch/arm/src/armv7-a/arm_gicv2.c index 5db74cff91..fbdc7eca1d 100644 --- a/arch/arm/src/armv7-a/arm_gicv2.c +++ b/arch/arm/src/armv7-a/arm_gicv2.c @@ -523,4 +523,56 @@ int up_prioritize_irq(int irq, int priority) return -EINVAL; } +/**************************************************************************** + * Name: arm_gic_irq_trigger + * + * Description: + * Set the trigger type for the specificd IRQ source and the current CPU. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + * Input Paramters: + * irq - The interrupt request to modify. + * edge - False: Active HIGH level sensitive, True: Rising edge sensitive + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ****************************************************************************/ + +int arm_gic_irq_trigger(int irq, bool edge) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t intcfg; + + if (irq > GIC_IRQ_SGI15 && irq < NR_IRQS) + { + /* Get the address of the Interrupt Configuration Register for this + * irq. + */ + + regaddr = GIC_ICDICFR(irq); + + /* Get the new Interrupt configuration bit setting */ + + intcfg = (edge ? (INT_ICDICFR_EDGE | INT_ICDICFR_1N) : INT_ICDICFR_1N); + + /* Write the correct interrupt trigger to the Interrupt Configuration + * Register. + */ + + regval = getreg32(regaddr); + regval &= ~GIC_ICDICFR_ID_MASK(irq); + regval |= GIC_ICDICFR_ID(irq, intcfg); + putreg32(regval, regaddr); + + return OK; + } + + return -EINVAL; +} + + #endif /* CONFIG_ARMV7A_HAVE_GICv2 */ diff --git a/arch/arm/src/armv7-a/gic.h b/arch/arm/src/armv7-a/gic.h index 45f8a606cb..cc6ee48330 100644 --- a/arch/arm/src/armv7-a/gic.h +++ b/arch/arm/src/armv7-a/gic.h @@ -495,7 +495,7 @@ #define INT_ICDICFR_EDGE 2 /* Bit n+2: 1=Edge sensitive */ #define GIC_ICDICFR_ID_SHIFT(n) GIC_SHIFT16(n) -#define GIC_ICDICFR_ID_MASK(n) GIC_MASK16(n +#define GIC_ICDICFR_ID_MASK(n) GIC_MASK16(n) # define GIC_ICDICFR_ID(n,c) ((uint32_t)(c) << GIC_SHIFT16(n)) /* PPI Status Register */ @@ -720,6 +720,26 @@ void arm_gic0_initialize(void); void arm_gic_initialize(void); +/**************************************************************************** + * Name: arm_gic_irq_trigger + * + * Description: + * Set the trigger type for the specificd IRQ source and the current CPU. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + * Input Paramters: + * irq - The interrupt request to modify. + * edge - False: Active HIGH level sensitive, True: Rising edge sensitive + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ****************************************************************************/ + +int arm_gic_irq_trigger(int irq, bool edge); + /**************************************************************************** * Name: arm_decodeirq * diff --git a/arch/arm/src/imx6/imx_serial.c b/arch/arm/src/imx6/imx_serial.c index 39a61fddff..f5da98d917 100644 --- a/arch/arm/src/imx6/imx_serial.c +++ b/arch/arm/src/imx6/imx_serial.c @@ -57,6 +57,7 @@ #include "up_arch.h" #include "up_internal.h" +#include "gic.h" #include "chip/imx_uart.h" #include "imx_config.h" #include "imx_lowputc.h" @@ -613,6 +614,10 @@ static int imx_attach(struct uart_dev_s *dev) ret = irq_attach(priv->irq, priv->handler); if (ret == OK) { + /* Configure as a (high) level interrupt */ + + (void)arm_gic_irq_trigger(priv->irq, false); + /* Enable the interrupt (RX and TX interrupts are still disabled * in the UART */ diff --git a/arch/arm/src/imx6/imx_timerisr.c b/arch/arm/src/imx6/imx_timerisr.c index 50d405973f..4b01fae8d1 100644 --- a/arch/arm/src/imx6/imx_timerisr.c +++ b/arch/arm/src/imx6/imx_timerisr.c @@ -46,6 +46,7 @@ #include #include "up_arch.h" +#include "gic.h" #include "chip/imx_ccm.h" #include "chip/imx_gpt.h" @@ -235,6 +236,10 @@ void up_timer_initialize(void) cr |= GPT_CR_EN; putreg32(cr, IMX_GPT_CR); + /* Configure as a (rising) edge-triggered interrupt */ + + (void)arm_gic_irq_trigger(IMX_IRQ_GPT, true); + /* Attach the timer interrupt vector */ (void)irq_attach(IMX_IRQ_GPT, (xcpt_t)up_timerisr); diff --git a/configs/sabre-6quad/README.txt b/configs/sabre-6quad/README.txt index c29b7b6dcb..19afbcd032 100644 --- a/configs/sabre-6quad/README.txt +++ b/configs/sabre-6quad/README.txt @@ -46,6 +46,14 @@ no interrupt driver serial console output (syslog, printf). 2016-05-16: I know get serial interrupts (but not timer interrupts). This involves a few changes to GIC bit settings that I do not fully understand. +With this change, the NSH serial console works: + + MX6Q SABRESD U-Boot > ABEFGHILMN + + NuttShell (NSH) + nsh> + +But there are still no timer interrupts. Platform Features =================