Signed-off-by: Ludovic Desroches <[email protected]>
---

Hi Linus,

I have reworked my patch (of course it will be split for submission) trying to
follow your advices.

I have replaced pinctrl_add_gpio_range() with of_gpiochip_add(). I'll do more
tests but it seems to work. Maybe I've missed something but I still need to fix
the case when there is a gpio controller not used.

A lot of things rely on the gpio controller id (taken from the alias):
index for gpio_chips array, pin muxing, naming, etc. I am not sure I can't get
rid of this constraint.

Regards

Ludovic

 arch/arm/boot/dts/sama5d4.dtsi | 19 ++++++++++++++++++-
 drivers/pinctrl/pinctrl-at91.c | 42 +++++++++++++++++++++++-------------------
 2 files changed, 41 insertions(+), 20 deletions(-)

diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi
index 1b0f30c..c1c01a3 100644
--- a/arch/arm/boot/dts/sama5d4.dtsi
+++ b/arch/arm/boot/dts/sama5d4.dtsi
@@ -62,6 +62,7 @@
                gpio0 = &pioA;
                gpio1 = &pioB;
                gpio2 = &pioC;
+               gpio3 = &pioD;
                gpio4 = &pioE;
                tcb0 = &tcb0;
                tcb1 = &tcb1;
@@ -1063,7 +1064,7 @@
                        };
 
 
