| From 014d3e2a7927a4c67f1a9f1c3112f2d597208b9b Mon Sep 17 00:00:00 2001 |
| From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Date: Fri, 29 Nov 2013 14:48:00 +0100 |
| Subject: gpio: rcar: Support both edge trigger with DT |
| |
| Some versions of the R-Car GPIO controller support triggering on both |
| edges of the input signal. Whether this capability is supported is |
| currently specified in platform data. R-Car GPIO devices instantiated |
| from the device tree have the capability turned off even when the |
| hardware supports it. |
| |
| To fix this, add DT match data support to the driver, initialize both |
| edge trigger support from match data and enable both edge trigger in |
| r8a7790 and r8a7791 match data. |
| |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Acked-by: Magnus Damm <damm@opensource.se> |
| Signed-off-by: Linus Walleij <linus.walleij@linaro.org> |
| (cherry picked from commit 850dfe17e3c467f50a0b9a527a65831873740c23) |
| (Queued by Linus Walleij for v3.14 but not yet in Linus's tree) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/gpio/gpio-rcar.c | 56 +++++++++++++++++++++++++++++++++++++----------- |
| 1 file changed, 43 insertions(+), 13 deletions(-) |
| |
| diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c |
| index b0238442f737..6bb29c40a763 100644 |
| --- a/drivers/gpio/gpio-rcar.c |
| +++ b/drivers/gpio/gpio-rcar.c |
| @@ -284,7 +284,34 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = { |
| .map = gpio_rcar_irq_domain_map, |
| }; |
| |
| -static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) |
| +struct gpio_rcar_info { |
| + bool has_both_edge_trigger; |
| +}; |
| + |
| +static const struct of_device_id gpio_rcar_of_table[] = { |
| + { |
| + .compatible = "renesas,gpio-r8a7790", |
| + .data = (void *)&(const struct gpio_rcar_info) { |
| + .has_both_edge_trigger = true, |
| + }, |
| + }, { |
| + .compatible = "renesas,gpio-r8a7791", |
| + .data = (void *)&(const struct gpio_rcar_info) { |
| + .has_both_edge_trigger = true, |
| + }, |
| + }, { |
| + .compatible = "renesas,gpio-rcar", |
| + .data = (void *)&(const struct gpio_rcar_info) { |
| + .has_both_edge_trigger = false, |
| + }, |
| + }, { |
| + /* Terminator */ |
| + }, |
| +}; |
| + |
| +MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); |
| + |
| +static int gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) |
| { |
| struct gpio_rcar_config *pdata = p->pdev->dev.platform_data; |
| struct device_node *np = p->pdev->dev.of_node; |
| @@ -294,11 +321,21 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) |
| if (pdata) { |
| p->config = *pdata; |
| } else if (IS_ENABLED(CONFIG_OF) && np) { |
| + const struct of_device_id *match; |
| + const struct gpio_rcar_info *info; |
| + |
| + match = of_match_node(gpio_rcar_of_table, np); |
| + if (!match) |
| + return -EINVAL; |
| + |
| + info = match->data; |
| + |
| ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, |
| &args); |
| p->config.number_of_pins = ret == 0 ? args.args[2] |
| : RCAR_MAX_GPIO_PER_BANK; |
| p->config.gpio_base = -1; |
| + p->config.has_both_edge_trigger = info->has_both_edge_trigger; |
| } |
| |
| if (p->config.number_of_pins == 0 || |
| @@ -308,6 +345,8 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) |
| p->config.number_of_pins, RCAR_MAX_GPIO_PER_BANK); |
| p->config.number_of_pins = RCAR_MAX_GPIO_PER_BANK; |
| } |
| + |
| + return 0; |
| } |
| |
| static int gpio_rcar_probe(struct platform_device *pdev) |
| @@ -330,7 +369,9 @@ static int gpio_rcar_probe(struct platform_device *pdev) |
| spin_lock_init(&p->lock); |
| |
| /* Get device configuration from DT node or platform data. */ |
| - gpio_rcar_parse_pdata(p); |
| + ret = gpio_rcar_parse_pdata(p); |
| + if (ret < 0) |
| + return ret; |
| |
| platform_set_drvdata(pdev, p); |
| |
| @@ -435,17 +476,6 @@ static int gpio_rcar_remove(struct platform_device *pdev) |
| return 0; |
| } |
| |
| -#ifdef CONFIG_OF |
| -static const struct of_device_id gpio_rcar_of_table[] = { |
| - { |
| - .compatible = "renesas,gpio-rcar", |
| - }, |
| - { }, |
| -}; |
| - |
| -MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); |
| -#endif |
| - |
| static struct platform_driver gpio_rcar_device_driver = { |
| .probe = gpio_rcar_probe, |
| .remove = gpio_rcar_remove, |
| -- |
| 1.8.5.rc3 |
| |