From: Benjamin Tietz <benja...@micronet24.de>

If CONFIG_DM_GPIO is enabled, the STM32 SOC GPIO driver will switch it's 
behaviour
from implementing the gpio_*() interface directly to provide a gpio-device.
---
 drivers/gpio/stm32_gpio.c |  133 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
index be662c3..844b3e1 100644
--- a/drivers/gpio/stm32_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -220,6 +220,138 @@ out:
        return rv;
 }
 
+#ifdef CONFIG_DM_GPIO
+#include <asm-generic/gpio.h>
+#include <dm/device.h>
+#include <clk.h>
+#include <dt-bindings/gpio/gpio.h>
+
+struct stm32_gpio_priv {
+       int portnum;
+       u32 requested;
+};
+
+static int stm32_gpio_request(struct udevice *dev, unsigned offset, const char 
*label)
+{
+       struct stm32_gpio_priv *priv = dev_get_priv(dev);
+       if(priv->requested & (1<<offset))
+               return -EBUSY;
+       if(!priv->requested) {
+               struct udevice *clk = NULL;
+               int clk_id;
+               if((clk_id = clk_get_by_index(dev, 0, &clk)) >= 0)
+                       clk_enable(clk, clk_id);
+       }
+       priv->requested |= 1<<offset;
+       return 0;
+}
+
+static int stm32_gpio_free(struct udevice *dev, unsigned offset)
+{
+       struct stm32_gpio_priv *priv = dev_get_priv(dev);
+       priv->requested &= ~(1<<offset);
+       if(!priv->requested) {
+               struct udevice *clk = NULL;
+               int clk_id;
+               if((clk_id = clk_get_by_index(dev, 0, &clk)) >= 0)
+                       clk_disable(clk, clk_id);
+       }
+       return 0;
+}
+
+static int stm32_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+       struct stm32_gpio_priv *priv = dev_get_priv(dev);
+       struct stm32_gpio_dsc dsc = {
+               .port = priv->portnum,
+               .pin = offset,
+       };
+       return stm32_gpio_config(&dsc, &ctl_in);
+}
+
+static int stm32_gpio_direction_output(struct udevice *dev, unsigned offset, 
int value)
+{
+       struct stm32_gpio_priv *priv = dev_get_priv(dev);
+       struct stm32_gpio_dsc dsc = {
+               .port = priv->portnum,
+               .pin = offset,
+       };
+       int ret = stm32_gpio_config(&dsc, &ctl_out);
+       if(ret >= 0)
+               ret = stm32_gpout_set(&dsc, value);
+       return ret;
+}
+
+static int stm32_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+       struct stm32_gpio_priv *priv = dev_get_priv(dev);
+       struct stm32_gpio_dsc dsc = {
+               .port = priv->portnum,
+               .pin = offset,
+       };
+       return !!stm32_gpin_get(&dsc);
+}
+
+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_dsc dsc = {
+               .port = priv->portnum,
+               .pin = offset,
+       };
+       return stm32_gpout_set(&dsc, value);
+}
+
+static struct dm_gpio_ops stm32_gpio_ops = {
+       .request = stm32_gpio_request,
+       .free = stm32_gpio_free,
+       .direction_input = stm32_gpio_direction_input,
+       .direction_output = stm32_gpio_direction_output,
+       .get_value = stm32_gpio_get_value,
+       .set_value = stm32_gpio_set_value,
+};
+
+static int stm32_gpio_probe(struct udevice *dev)
+{
+       struct stm32_gpio_priv *priv = dev_get_priv(dev);
+       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+       fdt_addr_t addr;
+       fdt_size_t size;
+       int i;
+       priv->requested = 0;
+
+       addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+       if (addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       if(size < sizeof(struct stm32_gpio_ctl))
+               return -EINVAL;
+
+       for(i=0; i < sizeof(io_base)/sizeof(io_base[0]); i++) {
+               if(io_base[i] != addr)
+                       continue;
+               priv->portnum = i;
+               uc_priv->bank_name = dev->name;
+               uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, 
dev->of_offset, "gpio-count", 16);
+               return 0;
+       }
+       return -ENXIO;
+}
+
+static const struct udevice_id stm32_gpio_ids[] = {
+       { .compatible = "st,stm32-gpio" },
+       { }
+};
+
+U_BOOT_DRIVER(stm32_gpio) = {
+       .name           = "stm32_gpio",
+       .id             = UCLASS_GPIO,
+       .ops            = &stm32_gpio_ops,
+       .probe          = stm32_gpio_probe,
+       .priv_auto_alloc_size = sizeof(struct stm32_gpio_priv),
+       .of_match       = stm32_gpio_ids,
+};
+#else
 /* Common GPIO API */
 
 int gpio_request(unsigned gpio, const char *label)
@@ -277,3 +409,4 @@ int gpio_set_value(unsigned gpio, int value)
 
        return stm32_gpout_set(&dsc, value);
 }
+#endif

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to