Blame view

drivers/pinctrl/pinconf-generic.c 12.2 KB
af873fcec   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
394349f77   Linus Walleij   pinctrl: introduc...
2
3
4
5
6
7
8
  /*
   * Core driver for the generic pin config portions of the pin control subsystem
   *
   * Copyright (C) 2011 ST-Ericsson SA
   * Written on behalf of Linaro for ST-Ericsson
   *
   * Author: Linus Walleij <linus.walleij@linaro.org>
394349f77   Linus Walleij   pinctrl: introduc...
9
10
11
12
13
   */
  
  #define pr_fmt(fmt) "generic pinconfig core: " fmt
  
  #include <linux/kernel.h>
9cfd1724f   Haojian Zhuang   pinctrl: generic:...
14
  #include <linux/module.h>
394349f77   Linus Walleij   pinctrl: introduc...
15
16
17
18
19
20
21
22
  #include <linux/init.h>
  #include <linux/device.h>
  #include <linux/slab.h>
  #include <linux/debugfs.h>
  #include <linux/seq_file.h>
  #include <linux/pinctrl/pinctrl.h>
  #include <linux/pinctrl/pinconf.h>
  #include <linux/pinctrl/pinconf-generic.h>
7db9af4b6   Heiko Stübner   pinctrl: add func...
23
  #include <linux/of.h>
394349f77   Linus Walleij   pinctrl: introduc...
24
25
  #include "core.h"
  #include "pinconf.h"
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
26
  #include "pinctrl-utils.h"
394349f77   Linus Walleij   pinctrl: introduc...
27
28
  
  #ifdef CONFIG_DEBUG_FS
2500bcc9d   Soren Brinkmann   pinctrl: pinconf-...
29
  static const struct pin_config_item conf_items[] = {
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
30
  	PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL, false),
eec450713   Soren Brinkmann   pinctrl: pinconf-...
31
32
  	PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL, false),
  	PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL, false),
eec450713   Soren Brinkmann   pinctrl: pinconf-...
33
  	PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL, false),
7970cb770   Heiko Stübner   pinctrl: add pinc...
34
  	PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
eec450713   Soren Brinkmann   pinctrl: pinconf-...
35
  				"input bias pull to pin specific state", NULL, false),
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
36
  	PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL, false),
eec450713   Soren Brinkmann   pinctrl: pinconf-...
37
38
  	PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false),
  	PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
39
  	PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
eec450713   Soren Brinkmann   pinctrl: pinconf-...
40
  	PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA", true),
c08e7e4c8   Guillaume La Roque   pinctrl: generic:...
41
  	PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH_UA, "output drive strength", "uA", true),
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
42
  	PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec", true),
eec450713   Soren Brinkmann   pinctrl: pinconf-...
43
  	PCONFDUMP(PIN_CONFIG_INPUT_ENABLE, "input enabled", NULL, false),
eec450713   Soren Brinkmann   pinctrl: pinconf-...
44
  	PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL, false),
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
45
  	PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL, false),
eec450713   Soren Brinkmann   pinctrl: pinconf-...
46
  	PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode", true),
425562429   Jacopo Mondi   pinctrl: generic:...
47
  	PCONFDUMP(PIN_CONFIG_OUTPUT_ENABLE, "output enabled", NULL, false),
eec450713   Soren Brinkmann   pinctrl: pinconf-...
48
  	PCONFDUMP(PIN_CONFIG_OUTPUT, "pin output", "level", true),
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
49
  	PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector", true),
6606bc9de   Baolin Wang   pinctrl: Add slee...
50
  	PCONFDUMP(PIN_CONFIG_SLEEP_HARDWARE_STATE, "sleep hardware state", NULL, false),
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
51
  	PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL, true),
e0e1e39de   Linus Walleij   pinctrl: Add skew...
52
  	PCONFDUMP(PIN_CONFIG_SKEW_DELAY, "skew delay", NULL, true),
394349f77   Linus Walleij   pinctrl: introduc...
53
  };
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
54
55
56
57
  static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev,
  				     struct seq_file *s, const char *gname,
  				     unsigned pin,
  				     const struct pin_config_item *items,
a672eb5e2   Masahiro Yamada   pinctrl: pinconf:...
58
  				     int nitems, int *print_sep)
