[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(®s->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), ®s->bsrr);
> + writel(BSRR_BIT(offset, value), ®s->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(®s->idr) & BIT(idx) ? 1 : 0;
> + return readl(®s->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), ®s->bsrr);
> + writel(BSRR_BIT(offset, value), ®s->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(®s->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), ®s->bsrr);
> + stm32_gpio_set_moder(regs, offset, STM32_GPIO_MODE_OUT);
> + writel(BSRR_BIT(offset, value), ®s->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(®s->idr) & BIT(idx))
> + if (readl(®s->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