aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-rcar.c
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2015-03-18 14:41:09 -0400
committerLinus Walleij <linus.walleij@linaro.org>2015-03-26 05:25:32 -0400
commitab82fa7da4dce5c728730d7aa0e11a2cbc9266da (patch)
tree9dbd5bda183455a012a4dba19a507cc5c3c14767 /drivers/gpio/gpio-rcar.c
parent3dc1e6852115b3163e7dacc76bbcb78ccff29421 (diff)
gpio: rcar: Prevent module clock disable when wake-up is enabled
When the GPIO module is needed for wake-up, it's module clock must not be disabled. Hence implement irq_chip.irq_set_wake(), which increments/decrements the clock's enable_count when needed, and forwards the wake-up state to the upstream interrupt controller. This fixes wake-up from s2ram using gpio-keys when using a PM Domain to manage the module clock. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-rcar.c')
-rw-r--r--drivers/gpio/gpio-rcar.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index d96166ca1b42..fd3977465948 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -14,6 +14,7 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 */ 15 */
16 16
17#include <linux/clk.h>
17#include <linux/err.h> 18#include <linux/err.h>
18#include <linux/gpio.h> 19#include <linux/gpio.h>
19#include <linux/init.h> 20#include <linux/init.h>
@@ -37,6 +38,8 @@ struct gpio_rcar_priv {
37 struct platform_device *pdev; 38 struct platform_device *pdev;
38 struct gpio_chip gpio_chip; 39 struct gpio_chip gpio_chip;
39 struct irq_chip irq_chip; 40 struct irq_chip irq_chip;
41 unsigned int irq_parent;
42 struct clk *clk;
40}; 43};
41 44
42#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */ 45#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
@@ -169,6 +172,25 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
169 return 0; 172 return 0;
170} 173}
171 174
175static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on)
176{
177 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
178 struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
179 gpio_chip);
180
181 irq_set_irq_wake(p->irq_parent, on);
182
183 if (!p->clk)
184 return 0;
185
186 if (on)
187 clk_enable(p->clk);
188 else
189 clk_disable(p->clk);
190
191 return 0;
192}
193
172static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) 194static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
173{ 195{
174 struct gpio_rcar_priv *p = dev_id; 196 struct gpio_rcar_priv *p = dev_id;
@@ -367,6 +389,12 @@ static int gpio_rcar_probe(struct platform_device *pdev)
367 389
368 platform_set_drvdata(pdev, p); 390 platform_set_drvdata(pdev, p);
369 391
392 p->clk = devm_clk_get(dev, NULL);
393 if (IS_ERR(p->clk)) {
394 dev_warn(dev, "unable to get clock\n");
395 p->clk = NULL;
396 }
397
370 pm_runtime_enable(dev); 398 pm_runtime_enable(dev);
371 pm_runtime_get_sync(dev); 399 pm_runtime_get_sync(dev);
372 400
@@ -404,8 +432,8 @@ static int gpio_rcar_probe(struct platform_device *pdev)
404 irq_chip->irq_mask = gpio_rcar_irq_disable; 432 irq_chip->irq_mask = gpio_rcar_irq_disable;
405 irq_chip->irq_unmask = gpio_rcar_irq_enable; 433 irq_chip->irq_unmask = gpio_rcar_irq_enable;
406 irq_chip->irq_set_type = gpio_rcar_irq_set_type; 434 irq_chip->irq_set_type = gpio_rcar_irq_set_type;
407 irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED 435 irq_chip->irq_set_wake = gpio_rcar_irq_set_wake;
408 | IRQCHIP_MASK_ON_SUSPEND; 436 irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
409 437
410 ret = gpiochip_add(gpio_chip); 438 ret = gpiochip_add(gpio_chip);
411 if (ret) { 439 if (ret) {
@@ -420,6 +448,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
420 goto err1; 448 goto err1;
421 } 449 }
422 450
451 p->irq_parent = irq->start;
423 if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler, 452 if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler,
424 IRQF_SHARED, name, p)) { 453 IRQF_SHARED, name, p)) {
425 dev_err(dev, "failed to request IRQ\n"); 454 dev_err(dev, "failed to request IRQ\n");