diff options
Diffstat (limited to 'drivers/pinctrl/pinconf.c')
-rw-r--r-- | drivers/pinctrl/pinconf.c | 233 |
1 files changed, 44 insertions, 189 deletions
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 694c3ace4520..596a2522a6b1 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -35,7 +35,9 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev) return -EINVAL; } /* We have to be able to config the pins in SOME way */ - if (!ops->pin_config_set && !ops->pin_config_group_set) { + if (!ops->pin_config_set && !ops->pin_config_group_set + && !ops->pin_config_set_bulk + && !ops->pin_config_group_set_bulk) { dev_err(pctldev->dev, "pinconf has to be able to set a pins config\n"); return -EINVAL; @@ -75,98 +77,6 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, 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 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, config); - 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) { @@ -204,88 +114,6 @@ unlock: mutex_unlock(&pctldev->mutex); return ret; } -EXPORT_SYMBOL(pin_config_group_get); - -int pin_config_group_set(const char *dev_name, const char *pin_group, - unsigned long config) -{ - struct pinctrl_dev *pctldev; - const struct pinconf_ops *ops; - const struct pinctrl_ops *pctlops; - int selector; - const unsigned *pins; - unsigned num_pins; - int ret; - int i; - - pctldev = get_pinctrl_dev_from_devname(dev_name); - if (!pctldev) { - ret = -EINVAL; - return ret; - } - - mutex_lock(&pctldev->mutex); - - ops = pctldev->desc->confops; - pctlops = pctldev->desc->pctlops; - - if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) { - dev_err(pctldev->dev, "cannot configure pin group, missing " - "config function in driver\n"); - ret = -EINVAL; - goto unlock; - } - - selector = pinctrl_get_group_selector(pctldev, pin_group); - if (selector < 0) { - ret = selector; - goto unlock; - } - - ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins); - if (ret) { - dev_err(pctldev->dev, "cannot configure pin group, error " - "getting pins\n"); - goto unlock; - } - - /* - * If the pin controller supports handling entire groups we use that - * capability. - */ - if (ops->pin_config_group_set) { - ret = ops->pin_config_group_set(pctldev, selector, config); - /* - * If the pin controller prefer that a certain group be handled - * pin-by-pin as well, it returns -EAGAIN. - */ - if (ret != -EAGAIN) - goto unlock; - } - - /* - * If the controller cannot handle entire groups, we configure each pin - * individually. - */ - if (!ops->pin_config_set) { - ret = 0; - goto unlock; - } - - for (i = 0; i < num_pins; i++) { - ret = ops->pin_config_set(pctldev, pins[i], config); - if (ret < 0) - goto unlock; - } - - ret = 0; - -unlock: - mutex_unlock(&pctldev->mutex); - - return ret; -} -EXPORT_SYMBOL(pin_config_group_set); int pinconf_map_to_setting(struct pinctrl_map const *map, struct pinctrl_setting *setting) @@ -332,7 +160,7 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting) { struct pinctrl_dev *pctldev = setting->pctldev; const struct pinconf_ops *ops = pctldev->desc->confops; - int i, ret; + int ret, i; if (!ops) { dev_err(pctldev->dev, "missing confops\n"); @@ -341,39 +169,66 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting) switch (setting->type) { case PIN_MAP_TYPE_CONFIGS_PIN: - if (!ops->pin_config_set) { + if (!ops->pin_config_set && !ops->pin_config_set_bulk) { dev_err(pctldev->dev, "missing pin_config_set op\n"); return -EINVAL; } - for (i = 0; i < setting->data.configs.num_configs; i++) { - ret = ops->pin_config_set(pctldev, + if (ops->pin_config_set_bulk) { + ret = ops->pin_config_set_bulk(pctldev, setting->data.configs.group_or_pin, - setting->data.configs.configs[i]); + setting->data.configs.configs, + setting->data.configs.num_configs); if (ret < 0) { dev_err(pctldev->dev, - "pin_config_set op failed for pin %d config %08lx\n", - setting->data.configs.group_or_pin, - setting->data.configs.configs[i]); + "pin_config_set_bulk op failed for pin %d\n", + setting->data.configs.group_or_pin); return ret; } + } else if (ops->pin_config_set) { + for (i = 0; i < setting->data.configs.num_configs; i++) { + ret = ops->pin_config_set(pctldev, + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + if (ret < 0) { + dev_err(pctldev->dev, + "pin_config_set op failed for pin %d config %08lx\n", + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + return ret; + } + } } break; case PIN_MAP_TYPE_CONFIGS_GROUP: - if (!ops->pin_config_group_set) { + if (!ops->pin_config_group_set && + !ops->pin_config_group_set_bulk) { dev_err(pctldev->dev, "missing pin_config_group_set op\n"); return -EINVAL; } - for (i = 0; i < setting->data.configs.num_configs; i++) { - ret = ops->pin_config_group_set(pctldev, + if (ops->pin_config_group_set_bulk) { + ret = ops->pin_config_group_set_bulk(pctldev, setting->data.configs.group_or_pin, - setting->data.configs.configs[i]); + setting->data.configs.configs, + setting->data.configs.num_configs); if (ret < 0) { dev_err(pctldev->dev, - "pin_config_group_set op failed for group %d config %08lx\n", + "pin_config_group_set_bulk op failed for group %d\n", + setting->data.configs.group_or_pin); + return ret; + } + } else if (ops->pin_config_group_set) { + for (i = 0; i < setting->data.configs.num_configs; i++) { + ret = ops->pin_config_group_set(pctldev, setting->data.configs.group_or_pin, setting->data.configs.configs[i]); - return ret; + if (ret < 0) { + dev_err(pctldev->dev, + "pin_config_group_set op failed for group %d config %08lx\n", + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + return ret; + } } } break; |