diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c index f120ee9808620faf7790dad15abef4183011024b..5bff27f75b504400504e2ce7a5da7a4add7cb4ee 100644 --- a/drivers/gpio/stm32_gpio.c +++ b/drivers/gpio/stm32_gpio.c @@ -41,6 +41,11 @@ static void stm32_gpio_set_moder(struct stm32_gpio_regs *regs, clrsetbits_le32(®s->moder, mask, mode << bits_index); } +static int stm32_gpio_get_moder(struct stm32_gpio_regs *regs, int idx) +{ + return (readl(®s->moder) >> MODE_BITS(idx)) & MODE_BITS_MASK; +} + static void stm32_gpio_set_otype(struct stm32_gpio_regs *regs, int idx, enum stm32_gpio_otype otype) @@ -51,6 +56,12 @@ static void stm32_gpio_set_otype(struct stm32_gpio_regs *regs, clrsetbits_le32(®s->otyper, OTYPE_MSK << bits, otype << bits); } +static enum stm32_gpio_otype stm32_gpio_get_otype(struct stm32_gpio_regs *regs, + int idx) +{ + return (readl(®s->otyper) >> OTYPE_BITS(idx)) & OTYPE_MSK; +} + static void stm32_gpio_set_pupd(struct stm32_gpio_regs *regs, int idx, enum stm32_gpio_pupd pupd) @@ -61,6 +72,12 @@ static void stm32_gpio_set_pupd(struct stm32_gpio_regs *regs, clrsetbits_le32(®s->pupdr, PUPD_MASK << bits, pupd << bits); } +static enum stm32_gpio_pupd stm32_gpio_get_pupd(struct stm32_gpio_regs *regs, + int idx) +{ + return (readl(®s->pupdr) >> PUPD_BITS(idx)) & PUPD_MASK; +} + /* * convert gpio offset to gpio index taking into account gpio holes * into gpio bank @@ -202,6 +219,47 @@ static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, return 0; } +static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, + ulong *flags) +{ + 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; + + switch (stm32_gpio_get_moder(regs, idx)) { + case STM32_GPIO_MODE_OUT: + dir_flags |= GPIOD_IS_OUT; + if (stm32_gpio_get_otype(regs, idx) == STM32_GPIO_OTYPE_OD) + dir_flags |= GPIOD_OPEN_DRAIN; + if (readl(®s->idr) & BIT(idx)) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + break; + case STM32_GPIO_MODE_IN: + dir_flags |= GPIOD_IS_IN; + switch (stm32_gpio_get_pupd(regs, idx)) { + case STM32_GPIO_PUPD_UP: + dir_flags |= GPIOD_PULL_UP; + break; + case STM32_GPIO_PUPD_DOWN: + dir_flags |= GPIOD_PULL_DOWN; + break; + default: + break; + } + break; + default: + break; + } + *flags = dir_flags; + + return 0; +} + static const struct dm_gpio_ops gpio_stm32_ops = { .direction_input = stm32_gpio_direction_input, .direction_output = stm32_gpio_direction_output, @@ -209,6 +267,7 @@ static const struct dm_gpio_ops gpio_stm32_ops = { .set_value = stm32_gpio_set_value, .get_function = stm32_gpio_get_function, .set_dir_flags = stm32_gpio_set_dir_flags, + .get_dir_flags = stm32_gpio_get_dir_flags, }; static int gpio_stm32_probe(struct udevice *dev)