提交 479c901f 编写于 作者: D Darius Augulis 提交者: Sascha Hauer

MXC: Lets handle IRQ by priority, defined with exported API function

Signed-off-by: NDarius Augulis <augulis.darius@gmail.com>
Signed-off-by: NSascha Hauer <s.hauer@pengutronix.de>
上级 d7568f79
...@@ -23,4 +23,15 @@ source "arch/arm/mach-mx3/Kconfig" ...@@ -23,4 +23,15 @@ source "arch/arm/mach-mx3/Kconfig"
endmenu 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 endif
...@@ -9,11 +9,17 @@ ...@@ -9,11 +9,17 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#define AVIC_NIMASK 0x04
@ this macro disables fast irq (not implemented) @ this macro disables fast irq (not implemented)
.macro disable_fiq .macro disable_fiq
.endm .endm
.macro get_irqnr_preamble, base, tmp .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 .endm
.macro arch_ret_to_user, tmp1, tmp2 .macro arch_ret_to_user, tmp1, tmp2
...@@ -23,7 +29,6 @@ ...@@ -23,7 +29,6 @@
@ and returns its number in irqnr @ and returns its number in irqnr
@ and returns if an interrupt occured in irqstat @ and returns if an interrupt occured in irqstat
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \base, =AVIC_IO_ADDRESS(AVIC_BASE_ADDR)
@ Load offset & priority of the highest priority @ Load offset & priority of the highest priority
@ interrupt pending from AVIC_NIVECSR @ interrupt pending from AVIC_NIVECSR
ldr \irqstat, [\base, #0x40] ldr \irqstat, [\base, #0x40]
...@@ -32,6 +37,11 @@ ...@@ -32,6 +37,11 @@
mov \irqnr, \irqstat, asr #16 mov \irqnr, \irqstat, asr #16
@ set zero flag if IRQ + 1 == 0 @ set zero flag if IRQ + 1 == 0
adds \tmp, \irqnr, #1 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 .endm
@ irq priority table (not used) @ irq priority table (not used)
......
...@@ -12,5 +12,6 @@ ...@@ -12,5 +12,6 @@
#define __ASM_ARCH_MXC_IRQS_H__ #define __ASM_ARCH_MXC_IRQS_H__
#include <mach/hardware.h> #include <mach/hardware.h>
extern void imx_irq_set_priority(unsigned char irq, unsigned char prio);
#endif /* __ASM_ARCH_MXC_IRQS_H__ */ #endif /* __ASM_ARCH_MXC_IRQS_H__ */
...@@ -30,14 +30,7 @@ ...@@ -30,14 +30,7 @@
#define AVIC_INTENABLEL (AVIC_BASE + 0x14) /* int enable reg low */ #define AVIC_INTENABLEL (AVIC_BASE + 0x14) /* int enable reg low */
#define AVIC_INTTYPEH (AVIC_BASE + 0x18) /* int type reg high */ #define AVIC_INTTYPEH (AVIC_BASE + 0x18) /* int type reg high */
#define AVIC_INTTYPEL (AVIC_BASE + 0x1C) /* int type reg low */ #define AVIC_INTTYPEL (AVIC_BASE + 0x1C) /* int type reg low */
#define AVIC_NIPRIORITY7 (AVIC_BASE + 0x20) /* norm int priority lvl7 */ #define AVIC_NIPRIORITY(x) (AVIC_BASE + (0x20 + 4 * (7 - (x)))) /* int priority */
#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_NIVECSR (AVIC_BASE + 0x40) /* norm int vector/status */ #define AVIC_NIVECSR (AVIC_BASE + 0x40) /* norm int vector/status */
#define AVIC_FIVECSR (AVIC_BASE + 0x44) /* fast int vector/status */ #define AVIC_FIVECSR (AVIC_BASE + 0x44) /* fast int vector/status */
#define AVIC_INTSRCH (AVIC_BASE + 0x48) /* int source reg high */ #define AVIC_INTSRCH (AVIC_BASE + 0x48) /* int source reg high */
...@@ -54,6 +47,24 @@ ...@@ -54,6 +47,24 @@
#define IIM_PROD_REV_SH 3 #define IIM_PROD_REV_SH 3
#define IIM_PROD_REV_LEN 5 #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 */ /* Disable interrupt number "irq" in the AVIC */
static void mxc_mask_irq(unsigned int irq) static void mxc_mask_irq(unsigned int irq)
{ {
...@@ -101,10 +112,14 @@ void __init mxc_init_irq(void) ...@@ -101,10 +112,14 @@ void __init mxc_init_irq(void)
set_irq_flags(i, IRQF_VALID); 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) */ /* 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); reg |= (0xF << 28);
__raw_writel(reg, AVIC_NIPRIORITY6); __raw_writel(reg, AVIC_NIPRIORITY(6));
/* init architectures chained interrupt handler */ /* init architectures chained interrupt handler */
mxc_register_gpios(); mxc_register_gpios();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册