From 855c9a52256d0115fefbe569e5aaabbbbecbacb8 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 1 Apr 2016 06:58:49 -0600 Subject: [PATCH] ARMv7-A GIC: Move debug logic to a separate file; fix some errors in debug logic. --- arch/arm/src/armv7-a/arm_gicv2.c | 341 +------------------------- arch/arm/src/armv7-a/arm_gicv2_dump.c | 309 +++++++++++++++++++++++ arch/arm/src/armv7-a/gic.h | 137 +++++++++-- arch/arm/src/imx6/Make.defs | 4 + 4 files changed, 427 insertions(+), 364 deletions(-) create mode 100644 arch/arm/src/armv7-a/arm_gicv2_dump.c diff --git a/arch/arm/src/armv7-a/arm_gicv2.c b/arch/arm/src/armv7-a/arm_gicv2.c index 7917077019..c50a992bc1 100644 --- a/arch/arm/src/armv7-a/arm_gicv2.c +++ b/arch/arm/src/armv7-a/arm_gicv2.c @@ -41,11 +41,8 @@ #include #include -#include -#include #include #include -#include #include #include @@ -56,306 +53,6 @@ #ifdef CONFIG_ARMV7A_HAVE_GICv2 -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: arm_gic_nlines - * - * Description: - * Return the number of interrupt lines supported by this GIC - * implementation (include both PPIs (32) and SPIs). - * - * Input Parameters: - * None - * - * Returned Value: - * The number of interrupt lines. - * - ****************************************************************************/ - -static inline unsigned int arm_gic_nlines(void) -{ - uint32_t regval; - uint32_t field; - - /* Get the number of interrupt lines. */ - - regval = getreg32(GIC_ICDICTR); - field = (regval & GIC_ICDICTR_ITLINES_MASK) >> GIC_ICDICTR_ITLINES_SHIFT; - return (field + 1) << 5; -} - -/**************************************************************************** - * Name: arm_gic_dump_cpu - * - * Description: - * Dump CPU interface registers. - * - * Input Parameters: - * all - True: Dump all IRQs; False: Dump only registers for this IRQ - * irq - if all == false, then dump only this IRQ. - * nlines - Number of interrupts to dump if all == true; - * - * Returned Value: - * None. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_IRQ -static inline void arm_gic_dump_cpu(bool all, int irq, int nlines) -{ - lowsyslog(LOG_INFO, " CPU Interface Registers:\n"); - lowsyslog(LOG_INFO, " ICR: %08x PMR: %08x BPR: %08x IAR: %08x\n", - getreg32(GIC_ICCICR), getreg32(GIC_ICCPMR), - getreg32(GIC_ICCBPR), getreg32(GIC_ICCIAR)); - lowsyslog(LOG_INFO, " RPR: %08x HPIR: %08x ABPR: %08x\n", - getreg32(GIC_ICCRPR), getreg32(GIC_ICCHPIR), - getreg32(GIC_ICCABPR)); - lowsyslog(LOG_INFO, " AIAR: %08x AHPIR: %08x IDR: %08x\n", - getreg32(GIC_ICCAIAR), getreg32(GIC_ICCAHPIR), - getreg32(GIC_ICCIDR)); - lowsyslog(LOG_INFO, " APR1: %08x APR2: %08x APR3: %08x APR4: %08x\n", - getreg32(GIC_ICCAPR1), getreg32(GIC_ICCAPR2), - getreg32(GIC_ICCAPR3), getreg32(GIC_ICCAPR4)); - lowsyslog(LOG_INFO, " NSAPR1: %08x NSAPR2: %08x NSAPR3: %08x NSAPR4: %08x\n", - getreg32(GIC_ICCNSAPR1), getreg32(GIC_ICCNSAPR2), - getreg32(GIC_ICCNSAPR3), getreg32(GIC_ICCNSAPR4)); -} -#endif - -/**************************************************************************** - * Name: arm_gic_dumpregs - * - * Description: - * Dump registers with 4x8-bit per interrupt - * - * Input Parameters: - * regaddr - First register address - * nlines - Number of interrupt lines - * incr - IRQs per 32-bit word - * - * Returned Value: - * None. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_IRQ -static void arm_gic_dumpregs(uintptr_t regaddr, int nlines, int incr) -{ - unsigned int i; - - incr <<= 2; - for (i = 0; i < nlines; i += incr) - { - lowsyslog(LOG_INFO, " %08x %08x %08x %08x\n", - getreg32(regaddr), getreg32(regaddr + 4), - getreg32(regaddr + 8), getreg32(regaddr + 12)); - } -} -#endif - -/**************************************************************************** - * Name: arm_gic_dump4 - * - * Description: - * Dump registers with 4x8-bit per interrupt - * - * Input Parameters: - * name - Register name - * regaddr - First register address - * nlines - Number of interrupt lines - * - * Returned Value: - * None. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_IRQ -static inline void arm_gic_dump4(const char *name, uintptr_t regaddr, - int nlines) -{ - lowsyslog(LOG_INFO, " %s\n", name); - arm_gic_dumpregs(regaddr, nlines, 4); -} -#endif - -/**************************************************************************** - * Name: arm_gic_dump8 - * - * Description: - * Dump registers with 8x4-bit per interrupt - * - * Input Parameters: - * name - Register name - * regaddr - First register address - * nlines - Number of interrupt lines - * - * Returned Value: - * None. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_IRQ -static inline void arm_gic_dump8(const char *name, uintptr_t regaddr, - int nlines) -{ - lowsyslog(LOG_INFO, " %s\n", name); - arm_gic_dumpregs(regaddr, nlines, 8); -} -#endif - -/**************************************************************************** - * Name: arm_gic_dump16 - * - * Description: - * Dump registers with 16 x 2-bit per interrupt - * - * Input Parameters: - * name - Register name - * regaddr - First register address - * nlines - Number of interrupt lines - * - * Returned Value: - * None. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_IRQ -static inline void arm_gic_dump16(const char *name, uintptr_t regaddr, - int nlines) -{ - lowsyslog(LOG_INFO, " %s\n", name); - arm_gic_dumpregs(regaddr, nlines, 16); -} -#endif - -/**************************************************************************** - * Name: arm_gic_dump32 - * - * Description: - * Dump registers with 32 x 1-bit per interrupt - * - * Input Parameters: - * name - Register name - * regaddr - First register address - * nlines - Number of interrupt lines - * - * Returned Value: - * None. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_IRQ -static inline void arm_gic_dump32(const char *name, uintptr_t regaddr, - int nlines) -{ - lowsyslog(LOG_INFO, " %s\n", name); - arm_gic_dumpregs(regaddr, nlines, 32); -} -#endif - -/**************************************************************************** - * Name: arm_gic_dump_distributor - * - * Description: - * Dump distributor interface registers. - * - * Input Parameters: - * all - True: Dump all IRQs; False: Dump only registers for this IRQ - * irq - if all == false, then dump only this IRQ. - * nlines - Number of interrupts to dump if all == true; - * - * Returned Value: - * None. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_IRQ -static inline void arm_gic_dump_distributor(bool all, int irq, int nlines) -{ - lowsyslog(LOG_INFO, " Distributor Registers:\n"); - lowsyslog(LOG_INFO, " DCR: %08x ICTR: %08x IIDR: %08x PPISR: %08x\n", - getreg32(GIC_ICDDCR), getreg32(GIC_ICDICTR), - getreg32(GIC_ICDIIDR), getreg32(GIC_ICDPPISR)); - - if (all) - { - arm_gic_dump32("ISR:", GIC_ICDISR(0), nlines); - arm_gic_dump32("ISER/ICER:", GIC_ICDISER(0), nlines); - arm_gic_dump32("ISPR/ICPR:", GIC_ICDISPR(0), nlines); - arm_gic_dump32("SAR/CAR:", GIC_ICDSAR(0), nlines); - arm_gic_dump4("IPR:", GIC_ICDIPR(0), nlines); - arm_gic_dump4("IPTR:", GIC_ICDIPTR(0), nlines); - arm_gic_dump16("ICFR:", GIC_ICDICFR(0), nlines); - arm_gic_dump32("SPISR:", GIC_ICDSPISR(0), nlines); - arm_gic_dump32("NSACR:", GIC_ICDNSACR(0), nlines); - arm_gic_dump8("SCPR/SSPR:", GIC_ICDSCPR(0), nlines); - } - else - { - lowsyslog(LOG_INFO, " ISR: %08x ISER: %08x ISPR: %08x SAR: %08x\n", - getreg32(GIC_ICDISR(irq)), getreg32(GIC_ICDISER(irq)), - getreg32(GIC_ICDISPR(irq)), getreg32(GIC_ICDSAR(irq))); - lowsyslog(LOG_INFO, " IPR: %08x IPTR: %08x ICFR: %08x SPISR: %08x\n", - getreg32(GIC_ICDIPR(irq)), getreg32(GIC_ICDIPTR(irq)), - getreg32(GIC_ICDICFR(irq)), getreg32(GIC_ICDSPISR(irq))); - lowsyslog(LOG_INFO, " NSACR: %08x SCPR: %08x\n", - getreg32(GIC_ICDNSACR(irq)), getreg32(GIC_ICDSCPR(irq))); - } - - lowsyslog(LOG_INFO, " PIDR:\n"); - lowsyslog(LOG_INFO, " %08x %08x %08x %08x\n", - getreg32(GIC_ICDPIDR(0)), getreg32(GIC_ICDPIDR(1)), - getreg32(GIC_ICDPIDR(2)), getreg32(GIC_ICDPIDR(3))); - lowsyslog(LOG_INFO, " %08x %08x %08x %08x\n", - getreg32(GIC_ICDPIDR(4)), getreg32(GIC_ICDPIDR(5)), - getreg32(GIC_ICDPIDR(6))); - lowsyslog(LOG_INFO, " CIDR:\n"); - lowsyslog(LOG_INFO, " %08x %08x %08x %08x\n", - getreg32(GIC_ICDCIDR(0)), getreg32(GIC_ICDCIDR(1)), - getreg32(GIC_ICDCIDR(2)), getreg32(GIC_ICDCIDR(3))); -} -#endif - -/**************************************************************************** - * Name: arm_gic_dump - * - * Description: - * Return the number of interrupt lines supported by this GIC - * implementation (include both PPIs (32) and SPIs). - * - * Input Parameters: - * all - True: Dump all IRQs; False: Dump only registers for this IRQ - * irq - if all == false, then dump only this IRQ. - * - * Returned Value: - * The number of interrupt lines. - * - ****************************************************************************/ - -#ifdef CONFIG_DEBUG_IRQ -static void arm_gic_dump(const char *msg, bool all, int irq) -{ - unsigned int nlines = arm_gic_nlines(); - - if (all) - { - lowsyslog(LOG_INFO, "GIC: %s NLINES=%u\n", msg, nlines); - } - else - { - lowsyslog(LOG_INFO, "GIC: %s IRQ=%d\n", msg, irq); - } - - arm_gic_dump_cpu(all, irq, nlines); - arm_gic_dump_distributor(all, irq, nlines); -} -#else -# define arm_gic_dump(m,a,i) -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -658,6 +355,8 @@ uint32_t *arm_decodeirq(uint32_t *regs) regval = getreg32(GIC_ICCIAR); irq = (regval & GIC_ICCIAR_INTID_MASK) >> GIC_ICCIAR_INTID_SHIFT; + gicllvdbg("irq=%d\n", irq); + /* Ignore spurions IRQs. ICCIAR will report 1023 if there is no pending * interrupt. */ @@ -792,40 +491,4 @@ int up_prioritize_irq(int irq, int priority) return -EINVAL; } -/**************************************************************************** - * Name: arm_cpu_sgi - * - * Description: - * Perform a Software Generated Interrupt (SGI). If CONFIG_SMP is - * selected, then the SGI is sent to all CPUs specified in the CPU set. - * That set may include the current CPU. - * - * If CONFIG_SMP is not selected, the cpuset is ignored and SGI is sent - * only to the current CPU. - * - * Input Paramters - * sgi - The SGI interrupt ID (0-15) - * cpuset - The set of CPUs to receive the SGI - * - * Returned Value: - * OK is always returned at present. - * - ****************************************************************************/ - -int arm_cpu_sgi(int sgi, unsigned int cpuset) -{ - uint32_t regval; - -#ifdef CONFIG_SMP - regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(cpuset) | - GIC_ICDSGIR_TGTFILTER_LIST; -#else - regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(0) | - GIC_ICDSGIR_TGTFILTER_THIS; -#endif - - putreg32(regval, GIC_ICDSGIR); - return OK; -} - #endif /* CONFIG_ARMV7A_HAVE_GICv2 */ diff --git a/arch/arm/src/armv7-a/arm_gicv2_dump.c b/arch/arm/src/armv7-a/arm_gicv2_dump.c new file mode 100644 index 0000000000..1791540fe5 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_gicv2_dump.c @@ -0,0 +1,309 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_gicv2_dump.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "up_arch.h" +#include "gic.h" + +#if defined(CONFIG_ARMV7A_HAVE_GICv2) && defined(CONFIG_DEBUG_IRQ) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_gic_dump_cpu + * + * Description: + * Dump CPU interface registers. + * + * Input Parameters: + * all - True: Dump all IRQs; False: Dump only registers for this IRQ + * irq - if all == false, then dump only this IRQ. + * nlines - Number of interrupts to dump if all == true; + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static inline void arm_gic_dump_cpu(bool all, int irq, int nlines) +{ + lowsyslog(LOG_INFO, " CPU Interface Registers:\n"); + lowsyslog(LOG_INFO, " ICR: %08x PMR: %08x BPR: %08x IAR: %08x\n", + getreg32(GIC_ICCICR), getreg32(GIC_ICCPMR), + getreg32(GIC_ICCBPR), getreg32(GIC_ICCIAR)); + lowsyslog(LOG_INFO, " RPR: %08x HPIR: %08x ABPR: %08x\n", + getreg32(GIC_ICCRPR), getreg32(GIC_ICCHPIR), + getreg32(GIC_ICCABPR)); + lowsyslog(LOG_INFO, " AIAR: %08x AHPIR: %08x IDR: %08x\n", + getreg32(GIC_ICCAIAR), getreg32(GIC_ICCAHPIR), + getreg32(GIC_ICCIDR)); + lowsyslog(LOG_INFO, " APR1: %08x APR2: %08x APR3: %08x APR4: %08x\n", + getreg32(GIC_ICCAPR1), getreg32(GIC_ICCAPR2), + getreg32(GIC_ICCAPR3), getreg32(GIC_ICCAPR4)); + lowsyslog(LOG_INFO, " NSAPR1: %08x NSAPR2: %08x NSAPR3: %08x NSAPR4: %08x\n", + getreg32(GIC_ICCNSAPR1), getreg32(GIC_ICCNSAPR2), + getreg32(GIC_ICCNSAPR3), getreg32(GIC_ICCNSAPR4)); +} + +/**************************************************************************** + * Name: arm_gic_dumpregs + * + * Description: + * Dump registers with 4x8-bit per interrupt + * + * Input Parameters: + * regaddr - First register address + * nlines - Number of interrupt lines + * incr - IRQs per 32-bit word + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void arm_gic_dumpregs(uintptr_t regaddr, int nlines, int incr) +{ + unsigned int i; + + incr <<= 2; + for (i = 0; i < nlines; i += incr, regaddr += 16) + { + lowsyslog(LOG_INFO, " %08x %08x %08x %08x\n", + getreg32(regaddr), getreg32(regaddr + 4), + getreg32(regaddr + 8), getreg32(regaddr + 12)); + } +} + +/**************************************************************************** + * Name: arm_gic_dump4 + * + * Description: + * Dump registers with 4x8-bit per interrupt + * + * Input Parameters: + * name - Register name + * regaddr - First register address + * nlines - Number of interrupt lines + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static inline void arm_gic_dump4(const char *name, uintptr_t regaddr, + int nlines) +{ + lowsyslog(LOG_INFO, " %s[%08lx]\n", name, (unsigned long)regaddr); + arm_gic_dumpregs(regaddr, nlines, 4); +} + +/**************************************************************************** + * Name: arm_gic_dump8 + * + * Description: + * Dump registers with 8x4-bit per interrupt + * + * Input Parameters: + * name - Register name + * regaddr - First register address + * nlines - Number of interrupt lines + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static inline void arm_gic_dump8(const char *name, uintptr_t regaddr, + int nlines) +{ + lowsyslog(LOG_INFO, " %s[%08lx]\n", name, (unsigned long)regaddr); + arm_gic_dumpregs(regaddr, nlines, 8); +} + +/**************************************************************************** + * Name: arm_gic_dump16 + * + * Description: + * Dump registers with 16 x 2-bit per interrupt + * + * Input Parameters: + * name - Register name + * regaddr - First register address + * nlines - Number of interrupt lines + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static inline void arm_gic_dump16(const char *name, uintptr_t regaddr, + int nlines) +{ + lowsyslog(LOG_INFO, " %s[%08lx]\n", name, (unsigned long)regaddr); + arm_gic_dumpregs(regaddr, nlines, 16); +} + +/**************************************************************************** + * Name: arm_gic_dump32 + * + * Description: + * Dump registers with 32 x 1-bit per interrupt + * + * Input Parameters: + * name - Register name + * regaddr - First register address + * nlines - Number of interrupt lines + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static inline void arm_gic_dump32(const char *name, uintptr_t regaddr, + int nlines) +{ + lowsyslog(LOG_INFO, " %s[%08lx]\n", name, (unsigned long)regaddr); + arm_gic_dumpregs(regaddr, nlines, 32); +} + +/**************************************************************************** + * Name: arm_gic_dump_distributor + * + * Description: + * Dump distributor interface registers. + * + * Input Parameters: + * all - True: Dump all IRQs; False: Dump only registers for this IRQ + * irq - if all == false, then dump only this IRQ. + * nlines - Number of interrupts to dump if all == true; + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static inline void arm_gic_dump_distributor(bool all, int irq, int nlines) +{ + lowsyslog(LOG_INFO, " Distributor Registers:\n"); + lowsyslog(LOG_INFO, " DCR: %08x ICTR: %08x IIDR: %08x PPISR: %08x\n", + getreg32(GIC_ICDDCR), getreg32(GIC_ICDICTR), + getreg32(GIC_ICDIIDR), getreg32(GIC_ICDPPISR)); + + if (all) + { + arm_gic_dump32("ISR", GIC_ICDISR(0), nlines); + arm_gic_dump32("ISER/ICER", GIC_ICDISER(0), nlines); + arm_gic_dump32("ISPR/ICPR", GIC_ICDISPR(0), nlines); + arm_gic_dump32("SAR/CAR", GIC_ICDSAR(0), nlines); + arm_gic_dump4("IPR", GIC_ICDIPR(0), nlines); + arm_gic_dump4("IPTR", GIC_ICDIPTR(0), nlines); + arm_gic_dump16("ICFR", GIC_ICDICFR(0), nlines); + arm_gic_dump32("SPISR", GIC_ICDSPISR(0), nlines); + arm_gic_dump32("NSACR", GIC_ICDNSACR(0), nlines); + arm_gic_dump8("SCPR/SSPR", GIC_ICDSCPR(0), nlines); + } + else + { + lowsyslog(LOG_INFO, " ISR: %08x ISER: %08x ISPR: %08x SAR: %08x\n", + getreg32(GIC_ICDISR(irq)), getreg32(GIC_ICDISER(irq)), + getreg32(GIC_ICDISPR(irq)), getreg32(GIC_ICDSAR(irq))); + lowsyslog(LOG_INFO, " IPR: %08x IPTR: %08x ICFR: %08x SPISR: %08x\n", + getreg32(GIC_ICDIPR(irq)), getreg32(GIC_ICDIPTR(irq)), + getreg32(GIC_ICDICFR(irq)), getreg32(GIC_ICDSPISR(irq))); + lowsyslog(LOG_INFO, " NSACR: %08x SCPR: %08x\n", + getreg32(GIC_ICDNSACR(irq)), getreg32(GIC_ICDSCPR(irq))); + } + + lowsyslog(LOG_INFO, " PIDR[%08lx]:\n", (unsigned long)GIC_ICDPIDR(0)); + lowsyslog(LOG_INFO, " %08x %08x %08x %08x\n", + getreg32(GIC_ICDPIDR(0)), getreg32(GIC_ICDPIDR(1)), + getreg32(GIC_ICDPIDR(2)), getreg32(GIC_ICDPIDR(3))); + lowsyslog(LOG_INFO, " %08x %08x %08x %08x\n", + getreg32(GIC_ICDPIDR(4)), getreg32(GIC_ICDPIDR(5)), + getreg32(GIC_ICDPIDR(6))); + lowsyslog(LOG_INFO, " CIDR[%08lx]:\n", (unsigned long)GIC_ICDCIDR(0)); + lowsyslog(LOG_INFO, " %08x %08x %08x %08x\n", + getreg32(GIC_ICDCIDR(0)), getreg32(GIC_ICDCIDR(1)), + getreg32(GIC_ICDCIDR(2)), getreg32(GIC_ICDCIDR(3))); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_gic_dump + * + * Description: + * Dump GIC registers to the SYSLOG device + * + * Input Parameters: + * msg - Message to print with the register data + * all - True: Dump all IRQs; False: Dump only registers for this IRQ + * irq - if all == false, then dump only this IRQ. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void arm_gic_dump(const char *msg, bool all, int irq) +{ + unsigned int nlines = arm_gic_nlines(); + + if (all) + { + lowsyslog(LOG_INFO, "GIC: %s NLINES=%u\n", msg, nlines); + } + else + { + lowsyslog(LOG_INFO, "GIC: %s IRQ=%d\n", msg, irq); + } + + arm_gic_dump_cpu(all, irq, nlines); + arm_gic_dump_distributor(all, irq, nlines); +} + +#endif /* CONFIG_ARMV7A_HAVE_GICv2 && CONFIG_DEBUG_IRQ */ diff --git a/arch/arm/src/armv7-a/gic.h b/arch/arm/src/armv7-a/gic.h index 709d5ef673..153f74dd90 100644 --- a/arch/arm/src/armv7-a/gic.h +++ b/arch/arm/src/armv7-a/gic.h @@ -49,8 +49,12 @@ ****************************************************************************/ #include "nuttx/config.h" + +#include #include + #include "mpcore.h" +#include "up_arch.h" #ifdef CONFIG_ARMV7A_HAVE_GICv2 @@ -588,17 +592,100 @@ #define GIC_IRQ_SPI 32 /* First SPI interrupt ID */ +/* General Macro Definitions ************************************************/ +/* Debug */ + +#ifdef CONFIG_DEBUG_IRQ +# define gicdbg(format, ...) dbg(format, ##__VA_ARGS__) +# define giclldbg(format, ...) lldbg(format, ##__VA_ARGS__) +# define gicvdbg(format, ...) vdbg(format, ##__VA_ARGS__) +# define gicllvdbg(format, ...) llvdbg(format, ##__VA_ARGS__) +#else +# define gicdbg(x...) +# define giclldbg(x...) +# define gicvdbg(x...) +# define gicllvdbg(x...) +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: arm_gic_nlines + * + * Description: + * Return the number of interrupt lines supported by this GIC + * implementation (include both PPIs (32) and SPIs). + * + * Input Parameters: + * None + * + * Returned Value: + * The number of interrupt lines. + * + ****************************************************************************/ + +static inline unsigned int arm_gic_nlines(void) +{ + uint32_t regval; + uint32_t field; + + /* Get the number of interrupt lines. */ + + regval = getreg32(GIC_ICDICTR); + field = (regval & GIC_ICDICTR_ITLINES_MASK) >> GIC_ICDICTR_ITLINES_SHIFT; + return (field + 1) << 5; +} + +/**************************************************************************** + * Name: arm_cpu_sgi + * + * Description: + * Perform a Software Generated Interrupt (SGI). If CONFIG_SMP is + * selected, then the SGI is sent to all CPUs specified in the CPU set. + * That set may include the current CPU. + * + * If CONFIG_SMP is not selected, the cpuset is ignored and SGI is sent + * only to the current CPU. + * + * Input Paramters + * sgi - The SGI interrupt ID (0-15) + * cpuset - The set of CPUs to receive the SGI + * + * Returned Value: + * OK is always returned at present. + * + ****************************************************************************/ + +static inline int arm_cpu_sgi(int sgi, unsigned int cpuset) +{ + uint32_t regval; + +#ifdef CONFIG_SMP + regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(cpuset) | + GIC_ICDSGIR_TGTFILTER_LIST; +#else + regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(0) | + GIC_ICDSGIR_TGTFILTER_THIS; +#endif + + putreg32(regval, GIC_ICDSGIR); + return OK; +} + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -#ifndef __ASSEMBLY__ #ifdef __cplusplus -#define EXTERN extern "C" +# define EXTERN extern "C" extern "C" { #else -#define EXTERN extern +# define EXTERN extern #endif /**************************************************************************** @@ -652,28 +739,6 @@ void arm_gic_initialize(void); uint32_t *arm_decodeirq(uint32_t *regs); -/**************************************************************************** - * Name: arm_cpu_sgi - * - * Description: - * Perform a Software Generated Interrupt (SGI). If CONFIG_SMP is - * selected, then the SGI is sent to all CPUs specified in the CPU set. - * That set may include the current CPU. - * - * If CONFIG_SMP is not selected, the cpuset is ignored and SGI is sent - * only to the current CPU. - * - * Input Paramters - * sgi - The SGI interrupt ID (0-15) - * cpuset - The set of CPUs to receive the SGI - * - * Returned Value: - * OK is always retured at present. - * - ****************************************************************************/ - -int arm_cpu_sgi(int sgi, unsigned int cpuset); - /**************************************************************************** * Name: arm_start_handler * @@ -718,6 +783,28 @@ int arm_start_handler(int irq, FAR void *context); int arm_pause_handler(int irq, FAR void *context); #endif +/**************************************************************************** + * Name: arm_gic_dump + * + * Description: + * Dump GIC registers to the SYSLOG device + * + * Input Parameters: + * msg - Message to print with the register data + * all - True: Dump all IRQs; False: Dump only registers for this IRQ + * irq - if all == false, then dump only this IRQ. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_IRQ +void arm_gic_dump(const char *msg, bool all, int irq); +#else +# define arm_gic_dump(m,a,i) +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/arch/arm/src/imx6/Make.defs b/arch/arm/src/imx6/Make.defs index fb176d44a5..8ddf77b5e8 100644 --- a/arch/arm/src/imx6/Make.defs +++ b/arch/arm/src/imx6/Make.defs @@ -80,6 +80,10 @@ ifeq ($(CONFIG_SMP),y) CMN_CSRCS += arm_cpuindex.c arm_cpustart.c arm_cpupause.c endif +ifeq ($(CONFIG_DEBUG_IRQ),y) +CMN_CSRCS += arm_gicv2_dump.c +endif + # Use common heap allocation for now (may need to be customized later) CMN_CSRCS += up_allocateheap.c