예제 #1
0
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;
}
예제 #2
0
파일: pinctrl-sprd.c 프로젝트: Lyude/linux
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;
}