diff options
author | Kevin Cernekee <cernekee@gmail.com> | 2014-12-25 12:49:05 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-04-01 11:21:37 -0400 |
commit | 7b7230e70e9eda75356cf15c450b65b77924486f (patch) | |
tree | 240e5446a54d0de5e3caf8566ac39cc01cf7459b /drivers/irqchip | |
parent | ca40f1b23df70c6f31b14a5743a6f3b60e862ce1 (diff) |
IRQCHIP: bcm7120-l2: Add support for BCM3380-style controllers
These controllers support multiple enable/status pairs (64+ IRQs),
can put the enable/status words at different offsets, and do not
support multiple parent IRQs.
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Cc: f.fainelli@gmail.com
Cc: jaedon.shin@gmail.com
Cc: abrestic@chromium.org
Cc: tglx@linutronix.de
Cc: jason@lakedaemon.net
Cc: jogo@openwrt.org
Cc: arnd@arndb.de
Cc: computersforpeace@gmail.com
Cc: linux-mips@linux-mips.org
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/8843/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-bcm7120-l2.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c index 6a6285897df1..3ba5cc780fcb 100644 --- a/drivers/irqchip/irq-bcm7120-l2.c +++ b/drivers/irqchip/irq-bcm7120-l2.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/kconfig.h> | 16 | #include <linux/kconfig.h> |
17 | #include <linux/kernel.h> | ||
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
18 | #include <linux/of.h> | 19 | #include <linux/of.h> |
19 | #include <linux/of_irq.h> | 20 | #include <linux/of_irq.h> |
@@ -120,10 +121,15 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn, | |||
120 | /* For multiple parent IRQs with multiple words, this looks like: | 121 | /* For multiple parent IRQs with multiple words, this looks like: |
121 | * <irq0_w0 irq0_w1 irq1_w0 irq1_w1 ...> | 122 | * <irq0_w0 irq0_w1 irq1_w0 irq1_w1 ...> |
122 | */ | 123 | */ |
123 | for (idx = 0; idx < data->n_words; idx++) | 124 | for (idx = 0; idx < data->n_words; idx++) { |
124 | data->irq_map_mask[idx] |= | 125 | if (data->map_mask_prop) { |
125 | be32_to_cpup(data->map_mask_prop + | 126 | data->irq_map_mask[idx] |= |
126 | irq * data->n_words + idx); | 127 | be32_to_cpup(data->map_mask_prop + |
128 | irq * data->n_words + idx); | ||
129 | } else { | ||
130 | data->irq_map_mask[idx] = 0xffffffff; | ||
131 | } | ||
132 | } | ||
127 | 133 | ||
128 | irq_set_handler_data(parent_irq, data); | 134 | irq_set_handler_data(parent_irq, data); |
129 | irq_set_chained_handler(parent_irq, bcm7120_l2_intc_irq_handle); | 135 | irq_set_chained_handler(parent_irq, bcm7120_l2_intc_irq_handle); |
@@ -165,6 +171,37 @@ static int __init bcm7120_l2_intc_iomap_7120(struct device_node *dn, | |||
165 | return 0; | 171 | return 0; |
166 | } | 172 | } |
167 | 173 | ||
174 | static int __init bcm7120_l2_intc_iomap_3380(struct device_node *dn, | ||
175 | struct bcm7120_l2_intc_data *data) | ||
176 | { | ||
177 | unsigned int gc_idx; | ||
178 | |||
179 | for (gc_idx = 0; gc_idx < MAX_WORDS; gc_idx++) { | ||
180 | unsigned int map_idx = gc_idx * 2; | ||
181 | void __iomem *en = of_iomap(dn, map_idx + 0); | ||
182 | void __iomem *stat = of_iomap(dn, map_idx + 1); | ||
183 | void __iomem *base = min(en, stat); | ||
184 | |||
185 | data->map_base[map_idx + 0] = en; | ||
186 | data->map_base[map_idx + 1] = stat; | ||
187 | |||
188 | if (!base) | ||
189 | break; | ||
190 | |||
191 | data->pair_base[gc_idx] = base; | ||
192 | data->en_offset[gc_idx] = en - base; | ||
193 | data->stat_offset[gc_idx] = stat - base; | ||
194 | } | ||
195 | |||
196 | if (!gc_idx) { | ||
197 | pr_err("unable to map registers\n"); | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | data->n_words = gc_idx; | ||
202 | return 0; | ||
203 | } | ||
204 | |||
168 | int __init bcm7120_l2_intc_probe(struct device_node *dn, | 205 | int __init bcm7120_l2_intc_probe(struct device_node *dn, |
169 | struct device_node *parent, | 206 | struct device_node *parent, |
170 | int (*iomap_regs_fn)(struct device_node *, | 207 | int (*iomap_regs_fn)(struct device_node *, |
@@ -279,5 +316,15 @@ int __init bcm7120_l2_intc_probe_7120(struct device_node *dn, | |||
279 | "BCM7120 L2"); | 316 | "BCM7120 L2"); |
280 | } | 317 | } |
281 | 318 | ||
319 | int __init bcm7120_l2_intc_probe_3380(struct device_node *dn, | ||
320 | struct device_node *parent) | ||
321 | { | ||
322 | return bcm7120_l2_intc_probe(dn, parent, bcm7120_l2_intc_iomap_3380, | ||
323 | "BCM3380 L2"); | ||
324 | } | ||
325 | |||
282 | IRQCHIP_DECLARE(bcm7120_l2_intc, "brcm,bcm7120-l2-intc", | 326 | IRQCHIP_DECLARE(bcm7120_l2_intc, "brcm,bcm7120-l2-intc", |
283 | bcm7120_l2_intc_probe_7120); | 327 | bcm7120_l2_intc_probe_7120); |
328 | |||
329 | IRQCHIP_DECLARE(bcm3380_l2_intc, "brcm,bcm3380-l2-intc", | ||
330 | bcm7120_l2_intc_probe_3380); | ||