linux/drivers/pinctrl/berlin/berlin.c
<<
>>
Prefs
   1/*
   2 * Marvell Berlin SoC pinctrl core driver
   3 *
   4 * Copyright (C) 2014 Marvell Technology Group Ltd.
   5 *
   6 * Antoine Ténart <antoine.tenart@free-electrons.com>
   7 *
   8 * This file is licensed under the terms of the GNU General Public
   9 * License version 2. This program is licensed "as is" without any
  10 * warranty of any kind, whether express or implied.
  11 */
  12
  13#include <linux/io.h>
  14#include <linux/mfd/syscon.h>
  15#include <linux/module.h>
  16#include <linux/of.h>
  17#include <linux/of_address.h>
  18#include <linux/of_device.h>
  19#include <linux/pinctrl/pinctrl.h>
  20#include <linux/pinctrl/pinmux.h>
  21#include <linux/platform_device.h>
  22#include <linux/regmap.h>
  23#include <linux/slab.h>
  24
  25#include "../core.h"
  26#include "../pinctrl-utils.h"
  27#include "berlin.h"
  28
  29struct berlin_pinctrl {
  30        struct regmap *regmap;
  31        struct device *dev;
  32        const struct berlin_pinctrl_desc *desc;
  33        struct berlin_pinctrl_function *functions;
  34        unsigned nfunctions;
  35        struct pinctrl_dev *pctrl_dev;
  36};
  37
  38static int berlin_pinctrl_get_group_count(struct pinctrl_dev *pctrl_dev)
  39{
  40        struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  41
  42        return pctrl->desc->ngroups;
  43}
  44
  45static const char *berlin_pinctrl_get_group_name(struct pinctrl_dev *pctrl_dev,
  46                                                 unsigned group)
  47{
  48        struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  49
  50        return pctrl->desc->groups[group].name;
  51}
  52
  53static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
  54                                         struct device_node *node,
  55                                         struct pinctrl_map **map,
  56                                         unsigned *num_maps)
  57{
  58        struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
  59        struct property *prop;
  60        const char *function_name, *group_name;
  61        unsigned reserved_maps = 0;
  62        int ret, ngroups;
  63
  64        *map = NULL;
  65        *num_maps = 0;
  66
  67        ret = of_property_read_string(node, "function", &function_name);
  68        if (ret) {
  69                dev_err(pctrl->dev,
  70                        "missing function property in node %s\n",
  71                        node->name);
  72                return -EINVAL;
  73        }
  74
  75        ngroups = of_property_count_strings(node, "groups");
  76        if (ngroups < 0) {
  77                dev_err(pctrl->dev,
  78                        "missing groups property in node %s\n",
  79                        node->name);
  80                return -EINVAL;
  81        }
  82
  83        ret = pinctrl_utils_reserve_map(pctrl_dev, map, &reserved_maps,
  84                                        num_maps, ngroups);
  85        if (ret) {
  86                dev_err(pctrl->dev, "can't reserve map: %d\n", ret);
  87                return ret;
  88        }
  89
  90        of_property_for_each_string(node, "groups", prop, group_name) {
  91                ret = pinctrl_utils_add_map_mux(pctrl_dev, map, &reserved_maps,
  92                                                num_maps, group_name,
  93                                                function_name);
  94                if (ret) {
  95                        dev_err(pctrl->dev, "can't add map: %d\n", ret);
  96                        return ret;
  97                }
  98        }
  99
 100        return 0;
 101}
 102
 103static const struct pinctrl_ops berlin_pinctrl_ops = {
 104        .get_groups_count       = &berlin_pinctrl_get_group_count,
 105        .get_group_name         = &berlin_pinctrl_get_group_name,
 106        .dt_node_to_map         = &berlin_pinctrl_dt_node_to_map,
 107        .dt_free_map            = &pinctrl_utils_dt_free_map,
 108};
 109
 110static int berlin_pinmux_get_functions_count(struct pinctrl_dev *pctrl_dev)
 111{
 112        struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
 113
 114        return pctrl->nfunctions;
 115}
 116
 117static const char *berlin_pinmux_get_function_name(struct pinctrl_dev *pctrl_dev,
 118                                                   unsigned function)
 119{
 120        struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
 121
 122        return pctrl->functions[function].name;
 123}
 124
 125static int berlin_pinmux_get_function_groups(struct pinctrl_dev *pctrl_dev,
 126                                             unsigned function,
 127                                             const char * const **groups,
 128                                             unsigned * const num_groups)
 129{
 130        struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
 131
 132        *groups = pctrl->functions[function].groups;
 133        *num_groups = pctrl->functions[function].ngroups;
 134
 135        return 0;
 136}
 137
 138static struct berlin_desc_function *
 139berlin_pinctrl_find_function_by_name(struct berlin_pinctrl *pctrl,
 140                                     const struct berlin_desc_group *group,
 141                                     const char *fname)
 142{
 143        struct berlin_desc_function *function = group->functions;
 144
 145        while (function->name) {
 146                if (!strcmp(function->name, fname))
 147                        return function;
 148
 149                function++;
 150        }
 151
 152        return NULL;
 153}
 154
 155static int berlin_pinmux_set(struct pinctrl_dev *pctrl_dev,
 156                             unsigned function,
 157                             unsigned group)
 158{
 159        struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
 160        const struct berlin_desc_group *group_desc = pctrl->desc->groups + group;
 161        struct berlin_pinctrl_function *func = pctrl->functions + function;
 162        struct berlin_desc_function *function_desc =
 163                berlin_pinctrl_find_function_by_name(pctrl, group_desc,
 164                                                     func->name);
 165        u32 mask, val;
 166
 167        if (!function_desc)
 168                return -EINVAL;
 169
 170        mask = GENMASK(group_desc->lsb + group_desc->bit_width - 1,
 171                       group_desc->lsb);
 172        val = function_desc->muxval << group_desc->lsb;
 173        regmap_update_bits(pctrl->regmap, group_desc->offset, mask, val);
 174
 175        return 0;
 176}
 177
 178static const struct pinmux_ops berlin_pinmux_ops = {
 179        .get_functions_count    = &berlin_pinmux_get_functions_count,
 180        .get_function_name      = &berlin_pinmux_get_function_name,
 181        .get_function_groups    = &berlin_pinmux_get_function_groups,
 182        .set_mux                = &berlin_pinmux_set,
 183};
 184
 185static int berlin_pinctrl_add_function(struct berlin_pinctrl *pctrl,
 186                                       const char *name)
 187{
 188        struct berlin_pinctrl_function *function = pctrl->functions;
 189
 190        while (function->name) {
 191                if (!strcmp(function->name, name)) {
 192                        function->ngroups++;
 193                        return -EEXIST;
 194                }
 195                function++;
 196        }
 197
 198        function->name = name;
 199        function->ngroups = 1;
 200
 201        pctrl->nfunctions++;
 202
 203        return 0;
 204}
 205
 206static int berlin_pinctrl_build_state(struct platform_device *pdev)
 207{
 208        struct berlin_pinctrl *pctrl = platform_get_drvdata(pdev);
 209        struct berlin_desc_group const *desc_group;
 210        struct berlin_desc_function const *desc_function;
 211        int i, max_functions = 0;
 212
 213        pctrl->nfunctions = 0;
 214
 215        for (i = 0; i < pctrl->desc->ngroups; i++) {
 216                desc_group = pctrl->desc->groups + i;
 217                /* compute the maxiumum number of functions a group can have */
 218                max_functions += 1 << (desc_group->bit_width + 1);
 219        }
 220
 221        /* we will reallocate later */
 222        pctrl->functions = devm_kzalloc(&pdev->dev,
 223                                        max_functions * sizeof(*pctrl->functions),
 224                                        GFP_KERNEL);
 225        if (!pctrl->functions)
 226                return -ENOMEM;
 227
 228        /* register all functions */
 229        for (i = 0; i < pctrl->desc->ngroups; i++) {
 230                desc_group = pctrl->desc->groups + i;
 231                desc_function = desc_group->functions;
 232
 233                while (desc_function->name) {
 234                        berlin_pinctrl_add_function(pctrl, desc_function->name);
 235                        desc_function++;
 236                }
 237        }
 238
 239        pctrl->functions = krealloc(pctrl->functions,
 240                                    pctrl->nfunctions * sizeof(*pctrl->functions),
 241                                    GFP_KERNEL);
 242
 243        /* map functions to theirs groups */
 244        for (i = 0; i < pctrl->desc->ngroups; i++) {
 245                desc_group = pctrl->desc->groups + i;
 246                desc_function = desc_group->functions;
 247
 248                while (desc_function->name) {
 249                        struct berlin_pinctrl_function
 250                                *function = pctrl->functions;
 251                        const char **groups;
 252                        bool found = false;
 253
 254                        while (function->name) {
 255                                if (!strcmp(desc_function->name, function->name)) {
 256                                        found = true;
 257                                        break;
 258                                }
 259                                function++;
 260                        }
 261
 262                        if (!found)
 263                                return -EINVAL;
 264
 265                        if (!function->groups) {
 266                                function->groups =
 267                                        devm_kzalloc(&pdev->dev,
 268                                                     function->ngroups * sizeof(char *),
 269                                                     GFP_KERNEL);
 270
 271                                if (!function->groups)
 272                                        return -ENOMEM;
 273                        }
 274
 275                        groups = function->groups;
 276                        while (*groups)
 277                                groups++;
 278
 279                        *groups = desc_group->name;
 280
 281                        desc_function++;
 282                }
 283        }
 284
 285        return 0;
 286}
 287
 288static struct pinctrl_desc berlin_pctrl_desc = {
 289        .name           = "berlin-pinctrl",
 290        .pctlops        = &berlin_pinctrl_ops,
 291        .pmxops         = &berlin_pinmux_ops,
 292        .owner          = THIS_MODULE,
 293};
 294
 295int berlin_pinctrl_probe(struct platform_device *pdev,
 296                         const struct berlin_pinctrl_desc *desc)
 297{
 298        struct device *dev = &pdev->dev;
 299        struct device_node *parent_np = of_get_parent(dev->of_node);
 300        struct berlin_pinctrl *pctrl;
 301        struct regmap *regmap;
 302        int ret;
 303
 304        regmap = syscon_node_to_regmap(parent_np);
 305        of_node_put(parent_np);
 306        if (IS_ERR(regmap))
 307                return PTR_ERR(regmap);
 308
 309        pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
 310        if (!pctrl)
 311                return -ENOMEM;
 312
 313        platform_set_drvdata(pdev, pctrl);
 314
 315        pctrl->regmap = regmap;
 316        pctrl->dev = &pdev->dev;
 317        pctrl->desc = desc;
 318
 319        ret = berlin_pinctrl_build_state(pdev);
 320        if (ret) {
 321                dev_err(dev, "cannot build driver state: %d\n", ret);
 322                return ret;
 323        }
 324
 325        pctrl->pctrl_dev = pinctrl_register(&berlin_pctrl_desc, dev, pctrl);
 326        if (IS_ERR(pctrl->pctrl_dev)) {
 327                dev_err(dev, "failed to register pinctrl driver\n");
 328                return PTR_ERR(pctrl->pctrl_dev);
 329        }
 330
 331        return 0;
 332}
 333