[PATCH 1/8] pinctrl: Add new function pinctrl_generic_set_state_prefix()

Stefan Roese sr at denx.de
Thu Jul 28 08:25:37 CEST 2022


On 25.07.22 13:56, Pali Rohár wrote:
> This new function pinctrl_generic_set_state_prefix() behaves like
> pinctrl_generic_set_state() but it takes third string argument which is
> used as the prefix for each device tree string property.
> 
> This is needed for Marvell pinctrl drivers, becase Linux device tree files
> have pinmux properties prefixed by "marvell," string.
> 
> This change allows to use generic U-Boot pinctrl functions for Armada 38x
> pinctrl driver without need to copy+paste of the majority U-Boot pinctrl
> code.
> 
> Signed-off-by: Pali Rohár <pali at kernel.org>

Reviewed-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan

> ---
>   drivers/pinctrl/pinctrl-generic.c | 100 +++++++++++++++++++++++++-----
>   include/dm/pinctrl.h              |   2 +
>   2 files changed, 85 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
> index 3c8e24088ce4..ec21d4ff8387 100644
> --- a/drivers/pinctrl/pinctrl-generic.c
> +++ b/drivers/pinctrl/pinctrl-generic.c
> @@ -234,6 +234,24 @@ enum pinmux_subnode_type {
>   	PST_PINMUX,
>   };
>   
> +static const char *alloc_name_with_prefix(const char *name, const char *prefix)
> +{
> +	if (prefix) {
> +		char *name_with_prefix = malloc(strlen(prefix) + sizeof("pins"));
> +		if (name_with_prefix)
> +			sprintf(name_with_prefix, "%s%s", prefix, name);
> +		return name_with_prefix;
> +	} else {
> +		return name;
> +	}
> +}
> +
> +static void free_name_with_prefix(const char *name_with_prefix, const char *prefix)
> +{
> +	if (prefix)
> +		free((char *)name_with_prefix);
> +}
> +
>   /**
>    * pinctrl_generic_set_state_one() - set state for a certain pin/group
>    * Apply all pin multiplexing and pin configurations specified by @config
> @@ -248,9 +266,11 @@ enum pinmux_subnode_type {
>    */
>   static int pinctrl_generic_set_state_one(struct udevice *dev,
>   					 struct udevice *config,
> +					 const char *prefix,
>   					 enum pinmux_subnode_type subnode_type,
>   					 unsigned selector)
>   {
> +	const char *function_propname;
>   	const char *propname;
>   	const void *value;
>   	struct ofprop property;
> @@ -259,18 +279,26 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
>   
>   	assert(subnode_type != PST_NONE);
>   
> +	function_propname = alloc_name_with_prefix("function", prefix);
> +	if (!function_propname)
> +		return -ENOMEM;
> +
>   	dev_for_each_property(property, config) {
>   		value = dev_read_prop_by_prop(&property, &propname, &len);
> -		if (!value)
> +		if (!value) {
> +			free_name_with_prefix(function_propname, prefix);
>   			return -EINVAL;
> +		}
>   
>   		/* pinmux subnodes already have their muxing set */
>   		if (subnode_type != PST_PINMUX &&
> -		    !strcmp(propname, "function")) {
> +		    !strcmp(propname, function_propname)) {
>   			func_selector = pinmux_func_name_to_selector(dev,
>   								     value);
> -			if (func_selector < 0)
> +			if (func_selector < 0) {
> +				free_name_with_prefix(function_propname, prefix);
>   				return func_selector;
> +			}
>   			ret = pinmux_enable_setting(dev,
>   						    subnode_type == PST_GROUP,
>   						    selector,
> @@ -291,10 +319,13 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
>   						     selector, param, arg);
>   		}
>   
> -		if (ret)
> +		if (ret) {
> +			free_name_with_prefix(function_propname, prefix);
>   			return ret;
> +		}
>   	}
>   
> +	free_name_with_prefix(function_propname, prefix);
>   	return 0;
>   }
>   
> @@ -309,20 +340,34 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
>    */
>   static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev,
>   								 struct udevice *config,
> +								 const char *prefix,
>   								 int *count)
>   {
>   	const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
> +	const char *propname;
>   
> -	*count = dev_read_string_count(config, "pins");
> +	propname = alloc_name_with_prefix("pins", prefix);
> +	if (!propname)
> +		return -ENOMEM;
> +	*count = dev_read_string_count(config, propname);
> +	free_name_with_prefix(propname, prefix);
>   	if (*count >= 0)
>   		return PST_PIN;
>   
> -	*count = dev_read_string_count(config, "groups");
> +	propname = alloc_name_with_prefix("groups", prefix);
> +	if (!propname)
> +		return -ENOMEM;
> +	*count = dev_read_string_count(config, propname);
> +	free_name_with_prefix(propname, prefix);
>   	if (*count >= 0)
>   		return PST_GROUP;
>   
>   	if (ops->pinmux_property_set) {
> -		*count = dev_read_size(config, "pinmux");
> +		propname = alloc_name_with_prefix("pinmux", prefix);
> +		if (!propname)
> +			return -ENOMEM;
> +		*count = dev_read_size(config, propname);
> +		free_name_with_prefix(propname, prefix);
>   		if (*count >= 0 && !(*count % sizeof(u32))) {
>   			*count /= sizeof(u32);
>   			return PST_PINMUX;
> @@ -338,23 +383,30 @@ static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice
>    *
>    * @dev: pin controller device
>    * @config: pseudo device pointing to config node
> + * @prefix: device tree property prefix (e.g. vendor specific)
>    * @return: 0 on success, or negative error code on failure
>    */
>   static int pinctrl_generic_set_state_subnode(struct udevice *dev,
> -					     struct udevice *config)
> +					     struct udevice *config,
> +					     const char *prefix)
>   {
>   	enum pinmux_subnode_type subnode_type;
> +	const char *propname;
>   	const char *name;
>   	int count, selector, i, ret, scratch;
>   	const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */
>   
> -	subnode_type = pinctrl_generic_get_subnode_type(dev, config, &count);
> +	subnode_type = pinctrl_generic_get_subnode_type(dev, config, prefix, &count);
>   
>   	debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name,
>   	      count);
>   
>   	if (subnode_type == PST_PINMUX) {
> -		pinmux_groups = dev_read_prop(config, "pinmux", &scratch);
> +		propname = alloc_name_with_prefix("pinmux", prefix);
> +		if (!propname)
> +			return -ENOMEM;
> +		pinmux_groups = dev_read_prop(config, propname, &scratch);
> +		free_name_with_prefix(propname, prefix);
>   		if (!pinmux_groups)
>   			return -EINVAL;
>   	}
> @@ -362,13 +414,21 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
>   	for (i = 0; i < count; i++) {
>   		switch (subnode_type) {
>   		case PST_PIN:
> -			ret = dev_read_string_index(config, "pins", i, &name);
> +			propname = alloc_name_with_prefix("pins", prefix);
> +			if (!propname)
> +				return -ENOMEM;
> +			ret = dev_read_string_index(config, propname, i, &name);
> +			free_name_with_prefix(propname, prefix);
>   			if (ret)
>   				return ret;
>   			selector = pinctrl_pin_name_to_selector(dev, name);
>   			break;
>   		case PST_GROUP:
> -			ret = dev_read_string_index(config, "groups", i, &name);
> +			propname = alloc_name_with_prefix("groups", prefix);
> +			if (!propname)
> +				return -ENOMEM;
> +			ret = dev_read_string_index(config, propname, i, &name);
> +			free_name_with_prefix(propname, prefix);
>   			if (ret)
>   				return ret;
>   			selector = pinctrl_group_name_to_selector(dev, name);
> @@ -390,8 +450,8 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
>   		if (selector < 0)
>   			return selector;
>   
> -		ret = pinctrl_generic_set_state_one(dev, config, subnode_type,
> -						    selector);
> +		ret = pinctrl_generic_set_state_one(dev, config, prefix,
> +						    subnode_type, selector);
>   		if (ret)
>   			return ret;
>   	}
> @@ -399,22 +459,28 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
>   	return 0;
>   }
>   
> -int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config)
> +int pinctrl_generic_set_state_prefix(struct udevice *dev, struct udevice *config,
> +				     const char *prefix)
>   {
>   	struct udevice *child;
>   	int ret;
>   
> -	ret = pinctrl_generic_set_state_subnode(dev, config);
> +	ret = pinctrl_generic_set_state_subnode(dev, config, prefix);
>   	if (ret)
>   		return ret;
>   
>   	for (device_find_first_child(config, &child);
>   	     child;
>   	     device_find_next_child(&child)) {
> -		ret = pinctrl_generic_set_state_subnode(dev, child);
> +		ret = pinctrl_generic_set_state_subnode(dev, child, prefix);
>   		if (ret)
>   			return ret;
>   	}
>   
>   	return 0;
>   }
> +
> +int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config)
> +{
> +	return pinctrl_generic_set_state_prefix(dev, config, NULL);
> +}
> diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h
> index a09b242fd990..5436dc4a9a71 100644
> --- a/include/dm/pinctrl.h
> +++ b/include/dm/pinctrl.h
> @@ -491,6 +491,8 @@ enum pin_config_param {
>    * Return: 0 on success, or negative error code on failure
>    */
>   int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config);
> +int pinctrl_generic_set_state_prefix(struct udevice *pctldev, struct udevice *config,
> +				     const char *prefix);
>   #else
>   static inline int pinctrl_generic_set_state(struct udevice *pctldev,
>   					    struct udevice *config)

Viele Grüße,
Stefan Roese

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de


More information about the U-Boot mailing list