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/uaccess.h>
  21#include <linux/pinctrl/machine.h>
  22#include <linux/pinctrl/pinctrl.h>
  23#include <linux/pinctrl/pinconf.h>
  24#include "core.h"
  25#include "pinconf.h"
  26
  27int pinconf_check_ops(struct pinctrl_dev *pctldev)
  28{
  29        const struct pinconf_ops *ops = pctldev->desc->confops;
  30
  31        /* We have to be able to config the pins in SOME way */
  32        if (!ops->pin_config_set && !ops->pin_config_group_set) {
  33                dev_err(pctldev->dev,
  34                        "pinconf has to be able to set a pins config\n");
  35                return -EINVAL;
  36        }
  37        return 0;
  38}
  39
  40int pinconf_validate_map(const struct pinctrl_map *map, int i)
  41{
  42        if (!map->data.configs.group_or_pin) {
  43                pr_err("failed to register map %s (%d): no group/pin given\n",
  44                       map->name, i);
  45                return -EINVAL;
  46        }
  47
  48        if (!map->data.configs.num_configs ||
  49                        !map->data.configs.configs) {
  50                pr_err("failed to register map %s (%d): no configs given\n",
  51                       map->name, i);
  52                return -EINVAL;
  53        }
  54
  55        return 0;
  56}
  57
  58int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
  59                           unsigned long *config)
  60{
  61        const struct pinconf_ops *ops = pctldev->desc->confops;
  62
  63        if (!ops || !ops->pin_config_get) {
  64                dev_dbg(pctldev->dev,
  65                        "cannot get pin configuration, .pin_config_get missing in driver\n");
  66                return -ENOTSUPP;
  67        }
  68
  69        return ops->pin_config_get(pctldev, pin, config);
  70}
  71
  72int pin_config_group_get(const char *dev_name, const char *pin_group,
  73                         unsigned long *config)
  74{
  75        struct pinctrl_dev *pctldev;
  76        const struct pinconf_ops *ops;
  77        int selector, ret;
  78
  79        pctldev = get_pinctrl_dev_from_devname(dev_name);
  80        if (!pctldev) {
  81                ret = -EINVAL;
  82                return ret;
  83        }
  84
  85        mutex_lock(&pctldev->mutex);
  86
  87        ops = pctldev->desc->confops;
  88
  89        if (!ops || !ops->pin_config_group_get) {
  90                dev_dbg(pctldev->dev,
  91                        "cannot get configuration for pin group, missing group config get function in driver\n");
  92                ret = -ENOTSUPP;
  93                goto unlock;
  94        }
  95
  96        selector = pinctrl_get_group_selector(pctldev, pin_group);
  97        if (selector < 0) {
  98                ret = selector;
  99                goto unlock;
 100        }
 101
 102        ret = ops->pin_config_group_get(pctldev, selector, config);
 103
 104unlock:
 105        mutex_unlock(&pctldev->mutex);
 106        return ret;
 107}
 108
 109int pinconf_map_to_setting(const struct pinctrl_map *map,
 110                          struct pinctrl_setting *setting)
 111{
 112        struct pinctrl_dev *pctldev = setting->pctldev;
 113        int pin;
 114
 115        switch (setting->type) {
 116        case PIN_MAP_TYPE_CONFIGS_PIN:
 117                pin = pin_get_from_name(pctldev,
 118                                        map->data.configs.group_or_pin);
 119                if (pin < 0) {
 120                        dev_err(pctldev->dev, "could not map pin config for \"%s\"",
 121                                map->data.configs.group_or_pin);
 122                        return pin;
 123                }
 124                setting->data.configs.group_or_pin = pin;
 125                break;
 126        case PIN_MAP_TYPE_CONFIGS_GROUP:
 127                pin = pinctrl_get_group_selector(pctldev,
 128                                         map->data.configs.group_or_pin);
 129                if (pin < 0) {
 130                        dev_err(pctldev->dev, "could not map group config for \"%s\"",
 131                                map->data.configs.group_or_pin);
 132                        return pin;
 133                }
 134                setting->data.configs.group_or_pin = pin;
 135                break;
 136        default:
 137                return -EINVAL;
 138        }
 139
 140        setting->data.configs.num_configs = map->data.configs.num_configs;
 141        setting->data.configs.configs = map->data.configs.configs;
 142
 143        return 0;
 144}
 145
 146void pinconf_free_setting(const struct pinctrl_setting *setting)
 147{
 148}
 149
 150int pinconf_apply_setting(const struct pinctrl_setting *setting)
 151{
 152        struct pinctrl_dev *pctldev = setting->pctldev;
 153        const struct pinconf_ops *ops = pctldev->desc->confops;
 154        int ret;
 155
 156        if (!ops) {
 157                dev_err(pctldev->dev, "missing confops\n");
 158                return -EINVAL;
 159        }
 160
 161        switch (setting->type) {
 162        case PIN_MAP_TYPE_CONFIGS_PIN:
 163                if (!ops->pin_config_set) {
 164                        dev_err(pctldev->dev, "missing pin_config_set op\n");
 165                        return -EINVAL;
 166                }
 167                ret = ops->pin_config_set(pctldev,
 168                                setting->data.configs.group_or_pin,
 169                                setting->data.configs.configs,
 170                                setting->data.configs.num_configs);
 171                if (ret < 0) {
 172                        dev_err(pctldev->dev,
 173                                "pin_config_set op failed for pin %d\n",
 174                                setting->data.configs.group_or_pin);
 175                        return ret;
 176                }
 177                break;
 178        case PIN_MAP_TYPE_CONFIGS_GROUP:
 179                if (!ops->pin_config_group_set) {
 180                        dev_err(pctldev->dev,
 181                                "missing pin_config_group_set op\n");
 182                        return -EINVAL;
 183                }
 184                ret = ops->pin_config_group_set(pctldev,
 185                                setting->data.configs.group_or_pin,
 186                                setting->data.configs.configs,
 187                                setting->data.configs.num_configs);
 188                if (ret < 0) {
 189                        dev_err(pctldev->dev,
 190                                "pin_config_group_set op failed for group %d\n",
 191                                setting->data.configs.group_or_pin);
 192                        return ret;
 193                }
 194                break;
 195        default:
 196                return -EINVAL;
 197        }
 198
 199        return 0;
 200}
 201
 202int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
 203                       unsigned long *configs, size_t nconfigs)
 204{
 205        const struct pinconf_ops *ops;
 206
 207        ops = pctldev->desc->confops;
 208        if (!ops || !ops->pin_config_set)
 209                return -ENOTSUPP;
 210
 211        return ops->pin_config_set(pctldev, pin, configs, nconfigs);
 212}
 213
 214#ifdef CONFIG_DEBUG_FS
 215
 216static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev,
 217                      unsigned long *configs, unsigned num_configs)
 218{
 219        const struct pinconf_ops *confops;
 220        int i;
 221
 222        if (pctldev)
 223                confops = pctldev->desc->confops;
 224        else
 225                confops = NULL;
 226
 227        for (i = 0; i < num_configs; i++) {
 228                seq_puts(s, "config ");
 229                if (confops && confops->pin_config_config_dbg_show)
 230                        confops->pin_config_config_dbg_show(pctldev, s,
 231                                                            configs[i]);
 232                else
 233                        seq_printf(s, "%08lx", configs[i]);
 234                seq_putc(s, '\n');
 235        }
 236}
 237
 238void pinconf_show_map(struct seq_file *s, const struct pinctrl_map *map)
 239{
 240        struct pinctrl_dev *pctldev;
 241
 242        pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
 243
 244        switch (map->type) {
 245        case PIN_MAP_TYPE_CONFIGS_PIN:
 246                seq_puts(s, "pin ");
 247                break;
 248        case PIN_MAP_TYPE_CONFIGS_GROUP:
 249                seq_puts(s, "group ");
 250                break;
 251        default:
 252                break;
 253        }
 254
 255        seq_printf(s, "%s\n", map->data.configs.group_or_pin);
 256
 257        pinconf_show_config(s, pctldev, map->data.configs.configs,
 258                            map->data.configs.num_configs);
 259}
 260
 261void pinconf_show_setting(struct seq_file *s,
 262                          const struct pinctrl_setting *setting)
 263{
 264        struct pinctrl_dev *pctldev = setting->pctldev;
 265        const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
 266        struct pin_desc *desc;
 267
 268        switch (setting->type) {
 269        case PIN_MAP_TYPE_CONFIGS_PIN:
 270                desc = pin_desc_get(setting->pctldev,
 271                                    setting->data.configs.group_or_pin);
 272                seq_printf(s, "pin %s (%d)", desc->name,
 273                           setting->data.configs.group_or_pin);
 274                break;
 275        case PIN_MAP_TYPE_CONFIGS_GROUP:
 276                seq_printf(s, "group %s (%d)",
 277                           pctlops->get_group_name(pctldev,
 278                                        setting->data.configs.group_or_pin),
 279                           setting->data.configs.group_or_pin);
 280                break;
 281        default:
 282                break;
 283        }
 284
 285        /*
 286         * FIXME: We should really get the pin controller to dump the config
 287         * values, so they can be decoded to something meaningful.
 288         */
 289        pinconf_show_config(s, pctldev, setting->data.configs.configs,
 290                            setting->data.configs.num_configs);
 291}
 292
 293static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
 294                             struct seq_file *s, int pin)
 295{
 296        const struct pinconf_ops *ops = pctldev->desc->confops;
 297
 298        /* no-op when not using generic pin config */
 299        pinconf_generic_dump_pins(pctldev, s, NULL, pin);
 300        if (ops && ops->pin_config_dbg_show)
 301                ops->pin_config_dbg_show(pctldev, s, pin);
 302}
 303
 304static int pinconf_pins_show(struct seq_file *s, void *what)
 305{
 306        struct pinctrl_dev *pctldev = s->private;
 307        unsigned i, pin;
 308
 309        seq_puts(s, "Pin config settings per pin\n");
 310        seq_puts(s, "Format: pin (name): configs\n");
 311
 312        mutex_lock(&pctldev->mutex);
 313
 314        /* The pin number can be retrived from the pin controller descriptor */
 315        for (i = 0; i < pctldev->desc->npins; i++) {
 316                struct pin_desc *desc;
 317
 318                pin = pctldev->desc->pins[i].number;
 319                desc = pin_desc_get(pctldev, pin);
 320                /* Skip if we cannot search the pin */
 321                if (!desc)
 322                        continue;
 323
 324                seq_printf(s, "pin %d (%s): ", pin, desc->name);
 325
 326                pinconf_dump_pin(pctldev, s, pin);
 327                seq_putc(s, '\n');
 328        }
 329
 330        mutex_unlock(&pctldev->mutex);
 331
 332        return 0;
 333}
 334
 335static void pinconf_dump_group(struct pinctrl_dev *pctldev,
 336                               struct seq_file *s, unsigned selector,
 337                               const char *gname)
 338{
 339        const struct pinconf_ops *ops = pctldev->desc->confops;
 340
 341        /* no-op when not using generic pin config */
 342        pinconf_generic_dump_pins(pctldev, s, gname, 0);
 343        if (ops && ops->pin_config_group_dbg_show)
 344                ops->pin_config_group_dbg_show(pctldev, s, selector);
 345}
 346
 347static int pinconf_groups_show(struct seq_file *s, void *what)
 348{
 349        struct pinctrl_dev *pctldev = s->private;
 350        const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
 351        unsigned ngroups = pctlops->get_groups_count(pctldev);
 352        unsigned selector = 0;
 353
 354        seq_puts(s, "Pin config settings per pin group\n");
 355        seq_puts(s, "Format: group (name): configs\n");
 356
 357        while (selector < ngroups) {
 358                const char *gname = pctlops->get_group_name(pctldev, selector);
 359
 360                seq_printf(s, "%u (%s): ", selector, gname);
 361                pinconf_dump_group(pctldev, s, selector, gname);
 362                seq_putc(s, '\n');
 363                selector++;
 364        }
 365
 366        return 0;
 367}
 368
 369DEFINE_SHOW_ATTRIBUTE(pinconf_pins);
 370DEFINE_SHOW_ATTRIBUTE(pinconf_groups);
 371
 372#define MAX_NAME_LEN 15
 373
 374struct dbg_cfg {
 375        enum pinctrl_map_type map_type;
 376        char dev_name[MAX_NAME_LEN + 1];
 377        char state_name[MAX_NAME_LEN + 1];
 378        char pin_name[MAX_NAME_LEN + 1];
 379};
 380
 381/*
 382 * Goal is to keep this structure as global in order to simply read the
 383 * pinconf-config file after a write to check config is as expected
 384 */
 385static struct dbg_cfg pinconf_dbg_conf;
 386
 387/**
 388 * pinconf_dbg_config_print() - display the pinctrl config from the pinctrl
 389 * map, of the dev/pin/state that was last written to pinconf-config file.
 390 * @s: string filled in  with config description
 391 * @d: not used
 392 */
 393static int pinconf_dbg_config_print(struct seq_file *s, void *d)
 394{
 395        struct pinctrl_maps *maps_node;
 396        const struct pinctrl_map *map;
 397        const struct pinctrl_map *found = NULL;
 398        struct pinctrl_dev *pctldev;
 399        struct dbg_cfg *dbg = &pinconf_dbg_conf;
 400        int i;
 401
 402        mutex_lock(&pinctrl_maps_mutex);
 403
 404        /* Parse the pinctrl map and look for the elected pin/state */
 405        for_each_maps(maps_node, i, map) {
 406                if (map->type != dbg->map_type)
 407                        continue;
 408                if (strcmp(map->dev_name, dbg->dev_name))
 409                        continue;
 410                if (strcmp(map->name, dbg->state_name))
 411                        continue;
 412
 413                if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) {
 414                        /* We found the right pin */
 415                        found = map;
 416                        break;
 417                }
 418        }
 419
 420        if (!found) {
 421                seq_printf(s, "No config found for dev/state/pin, expected:\n");
 422                seq_printf(s, "Searched dev:%s\n", dbg->dev_name);
 423                seq_printf(s, "Searched state:%s\n", dbg->state_name);
 424                seq_printf(s, "Searched pin:%s\n", dbg->pin_name);
 425                seq_printf(s, "Use: modify config_pin <devname> "\
 426                                "<state> <pinname> <value>\n");
 427                goto exit;
 428        }
 429
 430        pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name);
 431        seq_printf(s, "Dev %s has config of %s in state %s:\n",
 432                   dbg->dev_name, dbg->pin_name, dbg->state_name);
 433        pinconf_show_config(s, pctldev, found->data.configs.configs,
 434                            found->data.configs.num_configs);
 435
 436exit:
 437        mutex_unlock(&pinctrl_maps_mutex);
 438
 439        return 0;
 440}
 441
 442/**
 443 * pinconf_dbg_config_write() - modify the pinctrl config in the pinctrl
 444 * map, of a dev/pin/state entry based on user entries to pinconf-config
 445 * @user_buf: contains the modification request with expected format:
 446 *     modify <config> <devicename> <state> <name> <newvalue>
 447 * modify is literal string, alternatives like add/delete not supported yet
 448 * <config> is the configuration to be changed. Supported configs are
 449 *     "config_pin" or "config_group", alternatives like config_mux are not
 450 *     supported yet.
 451 * <devicename> <state> <name> are values that should match the pinctrl-maps
 452 * <newvalue> reflects the new config and is driver dependent
 453 */
 454static ssize_t pinconf_dbg_config_write(struct file *file,
 455        const char __user *user_buf, size_t count, loff_t *ppos)
 456{
 457        struct pinctrl_maps *maps_node;
 458        const struct pinctrl_map *map;
 459        const struct pinctrl_map *found = NULL;
 460        struct pinctrl_dev *pctldev;
 461        const struct pinconf_ops *confops = NULL;
 462        struct dbg_cfg *dbg = &pinconf_dbg_conf;
 463        const struct pinctrl_map_configs *configs;
 464        char config[MAX_NAME_LEN + 1];
 465        char buf[128];
 466        char *b = &buf[0];
 467        int buf_size;
 468        char *token;
 469        int i;
 470
 471        /* Get userspace string and assure termination */
 472        buf_size = min(count, sizeof(buf) - 1);
 473        if (copy_from_user(buf, user_buf, buf_size))
 474                return -EFAULT;
 475        buf[buf_size] = 0;
 476
 477        /*
 478         * need to parse entry and extract parameters:
 479         * modify configs_pin devicename state pinname newvalue
 480         */
 481
 482        /* Get arg: 'modify' */
 483        token = strsep(&b, " ");
 484        if (!token)
 485                return -EINVAL;
 486        if (strcmp(token, "modify"))
 487                return -EINVAL;
 488
 489        /*
 490         * Get arg type: "config_pin" and "config_group"
 491         *                types are supported so far
 492         */
 493        token = strsep(&b, " ");
 494        if (!token)
 495                return -EINVAL;
 496        if (!strcmp(token, "config_pin"))
 497                dbg->map_type = PIN_MAP_TYPE_CONFIGS_PIN;
 498        else if (!strcmp(token, "config_group"))
 499                dbg->map_type = PIN_MAP_TYPE_CONFIGS_GROUP;
 500        else
 501                return -EINVAL;
 502
 503        /* get arg 'device_name' */
 504        token = strsep(&b, " ");
 505        if (!token)
 506                return -EINVAL;
 507        if (strlen(token) >= MAX_NAME_LEN)
 508                return -EINVAL;
 509        strncpy(dbg->dev_name, token, MAX_NAME_LEN);
 510
 511        /* get arg 'state_name' */
 512        token = strsep(&b, " ");
 513        if (!token)
 514                return -EINVAL;
 515        if (strlen(token) >= MAX_NAME_LEN)
 516                return -EINVAL;
 517        strncpy(dbg->state_name, token, MAX_NAME_LEN);
 518
 519        /* get arg 'pin_name' */
 520        token = strsep(&b, " ");
 521        if (!token)
 522                return -EINVAL;
 523        if (strlen(token) >= MAX_NAME_LEN)
 524                return -EINVAL;
 525        strncpy(dbg->pin_name, token, MAX_NAME_LEN);
 526
 527        /* get new_value of config' */
 528        token = strsep(&b, " ");
 529        if (!token)
 530                return -EINVAL;
 531        if (strlen(token) >= MAX_NAME_LEN)
 532                return -EINVAL;
 533        strncpy(config, token, MAX_NAME_LEN);
 534
 535        mutex_lock(&pinctrl_maps_mutex);
 536
 537        /* Parse the pinctrl map and look for the selected dev/state/pin */
 538        for_each_maps(maps_node, i, map) {
 539                if (strcmp(map->dev_name, dbg->dev_name))
 540                        continue;
 541                if (map->type != dbg->map_type)
 542                        continue;
 543                if (strcmp(map->name, dbg->state_name))
 544                        continue;
 545
 546                /*  we found the right pin / state, so overwrite config */
 547                if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) {
 548                        found = map;
 549                        break;
 550                }
 551        }
 552
 553        if (!found) {
 554                count = -EINVAL;
 555                goto exit;
 556        }
 557
 558        pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name);
 559        if (pctldev)
 560                confops = pctldev->desc->confops;
 561
 562        if (confops && confops->pin_config_dbg_parse_modify) {
 563                configs = &found->data.configs;
 564                for (i = 0; i < configs->num_configs; i++) {
 565                        confops->pin_config_dbg_parse_modify(pctldev,
 566                                                     config,
 567                                                     &configs->configs[i]);
 568                }
 569        }
 570
 571exit:
 572        mutex_unlock(&pinctrl_maps_mutex);
 573
 574        return count;
 575}
 576
 577static int pinconf_dbg_config_open(struct inode *inode, struct file *file)
 578{
 579        return single_open(file, pinconf_dbg_config_print, inode->i_private);
 580}
 581
 582static const struct file_operations pinconf_dbg_pinconfig_fops = {
 583        .open = pinconf_dbg_config_open,
 584        .write = pinconf_dbg_config_write,
 585        .read = seq_read,
 586        .llseek = seq_lseek,
 587        .release = single_release,
 588        .owner = THIS_MODULE,
 589};
 590
 591void pinconf_init_device_debugfs(struct dentry *devroot,
 592                         struct pinctrl_dev *pctldev)
 593{
 594        debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO,
 595                            devroot, pctldev, &pinconf_pins_fops);
 596        debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
 597                            devroot, pctldev, &pinconf_groups_fops);
 598        debugfs_create_file("pinconf-config",  (S_IRUGO | S_IWUSR | S_IWGRP),
 599                            devroot, pctldev, &pinconf_dbg_pinconfig_fops);
 600}
 601
 602#endif
 603