summaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-11 21:28:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-11 21:28:06 -0500
commit3d116a66ed9df0271b8d267093b3bfde2be19b3a (patch)
tree8415b051c87b44ea9f7ecd50bf850155b028737e /drivers/irqchip
parentb4cee21ee057ff3e5c9014fb6a175bd932c5ce62 (diff)
parentd3b421cd07e4c0d4d6c0bbd55ca169c054fc081d (diff)
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq updates from Thomas Gleixner: "The irq department provides: - Support for MSI to wire bridges and a first user of it - More ACPI support for ARM/GIC - A new TS-4800 interrupt controller driver - RCU based free of interrupt descriptors to support the upcoming Intel VMD technology without introducing a locking nightmare - The usual pile of fixes and updates to drivers and core code" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (41 commits) irqchip/omap-intc: Add support for spurious irq handling irqchip/zevio: Use irq_data_get_chip_type() helper irqchip/omap-intc: Remove duplicate setup for IRQ chip type handler irqchip/ts4800: Add TS-4800 interrupt controller irqchip/ts4800: Add documentation for TS-4800 interrupt controller irq/platform-MSI: Increase the maximum MSIs the MSI framework can support irqchip/gicv2m: Miscellaneous fixes for v2m resources and SPI ranges irqchip/bcm2836: Make code more readable irqchip/bcm2836: Tolerate IRQs while no flag is set in ISR irqchip/bcm2836: Add SMP support for the 2836 irqchip/bcm2836: Fix initialization of the LOCAL_IRQ_CNT timers irqchip/gic-v2m: acpi: Introducing GICv2m ACPI support irqchip/gic-v2m: Refactor to prepare for ACPI support irqdomain: Introduce is_fwnode_irqchip helper acpi: pci: Setup MSI domain for ACPI based pci devices genirq/msi: Export functions to allow MSI domains in modules irqchip/mbigen: Implement the mbigen irq chip operation functions irqchip/mbigen: Create irq domain for each mbigen device irqchip/mgigen: Add platform device driver for mbigen device dt-bindings: Documents the mbigen bindings ...
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/Kconfig19
-rw-r--r--drivers/irqchip/Makefile3
-rw-r--r--drivers/irqchip/irq-bcm2836.c55
-rw-r--r--drivers/irqchip/irq-gic-realview.c43
-rw-r--r--drivers/irqchip/irq-gic-v2m.c165
-rw-r--r--drivers/irqchip/irq-gic.c64
-rw-r--r--drivers/irqchip/irq-mbigen.c297
-rw-r--r--drivers/irqchip/irq-omap-intc.c28
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c96
-rw-r--r--drivers/irqchip/irq-sunxi-nmi.c13
-rw-r--r--drivers/irqchip/irq-ts4800.c163
-rw-r--r--drivers/irqchip/irq-zevio.c3
12 files changed, 840 insertions, 109 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e5d982..11fc2a27fa2e 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -8,6 +8,11 @@ config ARM_GIC
8 select IRQ_DOMAIN_HIERARCHY 8 select IRQ_DOMAIN_HIERARCHY
9 select MULTI_IRQ_HANDLER 9 select MULTI_IRQ_HANDLER
10 10
11config ARM_GIC_MAX_NR
12 int
13 default 2 if ARCH_REALVIEW
14 default 1
15
11config ARM_GIC_V2M 16config ARM_GIC_V2M
12 bool 17 bool
13 depends on ARM_GIC 18 depends on ARM_GIC
@@ -27,6 +32,14 @@ config ARM_GIC_V3_ITS
27 bool 32 bool
28 select PCI_MSI_IRQ_DOMAIN 33 select PCI_MSI_IRQ_DOMAIN
29 34
35config HISILICON_IRQ_MBIGEN
36 bool "Support mbigen interrupt controller"
37 default n
38 depends on ARM_GIC_V3 && ARM_GIC_V3_ITS && GENERIC_MSI_IRQ_DOMAIN
39 help
40 Enable the mbigen interrupt controller used on
41 Hisilicon platform.
42
30config ARM_NVIC 43config ARM_NVIC
31 bool 44 bool
32 select IRQ_DOMAIN 45 select IRQ_DOMAIN
@@ -138,6 +151,12 @@ config TB10X_IRQC
138 select IRQ_DOMAIN 151 select IRQ_DOMAIN
139 select GENERIC_IRQ_CHIP 152 select GENERIC_IRQ_CHIP
140 153
154config TS4800_IRQ
155 tristate "TS-4800 IRQ controller"
156 select IRQ_DOMAIN
157 help
158 Support for the TS-4800 FPGA IRQ controller
159
141config VERSATILE_FPGA_IRQ 160config VERSATILE_FPGA_IRQ
142 bool 161 bool
143 select IRQ_DOMAIN 162 select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f6e6d6..d4c2e4ebc308 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -21,9 +21,11 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
21obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o 21obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
22obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o 22obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
23obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o 23obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
24obj-$(CONFIG_REALVIEW_DT) += irq-gic-realview.o
24obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o 25obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
25obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o 26obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
26obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o 27obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o
28obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
27obj-$(CONFIG_ARM_NVIC) += irq-nvic.o 29obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
28obj-$(CONFIG_ARM_VIC) += irq-vic.o 30obj-$(CONFIG_ARM_VIC) += irq-vic.o
29obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o 31obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o
@@ -39,6 +41,7 @@ obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o
39obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o 41obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o
40obj-$(CONFIG_ST_IRQCHIP) += irq-st.o 42obj-$(CONFIG_ST_IRQCHIP) += irq-st.o
41obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o 43obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o
44obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o
42obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o 45obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o
43obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o 46obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o
44obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o 47obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index f68708281fcf..963065a0d774 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -21,6 +21,9 @@
21#include <linux/irqdomain.h> 21#include <linux/irqdomain.h>
22#include <asm/exception.h> 22#include <asm/exception.h>
23 23
24#define LOCAL_CONTROL 0x000
25#define LOCAL_PRESCALER 0x008
26
24/* 27/*
25 * The low 2 bits identify the CPU that the GPU IRQ goes to, and the 28 * The low 2 bits identify the CPU that the GPU IRQ goes to, and the
26 * next 2 bits identify the CPU that the GPU FIQ goes to. 29 * next 2 bits identify the CPU that the GPU FIQ goes to.
@@ -50,14 +53,16 @@
50/* Same status bits as above, but for FIQ. */ 53/* Same status bits as above, but for FIQ. */
51#define LOCAL_FIQ_PENDING0 0x070 54#define LOCAL_FIQ_PENDING0 0x070
52/* 55/*
53 * Mailbox0 write-to-set bits. There are 16 mailboxes, 4 per CPU, and 56 * Mailbox write-to-set bits. There are 16 mailboxes, 4 per CPU, and
54 * these bits are organized by mailbox number and then CPU number. We 57 * these bits are organized by mailbox number and then CPU number. We
55 * use mailbox 0 for IPIs. The mailbox's interrupt is raised while 58 * use mailbox 0 for IPIs. The mailbox's interrupt is raised while
56 * any bit is set. 59 * any bit is set.
57 */ 60 */
58#define LOCAL_MAILBOX0_SET0 0x080 61#define LOCAL_MAILBOX0_SET0 0x080
59/* Mailbox0 write-to-clear bits. */ 62#define LOCAL_MAILBOX3_SET0 0x08c
63/* Mailbox write-to-clear bits. */
60#define LOCAL_MAILBOX0_CLR0 0x0c0 64#define LOCAL_MAILBOX0_CLR0 0x0c0
65#define LOCAL_MAILBOX3_CLR0 0x0cc
61 66
62#define LOCAL_IRQ_CNTPSIRQ 0 67#define LOCAL_IRQ_CNTPSIRQ 0
63#define LOCAL_IRQ_CNTPNSIRQ 1 68#define LOCAL_IRQ_CNTPNSIRQ 1
@@ -162,7 +167,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
162 u32 stat; 167 u32 stat;
163 168
164 stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu); 169 stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);
165 if (stat & 0x10) { 170 if (stat & BIT(LOCAL_IRQ_MAILBOX0)) {
166#ifdef CONFIG_SMP 171#ifdef CONFIG_SMP
167 void __iomem *mailbox0 = (intc.base + 172 void __iomem *mailbox0 = (intc.base +
168 LOCAL_MAILBOX0_CLR0 + 16 * cpu); 173 LOCAL_MAILBOX0_CLR0 + 16 * cpu);
@@ -172,7 +177,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
172 writel(1 << ipi, mailbox0); 177 writel(1 << ipi, mailbox0);
173 handle_IPI(ipi, regs); 178 handle_IPI(ipi, regs);
174#endif 179#endif
175 } else { 180 } else if (stat) {
176 u32 hwirq = ffs(stat) - 1; 181 u32 hwirq = ffs(stat) - 1;
177 182
178 handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs); 183 handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
@@ -217,6 +222,24 @@ static struct notifier_block bcm2836_arm_irqchip_cpu_notifier = {
217 .notifier_call = bcm2836_arm_irqchip_cpu_notify, 222 .notifier_call = bcm2836_arm_irqchip_cpu_notify,
218 .priority = 100, 223 .priority = 100,
219}; 224};
225
226int __init bcm2836_smp_boot_secondary(unsigned int cpu,
227 struct task_struct *idle)
228{
229 unsigned long secondary_startup_phys =
230 (unsigned long)virt_to_phys((void *)secondary_startup);
231
232 dsb();
233 writel(secondary_startup_phys,
234 intc.base + LOCAL_MAILBOX3_SET0 + 16 * cpu);
235
236 return 0;
237}
238
239static const struct smp_operations bcm2836_smp_ops __initconst = {
240 .smp_boot_secondary = bcm2836_smp_boot_secondary,
241};
242
220#endif 243#endif
221 244
222static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = { 245static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {
@@ -234,9 +257,31 @@ bcm2836_arm_irqchip_smp_init(void)
234 register_cpu_notifier(&bcm2836_arm_irqchip_cpu_notifier); 257 register_cpu_notifier(&bcm2836_arm_irqchip_cpu_notifier);
235 258
236 set_smp_cross_call(bcm2836_arm_irqchip_send_ipi); 259 set_smp_cross_call(bcm2836_arm_irqchip_send_ipi);
260 smp_set_ops(&bcm2836_smp_ops);
237#endif 261#endif
238} 262}
239 263
264/*
265 * The LOCAL_IRQ_CNT* timer firings are based off of the external
266 * oscillator with some scaling. The firmware sets up CNTFRQ to
267 * report 19.2Mhz, but doesn't set up the scaling registers.
268 */
269static void bcm2835_init_local_timer_frequency(void)
270{
271 /*
272 * Set the timer to source from the 19.2Mhz crystal clock (bit
273 * 8 unset), and only increment by 1 instead of 2 (bit 9
274 * unset).
275 */
276 writel(0, intc.base + LOCAL_CONTROL);
277
278 /*
279 * Set the timer prescaler to 1:1 (timer freq = input freq *
280 * 2**31 / prescaler)
281 */
282 writel(0x80000000, intc.base + LOCAL_PRESCALER);
283}
284
240static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node, 285static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
241 struct device_node *parent) 286 struct device_node *parent)
242{ 287{
@@ -246,6 +291,8 @@ static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
246 node->full_name); 291 node->full_name);
247 } 292 }
248 293
294 bcm2835_init_local_timer_frequency();
295
249 intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1, 296 intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,
250 &bcm2836_arm_irqchip_intc_ops, 297 &bcm2836_arm_irqchip_intc_ops,
251 NULL); 298 NULL);
diff --git a/drivers/irqchip/irq-gic-realview.c b/drivers/irqchip/irq-gic-realview.c
new file mode 100644
index 000000000000..aa46eb280a7f
--- /dev/null
+++ b/drivers/irqchip/irq-gic-realview.c
@@ -0,0 +1,43 @@
1/*
2 * Special GIC quirks for the ARM RealView
3 * Copyright (C) 2015 Linus Walleij
4 */
5#include <linux/of.h>
6#include <linux/regmap.h>
7#include <linux/mfd/syscon.h>
8#include <linux/bitops.h>
9#include <linux/irqchip.h>
10#include <linux/irqchip/arm-gic.h>
11
12#define REALVIEW_SYS_LOCK_OFFSET 0x20
13#define REALVIEW_PB11MP_SYS_PLD_CTRL1 0x74
14#define VERSATILE_LOCK_VAL 0xA05F
15#define PLD_INTMODE_MASK BIT(22)|BIT(23)|BIT(24)
16#define PLD_INTMODE_LEGACY 0x0
17#define PLD_INTMODE_NEW_DCC BIT(22)
18#define PLD_INTMODE_NEW_NO_DCC BIT(23)
19#define PLD_INTMODE_FIQ_ENABLE BIT(24)
20
21static int __init
22realview_gic_of_init(struct device_node *node, struct device_node *parent)
23{
24 static struct regmap *map;
25
26 /* The PB11MPCore GIC needs to be configured in the syscon */
27 map = syscon_regmap_lookup_by_compatible("arm,realview-pb11mp-syscon");
28 if (!IS_ERR(map)) {
29 /* new irq mode with no DCC */
30 regmap_write(map, REALVIEW_SYS_LOCK_OFFSET,
31 VERSATILE_LOCK_VAL);
32 regmap_update_bits(map, REALVIEW_PB11MP_SYS_PLD_CTRL1,
33 PLD_INTMODE_NEW_NO_DCC,
34 PLD_INTMODE_MASK);
35 regmap_write(map, REALVIEW_SYS_LOCK_OFFSET, 0x0000);
36 pr_info("TC11MP GIC: set up interrupt controller to NEW mode, no DCC\n");
37 } else {
38 pr_err("TC11MP GIC setup: could not find syscon\n");
39 return -ENXIO;
40 }
41 return gic_of_init(node, parent);
42}
43IRQCHIP_DECLARE(armtc11mp_gic, "arm,tc11mp-gic", realview_gic_of_init);
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 87f8d104acab..c779f83e511d 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -15,9 +15,11 @@
15 15
16#define pr_fmt(fmt) "GICv2m: " fmt 16#define pr_fmt(fmt) "GICv2m: " fmt
17 17
18#include <linux/acpi.h>
18#include <linux/irq.h> 19#include <linux/irq.h>
19#include <linux/irqdomain.h> 20#include <linux/irqdomain.h>
20#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/msi.h>
21#include <linux/of_address.h> 23#include <linux/of_address.h>
22#include <linux/of_pci.h> 24#include <linux/of_pci.h>
23#include <linux/slab.h> 25#include <linux/slab.h>
@@ -55,7 +57,7 @@ static DEFINE_SPINLOCK(v2m_lock);
55 57
56struct v2m_data { 58struct v2m_data {
57 struct list_head entry; 59 struct list_head entry;
58 struct device_node *node; 60 struct fwnode_handle *fwnode;
59 struct resource res; /* GICv2m resource */ 61 struct resource res; /* GICv2m resource */
60 void __iomem *base; /* GICv2m virt address */ 62 void __iomem *base; /* GICv2m virt address */
61 u32 spi_start; /* The SPI number that MSIs start */ 63 u32 spi_start; /* The SPI number that MSIs start */
@@ -138,6 +140,11 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
138 fwspec.param[0] = 0; 140 fwspec.param[0] = 0;
139 fwspec.param[1] = hwirq - 32; 141 fwspec.param[1] = hwirq - 32;
140 fwspec.param[2] = IRQ_TYPE_EDGE_RISING; 142 fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
143 } else if (is_fwnode_irqchip(domain->parent->fwnode)) {
144 fwspec.fwnode = domain->parent->fwnode;
145 fwspec.param_count = 2;
146 fwspec.param[0] = hwirq;
147 fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
141 } else { 148 } else {
142 return -EINVAL; 149 return -EINVAL;
143 } 150 }
@@ -254,7 +261,9 @@ static void gicv2m_teardown(void)
254 list_del(&v2m->entry); 261 list_del(&v2m->entry);
255 kfree(v2m->bm); 262 kfree(v2m->bm);
256 iounmap(v2m->base); 263 iounmap(v2m->base);
257 of_node_put(v2m->node); 264 of_node_put(to_of_node(v2m->fwnode));
265 if (is_fwnode_irqchip(v2m->fwnode))
266 irq_domain_free_fwnode(v2m->fwnode);
258 kfree(v2m); 267 kfree(v2m);
259 } 268 }
260} 269}
@@ -268,7 +277,7 @@ static int gicv2m_allocate_domains(struct irq_domain *parent)
268 if (!v2m) 277 if (!v2m)
269 return 0; 278 return 0;
270 279
271 inner_domain = irq_domain_create_tree(of_node_to_fwnode(v2m->node), 280 inner_domain = irq_domain_create_tree(v2m->fwnode,
272 &gicv2m_domain_ops, v2m); 281 &gicv2m_domain_ops, v2m);
273 if (!inner_domain) { 282 if (!inner_domain) {
274 pr_err("Failed to create GICv2m domain\n"); 283 pr_err("Failed to create GICv2m domain\n");
@@ -277,10 +286,10 @@ static int gicv2m_allocate_domains(struct irq_domain *parent)
277 286
278 inner_domain->bus_token = DOMAIN_BUS_NEXUS; 287 inner_domain->bus_token = DOMAIN_BUS_NEXUS;
279 inner_domain->parent = parent; 288 inner_domain->parent = parent;
280 pci_domain = pci_msi_create_irq_domain(of_node_to_fwnode(v2m->node), 289 pci_domain = pci_msi_create_irq_domain(v2m->fwnode,
281 &gicv2m_msi_domain_info, 290 &gicv2m_msi_domain_info,
282 inner_domain); 291 inner_domain);
283 plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(v2m->node), 292 plat_domain = platform_msi_create_irq_domain(v2m->fwnode,
284 &gicv2m_pmsi_domain_info, 293 &gicv2m_pmsi_domain_info,
285 inner_domain); 294 inner_domain);
286 if (!pci_domain || !plat_domain) { 295 if (!pci_domain || !plat_domain) {
@@ -296,8 +305,9 @@ static int gicv2m_allocate_domains(struct irq_domain *parent)
296 return 0; 305 return 0;
297} 306}
298 307
299static int __init gicv2m_init_one(struct device_node *node, 308static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
300 struct irq_domain *parent) 309 u32 spi_start, u32 nr_spis,
310 struct resource *res)
301{ 311{
302 int ret; 312 int ret;
303 struct v2m_data *v2m; 313 struct v2m_data *v2m;
@@ -309,13 +319,9 @@ static int __init gicv2m_init_one(struct device_node *node,
309 } 319 }
310 320
311 INIT_LIST_HEAD(&v2m->entry); 321 INIT_LIST_HEAD(&v2m->entry);
312 v2m->node = node; 322 v2m->fwnode = fwnode;
313 323
314 ret = of_address_to_resource(node, 0, &v2m->res); 324 memcpy(&v2m->res, res, sizeof(struct resource));
315 if (ret) {
316 pr_err("Failed to allocate v2m resource.\n");
317 goto err_free_v2m;
318 }
319 325
320 v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res)); 326 v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res));
321 if (!v2m->base) { 327 if (!v2m->base) {
@@ -324,10 +330,9 @@ static int __init gicv2m_init_one(struct device_node *node,
324 goto err_free_v2m; 330 goto err_free_v2m;
325 } 331 }
326 332
327 if (!of_property_read_u32(node, "arm,msi-base-spi", &v2m->spi_start) && 333 if (spi_start && nr_spis) {
328 !of_property_read_u32(node, "arm,msi-num-spis", &v2m->nr_spis)) { 334 v2m->spi_start = spi_start;
329 pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n", 335 v2m->nr_spis = nr_spis;
330 v2m->spi_start, v2m->nr_spis);
331 } else { 336 } else {
332 u32 typer = readl_relaxed(v2m->base + V2M_MSI_TYPER); 337 u32 typer = readl_relaxed(v2m->base + V2M_MSI_TYPER);
333 338
@@ -359,10 +364,9 @@ static int __init gicv2m_init_one(struct device_node *node,
359 } 364 }
360 365
361 list_add_tail(&v2m->entry, &v2m_nodes); 366 list_add_tail(&v2m->entry, &v2m_nodes);
362 pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name,
363 (unsigned long)v2m->res.start, (unsigned long)v2m->res.end,
364 v2m->spi_start, (v2m->spi_start + v2m->nr_spis));
365 367
368 pr_info("range%pR, SPI[%d:%d]\n", res,
369 v2m->spi_start, (v2m->spi_start + v2m->nr_spis - 1));
366 return 0; 370 return 0;
367 371
368err_iounmap: 372err_iounmap:
@@ -377,19 +381,36 @@ static struct of_device_id gicv2m_device_id[] = {
377 {}, 381 {},
378}; 382};
379 383
380int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent) 384static int __init gicv2m_of_init(struct fwnode_handle *parent_handle,
385 struct irq_domain *parent)
381{ 386{
382 int ret = 0; 387 int ret = 0;
388 struct device_node *node = to_of_node(parent_handle);
383 struct device_node *child; 389 struct device_node *child;
384 390
385 for (child = of_find_matching_node(node, gicv2m_device_id); child; 391 for (child = of_find_matching_node(node, gicv2m_device_id); child;
386 child = of_find_matching_node(child, gicv2m_device_id)) { 392 child = of_find_matching_node(child, gicv2m_device_id)) {
393 u32 spi_start = 0, nr_spis = 0;
394 struct resource res;
395
387 if (!of_find_property(child, "msi-controller", NULL)) 396 if (!of_find_property(child, "msi-controller", NULL))
388 continue; 397 continue;
389 398
390 ret = gicv2m_init_one(child, parent); 399 ret = of_address_to_resource(child, 0, &res);
400 if (ret) {
401 pr_err("Failed to allocate v2m resource.\n");
402 break;
403 }
404
405 if (!of_property_read_u32(child, "arm,msi-base-spi",
406 &spi_start) &&
407 !of_property_read_u32(child, "arm,msi-num-spis", &nr_spis))
408 pr_info("DT overriding V2M MSI_TYPER (base:%u, num:%u)\n",
409 spi_start, nr_spis);
410
411 ret = gicv2m_init_one(&child->fwnode, spi_start, nr_spis, &res);
391 if (ret) { 412 if (ret) {
392 of_node_put(node); 413 of_node_put(child);
393 break; 414 break;
394 } 415 }
395 } 416 }
@@ -400,3 +421,101 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent)
400 gicv2m_teardown(); 421 gicv2m_teardown();
401 return ret; 422 return ret;
402} 423}
424
425#ifdef CONFIG_ACPI
426static int acpi_num_msi;
427
428static struct fwnode_handle *gicv2m_get_fwnode(struct device *dev)
429{
430 struct v2m_data *data;
431
432 if (WARN_ON(acpi_num_msi <= 0))
433 return NULL;
434
435 /* We only return the fwnode of the first MSI frame. */
436 data = list_first_entry_or_null(&v2m_nodes, struct v2m_data, entry);
437 if (!data)
438 return NULL;
439
440 return data->fwnode;
441}
442
443static int __init
444acpi_parse_madt_msi(struct acpi_subtable_header *header,
445 const unsigned long end)
446{
447 int ret;
448 struct resource res;
449 u32 spi_start = 0, nr_spis = 0;
450 struct acpi_madt_generic_msi_frame *m;
451 struct fwnode_handle *fwnode;
452
453 m = (struct acpi_madt_generic_msi_frame *)header;
454 if (BAD_MADT_ENTRY(m, end))
455 return -EINVAL;
456
457 res.start = m->base_address;
458 res.end = m->base_address + SZ_4K - 1;
459 res.flags = IORESOURCE_MEM;
460
461 if (m->flags & ACPI_MADT_OVERRIDE_SPI_VALUES) {
462 spi_start = m->spi_base;
463 nr_spis = m->spi_count;
464
465 pr_info("ACPI overriding V2M MSI_TYPER (base:%u, num:%u)\n",
466 spi_start, nr_spis);
467 }
468
469 fwnode = irq_domain_alloc_fwnode((void *)m->base_address);
470 if (!fwnode) {
471 pr_err("Unable to allocate GICv2m domain token\n");
472 return -EINVAL;
473 }
474
475 ret = gicv2m_init_one(fwnode, spi_start, nr_spis, &res);
476 if (ret)
477 irq_domain_free_fwnode(fwnode);
478
479 return ret;
480}
481
482static int __init gicv2m_acpi_init(struct irq_domain *parent)
483{
484 int ret;
485
486 if (acpi_num_msi > 0)
487 return 0;
488
489 acpi_num_msi = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_MSI_FRAME,
490 acpi_parse_madt_msi, 0);
491
492 if (acpi_num_msi <= 0)
493 goto err_out;
494
495 ret = gicv2m_allocate_domains(parent);
496 if (ret)
497 goto err_out;
498
499 pci_msi_register_fwnode_provider(&gicv2m_get_fwnode);
500
501 return 0;
502
503err_out:
504 gicv2m_teardown();
505 return -EINVAL;
506}
507#else /* CONFIG_ACPI */
508static int __init gicv2m_acpi_init(struct irq_domain *parent)
509{
510 return -EINVAL;
511}
512#endif /* CONFIG_ACPI */
513
514int __init gicv2m_init(struct fwnode_handle *parent_handle,
515 struct irq_domain *parent)
516{
517 if (is_of_node(parent_handle))
518 return gicv2m_of_init(parent_handle, parent);
519
520 return gicv2m_acpi_init(parent);
521}
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index abf2ffaed392..911758c056c1 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -69,6 +69,7 @@ union gic_base {
69}; 69};
70 70
71struct gic_chip_data { 71struct gic_chip_data {
72 struct irq_chip chip;
72 union gic_base dist_base; 73 union gic_base dist_base;
73 union gic_base cpu_base; 74 union gic_base cpu_base;
74#ifdef CONFIG_CPU_PM 75#ifdef CONFIG_CPU_PM
@@ -99,11 +100,7 @@ static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
99 100
100static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; 101static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
101 102
102#ifndef MAX_GIC_NR 103static struct gic_chip_data gic_data[CONFIG_ARM_GIC_MAX_NR] __read_mostly;
103#define MAX_GIC_NR 1
104#endif
105
106static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
107 104
108#ifdef CONFIG_GIC_NON_BANKED 105#ifdef CONFIG_GIC_NON_BANKED
109static void __iomem *gic_get_percpu_base(union gic_base *base) 106static void __iomem *gic_get_percpu_base(union gic_base *base)
@@ -336,7 +333,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
336 irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); 333 irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
337 irqnr = irqstat & GICC_IAR_INT_ID_MASK; 334 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
338 335
339 if (likely(irqnr > 15 && irqnr < 1021)) { 336 if (likely(irqnr > 15 && irqnr < 1020)) {
340 if (static_key_true(&supports_deactivate)) 337 if (static_key_true(&supports_deactivate))
341 writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); 338 writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
342 handle_domain_irq(gic->domain, irqnr, regs); 339 handle_domain_irq(gic->domain, irqnr, regs);
@@ -383,7 +380,6 @@ static void gic_handle_cascade_irq(struct irq_desc *desc)
383} 380}
384 381
385static struct irq_chip gic_chip = { 382static struct irq_chip gic_chip = {
386 .name = "GIC",
387 .irq_mask = gic_mask_irq, 383 .irq_mask = gic_mask_irq,
388 .irq_unmask = gic_unmask_irq, 384 .irq_unmask = gic_unmask_irq,
389 .irq_eoi = gic_eoi_irq, 385 .irq_eoi = gic_eoi_irq,
@@ -417,8 +413,7 @@ static struct irq_chip gic_eoimode1_chip = {
417 413
418void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) 414void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
419{ 415{
420 if (gic_nr >= MAX_GIC_NR) 416 BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
421 BUG();
422 irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq, 417 irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq,
423 &gic_data[gic_nr]); 418 &gic_data[gic_nr]);
424} 419}
@@ -524,7 +519,7 @@ int gic_cpu_if_down(unsigned int gic_nr)
524 void __iomem *cpu_base; 519 void __iomem *cpu_base;
525 u32 val = 0; 520 u32 val = 0;
526 521
527 if (gic_nr >= MAX_GIC_NR) 522 if (gic_nr >= CONFIG_ARM_GIC_MAX_NR)
528 return -EINVAL; 523 return -EINVAL;
529 524
530 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); 525 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
@@ -548,8 +543,7 @@ static void gic_dist_save(unsigned int gic_nr)
548 void __iomem *dist_base; 543 void __iomem *dist_base;
549 int i; 544 int i;
550 545
551 if (gic_nr >= MAX_GIC_NR) 546 BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
552 BUG();
553 547
554 gic_irqs = gic_data[gic_nr].gic_irqs; 548 gic_irqs = gic_data[gic_nr].gic_irqs;
555 dist_base = gic_data_dist_base(&gic_data[gic_nr]); 549 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
@@ -587,8 +581,7 @@ static void gic_dist_restore(unsigned int gic_nr)
587 unsigned int i; 581 unsigned int i;
588 void __iomem *dist_base; 582 void __iomem *dist_base;
589 583
590 if (gic_nr >= MAX_GIC_NR) 584 BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
591 BUG();
592 585
593 gic_irqs = gic_data[gic_nr].gic_irqs; 586 gic_irqs = gic_data[gic_nr].gic_irqs;
594 dist_base = gic_data_dist_base(&gic_data[gic_nr]); 587 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
@@ -634,8 +627,7 @@ static void gic_cpu_save(unsigned int gic_nr)
634 void __iomem *dist_base; 627 void __iomem *dist_base;
635 void __iomem *cpu_base; 628 void __iomem *cpu_base;
636 629
637 if (gic_nr >= MAX_GIC_NR) 630 BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
638 BUG();
639 631
640 dist_base = gic_data_dist_base(&gic_data[gic_nr]); 632 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
641 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); 633 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
@@ -664,8 +656,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
664 void __iomem *dist_base; 656 void __iomem *dist_base;
665 void __iomem *cpu_base; 657 void __iomem *cpu_base;
666 658
667 if (gic_nr >= MAX_GIC_NR) 659 BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
668 BUG();
669 660
670 dist_base = gic_data_dist_base(&gic_data[gic_nr]); 661 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
671 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); 662 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
@@ -703,7 +694,7 @@ static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
703{ 694{
704 int i; 695 int i;
705 696
706 for (i = 0; i < MAX_GIC_NR; i++) { 697 for (i = 0; i < CONFIG_ARM_GIC_MAX_NR; i++) {
707#ifdef CONFIG_GIC_NON_BANKED 698#ifdef CONFIG_GIC_NON_BANKED
708 /* Skip over unused GICs */ 699 /* Skip over unused GICs */
709 if (!gic_data[i].get_base) 700 if (!gic_data[i].get_base)
@@ -835,8 +826,7 @@ void gic_migrate_target(unsigned int new_cpu_id)
835 int i, ror_val, cpu = smp_processor_id(); 826 int i, ror_val, cpu = smp_processor_id();
836 u32 val, cur_target_mask, active_mask; 827 u32 val, cur_target_mask, active_mask;
837 828
838 if (gic_nr >= MAX_GIC_NR) 829 BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
839 BUG();
840 830
841 dist_base = gic_data_dist_base(&gic_data[gic_nr]); 831 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
842 if (!dist_base) 832 if (!dist_base)
@@ -925,20 +915,15 @@ void __init gic_init_physaddr(struct device_node *node)
925static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, 915static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
926 irq_hw_number_t hw) 916 irq_hw_number_t hw)
927{ 917{
928 struct irq_chip *chip = &gic_chip; 918 struct gic_chip_data *gic = d->host_data;
929
930 if (static_key_true(&supports_deactivate)) {
931 if (d->host_data == (void *)&gic_data[0])
932 chip = &gic_eoimode1_chip;
933 }
934 919
935 if (hw < 32) { 920 if (hw < 32) {
936 irq_set_percpu_devid(irq); 921 irq_set_percpu_devid(irq);
937 irq_domain_set_info(d, irq, hw, chip, d->host_data, 922 irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
938 handle_percpu_devid_irq, NULL, NULL); 923 handle_percpu_devid_irq, NULL, NULL);
939 irq_set_status_flags(irq, IRQ_NOAUTOEN); 924 irq_set_status_flags(irq, IRQ_NOAUTOEN);
940 } else { 925 } else {
941 irq_domain_set_info(d, irq, hw, chip, d->host_data, 926 irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
942 handle_fasteoi_irq, NULL, NULL); 927 handle_fasteoi_irq, NULL, NULL);
943 irq_set_probe(irq); 928 irq_set_probe(irq);
944 } 929 }
@@ -972,7 +957,7 @@ static int gic_irq_domain_translate(struct irq_domain *d,
972 return 0; 957 return 0;
973 } 958 }
974 959
975 if (fwspec->fwnode->type == FWNODE_IRQCHIP) { 960 if (is_fwnode_irqchip(fwspec->fwnode)) {
976 if(fwspec->param_count != 2) 961 if(fwspec->param_count != 2)
977 return -EINVAL; 962 return -EINVAL;
978 963
@@ -1040,11 +1025,20 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
1040 struct gic_chip_data *gic; 1025 struct gic_chip_data *gic;
1041 int gic_irqs, irq_base, i; 1026 int gic_irqs, irq_base, i;
1042 1027
1043 BUG_ON(gic_nr >= MAX_GIC_NR); 1028 BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
1044 1029
1045 gic_check_cpu_features(); 1030 gic_check_cpu_features();
1046 1031
1047 gic = &gic_data[gic_nr]; 1032 gic = &gic_data[gic_nr];
1033
1034 /* Initialize irq_chip */
1035 if (static_key_true(&supports_deactivate) && gic_nr == 0) {
1036 gic->chip = gic_eoimode1_chip;
1037 } else {
1038 gic->chip = gic_chip;
1039 gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr);
1040 }
1041
1048#ifdef CONFIG_GIC_NON_BANKED 1042#ifdef CONFIG_GIC_NON_BANKED
1049 if (percpu_offset) { /* Frankein-GIC without banked registers... */ 1043 if (percpu_offset) { /* Frankein-GIC without banked registers... */
1050 unsigned int cpu; 1044 unsigned int cpu;
@@ -1196,7 +1190,7 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
1196 return true; 1190 return true;
1197} 1191}
1198 1192
1199static int __init 1193int __init
1200gic_of_init(struct device_node *node, struct device_node *parent) 1194gic_of_init(struct device_node *node, struct device_node *parent)
1201{ 1195{
1202 void __iomem *cpu_base; 1196 void __iomem *cpu_base;
@@ -1234,7 +1228,7 @@ gic_of_init(struct device_node *node, struct device_node *parent)
1234 } 1228 }
1235 1229
1236 if (IS_ENABLED(CONFIG_ARM_GIC_V2M)) 1230 if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
1237 gicv2m_of_init(node, gic_data[gic_cnt].domain); 1231 gicv2m_init(&node->fwnode, gic_data[gic_cnt].domain);
1238 1232
1239 gic_cnt++; 1233 gic_cnt++;
1240 return 0; 1234 return 0;
@@ -1359,6 +1353,10 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
1359 __gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle); 1353 __gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle);
1360 1354
1361 acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle); 1355 acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
1356
1357 if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
1358 gicv2m_init(NULL, gic_data[0].domain);
1359
1362 return 0; 1360 return 0;
1363} 1361}
1364IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 1362IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
new file mode 100644
index 000000000000..4dd3eb8a40b3
--- /dev/null
+++ b/drivers/irqchip/irq-mbigen.c
@@ -0,0 +1,297 @@
1/*
2 * Copyright (C) 2015 Hisilicon Limited, All Rights Reserved.
3 * Author: Jun Ma <majun258@huawei.com>
4 * Author: Yun Wu <wuyun.wu@huawei.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/interrupt.h>
20#include <linux/irqchip.h>
21#include <linux/module.h>
22#include <linux/msi.h>
23#include <linux/of_address.h>
24#include <linux/of_irq.h>
25#include <linux/of_platform.h>
26#include <linux/platform_device.h>
27#include <linux/slab.h>
28
29/* Interrupt numbers per mbigen node supported */
30#define IRQS_PER_MBIGEN_NODE 128
31
32/* 64 irqs (Pin0-pin63) are reserved for each mbigen chip */
33#define RESERVED_IRQ_PER_MBIGEN_CHIP 64
34
35/* The maximum IRQ pin number of mbigen chip(start from 0) */
36#define MAXIMUM_IRQ_PIN_NUM 1407
37
38/**
39 * In mbigen vector register
40 * bit[21:12]: event id value
41 * bit[11:0]: device id
42 */
43#define IRQ_EVENT_ID_SHIFT 12
44#define IRQ_EVENT_ID_MASK 0x3ff
45
46/* register range of each mbigen node */
47#define MBIGEN_NODE_OFFSET 0x1000
48
49/* offset of vector register in mbigen node */
50#define REG_MBIGEN_VEC_OFFSET 0x200
51
52/**
53 * offset of clear register in mbigen node
54 * This register is used to clear the status
55 * of interrupt
56 */
57#define REG_MBIGEN_CLEAR_OFFSET 0xa000
58
59/**
60 * offset of interrupt type register
61 * This register is used to configure interrupt
62 * trigger type
63 */
64#define REG_MBIGEN_TYPE_OFFSET 0x0
65
66/**
67 * struct mbigen_device - holds the information of mbigen device.
68 *
69 * @pdev: pointer to the platform device structure of mbigen chip.
70 * @base: mapped address of this mbigen chip.
71 */
72struct mbigen_device {
73 struct platform_device *pdev;
74 void __iomem *base;
75};
76
77static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
78{
79 unsigned int nid, pin;
80
81 hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
82 nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
83 pin = hwirq % IRQS_PER_MBIGEN_NODE;
84
85 return pin * 4 + nid * MBIGEN_NODE_OFFSET
86 + REG_MBIGEN_VEC_OFFSET;
87}
88
89static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
90 u32 *mask, u32 *addr)
91{
92 unsigned int nid, irq_ofst, ofst;
93
94 hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
95 nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
96 irq_ofst = hwirq % IRQS_PER_MBIGEN_NODE;
97
98 *mask = 1 << (irq_ofst % 32);
99 ofst = irq_ofst / 32 * 4;
100
101 *addr = ofst + nid * MBIGEN_NODE_OFFSET
102 + REG_MBIGEN_TYPE_OFFSET;
103}
104
105static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
106 u32 *mask, u32 *addr)
107{
108 unsigned int ofst;
109
110 hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
111 ofst = hwirq / 32 * 4;
112
113 *mask = 1 << (hwirq % 32);
114 *addr = ofst + REG_MBIGEN_CLEAR_OFFSET;
115}
116
117static void mbigen_eoi_irq(struct irq_data *data)
118{
119 void __iomem *base = data->chip_data;
120 u32 mask, addr;
121
122 get_mbigen_clear_reg(data->hwirq, &mask, &addr);
123
124 writel_relaxed(mask, base + addr);
125
126 irq_chip_eoi_parent(data);
127}
128
129static int mbigen_set_type(struct irq_data *data, unsigned int type)
130{
131 void __iomem *base = data->chip_data;
132 u32 mask, addr, val;
133
134 if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
135 return -EINVAL;
136
137 get_mbigen_type_reg(data->hwirq, &mask, &addr);
138
139 val = readl_relaxed(base + addr);
140
141 if (type == IRQ_TYPE_LEVEL_HIGH)
142 val |= mask;
143 else
144 val &= ~mask;
145
146 writel_relaxed(val, base + addr);
147
148 return 0;
149}
150
151static struct irq_chip mbigen_irq_chip = {
152 .name = "mbigen-v2",
153 .irq_mask = irq_chip_mask_parent,
154 .irq_unmask = irq_chip_unmask_parent,
155 .irq_eoi = mbigen_eoi_irq,
156 .irq_set_type = mbigen_set_type,
157 .irq_set_affinity = irq_chip_set_affinity_parent,
158};
159
160static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg)
161{
162 struct irq_data *d = irq_get_irq_data(desc->irq);
163 void __iomem *base = d->chip_data;
164 u32 val;
165
166 base += get_mbigen_vec_reg(d->hwirq);
167 val = readl_relaxed(base);
168
169 val &= ~(IRQ_EVENT_ID_MASK << IRQ_EVENT_ID_SHIFT);
170 val |= (msg->data << IRQ_EVENT_ID_SHIFT);
171
172 /* The address of doorbell is encoded in mbigen register by default
173 * So,we don't need to program the doorbell address at here
174 */
175 writel_relaxed(val, base);
176}
177
178static int mbigen_domain_translate(struct irq_domain *d,
179 struct irq_fwspec *fwspec,
180 unsigned long *hwirq,
181 unsigned int *type)
182{
183 if (is_of_node(fwspec->fwnode)) {
184 if (fwspec->param_count != 2)
185 return -EINVAL;
186
187 if ((fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) ||
188 (fwspec->param[0] < RESERVED_IRQ_PER_MBIGEN_CHIP))
189 return -EINVAL;
190 else
191 *hwirq = fwspec->param[0];
192
193 /* If there is no valid irq type, just use the default type */
194 if ((fwspec->param[1] == IRQ_TYPE_EDGE_RISING) ||
195 (fwspec->param[1] == IRQ_TYPE_LEVEL_HIGH))
196 *type = fwspec->param[1];
197 else
198 return -EINVAL;
199
200 return 0;
201 }
202 return -EINVAL;
203}
204
205static int mbigen_irq_domain_alloc(struct irq_domain *domain,
206 unsigned int virq,
207 unsigned int nr_irqs,
208 void *args)
209{
210 struct irq_fwspec *fwspec = args;
211 irq_hw_number_t hwirq;
212 unsigned int type;
213 struct mbigen_device *mgn_chip;
214 int i, err;
215
216 err = mbigen_domain_translate(domain, fwspec, &hwirq, &type);
217 if (err)
218 return err;
219
220 err = platform_msi_domain_alloc(domain, virq, nr_irqs);
221 if (err)
222 return err;
223
224 mgn_chip = platform_msi_get_host_data(domain);
225
226 for (i = 0; i < nr_irqs; i++)
227 irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
228 &mbigen_irq_chip, mgn_chip->base);
229
230 return 0;
231}
232
233static struct irq_domain_ops mbigen_domain_ops = {
234 .translate = mbigen_domain_translate,
235 .alloc = mbigen_irq_domain_alloc,
236 .free = irq_domain_free_irqs_common,
237};
238
239static int mbigen_device_probe(struct platform_device *pdev)
240{
241 struct mbigen_device *mgn_chip;
242 struct resource *res;
243 struct irq_domain *domain;
244 u32 num_pins;
245
246 mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL);
247 if (!mgn_chip)
248 return -ENOMEM;
249
250 mgn_chip->pdev = pdev;
251
252 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
253 mgn_chip->base = devm_ioremap_resource(&pdev->dev, res);
254 if (IS_ERR(mgn_chip->base))
255 return PTR_ERR(mgn_chip->base);
256
257 if (of_property_read_u32(pdev->dev.of_node, "num-pins", &num_pins) < 0) {
258 dev_err(&pdev->dev, "No num-pins property\n");
259 return -EINVAL;
260 }
261
262 domain = platform_msi_create_device_domain(&pdev->dev, num_pins,
263 mbigen_write_msg,
264 &mbigen_domain_ops,
265 mgn_chip);
266
267 if (!domain)
268 return -ENOMEM;
269
270 platform_set_drvdata(pdev, mgn_chip);
271
272 dev_info(&pdev->dev, "Allocated %d MSIs\n", num_pins);
273
274 return 0;
275}
276
277static const struct of_device_id mbigen_of_match[] = {
278 { .compatible = "hisilicon,mbigen-v2" },
279 { /* END */ }
280};
281MODULE_DEVICE_TABLE(of, mbigen_of_match);
282
283static struct platform_driver mbigen_platform_driver = {
284 .driver = {
285 .name = "Hisilicon MBIGEN-V2",
286 .owner = THIS_MODULE,
287 .of_match_table = mbigen_of_match,
288 },
289 .probe = mbigen_device_probe,
290};
291
292module_platform_driver(mbigen_platform_driver);
293
294MODULE_AUTHOR("Jun Ma <majun258@huawei.com>");
295MODULE_AUTHOR("Yun Wu <wuyun.wu@huawei.com>");
296MODULE_LICENSE("GPL");
297MODULE_DESCRIPTION("Hisilicon MBI Generator driver");
diff --git a/drivers/irqchip/irq-omap-intc.c b/drivers/irqchip/irq-omap-intc.c
index 8587d0f8d8c0..9d1bcfc33e4c 100644
--- a/drivers/irqchip/irq-omap-intc.c
+++ b/drivers/irqchip/irq-omap-intc.c
@@ -47,6 +47,7 @@
47#define INTC_ILR0 0x0100 47#define INTC_ILR0 0x0100
48 48
49#define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */ 49#define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */
50#define SPURIOUSIRQ_MASK (0x1ffffff << 7)
50#define INTCPS_NR_ILR_REGS 128 51#define INTCPS_NR_ILR_REGS 128
51#define INTCPS_NR_MIR_REGS 4 52#define INTCPS_NR_MIR_REGS 4
52 53
@@ -207,7 +208,6 @@ static int __init omap_alloc_gc_of(struct irq_domain *d, void __iomem *base)
207 ct = gc->chip_types; 208 ct = gc->chip_types;
208 209
209 ct->type = IRQ_TYPE_LEVEL_MASK; 210 ct->type = IRQ_TYPE_LEVEL_MASK;
210 ct->handler = handle_level_irq;
211 211
212 ct->chip.irq_ack = omap_mask_ack_irq; 212 ct->chip.irq_ack = omap_mask_ack_irq;
213 ct->chip.irq_mask = irq_gc_mask_disable_reg; 213 ct->chip.irq_mask = irq_gc_mask_disable_reg;
@@ -330,11 +330,35 @@ static int __init omap_init_irq(u32 base, struct device_node *node)
330static asmlinkage void __exception_irq_entry 330static asmlinkage void __exception_irq_entry
331omap_intc_handle_irq(struct pt_regs *regs) 331omap_intc_handle_irq(struct pt_regs *regs)
332{ 332{
333 extern unsigned long irq_err_count;
333 u32 irqnr; 334 u32 irqnr;
334 335
335 irqnr = intc_readl(INTC_SIR); 336 irqnr = intc_readl(INTC_SIR);
337
338 /*
339 * A spurious IRQ can result if interrupt that triggered the
340 * sorting is no longer active during the sorting (10 INTC
341 * functional clock cycles after interrupt assertion). Or a
342 * change in interrupt mask affected the result during sorting
343 * time. There is no special handling required except ignoring
344 * the SIR register value just read and retrying.
345 * See section 6.2.5 of AM335x TRM Literature Number: SPRUH73K
346 *
347 * Many a times, a spurious interrupt situation has been fixed
348 * by adding a flush for the posted write acking the IRQ in
349 * the device driver. Typically, this is going be the device
350 * driver whose interrupt was handled just before the spurious
351 * IRQ occurred. Pay attention to those device drivers if you
352 * run into hitting the spurious IRQ condition below.
353 */
354 if (unlikely((irqnr & SPURIOUSIRQ_MASK) == SPURIOUSIRQ_MASK)) {
355 pr_err_once("%s: spurious irq!\n", __func__);
356 irq_err_count++;
357 omap_ack_irq(NULL);
358 return;
359 }
360
336 irqnr &= ACTIVEIRQ_MASK; 361 irqnr &= ACTIVEIRQ_MASK;
337 WARN_ONCE(!irqnr, "Spurious IRQ ?\n");
338 handle_domain_irq(domain, irqnr, regs); 362 handle_domain_irq(domain, irqnr, regs);
339} 363}
340 364
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index c325806561be..713177d97c7a 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -31,7 +31,6 @@
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/of_device.h> 33#include <linux/of_device.h>
34#include <linux/platform_data/irq-renesas-intc-irqpin.h>
35#include <linux/pm_runtime.h> 34#include <linux/pm_runtime.h>
36 35
37#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */ 36#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */
@@ -75,18 +74,20 @@ struct intc_irqpin_irq {
75struct intc_irqpin_priv { 74struct intc_irqpin_priv {
76 struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR]; 75 struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR];
77 struct intc_irqpin_irq irq[INTC_IRQPIN_MAX]; 76 struct intc_irqpin_irq irq[INTC_IRQPIN_MAX];
78 struct renesas_intc_irqpin_config config; 77 unsigned int sense_bitfield_width;
79 unsigned int number_of_irqs;
80 struct platform_device *pdev; 78 struct platform_device *pdev;
81 struct irq_chip irq_chip; 79 struct irq_chip irq_chip;
82 struct irq_domain *irq_domain; 80 struct irq_domain *irq_domain;
83 struct clk *clk; 81 struct clk *clk;
84 bool shared_irqs; 82 unsigned shared_irqs:1;
83 unsigned needs_clk:1;
85 u8 shared_irq_mask; 84 u8 shared_irq_mask;
86}; 85};
87 86
88struct intc_irqpin_irlm_config { 87struct intc_irqpin_config {
89 unsigned int irlm_bit; 88 unsigned int irlm_bit;
89 unsigned needs_irlm:1;
90 unsigned needs_clk:1;
90}; 91};
91 92
92static unsigned long intc_irqpin_read32(void __iomem *iomem) 93static unsigned long intc_irqpin_read32(void __iomem *iomem)
@@ -171,7 +172,7 @@ static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
171static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value) 172static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
172{ 173{
173 /* The SENSE register is assumed to be 32-bit. */ 174 /* The SENSE register is assumed to be 32-bit. */
174 int bitfield_width = p->config.sense_bitfield_width; 175 int bitfield_width = p->sense_bitfield_width;
175 int shift = 32 - (irq + 1) * bitfield_width; 176 int shift = 32 - (irq + 1) * bitfield_width;
176 177
177 dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value); 178 dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
@@ -361,8 +362,15 @@ static const struct irq_domain_ops intc_irqpin_irq_domain_ops = {
361 .xlate = irq_domain_xlate_twocell, 362 .xlate = irq_domain_xlate_twocell,
362}; 363};
363 364
364static const struct intc_irqpin_irlm_config intc_irqpin_irlm_r8a777x = { 365static const struct intc_irqpin_config intc_irqpin_irlm_r8a777x = {
365 .irlm_bit = 23, /* ICR0.IRLM0 */ 366 .irlm_bit = 23, /* ICR0.IRLM0 */
367 .needs_irlm = 1,
368 .needs_clk = 0,
369};
370
371static const struct intc_irqpin_config intc_irqpin_rmobile = {
372 .needs_irlm = 0,
373 .needs_clk = 1,
366}; 374};
367 375
368static const struct of_device_id intc_irqpin_dt_ids[] = { 376static const struct of_device_id intc_irqpin_dt_ids[] = {
@@ -371,14 +379,18 @@ static const struct of_device_id intc_irqpin_dt_ids[] = {
371 .data = &intc_irqpin_irlm_r8a777x }, 379 .data = &intc_irqpin_irlm_r8a777x },
372 { .compatible = "renesas,intc-irqpin-r8a7779", 380 { .compatible = "renesas,intc-irqpin-r8a7779",
373 .data = &intc_irqpin_irlm_r8a777x }, 381 .data = &intc_irqpin_irlm_r8a777x },
382 { .compatible = "renesas,intc-irqpin-r8a7740",
383 .data = &intc_irqpin_rmobile },
384 { .compatible = "renesas,intc-irqpin-sh73a0",
385 .data = &intc_irqpin_rmobile },
374 {}, 386 {},
375}; 387};
376MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids); 388MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
377 389
378static int intc_irqpin_probe(struct platform_device *pdev) 390static int intc_irqpin_probe(struct platform_device *pdev)
379{ 391{
392 const struct intc_irqpin_config *config = NULL;
380 struct device *dev = &pdev->dev; 393 struct device *dev = &pdev->dev;
381 struct renesas_intc_irqpin_config *pdata = dev->platform_data;
382 const struct of_device_id *of_id; 394 const struct of_device_id *of_id;
383 struct intc_irqpin_priv *p; 395 struct intc_irqpin_priv *p;
384 struct intc_irqpin_iomem *i; 396 struct intc_irqpin_iomem *i;
@@ -388,6 +400,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
388 void (*enable_fn)(struct irq_data *d); 400 void (*enable_fn)(struct irq_data *d);
389 void (*disable_fn)(struct irq_data *d); 401 void (*disable_fn)(struct irq_data *d);
390 const char *name = dev_name(dev); 402 const char *name = dev_name(dev);
403 bool control_parent;
404 unsigned int nirqs;
391 int ref_irq; 405 int ref_irq;
392 int ret; 406 int ret;
393 int k; 407 int k;
@@ -399,23 +413,28 @@ static int intc_irqpin_probe(struct platform_device *pdev)
399 } 413 }
400 414
401 /* deal with driver instance configuration */ 415 /* deal with driver instance configuration */
402 if (pdata) { 416 of_property_read_u32(dev->of_node, "sense-bitfield-width",
403 memcpy(&p->config, pdata, sizeof(*pdata)); 417 &p->sense_bitfield_width);
404 } else { 418 control_parent = of_property_read_bool(dev->of_node, "control-parent");
405 of_property_read_u32(dev->of_node, "sense-bitfield-width", 419 if (!p->sense_bitfield_width)
406 &p->config.sense_bitfield_width); 420 p->sense_bitfield_width = 4; /* default to 4 bits */
407 p->config.control_parent = of_property_read_bool(dev->of_node,
408 "control-parent");
409 }
410 if (!p->config.sense_bitfield_width)
411 p->config.sense_bitfield_width = 4; /* default to 4 bits */
412 421
413 p->pdev = pdev; 422 p->pdev = pdev;
414 platform_set_drvdata(pdev, p); 423 platform_set_drvdata(pdev, p);
415 424
425 of_id = of_match_device(intc_irqpin_dt_ids, dev);
426 if (of_id && of_id->data) {
427 config = of_id->data;
428 p->needs_clk = config->needs_clk;
429 }
430
416 p->clk = devm_clk_get(dev, NULL); 431 p->clk = devm_clk_get(dev, NULL);
417 if (IS_ERR(p->clk)) { 432 if (IS_ERR(p->clk)) {
418 dev_warn(dev, "unable to get clock\n"); 433 if (p->needs_clk) {
434 dev_err(dev, "unable to get clock\n");
435 ret = PTR_ERR(p->clk);
436 goto err0;
437 }
419 p->clk = NULL; 438 p->clk = NULL;
420 } 439 }
421 440
@@ -443,8 +462,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
443 p->irq[k].requested_irq = irq->start; 462 p->irq[k].requested_irq = irq->start;
444 } 463 }
445 464
446 p->number_of_irqs = k; 465 nirqs = k;
447 if (p->number_of_irqs < 1) { 466 if (nirqs < 1) {
448 dev_err(dev, "not enough IRQ resources\n"); 467 dev_err(dev, "not enough IRQ resources\n");
449 ret = -EINVAL; 468 ret = -EINVAL;
450 goto err0; 469 goto err0;
@@ -485,20 +504,16 @@ static int intc_irqpin_probe(struct platform_device *pdev)
485 } 504 }
486 505
487 /* configure "individual IRQ mode" where needed */ 506 /* configure "individual IRQ mode" where needed */
488 of_id = of_match_device(intc_irqpin_dt_ids, dev); 507 if (config && config->needs_irlm) {
489 if (of_id && of_id->data) {
490 const struct intc_irqpin_irlm_config *irlm_config = of_id->data;
491
492 if (io[INTC_IRQPIN_REG_IRLM]) 508 if (io[INTC_IRQPIN_REG_IRLM])
493 intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_IRLM, 509 intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_IRLM,
494 irlm_config->irlm_bit, 510 config->irlm_bit, 1, 1);
495 1, 1);
496 else 511 else
497 dev_warn(dev, "unable to select IRLM mode\n"); 512 dev_warn(dev, "unable to select IRLM mode\n");
498 } 513 }
499 514
500 /* mask all interrupts using priority */ 515 /* mask all interrupts using priority */
501 for (k = 0; k < p->number_of_irqs; k++) 516 for (k = 0; k < nirqs; k++)
502 intc_irqpin_mask_unmask_prio(p, k, 1); 517 intc_irqpin_mask_unmask_prio(p, k, 1);
503 518
504 /* clear all pending interrupts */ 519 /* clear all pending interrupts */
@@ -506,16 +521,16 @@ static int intc_irqpin_probe(struct platform_device *pdev)
506 521
507 /* scan for shared interrupt lines */ 522 /* scan for shared interrupt lines */
508 ref_irq = p->irq[0].requested_irq; 523 ref_irq = p->irq[0].requested_irq;
509 p->shared_irqs = true; 524 p->shared_irqs = 1;
510 for (k = 1; k < p->number_of_irqs; k++) { 525 for (k = 1; k < nirqs; k++) {
511 if (ref_irq != p->irq[k].requested_irq) { 526 if (ref_irq != p->irq[k].requested_irq) {
512 p->shared_irqs = false; 527 p->shared_irqs = 0;
513 break; 528 break;
514 } 529 }
515 } 530 }
516 531
517 /* use more severe masking method if requested */ 532 /* use more severe masking method if requested */
518 if (p->config.control_parent) { 533 if (control_parent) {
519 enable_fn = intc_irqpin_irq_enable_force; 534 enable_fn = intc_irqpin_irq_enable_force;
520 disable_fn = intc_irqpin_irq_disable_force; 535 disable_fn = intc_irqpin_irq_disable_force;
521 } else if (!p->shared_irqs) { 536 } else if (!p->shared_irqs) {
@@ -534,9 +549,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
534 irq_chip->irq_set_wake = intc_irqpin_irq_set_wake; 549 irq_chip->irq_set_wake = intc_irqpin_irq_set_wake;
535 irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND; 550 irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND;
536 551
537 p->irq_domain = irq_domain_add_simple(dev->of_node, 552 p->irq_domain = irq_domain_add_simple(dev->of_node, nirqs, 0,
538 p->number_of_irqs,
539 p->config.irq_base,
540 &intc_irqpin_irq_domain_ops, p); 553 &intc_irqpin_irq_domain_ops, p);
541 if (!p->irq_domain) { 554 if (!p->irq_domain) {
542 ret = -ENXIO; 555 ret = -ENXIO;
@@ -555,7 +568,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
555 } 568 }
556 } else { 569 } else {
557 /* request interrupts one by one */ 570 /* request interrupts one by one */
558 for (k = 0; k < p->number_of_irqs; k++) { 571 for (k = 0; k < nirqs; k++) {
559 if (devm_request_irq(dev, p->irq[k].requested_irq, 572 if (devm_request_irq(dev, p->irq[k].requested_irq,
560 intc_irqpin_irq_handler, 0, name, 573 intc_irqpin_irq_handler, 0, name,
561 &p->irq[k])) { 574 &p->irq[k])) {
@@ -567,17 +580,10 @@ static int intc_irqpin_probe(struct platform_device *pdev)
567 } 580 }
568 581
569 /* unmask all interrupts on prio level */ 582 /* unmask all interrupts on prio level */
570 for (k = 0; k < p->number_of_irqs; k++) 583 for (k = 0; k < nirqs; k++)
571 intc_irqpin_mask_unmask_prio(p, k, 0); 584 intc_irqpin_mask_unmask_prio(p, k, 0);
572 585
573 dev_info(dev, "driving %d irqs\n", p->number_of_irqs); 586 dev_info(dev, "driving %d irqs\n", nirqs);
574
575 /* warn in case of mismatch if irq base is specified */
576 if (p->config.irq_base) {
577 if (p->config.irq_base != p->irq[0].domain_irq)
578 dev_warn(dev, "irq base mismatch (%d/%d)\n",
579 p->config.irq_base, p->irq[0].domain_irq);
580 }
581 587
582 return 0; 588 return 0;
583 589
diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
index 4ef178078e5b..0820f67cc9a7 100644
--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -50,6 +50,12 @@ static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = {
50 .enable = 0x34, 50 .enable = 0x34,
51}; 51};
52 52
53static struct sunxi_sc_nmi_reg_offs sun9i_reg_offs = {
54 .ctrl = 0x00,
55 .pend = 0x08,
56 .enable = 0x04,
57};
58
53static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off, 59static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
54 u32 val) 60 u32 val)
55{ 61{
@@ -207,3 +213,10 @@ static int __init sun7i_sc_nmi_irq_init(struct device_node *node,
207 return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs); 213 return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs);
208} 214}
209IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init); 215IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init);
216
217static int __init sun9i_nmi_irq_init(struct device_node *node,
218 struct device_node *parent)
219{
220 return sunxi_sc_nmi_irq_init(node, &sun9i_reg_offs);
221}
222IRQCHIP_DECLARE(sun9i_nmi, "allwinner,sun9i-a80-nmi", sun9i_nmi_irq_init);
diff --git a/drivers/irqchip/irq-ts4800.c b/drivers/irqchip/irq-ts4800.c
new file mode 100644
index 000000000000..4192bdcd2734
--- /dev/null
+++ b/drivers/irqchip/irq-ts4800.c
@@ -0,0 +1,163 @@
1/*
2 * Multiplexed-IRQs driver for TS-4800's FPGA
3 *
4 * Copyright (c) 2015 - Savoir-faire Linux
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#include <linux/interrupt.h>
12#include <linux/io.h>
13#include <linux/irq.h>
14#include <linux/irqchip.h>
15#include <linux/irqchip/chained_irq.h>
16#include <linux/irqdomain.h>
17#include <linux/module.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20#include <linux/of_irq.h>
21#include <linux/platform_device.h>
22
23#define IRQ_MASK 0x4
24#define IRQ_STATUS 0x8
25
26struct ts4800_irq_data {
27 void __iomem *base;
28 struct irq_domain *domain;
29 struct irq_chip irq_chip;
30};
31
32static void ts4800_irq_mask(struct irq_data *d)
33{
34 struct ts4800_irq_data *data = irq_data_get_irq_chip_data(d);
35 u16 reg = readw(data->base + IRQ_MASK);
36 u16 mask = 1 << d->hwirq;
37
38 writew(reg | mask, data->base + IRQ_MASK);
39}
40
41static void ts4800_irq_unmask(struct irq_data *d)
42{
43 struct ts4800_irq_data *data = irq_data_get_irq_chip_data(d);
44 u16 reg = readw(data->base + IRQ_MASK);
45 u16 mask = 1 << d->hwirq;
46
47 writew(reg & ~mask, data->base + IRQ_MASK);
48}
49
50static int ts4800_irqdomain_map(struct irq_domain *d, unsigned int irq,
51 irq_hw_number_t hwirq)
52{
53 struct ts4800_irq_data *data = d->host_data;
54
55 irq_set_chip_and_handler(irq, &data->irq_chip, handle_simple_irq);
56 irq_set_chip_data(irq, data);
57 irq_set_noprobe(irq);
58
59 return 0;
60}
61
62struct irq_domain_ops ts4800_ic_ops = {
63 .map = ts4800_irqdomain_map,
64 .xlate = irq_domain_xlate_onecell,
65};
66
67static void ts4800_ic_chained_handle_irq(struct irq_desc *desc)
68{
69 struct ts4800_irq_data *data = irq_desc_get_handler_data(desc);
70 struct irq_chip *chip = irq_desc_get_chip(desc);
71 u16 status = readw(data->base + IRQ_STATUS);
72
73 chained_irq_enter(chip, desc);
74
75 if (unlikely(status == 0)) {
76 handle_bad_irq(desc);
77 goto out;
78 }
79
80 do {
81 unsigned int bit = __ffs(status);
82 int irq = irq_find_mapping(data->domain, bit);
83
84 status &= ~(1 << bit);
85 generic_handle_irq(irq);
86 } while (status);
87
88out:
89 chained_irq_exit(chip, desc);
90}
91
92static int ts4800_ic_probe(struct platform_device *pdev)
93{
94 struct device_node *node = pdev->dev.of_node;
95 struct ts4800_irq_data *data;
96 struct irq_chip *irq_chip;
97 struct resource *res;
98 int parent_irq;
99
100 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
101 if (!data)
102 return -ENOMEM;
103
104 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
105 data->base = devm_ioremap_resource(&pdev->dev, res);
106 if (IS_ERR(data->base))
107 return PTR_ERR(data->base);
108
109 writew(0xFFFF, data->base + IRQ_MASK);
110
111 parent_irq = irq_of_parse_and_map(node, 0);
112 if (!parent_irq) {
113 dev_err(&pdev->dev, "failed to get parent IRQ\n");
114 return -EINVAL;
115 }
116
117 irq_chip = &data->irq_chip;
118 irq_chip->name = dev_name(&pdev->dev);
119 irq_chip->irq_mask = ts4800_irq_mask;
120 irq_chip->irq_unmask = ts4800_irq_unmask;
121
122 data->domain = irq_domain_add_linear(node, 8, &ts4800_ic_ops, data);
123 if (!data->domain) {
124 dev_err(&pdev->dev, "cannot add IRQ domain\n");
125 return -ENOMEM;
126 }
127
128 irq_set_chained_handler_and_data(parent_irq,
129 ts4800_ic_chained_handle_irq, data);
130
131 platform_set_drvdata(pdev, data);
132
133 return 0;
134}
135
136static int ts4800_ic_remove(struct platform_device *pdev)
137{
138 struct ts4800_irq_data *data = platform_get_drvdata(pdev);
139
140 irq_domain_remove(data->domain);
141
142 return 0;
143}
144
145static const struct of_device_id ts4800_ic_of_match[] = {
146 { .compatible = "technologic,ts4800-irqc", },
147 {},
148};
149MODULE_DEVICE_TABLE(of, ts4800_ic_of_match);
150
151static struct platform_driver ts4800_ic_driver = {
152 .probe = ts4800_ic_probe,
153 .remove = ts4800_ic_remove,
154 .driver = {
155 .name = "ts4800-irqc",
156 .of_match_table = ts4800_ic_of_match,
157 },
158};
159module_platform_driver(ts4800_ic_driver);
160
161MODULE_AUTHOR("Damien Riegel <damien.riegel@savoirfairelinux.com>");
162MODULE_LICENSE("GPL v2");
163MODULE_ALIAS("platform:ts4800_irqc");
diff --git a/drivers/irqchip/irq-zevio.c b/drivers/irqchip/irq-zevio.c
index 4c48fa88a03d..cb9d8ec37507 100644
--- a/drivers/irqchip/irq-zevio.c
+++ b/drivers/irqchip/irq-zevio.c
@@ -43,8 +43,7 @@ static void __iomem *zevio_irq_io;
43static void zevio_irq_ack(struct irq_data *irqd) 43static void zevio_irq_ack(struct irq_data *irqd)
44{ 44{
45 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(irqd); 45 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(irqd);
46 struct irq_chip_regs *regs = 46 struct irq_chip_regs *regs = &irq_data_get_chip_type(irqd)->regs;
47 &container_of(irqd->chip, struct irq_chip_type, chip)->regs;
48 47
49 readl(gc->reg_base + regs->ack); 48 readl(gc->reg_base + regs->ack);
50} 49}