aboutsummaryrefslogtreecommitdiffstats
path: root/arch/openrisc
diff options
context:
space:
mode:
authorJonas Bonn <jonas@southpole.se>2012-04-06 06:52:54 -0400
committerJonas Bonn <jonas@southpole.se>2012-05-08 05:42:55 -0400
commitb4c4c6ee93501a46d58d5511fc8bb9aeb4508c6d (patch)
tree402937a7e148290010a375b9dfbc9f9c96c09d2f /arch/openrisc
parentd48b97b403d23f6df0b990cee652bdf9a52337a3 (diff)
openrisc: implement irqdomains
This moves OpenRISC to using the irqdomain infrastructure. This doesn't fundamentally change anything other than that it will be easier to have multiple interrupt controllers in the future. Signed-off-by: Jonas Bonn <jonas@southpole.se>
Diffstat (limited to 'arch/openrisc')
-rw-r--r--arch/openrisc/Kconfig1
-rw-r--r--arch/openrisc/kernel/irq.c79
2 files changed, 48 insertions, 32 deletions
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index a4787197d8fe..7589051e79e0 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -7,6 +7,7 @@ config OPENRISC
7 def_bool y 7 def_bool y
8 select OF 8 select OF
9 select OF_EARLY_FLATTREE 9 select OF_EARLY_FLATTREE
10 select IRQ_DOMAIN
10 select HAVE_MEMBLOCK 11 select HAVE_MEMBLOCK
11 select ARCH_WANT_OPTIONAL_GPIOLIB 12 select ARCH_WANT_OPTIONAL_GPIOLIB
12 select HAVE_ARCH_TRACEHOOK 13 select HAVE_ARCH_TRACEHOOK
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c
index 4bfead220956..15c5ea3e98d4 100644
--- a/arch/openrisc/kernel/irq.c
+++ b/arch/openrisc/kernel/irq.c
@@ -24,7 +24,7 @@
24#include <linux/seq_file.h> 24#include <linux/seq_file.h>
25#include <linux/kernel_stat.h> 25#include <linux/kernel_stat.h>
26#include <linux/export.h> 26#include <linux/export.h>
27 27#include <linux/irqdomain.h>
28#include <linux/irqflags.h> 28#include <linux/irqflags.h>
29 29
30/* read interrupt enabled status */ 30/* read interrupt enabled status */
@@ -98,6 +98,7 @@ static void or1k_pic_mask_ack(struct irq_data *data)
98#endif 98#endif
99} 99}
100 100
101#if 0
101static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type) 102static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
102{ 103{
103 /* There's nothing to do in the PIC configuration when changing 104 /* There's nothing to do in the PIC configuration when changing
@@ -107,43 +108,64 @@ static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
107 108
108 return irq_setup_alt_chip(data, flow_type); 109 return irq_setup_alt_chip(data, flow_type);
109} 110}
111#endif
112
113static struct irq_chip or1k_dev = {
114 .name = "or1k-PIC",
115 .irq_unmask = or1k_pic_unmask,
116 .irq_mask = or1k_pic_mask,
117 .irq_ack = or1k_pic_ack,
118 .irq_mask_ack = or1k_pic_mask_ack,
119};
120
121static struct irq_domain *root_domain;
110 122
111static inline int pic_get_irq(int first) 123static inline int pic_get_irq(int first)
112{ 124{
113 int irq; 125 int hwirq;
114 126
115 irq = ffs(mfspr(SPR_PICSR) >> first); 127 hwirq = ffs(mfspr(SPR_PICSR) >> first);
128 if (!hwirq)
129 return NO_IRQ;
130 else
131 hwirq = hwirq + first -1;
116 132
117 return irq ? irq + first - 1 : NO_IRQ; 133 return irq_find_mapping(root_domain, hwirq);
118} 134}
119 135
120static void __init or1k_irq_init(void) 136
137static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
121{ 138{
122 struct irq_chip_generic *gc; 139 irq_set_chip_and_handler_name(irq, &or1k_dev,
123 struct irq_chip_type *ct; 140 handle_level_irq, "level");
141 irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE);
124 142
125 /* Disable all interrupts until explicitly requested */ 143 return 0;
126 mtspr(SPR_PICMR, (0UL)); 144}
127 145
128 gc = irq_alloc_generic_chip("or1k-PIC", 1, 0, 0, handle_level_irq); 146static const struct irq_domain_ops or1k_irq_domain_ops = {
129 ct = gc->chip_types; 147 .xlate = irq_domain_xlate_onecell,
148 .map = or1k_map,
149};
130 150
131 ct->chip.irq_unmask = or1k_pic_unmask; 151/*
132 ct->chip.irq_mask = or1k_pic_mask; 152 * This sets up the IRQ domain for the PIC built in to the OpenRISC
133 ct->chip.irq_ack = or1k_pic_ack; 153 * 1000 CPU. This is the "root" domain as these are the interrupts
134 ct->chip.irq_mask_ack = or1k_pic_mask_ack; 154 * that directly trigger an exception in the CPU.
135 ct->chip.irq_set_type = or1k_pic_set_type; 155 */
156static void __init or1k_irq_init(void)
157{
158 struct device_node *intc = NULL;
136 159
137 /* The OR1K PIC can handle both level and edge trigged 160 /* The interrupt controller device node is mandatory */
138 * interrupts in roughly the same manner 161 intc = of_find_compatible_node(NULL, NULL, "opencores,or1k-pic");
139 */ 162 BUG_ON(!intc);
140#if 0
141 /* FIXME: chip.type??? */
142 ct->chip.type = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_MASK;
143#endif
144 163
145 irq_setup_generic_chip(gc, IRQ_MSK(NR_IRQS), 0, 164 /* Disable all interrupts until explicitly requested */
146 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); 165 mtspr(SPR_PICMR, (0UL));
166
167 root_domain = irq_domain_add_linear(intc, 32,
168 &or1k_irq_domain_ops, NULL);
147} 169}
148 170
149void __init init_IRQ(void) 171void __init init_IRQ(void)
@@ -164,10 +186,3 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
164 irq_exit(); 186 irq_exit();
165 set_irq_regs(old_regs); 187 set_irq_regs(old_regs);
166} 188}
167
168unsigned int irq_create_of_mapping(struct device_node *controller,
169 const u32 *intspec, unsigned int intsize)
170{
171 return intspec[0];
172}
173EXPORT_SYMBOL_GPL(irq_create_of_mapping);