]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/pinctrl/pinmux.c
pinctrl: make pinmux disable function optional
[karo-tx-linux.git] / drivers / pinctrl / pinmux.c
index 4e62783a573a2443efa7db6f807e4fbda5deacd5..3d5ac73bd5a7f978534a315b028e904433c0279b 100644 (file)
 int pinmux_check_ops(struct pinctrl_dev *pctldev)
 {
        const struct pinmux_ops *ops = pctldev->desc->pmxops;
+       unsigned nfuncs;
        unsigned selector = 0;
 
        /* Check that we implement required operations */
-       if (!ops->list_functions ||
+       if (!ops ||
+           !ops->get_functions_count ||
            !ops->get_function_name ||
            !ops->get_function_groups ||
-           !ops->enable ||
-           !ops->disable)
+           !ops->enable) {
+               dev_err(pctldev->dev, "pinmux ops lacks necessary functions\n");
                return -EINVAL;
-
+       }
        /* Check that all functions registered have names */
-       while (ops->list_functions(pctldev, selector) >= 0) {
+       nfuncs = ops->get_functions_count(pctldev);
+       while (selector < nfuncs) {
                const char *fname = ops->get_function_name(pctldev,
                                                           selector);
                if (!fname) {
-                       pr_err("pinmux ops has no name for function%u\n",
+                       dev_err(pctldev->dev, "pinmux ops has no name for function%u\n",
                                selector);
                        return -EINVAL;
                }
@@ -85,20 +88,23 @@ static int pin_request(struct pinctrl_dev *pctldev,
        const struct pinmux_ops *ops = pctldev->desc->pmxops;
        int status = -EINVAL;
 
-       dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, owner);
-
        desc = pin_desc_get(pctldev, pin);
        if (desc == NULL) {
                dev_err(pctldev->dev,
-                       "pin is not registered so it cannot be requested\n");
+                       "pin %d is not registered so it cannot be requested\n",
+                       pin);
                goto out;
        }
 
+       dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
+               pin, desc->name, owner);
+
        if (gpio_range) {
                /* There's no need to support multiple GPIO requests */
                if (desc->gpio_owner) {
                        dev_err(pctldev->dev,
-                               "pin already requested\n");
+                               "pin %s already requested by %s; cannot claim for %s\n",
+                               desc->name, desc->gpio_owner, owner);
                        goto out;
                }
 
@@ -106,7 +112,8 @@ static int pin_request(struct pinctrl_dev *pctldev,
        } else {
                if (desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
                        dev_err(pctldev->dev,
-                               "pin already requested\n");
+                               "pin %s already requested by %s; cannot claim for %s\n",
+                               desc->name, desc->mux_owner, owner);
                        goto out;
                }
 
@@ -139,8 +146,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
                status = 0;
 
        if (status) {
-               dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
-                      pctldev->desc->name, pin);
+               dev_err(pctldev->dev, "request() failed for pin %d\n", pin);
                module_put(pctldev->owner);
        }
 
@@ -157,7 +163,7 @@ out_free_pin:
 out:
        if (status)
                dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
-                      pin, owner, status);
+                       pin, owner, status);
 
        return status;
 }
@@ -287,10 +293,11 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
                                        const char *function)
 {
        const struct pinmux_ops *ops = pctldev->desc->pmxops;
+       unsigned nfuncs = ops->get_functions_count(pctldev);
        unsigned selector = 0;
 
        /* See if this pctldev has this function */
-       while (ops->list_functions(pctldev, selector) >= 0) {
+       while (selector < nfuncs) {
                const char *fname = ops->get_function_name(pctldev,
                                                           selector);
 
@@ -319,18 +326,32 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
        const unsigned *pins;
        unsigned num_pins;
 
-       setting->data.mux.func =
-               pinmux_func_name_to_selector(pctldev, map->data.mux.function);
-       if (setting->data.mux.func < 0)
-               return setting->data.mux.func;
+       if (!pmxops) {
+               dev_err(pctldev->dev, "does not support mux function\n");
+               return -EINVAL;
+       }
+
+       ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
+       if (ret < 0) {
+               dev_err(pctldev->dev, "invalid function %s in map table\n",
+                       map->data.mux.function);
+               return ret;
+       }
+       setting->data.mux.func = ret;
 
        ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
                                          &groups, &num_groups);
-       if (ret < 0)
+       if (ret < 0) {
+               dev_err(pctldev->dev, "can't query groups for function %s\n",
+                       map->data.mux.function);
                return ret;
-       if (!num_groups)
+       }
+       if (!num_groups) {
+               dev_err(pctldev->dev,
+                       "function %s can't be selected on any group\n",
+                       map->data.mux.function);
                return -EINVAL;
-
+       }
        if (map->data.mux.group) {
                bool found = false;
                group = map->data.mux.group;
@@ -340,15 +361,23 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
                                break;
                        }
                }
-               if (!found)
+               if (!found) {
+                       dev_err(pctldev->dev,
+                               "invalid group \"%s\" for function \"%s\"\n",
+                               group, map->data.mux.function);
                        return -EINVAL;
+               }
        } else {
                group = groups[0];
        }
 
-       setting->data.mux.group = pinctrl_get_group_selector(pctldev, group);
-       if (setting->data.mux.group < 0)
-               return setting->data.mux.group;
+       ret = pinctrl_get_group_selector(pctldev, group);
+       if (ret < 0) {
+               dev_err(pctldev->dev, "invalid group %s in map table\n",
+                       map->data.mux.group);
+               return ret;
+       }
+       setting->data.mux.group = ret;
 
        ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
                                      &num_pins);
@@ -364,7 +393,7 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
                ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
                if (ret) {
                        dev_err(pctldev->dev,
-                               "could not get request pin %d on device %s\n",
+                               "could not request pin %d on device %s\n",
                                pins[i], pinctrl_dev_get_name(pctldev));
                        /* On error release all taken pins */
                        i--; /* this pin just failed */
@@ -467,7 +496,8 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
                desc->mux_setting = NULL;
        }
 
-       ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
+       if (ops->disable)
+               ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -477,11 +507,15 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
 {
        struct pinctrl_dev *pctldev = s->private;
        const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
+       unsigned nfuncs;
        unsigned func_selector = 0;
 
-       mutex_lock(&pinctrl_mutex);
+       if (!pmxops)
+               return 0;
 
-       while (pmxops->list_functions(pctldev, func_selector) >= 0) {
+       mutex_lock(&pinctrl_mutex);
+       nfuncs = pmxops->get_functions_count(pctldev);
+       while (func_selector < nfuncs) {
                const char *func = pmxops->get_function_name(pctldev,
                                                          func_selector);
                const char * const *groups;
@@ -515,6 +549,9 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
        const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
        unsigned i, pin;
 
+       if (!pmxops)
+               return 0;
+
        seq_puts(s, "Pinmux settings per pin\n");
        seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n");