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 mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device_node *node, struct pinctrl_map **map, unsigned *reserved_maps, unsigned *num_maps) { struct property *pins; u32 pinfunc, pin, func; int num_pins, num_funcs, maps_per_pin; unsigned long *configs; unsigned int num_configs; bool has_config = 0; int i, err; unsigned reserve = 0; struct mtk_pinctrl_group *grp; struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); pins = of_find_property(node, "pinmux", NULL); if (!pins) { dev_err(pctl->dev, "missing pins property in node %s .\n", node->name); return -EINVAL; } err = pinconf_generic_parse_dt_config(node, pctldev, &configs, &num_configs); if (num_configs) has_config = 1; num_pins = pins->length / sizeof(u32); num_funcs = num_pins; maps_per_pin = 0; if (num_funcs) maps_per_pin++; if (has_config && num_pins >= 1) maps_per_pin++; if (!num_pins || !maps_per_pin) return -EINVAL; reserve = num_pins * maps_per_pin; err = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps, reserve); if (err < 0) goto fail; for (i = 0; i < num_pins; i++) { err = of_property_read_u32_index(node, "pinmux", i, &pinfunc); if (err) goto fail; pin = MTK_GET_PIN_NO(pinfunc); func = MTK_GET_PIN_FUNC(pinfunc); if (pin >= pctl->devdata->npins || func >= ARRAY_SIZE(mtk_gpio_functions)) { dev_err(pctl->dev, "invalid pins value.\n"); err = -EINVAL; goto fail; } grp = mtk_pctrl_find_group_by_pin(pctl, pin); if (!grp) { dev_err(pctl->dev, "unable to match pin %d to group\n", pin); return -EINVAL; } err = mtk_pctrl_dt_node_to_map_func(pctl, pin, func, grp, map, reserved_maps, num_maps); if (err < 0) goto fail; if (has_config) { err = pinctrl_utils_add_map_configs(pctldev, map, reserved_maps, num_maps, grp->name, configs, num_configs, PIN_MAP_TYPE_CONFIGS_GROUP); if (err < 0) goto fail; } } return 0; fail: return err; }
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; }