Commit d43be80a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v4.16-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO fix from Linus Walleij:
 "This is a single GPIO fix for the v4.16 series affecting the Renesas
  driver, and fixes wakeup from external stuff"

* tag 'gpio-v4.16-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: rcar: Use wakeup_path i.s.o. explicit clock handling
parents 3266b5bd 9ac79ba9
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -37,10 +36,9 @@ struct gpio_rcar_priv { ...@@ -37,10 +36,9 @@ struct gpio_rcar_priv {
struct platform_device *pdev; struct platform_device *pdev;
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;
struct irq_chip irq_chip; struct irq_chip irq_chip;
struct clk *clk;
unsigned int irq_parent; unsigned int irq_parent;
atomic_t wakeup_path;
bool has_both_edge_trigger; bool has_both_edge_trigger;
bool needs_clk;
}; };
#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */ #define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
...@@ -186,13 +184,10 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on) ...@@ -186,13 +184,10 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on)
} }
} }
if (!p->clk)
return 0;
if (on) if (on)
clk_enable(p->clk); atomic_inc(&p->wakeup_path);
else else
clk_disable(p->clk); atomic_dec(&p->wakeup_path);
return 0; return 0;
} }
...@@ -330,17 +325,14 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, ...@@ -330,17 +325,14 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
struct gpio_rcar_info { struct gpio_rcar_info {
bool has_both_edge_trigger; bool has_both_edge_trigger;
bool needs_clk;
}; };
static const struct gpio_rcar_info gpio_rcar_info_gen1 = { static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
.has_both_edge_trigger = false, .has_both_edge_trigger = false,
.needs_clk = false,
}; };
static const struct gpio_rcar_info gpio_rcar_info_gen2 = { static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
.has_both_edge_trigger = true, .has_both_edge_trigger = true,
.needs_clk = true,
}; };
static const struct of_device_id gpio_rcar_of_table[] = { static const struct of_device_id gpio_rcar_of_table[] = {
...@@ -403,7 +395,6 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins) ...@@ -403,7 +395,6 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins)
ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args);
*npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; *npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK;
p->has_both_edge_trigger = info->has_both_edge_trigger; p->has_both_edge_trigger = info->has_both_edge_trigger;
p->needs_clk = info->needs_clk;
if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) { if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) {
dev_warn(&p->pdev->dev, dev_warn(&p->pdev->dev,
...@@ -440,16 +431,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -440,16 +431,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, p); platform_set_drvdata(pdev, p);
p->clk = devm_clk_get(dev, NULL);
if (IS_ERR(p->clk)) {
if (p->needs_clk) {
dev_err(dev, "unable to get clock\n");
ret = PTR_ERR(p->clk);
goto err0;
}
p->clk = NULL;
}
pm_runtime_enable(dev); pm_runtime_enable(dev);
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
...@@ -531,11 +512,24 @@ static int gpio_rcar_remove(struct platform_device *pdev) ...@@ -531,11 +512,24 @@ static int gpio_rcar_remove(struct platform_device *pdev)
return 0; return 0;
} }
static int __maybe_unused gpio_rcar_suspend(struct device *dev)
{
struct gpio_rcar_priv *p = dev_get_drvdata(dev);
if (atomic_read(&p->wakeup_path))
device_set_wakeup_path(dev);
return 0;
}
static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, NULL);
static struct platform_driver gpio_rcar_device_driver = { static struct platform_driver gpio_rcar_device_driver = {
.probe = gpio_rcar_probe, .probe = gpio_rcar_probe,
.remove = gpio_rcar_remove, .remove = gpio_rcar_remove,
.driver = { .driver = {
.name = "gpio_rcar", .name = "gpio_rcar",
.pm = &gpio_rcar_pm_ops,
.of_match_table = of_match_ptr(gpio_rcar_of_table), .of_match_table = of_match_ptr(gpio_rcar_of_table),
} }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment