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

Patrice CHOTARD patrice.chotard at foss.st.com
Tue May 10 10:06:32 CEST 2022



On 5/6/22 10:39, Patrick DELAUNAY wrote:
> 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
> 
Applied to u-boot-stm32

Thanks
Patrice


More information about the U-Boot mailing list