[PATCH 3/3] gpio: stm32_gpio: Rework GPIO hole management

Patrick DELAUNAY patrick.delaunay at foss.st.com
Fri May 6 10:39:33 CEST 2022


Hi,

On 4/22/22 09:38, Patrice Chotard wrote:
> 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 at foss.st.com>
> ---
>
>   drivers/gpio/stm32_gpio.c       | 103 +++++++++++---------------------
>   drivers/gpio/stm32_gpio_priv.h  |   2 -
>   drivers/pinctrl/pinctrl_stm32.c |   5 +-
>   3 files changed, 37 insertions(+), 73 deletions(-)
>
> diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
> index 8667ed3835..7a2ca91c76 100644
> --- a/drivers/gpio/stm32_gpio.c
> +++ b/drivers/gpio/stm32_gpio.c
> @@ -83,38 +83,22 @@ static enum stm32_gpio_pupd stm32_gpio_get_pupd(struct stm32_gpio_regs *regs,
>   	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 @@ static int stm32_gpio_direction_output(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_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 @@ static int stm32_gpio_get_value(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;
>   
> -	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 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset)
>   	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 @@ static int stm32_gpio_set_flags(struct udevice *dev, unsigned int 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;
>   
>   	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 @@ static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset,
>   {
>   	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 @@ static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset,
>   	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 @@ static int gpio_stm32_probe(struct udevice *dev)
>   	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)
> diff --git a/drivers/gpio/stm32_gpio_priv.h b/drivers/gpio/stm32_gpio_priv.h
> index d3d8f2ed5d..662a000fe7 100644
> --- a/drivers/gpio/stm32_gpio_priv.h
> +++ b/drivers/gpio/stm32_gpio_priv.h
> @@ -81,6 +81,4 @@ struct stm32_gpio_priv {
>   	unsigned int gpio_range;
>   };
>   
> -int stm32_offset_to_index(struct udevice *dev, unsigned int offset);
> -
>   #endif /* _STM32_GPIO_PRIV_H_ */
> diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
> index 373f51f046..56a20e8bd2 100644
> --- a/drivers/pinctrl/pinctrl_stm32.c
> +++ b/drivers/pinctrl/pinctrl_stm32.c
> @@ -157,10 +157,7 @@ static struct udevice *stm32_pinctrl_get_gpio_dev(struct udevice *dev,
>   			 * we found the bank, convert pin selector to
>   			 * gpio bank index
>   			 */
> -			*idx = stm32_offset_to_index(gpio_bank->gpio_dev,
> -						     selector - pin_count);
> -			if (IS_ERR_VALUE(*idx))
> -				return NULL;
> +			*idx = selector - pin_count;
>   
>   			return gpio_bank->gpio_dev;
>   		}


Reviewed-by: Patrick Delaunay <patrick.delaunay at foss.st.com>

Thanks
Patrick



More information about the U-Boot mailing list