[PATCH] gpio: allocate dynamic gpio numbers top down

Sascha Hauer s.hauer at pengutronix.de
Tue Mar 29 01:52:07 PDT 2022


For GPIO controllers with dynamic GPIO number bases a free base
is searched for bottom up. This means that GPIO controllers with
fixed GPIO numbers must be registered before any controller with
dynamic GPIO number base is registered, because otherwise the
GPIO controllers with fixed GPIO numbers find their range occupied
and can't be registered anymore.

The probe order normally makes sure the SoC internal GPIO controllers
with fixed numbers are registered first. With deep probe enabled
we can't rely on the probe order anymore, so we need another solution.

With this patch a free GPIO number range is searched for top down
intead of bottom up, so as long as we have enough space in the
ARCH_NR_GPIOS range the SoC internal GPIO controllers find their
base unoccupied. GPIO controllers with dynamic GPIO numbers will
change their numbers with this patch, but code shouldn't rely on
these numbers anyway.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/gpio/gpiolib.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index f709d11f75..c9b33bcd6c 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -414,22 +414,19 @@ free_array:
 }
 EXPORT_SYMBOL(gpio_array_to_id);
 
-static int gpiochip_find_base(int start, int ngpio)
+static int gpiochip_find_base(int ngpio)
 {
 	int i;
 	int spare = 0;
 	int base = -ENOSPC;
 
-	if (start < 0)
-		start = 0;
-
-	for (i = start; i < ARCH_NR_GPIOS; i++) {
+	for (i = ARCH_NR_GPIOS - 1; i >= 0; i--) {
 		struct gpio_chip *chip = gpio_desc[i].chip;
 
 		if (!chip) {
 			spare++;
 			if (spare == ngpio) {
-				base = i + 1 - ngpio;
+				base = i;
 				break;
 			}
 		} else {
@@ -614,14 +611,17 @@ int gpiochip_add(struct gpio_chip *chip)
 {
 	int base, i;
 
-	base = gpiochip_find_base(chip->base, chip->ngpio);
-	if (base < 0)
-		return base;
-
-	if (chip->base >= 0 && chip->base != base)
-		return -EBUSY;
+	if (chip->base >= 0) {
+		for (i = 0; i < chip->ngpio; i++) {
+			if (gpio_desc[chip->base + i].chip)
+				return -EBUSY;
+		}
+	} else {
+		chip->base = gpiochip_find_base(chip->ngpio);
+		if (chip->base < 0)
+			return -ENOSPC;
+	}
 
-	chip->base = base;
 
 	list_add_tail(&chip->list, &chip_list);
 
-- 
2.30.2




More information about the barebox mailing list