gpio: stm32_gpio: Rework GPIO hole management

On some STM32 SoC's package, GPIO bank may have hole in their GPIO bank
Example:
  If GPIO bank have 16 GPIO pins [0-15].
  In particular SoC's package case, some GPIO bank can have less GPIO pins:
    - [0-10] => 11 pins;
    - [2-7] => 6 pins.

Commit dbf928dd2634 ("gpio: stm32f7: Add gpio bank holes management")
proposed a first implementation by not counting GPIO "inside" hole. GPIO
are not displaying correctly using gpio or pinmux command when GPIO holes
are located at the beginning of GPIO bank.

To simplify, consider that all GPIO have 16 GPIO and use the gpio_ranges
struct to indicate if a GPIO is mapped or not. GPIO uclass offers several
GPIO functions ("input", "output", "unused", "unknown" and "func"), use
"unknown" GPIO function to indicate that a GPIO is not mapped.

stm32_offset_to_index() is no more needed and removed.

This must be reflected using the "gpio" command to indicate to user
that a particular GPIO is not mapped (marked as "unknown") as shown below:

Example for a 16 pins GPIO bank with the [2-7] mapping (only 6 pins
mapped):
GPIOI0          : unknown
GPIOI1          : unknown
GPIOI2          : analog
GPIOI3          : analog
GPIOI4          : alt function 0 push-pull pull-down
GPIOI5          : alt function 0 push-pull pull-down
GPIOI6          : alt function 0 push-pull pull-down
GPIOI7          : analog
GPIOI8          : unknown
GPIOI9          : unknown
GPIOI10         : unknown
GPIOI11         : unknown
GPIOI12         : unknown
GPIOI13         : unknown
GPIOI14         : unknown
GPIOI15         : unknown

Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
index 8667ed3..7a2ca91 100644
--- a/drivers/gpio/stm32_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -83,38 +83,22 @@
 	return (readl(&regs->pupdr) >> PUPD_BITS(idx)) & PUPD_MASK;
 }
 
-/*
- * convert gpio offset to gpio index taking into account gpio holes
- * into gpio bank
- */
-int stm32_offset_to_index(struct udevice *dev, unsigned int offset)
+static bool stm32_gpio_is_mapped(struct udevice *dev, int offset)
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
-	unsigned int idx = 0;
-	int i;
 
-	for (i = 0; i < STM32_GPIOS_PER_BANK; i++) {
-		if (priv->gpio_range & BIT(i)) {
-			if (idx == offset)
-				return idx;
-			idx++;
-		}
-	}
-	/* shouldn't happen */
-	return -EINVAL;
+	return !!(priv->gpio_range & BIT(offset));
 }
 
 static int stm32_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
-	int idx;
 
-	idx = stm32_offset_to_index(dev, offset);
-	if (idx < 0)
-		return idx;
+	if (!stm32_gpio_is_mapped(dev, offset))
+		return -ENXIO;
 
-	stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN);
+	stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_IN);
 
 	return 0;
 }
@@ -124,15 +108,13 @@
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
-	int idx;
 
-	idx = stm32_offset_to_index(dev, offset);
-	if (idx < 0)
-		return idx;
+	if (!stm32_gpio_is_mapped(dev, offset))
+		return -ENXIO;
 
-	stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
+	stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_OUT);
 
-	writel(BSRR_BIT(idx, value), &regs->bsrr);
+	writel(BSRR_BIT(offset, value), &regs->bsrr);
 
 	return 0;
 }
@@ -141,26 +123,22 @@
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
-	int idx;
 
-	idx = stm32_offset_to_index(dev, offset);
-	if (idx < 0)
-		return idx;
+	if (!stm32_gpio_is_mapped(dev, offset))
+		return -ENXIO;
 
-	return readl(&regs->idr) & BIT(idx) ? 1 : 0;
+	return readl(&regs->idr) & BIT(offset) ? 1 : 0;
 }
 
 static int stm32_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
-	int idx;
 
-	idx = stm32_offset_to_index(dev, offset);
-	if (idx < 0)
-		return idx;
+	if (!stm32_gpio_is_mapped(dev, offset))
+		return -ENXIO;
 
-	writel(BSRR_BIT(idx, value), &regs->bsrr);
+	writel(BSRR_BIT(offset, value), &regs->bsrr);
 
 	return 0;
 }
