Commit d43be80a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+16 −22
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@
 * GNU General Public License for more details.
 */

#include <linux/clk.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
@@ -37,10 +36,9 @@ struct gpio_rcar_priv {
	struct platform_device *pdev;
	struct gpio_chip gpio_chip;
	struct irq_chip irq_chip;
	struct clk *clk;
	unsigned int irq_parent;
	atomic_t wakeup_path;
	bool has_both_edge_trigger;
	bool needs_clk;
};

#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)
		}
	}

	if (!p->clk)
		return 0;

	if (on)
		clk_enable(p->clk);
		atomic_inc(&p->wakeup_path);
	else
		clk_disable(p->clk);
		atomic_dec(&p->wakeup_path);

	return 0;
}
@@ -330,17 +325,14 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,

struct gpio_rcar_info {
	bool has_both_edge_trigger;
	bool needs_clk;
};

static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
	.has_both_edge_trigger = false,
	.needs_clk = false,
};

static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
	.has_both_edge_trigger = true,
	.needs_clk = true,
};

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)
	ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args);
	*npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK;
	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) {
		dev_warn(&p->pdev->dev,
@@ -440,16 +431,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)

	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);

	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -531,11 +512,24 @@ static int gpio_rcar_remove(struct platform_device *pdev)
	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 = {
	.probe		= gpio_rcar_probe,
	.remove		= gpio_rcar_remove,
	.driver		= {
		.name	= "gpio_rcar",
		.pm     = &gpio_rcar_pm_ops,
		.of_match_table = of_match_ptr(gpio_rcar_of_table),
	}
};