diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 6cbcaa6709da..3fcb7e584a93 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -622,8 +622,13 @@ static int pinctrl_generic_group_name_to_selector(struct pinctrl_dev *pctldev, const char *function) { const struct pinctrl_ops *ops = pctldev->desc->pctlops; - int ngroups = ops->get_groups_count(pctldev); int selector = 0; + int ngroups; + + if (!ops->get_groups_count || !ops->get_group_name) + return -EINVAL; + + ngroups = ops->get_groups_count(pctldev); /* See if this pctldev has this group */ while (selector < ngroups) { @@ -738,8 +743,15 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, const char *pin_group) { const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; - unsigned int ngroups = pctlops->get_groups_count(pctldev); unsigned int group_selector = 0; + unsigned int ngroups; + + if (!pctlops->get_groups_count || !pctlops->get_group_name) { + dev_err(pctldev->dev, "does not support pin groups\n"); + return -EINVAL; + } + + ngroups = pctlops->get_groups_count(pctldev); while (group_selector < ngroups) { const char *gname = pctlops->get_group_name(pctldev, @@ -1801,6 +1813,11 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) mutex_lock(&pctldev->mutex); + if (!ops->get_groups_count || !ops->get_group_name) { + mutex_unlock(&pctldev->mutex); + return 0; + } + ngroups = ops->get_groups_count(pctldev); seq_puts(s, "registered pin groups:\n"); @@ -2081,12 +2098,25 @@ static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev) static int pinctrl_check_ops(struct pinctrl_dev *pctldev) { const struct pinctrl_ops *ops = pctldev->desc->pctlops; + const struct pinconf_ops *confops = pctldev->desc->confops; + bool needs_groups = false; - if (!ops || - !ops->get_groups_count || - !ops->get_group_name) + if (!ops) return -EINVAL; + if (pctldev->desc->pmxops) + needs_groups = true; + + if (confops && (confops->pin_config_group_get || + confops->pin_config_group_set)) + needs_groups = true; + + if (needs_groups && (!ops->get_groups_count || !ops->get_group_name)) { + dev_err(pctldev->dev, + "driver needs group callbacks for mux or group config\n"); + return -EINVAL; + } + return 0; } diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index dca963633b5d..81686844dfa5 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -275,7 +275,7 @@ void pinconf_show_setting(struct seq_file *s, case PIN_MAP_TYPE_CONFIGS_GROUP: seq_printf(s, "group %s (%d)", pctlops->get_group_name(pctldev, - setting->data.configs.group_or_pin), + setting->data.configs.group_or_pin), setting->data.configs.group_or_pin); break; default: @@ -348,8 +348,13 @@ static int pinconf_groups_show(struct seq_file *s, void *what) { struct pinctrl_dev *pctldev = s->private; const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; - unsigned int ngroups = pctlops->get_groups_count(pctldev); unsigned int selector = 0; + unsigned int ngroups; + + if (!pctlops->get_groups_count || !pctlops->get_group_name) + return 0; + + ngroups = pctlops->get_groups_count(pctldev); seq_puts(s, "Pin config settings per pin group\n"); seq_puts(s, "Format: group (name): configs\n");