aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Cooper <jason@lakedaemon.net>2014-09-14 03:53:17 -0400
committerJason Cooper <jason@lakedaemon.net>2014-09-14 03:53:17 -0400
commit1fc9d96ec63e7e071f22b89c268145d50720d667 (patch)
treefb673039eabc9612e6f6209e88a762dcbf8ca919
parent705bc96c2c15313c0677607f6e81800f4d2b4534 (diff)
parent8703ec19c706eb4d9f2848d50e9fc41d73eb4a40 (diff)
Merge branch 'irqchip/keystone' into irqchip/core
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt36
-rw-r--r--drivers/irqchip/Kconfig7
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-keystone.c232
4 files changed, 276 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt
new file mode 100644
index 000000000000..d9bb106bdd16
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt
@@ -0,0 +1,36 @@
1Keystone 2 IRQ controller IP
2
3On Keystone SOCs, DSP cores can send interrupts to ARM
4host using the IRQ controller IP. It provides 28 IRQ signals to ARM.
5The IRQ handler running on HOST OS can identify DSP signal source by
6analyzing SRCCx bits in IPCARx registers. This is one of the component
7used by the IPC mechanism used on Keystone SOCs.
8
9Required Properties:
10- compatible: should be "ti,keystone-irq"
11- ti,syscon-dev : phandle and offset pair. The phandle to syscon used to
12 access device control registers and the offset inside
13 device control registers range.
14- interrupt-controller : Identifies the node as an interrupt controller
15- #interrupt-cells : Specifies the number of cells needed to encode interrupt
16 source should be 1.
17- interrupts: interrupt reference to primary interrupt controller
18
19Please refer to interrupts.txt in this directory for details of the common
20Interrupt Controllers bindings used by client devices.
21
22Example:
23 kirq0: keystone_irq0@026202a0 {
24 compatible = "ti,keystone-irq";
25 ti,syscon-dev = <&devctrl 0x2a0>;
26 interrupts = <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>;
27 interrupt-controller;
28 #interrupt-cells = <1>;
29 };
30
31 dsp0: dsp0 {
32 compatible = "linux,rproc-user";
33 ...
34 interrupt-parent = <&kirq0>;
35 interrupts = <10 2>;
36 };
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index b8632bf9a7f3..c88896478e70 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -113,3 +113,10 @@ config IRQ_CROSSBAR
113 The primary irqchip invokes the crossbar's callback which inturn allocates 113 The primary irqchip invokes the crossbar's callback which inturn allocates
114 a free irq and configures the IP. Thus the peripheral interrupts are 114 a free irq and configures the IP. Thus the peripheral interrupts are
115 routed to one of the free irqchip interrupt lines. 115 routed to one of the free irqchip interrupt lines.
116
117config KEYSTONE_IRQ
118 tristate "Keystone 2 IRQ controller IP"
119 depends on ARCH_KEYSTONE
120 help
121 Support for Texas Instruments Keystone 2 IRQ controller IP which
122 is part of the Keystone 2 IPC mechanism
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 73052ba9ca62..69fc7fc8d1bb 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o
34obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o 34obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o
35obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o 35obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
36obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o 36obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o
37obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o
diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c
new file mode 100644
index 000000000000..608abf9c9283
--- /dev/null
+++ b/drivers/irqchip/irq-keystone.c
@@ -0,0 +1,232 @@
1/*
2 * Texas Instruments Keystone IRQ controller IP driver
3 *
4 * Copyright (C) 2014 Texas Instruments, Inc.
5 * Author: Sajesh Kumar Saran <sajesh@ti.com>
6 * Grygorii Strashko <grygorii.strashko@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation version 2.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/irq.h>
19#include <linux/bitops.h>
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/irqdomain.h>
23#include <linux/irqchip/chained_irq.h>
24#include <linux/of.h>
25#include <linux/of_platform.h>
26#include <linux/mfd/syscon.h>
27#include <linux/regmap.h>
28#include "irqchip.h"
29
30
31/* The source ID bits start from 4 to 31 (total 28 bits)*/
32#define BIT_OFS 4
33#define KEYSTONE_N_IRQ (32 - BIT_OFS)
34
35struct keystone_irq_device {
36 struct device *dev;
37 struct irq_chip chip;
38 u32 mask;
39 int irq;
40 struct irq_domain *irqd;
41 struct regmap *devctrl_regs;
42 u32 devctrl_offset;
43};
44
45static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq)
46{
47 int ret;
48 u32 val = 0;
49
50 ret = regmap_read(kirq->devctrl_regs, kirq->devctrl_offset, &val);
51 if (ret < 0)
52 dev_dbg(kirq->dev, "irq read failed ret(%d)\n", ret);
53 return val;
54}
55
56static inline void
57keystone_irq_writel(struct keystone_irq_device *kirq, u32 value)
58{
59 int ret;
60
61 ret = regmap_write(kirq->devctrl_regs, kirq->devctrl_offset, value);
62 if (ret < 0)
63 dev_dbg(kirq->dev, "irq write failed ret(%d)\n", ret);
64}
65
66static void keystone_irq_setmask(struct irq_data *d)
67{
68 struct keystone_irq_device *kirq = irq_data_get_irq_chip_data(d);
69
70 kirq->mask |= BIT(d->hwirq);
71 dev_dbg(kirq->dev, "mask %lu [%x]\n", d->hwirq, kirq->mask);
72}
73
74static void keystone_irq_unmask(struct irq_data *d)
75{
76 struct keystone_irq_device *kirq = irq_data_get_irq_chip_data(d);
77
78 kirq->mask &= ~BIT(d->hwirq);
79 dev_dbg(kirq->dev, "unmask %lu [%x]\n", d->hwirq, kirq->mask);
80}
81
82static void keystone_irq_ack(struct irq_data *d)
83{
84 /* nothing to do here */
85}
86
87static void keystone_irq_handler(unsigned irq, struct irq_desc *desc)
88{
89 struct keystone_irq_device *kirq = irq_desc_get_handler_data(desc);
90 unsigned long pending;
91 int src, virq;
92
93 dev_dbg(kirq->dev, "start irq %d\n", irq);
94
95 chained_irq_enter(irq_desc_get_chip(desc), desc);
96
97 pending = keystone_irq_readl(kirq);
98 keystone_irq_writel(kirq, pending);
99
100 dev_dbg(kirq->dev, "pending 0x%lx, mask 0x%x\n", pending, kirq->mask);
101
102 pending = (pending >> BIT_OFS) & ~kirq->mask;
103
104 dev_dbg(kirq->dev, "pending after mask 0x%lx\n", pending);
105
106 for (src = 0; src < KEYSTONE_N_IRQ; src++) {
107 if (BIT(src) & pending) {
108 virq = irq_find_mapping(kirq->irqd, src);
109 dev_dbg(kirq->dev, "dispatch bit %d, virq %d\n",
110 src, virq);
111 if (!virq)
112 dev_warn(kirq->dev, "sporious irq detected hwirq %d, virq %d\n",
113 src, virq);
114 generic_handle_irq(virq);
115 }
116 }
117
118 chained_irq_exit(irq_desc_get_chip(desc), desc);
119
120 dev_dbg(kirq->dev, "end irq %d\n", irq);
121}