diff options
-rw-r--r-- | drivers/pinctrl/pinconf-generic.c | 96 | ||||
-rw-r--r-- | include/linux/pinctrl/pinconf-generic.h | 6 |
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 | |||
241 | int 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 | |||
305 | exit: | ||
306 | kfree(configs); | ||
307 | return ret; | ||
308 | } | ||
309 | EXPORT_SYMBOL_GPL(pinconf_generic_dt_subnode_to_map); | ||
310 | |||
311 | int 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 | } | ||
333 | EXPORT_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 | ||
140 | int 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); | ||
143 | int 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 */ |