aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Stübner <heiko@sntech.de>2013-06-10 15:40:29 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-06-16 05:57:32 -0400
commit7db9af4b6e41be599e0fcd50d687138a5add428c (patch)
tree222803dcf9b69980bf4398fc203b832dc2b1a6c8
parent5c0e3580cb988cf4688070d2d7ac56cf83fc6959 (diff)
pinctrl: add function to parse generic pinconfig properties from a dt node
pinconf_generic_parse_dt_config() takes a node as input and generates an array of generic pinconfig values from the properties of this node. As I couldn't find a mechanism to count the number of properties of a node the function uses internally an array to accept one of parameter and copies the real present options to a smaller variable at its end. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt38
-rw-r--r--drivers/pinctrl/pinconf-generic.c81
-rw-r--r--drivers/pinctrl/pinconf.h6
3 files changed, 125 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
index c95ea8278f87..ef7cd572214c 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -126,3 +126,41 @@ device; they may be grandchildren, for example. Whether this is legal, and
126whether there is any interaction between the child and intermediate parent 126whether there is any interaction between the child and intermediate parent
127nodes, is again defined entirely by the binding for the individual pin 127nodes, is again defined entirely by the binding for the individual pin
128controller device. 128controller device.
129
130== Using generic pinconfig options ==
131
132Generic pinconfig parameters can be used by defining a separate node containing
133the applicable parameters (and optional values), like:
134
135pcfg_pull_up: pcfg_pull_up {
136 bias-pull-up;
137 drive-strength = <20>;
138};
139
140This node should then be referenced in the appropriate pinctrl node as a phandle
141and parsed in the driver using the pinconf_generic_parse_dt_config function.
142
143Supported configuration parameters are:
144
145bias-disable - disable any pin bias
146bias-high-impedance - high impedance mode ("third-state", "floating")
147bias-bus-hold - latch weakly
148bias-pull-up - pull up the pin
149bias-pull-down - pull down the pin
150bias-pull-pin-default - use pin-default pull state
151drive-push-pull - drive actively high and low
152drive-open-drain - drive with open drain
153drive-open-source - drive with open source
154drive-strength - sink or source at most X mA
155input-schmitt-enable - enable schmitt-trigger mode
156input-schmitt-disable - disable schmitt-trigger mode
157input-schmitt - run in schmitt-trigger mode with hysteresis X
158input-debounce - debounce mode with debound time X
159power-source - select power source X
160slew-rate - use slew-rate X
161low-power-mode - low power mode
162output-low - set the pin to output mode with low level
163output-high - set the pin to output mode with high level
164
165More in-depth documentation on these parameters can be found in
166<include/linux/pinctrl/pinconfig-generic.h>
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 9a6812b50a32..d3c693c0c250 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -21,6 +21,7 @@
21#include <linux/pinctrl/pinctrl.h> 21#include <linux/pinctrl/pinctrl.h>
22#include <linux/pinctrl/pinconf.h> 22#include <linux/pinctrl/pinconf.h>
23#include <linux/pinctrl/pinconf-generic.h> 23#include <linux/pinctrl/pinconf-generic.h>
24#include <linux/of.h>
24#include "core.h" 25#include "core.h"
25#include "pinconf.h" 26#include "pinconf.h"
26 27
@@ -139,3 +140,83 @@ void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
139} 140}
140EXPORT_SYMBOL_GPL(pinconf_generic_dump_config); 141EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
141#endif 142#endif
143
144#ifdef CONFIG_OF
145struct pinconf_generic_dt_params {
146 const char * const property;
147 enum pin_config_param param;
148 u32 default_value;
149};
150
151static struct pinconf_generic_dt_params dt_params[] = {
152 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
153 { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
154 { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
155 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 0 },
156 { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 0 },
157 { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 0 },
158 { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
159 { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
160 { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
161 { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
162 { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
163 { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
164 { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
165 { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
166 { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
167 { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
168 { "low-power-mode", PIN_CONFIG_LOW_POWER_MODE, 0 },
169 { "output-low", PIN_CONFIG_OUTPUT, 0, },
170 { "output-high", PIN_CONFIG_OUTPUT, 1, },
171};
172
173/**
174 * pinconf_generic_parse_dt_config()
175 * parse the config properties into generic pinconfig values.
176 * @np: node containing the pinconfig properties
177 * @configs: array with nconfigs entries containing the generic pinconf values
178 * @nconfigs: umber of configurations
179 */
180int pinconf_generic_parse_dt_config(struct device_node *np,
181 unsigned long **configs,
182 unsigned int *nconfigs)
183{
184 unsigned long cfg[ARRAY_SIZE(dt_params)];
185 unsigned int ncfg = 0;
186 int ret;
187 int i;
188 u32 val;
189
190 if (!np)
191 return -EINVAL;
192
193 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
194 struct pinconf_generic_dt_params *par = &dt_params[i];
195 ret = of_property_read_u32(np, par->property, &val);
196
197 /* property not found */
198 if (ret == -EINVAL)
199 continue;
200
201 /* use default value, when no value is specified */
202 if (ret)
203 val = par->default_value;
204
205 pr_debug("found %s with value %u\n", par->property, val);
206 cfg[ncfg] = pinconf_to_config_packed(par->param, val);
207 ncfg++;
208 }
209
210 /*
211 * Now limit the number of configs to the real number of
212 * found properties.
213 */
214 *configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL);
215 if (!*configs)
216 return -ENOMEM;
217
218 memcpy(*configs, &cfg, ncfg * sizeof(unsigned long));
219 *nconfigs = ncfg;
220 return 0;
221}
222#endif
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index 92c7267244d2..a4a5417e1413 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -123,3 +123,9 @@ static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
123 return; 123 return;
124} 124}
125#endif 125#endif
126
127#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF)
128int pinconf_generic_parse_dt_config(struct device_node *np,
129 unsigned long **configs,
130 unsigned int *nconfigs);
131#endif