394349f77   Linus Walleij   pinctrl: introduc...
59
  {
394349f77   Linus Walleij   pinctrl: introduc...
60
  	int i;
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
61
  	for (i = 0; i < nitems; i++) {
394349f77   Linus Walleij   pinctrl: introduc...
62
63
64
65
  		unsigned long config;
  		int ret;
  
  		/* We want to check out this parameter */
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
66
67
68
69
70
71
  		config = pinconf_to_config_packed(items[i].param, 0);
  		if (gname)
  			ret = pin_config_group_get(dev_name(pctldev->dev),
  						   gname, &config);
  		else
  			ret = pin_config_get_for_pin(pctldev, pin, &config);
394349f77   Linus Walleij   pinctrl: introduc...
72
73
74
75
76
77
78
  		/* These are legal errors */
  		if (ret == -EINVAL || ret == -ENOTSUPP)
  			continue;
  		if (ret) {
  			seq_printf(s, "ERROR READING CONFIG SETTING %d ", i);
  			continue;
  		}
a672eb5e2   Masahiro Yamada   pinctrl: pinconf:...
79
80
81
82
  		/* comma between multiple configs */
  		if (*print_sep)
  			seq_puts(s, ", ");
  		*print_sep = 1;
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
83
  		seq_puts(s, items[i].display);
394349f77   Linus Walleij   pinctrl: introduc...
84
  		/* Print unit if available */
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
85
  		if (items[i].has_arg) {
eec450713   Soren Brinkmann   pinctrl: pinconf-...
86
87
  			seq_printf(s, " (%u",
  				   pinconf_to_config_argument(config));
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
88
89
  			if (items[i].format)
  				seq_printf(s, " %s)", items[i].format);
eec450713   Soren Brinkmann   pinctrl: pinconf-...
90
91
92
  			else
  				seq_puts(s, ")");
  		}
394349f77   Linus Walleij   pinctrl: introduc...
93
94
  	}
  }
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
95
96
97
98
99
100
101
102
103
104
105
106
107
  /**
   * pinconf_generic_dump_pins - Print information about pin or group of pins
   * @pctldev:	Pincontrol device
   * @s:		File to print to
   * @gname:	Group name specifying pins
   * @pin:	Pin number specyfying pin
   *
   * Print the pinconf configuration for the requested pin(s) to @s. Pins can be
   * specified either by pin using @pin or by group using @gname. Only one needs
   * to be specified the other can be NULL/0.
   */
  void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev, struct seq_file *s,
  			       const char *gname, unsigned pin)
394349f77   Linus Walleij   pinctrl: introduc...
108
109
  {
  	const struct pinconf_ops *ops = pctldev->desc->confops;
a672eb5e2   Masahiro Yamada   pinctrl: pinconf:...
110
  	int print_sep = 0;
394349f77   Linus Walleij   pinctrl: introduc...
111
112
113
  
  	if (!ops->is_generic)
  		return;
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
114
115
  	/* generic parameters */
  	pinconf_generic_dump_one(pctldev, s, gname, pin, conf_items,
a672eb5e2   Masahiro Yamada   pinctrl: pinconf:...
116
  				 ARRAY_SIZE(conf_items), &print_sep);
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
117
  	/* driver-specific parameters */
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
118
119
  	if (pctldev->desc->num_custom_params &&
  	    pctldev->desc->custom_conf_items)
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
120
  		pinconf_generic_dump_one(pctldev, s, gname, pin,
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
121
  					 pctldev->desc->custom_conf_items,
a672eb5e2   Masahiro Yamada   pinctrl: pinconf:...
122
123
  					 pctldev->desc->num_custom_params,
  					 &print_sep);
394349f77   Linus Walleij   pinctrl: introduc...
124
  }
9cfd1724f   Haojian Zhuang   pinctrl: generic:...
125
126
127
128
  void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
  				 struct seq_file *s, unsigned long config)
  {
  	int i;
b6465424a   Sachin Kamat   pinctrl: generic:...
129
  	for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
9cfd1724f   Haojian Zhuang   pinctrl: generic:...
130
131
132
133
134
  		if (pinconf_to_config_param(config) != conf_items[i].param)
  			continue;
  		seq_printf(s, "%s: 0x%x", conf_items[i].display,
  			   pinconf_to_config_argument(config));
  	}
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
135

f684e4ac9   Linus Walleij   pinctrl: pinconf-...
136
137
  	if (!pctldev->desc->num_custom_params ||
  	    !pctldev->desc->custom_conf_items)
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
138
  		return;
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
139
140
141
  	for (i = 0; i < pctldev->desc->num_custom_params; i++) {
  		if (pinconf_to_config_param(config) !=
  		    pctldev->desc->custom_conf_items[i].param)
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
142
  			continue;
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
143
144
145
  		seq_printf(s, "%s: 0x%x",
  				pctldev->desc->custom_conf_items[i].display,
  				pinconf_to_config_argument(config));
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
146
  	}
