]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/pinctrl/pinctrl-single.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / drivers / pinctrl / pinctrl-single.c
index 5e7a37ddef8e3f7337a322ea90de8ba5b7b557d3..8b2d45e85baea612451812fb7cc82b88b75d8d9c 100644 (file)
@@ -33,6 +33,7 @@
 #include "core.h"
 #include "devicetree.h"
 #include "pinconf.h"
+#include "pinmux.h"
 
 #define DRIVER_NAME                    "pinctrl-single"
 #define PCS_OFF_DISABLED               ~0U
@@ -160,13 +161,10 @@ struct pcs_soc_data {
  * @bits_per_mux: number of bits per mux
  * @bits_per_pin: number of bits per pin
  * @pins:      physical pins on the SoC
- * @ftree:     function index radix tree
- * @functions: list of functions
  * @gpiofuncs: list of gpio functions
  * @irqs:      list of interrupt registers
  * @chip:      chip container for this instance
  * @domain:    IRQ domain for this instance
- * @nfuncs:    number of functions
  * @desc:      pin controller descriptor
  * @read:      register read function to use
  * @write:     register write function to use
@@ -194,13 +192,10 @@ struct pcs_device {
        bool bits_per_mux;
        unsigned bits_per_pin;
        struct pcs_data pins;
-       struct radix_tree_root ftree;
-       struct list_head functions;
        struct list_head gpiofuncs;
        struct list_head irqs;
        struct irq_chip chip;
        struct irq_domain *domain;
-       unsigned nfuncs;
        struct pinctrl_desc desc;
        unsigned (*read)(void __iomem *reg);
        void (*write)(unsigned val, void __iomem *reg);
@@ -307,59 +302,13 @@ static const struct pinctrl_ops pcs_pinctrl_ops = {
        .dt_free_map = pcs_dt_free_map,
 };
 
-static int pcs_get_functions_count(struct pinctrl_dev *pctldev)
-{
-       struct pcs_device *pcs;
-
-       pcs = pinctrl_dev_get_drvdata(pctldev);
-
-       return pcs->nfuncs;
-}
-
-static const char *pcs_get_function_name(struct pinctrl_dev *pctldev,
-                                               unsigned fselector)
-{
-       struct pcs_device *pcs;
-       struct pcs_function *func;
-
-       pcs = pinctrl_dev_get_drvdata(pctldev);
-       func = radix_tree_lookup(&pcs->ftree, fselector);
-       if (!func) {
-               dev_err(pcs->dev, "%s could not find function%i\n",
-                       __func__, fselector);
-               return NULL;
-       }
-
-       return func->name;
-}
-
-static int pcs_get_function_groups(struct pinctrl_dev *pctldev,
-                                       unsigned fselector,
-                                       const char * const **groups,
-                                       unsigned * const ngroups)
-{
-       struct pcs_device *pcs;
-       struct pcs_function *func;
-
-       pcs = pinctrl_dev_get_drvdata(pctldev);
-       func = radix_tree_lookup(&pcs->ftree, fselector);
-       if (!func) {
-               dev_err(pcs->dev, "%s could not find function%i\n",
-                       __func__, fselector);
-               return -EINVAL;
-       }
-       *groups = func->pgnames;
-       *ngroups = func->npgnames;
-
-       return 0;
-}
-
 static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
                            struct pcs_function **func)
 {
        struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
        struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
        const struct pinctrl_setting_mux *setting;
+       struct function_desc *function;
        unsigned fselector;
 
        /* If pin is not described in DTS & enabled, mux_setting is NULL. */
@@ -367,7 +316,8 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
        if (!setting)
                return -ENOTSUPP;
        fselector = setting->func;
-       *func = radix_tree_lookup(&pcs->ftree, fselector);
+       function = pinmux_generic_get_function(pctldev, fselector);
+       *func = function->data;
        if (!(*func)) {
                dev_err(pcs->dev, "%s could not find function%i\n",
                        __func__, fselector);
@@ -380,6 +330,7 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
        unsigned group)
 {
        struct pcs_device *pcs;
+       struct function_desc *function;
        struct pcs_function *func;
        int i;
 
@@ -387,7 +338,8 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
        /* If function mask is null, needn't enable it. */
        if (!pcs->fmask)
                return 0;
-       func = radix_tree_lookup(&pcs->ftree, fselector);
+       function = pinmux_generic_get_function(pctldev, fselector);
+       func = function->data;
        if (!func)
                return -EINVAL;
 
@@ -445,9 +397,9 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,
 }
 
 static const struct pinmux_ops pcs_pinmux_ops = {
-       .get_functions_count = pcs_get_functions_count,
-       .get_function_name = pcs_get_function_name,
-       .get_function_groups = pcs_get_function_groups,
+       .get_functions_count = pinmux_generic_get_function_count,
+       .get_function_name = pinmux_generic_get_function_name,
+       .get_function_groups = pinmux_generic_get_function_groups,
        .set_mux = pcs_set_mux,
        .gpio_request_enable = pcs_request_gpio,
 };
@@ -552,7 +504,7 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
        struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
        struct pcs_function *func;
        unsigned offset = 0, shift = 0, i, data, ret;
-       u16 arg;
+       u32 arg;
        int j;
 
        ret = pcs_get_function(pctldev, pin, &func);
@@ -789,43 +741,24 @@ static struct pcs_function *pcs_add_function(struct pcs_device *pcs,
                                        unsigned npgnames)
 {
        struct pcs_function *function;
+       int res;
 
        function = devm_kzalloc(pcs->dev, sizeof(*function), GFP_KERNEL);
        if (!function)
                return NULL;
 
-       function->name = name;
        function->vals = vals;
        function->nvals = nvals;
-       function->pgnames = pgnames;
-       function->npgnames = npgnames;
 
-       mutex_lock(&pcs->mutex);
-       list_add_tail(&function->node, &pcs->functions);
-       radix_tree_insert(&pcs->ftree, pcs->nfuncs, function);
-       pcs->nfuncs++;
-       mutex_unlock(&pcs->mutex);
+       res = pinmux_generic_add_function(pcs->pctl, name,
+                                         pgnames, npgnames,
+                                         function);
+       if (res)
+               return NULL;
 
        return function;
 }
 
-static void pcs_remove_function(struct pcs_device *pcs,
-                               struct pcs_function *function)
-{
-       int i;
-
-       mutex_lock(&pcs->mutex);
-       for (i = 0; i < pcs->nfuncs; i++) {
-               struct pcs_function *found;
-
-               found = radix_tree_lookup(&pcs->ftree, i);
-               if (found == function)
-                       radix_tree_delete(&pcs->ftree, i);
-       }
-       list_del(&function->node);
-       mutex_unlock(&pcs->mutex);
-}
-
 /**
  * pcs_get_pin_by_offset() - get a pin index based on the register offset
  * @pcs: pcs driver instance
@@ -1103,7 +1036,7 @@ free_pingroups:
        pinctrl_generic_remove_last_group(pcs->pctl);
        *num_maps = 1;
 free_function:
-       pcs_remove_function(pcs, function);
+       pinmux_generic_remove_last_function(pcs->pctl);
 
 free_pins:
        devm_kfree(pcs->dev, pins);
@@ -1235,8 +1168,7 @@ free_pingroups:
        pinctrl_generic_remove_last_group(pcs->pctl);
        *num_maps = 1;
 free_function:
-       pcs_remove_function(pcs, function);
-
+       pinmux_generic_remove_last_function(pcs->pctl);
 free_pins:
        devm_kfree(pcs->dev, pins);
 
@@ -1303,33 +1235,6 @@ free_map:
        return ret;
 }
 
-/**
- * pcs_free_funcs() - free memory used by functions
- * @pcs: pcs driver instance
- */
-static void pcs_free_funcs(struct pcs_device *pcs)
-{
-       struct list_head *pos, *tmp;
-       int i;
-
-       mutex_lock(&pcs->mutex);
-       for (i = 0; i < pcs->nfuncs; i++) {
-               struct pcs_function *func;
-
-               func = radix_tree_lookup(&pcs->ftree, i);
-               if (!func)
-                       continue;
-               radix_tree_delete(&pcs->ftree, i);
-       }
-       list_for_each_safe(pos, tmp, &pcs->functions) {
-               struct pcs_function *function;
-
-               function = list_entry(pos, struct pcs_function, node);
-               list_del(&function->node);
-       }
-       mutex_unlock(&pcs->mutex);
-}
-
 /**
  * pcs_irq_free() - free interrupt
  * @pcs: pcs driver instance
@@ -1358,7 +1263,6 @@ static void pcs_free_resources(struct pcs_device *pcs)
 {
        pcs_irq_free(pcs);
        pinctrl_unregister(pcs->pctl);
-       pcs_free_funcs(pcs);
 
 #if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
        if (pcs->missing_nr_pinctrl_cells)
@@ -1753,7 +1657,6 @@ static int pcs_probe(struct platform_device *pdev)
        pcs->np = np;
        raw_spin_lock_init(&pcs->lock);
        mutex_init(&pcs->mutex);
-       INIT_LIST_HEAD(&pcs->functions);
        INIT_LIST_HEAD(&pcs->gpiofuncs);
        soc = match->data;
        pcs->flags = soc->flags;
@@ -1814,7 +1717,6 @@ static int pcs_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       INIT_RADIX_TREE(&pcs->ftree, GFP_KERNEL);
        platform_set_drvdata(pdev, pcs);
 
        switch (pcs->width) {
@@ -1845,10 +1747,9 @@ static int pcs_probe(struct platform_device *pdev)
        if (ret < 0)
                goto free;
 
-       pcs->pctl = pinctrl_register(&pcs->desc, pcs->dev, pcs);
-       if (IS_ERR(pcs->pctl)) {
+       ret = pinctrl_register_and_init(&pcs->desc, pcs->dev, pcs, &pcs->pctl);
+       if (ret) {
                dev_err(pcs->dev, "could not register single pinctrl driver\n");
-               ret = PTR_ERR(pcs->pctl);
                goto free;
        }