diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/include/asm/irq.h | 16 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/setup-sh7786.c | 36 | ||||
-rw-r--r-- | arch/sh/kernel/irq.c | 49 |
3 files changed, 75 insertions, 26 deletions
diff --git a/arch/sh/include/asm/irq.h b/arch/sh/include/asm/irq.h index df8e1500527c..99c593b3a827 100644 --- a/arch/sh/include/asm/irq.h +++ b/arch/sh/include/asm/irq.h | |||
@@ -12,6 +12,14 @@ | |||
12 | #define NR_IRQS_LEGACY 8 /* Legacy external IRQ0-7 */ | 12 | #define NR_IRQS_LEGACY 8 /* Legacy external IRQ0-7 */ |
13 | 13 | ||
14 | /* | 14 | /* |
15 | * This is a special IRQ number for indicating that no IRQ has been | ||
16 | * triggered and to simply ignore the IRQ dispatch. This is a special | ||
17 | * case that can happen with IRQ auto-distribution when multiple CPUs | ||
18 | * are woken up and signalled in parallel. | ||
19 | */ | ||
20 | #define NO_IRQ_IGNORE ((unsigned int)-1) | ||
21 | |||
22 | /* | ||
15 | * Convert back and forth between INTEVT and IRQ values. | 23 | * Convert back and forth between INTEVT and IRQ values. |
16 | */ | 24 | */ |
17 | #ifdef CONFIG_CPU_HAS_INTEVT | 25 | #ifdef CONFIG_CPU_HAS_INTEVT |
@@ -53,6 +61,14 @@ extern void irq_ctx_exit(int cpu); | |||
53 | # define irq_ctx_exit(cpu) do { } while (0) | 61 | # define irq_ctx_exit(cpu) do { } while (0) |
54 | #endif | 62 | #endif |
55 | 63 | ||
64 | #ifdef CONFIG_INTC_BALANCING | ||
65 | extern unsigned int irq_lookup(unsigned int irq); | ||
66 | extern void irq_finish(unsigned int irq); | ||
67 | #else | ||
68 | #define irq_lookup(irq) (irq) | ||
69 | #define irq_finish(irq) do { } while (0) | ||
70 | #endif | ||
71 | |||
56 | #include <asm-generic/irq.h> | 72 | #include <asm-generic/irq.h> |
57 | #ifdef CONFIG_CPU_SH5 | 73 | #ifdef CONFIG_CPU_SH5 |
58 | #include <cpu/irq.h> | 74 | #include <cpu/irq.h> |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 235edf8065df..d7336036d04d 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c | |||
@@ -573,7 +573,6 @@ static struct platform_device *sh7786_devices[] __initdata = { | |||
573 | &usb_ohci_device, | 573 | &usb_ohci_device, |
574 | }; | 574 | }; |
575 | 575 | ||
576 | |||
577 | /* | 576 | /* |
578 | * Please call this function if your platform board | 577 | * Please call this function if your platform board |
579 | * use external clock for USB | 578 | * use external clock for USB |
@@ -581,6 +580,7 @@ static struct platform_device *sh7786_devices[] __initdata = { | |||
581 | #define USBCTL0 0xffe70858 | 580 | #define USBCTL0 0xffe70858 |
582 | #define CLOCK_MODE_MASK 0xffffff7f | 581 | #define CLOCK_MODE_MASK 0xffffff7f |
583 | #define EXT_CLOCK_MODE 0x00000080 | 582 | #define EXT_CLOCK_MODE 0x00000080 |
583 | |||
584 | void __init sh7786_usb_use_exclock(void) | 584 | void __init sh7786_usb_use_exclock(void) |
585 | { | 585 | { |
586 | u32 val = __raw_readl(USBCTL0) & CLOCK_MODE_MASK; | 586 | u32 val = __raw_readl(USBCTL0) & CLOCK_MODE_MASK; |
@@ -598,6 +598,7 @@ void __init sh7786_usb_use_exclock(void) | |||
598 | #define PLL_ENB 0x00000002 | 598 | #define PLL_ENB 0x00000002 |
599 | #define PHY_RST 0x00000004 | 599 | #define PHY_RST 0x00000004 |
600 | #define ACT_PLL_STATUS 0xc0000000 | 600 | #define ACT_PLL_STATUS 0xc0000000 |
601 | |||
601 | static void __init sh7786_usb_setup(void) | 602 | static void __init sh7786_usb_setup(void) |
602 | { | 603 | { |
603 | int i = 1000000; | 604 | int i = 1000000; |
@@ -753,9 +754,19 @@ static struct intc_vect vectors[] __initdata = { | |||
753 | #define INTMSK2 0xfe410068 | 754 | #define INTMSK2 0xfe410068 |
754 | #define INTMSKCLR2 0xfe41006c | 755 | #define INTMSKCLR2 0xfe41006c |
755 | 756 | ||
757 | #define INTDISTCR0 0xfe4100b0 | ||
758 | #define INTDISTCR1 0xfe4100b4 | ||
759 | #define INTACK 0xfe4100b8 | ||
760 | #define INTACKCLR 0xfe4100bc | ||
761 | #define INT2DISTCR0 0xfe410900 | ||
762 | #define INT2DISTCR1 0xfe410904 | ||
763 | #define INT2DISTCR2 0xfe410908 | ||
764 | #define INT2DISTCR3 0xfe41090c | ||
765 | |||
756 | static struct intc_mask_reg mask_registers[] __initdata = { | 766 | static struct intc_mask_reg mask_registers[] __initdata = { |
757 | { CnINTMSK0, CnINTMSKCLR0, 32, | 767 | { CnINTMSK0, CnINTMSKCLR0, 32, |
758 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, | 768 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 }, |
769 | INTC_SMP_BALANCING(INTDISTCR0) }, | ||
759 | { INTMSK2, INTMSKCLR2, 32, | 770 | { INTMSK2, INTMSKCLR2, 32, |
760 | { IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH, | 771 | { IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH, |
761 | IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH, | 772 | IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH, |
@@ -767,7 +778,8 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
767 | IRL4_HHLL, IRL4_HHLH, IRL4_HHHL, 0, } }, | 778 | IRL4_HHLL, IRL4_HHLH, IRL4_HHHL, 0, } }, |
768 | { CnINT2MSKR0, CnINT2MSKCR0 , 32, | 779 | { CnINT2MSKR0, CnINT2MSKCR0 , 32, |
769 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 780 | { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
770 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WDT } }, | 781 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WDT }, |
782 | INTC_SMP_BALANCING(INT2DISTCR0) }, | ||
771 | { CnINT2MSKR1, CnINT2MSKCR1, 32, | 783 | { CnINT2MSKR1, CnINT2MSKCR1, 32, |
772 | { TMU0_0, TMU0_1, TMU0_2, TMU0_3, TMU1_0, TMU1_1, TMU1_2, 0, | 784 | { TMU0_0, TMU0_1, TMU0_2, TMU0_3, TMU1_0, TMU1_1, TMU1_2, 0, |
773 | DMAC0_0, DMAC0_1, DMAC0_2, DMAC0_3, DMAC0_4, DMAC0_5, DMAC0_6, | 785 | DMAC0_0, DMAC0_1, DMAC0_2, DMAC0_3, DMAC0_4, DMAC0_5, DMAC0_6, |
@@ -776,14 +788,14 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
776 | HPB_0, HPB_1, HPB_2, | 788 | HPB_0, HPB_1, HPB_2, |
777 | SCIF0_0, SCIF0_1, SCIF0_2, SCIF0_3, | 789 | SCIF0_0, SCIF0_1, SCIF0_2, SCIF0_3, |
778 | SCIF1, | 790 | SCIF1, |
779 | TMU2, TMU3, 0, } }, | 791 | TMU2, TMU3, 0, }, INTC_SMP_BALANCING(INT2DISTCR1) }, |
780 | { CnINT2MSKR2, CnINT2MSKCR2, 32, | 792 | { CnINT2MSKR2, CnINT2MSKCR2, 32, |
781 | { 0, 0, SCIF2, SCIF3, SCIF4, SCIF5, | 793 | { 0, 0, SCIF2, SCIF3, SCIF4, SCIF5, |
782 | Eth_0, Eth_1, | 794 | Eth_0, Eth_1, |
783 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 795 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
784 | PCIeC0_0, PCIeC0_1, PCIeC0_2, | 796 | PCIeC0_0, PCIeC0_1, PCIeC0_2, |
785 | PCIeC1_0, PCIeC1_1, PCIeC1_2, | 797 | PCIeC1_0, PCIeC1_1, PCIeC1_2, |
786 | USB, 0, 0 } }, | 798 | USB, 0, 0 }, INTC_SMP_BALANCING(INT2DISTCR2) }, |
787 | { CnINT2MSKR3, CnINT2MSKCR3, 32, | 799 | { CnINT2MSKR3, CnINT2MSKCR3, 32, |
788 | { 0, 0, 0, 0, 0, 0, | 800 | { 0, 0, 0, 0, 0, 0, |
789 | I2C0, I2C1, | 801 | I2C0, I2C1, |
@@ -792,7 +804,7 @@ static struct intc_mask_reg mask_registers[] __initdata = { | |||
792 | HAC0, HAC1, | 804 | HAC0, HAC1, |
793 | FLCTL, 0, | 805 | FLCTL, 0, |
794 | HSPI, GPIO0, GPIO1, Thermal, | 806 | HSPI, GPIO0, GPIO1, Thermal, |
795 | 0, 0, 0, 0, 0, 0, 0, 0 } }, | 807 | 0, 0, 0, 0, 0, 0, 0, 0 }, INTC_SMP_BALANCING(INT2DISTCR3) }, |
796 | }; | 808 | }; |
797 | 809 | ||
798 | static struct intc_prio_reg prio_registers[] __initdata = { | 810 | static struct intc_prio_reg prio_registers[] __initdata = { |
@@ -910,6 +922,18 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567, | |||
910 | #define INTC_INTMSKCLR2 INTMSKCLR2 | 922 | #define INTC_INTMSKCLR2 INTMSKCLR2 |
911 | #define INTC_USERIMASK 0xfe411000 | 923 | #define INTC_USERIMASK 0xfe411000 |
912 | 924 | ||
925 | #ifdef CONFIG_INTC_BALANCING | ||
926 | unsigned int irq_lookup(unsigned int irq) | ||
927 | { | ||
928 | return __raw_readl(INTACK) & 1 ? irq : NO_IRQ_IGNORE; | ||
929 | } | ||
930 | |||
931 | void irq_finish(unsigned int irq) | ||
932 | { | ||
933 | __raw_writel(irq2evt(irq), INTACKCLR); | ||
934 | } | ||
935 | #endif | ||
936 | |||
913 | void __init plat_irq_setup(void) | 937 | void __init plat_irq_setup(void) |
914 | { | 938 | { |
915 | /* disable IRQ3-0 + IRQ7-4 */ | 939 | /* disable IRQ3-0 + IRQ7-4 */ |
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index d2d41d046657..f6a9319c28e2 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c | |||
@@ -113,19 +113,14 @@ union irq_ctx { | |||
113 | 113 | ||
114 | static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; | 114 | static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; |
115 | static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; | 115 | static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; |
116 | #endif | ||
117 | 116 | ||
118 | asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs) | 117 | static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; |
118 | static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; | ||
119 | |||
120 | static inline void handle_one_irq(unsigned int irq) | ||
119 | { | 121 | { |
120 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
121 | #ifdef CONFIG_IRQSTACKS | ||
122 | union irq_ctx *curctx, *irqctx; | 122 | union irq_ctx *curctx, *irqctx; |
123 | #endif | ||
124 | |||
125 | irq_enter(); | ||
126 | irq = irq_demux(irq); | ||
127 | 123 | ||
128 | #ifdef CONFIG_IRQSTACKS | ||
129 | curctx = (union irq_ctx *)current_thread_info(); | 124 | curctx = (union irq_ctx *)current_thread_info(); |
130 | irqctx = hardirq_ctx[smp_processor_id()]; | 125 | irqctx = hardirq_ctx[smp_processor_id()]; |
131 | 126 | ||
@@ -164,20 +159,9 @@ asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs) | |||
164 | "r5", "r6", "r7", "r8", "t", "pr" | 159 | "r5", "r6", "r7", "r8", "t", "pr" |
165 | ); | 160 | ); |
166 | } else | 161 | } else |
167 | #endif | ||
168 | generic_handle_irq(irq); | 162 | generic_handle_irq(irq); |
169 | |||
170 | irq_exit(); | ||
171 | |||
172 | set_irq_regs(old_regs); | ||
173 | return 1; | ||
174 | } | 163 | } |
175 | 164 | ||
176 | #ifdef CONFIG_IRQSTACKS | ||
177 | static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; | ||
178 | |||
179 | static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; | ||
180 | |||
181 | /* | 165 | /* |
182 | * allocate per-cpu stacks for hardirq and for softirq processing | 166 | * allocate per-cpu stacks for hardirq and for softirq processing |
183 | */ | 167 | */ |
@@ -257,8 +241,33 @@ asmlinkage void do_softirq(void) | |||
257 | 241 | ||
258 | local_irq_restore(flags); | 242 | local_irq_restore(flags); |
259 | } | 243 | } |
244 | #else | ||
245 | static inline void handle_one_irq(unsigned int irq) | ||
246 | { | ||
247 | generic_handle_irq(irq); | ||
248 | } | ||
260 | #endif | 249 | #endif |
261 | 250 | ||
251 | asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs) | ||
252 | { | ||
253 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
254 | |||
255 | irq_enter(); | ||
256 | |||
257 | irq = irq_demux(irq_lookup(irq)); | ||
258 | |||
259 | if (irq != NO_IRQ_IGNORE) { | ||
260 | handle_one_irq(irq); | ||
261 | irq_finish(irq); | ||
262 | } | ||
263 | |||
264 | irq_exit(); | ||
265 | |||
266 | set_irq_regs(old_regs); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
262 | void __init init_IRQ(void) | 271 | void __init init_IRQ(void) |
263 | { | 272 | { |
264 | plat_irq_setup(); | 273 | plat_irq_setup(); |