diff mbox

[v5,01/22] pinctrl: generic: Add DT bindings

Message ID 1370989371-30846-2-git-send-email-laurent.pinchart+renesas@ideasonboard.com (mailing list archive)
State New, archived
Headers show

Commit Message

Laurent Pinchart June 11, 2013, 10:22 p.m. UTC
Document DT properties for the generic pinctrl parameters and add a
parser function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../bindings/pinctrl/pinctrl-bindings.txt          | 29 +++++++
 drivers/pinctrl/pinconf-generic.c                  | 94 ++++++++++++++++++++++
 drivers/pinctrl/pinconf.h                          | 17 ++++
 3 files changed, 140 insertions(+)

Comments

Linus Walleij June 12, 2013, 9:24 a.m. UTC | #1
On Wed, Jun 12, 2013 at 12:22 AM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:

> Document DT properties for the generic pinctrl parameters and add a
> parser function.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

It appears we have a race here, as something like three people,
or four, happened to do generic pinconf bindings at the same time.

Yesterday I applied Heiko Stübners patch
"pinctrl: add function to parse generic pinconfig properties from a dt node"
doing basically the same thing. With subtle differences...
but it already supports schmittrigging and some more.

It appears to be close to your idea though!

Would it be possible for you to look at what I have on my "devel" branch
now (same as submitted for -next), rebase on that and patch any problems?

> +               if (param->flag) {
> +                       ret = of_property_read_bool(np, param->property)
> +                           ? 0 : -EINVAL;
> +                       val = 1;
> +               } else {
> +                       ret = of_property_read_u32(np, param->property, &val);
> +               }

This construct is done differently in Heiko's code, please
review it so we know we have a nice, efficient parser.

Yours,
Linus Walleij
Laurent Pinchart June 13, 2013, 10:23 p.m. UTC | #2
Hi Linus,

On Wednesday 12 June 2013 11:24:38 Linus Walleij wrote:
> On Wed, Jun 12, 2013 at 12:22 AM, Laurent Pinchart wrote:
> > Document DT properties for the generic pinctrl parameters and add a
> > parser function.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> It appears we have a race here, as something like three people,
> or four, happened to do generic pinconf bindings at the same time.
> 
> Yesterday I applied Heiko Stübners patch
> "pinctrl: add function to parse generic pinconfig properties from a dt node"
> doing basically the same thing. With subtle differences...
> but it already supports schmittrigging and some more.
> 
> It appears to be close to your idea though!
> 
> Would it be possible for you to look at what I have on my "devel" branch
> now (same as submitted for -next), rebase on that and patch any problems?

OK, I will do so. In the meantime I'll resubmit this patch series without the 
pinconf DT bindings for inclusion in v3.11, and will then post follow-up 
patches to add pinconf DT support, for v3.11 or v3.12 depending on the timing.

> > +               if (param->flag) {
> > +                       ret = of_property_read_bool(np, param->property)
> > +                           ? 0 : -EINVAL;
> > +                       val = 1;
> > +               } else {
> > +                       ret = of_property_read_u32(np, param->property,
> > &val); +               }
> 
> This construct is done differently in Heiko's code, please review it so we
> know we have a nice, efficient parser.
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
index c95ea82..e499ff0 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -126,3 +126,32 @@  device; they may be grandchildren, for example. Whether this is legal, and
 whether there is any interaction between the child and intermediate parent
 nodes, is again defined entirely by the binding for the individual pin
 controller device.
+
+== Generic pinconf parameters ==
+
+Pin configuration parameters are expressed by DT properties in the pin
+controller device state nodes and child nodes. For devices that use the generic
+pinconf parameters the following properties are defined.
+
+- tristate: A boolean, put the pin into high impedance state when set.
+
+- pull-up: An integer representing the pull-up strength. 0 disables the pull-up,
+  non-zero values enable it.
+
+- pull-down: An integer representing the pull-down strength. 0 disables the
+  pull-down, non-zero values enables it.
+
+- schmitt: An integer, enable or disable Schmitt trigger mode for the pins.
+  Valid values are
+    0: Schmitt trigger disabled (no hysteresis)
+    1: Schmitt trigger enabled
+
+- slew-rate: An integer controlling the pin slew rate. Values are device-
+  dependent.
+
+- drive-strength: An integer representing the drive strength of pins in mA.
+  Valid values are device-dependent.
+
+The pinctrl device DT bindings documentation must list the properties that
+apply to the device, and define the valid range for all device-dependent
+values.
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 2ad5a8d..bd0e41d 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -15,6 +15,7 @@ 
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -135,3 +136,96 @@  void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
 }
 EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
 #endif
+
+struct pinconf_generic_param {
+	const char *property;
+	enum pin_config_param param;
+	bool flag;
+};
+
+static const struct pinconf_generic_param pinconf_generic_params[] = {
+	{ "tristate",		PIN_CONFIG_BIAS_HIGH_IMPEDANCE,		true },
+	{ "pull-up",		PIN_CONFIG_BIAS_PULL_UP,		false },
+	{ "pull-down",		PIN_CONFIG_BIAS_PULL_DOWN,		false },
+	{ "schmitt",		PIN_CONFIG_INPUT_SCHMITT_ENABLE,	true },
+	{ "slew-rate",		PIN_CONFIG_SLEW_RATE,			false },
+	{ "drive-strength",	PIN_CONFIG_DRIVE_STRENGTH,		false },
+};
+
+static int pinconf_generic_add_config(unsigned long **configs,
+				      unsigned int *num_configs,
+				      unsigned long config)
+{
+	unsigned int count = *num_configs + 1;
+	unsigned long *cfgs;
+
+	cfgs = krealloc(*configs, sizeof(*cfgs) * count, GFP_KERNEL);
+	if (cfgs == NULL)
+		return -ENOMEM;
+
+	cfgs[count - 1] = config;
+
+	*configs = cfgs;
+	*num_configs = count;
+
+	return 0;
+}
+
+/**
+ * pinconf_generic_parse_params - Parse generic pinconf parameters from DT
+ * @dev: the device, used to print error messages
+ * @np: the DT node that contains generic pinconf parameters
+ * @cfgs: the returned array of pinconf parameters
+ *
+ * The parameters array is allocated dynamically and returned through the cfgs
+ * argument. The caller is responsible for freeing the array with kfree(). If no
+ * configuration parameter is found, or if an error occurs, no parameters array
+ * will be allocated and the cfgs argument will be set to NULL.
+ *
+ * Return the number of configuration parameters successfully parsed, or a
+ * negative value if an error occurred. Used error codes are
+ *
+ * -ENOMEM if memory can't be allocated for the parameters array
+ */
+int pinconf_generic_parse_params(struct device *dev, struct device_node *np,
+				 unsigned long **cfgs)
+{
+	unsigned long *configs = NULL;
+	unsigned int num_configs = 0;
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(pinconf_generic_params); ++i) {
+		const struct pinconf_generic_param *param =
+			&pinconf_generic_params[i];
+		unsigned long config;
+		u32 val;
+
+		if (param->flag) {
+			ret = of_property_read_bool(np, param->property)
+			    ? 0 : -EINVAL;
+			val = 1;
+		} else {
+			ret = of_property_read_u32(np, param->property, &val);
+		}
+
+		if (ret) {
+			if (ret != -EINVAL)
+				dev_err(dev, "failed to parse property %s\n",
+					param->property);
+			continue;
+		}
+
+		config = pinconf_to_config_packed(param->param, val);
+		ret = pinconf_generic_add_config(&configs, &num_configs, config);
+		if (ret < 0) {
+			kfree(configs);
+			*cfgs = NULL;
+			return ret;
+		}
+	}
+
+	*cfgs = configs;
+	return num_configs;
+}
+EXPORT_SYMBOL_GPL(pinconf_generic_parse_params);
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index 92c7267..eb8550b 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -90,6 +90,23 @@  static inline void pinconf_init_device_debugfs(struct dentry *devroot,
  * pin config.
  */
 
+#if defined(CONFIG_GENERIC_PINCONF)
+
+int pinconf_generic_parse_params(struct device *dev, struct device_node *np,
+				 unsigned long **cfgs);
+
+#else
+
+static inline int pinconf_generic_parse_params(struct device *dev,
+					       struct device_node *np,
+					       unsigned long **cfgs)
+{
+	*cfgs = NULL;
+	return 0;
+}
+
+#endif
+
 #if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_DEBUG_FS)
 
 void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,