linux/drivers/pinctrl/pinconf.c
<<
>>
Prefs
   1/*
   2 * Core driver for the pin config portions of the pin control subsystem
   3 *
   4 * Copyright (C) 2011 ST-Ericsson SA
   5 * Written on behalf of Linaro for ST-Ericsson
   6 *
   7 * Author: Linus Walleij <linus.walleij@linaro.org>
   8 *
   9 * License terms: GNU General Public License (GPL) version 2
  10 */
  11#define pr_fmt(fmt) "pinconfig core: " fmt
  12
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/init.h>
  16#include <linux/device.h>
  17#include <linux/slab.h>
  18#include <linux/debugfs.h>
  19#include <linux/seq_file.h>
  20#include <linux/pinctrl/machine.h>
  21#include <linux/pinctrl/pinctrl.h>
  22#include <linux/pinctrl/pinconf.h>
  23#include "core.h"
  24#include "pinconf.h"
  25
  26int pinconf_check_ops(struct pinctrl_dev *pctldev)
  27{
  28        const struct pinconf_ops *ops = pctldev->desc->confops;
  29
  30        /* We must be able to read out pin status */
  31        if (!ops->pin_config_get && !ops->pin_config_group_get) {
  32                dev_err(pctldev->dev,
  33                        "pinconf must be able to read out pin status\n");
  34                return -EINVAL;
  35        }
  36        /* We have to be able to config the pins in SOME way */
  37        if (!ops->pin_config_set && !ops->pin_config_group_set) {
  38                dev_err(pctldev->dev,
  39                        "pinconf has to be able to set a pins config\n");
  40                return -EINVAL;
  41        }
  42        return 0;
  43}
  44
  45int pinconf_validate_map(struct pinctrl_map const *map, int i)
  46{
  47        if (!map->data.configs.group_or_pin) {
  48                pr_err("failed to register map %s (%d): no group/pin given\n",
  49                       map->name, i);
  50                return -EINVAL;
  51        }
  52
  53        if (!map->data.configs.num_configs ||
  54                        !map->data.configs.configs) {
  55                pr_err("failed to register map %s (%d): no configs given\n",
  56                       map->name, i);
  57                return -EINVAL;
  58        }
  59
  60        return 0;
  61}
  62
  63int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
  64                           unsigned long *config)
  65{
  66        const struct pinconf_ops *ops = pctldev->desc->confops;
  67
  68        if (!ops || !ops->pin_config_get) {
  69                dev_err(pctldev->dev, "cannot get pin configuration, missing "
  70                        "pin_config_get() function in driver\n");
  71                return -EINVAL;
  72        }
  73
  74        return ops->pin_config_get(pctldev, pin, config);
  75}
  76
  77/**
  78 * pin_config_get() - get the configuration of a single pin parameter
  79 * @dev_name: name of the pin controller device for this pin
  80 * @name: name of the pin to get the config for
  81 * @config: the config pointed to by this argument will be filled in with the
  82 *      current pin state, it can be used directly by drivers as a numeral, or
  83 *      it can be dereferenced to any struct.
  84 */
  85int pin_config_get(const char *dev_name, const char *name,
  86                          unsigned long *config)
  87{
  88        struct pinctrl_dev *pctldev;
  89        int pin;
  90
  91        mutex_lock(&pinctrl_mutex);
  92
  93        pctldev = get_pinctrl_dev_from_devname(dev_name);
  94        if (!pctldev) {
  95                pin = -EINVAL;
  96                goto unlock;
  97        }
  98
  99        pin = pin_get_from_name(pctldev, name);
 100        if (pin < 0)
 101                goto unlock;
 102
 103        pin = pin_config_get_for_pin(pctldev, pin, config);
 104
 105unlock:
 106        mutex_unlock(&pinctrl_mutex);
 107        return pin;
 108}
 109EXPORT_SYMBOL(pin_config_get);
 110
 111static int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
 112                           unsigned long config)
 113{
 114        const struct pinconf_ops *ops = pctldev->desc->confops;
 115        int ret;
 116
 117        if (!ops || !ops->pin_config_set) {
 118                dev_err(pctldev->dev, "cannot configure pin, missing "
 119                        "config function in driver\n");
 120                return -EINVAL;
 121        }
 122
 123        ret = ops->pin_config_set(pctldev, pin, config);
 124        if (ret) {
 125                dev_err(pctldev->dev,
 126                        "unable to set pin configuration on pin %d\n", pin);
 127                return ret;
 128        }
 129
 130        return 0;
 131}
 132
 133/**
 134 * pin_config_set() - set the configuration of a single pin parameter
 135 * @dev_name: name of pin controller device for this pin
 136 * @name: name of the pin to set the config for
 137 * @config: the config in this argument will contain the desired pin state, it
 138 *      can be used directly by drivers as a numeral, or it can be dereferenced
 139 *      to any struct.
 140 */
 141int pin_config_set(const char *dev_name, const char *name,
 142                   unsigned long config)
 143{
 144        struct pinctrl_dev *pctldev;
 145        int pin, ret;
 146
 147        mutex_lock(&pinctrl_mutex);
 148
 149        pctldev = get_pinctrl_dev_from_devname(dev_name);
 150        if (!pctldev) {
 151                ret = -EINVAL;
 152                goto unlock;
 153        }
 154
 155        pin = pin_get_from_name(pctldev, name);
 156        if (pin < 0) {
 157                ret = pin;
 158                goto unlock;
 159        }
 160
 161        ret = pin_config_set_for_pin(pctldev, pin, config);
 162
 163unlock:
 164        mutex_unlock(&pinctrl_mutex);
 165        return ret;
 166}
 167EXPORT_SYMBOL(pin_config_set);
 168
 169int pin_config_group_get(const char *dev_name, const char *pin_group,
 170                         unsigned long *config)
 171{
 172        struct pinctrl_dev *pctldev;
 173        const struct pinconf_ops *ops;
 174        int selector, ret;
 175
 176        mutex_lock(&pinctrl_mutex);
 177
 178        pctldev = get_pinctrl_dev_from_devname(dev_name);
 179        if (!pctldev) {
 180                ret = -EINVAL;
 181                goto unlock;
 182        }
 183        ops = pctldev->desc->confops;
 184
 185        if (!ops || !ops->pin_config_group_get) {
 186                dev_err(pctldev->dev, "cannot get configuration for pin "
 187                        "group, missing group config get function in "
 188                        "driver\n");
 189                ret = -EINVAL;
 190                goto unlock;
 191        }
 192
 193        selector = pinctrl_get_group_selector(pctldev, pin_group);
 194        if (selector < 0) {
 195                ret = selector;
 196                goto unlock;
 197        }
 198
 199        ret = ops->pin_config_group_get(pctldev, selector, config);
 200
 201unlock:
 202        mutex_unlock(&pinctrl_mutex);
 203        return ret;
 204}
 205EXPORT_SYMBOL(pin_config_group_get);
 206
 207int pin_config_group_set(const char *dev_name, const char *pin_group,
 208                         unsigned long config)
 209{
 210        struct pinctrl_dev *pctldev;
 211        const struct pinconf_ops *ops;
 212        const struct pinctrl_ops *pctlops;
 213        int selector;
 214        const unsigned *pins;
 215        unsigned num_pins;
 216        int ret;
 217        int i;
 218
 219        mutex_lock(&pinctrl_mutex);
 220
 221        pctldev = get_pinctrl_dev_from_devname(dev_name);
 222        if (!pctldev) {
 223                ret = -EINVAL;
 224                goto unlock;
 225        }
 226        ops = pctldev->desc->confops;
 227        pctlops = pctldev->desc->pctlops;
 228
 229        if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) {
 230                dev_err(pctldev->dev, "cannot configure pin group, missing "
 231                        "config function in driver\n");
 232                ret = -EINVAL;
 233                goto unlock;
 234        }
 235
 236        selector = pinctrl_get_group_selector(pctldev, pin_group);
 237        if (selector < 0) {
 238                ret = selector;
 239                goto unlock;
 240        }
 241
 242        ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins);
 243        if (ret) {
 244                dev_err(pctldev->dev, "cannot configure pin group, error "
 245                        "getting pins\n");
 246                goto unlock;
 247        }
 248
 249        /*
 250         * If the pin controller supports handling entire groups we use that
 251         * capability.
 252         */
 253        if (ops->pin_config_group_set) {
 254                ret = ops->pin_config_group_set(pctldev, selector, config);
 255                /*
 256                 * If the pin controller prefer that a certain group be handled
 257                 * pin-by-pin as well, it returns -EAGAIN.
 258                 */
 259                if (ret != -EAGAIN)
 260                        goto unlock;
 261        }
 262
 263        /*
 264         * If the controller cannot handle entire groups, we configure each pin
 265         * individually.
 266         */
 267        if (!ops->pin_config_set) {
 268                ret = 0;
 269                goto unlock;
 270        }
 271
 272        for (i = 0; i < num_pins; i++) {
 273                ret = ops->pin_config_set(pctldev, pins[i], config);
 274                if (ret < 0)
 275                        goto unlock;
 276        }
 277
 278        ret = 0;
 279
 280unlock:
 281        mutex_unlock(&pinctrl_mutex);
 282
 283        return ret;
 284}
 285EXPORT_SYMBOL(pin_config_group_set);
 286
 287int pinconf_map_to_setting(struct pinctrl_map const *map,
 288                          struct pinctrl_setting *setting)
 289{
 290        struct pinctrl_dev *pctldev = setting->pctldev;
 291        int pin;
 292
 293        switch (setting->type) {
 294        case PIN_MAP_TYPE_CONFIGS_PIN:
 295                pin = pin_get_from_name(pctldev,
 296                                        map->data.configs.group_or_pin);
 297                if (pin < 0) {
 298                        dev_err(pctldev->dev, "could not map pin config for \"%s\"",
 299                                map->data.configs.group_or_pin);
 300                        return pin;
 301                }
 302                setting->data.configs.group_or_pin = pin;
 303                break;
 304        case PIN_MAP_TYPE_CONFIGS_GROUP:
 305                pin = pinctrl_get_group_selector(pctldev,
 306                                         map->data.configs.group_or_pin);
 307                if (pin < 0) {
 308                        dev_err(pctldev->dev, "could not map group config for \"%s\"",
 309                                map->data.configs.group_or_pin);
 310                        return pin;
 311                }
 312                setting->data.configs.group_or_pin = pin;
 313                break;
 314        default:
 315                return -EINVAL;
 316        }
 317
 318        setting->data.configs.num_configs = map->data.configs.num_configs;
 319        setting->data.configs.configs = map->data.configs.configs;
 320
 321        return 0;
 322}
 323
 324void pinconf_free_setting(struct pinctrl_setting const *setting)
 325{
 326}
 327
 328int pinconf_apply_setting(struct pinctrl_setting const *setting)
 329{
 330        struct pinctrl_dev *pctldev = setting->pctldev;
 331        const struct pinconf_ops *ops = pctldev->desc->confops;
 332        int i, ret;
 333
 334        if (!ops) {
 335                dev_err(pctldev->dev, "missing confops\n");
 336                return -EINVAL;
 337        }
 338
 339        switch (setting->type) {
 340        case PIN_MAP_TYPE_CONFIGS_PIN:
 341                if (!ops->pin_config_set) {
 342                        dev_err(pctldev->dev, "missing pin_config_set op\n");
 343                        return -EINVAL;
 344                }
 345                for (i = 0; i < setting->data.configs.num_configs; i++) {
 346                        ret = ops->pin_config_set(pctldev,
 347                                        setting->data.configs.group_or_pin,
 348                                        setting->data.configs.configs[i]);
 349                        if (ret < 0) {
 350                                dev_err(pctldev->dev,
 351                                        "pin_config_set op failed for pin %d config %08lx\n",
 352                                        setting->data.configs.group_or_pin,
 353                                        setting->data.configs.configs[i]);
 354                                return ret;
 355                        }
 356                }
 357                break;
 358        case PIN_MAP_TYPE_CONFIGS_GROUP:
 359                if (!ops->pin_config_group_set) {
 360                        dev_err(pctldev->dev,
 361                                "missing pin_config_group_set op\n");
 362                        return -EINVAL;
 363                }
 364                for (i = 0; i < setting->data.configs.num_configs; i++) {
 365                        ret = ops->pin_config_group_set(pctldev,
 366                                        setting->data.configs.group_or_pin,
 367                                        setting->data.configs.configs[i]);
 368                        if (ret < 0) {
 369                                dev_err(pctldev->dev,
 370                                        "pin_config_group_set op failed for group %d config %08lx\n",
 371                                        setting->data.configs.group_or_pin,
 372                                        setting->data.configs.configs[i]);
 373                                return ret;
 374                        }
 375                }
 376                break;
 377        default:
 378                return -EINVAL;
 379        }
 380
 381        return 0;
 382}
 383
 384#ifdef CONFIG_DEBUG_FS
 385
 386void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
 387{
 388        struct pinctrl_dev *pctldev;
 389        const struct pinconf_ops *confops;
 390        int i;
 391
 392        pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
 393        if (pctldev)
 394                confops = pctldev->desc->confops;
 395        else
 396                confops = NULL;
 397
 398        switch (map->type) {
 399        case PIN_MAP_TYPE_CONFIGS_PIN:
 400                seq_printf(s, "pin ");
 401                break;
 402        case PIN_MAP_TYPE_CONFIGS_GROUP:
 403                seq_printf(s, "group ");
 404                break;
 405        default:
 406                break;
 407        }
 408
 409        seq_printf(s, "%s\n", map->data.configs.group_or_pin);
 410
 411        for (i = 0; i < map->data.configs.num_configs; i++) {
 412                seq_printf(s, "config ");
 413                if (confops && confops->pin_config_config_dbg_show)
 414                        confops->pin_config_config_dbg_show(pctldev, s,
 415                                                map->data.configs.configs[i]);
 416                else
 417                        seq_printf(s, "%08lx", map->data.configs.configs[i]);
 418                seq_printf(s, "\n");
 419        }
 420}
 421
 422void pinconf_show_setting(struct seq_file *s,
 423                          struct pinctrl_setting const *setting)
 424{
 425        struct pinctrl_dev *pctldev = setting->pctldev;
 426        const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
 427        const struct pinconf_ops *confops = pctldev->desc->confops;
 428        struct pin_desc *desc;
 429        int i;
 430
 431        switch (setting->type) {
 432        case PIN_MAP_TYPE_CONFIGS_PIN:
 433                desc = pin_desc_get(setting->pctldev,
 434                                    setting->data.configs.group_or_pin);
 435                seq_printf(s, "pin %s (%d)",
 436                           desc->name ? desc->name : "unnamed",
 437                           setting->data.configs.group_or_pin);
 438                break;
 439        case PIN_MAP_TYPE_CONFIGS_GROUP:
 440                seq_printf(s, "group %s (%d)",
 441                           pctlops->get_group_name(pctldev,
 442                                        setting->data.configs.group_or_pin),
 443                           setting->data.configs.group_or_pin);
 444                break;
 445        default:
 446                break;
 447        }
 448
 449        /*
 450         * FIXME: We should really get the pin controler to dump the config
 451         * values, so they can be decoded to something meaningful.
 452         */
 453        for (i = 0; i < setting->data.configs.num_configs; i++) {
 454                seq_printf(s, " ");
 455                if (confops && confops->pin_config_config_dbg_show)
 456                        confops->pin_config_config_dbg_show(pctldev, s,
 457                                setting->data.configs.configs[i]);
 458                else
 459                        seq_printf(s, "%08lx",
 460                                   setting->data.configs.configs[i]);
 461        }
 462
 463        seq_printf(s, "\n");
 464}
 465
 466static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
 467                             struct seq_file *s, int pin)
 468{
 469        const struct pinconf_ops *ops = pctldev->desc->confops;
 470
 471        /* no-op when not using generic pin config */
 472        pinconf_generic_dump_pin(pctldev, s, pin);
 473        if (ops && ops->pin_config_dbg_show)
 474                ops->pin_config_dbg_show(pctldev, s, pin);
 475}
 476
 477static int pinconf_pins_show(struct seq_file *s, void *what)
 478{
 479        struct pinctrl_dev *pctldev = s->private;
 480        const struct pinconf_ops *ops = pctldev->desc->confops;
 481        unsigned i, pin;
 482
 483        if (!ops || !ops->pin_config_get)
 484                return 0;
 485
 486        seq_puts(s, "Pin config settings per pin\n");
 487        seq_puts(s, "Format: pin (name): configs\n");
 488
 489        mutex_lock(&pinctrl_mutex);
 490
 491        /* The pin number can be retrived from the pin controller descriptor */
 492        for (i = 0; i < pctldev->desc->npins; i++) {
 493                struct pin_desc *desc;
 494
 495                pin = pctldev->desc->pins[i].number;
 496                desc = pin_desc_get(pctldev, pin);
 497                /* Skip if we cannot search the pin */
 498                if (desc == NULL)
 499                        continue;
 500
 501                seq_printf(s, "pin %d (%s):", pin,
 502                           desc->name ? desc->name : "unnamed");
 503
 504                pinconf_dump_pin(pctldev, s, pin);
 505
 506                seq_printf(s, "\n");
 507        }
 508
 509        mutex_unlock(&pinctrl_mutex);
 510
 511        return 0;
 512}
 513
 514static void pinconf_dump_group(struct pinctrl_dev *pctldev,
 515                               struct seq_file *s, unsigned selector,
 516                               const char *gname)
 517{
 518        const struct pinconf_ops *ops = pctldev->desc->confops;
 519
 520        /* no-op when not using generic pin config */
 521        pinconf_generic_dump_group(pctldev, s, gname);
 522        if (ops && ops->pin_config_group_dbg_show)
 523                ops->pin_config_group_dbg_show(pctldev, s, selector);
 524}
 525
 526static int pinconf_groups_show(struct seq_file *s, void *what)
 527{
 528        struct pinctrl_dev *pctldev = s->private;
 529        const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
 530        const struct pinconf_ops *ops = pctldev->desc->confops;
 531        unsigned ngroups = pctlops->get_groups_count(pctldev);
 532        unsigned selector = 0;
 533
 534        if (!ops || !ops->pin_config_group_get)
 535                return 0;
 536
 537        seq_puts(s, "Pin config settings per pin group\n");
 538        seq_puts(s, "Format: group (name): configs\n");
 539
 540        while (selector < ngroups) {
 541                const char *gname = pctlops->get_group_name(pctldev, selector);
 542
 543                seq_printf(s, "%u (%s):", selector, gname);
 544                pinconf_dump_group(pctldev, s, selector, gname);
 545                seq_printf(s, "\n");
 546
 547                selector++;
 548        }
 549
 550        return 0;
 551}
 552
 553static int pinconf_pins_open(struct inode *inode, struct file *file)
 554{
 555        return single_open(file, pinconf_pins_show, inode->i_private);
 556}
 557
 558static int pinconf_groups_open(struct inode *inode, struct file *file)
 559{
 560        return single_open(file, pinconf_groups_show, inode->i_private);
 561}
 562
 563static const struct file_operations pinconf_pins_ops = {
 564        .open           = pinconf_pins_open,
 565        .read           = seq_read,
 566        .llseek         = seq_lseek,
 567        .release        = single_release,
 568};
 569
 570static const struct file_operations pinconf_groups_ops = {
 571        .open           = pinconf_groups_open,
 572        .read           = seq_read,
 573        .llseek         = seq_lseek,
 574        .release        = single_release,
 575};
 576
 577void pinconf_init_device_debugfs(struct dentry *devroot,
 578                         struct pinctrl_dev *pctldev)
 579{
 580        debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO,
 581                            devroot, pctldev, &pinconf_pins_ops);
 582        debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
 583                            devroot, pctldev, &pinconf_groups_ops);
 584}
 585
 586#endif
 587
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.