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