pinctrl: single: Parse gpio details from dt
authorBharat Gooty <bharat.gooty@broadcom.com>
Tue, 24 Aug 2021 10:16:31 +0000 (15:46 +0530)
committerTom Rini <trini@konsulko.com>
Tue, 5 Oct 2021 12:43:03 +0000 (08:43 -0400)
Parse different gpio properties from dt as part of probe
function. This detail is required to enable pinctrl pad
later when gpio lines are requested.

Signed-off-by: Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
Signed-off-by: Bharat Gooty <bharat.gooty@broadcom.com>
Acked-by: Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
drivers/pinctrl/pinctrl-single.c

index cf9ad36..0f96cd5 100644 (file)
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <dm/device_compat.h>
 #include <dm/devres.h>
+#include <dm/of_access.h>
 #include <dm/pinctrl.h>
 #include <linux/libfdt.h>
 #include <linux/list.h>
@@ -45,10 +46,26 @@ struct single_func {
 };
 
 /**
+ * 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_priv - private data
  * @bits_per_pin: number of bits per pin
  * @npins: number of selectable pins
  * @pin_name: temporary buffer to store the pin name
+ * @functions: list pin functions
+ * @gpiofuncs: list gpio functions
  */
 struct single_priv {
 #if (IS_ENABLED(CONFIG_SANDBOX))
@@ -58,6 +75,7 @@ struct single_priv {
        unsigned int npins;
        char pin_name[PINNAME_SIZE];
        struct list_head functions;
+       struct list_head gpiofuncs;
 };
 
 /**
@@ -454,6 +472,36 @@ static int single_get_pins_count(struct udevice *dev)
        return priv->npins;
 }
 
+static int single_add_gpio_func(struct udevice *dev)
+{
+       struct single_priv *priv = dev_get_priv(dev);
+       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_ofnode(dev), 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];
+               list_add_tail(&range->node, &priv->gpiofuncs);
+       }
+       return ret;
+}
+
 static int single_probe(struct udevice *dev)
 {
        struct single_pdata *pdata = dev_get_plat(dev);
@@ -461,6 +509,7 @@ static int single_probe(struct udevice *dev)
        u32 size;
 
        INIT_LIST_HEAD(&priv->functions);
+       INIT_LIST_HEAD(&priv->gpiofuncs);
 
        size = pdata->offset + pdata->width / BITS_PER_BYTE;
        #if (CONFIG_IS_ENABLED(SANDBOX))
@@ -483,6 +532,9 @@ static int single_probe(struct udevice *dev)
                priv->npins *= (pdata->width / priv->bits_per_pin);
        }
 
+       if (single_add_gpio_func(dev))
+               dev_dbg(dev, "gpio functions are not added\n");
+
        dev_dbg(dev, "%d pins\n", priv->npins);
        return 0;
 }