Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Heiko Stübner and committed by
Linus Walleij
7db9af4b 5c0e3580

+125
+38
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
··· 126 126 whether there is any interaction between the child and intermediate parent 127 127 nodes, is again defined entirely by the binding for the individual pin 128 128 controller device. 129 + 130 + == Using generic pinconfig options == 131 + 132 + Generic pinconfig parameters can be used by defining a separate node containing 133 + the applicable parameters (and optional values), like: 134 + 135 + pcfg_pull_up: pcfg_pull_up { 136 + bias-pull-up; 137 + drive-strength = <20>; 138 + }; 139 + 140 + This node should then be referenced in the appropriate pinctrl node as a phandle 141 + and parsed in the driver using the pinconf_generic_parse_dt_config function. 142 + 143 + Supported configuration parameters are: 144 + 145 + bias-disable - disable any pin bias 146 + bias-high-impedance - high impedance mode ("third-state", "floating") 147 + bias-bus-hold - latch weakly 148 + bias-pull-up - pull up the pin 149 + bias-pull-down - pull down the pin 150 + bias-pull-pin-default - use pin-default pull state 151 + drive-push-pull - drive actively high and low 152 + drive-open-drain - drive with open drain 153 + drive-open-source - drive with open source 154 + drive-strength - sink or source at most X mA 155 + input-schmitt-enable - enable schmitt-trigger mode 156 + input-schmitt-disable - disable schmitt-trigger mode 157 + input-schmitt - run in schmitt-trigger mode with hysteresis X 158 + input-debounce - debounce mode with debound time X 159 + power-source - select power source X 160 + slew-rate - use slew-rate X 161 + low-power-mode - low power mode 162 + output-low - set the pin to output mode with low level 163 + output-high - set the pin to output mode with high level 164 + 165 + More in-depth documentation on these parameters can be found in 166 + <include/linux/pinctrl/pinconfig-generic.h>
+81
drivers/pinctrl/pinconf-generic.c
··· 21 21 #include <linux/pinctrl/pinctrl.h> 22 22 #include <linux/pinctrl/pinconf.h> 23 23 #include <linux/pinctrl/pinconf-generic.h> 24 + #include <linux/of.h> 24 25 #include "core.h" 25 26 #include "pinconf.h" 26 27 ··· 139 138 } 140 139 } 141 140 EXPORT_SYMBOL_GPL(pinconf_generic_dump_config); 141 + #endif 142 + 143 + #ifdef CONFIG_OF 144 + struct pinconf_generic_dt_params { 145 + const char * const property; 146 + enum pin_config_param param; 147 + u32 default_value; 148 + }; 149 + 150 + static struct pinconf_generic_dt_params dt_params[] = { 151 + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, 152 + { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 }, 153 + { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 }, 154 + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 0 }, 155 + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 0 }, 156 + { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 0 }, 157 + { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 }, 158 + { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 }, 159 + { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 }, 160 + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, 161 + { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 }, 162 + { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 }, 163 + { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 }, 164 + { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 }, 165 + { "power-source", PIN_CONFIG_POWER_SOURCE, 0 }, 166 + { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 }, 167 + { "low-power-mode", PIN_CONFIG_LOW_POWER_MODE, 0 }, 168 + { "output-low", PIN_CONFIG_OUTPUT, 0, }, 169 + { "output-high", PIN_CONFIG_OUTPUT, 1, }, 170 + }; 171 + 172 + /** 173 + * pinconf_generic_parse_dt_config() 174 + * parse the config properties into generic pinconfig values. 175 + * @np: node containing the pinconfig properties 176 + * @configs: array with nconfigs entries containing the generic pinconf values 177 + * @nconfigs: umber of configurations 178 + */ 179 + int pinconf_generic_parse_dt_config(struct device_node *np, 180 + unsigned long **configs, 181 + unsigned int *nconfigs) 182 + { 183 + unsigned long cfg[ARRAY_SIZE(dt_params)]; 184 + unsigned int ncfg = 0; 185 + int ret; 186 + int i; 187 + u32 val; 188 + 189 + if (!np) 190 + return -EINVAL; 191 + 192 + for (i = 0; i < ARRAY_SIZE(dt_params); i++) { 193 + struct pinconf_generic_dt_params *par = &dt_params[i]; 194 + ret = of_property_read_u32(np, par->property, &val); 195 + 196 + /* property not found */ 197 + if (ret == -EINVAL) 198 + continue; 199 + 200 + /* use default value, when no value is specified */ 201 + if (ret) 202 + val = par->default_value; 203 + 204 + pr_debug("found %s with value %u\n", par->property, val); 205 + cfg[ncfg] = pinconf_to_config_packed(par->param, val); 206 + ncfg++; 207 + } 208 + 209 + /* 210 + * Now limit the number of configs to the real number of 211 + * found properties. 212 + */ 213 + *configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL); 214 + if (!*configs) 215 + return -ENOMEM; 216 + 217 + memcpy(*configs, &cfg, ncfg * sizeof(unsigned long)); 218 + *nconfigs = ncfg; 219 + return 0; 220 + } 142 221 #endif
+6
drivers/pinctrl/pinconf.h
··· 123 123 return; 124 124 } 125 125 #endif 126 + 127 + #if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF) 128 + int pinconf_generic_parse_dt_config(struct device_node *np, 129 + unsigned long **configs, 130 + unsigned int *nconfigs); 131 + #endif