-                       pinctrl@fc06a000 {
+                       pinctrl: pinctrl@fc06a000 {
                                #address-cells = <1>;
                                #size-cells = <1>;
                                compatible = "atmel,at91sam9x5-pinctrl", 
"atmel,at91rm9200-pinctrl", "simple-bus";
@@ -1084,6 +1085,7 @@
                                        interrupts = <23 IRQ_TYPE_LEVEL_HIGH 1>;
                                        #gpio-cells = <2>;
                                        gpio-controller;
+                                       gpio-ranges = <&pinctrl 0 0 32>;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                                        clocks = <&pioA_clk>;
@@ -1095,6 +1097,7 @@
                                        interrupts = <24 IRQ_TYPE_LEVEL_HIGH 1>;
                                        #gpio-cells = <2>;
                                        gpio-controller;
+                                       gpio-ranges = <&pinctrl 0 32 32>;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                                        clocks = <&pioB_clk>;
@@ -1106,17 +1109,31 @@
                                        interrupts = <25 IRQ_TYPE_LEVEL_HIGH 1>;
                                        #gpio-cells = <2>;
                                        gpio-controller;
+                                       gpio-ranges = <&pinctrl 0 64 32>;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                                        clocks = <&pioC_clk>;
                                };
 
+                               pioD: gpio@fc068000 {
+                                       compatible = "atmel,at91sam9x5-gpio", 
"atmel,at91rm9200-gpio";
+                                       reg = <0xfc068000 0x100>;
+                                       interrupts = <5 IRQ_TYPE_LEVEL_HIGH 1>;
+                                       #gpio-cells = <2>;
+                                       gpio-controller;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                                       clocks = <&pioD_clk>;
+                                       status = "disabled";
+                               };
+
                                pioE: gpio@fc06d000 {
                                        compatible = "atmel,at91sam9x5-gpio", 
"atmel,at91rm9200-gpio";
                                        reg = <0xfc06d000 0x100>;
                                        interrupts = <26 IRQ_TYPE_LEVEL_HIGH 1>;
                                        #gpio-cells = <2>;
                                        gpio-controller;
+                                       gpio-ranges = <&pinctrl 0 128 32>;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                                        clocks = <&pioE_clk>;
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index dfd021e..f5d4aea 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -13,6 +13,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -35,7 +36,6 @@ struct at91_pinctrl_mux_ops;
 
 struct at91_gpio_chip {
        struct gpio_chip        chip;
-       struct pinctrl_gpio_range range;
        struct at91_gpio_chip   *next;          /* Bank sharing same clock */
        int                     pioc_hwirq;     /* PIO bank interrupt 
identifier on AIC */
        int                     pioc_virq;      /* PIO bank Linux virtual 
interrupt */
@@ -178,6 +178,7 @@ struct at91_pinctrl {
        struct pinctrl_dev      *pctl;
 
        int                     nbanks;
+       int                     nactive_banks;
 
        uint32_t                *mux_mask;
        int                     nmux;
@@ -982,6 +983,8 @@ static void at91_pinctrl_child_count(struct at91_pinctrl 
*info,
        for_each_child_of_node(np, child) {
                if (of_device_is_compatible(child, gpio_compat)) {
                        info->nbanks++;
+                       if (of_device_is_available(child))
+                               info->nactive_banks;
                } else {
                        info->nfunctions++;
                        info->ngroups += of_get_child_count(child);
@@ -1145,8 +1148,12 @@ static int at91_pinctrl_probe_dt(struct platform_device 
*pdev,
        dev_dbg(&pdev->dev, "mux-mask\n");
        tmp = info->mux_mask;
        for (i = 0; i < info->nbanks; i++) {
+               if (!gpio_chips[i]) {
+                       tmp += info->nmux;
+                       continue;
+               }
                for (j = 0; j < info->nmux; j++, tmp++) {
-                       dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+                       dev_dbg(&pdev->dev, "pio%c:periphal %c\t0x%x\n", 'A' + 
i, 'A' + j, tmp[0]);
                }
        }
 
@@ -1185,7 +1192,7 @@ static int at91_pinctrl_probe(struct platform_device 
*pdev)
 {
        struct at91_pinctrl *info;
        struct pinctrl_pin_desc *pdesc;
-       int ret, i, j, k;
+       int ret, i, j, k, ngpio_chips_enabled = 0;
 
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (!info)
@@ -1201,11 +1208,15 @@ static int at91_pinctrl_probe(struct platform_device 
*pdev)
         * need this to proceed.
         */
        for (i = 0; i < info->nbanks; i++) {
-               if (!gpio_chips[i]) {
-                       dev_warn(&pdev->dev, "GPIO chip %d not registered 
yet\n", i);
-                       devm_kfree(&pdev->dev, info);
-                       return -EPROBE_DEFER;
-               }
+               if (gpio_chips[i])
+                       ngpio_chips_enabled++;
+       }
+       if (ngpio_chips_enabled < info->nactive_banks) {
+               dev_warn(&pdev->dev,
+                        "All GPIO chips are not registered yet (%d/%d)\n",
+                        ngpio_chips_enabled, info->nactive_banks);
+               devm_kfree(&pdev->dev, info);
+               return -EPROBE_DEFER;
        }
 
        at91_pinctrl_desc.name = dev_name(&pdev->dev);
@@ -1233,9 +1244,9 @@ static int at91_pinctrl_probe(struct platform_device 
*pdev)
                goto err;
        }
 
-       /* We will handle a range of GPIO pins */
        for (i = 0; i < info->nbanks; i++)
-               pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+               if (gpio_chips[i])
+                       of_gpiochip_add(&gpio_chips[i]->chip);
 
        dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n");
 
@@ -1682,6 +1693,8 @@ static void at91_gpio_probe_fixup(void)
 
        for (i = 0; i < gpio_banks; i++) {
                at91_gpio = gpio_chips[i];
+               if (!at91_gpio)
+                       continue;
 
                /*
                 * GPIO controller are grouped on some SoC:
@@ -1705,7 +1718,6 @@ static int at91_gpio_probe(struct platform_device *pdev)
        struct resource *res;
        struct at91_gpio_chip *at91_chip = NULL;
        struct gpio_chip *chip;
-       struct pinctrl_gpio_range *range;
        int ret = 0;
        int irq, i;
        int alias_idx = of_alias_get_id(np, "gpio");
@@ -1790,14 +1802,6 @@ static int at91_gpio_probe(struct platform_device *pdev)
 
        chip->names = (const char *const *)names;
 
-       range = &at91_chip->range;
-       range->name = chip->label;
-       range->id = alias_idx;
-       range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
-
-       range->npins = chip->ngpio;
-       range->gc = chip;
-
        ret = gpiochip_add(chip);
        if (ret)
                goto gpiochip_add_err;
-- 
2.0.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to