|
@@ -24,6 +24,7 @@
|
|
|
#include <linux/of.h>
|
|
|
#include "core.h"
|
|
|
#include "pinconf.h"
|
|
|
+#include "pinctrl-utils.h"
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
|
|
|
@@ -236,4 +237,99 @@ out:
|
|
|
kfree(cfg);
|
|
|
return ret;
|
|
|
}
|
|
|
+
|
|
|
+int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
|
|
+ struct device_node *np, struct pinctrl_map **map,
|
|
|
+ unsigned *reserved_maps, unsigned *num_maps)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ const char *function;
|
|
|
+ struct device *dev = pctldev->dev;
|
|
|
+ unsigned long *configs = NULL;
|
|
|
+ unsigned num_configs = 0;
|
|
|
+ unsigned reserve;
|
|
|
+ struct property *prop;
|
|
|
+ const char *group;
|
|
|
+
|
|
|
+ ret = of_property_read_string(np, "function", &function);
|
|
|
+ if (ret < 0) {
|
|
|
+ /* EINVAL=missing, which is fine since it's optional */
|
|
|
+ if (ret != -EINVAL)
|
|
|
+ dev_err(dev,
|
|
|
+ "could not parse property ti,function\n");
|
|
|
+ function = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(dev, "could not parse node property\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ reserve = 0;
|
|
|
+ if (function != NULL)
|
|
|
+ reserve++;
|
|
|
+ if (num_configs)
|
|
|
+ reserve++;
|
|
|
+ ret = of_property_count_strings(np, "pins");
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(dev, "could not parse property ti,pins\n");
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+ reserve *= ret;
|
|
|
+
|
|
|
+ ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
|
|
|
+ num_maps, reserve);
|
|
|
+ if (ret < 0)
|
|
|
+ goto exit;
|
|
|
+
|
|
|
+ of_property_for_each_string(np, "pins", prop, group) {
|
|
|
+ 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,
|
|
|
+ num_configs, PIN_MAP_TYPE_CONFIGS_PIN);
|
|
|
+ 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,
|
|
|
+ unsigned *num_maps)
|
|
|
+{
|
|
|
+ unsigned reserved_maps;
|
|
|
+ struct device_node *np;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ reserved_maps = 0;
|
|
|
+ *map = NULL;
|
|
|
+ *num_maps = 0;
|
|
|
+
|
|
|
+ for_each_child_of_node(np_config, np) {
|
|
|
+ ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
|
|
|
+ &reserved_maps, num_maps);
|
|
|
+ if (ret < 0) {
|
|
|
+ pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map);
|
|
|
+
|
|
|
#endif
|