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>
This commit is contained in:
parent
d7568f79d5
commit
479c901f59
4 changed files with 48 additions and 11 deletions
|
@ -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 @@
|
||||||
* 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 @@
|
||||||
@ 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 @@
|
||||||
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 @@
|
||||||
#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 @@
|
||||||
#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 @@
|
||||||
#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)
|
||||||
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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue