gpio: sunxi: Implement .set_flags
authorSamuel Holland <samuel@sholland.org>
Thu, 21 Oct 2021 04:52:56 +0000 (23:52 -0500)
committerAndre Przywara <andre.przywara@arm.com>
Sun, 30 Jan 2022 01:25:00 +0000 (01:25 +0000)
This, along with gpio_flags_xlate(), allows the GPIO driver to handle
pull-up/down flags provided by consumer drivers or in the device tree.

Signed-off-by: Samuel Holland <samuel@sholland.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
drivers/gpio/sunxi_gpio.c

index caefb14..6c3c108 100644 (file)
@@ -139,27 +139,6 @@ int sunxi_name_to_gpio(const char *name)
        return ret ? ret : gpio;
 }
 
-static int sunxi_gpio_direction_input(struct udevice *dev, unsigned offset)
-{
-       struct sunxi_gpio_plat *plat = dev_get_plat(dev);
-
-       sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_INPUT);
-
-       return 0;
-}
-
-static int sunxi_gpio_direction_output(struct udevice *dev, unsigned offset,
-                                      int value)
-{
-       struct sunxi_gpio_plat *plat = dev_get_plat(dev);
-       u32 num = GPIO_NUM(offset);
-
-       sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
-       clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
-
-       return 0;
-}
-
 static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
 {
        struct sunxi_gpio_plat *plat = dev_get_plat(dev);
@@ -172,16 +151,6 @@ static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
        return dat & 0x1;
 }
 
-static int sunxi_gpio_set_value(struct udevice *dev, unsigned offset,
-                               int value)
-{
-       struct sunxi_gpio_plat *plat = dev_get_plat(dev);
-       u32 num = GPIO_NUM(offset);
-
-       clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
-       return 0;
-}
-
 static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
 {
        struct sunxi_gpio_plat *plat = dev_get_plat(dev);
@@ -205,18 +174,41 @@ static int sunxi_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
        if (ret)
                return ret;
        desc->offset = args->args[1];
-       desc->flags = args->args[2] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+       desc->flags = gpio_flags_xlate(args->args[2]);
+
+       return 0;
+}
+
+static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
+                               ulong flags)
+{
+       struct sunxi_gpio_plat *plat = dev_get_plat(dev);
+
+       if (flags & GPIOD_IS_OUT) {
+               u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
+               u32 num = GPIO_NUM(offset);
+
+               clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
+               sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
+       } else if (flags & GPIOD_IS_IN) {
+               u32 pull = 0;
+
+               if (flags & GPIOD_PULL_UP)
+                       pull = 1;
+               else if (flags & GPIOD_PULL_DOWN)
+                       pull = 2;
+               sunxi_gpio_set_pull_bank(plat->regs, offset, pull);
+               sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_INPUT);
+       }
 
        return 0;
 }
 
 static const struct dm_gpio_ops gpio_sunxi_ops = {
-       .direction_input        = sunxi_gpio_direction_input,
-       .direction_output       = sunxi_gpio_direction_output,
        .get_value              = sunxi_gpio_get_value,
-       .set_value              = sunxi_gpio_set_value,
        .get_function           = sunxi_gpio_get_function,
        .xlate                  = sunxi_gpio_xlate,
+       .set_flags              = sunxi_gpio_set_flags,
 };
 
 /**