[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(®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
>
Applied to u-boot-stm32
Thanks
Patrice
More information about the U-Boot
mailing list