aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/pinconf-generic.c96
-rw-r--r--include/linux/pinctrl/pinconf-generic.h6
2 files changed, 102 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 8594f033ac21..d9536caa9c41 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -24,6 +24,7 @@
24#include <linux/of.h> 24#include <linux/of.h>
25#include "core.h" 25#include "core.h"
26#include "pinconf.h" 26#include "pinconf.h"
27#include "pinctrl-utils.h"
27 28
28#ifdef CONFIG_DEBUG_FS 29#ifdef CONFIG_DEBUG_FS
29 30
@@ -236,4 +237,99 @@ out:
236 kfree(cfg); 237 kfree(cfg);
237 return ret; 238 return ret;
238} 239}
240
241int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
242 struct device_node *np, struct pinctrl_map **map,
243 unsigned *reserved_maps, unsigned *num_maps)
244{
245 int ret;
246 const char *function;
247 struct device *dev = pctldev->dev;
248 unsigned long *configs = NULL;
249 unsigned num_configs = 0;
250 unsigned reserve;
251 struct property *prop;
252 const char *group;
253
254 ret = of_property_read_string(np, "function", &function);
255 if (ret < 0) {
256 /* EINVAL=missing, which is fine since it's optional */
257 if (ret != -EINVAL)
258 dev_err(dev,
259 "could not parse property ti,function\n");
260 function = NULL;
261 }
262
263 ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
264 if (ret < 0) {
265 dev_err(dev, "could not parse node property\n");
266 return ret;
267 }
268
269 reserve = 0;
270 if (function != NULL)
271 reserve++;
272 if (num_configs)
273 reserve++;
274 ret = of_property_count_strings(np, "pins");
275 if (ret < 0) {
276 dev_err(dev, "could not parse property ti,pins\n");
277 goto exit;
278 }
279 reserve *= ret;
280
281 ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
282 num_maps, reserve);
283 if (ret < 0)
284 goto exit;
285
286 of_property_for_each_string(np, "pins", prop, group) {
287 if (function) {
288 ret = pinctrl_utils_add_map_mux(pctldev, map,
289 reserved_maps, num_maps, group,
290 function);
291 if (ret < 0)
292 goto exit;
293 }
294
295 if (num_configs) {
296 ret = pinctrl_utils_add_map_configs(pctldev, map,
297 reserved_maps, num_maps, group, configs,
298 num_configs, PIN_MAP_TYPE_CONFIGS_PIN);
299 if (ret < 0)
300 goto exit;
301 }
302 }
303 ret = 0;
304
305exit:
306 kfree(configs);
307 return ret;
308}
309EXPORT_SYMBOL_GPL(pinconf_generic_dt_subnode_to_map);
310
311int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
312 struct device_node *np_config, struct pinctrl_map **map,
313 unsigned *num_maps)
314{
315 unsigned reserved_maps;
316 struct device_node *np;
317 int ret;
318
319 reserved_maps = 0;
320 *map = NULL;
321 *num_maps = 0;
322
323 for_each_child_of_node(np_config, np) {
324 ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
325 &reserved_maps, num_maps);
326 if (ret < 0) {
327 pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
328 return ret;
329 }
330 }
331 return 0;
332}
333EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map);
334
239#endif 335#endif
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
index bf7e989abcb5..a472b93292a3 100644
--- a/include/linux/pinctrl/pinconf-generic.h
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -137,6 +137,12 @@ static inline unsigned long pinconf_to_config_packed(enum pin_config_param param
137 return PIN_CONF_PACKED(param, argument); 137 return PIN_CONF_PACKED(param, argument);
138} 138}
139 139
140int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
141 struct device_node *np, struct pinctrl_map **map,
142 unsigned *reserved_maps, unsigned *num_maps);
143int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
144 struct device_node *np_config, struct pinctrl_map **map,
145 unsigned *num_maps);
140#endif /* CONFIG_GENERIC_PINCONF */ 146#endif /* CONFIG_GENERIC_PINCONF */
141 147
142#endif /* __LINUX_PINCTRL_PINCONF_GENERIC_H */ 148#endif /* __LINUX_PINCTRL_PINCONF_GENERIC_H */