GPIO banks are probed independently from pinctrl parent device as it's
simple-bus compatible. The pinctrl driver needs access to the GPIO
banks though for applying a pin configuration. This has two problems:

  - When we have a pinctrl hog, we can't apply it if GPIOs weren't
    probed before

  - In a deep probe system, pinctrl may be used before GPIO was probed

Fix this for deep probe systems by probing relevant GPIO banks on
demand. We wrap this in a deep_probe_is_supported() check to avoid
increasing code size for the configurations that use non-DT enabled
barebox proper as first stage bootloader.

Tested on SAMA5D4.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 drivers/pinctrl/pinctrl-at91.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 0295d928cf61..4b71d181d483 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -16,6 +16,7 @@
 #include <init.h>
 #include <driver.h>
 #include <getopt.h>
+#include <deep-probe.h>
 
 #include <mach/at91_pio.h>
 #include <mach/gpio.h>
@@ -47,17 +48,25 @@ struct at91_gpio_chip {
 #define DEBOUNCE_VAL_SHIFT      17
 #define DEBOUNCE_VAL    (0x3fff << DEBOUNCE_VAL_SHIFT)
 
-static int gpio_banks;
-
 static struct at91_gpio_chip gpio_chip[MAX_GPIO_BANKS];
 
 static inline struct at91_gpio_chip *pin_to_controller(unsigned pin)
 {
+       struct at91_gpio_chip *chip;
+
        pin /= MAX_NB_GPIO_PER_BANK;
-       if (likely(pin < gpio_banks))
-               return &gpio_chip[pin];
+       if (unlikely(pin >= MAX_GPIO_BANKS))
+               return NULL;
+
+       chip = &gpio_chip[pin];
+
+       if (!chip->regbase && deep_probe_is_supported()) {
+               char alias[] = "gpioX";
+               scnprintf(alias, sizeof(alias), "gpio%u", pin);
+               of_device_ensure_probed_by_alias(alias);
+       }
 
-       return NULL;
+       return chip;
 }
 
 /**
@@ -652,7 +661,6 @@ static int at91_gpio_probe(struct device_d *dev)
                return ret;
        }
 
-       gpio_banks = max(gpio_banks, alias_idx + 1);
        at91_gpio->regbase = dev_request_mem_region_err_null(dev, 0);
        if (!at91_gpio->regbase)
                return -ENOENT;
-- 
2.30.2


Reply via email to