@@ -171,14 +149,12 @@
 	struct stm32_gpio_regs *regs = priv->regs;
 	int bits_index;
 	int mask;
-	int idx;
 	u32 mode;
 
-	idx = stm32_offset_to_index(dev, offset);
-	if (idx < 0)
-		return idx;
+	if (!stm32_gpio_is_mapped(dev, offset))
+		return GPIOF_UNKNOWN;
 
-	bits_index = MODE_BITS(idx);
+	bits_index = MODE_BITS(offset);
 	mask = MODE_BITS_MASK << bits_index;
 
 	mode = (readl(&regs->moder) & mask) >> bits_index;
@@ -197,30 +173,28 @@
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
-	int idx;
 
-	idx = stm32_offset_to_index(dev, offset);
-	if (idx < 0)
-		return idx;
+	if (!stm32_gpio_is_mapped(dev, offset))
+		return -ENXIO;
 
 	if (flags & GPIOD_IS_OUT) {
 		bool value = flags & GPIOD_IS_OUT_ACTIVE;
 
 		if (flags & GPIOD_OPEN_DRAIN)
-			stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD);
+			stm32_gpio_set_otype(regs, offset, STM32_GPIO_OTYPE_OD);
 		else
-			stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP);
+			stm32_gpio_set_otype(regs, offset, STM32_GPIO_OTYPE_PP);
 
-		stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
-		writel(BSRR_BIT(idx, value), &regs->bsrr);
+		stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_OUT);
+		writel(BSRR_BIT(offset, value), &regs->bsrr);
 
 	} else if (flags & GPIOD_IS_IN) {
-		stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN);
+		stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_IN);
 	}
 	if (flags & GPIOD_PULL_UP)
-		stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_UP);
+		stm32_gpio_set_pupd(regs, offset, STM32_GPIO_PUPD_UP);
 	else if (flags & GPIOD_PULL_DOWN)
-		stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_DOWN);
+		stm32_gpio_set_pupd(regs, offset, STM32_GPIO_PUPD_DOWN);
 
 	return 0;
 }
@@ -230,19 +204,17 @@
 {
 	struct stm32_gpio_priv *priv = dev_get_priv(dev);
 	struct stm32_gpio_regs *regs = priv->regs;
-	int idx;
 	ulong dir_flags = 0;
 
-	idx = stm32_offset_to_index(dev, offset);
-	if (idx < 0)
-		return idx;
+	if (!stm32_gpio_is_mapped(dev, offset))
+		return -ENXIO;
 
-	switch (stm32_gpio_get_moder(regs, idx)) {
+	switch (stm32_gpio_get_moder(regs, offset)) {
 	case STM32_GPIO_MODE_OUT:
 		dir_flags |= GPIOD_IS_OUT;
-		if (stm32_gpio_get_otype(regs, idx) == STM32_GPIO_OTYPE_OD)
+		if (stm32_gpio_get_otype(regs, offset) == STM32_GPIO_OTYPE_OD)
 			dir_flags |= GPIOD_OPEN_DRAIN;
-		if (readl(&regs->idr) & BIT(idx))
+		if (readl(&regs->idr) & BIT(offset))
 			dir_flags |= GPIOD_IS_OUT_ACTIVE;
 		break;
 	case STM32_GPIO_MODE_IN:
@@ -251,7 +223,7 @@
 	default:
 		break;
 	}
-	switch (stm32_gpio_get_pupd(regs, idx)) {
+	switch (stm32_gpio_get_pupd(regs, offset)) {
 	case STM32_GPIO_PUPD_UP:
 		dir_flags |= GPIOD_PULL_UP;
 		break;
@@ -304,17 +276,14 @@
 	if (!ret && args.args_count < 3)
 		return -EINVAL;
 
-	if (ret == -ENOENT) {
-		uc_priv->gpio_count = STM32_GPIOS_PER_BANK;
+	uc_priv->gpio_count = STM32_GPIOS_PER_BANK;
+	if (ret == -ENOENT)
 		priv->gpio_range = GENMASK(STM32_GPIOS_PER_BANK - 1, 0);
-	}
 
 	while (ret != -ENOENT) {
 		priv->gpio_range |= GENMASK(args.args[2] + args.args[0] - 1,
 				    args.args[0]);
 
-		uc_priv->gpio_count += args.args[2];
-
 		ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3,
 						 ++i, &args);
 		if (!ret && args.args_count < 3)