]>
Commit | Line | Data |
---|---|---|
59e2be0a GKH |
1 | From b26a719bdba9aa926ceaadecc66e07623d2b8a53 Mon Sep 17 00:00:00 2001 |
2 | From: Geert Uytterhoeven <geert+renesas@glider.be> | |
3 | Date: Thu, 18 Feb 2016 17:06:30 +0100 | |
4 | Subject: gpio: rcar: Add Runtime PM handling for interrupts | |
5 | ||
6 | From: Geert Uytterhoeven <geert+renesas@glider.be> | |
7 | ||
8 | commit b26a719bdba9aa926ceaadecc66e07623d2b8a53 upstream. | |
9 | ||
10 | The R-Car GPIO driver handles Runtime PM for requested GPIOs only. | |
11 | ||
12 | When using a GPIO purely as an interrupt source, no Runtime PM handling | |
13 | is done, and the GPIO module's clock may not be enabled. | |
14 | ||
15 | To fix this: | |
16 | - Add .irq_request_resources() and .irq_release_resources() callbacks | |
17 | to handle Runtime PM when an interrupt is requested, | |
18 | - Add irq_bus_lock() and sync_unlock() callbacks to handle Runtime PM | |
19 | when e.g. disabling/enabling an interrupt, or configuring the | |
20 | interrupt type. | |
21 | ||
22 | Fixes: d5c3d84657db57bd "net: phy: Avoid polling PHY with PHY_IGNORE_INTERRUPTS" | |
23 | Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> | |
24 | Signed-off-by: Linus Walleij <linus.walleij@linaro.org> | |
25 | [fabrizio: cherry-pick to v4.4.y. Use container_of instead of | |
26 | gpiochip_get_data.] | |
27 | Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com> | |
28 | Reviewed-by: Biju Das <biju.das@bp.renesas.com> | |
29 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
30 | --- | |
31 | drivers/gpio/gpio-rcar.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ | |
32 | 1 file changed, 46 insertions(+) | |
33 | ||
34 | --- a/drivers/gpio/gpio-rcar.c | |
35 | +++ b/drivers/gpio/gpio-rcar.c | |
36 | @@ -200,6 +200,48 @@ static int gpio_rcar_irq_set_wake(struct | |
37 | return 0; | |
38 | } | |
39 | ||
40 | +static void gpio_rcar_irq_bus_lock(struct irq_data *d) | |
41 | +{ | |
42 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
43 | + struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, | |
44 | + gpio_chip); | |
45 | + | |
46 | + pm_runtime_get_sync(&p->pdev->dev); | |
47 | +} | |
48 | + | |
49 | +static void gpio_rcar_irq_bus_sync_unlock(struct irq_data *d) | |
50 | +{ | |
51 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
52 | + struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, | |
53 | + gpio_chip); | |
54 | + | |
55 | + pm_runtime_put(&p->pdev->dev); | |
56 | +} | |
57 | + | |
58 | + | |
59 | +static int gpio_rcar_irq_request_resources(struct irq_data *d) | |
60 | +{ | |
61 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
62 | + struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, | |
63 | + gpio_chip); | |
64 | + int error; | |
65 | + | |
66 | + error = pm_runtime_get_sync(&p->pdev->dev); | |
67 | + if (error < 0) | |
68 | + return error; | |
69 | + | |
70 | + return 0; | |
71 | +} | |
72 | + | |
73 | +static void gpio_rcar_irq_release_resources(struct irq_data *d) | |
74 | +{ | |
75 | + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
76 | + struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv, | |
77 | + gpio_chip); | |
78 | + | |
79 | + pm_runtime_put(&p->pdev->dev); | |
80 | +} | |
81 | + | |
82 | static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) | |
83 | { | |
84 | struct gpio_rcar_priv *p = dev_id; | |
85 | @@ -460,6 +502,10 @@ static int gpio_rcar_probe(struct platfo | |
86 | irq_chip->irq_unmask = gpio_rcar_irq_enable; | |
87 | irq_chip->irq_set_type = gpio_rcar_irq_set_type; | |
88 | irq_chip->irq_set_wake = gpio_rcar_irq_set_wake; | |
89 | + irq_chip->irq_bus_lock = gpio_rcar_irq_bus_lock; | |
90 | + irq_chip->irq_bus_sync_unlock = gpio_rcar_irq_bus_sync_unlock; | |
91 | + irq_chip->irq_request_resources = gpio_rcar_irq_request_resources; | |
92 | + irq_chip->irq_release_resources = gpio_rcar_irq_release_resources; | |
93 | irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; | |
94 | ||
95 | ret = gpiochip_add(gpio_chip); |