linux/drivers/pinctrl/pinctrl-lantiq.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/pinctrl/pinctrl-lantiq.c
   3 *  based on linux/drivers/pinctrl/pinctrl-pxa3xx.c
   4 *
   5 *  This program is free software; you can redistribute it and/or modify
   6 *  it under the terms of the GNU General Public License version 2 as
   7 *  publishhed by the Free Software Foundation.
   8 *
   9 *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/device.h>
  14#include <linux/io.h>
  15#include <linux/platform_device.h>
  16#include <linux/slab.h>
  17#include <linux/of.h>
  18
  19#include "pinctrl-lantiq.h"
  20
  21static int ltq_get_group_count(struct pinctrl_dev *pctrldev)
  22{
  23        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  24        return info->num_grps;
  25}
  26
  27static const char *ltq_get_group_name(struct pinctrl_dev *pctrldev,
  28                                         unsigned selector)
  29{
  30        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  31        if (selector >= info->num_grps)
  32                return NULL;
  33        return info->grps[selector].name;
  34}
  35
  36static int ltq_get_group_pins(struct pinctrl_dev *pctrldev,
  37                                 unsigned selector,
  38                                 const unsigned **pins,
  39                                 unsigned *num_pins)
  40{
  41        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
  42        if (selector >= info->num_grps)
  43                return -EINVAL;
  44        *pins = info->grps[selector].pins;
  45        *num_pins = info->grps[selector].npins;
  46        return 0;
  47}
  48
  49static void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
  50                                    struct pinctrl_map *map, unsigned num_maps)
  51{
  52        int i;
  53
  54        for (i = 0; i < num_maps; i++)
  55                if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN ||
  56                    map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
  57                        kfree(map[i].data.configs.configs);
  58        kfree(map);
  59}
  60
  61static void ltq_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
  62                                        struct seq_file *s,
  63                                        unsigned offset)
  64{
  65        seq_printf(s, " %s", dev_name(pctldev->dev));
  66}
  67
  68static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
  69                                struct device_node *np,
  70                                struct pinctrl_map **map)
  71{
  72        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
  73        struct property *pins = of_find_property(np, "lantiq,pins", NULL);
  74        struct property *groups = of_find_property(np, "lantiq,groups", NULL);
  75        unsigned long configs[3];
  76        unsigned num_configs = 0;
  77        struct property *prop;
  78        const char *group, *pin;
  79        const char *function;
  80        int ret, i;
  81
  82        if (!pins && !groups) {
  83                dev_err(pctldev->dev, "%s defines neither pins nor groups\n",
  84                        np->name);
  85                return;
  86        }
  87
  88        if (pins && groups) {
  89                dev_err(pctldev->dev, "%s defines both pins and groups\n",
  90                        np->name);
  91                return;
  92        }
  93
  94        ret = of_property_read_string(np, "lantiq,function", &function);
  95        if (groups && !ret) {
  96                of_property_for_each_string(np, "lantiq,groups", prop, group) {
  97                        (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
  98                        (*map)->name = function;
  99                        (*map)->data.mux.group = group;
 100                        (*map)->data.mux.function = function;
 101                        (*map)++;
 102                }
 103        }
 104
 105        for (i = 0; i < info->num_params; i++) {
 106                u32 val;
 107                int ret = of_property_read_u32(np,
 108                                info->params[i].property, &val);
 109                if (!ret)
 110                        configs[num_configs++] =
 111                                LTQ_PINCONF_PACK(info->params[i].param,
 112                                val);
 113        }
 114
 115        if (!num_configs)
 116                return;
 117
 118        of_property_for_each_string(np, "lantiq,pins", prop, pin) {
 119                (*map)->data.configs.configs = kmemdup(configs,
 120                                        num_configs * sizeof(unsigned long),
 121                                        GFP_KERNEL);
 122                (*map)->type = PIN_MAP_TYPE_CONFIGS_PIN;
 123                (*map)->name = pin;
 124                (*map)->data.configs.group_or_pin = pin;
 125                (*map)->data.configs.num_configs = num_configs;
 126                (*map)++;
 127        }
 128        of_property_for_each_string(np, "lantiq,groups", prop, group) {
 129                (*map)->data.configs.configs = kmemdup(configs,
 130                                        num_configs * sizeof(unsigned long),
 131                                        GFP_KERNEL);
 132                (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP;
 133                (*map)->name = group;
 134                (*map)->data.configs.group_or_pin = group;
 135                (*map)->data.configs.num_configs = num_configs;
 136                (*map)++;
 137        }
 138}
 139
 140static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
 141{
 142        int ret;
 143
 144        ret = of_property_count_strings(np, "lantiq,groups");
 145        if (ret < 0)
 146                ret = of_property_count_strings(np, "lantiq,pins");
 147        return ret;
 148}
 149
 150static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 151                                      struct device_node *np_config,
 152                                      struct pinctrl_map **map,
 153                                      unsigned *num_maps)
 154{
 155        struct pinctrl_map *tmp;
 156        struct device_node *np;
 157        int max_maps = 0;
 158
 159        for_each_child_of_node(np_config, np)
 160                max_maps += ltq_pinctrl_dt_subnode_size(np);
 161        *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL);
 162        if (!*map)
 163                return -ENOMEM;
 164        tmp = *map;
 165
 166        for_each_child_of_node(np_config, np)
 167                ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
 168        *num_maps = ((int)(tmp - *map));
 169
 170        return 0;
 171}
 172
 173static const struct pinctrl_ops ltq_pctrl_ops = {
 174        .get_groups_count       = ltq_get_group_count,
 175        .get_group_name         = ltq_get_group_name,
 176        .get_group_pins         = ltq_get_group_pins,
 177        .pin_dbg_show           = ltq_pinctrl_pin_dbg_show,
 178        .dt_node_to_map         = ltq_pinctrl_dt_node_to_map,
 179        .dt_free_map            = ltq_pinctrl_dt_free_map,
 180};
 181
 182static int ltq_pmx_func_count(struct pinctrl_dev *pctrldev)
 183{
 184        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
 185
 186        return info->num_funcs;
 187}
 188
 189static const char *ltq_pmx_func_name(struct pinctrl_dev *pctrldev,
 190                                         unsigned selector)
 191{
 192        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
 193
 194        if (selector >= info->num_funcs)
 195                return NULL;
 196
 197        return info->funcs[selector].name;
 198}
 199
 200static int ltq_pmx_get_groups(struct pinctrl_dev *pctrldev,
 201                                unsigned func,
 202                                const char * const **groups,
 203                                unsigned * const num_groups)
 204{
 205        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
 206
 207        *groups = info->funcs[func].groups;
 208        *num_groups = info->funcs[func].num_groups;
 209
 210        return 0;
 211}
 212
 213/* Return function number. If failure, return negative value. */
 214static int match_mux(const struct ltq_mfp_pin *mfp, unsigned mux)
 215{
 216        int i;
 217        for (i = 0; i < LTQ_MAX_MUX; i++) {
 218                if (mfp->func[i] == mux)
 219                        break;
 220        }
 221        if (i >= LTQ_MAX_MUX)
 222                return -EINVAL;
 223        return i;
 224}
 225
 226/* dont assume .mfp is linearly mapped. find the mfp with the correct .pin */
 227static int match_mfp(const struct ltq_pinmux_info *info, int pin)
 228{
 229        int i;
 230        for (i = 0; i < info->num_mfp; i++) {
 231                if (info->mfp[i].pin == pin)
 232                        return i;
 233        }
 234        return -1;
 235}
 236
 237/* check whether current pin configuration is valid. Negative for failure */
 238static int match_group_mux(const struct ltq_pin_group *grp,
 239                           const struct ltq_pinmux_info *info,
 240                           unsigned mux)
 241{
 242        int i, pin, ret = 0;
 243        for (i = 0; i < grp->npins; i++) {
 244                pin = match_mfp(info, grp->pins[i]);
 245                if (pin < 0) {
 246                        dev_err(info->dev, "could not find mfp for pin %d\n",
 247                                grp->pins[i]);
 248                        return -EINVAL;
 249                }
 250                ret = match_mux(&info->mfp[pin], mux);
 251                if (ret < 0) {
 252                        dev_err(info->dev, "Can't find mux %d on pin%d\n",
 253                                mux, pin);
 254                        break;
 255                }
 256        }
 257        return ret;
 258}
 259
 260static int ltq_pmx_enable(struct pinctrl_dev *pctrldev,
 261                                unsigned func,
 262                                unsigned group)
 263{
 264        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
 265        const struct ltq_pin_group *pin_grp = &info->grps[group];
 266        int i, pin, pin_func, ret;
 267
 268        if (!pin_grp->npins ||
 269                (match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
 270                dev_err(info->dev, "Failed to set the pin group: %s\n",
 271                        info->grps[group].name);
 272                return -EINVAL;
 273        }
 274        for (i = 0; i < pin_grp->npins; i++) {
 275                pin = match_mfp(info, pin_grp->pins[i]);
 276                if (pin < 0) {
 277                        dev_err(info->dev, "could not find mfp for pin %d\n",
 278                                pin_grp->pins[i]);
 279                        return -EINVAL;
 280                }
 281                pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
 282                ret = info->apply_mux(pctrldev, pin, pin_func);
 283                if (ret) {
 284                        dev_err(info->dev,
 285                                "failed to apply mux %d for pin %d\n",
 286                                pin_func, pin);
 287                        return ret;
 288                }
 289        }
 290        return 0;
 291}
 292
 293static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev,
 294                                struct pinctrl_gpio_range *range,
 295                                unsigned pin)
 296{
 297        struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
 298        int mfp = match_mfp(info, pin);
 299        int pin_func;
 300
 301        if (mfp < 0) {
 302                dev_err(info->dev, "could not find mfp for pin %d\n", pin);
 303                return -EINVAL;
 304        }
 305
 306        pin_func = match_mux(&info->mfp[mfp], 0);
 307        if (pin_func < 0) {
 308                dev_err(info->dev, "No GPIO function on pin%d\n", mfp);
 309                return -EINVAL;
 310        }
 311
 312        return info->apply_mux(pctrldev, mfp, pin_func);
 313}
 314
 315static const struct pinmux_ops ltq_pmx_ops = {
 316        .get_functions_count    = ltq_pmx_func_count,
 317        .get_function_name      = ltq_pmx_func_name,
 318        .get_function_groups    = ltq_pmx_get_groups,
 319        .enable                 = ltq_pmx_enable,
 320        .gpio_request_enable    = ltq_pmx_gpio_request_enable,
 321};
 322
 323/*
 324 * allow different socs to register with the generic part of the lanti
 325 * pinctrl code
 326 */
 327int ltq_pinctrl_register(struct platform_device *pdev,
 328                                struct ltq_pinmux_info *info)
 329{
 330        struct pinctrl_desc *desc;
 331
 332        if (!info)
 333                return -EINVAL;
 334        desc = info->desc;
 335        desc->pctlops = &ltq_pctrl_ops;
 336        desc->pmxops = &ltq_pmx_ops;
 337        info->dev = &pdev->dev;
 338
 339        info->pctrl = pinctrl_register(desc, &pdev->dev, info);
 340        if (!info->pctrl) {
 341                dev_err(&pdev->dev, "failed to register LTQ pinmux driver\n");
 342                return -EINVAL;
 343        }
 344        platform_set_drvdata(pdev, info);
 345        return 0;
 346}
 347
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.