aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorJason Cooper <jason@lakedaemon.net>2015-04-02 19:27:23 -0400
committerJason Cooper <jason@lakedaemon.net>2015-04-02 19:27:23 -0400
commit78223354a64284fe1ef74c5a7900435776fcf2a0 (patch)
tree857ca5c95f2908cea04fc8ecb35959921cec1a0d /drivers/irqchip
parent2a6c0f0ad5c0127d18b43674bd94785fae2ef5fe (diff)
parent6f46aedb9c85873b67f6186a8b0f9d7a769b6b2c (diff)
Merge branch 'irqchip/renesas' into irqchip/core
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-renesas-irqc.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index 2ea3412fdf8c..cdf80b7794cd 100644
--- a/drivers/irqchip/irq-renesas-irqc.c
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -17,6 +17,7 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20#include <linux/clk.h>
20#include <linux/init.h> 21#include <linux/init.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/spinlock.h> 23#include <linux/spinlock.h>
@@ -29,15 +30,26 @@
29#include <linux/slab.h> 30#include <linux/slab.h>
30#include <linux/module.h> 31#include <linux/module.h>
31#include <linux/platform_data/irq-renesas-irqc.h> 32#include <linux/platform_data/irq-renesas-irqc.h>
33#include <linux/pm_runtime.h>
32 34
33#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */ 35#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */
34 36
35#define IRQC_REQ_STS 0x00 37#define IRQC_REQ_STS 0x00 /* Interrupt Request Status Register */
36#define IRQC_EN_STS 0x04 38#define IRQC_EN_STS 0x04 /* Interrupt Enable Status Register */
37#define IRQC_EN_SET 0x08 39#define IRQC_EN_SET 0x08 /* Interrupt Enable Set Register */
38#define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10)) 40#define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10))
39#define DETECT_STATUS 0x100 41 /* SYS-CPU vs. RT-CPU */
42#define DETECT_STATUS 0x100 /* IRQn Detect Status Register */
43#define MONITOR 0x104 /* IRQn Signal Level Monitor Register */
44#define HLVL_STS 0x108 /* IRQn High Level Detect Status Register */
45#define LLVL_STS 0x10c /* IRQn Low Level Detect Status Register */
46#define S_R_EDGE_STS 0x110 /* IRQn Sync Rising Edge Detect Status Reg. */
47#define S_F_EDGE_STS 0x114 /* IRQn Sync Falling Edge Detect Status Reg. */
48#define A_R_EDGE_STS 0x118 /* IRQn Async Rising Edge Detect Status Reg. */
49#define A_F_EDGE_STS 0x11c /* IRQn Async Falling Edge Detect Status Reg. */
50#define CHTEN_STS 0x120 /* Chattering Reduction Status Register */
40#define IRQC_CONFIG(n) (0x180 + ((n) * 0x04)) 51#define IRQC_CONFIG(n) (0x180 + ((n) * 0x04))
52 /* IRQn Configuration Register */
41 53
42struct irqc_irq { 54struct irqc_irq {
43 int hw_irq; 55 int hw_irq;
@@ -55,6 +67,7 @@ struct irqc_priv {
55 struct platform_device *pdev; 67 struct platform_device *pdev;
56 struct irq_chip irq_chip; 68 struct irq_chip irq_chip;
57 struct irq_domain *irq_domain; 69 struct irq_domain *irq_domain;
70 struct clk *clk;
58}; 71};
59 72
60static void irqc_dbg(struct irqc_irq *i, char *str) 73static void irqc_dbg(struct irqc_irq *i, char *str)
@@ -108,6 +121,21 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
108 return 0; 121 return 0;
109} 122}
110 123
124static int irqc_irq_set_wake(struct irq_data *d, unsigned int on)
125{
126 struct irqc_priv *p = irq_data_get_irq_chip_data(d);
127
128 if (!p->clk)
129 return 0;
130
131 if (on)
132 clk_enable(p->clk);
133 else
134 clk_disable(p->clk);
135
136 return 0;
137}
138
111static irqreturn_t irqc_irq_handler(int irq, void *dev_id) 139static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
112{ 140{
113 struct irqc_irq *i = dev_id; 141 struct irqc_irq *i = dev_id;
@@ -170,6 +198,15 @@ static int irqc_probe(struct platform_device *pdev)
170 p->pdev = pdev; 198 p->pdev = pdev;
171 platform_set_drvdata(pdev, p); 199 platform_set_drvdata(pdev, p);
172 200
201 p->clk = devm_clk_get(&pdev->dev, NULL);
202 if (IS_ERR(p->clk)) {
203 dev_warn(&pdev->dev, "unable to get clock\n");
204 p->clk = NULL;
205 }
206
207 pm_runtime_enable(&pdev->dev);
208 pm_runtime_get_sync(&pdev->dev);
209
173 /* get hold of manadatory IOMEM */ 210 /* get hold of manadatory IOMEM */
174 io = platform_get_resource(pdev, IORESOURCE_MEM, 0); 211 io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
175 if (!io) { 212 if (!io) {
@@ -210,7 +247,8 @@ static int irqc_probe(struct platform_device *pdev)
210 irq_chip->irq_mask = irqc_irq_disable; 247 irq_chip->irq_mask = irqc_irq_disable;
211 irq_chip->irq_unmask = irqc_irq_enable; 248 irq_chip->irq_unmask = irqc_irq_enable;
212 irq_chip->irq_set_type = irqc_irq_set_type; 249 irq_chip->irq_set_type = irqc_irq_set_type;
213 irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; 250 irq_chip->irq_set_wake = irqc_irq_set_wake;
251 irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND;
214 252
215 p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, 253 p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
216 p->number_of_irqs, 254 p->number_of_irqs,
@@ -250,6 +288,8 @@ err3:
250err2: 288err2:
251 iounmap(p->iomem); 289 iounmap(p->iomem);
252err1: 290err1:
291 pm_runtime_put(&pdev->dev);
292 pm_runtime_disable(&pdev->dev);
253 kfree(p); 293 kfree(p);
254err0: 294err0:
255 return ret; 295 return ret;
@@ -265,6 +305,8 @@ static int irqc_remove(struct platform_device *pdev)
265 305
266 irq_domain_remove(p->irq_domain); 306 irq_domain_remove(p->irq_domain);
267 iounmap(p->iomem); 307 iounmap(p->iomem);
308 pm_runtime_put(&pdev->dev);
309 pm_runtime_disable(&pdev->dev);
268 kfree(p); 310 kfree(p);
269 return 0; 311 return 0;
270} 312}