diff options
Diffstat (limited to 'arch/arc/kernel/intc-arcv2.c')
-rw-r--r-- | arch/arc/kernel/intc-arcv2.c | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index 0394f9f61b46..942526322ae7 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/irqchip.h> | 14 | #include <linux/irqchip.h> |
15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
16 | 16 | ||
17 | static int irq_prio; | ||
18 | |||
17 | /* | 19 | /* |
18 | * Early Hardware specific Interrupt setup | 20 | * Early Hardware specific Interrupt setup |
19 | * -Called very early (start_kernel -> setup_arch -> setup_processor) | 21 | * -Called very early (start_kernel -> setup_arch -> setup_processor) |
@@ -24,6 +26,14 @@ void arc_init_IRQ(void) | |||
24 | { | 26 | { |
25 | unsigned int tmp; | 27 | unsigned int tmp; |
26 | 28 | ||
29 | struct irq_build { | ||
30 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
31 | unsigned int pad:3, firq:1, prio:4, exts:8, irqs:8, ver:8; | ||
32 | #else | ||
33 | unsigned int ver:8, irqs:8, exts:8, prio:4, firq:1, pad:3; | ||
34 | #endif | ||
35 | } irq_bcr; | ||
36 | |||
27 | struct aux_irq_ctrl { | 37 | struct aux_irq_ctrl { |
28 | #ifdef CONFIG_CPU_BIG_ENDIAN | 38 | #ifdef CONFIG_CPU_BIG_ENDIAN |
29 | unsigned int res3:18, save_idx_regs:1, res2:1, | 39 | unsigned int res3:18, save_idx_regs:1, res2:1, |
@@ -46,28 +56,25 @@ void arc_init_IRQ(void) | |||
46 | 56 | ||
47 | WRITE_AUX(AUX_IRQ_CTRL, ictrl); | 57 | WRITE_AUX(AUX_IRQ_CTRL, ictrl); |
48 | 58 | ||
49 | /* setup status32, don't enable intr yet as kernel doesn't want */ | ||
50 | tmp = read_aux_reg(0xa); | ||
51 | tmp |= ISA_INIT_STATUS_BITS; | ||
52 | tmp &= ~STATUS_IE_MASK; | ||
53 | asm volatile("flag %0 \n"::"r"(tmp)); | ||
54 | |||
55 | /* | 59 | /* |
56 | * ARCv2 core intc provides multiple interrupt priorities (upto 16). | 60 | * ARCv2 core intc provides multiple interrupt priorities (upto 16). |
57 | * Typical builds though have only two levels (0-high, 1-low) | 61 | * Typical builds though have only two levels (0-high, 1-low) |
58 | * Linux by default uses lower prio 1 for most irqs, reserving 0 for | 62 | * Linux by default uses lower prio 1 for most irqs, reserving 0 for |
59 | * NMI style interrupts in future (say perf) | 63 | * NMI style interrupts in future (say perf) |
60 | * | ||
61 | * Read the intc BCR to confirm that Linux default priority is avail | ||
62 | * in h/w | ||
63 | * | ||
64 | * Note: | ||
65 | * IRQ_BCR[27..24] contains N-1 (for N priority levels) and prio level | ||
66 | * is 0 based. | ||
67 | */ | 64 | */ |
68 | tmp = (read_aux_reg(ARC_REG_IRQ_BCR) >> 24 ) & 0xF; | 65 | |
69 | if (ARCV2_IRQ_DEF_PRIO > tmp) | 66 | READ_BCR(ARC_REG_IRQ_BCR, irq_bcr); |
70 | panic("Linux default irq prio incorrect\n"); | 67 | |
68 | irq_prio = irq_bcr.prio; /* Encoded as N-1 for N levels */ | ||
69 | pr_info("archs-intc\t: %d priority levels (default %d)%s\n", | ||
70 | irq_prio + 1, irq_prio, | ||
71 | irq_bcr.firq ? " FIRQ (not used)":""); | ||
72 | |||
73 | /* setup status32, don't enable intr yet as kernel doesn't want */ | ||
74 | tmp = read_aux_reg(0xa); | ||
75 | tmp |= STATUS_AD_MASK | (irq_prio << 1); | ||
76 | tmp &= ~STATUS_IE_MASK; | ||
77 | asm volatile("flag %0 \n"::"r"(tmp)); | ||
71 | } | 78 | } |
72 | 79 | ||
73 | static void arcv2_irq_mask(struct irq_data *data) | 80 | static void arcv2_irq_mask(struct irq_data *data) |
@@ -86,7 +93,7 @@ void arcv2_irq_enable(struct irq_data *data) | |||
86 | { | 93 | { |
87 | /* set default priority */ | 94 | /* set default priority */ |
88 | write_aux_reg(AUX_IRQ_SELECT, data->irq); | 95 | write_aux_reg(AUX_IRQ_SELECT, data->irq); |
89 | write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO); | 96 | write_aux_reg(AUX_IRQ_PRIORITY, irq_prio); |
90 | 97 | ||
91 | /* | 98 | /* |
92 | * hw auto enables (linux unmask) all by default | 99 | * hw auto enables (linux unmask) all by default |