diff options
author | Baruch Siach <baruch@tkos.co.il> | 2015-03-19 23:17:41 +0300 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-03-27 11:51:22 +0300 |
commit | c7289500e29df3441a7167861424e7d77a167dfb (patch) | |
tree | 25c4c1ee3df0261f92281040cbdedf6326803cb3 | |
parent | 12149a20b86330d6eac71edaad0357541abdcd05 (diff) | |
download | linux-c7289500e29df3441a7167861424e7d77a167dfb.tar.xz |
pinctrl: pinconf-generic: scan also referenced phandle node
Make pinconf_generic_dt_node_to_map() also scan the dt pin configuration node
directly referenced by phandle, not only its child nodes.
The "parent scan" feature needs a few other changes:
* Move the pinconf_generic_dt_node_to_map() error handling code to a common
place, under the 'exit' label.
* Move the pins/groups strings count earlier in
pinconf_generic_dt_subnode_to_map(), to allow us to bail out early when
these properties are missing or wrong
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/pinconf-generic.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 4db92f64b4de..b5fbfb3584d9 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -283,11 +283,26 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device *dev = pctldev->dev; unsigned long *configs = NULL; unsigned num_configs = 0; - unsigned reserve; + unsigned reserve, strings_count; struct property *prop; const char *group; const char *subnode_target_type = "pins"; + 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; + ret = of_property_read_string(np, "function", &function); if (ret < 0) { /* EINVAL=missing, which is fine since it's optional */ @@ -309,21 +324,7 @@ int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, if (num_configs) reserve++; - ret = of_property_count_strings(np, "pins"); - if (ret < 0) { - ret = of_property_count_strings(np, "groups"); - if (ret < 0) { - dev_err(dev, "could not parse property pins/groups\n"); - goto exit; - } - 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; - } - reserve *= ret; + reserve *= strings_count; ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps, reserve); @@ -367,15 +368,22 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev, *map = NULL; *num_maps = 0; + ret = pinconf_generic_dt_subnode_to_map(pctldev, np_config, map, + &reserved_maps, num_maps, type); + if (ret < 0) + goto exit; + for_each_child_of_node(np_config, np) { ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps, type); - if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); - return ret; - } + if (ret < 0) + goto exit; } return 0; + +exit: + pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); + return ret; } EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map); |