diff -drupN a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c --- a/drivers/pinctrl/pinconf.c 2018-08-06 17:23:04.000000000 +0300 +++ b/drivers/pinctrl/pinconf.c 2022-06-12 05:28:14.000000000 +0300 @@ -69,6 +69,99 @@ int pin_config_get_for_pin(struct pinctr return ops->pin_config_get(pctldev, pin, config); } +/** + * pin_config_get() - get the configuration of a single pin parameter + * @dev_name: name of the pin controller device for this pin + * @name: name of the pin to get the config for + * @config: the config pointed to by this argument will be filled in with the + * current pin state, it can be used directly by drivers as a numeral, or + * it can be dereferenced to any struct. + */ +int pin_config_get(const char *dev_name, const char *name, + unsigned long *config) +{ + struct pinctrl_dev *pctldev; + int pin; + + pctldev = get_pinctrl_dev_from_devname(dev_name); + if (!pctldev) { + pin = -EINVAL; + return pin; + } + + mutex_lock(&pctldev->mutex); + + pin = pin_get_from_name(pctldev, name); + if (pin < 0) + goto unlock; + + pin = pin_config_get_for_pin(pctldev, pin, config); + +unlock: + mutex_unlock(&pctldev->mutex); + return pin; +} +EXPORT_SYMBOL(pin_config_get); + +static int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long config) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + int ret; + + if (!ops || !ops->pin_config_set) { + dev_err(pctldev->dev, "cannot configure pin, missing " + "config function in driver\n"); + return -EINVAL; + } + + ret = ops->pin_config_set(pctldev, pin, (unsigned long *)config, 1); + if (ret) { + dev_err(pctldev->dev, + "unable to set pin configuration on pin %d\n", pin); + return ret; + } + + return 0; +} + +/** + * pin_config_set() - set the configuration of a single pin parameter + * @dev_name: name of pin controller device for this pin + * @name: name of the pin to set the config for + * @config: the config in this argument will contain the desired pin state, it + * can be used directly by drivers as a numeral, or it can be dereferenced + * to any struct. + */ +int pin_config_set(const char *dev_name, const char *name, + unsigned long config) +{ + struct pinctrl_dev *pctldev; + int pin, ret; + + pctldev = get_pinctrl_dev_from_devname(dev_name); + if (!pctldev) { + ret = -EINVAL; + return ret; + } + + mutex_lock(&pctldev->mutex); + + pin = pin_get_from_name(pctldev, name); + if (pin < 0) { + ret = pin; + goto unlock; + } + + ret = pin_config_set_for_pin(pctldev, pin, config); + +unlock: + mutex_unlock(&pctldev->mutex); + return ret; +} +EXPORT_SYMBOL(pin_config_set); + + int pin_config_group_get(const char *dev_name, const char *pin_group, unsigned long *config) { @@ -258,7 +351,8 @@ void pinconf_show_setting(struct seq_fil case PIN_MAP_TYPE_CONFIGS_PIN: desc = pin_desc_get(setting->pctldev, setting->data.configs.group_or_pin); - seq_printf(s, "pin %s (%d)", desc->name, + seq_printf(s, "pin %s (%d)", + desc->name ? desc->name : "unnamed", setting->data.configs.group_or_pin); break; case PIN_MAP_TYPE_CONFIGS_GROUP: @@ -310,7 +404,8 @@ static int pinconf_pins_show(struct seq_ if (desc == NULL) continue; - seq_printf(s, "pin %d (%s): ", pin, desc->name); + seq_printf(s, "pin %d (%s):", pin, + desc->name ? desc->name : "unnamed"); pinconf_dump_pin(pctldev, s, pin); @@ -347,7 +442,7 @@ static int pinconf_groups_show(struct se while (selector < ngroups) { const char *gname = pctlops->get_group_name(pctldev, selector); - seq_printf(s, "%u (%s): ", selector, gname); + seq_printf(s, "%u (%s):", selector, gname); pinconf_dump_group(pctldev, s, selector, gname); seq_printf(s, "\n");