diff options
-rw-r--r-- | drivers/pinctrl/pinctrl-generic.c | 100 | ||||
-rw-r--r-- | 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 3c8e240..ec21d4f 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 a09b242..5436dc4 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) |