aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-07-08 16:48:22 -0400
committerThomas Gleixner <tglx@linutronix.de>2014-07-08 16:49:16 -0400
commit4f808391df4ed5bea02519242710803df1ab040b (patch)
tree10a417dfa3fea122f81365893c7f11f5e54f5997
parente8d471edd27374c2f1c9eeecab3aaedf2775421f (diff)
parent885d078bfe92abfd5965a4f8846a3e72648ac9a6 (diff)
Merge tag 'irqchip-core-3.17-2' of git://git.infradead.org/users/jcooper/linux into irq/core
irqchip core changes form Jason Cooper * or1k-pic: Migrate driver from arch/openrisc * crossbar: Cleanup series
-rw-r--r--Documentation/devicetree/bindings/arm/omap/crossbar.txt36
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt23
-rw-r--r--arch/openrisc/Kconfig1
-rw-r--r--arch/openrisc/include/asm/irq.h3
-rw-r--r--arch/openrisc/kernel/irq.c146
-rw-r--r--drivers/irqchip/Kconfig4
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-crossbar.c168
-rw-r--r--drivers/irqchip/irq-or1k-pic.c182
9 files changed, 406 insertions, 158 deletions
diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
index fb88585cfb93..4139db353d0a 100644
--- a/Documentation/devicetree/bindings/arm/omap/crossbar.txt
+++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
@@ -10,6 +10,7 @@ Required properties:
10- compatible : Should be "ti,irq-crossbar" 10- compatible : Should be "ti,irq-crossbar"
11- reg: Base address and the size of the crossbar registers. 11- reg: Base address and the size of the crossbar registers.
12- ti,max-irqs: Total number of irqs available at the interrupt controller. 12- ti,max-irqs: Total number of irqs available at the interrupt controller.
13- ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed.
13- ti,reg-size: Size of a individual register in bytes. Every individual 14- ti,reg-size: Size of a individual register in bytes. Every individual
14 register is assumed to be of same size. Valid sizes are 1, 2, 4. 15 register is assumed to be of same size. Valid sizes are 1, 2, 4.
15- ti,irqs-reserved: List of the reserved irq lines that are not muxed using 16- ti,irqs-reserved: List of the reserved irq lines that are not muxed using
@@ -17,11 +18,46 @@ Required properties:
17 so crossbar bar driver should not consider them as free 18 so crossbar bar driver should not consider them as free
18 lines. 19 lines.
19 20
21Optional properties:
22- ti,irqs-skip: This is similar to "ti,irqs-reserved", but these are for
23 SOC-specific hard-wiring of those irqs which unexpectedly bypasses the
24 crossbar. These irqs have a crossbar register, but still cannot be used.
25
26- ti,irqs-safe-map: integer which maps to a safe configuration to use
27 when the interrupt controller irq is unused (when not provided, default is 0)
28
20Examples: 29Examples:
21 crossbar_mpu: @4a020000 { 30 crossbar_mpu: @4a020000 {
22 compatible = "ti,irq-crossbar"; 31 compatible = "ti,irq-crossbar";
23 reg = <0x4a002a48 0x130>; 32 reg = <0x4a002a48 0x130>;
24 ti,max-irqs = <160>; 33 ti,max-irqs = <160>;
34 ti,max-crossbar-sources = <400>;
25 ti,reg-size = <2>; 35 ti,reg-size = <2>;
26 ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>; 36 ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
37 ti,irqs-skip = <10 133 139 140>;
27 }; 38 };
39
40Consumer:
41========
42See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and
43Documentation/devicetree/bindings/arm/gic.txt for further details.
44
45An interrupt consumer on an SoC using crossbar will use:
46 interrupts = <GIC_SPI request_number interrupt_level>
47When the request number is between 0 to that described by
48"ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the
49request_number is greater than "ti,max-crossbar-sources", then it is mapped as a
50quirky hardware mapping direct to GIC.
51
52Example:
53 device_x@0x4a023000 {
54 /* Crossbar 8 used */
55 interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
56 ...
57 };
58
59 device_y@0x4a033000 {
60 /* Direct mapped GIC SPI 1 used */
61 interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>;
62 ...
63 };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt b/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt
new file mode 100644
index 000000000000..55c04faa3f3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt
@@ -0,0 +1,23 @@
1OpenRISC 1000 Programmable Interrupt Controller
2
3Required properties:
4
5- compatible : should be "opencores,or1k-pic-level" for variants with
6 level triggered interrupt lines, "opencores,or1k-pic-edge" for variants with
7 edge triggered interrupt lines or "opencores,or1200-pic" for machines
8 with the non-spec compliant or1200 type implementation.
9
10 "opencores,or1k-pic" is also provided as an alias to "opencores,or1200-pic",
11 but this is only for backwards compatibility.
12
13- interrupt-controller : Identifies the node as an interrupt controller
14- #interrupt-cells : Specifies the number of cells needed to encode an
15 interrupt source. The value shall be 1.
16
17Example:
18
19intc: interrupt-controller {
20 compatible = "opencores,or1k-pic-level";
21 interrupt-controller;
22 #interrupt-cells = <1>;
23};
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index e71d712afb79..88e83368bbf5 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -22,6 +22,7 @@ config OPENRISC
22 select GENERIC_STRNLEN_USER 22 select GENERIC_STRNLEN_USER
23 select MODULES_USE_ELF_RELA 23 select MODULES_USE_ELF_RELA
24 select HAVE_DEBUG_STACKOVERFLOW 24 select HAVE_DEBUG_STACKOVERFLOW
25 select OR1K_PIC
25 26
26config MMU 27config MMU
27 def_bool y 28 def_bool y
diff --git a/arch/openrisc/include/asm/irq.h b/arch/openrisc/include/asm/irq.h
index eb612b1865d2..b84634cc95eb 100644
--- a/arch/openrisc/include/asm/irq.h
+++ b/arch/openrisc/include/asm/irq.h
@@ -24,4 +24,7 @@
24 24
25#define NO_IRQ (-1) 25#define NO_IRQ (-1)
26 26
27void handle_IRQ(unsigned int, struct pt_regs *);
28extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
29
27#endif /* __ASM_OPENRISC_IRQ_H__ */ 30#endif /* __ASM_OPENRISC_IRQ_H__ */
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c
index 8ec77bc9f1e7..967eb1430203 100644
--- a/arch/openrisc/kernel/irq.c
+++ b/arch/openrisc/kernel/irq.c
@@ -16,11 +16,10 @@
16 16
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/of.h>
20#include <linux/ftrace.h> 19#include <linux/ftrace.h>
21#include <linux/irq.h> 20#include <linux/irq.h>
21#include <linux/irqchip.h>
22#include <linux/export.h> 22#include <linux/export.h>
23#include <linux/irqdomain.h>
24#include <linux/irqflags.h> 23#include <linux/irqflags.h>
25 24
26/* read interrupt enabled status */ 25/* read interrupt enabled status */
@@ -37,150 +36,31 @@ void arch_local_irq_restore(unsigned long flags)
37} 36}
38EXPORT_SYMBOL(arch_local_irq_restore); 37EXPORT_SYMBOL(arch_local_irq_restore);
39 38
40 39void __init init_IRQ(void)
41/* OR1K PIC implementation */
42
43/* We're a couple of cycles faster than the generic implementations with
44 * these 'fast' versions.
45 */
46
47static void or1k_pic_mask(struct irq_data *data)
48{
49 mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
50}
51
52static void or1k_pic_unmask(struct irq_data *data)
53{
54 mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
55}
56
57static void or1k_pic_ack(struct irq_data *data)
58{
59 /* EDGE-triggered interrupts need to be ack'ed in order to clear
60 * the latch.
61 * LEVEL-triggered interrupts do not need to be ack'ed; however,
62 * ack'ing the interrupt has no ill-effect and is quicker than
63 * trying to figure out what type it is...
64 */
65
66 /* The OpenRISC 1000 spec says to write a 1 to the bit to ack the
67 * interrupt, but the OR1200 does this backwards and requires a 0
68 * to be written...
69 */
70
71#ifdef CONFIG_OR1K_1200
72 /* There are two oddities with the OR1200 PIC implementation:
73 * i) LEVEL-triggered interrupts are latched and need to be cleared
74 * ii) the interrupt latch is cleared by writing a 0 to the bit,
75 * as opposed to a 1 as mandated by the spec
76 */
77
78 mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
79#else
80 WARN(1, "Interrupt handling possibly broken\n");
81 mtspr(SPR_PICSR, (1UL << data->hwirq));
82#endif
83}
84
85static void or1k_pic_mask_ack(struct irq_data *data)
86{
87 /* Comments for pic_ack apply here, too */
88
89#ifdef CONFIG_OR1K_1200
90 mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
91 mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
92#else
93 WARN(1, "Interrupt handling possibly broken\n");
94 mtspr(SPR_PICMR, (1UL << data->hwirq));
95 mtspr(SPR_PICSR, (1UL << data->hwirq));
96#endif
97}
98
99#if 0
100static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
101{
102 /* There's nothing to do in the PIC configuration when changing
103 * flow type. Level and edge-triggered interrupts are both
104 * supported, but it's PIC-implementation specific which type
105 * is handled. */
106
107 return irq_setup_alt_chip(data, flow_type);
108}
109#endif
110
111static struct irq_chip or1k_dev = {
112 .name = "or1k-PIC",
113 .irq_unmask = or1k_pic_unmask,
114 .irq_mask = or1k_pic_mask,
115 .irq_ack = or1k_pic_ack,
116 .irq_mask_ack = or1k_pic_mask_ack,
117};
118
119static struct irq_domain *root_domain;
120
121static inline int pic_get_irq(int first)
122{
123 int hwirq;
124
125 hwirq = ffs(mfspr(SPR_PICSR) >> first);
126 if (!hwirq)
127 return NO_IRQ;
128 else
129 hwirq = hwirq + first -1;
130
131 return irq_find_mapping(root_domain, hwirq);
132}
133
134
135static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
136{ 40{
137 irq_set_chip_and_handler_name(irq, &or1k_dev, 41 irqchip_init();
138 handle_level_irq, "level");
139 irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE);
140
141 return 0;
142} 42}
143 43
144static const struct irq_domain_ops or1k_irq_domain_ops = { 44static void (*handle_arch_irq)(struct pt_regs *);
145 .xlate = irq_domain_xlate_onecell,
146 .map = or1k_map,
147};
148
149/*
150 * This sets up the IRQ domain for the PIC built in to the OpenRISC
151 * 1000 CPU. This is the "root" domain as these are the interrupts
152 * that directly trigger an exception in the CPU.
153 */
154static void __init or1k_irq_init(void)
155{
156 struct device_node *intc = NULL;
157
158 /* The interrupt controller device node is mandatory */
159 intc = of_find_compatible_node(NULL, NULL, "opencores,or1k-pic");
160 BUG_ON(!intc);
161
162 /* Disable all interrupts until explicitly requested */
163 mtspr(SPR_PICMR, (0UL));
164
165 root_domain = irq_domain_add_linear(intc, 32,
166 &or1k_irq_domain_ops, NULL);
167}
168 45
169void __init init_IRQ(void) 46void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
170{ 47{
171 or1k_irq_init(); 48 handle_arch_irq = handle_irq;
172} 49}
173 50
174void __irq_entry do_IRQ(struct pt_regs *regs) 51void handle_IRQ(unsigned int irq, struct pt_regs *regs)
175{ 52{
176 int irq = -1;
177 struct pt_regs *old_regs = set_irq_regs(regs); 53 struct pt_regs *old_regs = set_irq_regs(regs);
178 54
179 irq_enter(); 55 irq_enter();
180 56
181 while ((irq = pic_get_irq(irq + 1)) != NO_IRQ) 57 generic_handle_irq(irq);
182 generic_handle_irq(irq);
183 58
184 irq_exit(); 59 irq_exit();
185 set_irq_regs(old_regs); 60 set_irq_regs(old_regs);
186} 61}
62
63void __irq_entry do_IRQ(struct pt_regs *regs)
64{
65 handle_arch_irq(regs);
66}
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index bbb746e35500..131f18562d7d 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -53,6 +53,10 @@ config CLPS711X_IRQCHIP
53 select SPARSE_IRQ 53 select SPARSE_IRQ
54 default y 54 default y
55 55
56config OR1K_PIC
57 bool
58 select IRQ_DOMAIN
59
56config ORION_IRQCHIP 60config ORION_IRQCHIP
57 bool 61 bool
58 select IRQ_DOMAIN 62 select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 62a13e5ef98f..7fba336c4daf 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_METAG) += irq-metag-ext.o
11obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o 11obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o
12obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o 12obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o
13obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o 13obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o
14obj-$(CONFIG_OR1K_PIC) += irq-or1k-pic.o
14obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o 15obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
15obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o 16obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
16obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o 17obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index 3d15d16a7088..85c2985d8bcb 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -15,22 +15,31 @@
15#include <linux/of_irq.h> 15#include <linux/of_irq.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/irqchip/arm-gic.h> 17#include <linux/irqchip/arm-gic.h>
18#include <linux/irqchip/irq-crossbar.h>
18 19
19#define IRQ_FREE -1 20#define IRQ_FREE -1
21#define IRQ_RESERVED -2
22#define IRQ_SKIP -3
20#define GIC_IRQ_START 32 23#define GIC_IRQ_START 32
21 24
22/* 25/**
26 * struct crossbar_device - crossbar device description
23 * @int_max: maximum number of supported interrupts 27 * @int_max: maximum number of supported interrupts
28 * @safe_map: safe default value to initialize the crossbar
29 * @max_crossbar_sources: Maximum number of crossbar sources
24 * @irq_map: array of interrupts to crossbar number mapping 30 * @irq_map: array of interrupts to crossbar number mapping
25 * @crossbar_base: crossbar base address 31 * @crossbar_base: crossbar base address
26 * @register_offsets: offsets for each irq number 32 * @register_offsets: offsets for each irq number
33 * @write: register write function pointer
27 */ 34 */
28struct crossbar_device { 35struct crossbar_device {
29 uint int_max; 36 uint int_max;
37 uint safe_map;
38 uint max_crossbar_sources;
30 uint *irq_map; 39 uint *irq_map;
31 void __iomem *crossbar_base; 40 void __iomem *crossbar_base;
32 int *register_offsets; 41 int *register_offsets;
33 void (*write) (int, int); 42 void (*write)(int, int);
34}; 43};
35 44
36static struct crossbar_device *cb; 45static struct crossbar_device *cb;
@@ -50,11 +59,22 @@ static inline void crossbar_writeb(int irq_no, int cb_no)
50 writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]); 59 writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
51} 60}
52 61
62static inline int get_prev_map_irq(int cb_no)
63{
64 int i;
65
66 for (i = cb->int_max - 1; i >= 0; i--)
67 if (cb->irq_map[i] == cb_no)
68 return i;
69
70 return -ENODEV;
71}
72
53static inline int allocate_free_irq(int cb_no) 73static inline int allocate_free_irq(int cb_no)
54{ 74{
55 int i; 75 int i;
56 76
57 for (i = 0; i < cb->int_max; i++) { 77 for (i = cb->int_max - 1; i >= 0; i--) {
58 if (cb->irq_map[i] == IRQ_FREE) { 78 if (cb->irq_map[i] == IRQ_FREE) {
59 cb->irq_map[i] = cb_no; 79 cb->irq_map[i] = cb_no;
60 return i; 80 return i;
@@ -64,19 +84,47 @@ static inline int allocate_free_irq(int cb_no)
64 return -ENODEV; 84 return -ENODEV;
65} 85}
66 86
87static inline bool needs_crossbar_write(irq_hw_number_t hw)
88{
89 int cb_no;
90
91 if (hw > GIC_IRQ_START) {
92 cb_no = cb->irq_map[hw - GIC_IRQ_START];
93 if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP)
94 return true;
95 }
96
97 return false;
98}
99
67static int crossbar_domain_map(struct irq_domain *d, unsigned int irq, 100static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
68 irq_hw_number_t hw) 101 irq_hw_number_t hw)
69{ 102{
70 cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]); 103 if (needs_crossbar_write(hw))
104 cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
105
71 return 0; 106 return 0;
72} 107}
73 108
109/**
110 * crossbar_domain_unmap - unmap a crossbar<->irq connection
111 * @d: domain of irq to unmap
112 * @irq: virq number
113 *
114 * We do not maintain a use count of total number of map/unmap
115 * calls for a particular irq to find out if a irq can be really
116 * unmapped. This is because unmap is called during irq_dispose_mapping(irq),
117 * after which irq is anyways unusable. So an explicit map has to be called
118 * after that.
119 */
74static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq) 120static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
75{ 121{
76 irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq; 122 irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
77 123
78 if (hw > GIC_IRQ_START) 124 if (needs_crossbar_write(hw)) {
79 cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE; 125 cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
126 cb->write(hw - GIC_IRQ_START, cb->safe_map);
127 }
80} 128}
81 129
82static int crossbar_domain_xlate(struct irq_domain *d, 130static int crossbar_domain_xlate(struct irq_domain *d,
@@ -85,18 +133,41 @@ static int crossbar_domain_xlate(struct irq_domain *d,
85 unsigned long *out_hwirq, 133 unsigned long *out_hwirq,
86 unsigned int *out_type) 134 unsigned int *out_type)
87{ 135{
88 unsigned long ret; 136 int ret;
137 int req_num = intspec[1];
138 int direct_map_num;
139
140 if (req_num >= cb->max_crossbar_sources) {
141 direct_map_num = req_num - cb->max_crossbar_sources;
142 if (direct_map_num < cb->int_max) {
143 ret = cb->irq_map[direct_map_num];
144 if (ret == IRQ_RESERVED || ret == IRQ_SKIP) {
145 /* We use the interrupt num as h/w irq num */
146 ret = direct_map_num;
147 goto found;
148 }
149 }
150
151 pr_err("%s: requested crossbar number %d > max %d\n",
152 __func__, req_num, cb->max_crossbar_sources);
153 return -EINVAL;
154 }
89 155
90 ret = allocate_free_irq(intspec[1]); 156 ret = get_prev_map_irq(req_num);
157 if (ret >= 0)
158 goto found;
91 159
92 if (IS_ERR_VALUE(ret)) 160 ret = allocate_free_irq(req_num);
161
162 if (ret < 0)
93 return ret; 163 return ret;
94 164
165found:
95 *out_hwirq = ret + GIC_IRQ_START; 166 *out_hwirq = ret + GIC_IRQ_START;
96 return 0; 167 return 0;
97} 168}
98 169
99const struct irq_domain_ops routable_irq_domain_ops = { 170static const struct irq_domain_ops routable_irq_domain_ops = {
100 .map = crossbar_domain_map, 171 .map = crossbar_domain_map,
101 .unmap = crossbar_domain_unmap, 172 .unmap = crossbar_domain_unmap,
102 .xlate = crossbar_domain_xlate 173 .xlate = crossbar_domain_xlate
@@ -104,22 +175,36 @@ const struct irq_domain_ops routable_irq_domain_ops = {
104 175
105static int __init crossbar_of_init(struct device_node *node) 176static int __init crossbar_of_init(struct device_node *node)
106{ 177{
107 int i, size, max, reserved = 0, entry; 178 int i, size, max = 0, reserved = 0, entry;
108 const __be32 *irqsr; 179 const __be32 *irqsr;
180 int ret = -ENOMEM;
109 181
110 cb = kzalloc(sizeof(*cb), GFP_KERNEL); 182 cb = kzalloc(sizeof(*cb), GFP_KERNEL);
111 183
112 if (!cb) 184 if (!cb)
113 return -ENOMEM; 185 return ret;
114 186
115 cb->crossbar_base = of_iomap(node, 0); 187 cb->crossbar_base = of_iomap(node, 0);
116 if (!cb->crossbar_base) 188 if (!cb->crossbar_base)
117 goto err1; 189 goto err_cb;
190
191 of_property_read_u32(node, "ti,max-crossbar-sources",
192 &cb->max_crossbar_sources);
193 if (!cb->max_crossbar_sources) {
194 pr_err("missing 'ti,max-crossbar-sources' property\n");
195 ret = -EINVAL;
196 goto err_base;
197 }
118 198
119 of_property_read_u32(node, "ti,max-irqs", &max); 199 of_property_read_u32(node, "ti,max-irqs", &max);
120 cb->irq_map = kzalloc(max * sizeof(int), GFP_KERNEL); 200 if (!max) {
201 pr_err("missing 'ti,max-irqs' property\n");
202 ret = -EINVAL;
203 goto err_base;
204 }
205 cb->irq_map = kcalloc(max, sizeof(int), GFP_KERNEL);
121 if (!cb->irq_map) 206 if (!cb->irq_map)
122 goto err2; 207 goto err_base;
123 208
124 cb->int_max = max; 209 cb->int_max = max;
125 210
@@ -137,15 +222,35 @@ static int __init crossbar_of_init(struct device_node *node)
137 i, &entry); 222 i, &entry);
138 if (entry > max) { 223 if (entry > max) {
139 pr_err("Invalid reserved entry\n"); 224 pr_err("Invalid reserved entry\n");
140 goto err3; 225 ret = -EINVAL;
226 goto err_irq_map;
227 }
228 cb->irq_map[entry] = IRQ_RESERVED;
229 }
230 }
231
232 /* Skip irqs hardwired to bypass the crossbar */
233 irqsr = of_get_property(node, "ti,irqs-skip", &size);
234 if (irqsr) {
235 size /= sizeof(__be32);
236
237 for (i = 0; i < size; i++) {
238 of_property_read_u32_index(node,
239 "ti,irqs-skip",
240 i, &entry);
241 if (entry > max) {
242 pr_err("Invalid skip entry\n");
243 ret = -EINVAL;
244 goto err_irq_map;
141 } 245 }
142 cb->irq_map[entry] = 0; 246 cb->irq_map[entry] = IRQ_SKIP;
143 } 247 }
144 } 248 }
145 249
146 cb->register_offsets = kzalloc(max * sizeof(int), GFP_KERNEL); 250
251 cb->register_offsets = kcalloc(max, sizeof(int), GFP_KERNEL);
147 if (!cb->register_offsets) 252 if (!cb->register_offsets)
148 goto err3; 253 goto err_irq_map;
149 254
150 of_property_read_u32(node, "ti,reg-size", &size); 255 of_property_read_u32(node, "ti,reg-size", &size);
151 256
@@ -161,7 +266,8 @@ static int __init crossbar_of_init(struct device_node *node)
161 break; 266 break;
162 default: 267 default:
163 pr_err("Invalid reg-size property\n"); 268 pr_err("Invalid reg-size property\n");
164 goto err4; 269 ret = -EINVAL;
270 goto err_reg_offset;
165 break; 271 break;
166 } 272 }
167 273
@@ -170,25 +276,37 @@ static int __init crossbar_of_init(struct device_node *node)
170 * reserved irqs. so find and store the offsets once. 276 * reserved irqs. so find and store the offsets once.
171 */ 277 */
172 for (i = 0; i < max; i++) { 278 for (i = 0; i < max; i++) {
173 if (!cb->irq_map[i]) 279 if (cb->irq_map[i] == IRQ_RESERVED)
174 continue; 280 continue;
175 281
176 cb->register_offsets[i] = reserved; 282 cb->register_offsets[i] = reserved;
177 reserved += size; 283 reserved += size;
178 } 284 }
179 285
286 of_property_read_u32(node, "ti,irqs-safe-map", &cb->safe_map);
287 /* Initialize the crossbar with safe map to start with */
288 for (i = 0; i < max; i++) {
289 if (cb->irq_map[i] == IRQ_RESERVED ||
290 cb->irq_map[i] == IRQ_SKIP)
291 continue;
292
293 cb->write(i, cb->safe_map);
294 }
295
180 register_routable_domain_ops(&routable_irq_domain_ops); 296 register_routable_domain_ops(&routable_irq_domain_ops);
181 return 0; 297 return 0;
182 298
183err4: 299err_reg_offset:
184 kfree(cb->register_offsets); 300 kfree(cb->register_offsets);
185err3: 301err_irq_map:
186 kfree(cb->irq_map); 302 kfree(cb->irq_map);
187err2: 303err_base:
188 iounmap(cb->crossbar_base); 304 iounmap(cb->crossbar_base);
189err1: 305err_cb:
190 kfree(cb); 306 kfree(cb);
191 return -ENOMEM; 307
308 cb = NULL;
309 return ret;
192} 310}
193 311
194static const struct of_device_id crossbar_match[] __initconst = { 312static const struct of_device_id crossbar_match[] __initconst = {
diff --git a/drivers/irqchip/irq-or1k-pic.c b/drivers/irqchip/irq-or1k-pic.c
new file mode 100644
index 000000000000..17ff033d9925
--- /dev/null
+++ b/drivers/irqchip/irq-or1k-pic.c
@@ -0,0 +1,182 @@
1/*
2 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
3 * Copyright (C) 2014 Stefan Kristansson <stefan.kristiansson@saunalahti.fi>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10
11#include <linux/irq.h>
12#include <linux/of.h>
13#include <linux/of_irq.h>
14#include <linux/of_address.h>
15
16#include "irqchip.h"
17
18/* OR1K PIC implementation */
19
20struct or1k_pic_dev {
21 struct irq_chip chip;
22 irq_flow_handler_t handle;
23 unsigned long flags;
24};
25
26/*
27 * We're a couple of cycles faster than the generic implementations with
28 * these 'fast' versions.
29 */
30
31static void or1k_pic_mask(struct irq_data *data)
32{
33 mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
34}
35
36static void or1k_pic_unmask(struct irq_data *data)
37{
38 mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
39}
40
41static void or1k_pic_ack(struct irq_data *data)
42{
43 mtspr(SPR_PICSR, (1UL << data->hwirq));
44}
45
46static void or1k_pic_mask_ack(struct irq_data *data)
47{
48 mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
49 mtspr(SPR_PICSR, (1UL << data->hwirq));
50}
51
52/*
53 * There are two oddities with the OR1200 PIC implementation:
54 * i) LEVEL-triggered interrupts are latched and need to be cleared
55 * ii) the interrupt latch is cleared by writing a 0 to the bit,
56 * as opposed to a 1 as mandated by the spec
57 */
58static void or1k_pic_or1200_ack(struct irq_data *data)
59{
60 mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
61}
62
63static void or1k_pic_or1200_mask_ack(struct irq_data *data)
64{
65 mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
66 mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
67}
68
69static struct or1k_pic_dev or1k_pic_level = {
70 .chip = {
71 .name = "or1k-PIC-level",
72 .irq_unmask = or1k_pic_unmask,
73 .irq_mask = or1k_pic_mask,
74 .irq_mask_ack = or1k_pic_mask,
75 },
76 .handle = handle_level_irq,
77 .flags = IRQ_LEVEL | IRQ_NOPROBE,
78};
79
80static struct or1k_pic_dev or1k_pic_edge = {
81 .chip = {
82 .name = "or1k-PIC-edge",
83 .irq_unmask = or1k_pic_unmask,
84 .irq_mask = or1k_pic_mask,
85 .irq_ack = or1k_pic_ack,
86 .irq_mask_ack = or1k_pic_mask_ack,
87 },
88 .handle = handle_edge_irq,
89 .flags = IRQ_LEVEL | IRQ_NOPROBE,
90};
91
92static struct or1k_pic_dev or1k_pic_or1200 = {
93 .chip = {
94 .name = "or1200-PIC",
95 .irq_unmask = or1k_pic_unmask,
96 .irq_mask = or1k_pic_mask,
97 .irq_ack = or1k_pic_or1200_ack,
98 .irq_mask_ack = or1k_pic_or1200_mask_ack,
99 },
100 .handle = handle_level_irq,
101 .flags = IRQ_LEVEL | IRQ_NOPROBE,
102};
103
104static struct irq_domain *root_domain;
105
106static inline int pic_get_irq(int first)
107{
108 int hwirq;
109
110 hwirq = ffs(mfspr(SPR_PICSR) >> first);
111 if (!hwirq)
112 return NO_IRQ;
113 else
114 hwirq = hwirq + first - 1;
115
116 return irq_find_mapping(root_domain, hwirq);
117}
118
119static void or1k_pic_handle_irq(struct pt_regs *regs)
120{
121 int irq = -1;
122
123 while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
124 handle_IRQ(irq, regs);
125}
126
127static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
128{
129 struct or1k_pic_dev *pic = d->host_data;
130
131 irq_set_chip_and_handler(irq, &pic->chip, pic->handle);
132 irq_set_status_flags(irq, pic->flags);
133
134 return 0;
135}
136
137static const struct irq_domain_ops or1k_irq_domain_ops = {
138 .xlate = irq_domain_xlate_onecell,
139 .map = or1k_map,
140};
141
142/*
143 * This sets up the IRQ domain for the PIC built in to the OpenRISC
144 * 1000 CPU. This is the "root" domain as these are the interrupts
145 * that directly trigger an exception in the CPU.
146 */
147static int __init or1k_pic_init(struct device_node *node,
148 struct or1k_pic_dev *pic)
149{
150 /* Disable all interrupts until explicitly requested */
151 mtspr(SPR_PICMR, (0UL));
152
153 root_domain = irq_domain_add_linear(node, 32, &or1k_irq_domain_ops,
154 pic);
155
156 set_handle_irq(or1k_pic_handle_irq);
157
158 return 0;
159}
160
161static int __init or1k_pic_or1200_init(struct device_node *node,
162 struct device_node *parent)
163{
164 return or1k_pic_init(node, &or1k_pic_or1200);
165}
166IRQCHIP_DECLARE(or1k_pic_or1200, "opencores,or1200-pic", or1k_pic_or1200_init);
167IRQCHIP_DECLARE(or1k_pic, "opencores,or1k-pic", or1k_pic_or1200_init);
168
169static int __init or1k_pic_level_init(struct device_node *node,
170 struct device_node *parent)
171{
172 return or1k_pic_init(node, &or1k_pic_level);
173}
174IRQCHIP_DECLARE(or1k_pic_level, "opencores,or1k-pic-level",
175 or1k_pic_level_init);
176
177static int __init or1k_pic_edge_init(struct device_node *node,
178 struct device_node *parent)
179{
180 return or1k_pic_init(node, &or1k_pic_edge);
181}
182IRQCHIP_DECLARE(or1k_pic_edge, "opencores,or1k-pic-edge", or1k_pic_edge_init);