aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2015-04-01 08:00:06 -0400
committerJason Cooper <jason@lakedaemon.net>2015-04-02 19:14:52 -0400
commit6f46aedb9c85873b67f6186a8b0f9d7a769b6b2c (patch)
tree376bc96b0c0ceaaa6c12ef676105612dbf6a3e0b
parent5593ce64d875d169a237e3818a4251948c901ce7 (diff)
irqchip: renesas-irqc: Add wake-up support
The IRQC module clock is managed through Runtime PM and PM Domains. If wake-up is enabled, this clock must not be disabled during system suspend. Hence implement irq_chip.irq_set_wake(), which increments/decrements the clock's enable_count when needed. This fixes wake-up by gpio-keys on r8a73a4/ape6evm. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Simon Horman <horms+renesas@verge.net.au> Link: https://lkml.kernel.org/r/1427889606-18671-1-git-send-email-geert+renesas@glider.be Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--drivers/irqchip/irq-renesas-irqc.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index 2fe9612041b0..7be2fdf69924 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>
@@ -66,6 +67,7 @@ struct irqc_priv {
66 struct platform_device *pdev; 67 struct platform_device *pdev;
67 struct irq_chip irq_chip; 68 struct irq_chip irq_chip;
68 struct irq_domain *irq_domain; 69 struct irq_domain *irq_domain;
70 struct clk *clk;
69}; 71};
70 72
71static void irqc_dbg(struct irqc_irq *i, char *str) 73static void irqc_dbg(struct irqc_irq *i, char *str)
@@ -119,6 +121,21 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
119 return 0; 121 return 0;
120} 122}
121 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
122static irqreturn_t irqc_irq_handler(int irq, void *dev_id) 139static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
123{ 140{
124 struct irqc_irq *i = dev_id; 141 struct irqc_irq *i = dev_id;
@@ -181,6 +198,12 @@ static int irqc_probe(struct platform_device *pdev)
181 p->pdev = pdev; 198 p->pdev = pdev;
182 platform_set_drvdata(pdev, p); 199 platform_set_drvdata(pdev, p);
183 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
184 pm_runtime_enable(&pdev->dev); 207 pm_runtime_enable(&pdev->dev);
185 pm_runtime_get_sync(&pdev->dev); 208 pm_runtime_get_sync(&pdev->dev);
186 209
@@ -224,7 +247,8 @@ static int irqc_probe(struct platform_device *pdev)
224 irq_chip->irq_mask = irqc_irq_disable; 247 irq_chip->irq_mask = irqc_irq_disable;
225 irq_chip->irq_unmask = irqc_irq_enable; 248 irq_chip->irq_unmask = irqc_irq_enable;
226 irq_chip->irq_set_type = irqc_irq_set_type; 249 irq_chip->irq_set_type = irqc_irq_set_type;
227 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;
228 252
229 p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, 253 p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
230 p->number_of_irqs, 254 p->number_of_irqs,