aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2014-09-12 09:15:18 -0400
committerJason Cooper <jason@lakedaemon.net>2014-09-14 02:47:40 -0400
commit705bc96c2c15313c0677607f6e81800f4d2b4534 (patch)
treee87fd69085507172290b8d0f41a7582c8cce9252
parent36845f1b54edc3237626d48270bbf3bc26d45f4f (diff)
irqchip: renesas-intc-irqpin: Add minimal runtime PM support
This is just enough to let pm_clk_*() enable the functional clock, and manage it for suspend/resume, if present. Before, it was assumed enabled by the bootloader or reset state. To prevent the clock from being disabled while the module is needed for wake-up, implement irq_chip.irq_set_wake(), which increments/decrements the clock's enable_count when needed. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lkml.kernel.org/r/1410527720-18061-3-git-send-email-geert+renesas@glider.be Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index a6b205b72c9b..542e850f4946 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.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/of.h> 22#include <linux/of.h>
22#include <linux/platform_device.h> 23#include <linux/platform_device.h>
@@ -30,6 +31,7 @@
30#include <linux/slab.h> 31#include <linux/slab.h>
31#include <linux/module.h> 32#include <linux/module.h>
32#include <linux/platform_data/irq-renesas-intc-irqpin.h> 33#include <linux/platform_data/irq-renesas-intc-irqpin.h>
34#include <linux/pm_runtime.h>
33 35
34#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */ 36#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */
35 37
@@ -75,6 +77,7 @@ struct intc_irqpin_priv {
75 struct platform_device *pdev; 77 struct platform_device *pdev;
76 struct irq_chip irq_chip; 78 struct irq_chip irq_chip;
77 struct irq_domain *irq_domain; 79 struct irq_domain *irq_domain;
80 struct clk *clk;
78 bool shared_irqs; 81 bool shared_irqs;
79 u8 shared_irq_mask; 82 u8 shared_irq_mask;
80}; 83};
@@ -270,6 +273,21 @@ static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type)
270 value ^ INTC_IRQ_SENSE_VALID); 273 value ^ INTC_IRQ_SENSE_VALID);
271} 274}
272 275
276static int intc_irqpin_irq_set_wake(struct irq_data *d, unsigned int on)
277{
278 struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
279
280 if (!p->clk)
281 return 0;
282
283 if (on)
284 clk_enable(p->clk);
285 else
286 clk_disable(p->clk);
287
288 return 0;
289}
290
273static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id) 291static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id)
274{ 292{
275 struct intc_irqpin_irq *i = dev_id; 293 struct intc_irqpin_irq *i = dev_id;
@@ -346,8 +364,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
346 p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); 364 p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
347 if (!p) { 365 if (!p) {
348 dev_err(dev, "failed to allocate driver data\n"); 366 dev_err(dev, "failed to allocate driver data\n");
349 ret = -ENOMEM; 367 return -ENOMEM;
350 goto err0;
351 } 368 }
352 369
353 /* deal with driver instance configuration */ 370 /* deal with driver instance configuration */
@@ -365,6 +382,15 @@ static int intc_irqpin_probe(struct platform_device *pdev)
365 p->pdev = pdev; 382 p->pdev = pdev;
366 platform_set_drvdata(pdev, p); 383 platform_set_drvdata(pdev, p);
367 384
385 p->clk = devm_clk_get(dev, NULL);
386 if (IS_ERR(p->clk)) {
387 dev_warn(dev, "unable to get clock\n");
388 p->clk = NULL;
389 }
390
391 pm_runtime_enable(dev);
392 pm_runtime_get_sync(dev);
393
368 /* get hold of manadatory IOMEM */ 394 /* get hold of manadatory IOMEM */
369 for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { 395 for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
370 io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k); 396 io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k);
@@ -456,7 +482,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
456 irq_chip->irq_mask = disable_fn; 482 irq_chip->irq_mask = disable_fn;
457 irq_chip->irq_unmask = enable_fn; 483 irq_chip->irq_unmask = enable_fn;
458 irq_chip->irq_set_type = intc_irqpin_irq_set_type; 484 irq_chip->irq_set_type = intc_irqpin_irq_set_type;
459 irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; 485 irq_chip->irq_set_wake = intc_irqpin_irq_set_wake;
486 irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND;
460 487
461 p->irq_domain = irq_domain_add_simple(dev->of_node, 488 p->irq_domain = irq_domain_add_simple(dev->of_node,
462 p->number_of_irqs, 489 p->number_of_irqs,
@@ -508,6 +535,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
508err1: 535err1:
509 irq_domain_remove(p->irq_domain); 536 irq_domain_remove(p->irq_domain);
510err0: 537err0:
538 pm_runtime_put(dev);
539 pm_runtime_disable(dev);
511 return ret; 540 return ret;
512} 541}
513 542
@@ -516,7 +545,8 @@ static int intc_irqpin_remove(struct platform_device *pdev)
516 struct intc_irqpin_priv *p = platform_get_drvdata(pdev); 545 struct intc_irqpin_priv *p = platform_get_drvdata(pdev);
517 546
518 irq_domain_remove(p->irq_domain); 547 irq_domain_remove(p->irq_domain);
519 548 pm_runtime_put(&pdev->dev);
549 pm_runtime_disable(&pdev->dev);
520 return 0; 550 return 0;
521} 551}
522 552