9cfd1724f   Haojian Zhuang   pinctrl: generic:...
147
148
  }
  EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
394349f77   Linus Walleij   pinctrl: introduc...
149
  #endif
7db9af4b6   Heiko Stübner   pinctrl: add func...
150
151
  
  #ifdef CONFIG_OF
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
152
  static const struct pinconf_generic_params dt_params[] = {
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
153
  	{ "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
7db9af4b6   Heiko Stübner   pinctrl: add func...
154
155
  	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
  	{ "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
9ee1f7d26   Heiko Stübner   pinctrl: clarify ...
156
  	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
9ee1f7d26   Heiko Stübner   pinctrl: clarify ...
157
  	{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
158
  	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
7db9af4b6   Heiko Stübner   pinctrl: add func...
159
160
  	{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
  	{ "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
161
  	{ "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
7db9af4b6   Heiko Stübner   pinctrl: add func...
162
  	{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
c08e7e4c8   Guillaume La Roque   pinctrl: generic:...
163
  	{ "drive-strength-microamp", PIN_CONFIG_DRIVE_STRENGTH_UA, 0 },
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
164
  	{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
8ba3f4d00   Sherman Yin   pinctrl: Adds sle...
165
  	{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
166
  	{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
69c308e2b   Masahiro Yamada   pinctrl: pinconf-...
167
  	{ "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
7db9af4b6   Heiko Stübner   pinctrl: add func...
168
  	{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
169
  	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
9ee1f7d26   Heiko Stübner   pinctrl: clarify ...
170
  	{ "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
171
  	{ "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
425562429   Jacopo Mondi   pinctrl: generic:...
172
173
  	{ "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 },
  	{ "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
7db9af4b6   Heiko Stübner   pinctrl: add func...
174
  	{ "output-high", PIN_CONFIG_OUTPUT, 1, },
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
175
176
  	{ "output-low", PIN_CONFIG_OUTPUT, 0, },
  	{ "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
6606bc9de   Baolin Wang   pinctrl: Add slee...
177
  	{ "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 },
3c4b23dd7   Masahiro Yamada   pinctrl: pinconf-...
178
  	{ "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
e0e1e39de   Linus Walleij   pinctrl: Add skew...
179
  	{ "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 },
7db9af4b6   Heiko Stübner   pinctrl: add func...
180
181
182
  };
  
  /**
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
183
   * parse_dt_cfg() - Parse DT pinconf parameters
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
184
   * @np:	DT node
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
185
   * @params:	Array of describing generic parameters
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
186
187
188
189
190
   * @count:	Number of entries in @params
   * @cfg:	Array of parsed config options
   * @ncfg:	Number of entries in @cfg
   *
   * Parse the config options described in @params from @np and puts the result
3ec440e33   Andy Shevchenko   pinctrl: Fix spel...
191
   * in @cfg. @cfg does not need to be empty, entries are added beginning at
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
192
193
194
195
   * @ncfg. @ncfg is updated to reflect the number of entries after parsing. @cfg
   * needs to have enough memory allocated to hold all possible entries.
   */
  static void parse_dt_cfg(struct device_node *np,
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
196
  			 const struct pinconf_generic_params *params,
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
197
198
199
200
201
202
203
204
  			 unsigned int count, unsigned long *cfg,
  			 unsigned int *ncfg)
  {
  	int i;
  
  	for (i = 0; i < count; i++) {
  		u32 val;
  		int ret;
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
205
  		const struct pinconf_generic_params *par = &params[i];
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  
  		ret = of_property_read_u32(np, par->property, &val);
  
  		/* property not found */
  		if (ret == -EINVAL)
  			continue;
  
  		/* use default value, when no value is specified */
  		if (ret)
  			val = par->default_value;
  
  		pr_debug("found %s with value %u
  ", par->property, val);
  		cfg[*ncfg] = pinconf_to_config_packed(par->param, val);
  		(*ncfg)++;
  	}
  }
  
  /**
7db9af4b6   Heiko Stübner   pinctrl: add func...
225
226
227
228
   * pinconf_generic_parse_dt_config()
   * parse the config properties into generic pinconfig values.
   * @np: node containing the pinconfig properties
   * @configs: array with nconfigs entries containing the generic pinconf values
d9ac5e25f   Yingjoe Chen   pinctrl: update d...
229
   *           must be freed when no longer necessary.
7db9af4b6   Heiko Stübner   pinctrl: add func...
230
231
232
   * @nconfigs: umber of configurations
   */
  int pinconf_generic_parse_dt_config(struct device_node *np,
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
233
  				    struct pinctrl_dev *pctldev,
7db9af4b6   Heiko Stübner   pinctrl: add func...
234
235
236
  				    unsigned long **configs,
  				    unsigned int *nconfigs)
  {
6abab2d4b   Heiko Stübner   pinctrl: dynamica...
237
  	unsigned long *cfg;
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
238
  	unsigned int max_cfg, ncfg = 0;
7db9af4b6   Heiko Stübner   pinctrl: add func...
239
  	int ret;
7db9af4b6   Heiko Stübner   pinctrl: add func...
240
241
242
  
  	if (!np)
  		return -EINVAL;
6abab2d4b   Heiko Stübner   pinctrl: dynamica...
243
  	/* allocate a temporary array big enough to hold one of each option */
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
244
245
  	max_cfg = ARRAY_SIZE(dt_params);
  	if (pctldev)
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
246
  		max_cfg += pctldev->desc->num_custom_params;
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
247
  	cfg = kcalloc(max_cfg, sizeof(*cfg), GFP_KERNEL);
6abab2d4b   Heiko Stübner   pinctrl: dynamica...
248
249
  	if (!cfg)
  		return -ENOMEM;
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
250
  	parse_dt_cfg(np, dt_params, ARRAY_SIZE(dt_params), cfg, &ncfg);
f684e4ac9   Linus Walleij   pinctrl: pinconf-...
251
252
253
254
  	if (pctldev && pctldev->desc->num_custom_params &&
  		pctldev->desc->custom_params)
  		parse_dt_cfg(np, pctldev->desc->custom_params,
  			     pctldev->desc->num_custom_params, cfg, &ncfg);
7db9af4b6   Heiko Stübner   pinctrl: add func...
255

6abab2d4b   Heiko Stübner   pinctrl: dynamica...
256
  	ret = 0;
e4a8844c0   Heiko Stübner   pinctrl: handle z...
257
258
259
260
  	/* no configs found at all */
  	if (ncfg == 0) {
  		*configs = NULL;
  		*nconfigs = 0;
6abab2d4b   Heiko Stübner   pinctrl: dynamica...
261
  		goto out;
e4a8844c0   Heiko Stübner   pinctrl: handle z...
262
  	}
7db9af4b6   Heiko Stübner   pinctrl: add func...
263
264
265
266
  	/*
  	 * Now limit the number of configs to the real number of
  	 * found properties.
  	 */
db388dfb9   Benoit Taine   pinctrl: pinconf-...
267
  	*configs = kmemdup(cfg, ncfg * sizeof(unsigned long), GFP_KERNEL);
6abab2d4b   Heiko Stübner   pinctrl: dynamica...
268
269
270
271
  	if (!*configs) {
  		ret = -ENOMEM;
  		goto out;
  	}
7db9af4b6   Heiko Stübner   pinctrl: add func...
272

7db9af4b6   Heiko Stübner   pinctrl: add func...
273
  	*nconfigs = ncfg;
6abab2d4b   Heiko Stübner   pinctrl: dynamica...
274
275
276
277
  
  out:
  	kfree(cfg);
  	return ret;
7db9af4b6   Heiko Stübner   pinctrl: add func...
278
  }
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
279
280
281
  
  int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
  		struct device_node *np, struct pinctrl_map **map,
3287c2408   Laxman Dewangan   pinctrl: utils : ...
282
283
  		unsigned *reserved_maps, unsigned *num_maps,
  		enum pinctrl_map_type type)
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
284
285
286
287
288
289
  {
  	int ret;
  	const char *function;
  	struct device *dev = pctldev->dev;
  	unsigned long *configs = NULL;
  	unsigned num_configs = 0;
c7289500e   Baruch Siach   pinctrl: pinconf-...
290
  	unsigned reserve, strings_count;
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
291
292
  	struct property *prop;
  	const char *group;
31c89c959   Soren Brinkmann   pinctrl: pinconf-...
293
  	const char *subnode_target_type = "pins";
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
294

c7289500e   Baruch Siach   pinctrl: pinconf-...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  	ret = of_property_count_strings(np, "pins");
  	if (ret < 0) {
  		ret = of_property_count_strings(np, "groups");
  		if (ret < 0)
  			/* skip this node; may contain config child nodes */
  			return 0;
  		if (type == PIN_MAP_TYPE_INVALID)
  			type = PIN_MAP_TYPE_CONFIGS_GROUP;
  		subnode_target_type = "groups";
  	} else {
  		if (type == PIN_MAP_TYPE_INVALID)
  			type = PIN_MAP_TYPE_CONFIGS_PIN;
  	}
  	strings_count = ret;
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
309
310
311
312
  	ret = of_property_read_string(np, "function", &function);
  	if (ret < 0) {
  		/* EINVAL=missing, which is fine since it's optional */
  		if (ret != -EINVAL)
f5292d06c   Rob Herring   pinctrl: Convert ...
313
314
315
  			dev_err(dev, "%pOF: could not parse property function
  ",
  				np);
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
316
317
  		function = NULL;
  	}
dd4d01f7b   Soren Brinkmann   pinctrl: pinconf-...
318
319
  	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
  					      &num_configs);
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
320
  	if (ret < 0) {
f5292d06c   Rob Herring   pinctrl: Convert ...
321
322
  		dev_err(dev, "%pOF: could not parse node property
  ", np);
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
323
324
325
326
327
328
329
330
  		return ret;
  	}
  
  	reserve = 0;
  	if (function != NULL)
  		reserve++;
  	if (num_configs)
  		reserve++;
31c89c959   Soren Brinkmann   pinctrl: pinconf-...
331

c7289500e   Baruch Siach   pinctrl: pinconf-...
332
  	reserve *= strings_count;
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
333
334
335
336
337
  
  	ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
  			num_maps, reserve);
  	if (ret < 0)
  		goto exit;
31c89c959   Soren Brinkmann   pinctrl: pinconf-...
338
  	of_property_for_each_string(np, subnode_target_type, prop, group) {
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
339
340
341
342
343
344
345
346
347
348
349
  		if (function) {
  			ret = pinctrl_utils_add_map_mux(pctldev, map,
  					reserved_maps, num_maps, group,
  					function);
  			if (ret < 0)
  				goto exit;
  		}
  
  		if (num_configs) {
  			ret = pinctrl_utils_add_map_configs(pctldev, map,
  					reserved_maps, num_maps, group, configs,
3287c2408   Laxman Dewangan   pinctrl: utils : ...
350
  					num_configs, type);
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
351
352
353
354
355
356
357
358
359
360
361
362
363
364
  			if (ret < 0)
  				goto exit;
  		}
  	}
  	ret = 0;
  
  exit:
  	kfree(configs);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(pinconf_generic_dt_subnode_to_map);
  
  int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
  		struct device_node *np_config, struct pinctrl_map **map,
3287c2408   Laxman Dewangan   pinctrl: utils : ...
365
  		unsigned *num_maps, enum pinctrl_map_type type)
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
366
367
368
369
370
371
372
373
  {
  	unsigned reserved_maps;
  	struct device_node *np;
  	int ret;
  
  	reserved_maps = 0;
  	*map = NULL;
  	*num_maps = 0;
c7289500e   Baruch Siach   pinctrl: pinconf-...
374
375
376
377
  	ret = pinconf_generic_dt_subnode_to_map(pctldev, np_config, map,
  						&reserved_maps, num_maps, type);
  	if (ret < 0)
  		goto exit;
e06c2ee5f   Laxman Dewangan   pinctrl: generic:...
378
  	for_each_available_child_of_node(np_config, np) {
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
379
  		ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
3287c2408   Laxman Dewangan   pinctrl: utils : ...
380
  					&reserved_maps, num_maps, type);
c7289500e   Baruch Siach   pinctrl: pinconf-...
381
382
  		if (ret < 0)
  			goto exit;
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
383
384
  	}
  	return 0;
c7289500e   Baruch Siach   pinctrl: pinconf-...
385
386
  
  exit:
d32f7fd3b   Irina Tirdea   pinctrl: Rename p...
387
  	pinctrl_utils_free_map(pctldev, *map, *num_maps);
c7289500e   Baruch Siach   pinctrl: pinconf-...
388
  	return ret;
e81c8f18a   Laxman Dewangan   pinctrl: pinconf-...
389
390
  }
  EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map);
8dfebf57b   Jon Hunter   pinctrl: pinconf:...
391
392
393
394
395
396
397
  void pinconf_generic_dt_free_map(struct pinctrl_dev *pctldev,
  				 struct pinctrl_map *map,
  				 unsigned num_maps)
  {
  	pinctrl_utils_free_map(pctldev, map, num_maps);
  }
  EXPORT_SYMBOL_GPL(pinconf_generic_dt_free_map);
7db9af4b6   Heiko Stübner   pinctrl: add func...
398
  #endif