diff mbox series

[U-Boot,3/3] pinctrl: pinctrl-single: Parse gpio details from dt

Message ID 20191122224443.29497-4-vladimir.olovyannikov@broadcom.com
State Deferred
Headers show
Series Extend pinctrl-single driver with APIs | expand

Commit Message

Vladimir Olovyannikov Nov. 22, 2019, 10:44 p.m. UTC
From: Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>

Parse different gpio properties from dt as part of probe
function. This detail is required to enable pinctrl pad.

Signed-off-by: Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
Signed-off-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
---
 drivers/pinctrl/pinctrl-single.c | 61 +++++++++++++++++++++++++++++++-
 1 file changed, 60 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 2dcc131513..449e8a2bfe 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -5,18 +5,35 @@ 
 
 #include <common.h>
 #include <dm.h>
+#include <dm/of_access.h>
 #include <dm/pinctrl.h>
 #include <linux/libfdt.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/**
+ * struct single_gpiofunc_range - pin ranges with same mux value of gpio fun
+ * @offset:	offset base of pins
+ * @npins:	number pins with the same mux value of gpio function
+ * @gpiofunc:	mux value of gpio function
+ * @node:	list node
+ */
+struct single_gpiofunc_range {
+	u32 offset;
+	u32 npins;
+	u32 gpiofunc;
+	struct list_head node;
+};
+
 /**
  * struct single_pdata - pinctrl device instance
  * @base	first configuration register
  * @offset	index of last configuration register
  * @mask	configuration-value mask bits
  * @width	configuration register bit width
+ * @mutex	mutex protecting the list
+ * @gpiofuncs	list of gpio functions
  * @read	register read function to use
  * @write	register write function to use
  */
@@ -26,6 +43,8 @@  struct single_pdata {
 	u32 mask;
 	int width;
 	bool bits_per_mux;
+	struct mutex mutex;
+	struct list_head gpiofuncs;
 	u32 (*read)(void __iomem *reg);
 	void (*write)(u32 val, void __iomem *reg);
 };
@@ -204,9 +223,42 @@  static int single_set_state(struct udevice *dev,
 	return len;
 }
 
+static int single_add_gpio_func(struct udevice *dev,
+				struct single_pdata *pdata)
+{
+	const char *propname = "pinctrl-single,gpio-range";
+	const char *cellname = "#pinctrl-single,gpio-range-cells";
+	struct single_gpiofunc_range *range;
+	struct ofnode_phandle_args gpiospec;
+	int ret, i;
+
+	for (i = 0; ; i++) {
+		ret = ofnode_parse_phandle_with_args(dev->node, propname,
+						     cellname, 0, i, &gpiospec);
+		/* Do not treat it as error. Only treat it as end condition. */
+		if (ret) {
+			ret = 0;
+			break;
+		}
+		range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
+		if (!range) {
+			ret = -ENOMEM;
+			break;
+		}
+		range->offset = gpiospec.args[0];
+		range->npins = gpiospec.args[1];
+		range->gpiofunc = gpiospec.args[2];
+		mutex_lock(&pdata->mutex);
+		list_add_tail(&range->node, &pdata->gpiofuncs);
+		mutex_unlock(&pdata->mutex);
+	}
+	return ret;
+}
+
 static int single_probe(struct udevice *dev)
 {
 	struct single_pdata *pdata = dev->platdata;
+	int ret;
 
 	switch (pdata->width) {
 	case 8:
@@ -227,7 +279,14 @@  static int single_probe(struct udevice *dev)
 		return -EINVAL;
 	}
 
-	return 0;
+	mutex_init(&pdata->mutex);
+	INIT_LIST_HEAD(&pdata->gpiofuncs);
+
+	ret = single_add_gpio_func(dev, pdata);
+	if (ret < 0)
+		dev_err(dev, "%s: Failed to add gpio functions\n", __func__);
+
+	return ret;
 }
 
 static int single_ofdata_to_platdata(struct udevice *dev)