[U-Boot] [PATCH v2 11/22] GPIO: STM32: make DTS-aware

Benjamin Tietz uboot at dresden.micronet24.de
Mon Jun 20 20:26:56 CEST 2016


From: Benjamin Tietz <benjamin at 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



More information about the U-Boot mailing list