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