diff options
author | Darius Augulis <augulis.darius@gmail.com> | 2008-09-09 05:29:41 -0400 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2008-09-09 06:13:50 -0400 |
commit | 479c901f59762732dee305166ae477171cae3617 (patch) | |
tree | b061499771021b431d54ec46fe66b3b31be4a37f /arch/arm/plat-mxc | |
parent | d7568f79d5c289d0d7859680be7b5afdcea0c9b2 (diff) |
MXC: Lets handle IRQ by priority, defined with exported API function
Signed-off-by: Darius Augulis <augulis.darius@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/plat-mxc')
-rw-r--r-- | arch/arm/plat-mxc/Kconfig | 11 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/entry-macro.S | 12 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/irqs.h | 1 | ||||
-rw-r--r-- | arch/arm/plat-mxc/irq.c | 35 |
4 files changed, 48 insertions, 11 deletions
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index e14eaad11dd5..b2a7e3fad117 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig | |||
@@ -23,4 +23,15 @@ source "arch/arm/mach-mx3/Kconfig" | |||
23 | 23 | ||
24 | endmenu | 24 | endmenu |
25 | 25 | ||
26 | config MXC_IRQ_PRIOR | ||
27 | bool "Use IRQ priority" | ||
28 | depends on ARCH_MXC | ||
29 | help | ||
30 | Select this if you want to use prioritized IRQ handling. | ||
31 | This feature prevents higher priority ISR to be interrupted | ||
32 | by lower priority IRQ even IRQF_DISABLED flag is not set. | ||
33 | This may be useful in embedded applications, where are strong | ||
34 | requirements for timing. | ||
35 | Say N here, unless you have a specialized requirement. | ||
36 | |||
26 | endif | 37 | endif |
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S index b542433afb1b..11632028f7d1 100644 --- a/arch/arm/plat-mxc/include/mach/entry-macro.S +++ b/arch/arm/plat-mxc/include/mach/entry-macro.S | |||
@@ -9,11 +9,17 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #define AVIC_NIMASK 0x04 | ||
13 | |||
12 | @ this macro disables fast irq (not implemented) | 14 | @ this macro disables fast irq (not implemented) |
13 | .macro disable_fiq | 15 | .macro disable_fiq |
14 | .endm | 16 | .endm |
15 | 17 | ||
16 | .macro get_irqnr_preamble, base, tmp | 18 | .macro get_irqnr_preamble, base, tmp |
19 | ldr \base, =AVIC_IO_ADDRESS(AVIC_BASE_ADDR) | ||
20 | #ifdef CONFIG_MXC_IRQ_PRIOR | ||
21 | ldr r4, [\base, #AVIC_NIMASK] | ||
22 | #endif | ||
17 | .endm | 23 | .endm |
18 | 24 | ||
19 | .macro arch_ret_to_user, tmp1, tmp2 | 25 | .macro arch_ret_to_user, tmp1, tmp2 |
@@ -23,7 +29,6 @@ | |||
23 | @ and returns its number in irqnr | 29 | @ and returns its number in irqnr |
24 | @ and returns if an interrupt occured in irqstat | 30 | @ and returns if an interrupt occured in irqstat |
25 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | 31 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp |
26 | ldr \base, =AVIC_IO_ADDRESS(AVIC_BASE_ADDR) | ||
27 | @ Load offset & priority of the highest priority | 32 | @ Load offset & priority of the highest priority |
28 | @ interrupt pending from AVIC_NIVECSR | 33 | @ interrupt pending from AVIC_NIVECSR |
29 | ldr \irqstat, [\base, #0x40] | 34 | ldr \irqstat, [\base, #0x40] |
@@ -32,6 +37,11 @@ | |||
32 | mov \irqnr, \irqstat, asr #16 | 37 | mov \irqnr, \irqstat, asr #16 |
33 | @ set zero flag if IRQ + 1 == 0 | 38 | @ set zero flag if IRQ + 1 == 0 |
34 | adds \tmp, \irqnr, #1 | 39 | adds \tmp, \irqnr, #1 |
40 | #ifdef CONFIG_MXC_IRQ_PRIOR | ||
41 | bicne \tmp, \irqstat, #0xFFFFFFE0 | ||
42 | strne \tmp, [\base, #AVIC_NIMASK] | ||
43 | streq r4, [\base, #AVIC_NIMASK] | ||
44 | #endif | ||
35 | .endm | 45 | .endm |
36 | 46 | ||
37 | @ irq priority table (not used) | 47 | @ irq priority table (not used) |
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h index 228c4f68ccdf..b55bba35e18a 100644 --- a/arch/arm/plat-mxc/include/mach/irqs.h +++ b/arch/arm/plat-mxc/include/mach/irqs.h | |||
@@ -12,5 +12,6 @@ | |||
12 | #define __ASM_ARCH_MXC_IRQS_H__ | 12 | #define __ASM_ARCH_MXC_IRQS_H__ |
13 | 13 | ||
14 | #include <mach/hardware.h> | 14 | #include <mach/hardware.h> |
15 | extern void imx_irq_set_priority(unsigned char irq, unsigned char prio); | ||
15 | 16 | ||
16 | #endif /* __ASM_ARCH_MXC_IRQS_H__ */ | 17 | #endif /* __ASM_ARCH_MXC_IRQS_H__ */ |
diff --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c index 1053b666c676..a41abf0bdd66 100644 --- a/arch/arm/plat-mxc/irq.c +++ b/arch/arm/plat-mxc/irq.c | |||
@@ -30,14 +30,7 @@ | |||
30 | #define AVIC_INTENABLEL (AVIC_BASE + 0x14) /* int enable reg low */ | 30 | #define AVIC_INTENABLEL (AVIC_BASE + 0x14) /* int enable reg low */ |
31 | #define AVIC_INTTYPEH (AVIC_BASE + 0x18) /* int type reg high */ | 31 | #define AVIC_INTTYPEH (AVIC_BASE + 0x18) /* int type reg high */ |
32 | #define AVIC_INTTYPEL (AVIC_BASE + 0x1C) /* int type reg low */ | 32 | #define AVIC_INTTYPEL (AVIC_BASE + 0x1C) /* int type reg low */ |
33 | #define AVIC_NIPRIORITY7 (AVIC_BASE + 0x20) /* norm int priority lvl7 */ | 33 | #define AVIC_NIPRIORITY(x) (AVIC_BASE + (0x20 + 4 * (7 - (x)))) /* int priority */ |
34 | #define AVIC_NIPRIORITY6 (AVIC_BASE + 0x24) /* norm int priority lvl6 */ | ||
35 | #define AVIC_NIPRIORITY5 (AVIC_BASE + 0x28) /* norm int priority lvl5 */ | ||
36 | #define AVIC_NIPRIORITY4 (AVIC_BASE + 0x2C) /* norm int priority lvl4 */ | ||
37 | #define AVIC_NIPRIORITY3 (AVIC_BASE + 0x30) /* norm int priority lvl3 */ | ||
38 | #define AVIC_NIPRIORITY2 (AVIC_BASE + 0x34) /* norm int priority lvl2 */ | ||
39 | #define AVIC_NIPRIORITY1 (AVIC_BASE + 0x38) /* norm int priority lvl1 */ | ||
40 | #define AVIC_NIPRIORITY0 (AVIC_BASE + 0x3C) /* norm int priority lvl0 */ | ||
41 | #define AVIC_NIVECSR (AVIC_BASE + 0x40) /* norm int vector/status */ | 34 | #define AVIC_NIVECSR (AVIC_BASE + 0x40) /* norm int vector/status */ |
42 | #define AVIC_FIVECSR (AVIC_BASE + 0x44) /* fast int vector/status */ | 35 | #define AVIC_FIVECSR (AVIC_BASE + 0x44) /* fast int vector/status */ |
43 | #define AVIC_INTSRCH (AVIC_BASE + 0x48) /* int source reg high */ | 36 | #define AVIC_INTSRCH (AVIC_BASE + 0x48) /* int source reg high */ |
@@ -54,6 +47,24 @@ | |||
54 | #define IIM_PROD_REV_SH 3 | 47 | #define IIM_PROD_REV_SH 3 |
55 | #define IIM_PROD_REV_LEN 5 | 48 | #define IIM_PROD_REV_LEN 5 |
56 | 49 | ||
50 | #ifdef CONFIG_MXC_IRQ_PRIOR | ||
51 | void imx_irq_set_priority(unsigned char irq, unsigned char prio) | ||
52 | { | ||
53 | unsigned int temp; | ||
54 | unsigned int mask = 0x0F << irq % 8 * 4; | ||
55 | |||
56 | if (irq > 63) | ||
57 | return; | ||
58 | |||
59 | temp = __raw_readl(AVIC_NIPRIORITY(irq / 8)); | ||
60 | temp &= ~mask; | ||
61 | temp |= prio & mask; | ||
62 | |||
63 | __raw_writel(temp, AVIC_NIPRIORITY(irq / 8)); | ||
64 | } | ||
65 | EXPORT_SYMBOL(imx_irq_set_priority); | ||
66 | #endif | ||
67 | |||
57 | /* Disable interrupt number "irq" in the AVIC */ | 68 | /* Disable interrupt number "irq" in the AVIC */ |
58 | static void mxc_mask_irq(unsigned int irq) | 69 | static void mxc_mask_irq(unsigned int irq) |
59 | { | 70 | { |
@@ -101,10 +112,14 @@ void __init mxc_init_irq(void) | |||
101 | set_irq_flags(i, IRQF_VALID); | 112 | set_irq_flags(i, IRQF_VALID); |
102 | } | 113 | } |
103 | 114 | ||
115 | /* Set default priority value (0) for all IRQ's */ | ||
116 | for (i = 0; i < 8; i++) | ||
117 | __raw_writel(0, AVIC_NIPRIORITY(i)); | ||
118 | |||
104 | /* Set WDOG2's interrupt the highest priority level (bit 28-31) */ | 119 | /* Set WDOG2's interrupt the highest priority level (bit 28-31) */ |
105 | reg = __raw_readl(AVIC_NIPRIORITY6); | 120 | reg = __raw_readl(AVIC_NIPRIORITY(6)); |
106 | reg |= (0xF << 28); | 121 | reg |= (0xF << 28); |
107 | __raw_writel(reg, AVIC_NIPRIORITY6); | 122 | __raw_writel(reg, AVIC_NIPRIORITY(6)); |
108 | 123 | ||
109 | /* init architectures chained interrupt handler */ | 124 | /* init architectures chained interrupt handler */ |
110 | mxc_register_gpios(); | 125 | mxc_register_gpios(); |