
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 --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)