aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/kernel/intc-arcv2.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/kernel/intc-arcv2.c')
-rw-r--r--arch/arc/kernel/intc-arcv2.c41
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
17static 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
73static void arcv2_irq_mask(struct irq_data *data) 80static 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