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, enum pinctrl_map_type type) { int ret; const char *function; struct device *dev = pctldev->dev; unsigned long *configs = NULL; unsigned num_configs = 0; 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 */ if (ret != -EINVAL) dev_err(dev, "%pOF: could not parse property function\n", np); function = NULL; } ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); if (ret < 0) { dev_err(dev, "%pOF: could not parse node property\n", np); return ret; } reserve = 0; if (function != NULL) reserve++; if (num_configs) reserve++; reserve *= strings_count; ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps, reserve); if (ret < 0) goto exit; of_property_for_each_string(np, subnode_target_type, 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, type); if (ret < 0) goto exit; } } ret = 0; exit: kfree(configs); return ret; }
static int sprd_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **map, unsigned int *num_maps) { struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); const struct sprd_pin_group *grp; unsigned long *configs = NULL; unsigned int num_configs = 0; unsigned int reserved_maps = 0; unsigned int reserve = 0; const char *function; enum pinctrl_map_type type; int ret; grp = sprd_pinctrl_find_group_by_name(pctl, np->name); if (!grp) { dev_err(pctl->dev, "unable to find group for node %s\n", of_node_full_name(np)); return -EINVAL; } ret = of_property_count_strings(np, "pins"); if (ret < 0) return ret; if (ret == 1) type = PIN_MAP_TYPE_CONFIGS_PIN; else type = PIN_MAP_TYPE_CONFIGS_GROUP; ret = of_property_read_string(np, "function", &function); if (ret < 0) { if (ret != -EINVAL) dev_err(pctl->dev, "%s: could not parse property function\n", of_node_full_name(np)); function = NULL; } ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); if (ret < 0) { dev_err(pctl->dev, "%s: could not parse node property\n", of_node_full_name(np)); return ret; } *map = NULL; *num_maps = 0; if (function != NULL) reserve++; if (num_configs) reserve++; ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, num_maps, reserve); if (ret < 0) goto out; if (function) { ret = pinctrl_utils_add_map_mux(pctldev, map, &reserved_maps, num_maps, grp->name, function); if (ret < 0) goto out; } if (num_configs) { const char *group_or_pin; unsigned int pin_id; if (type == PIN_MAP_TYPE_CONFIGS_PIN) { pin_id = grp->pins[0]; group_or_pin = pin_get_name(pctldev, pin_id); } else { group_or_pin = grp->name; } ret = pinctrl_utils_add_map_configs(pctldev, map, &reserved_maps, num_maps, group_or_pin, configs, num_configs, type); } out: kfree(configs); return ret; }