예제 #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
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;
}
예제 #3
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;
}