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