aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-21 13:27:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-21 13:27:19 -0400
commitc207f3a43194e108dda43dc9a1ce507335cff6b9 (patch)
tree55880f8301e8546b1908f69947d0d41aaa044814 /arch/microblaze
parentc7c66c0cb0c77b1a8edf09bca57d922312d58030 (diff)
parente7cc3aca0f6a36b018934264ee20bee45dc13e29 (diff)
Merge tag 'irqdomain-for-linus' of git://git.secretlab.ca/git/linux-2.6
Pull irq_domain support for all architectures from Grant Likely: "Generialize powerpc's irq_host as irq_domain This branch takes the PowerPC irq_host infrastructure (reverse mapping from Linux IRQ numbers to hardware irq numbering), generalizes it, renames it to irq_domain, and makes it available to all architectures. Originally the plan has been to create an all-new irq_domain implementation which addresses some of the powerpc shortcomings such as not handling 1:1 mappings well, but doing that proved to be far more difficult and invasive than generalizing the working code and refactoring it in-place. So, this branch rips out the 'new' irq_domain and replaces it with the modified powerpc version (in a fully bisectable way of course). It converts all users over to the new API and makes irq_domain selectable on any architecture. No architecture is forced to enable irq_domain, but the infrastructure is required for doing OpenFirmware style irq translations. It will even work on SPARC even though SPARC has it's own mechanism for translating irqs at boot time. MIPS, microblaze, embedded x86 and c6x are converted too. The resulting irq_domain code is probably still too verbose and can be optimized more, but that can be done incrementally and is a task for follow-on patches." * tag 'irqdomain-for-linus' of git://git.secretlab.ca/git/linux-2.6: (31 commits) dt: fix twl4030 for non-dt compile on x86 mfd: twl-core: Add IRQ_DOMAIN dependency devicetree: Add empty of_platform_populate() for !CONFIG_OF_ADDRESS (sparc) irq_domain: Centralize definition of irq_dispose_mapping() irq_domain/mips: Allow irq_domain on MIPS irq_domain/x86: Convert x86 (embedded) to use common irq_domain ppc-6xx: fix build failure in flipper-pic.c and hlwd-pic.c irq_domain/microblaze: Convert microblaze to use irq_domains irq_domain/powerpc: Replace custom xlate functions with library functions irq_domain/powerpc: constify irq_domain_ops irq_domain/c6x: Use library of xlate functions irq_domain/c6x: constify irq_domain structures irq_domain/c6x: Convert c6x to use generic irq_domain support. irq_domain: constify irq_domain_ops irq_domain: Create common xlate functions that device drivers can use irq_domain: Remove irq_domain_add_simple() irq_domain: Remove 'new' irq_domain in favour of the ppc one mfd: twl-core.c: Fix the number of interrupts managed by twl4030 of/address: add empty static inlines for !CONFIG_OF irq_domain: Add support for base irq and hwirq in legacy mappings ...
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/Kconfig1
-rw-r--r--arch/microblaze/include/asm/hardirq.h16
-rw-r--r--arch/microblaze/include/asm/irq.h42
-rw-r--r--arch/microblaze/kernel/intc.c61
-rw-r--r--arch/microblaze/kernel/irq.c24
-rw-r--r--arch/microblaze/kernel/setup.c2
6 files changed, 45 insertions, 101 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index c8d6efb99dbf..11060fa87da3 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -14,6 +14,7 @@ config MICROBLAZE
14 select TRACING_SUPPORT 14 select TRACING_SUPPORT
15 select OF 15 select OF
16 select OF_EARLY_FLATTREE 16 select OF_EARLY_FLATTREE
17 select IRQ_DOMAIN
17 select HAVE_GENERIC_HARDIRQS 18 select HAVE_GENERIC_HARDIRQS
18 select GENERIC_IRQ_PROBE 19 select GENERIC_IRQ_PROBE
19 select GENERIC_IRQ_SHOW 20 select GENERIC_IRQ_SHOW
diff --git a/arch/microblaze/include/asm/hardirq.h b/arch/microblaze/include/asm/hardirq.h
index cd1ac9aad56c..fb3c05a0cbbf 100644
--- a/arch/microblaze/include/asm/hardirq.h
+++ b/arch/microblaze/include/asm/hardirq.h
@@ -1,17 +1 @@
1/*
2 * Copyright (C) 2006 Atmark Techno, Inc.
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 */
8
9#ifndef _ASM_MICROBLAZE_HARDIRQ_H
10#define _ASM_MICROBLAZE_HARDIRQ_H
11
12/* should be defined in each interrupt controller driver */
13extern unsigned int get_irq(struct pt_regs *regs);
14
15#include <asm-generic/hardirq.h> #include <asm-generic/hardirq.h>
16
17#endif /* _ASM_MICROBLAZE_HARDIRQ_H */
diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h
index a175132e4496..bab3b1393ad4 100644
--- a/arch/microblaze/include/asm/irq.h
+++ b/arch/microblaze/include/asm/irq.h
@@ -9,49 +9,13 @@
9#ifndef _ASM_MICROBLAZE_IRQ_H 9#ifndef _ASM_MICROBLAZE_IRQ_H
10#define _ASM_MICROBLAZE_IRQ_H 10#define _ASM_MICROBLAZE_IRQ_H
11 11
12 12#define NR_IRQS (32 + 1)
13/*
14 * Linux IRQ# is currently offset by one to map to the hardware
15 * irq number. So hardware IRQ0 maps to Linux irq 1.
16 */
17#define NO_IRQ_OFFSET 1
18#define IRQ_OFFSET NO_IRQ_OFFSET
19#define NR_IRQS (32 + IRQ_OFFSET)
20#include <asm-generic/irq.h> 13#include <asm-generic/irq.h>
21 14
22/* This type is the placeholder for a hardware interrupt number. It has to
23 * be big enough to enclose whatever representation is used by a given
24 * platform.
25 */
26typedef unsigned long irq_hw_number_t;
27
28extern unsigned int nr_irq;
29
30struct pt_regs; 15struct pt_regs;
31extern void do_IRQ(struct pt_regs *regs); 16extern void do_IRQ(struct pt_regs *regs);
32 17
33/** FIXME - not implement 18/* should be defined in each interrupt controller driver */
34 * irq_dispose_mapping - Unmap an interrupt 19extern unsigned int get_irq(void);
35 * @virq: linux virq number of the interrupt to unmap
36 */
37static inline void irq_dispose_mapping(unsigned int virq)
38{
39 return;
40}
41
42struct irq_host;
43
44/**
45 * irq_create_mapping - Map a hardware interrupt into linux virq space
46 * @host: host owning this hardware interrupt or NULL for default host
47 * @hwirq: hardware irq number in that host space
48 *
49 * Only one mapping per hardware interrupt is permitted. Returns a linux
50 * virq number.
51 * If the sense/trigger is to be specified, set_irq_type() should be called
52 * on the number returned from that call.
53 */
54extern unsigned int irq_create_mapping(struct irq_host *host,
55 irq_hw_number_t hwirq);
56 20
57#endif /* _ASM_MICROBLAZE_IRQ_H */ 21#endif /* _ASM_MICROBLAZE_IRQ_H */
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index 44b177e2ab12..ad120672cee5 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/irqdomain.h>
12#include <linux/irq.h> 13#include <linux/irq.h>
13#include <asm/page.h> 14#include <asm/page.h>
14#include <linux/io.h> 15#include <linux/io.h>
@@ -25,8 +26,6 @@ static unsigned int intc_baseaddr;
25#define INTC_BASE intc_baseaddr 26#define INTC_BASE intc_baseaddr
26#endif 27#endif
27 28
28unsigned int nr_irq;
29
30/* No one else should require these constants, so define them locally here. */ 29/* No one else should require these constants, so define them locally here. */
31#define ISR 0x00 /* Interrupt Status Register */ 30#define ISR 0x00 /* Interrupt Status Register */
32#define IPR 0x04 /* Interrupt Pending Register */ 31#define IPR 0x04 /* Interrupt Pending Register */
@@ -84,24 +83,45 @@ static struct irq_chip intc_dev = {
84 .irq_mask_ack = intc_mask_ack, 83 .irq_mask_ack = intc_mask_ack,
85}; 84};
86 85
87unsigned int get_irq(struct pt_regs *regs) 86static struct irq_domain *root_domain;
87
88unsigned int get_irq(void)
88{ 89{
89 int irq; 90 unsigned int hwirq, irq = -1;
90 91
91 /* 92 hwirq = in_be32(INTC_BASE + IVR);
92 * NOTE: This function is the one that needs to be improved in 93 if (hwirq != -1U)
93 * order to handle multiple interrupt controllers. It currently 94 irq = irq_find_mapping(root_domain, hwirq);
94 * is hardcoded to check for interrupts only on the first INTC. 95
95 */ 96 pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq);
96 irq = in_be32(INTC_BASE + IVR) + NO_IRQ_OFFSET;
97 pr_debug("get_irq: %d\n", irq);
98 97
99 return irq; 98 return irq;
100} 99}
101 100
101int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
102{
103 u32 intr_mask = (u32)d->host_data;
104
105 if (intr_mask & (1 << hw)) {
106 irq_set_chip_and_handler_name(irq, &intc_dev,
107 handle_edge_irq, "edge");
108 irq_clear_status_flags(irq, IRQ_LEVEL);
109 } else {
110 irq_set_chip_and_handler_name(irq, &intc_dev,
111 handle_level_irq, "level");
112 irq_set_status_flags(irq, IRQ_LEVEL);
113 }
114 return 0;
115}
116
117static const struct irq_domain_ops xintc_irq_domain_ops = {
118 .xlate = irq_domain_xlate_onetwocell,
119 .map = xintc_map,
120};
121
102void __init init_IRQ(void) 122void __init init_IRQ(void)
103{ 123{
104 u32 i, intr_mask; 124 u32 nr_irq, intr_mask;
105 struct device_node *intc = NULL; 125 struct device_node *intc = NULL;
106#ifdef CONFIG_SELFMOD_INTC 126#ifdef CONFIG_SELFMOD_INTC
107 unsigned int intc_baseaddr = 0; 127 unsigned int intc_baseaddr = 0;
@@ -146,16 +166,9 @@ void __init init_IRQ(void)
146 /* Turn on the Master Enable. */ 166 /* Turn on the Master Enable. */
147 out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); 167 out_be32(intc_baseaddr + MER, MER_HIE | MER_ME);
148 168
149 for (i = IRQ_OFFSET; i < (nr_irq + IRQ_OFFSET); ++i) { 169 /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm
150 if (intr_mask & (0x00000001 << (i - IRQ_OFFSET))) { 170 * lazy and Michal can clean it up to something nicer when he tests
151 irq_set_chip_and_handler_name(i, &intc_dev, 171 * and commits this patch. ~~gcl */
152 handle_edge_irq, "edge"); 172 root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops,
153 irq_clear_status_flags(i, IRQ_LEVEL); 173 (void *)intr_mask);
154 } else {
155 irq_set_chip_and_handler_name(i, &intc_dev,
156 handle_level_irq, "level");
157 irq_set_status_flags(i, IRQ_LEVEL);
158 }
159 irq_get_irq_data(i)->hwirq = i - IRQ_OFFSET;
160 }
161} 174}
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index bbebcae72c02..ace700afbfdf 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -31,14 +31,13 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
31 trace_hardirqs_off(); 31 trace_hardirqs_off();
32 32
33 irq_enter(); 33 irq_enter();
34 irq = get_irq(regs); 34 irq = get_irq();
35next_irq: 35next_irq:
36 BUG_ON(!irq); 36 BUG_ON(!irq);
37 /* Substract 1 because of get_irq */ 37 generic_handle_irq(irq);
38 generic_handle_irq(irq + IRQ_OFFSET - NO_IRQ_OFFSET);
39 38
40 irq = get_irq(regs); 39 irq = get_irq();
41 if (irq) { 40 if (irq != -1U) {
42 pr_debug("next irq: %d\n", irq); 41 pr_debug("next irq: %d\n", irq);
43 ++concurrent_irq; 42 ++concurrent_irq;
44 goto next_irq; 43 goto next_irq;
@@ -48,18 +47,3 @@ next_irq:
48 set_irq_regs(old_regs); 47 set_irq_regs(old_regs);
49 trace_hardirqs_on(); 48 trace_hardirqs_on();
50} 49}
51
52/* MS: There is no any advance mapping mechanism. We are using simple 32bit
53 intc without any cascades or any connection that's why mapping is 1:1 */
54unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)
55{
56 return hwirq + IRQ_OFFSET;
57}
58EXPORT_SYMBOL_GPL(irq_create_mapping);
59
60unsigned int irq_create_of_mapping(struct device_node *controller,
61 const u32 *intspec, unsigned int intsize)
62{
63 return intspec[0] + IRQ_OFFSET;
64}
65EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 604cd9dd1333..70e6d0b41ab4 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -51,8 +51,6 @@ void __init setup_arch(char **cmdline_p)
51 51
52 unflatten_device_tree(); 52 unflatten_device_tree();
53 53
54 /* NOTE I think that this function is not necessary to call */
55 /* irq_early_init(); */
56 setup_cpuinfo(); 54 setup_cpuinfo();
57 55
58 microblaze_cache_init(); 56 microblaze_cache_init();