]> git.karo-electronics.de Git - linux-beck.git/commitdiff
MXC: Lets handle IRQ by priority, defined with exported API function
authorDarius Augulis <augulis.darius@gmail.com>
Tue, 9 Sep 2008 09:29:41 +0000 (11:29 +0200)
committerSascha Hauer <s.hauer@pengutronix.de>
Tue, 9 Sep 2008 10:13:50 +0000 (12:13 +0200)
Signed-off-by: Darius Augulis <augulis.darius@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
arch/arm/plat-mxc/Kconfig
arch/arm/plat-mxc/include/mach/entry-macro.S
arch/arm/plat-mxc/include/mach/irqs.h
arch/arm/plat-mxc/irq.c

index e14eaad11dd5aec3c330a0ac43d1e9d24b91bb41..b2a7e3fad117f44c97160c191ab8e34eff66dc0a 100644 (file)
@@ -23,4 +23,15 @@ source "arch/arm/mach-mx3/Kconfig"
 
 endmenu
 
+config MXC_IRQ_PRIOR
+       bool "Use IRQ priority"
+       depends on ARCH_MXC
+       help
+         Select this if you want to use prioritized IRQ handling.
+         This feature prevents higher priority ISR to be interrupted
+         by lower priority IRQ even IRQF_DISABLED flag is not set.
+         This may be useful in embedded applications, where are strong
+         requirements for timing.
+         Say N here, unless you have a specialized requirement.
+
 endif
index b542433afb1b45358de508e7bc09a91085aa2989..11632028f7d1ba6f44610c373b52b2721ea81cf4 100644 (file)
@@ -9,11 +9,17 @@
  * published by the Free Software Foundation.
  */
 
+#define AVIC_NIMASK    0x04
+
        @ this macro disables fast irq (not implemented)
        .macro  disable_fiq
        .endm
 
        .macro  get_irqnr_preamble, base, tmp
+       ldr     \base, =AVIC_IO_ADDRESS(AVIC_BASE_ADDR)
+#ifdef CONFIG_MXC_IRQ_PRIOR
+       ldr     r4, [\base, #AVIC_NIMASK]
+#endif
        .endm
 
        .macro  arch_ret_to_user, tmp1, tmp2
@@ -23,7 +29,6 @@
        @ and returns its number in irqnr
        @ and returns if an interrupt occured in irqstat
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \base, =AVIC_IO_ADDRESS(AVIC_BASE_ADDR)
        @ Load offset & priority of the highest priority
        @ interrupt pending from AVIC_NIVECSR
        ldr     \irqstat, [\base, #0x40]
        mov     \irqnr, \irqstat, asr #16
        @ set zero flag if IRQ + 1 == 0
        adds    \tmp, \irqnr, #1
+#ifdef CONFIG_MXC_IRQ_PRIOR
+       bicne   \tmp, \irqstat, #0xFFFFFFE0
+       strne   \tmp, [\base, #AVIC_NIMASK]
+       streq   r4, [\base, #AVIC_NIMASK]
+#endif
        .endm
 
        @ irq priority table (not used)
index 228c4f68ccdf1bce6fcaa8a7a1f56bd4689bc716..b55bba35e18a83e002bceb3d45835b3aa8ee9f3c 100644 (file)
@@ -12,5 +12,6 @@
 #define __ASM_ARCH_MXC_IRQS_H__
 
 #include <mach/hardware.h>
+extern void imx_irq_set_priority(unsigned char irq, unsigned char prio);
 
 #endif /* __ASM_ARCH_MXC_IRQS_H__ */
index 1053b666c676fd5217226fd3301ca90d23ca6e3f..a41abf0bdd6649235b9ac64840aae5e1cf03fa34 100644 (file)
 #define AVIC_INTENABLEL                (AVIC_BASE + 0x14)      /* int enable reg low */
 #define AVIC_INTTYPEH          (AVIC_BASE + 0x18)      /* int type reg high */
 #define AVIC_INTTYPEL          (AVIC_BASE + 0x1C)      /* int type reg low */
-#define AVIC_NIPRIORITY7       (AVIC_BASE + 0x20)      /* norm int priority lvl7 */
-#define AVIC_NIPRIORITY6       (AVIC_BASE + 0x24)      /* norm int priority lvl6 */
-#define AVIC_NIPRIORITY5       (AVIC_BASE + 0x28)      /* norm int priority lvl5 */
-#define AVIC_NIPRIORITY4       (AVIC_BASE + 0x2C)      /* norm int priority lvl4 */
-#define AVIC_NIPRIORITY3       (AVIC_BASE + 0x30)      /* norm int priority lvl3 */
-#define AVIC_NIPRIORITY2       (AVIC_BASE + 0x34)      /* norm int priority lvl2 */
-#define AVIC_NIPRIORITY1       (AVIC_BASE + 0x38)      /* norm int priority lvl1 */
-#define AVIC_NIPRIORITY0       (AVIC_BASE + 0x3C)      /* norm int priority lvl0 */
+#define AVIC_NIPRIORITY(x)     (AVIC_BASE + (0x20 + 4 * (7 - (x)))) /* int priority */
 #define AVIC_NIVECSR           (AVIC_BASE + 0x40)      /* norm int vector/status */
 #define AVIC_FIVECSR           (AVIC_BASE + 0x44)      /* fast int vector/status */
 #define AVIC_INTSRCH           (AVIC_BASE + 0x48)      /* int source reg high */
 #define IIM_PROD_REV_SH                3
 #define IIM_PROD_REV_LEN       5
 
+#ifdef CONFIG_MXC_IRQ_PRIOR
+void imx_irq_set_priority(unsigned char irq, unsigned char prio)
+{
+       unsigned int temp;
+       unsigned int mask = 0x0F << irq % 8 * 4;
+
+       if (irq > 63)
+               return;
+
+       temp = __raw_readl(AVIC_NIPRIORITY(irq / 8));
+       temp &= ~mask;
+       temp |= prio & mask;
+
+       __raw_writel(temp, AVIC_NIPRIORITY(irq / 8));
+}
+EXPORT_SYMBOL(imx_irq_set_priority);
+#endif
+
 /* Disable interrupt number "irq" in the AVIC */
 static void mxc_mask_irq(unsigned int irq)
 {
@@ -101,10 +112,14 @@ void __init mxc_init_irq(void)
                set_irq_flags(i, IRQF_VALID);
        }
 
+       /* Set default priority value (0) for all IRQ's */
+       for (i = 0; i < 8; i++)
+               __raw_writel(0, AVIC_NIPRIORITY(i));
+
        /* Set WDOG2's interrupt the highest priority level (bit 28-31) */
-       reg = __raw_readl(AVIC_NIPRIORITY6);
+       reg = __raw_readl(AVIC_NIPRIORITY(6));
        reg |= (0xF << 28);
-       __raw_writel(reg, AVIC_NIPRIORITY6);
+       __raw_writel(reg, AVIC_NIPRIORITY(6));
 
        /* init architectures chained interrupt handler */
        mxc_register_gpios();