#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>
unsigned int *pins;
};
+/**
+ * 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))
unsigned int npins;
char pin_name[PINNAME_SIZE];
struct list_head functions;
+ struct list_head gpiofuncs;
};
/**
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);
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))
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;
}