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 pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
  27                           unsigned long *config)
  28{
  29        const struct pinconf_ops *ops = pctldev->desc->confops;
  30
  31        if (!ops || !ops->pin_config_get) {
  32                dev_err(pctldev->dev, "cannot get pin configuration, missing "
  33                        "pin_config_get() function in driver\n");
  34                return -EINVAL;
  35        }
  36
  37        return ops->pin_config_get(pctldev, pin, config);
  38}
  39
  40/**
  41 * pin_config_get() - get the configuration of a single pin parameter
  42 * @dev_name: name of the pin controller device for this pin
  43 * @name: name of the pin to get the config for
  44 * @config: the config pointed to by this argument will be filled in with the
  45 *      current pin state, it can be used directly by drivers as a numeral, or
  46 *      it can be dereferenced to any struct.
  47 */
  48int pin_config_get(const char *dev_name, const char *name,
  49                          unsigned long *config)
  50{
  51        struct pinctrl_dev *pctldev;
  52        int pin;
  53
  54        pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
  55        if (!pctldev)
  56                return -EINVAL;
  57
  58        pin = pin_get_from_name(pctldev, name);
  59        if (pin < 0)
  60                return pin;
  61
  62        return pin_config_get_for_pin(pctldev, pin, config);
  63}
  64EXPORT_SYMBOL(pin_config_get);
  65
  66int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
  67                           unsigned long config)
  68{
  69        const struct pinconf_ops *ops = pctldev->desc->confops;
  70        int ret;
  71
  72        if (!ops || !ops->pin_config_set) {
  73                dev_err(pctldev->dev, "cannot configure pin, missing "
  74                        "config function in driver\n");
  75                return -EINVAL;
  76        }
  77
  78        ret = ops->pin_config_set(pctldev, pin, config);
  79        if (ret) {
  80                dev_err(pctldev->dev,
  81                        "unable to set pin configuration on pin %d\n", pin);
  82                return ret;
  83        }
  84
  85        return 0;
  86}
  87
  88/**
  89 * pin_config_set() - set the configuration of a single pin parameter
  90 * @dev_name: name of pin controller device for this pin
  91 * @name: name of the pin to set the config for
  92 * @config: the config in this argument will contain the desired pin state, it
  93 *      can be used directly by drivers as a numeral, or it can be dereferenced
  94 *      to any struct.
  95 */
  96int pin_config_set(const char *dev_name, const char *name,
  97                   unsigned long config)
  98{
  99        struct pinctrl_dev *pctldev;
 100        int pin;
 101
 102        pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
 103        if (!pctldev)
 104                return -EINVAL;
 105
 106        pin = pin_get_from_name(pctldev, name);
 107        if (pin < 0)
 108                return pin;
 109
 110        return pin_config_set_for_pin(pctldev, pin, config);
 111}
 112EXPORT_SYMBOL(pin_config_set);
 113
 114int pin_config_group_get(const char *dev_name, const char *pin_group,
 115                         unsigned long *config)
 116{
 117        struct pinctrl_dev *pctldev;
 118        const struct pinconf_ops *ops;
 119        int selector;
 120
 121        pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
 122        if (!pctldev)
 123                return -EINVAL;
 124        ops = pctldev->desc->confops;
 125
 126        if (!ops || !ops->pin_config_group_get) {
 127                dev_err(pctldev->dev, "cannot get configuration for pin "
 128                        "group, missing group config get function in "
 129                        "driver\n");
 130                return -EINVAL;
 131        }
 132
 133        selector = pinctrl_get_group_selector(pctldev, pin_group);
 134        if (selector < 0)
 135                return selector;
 136
 137        return ops->pin_config_group_get(pctldev, selector, config);
 138}
 139EXPORT_SYMBOL(pin_config_group_get);
 140
 141
 142int pin_config_group_set(const char *dev_name, const char *pin_group,
 143                         unsigned long config)
 144{
 145        struct pinctrl_dev *pctldev;
 146        const struct pinconf_ops *ops;
 147        const struct pinctrl_ops *pctlops;
 148        int selector;
 149        const unsigned *pins;
 150        unsigned num_pins;
 151        int ret;
 152        int i;
 153
 154        pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
 155        if (!pctldev)
 156                return -EINVAL;
 157        ops = pctldev->desc->confops;
 158        pctlops = pctldev->desc->pctlops;
 159
 160        if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) {
 161                dev_err(pctldev->dev, "cannot configure pin group, missing "
 162                        "config function in driver\n");
 163                return -EINVAL;
 164        }
 165
 166        selector = pinctrl_get_group_selector(pctldev, pin_group);
 167        if (selector < 0)
 168                return selector;
 169
 170        ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins);
 171        if (ret) {
 172                dev_err(pctldev->dev, "cannot configure pin group, error "
 173                        "getting pins\n");
 174                return ret;
 175        }
 176
 177        /*
 178         * If the pin controller supports handling entire groups we use that
 179         * capability.
 180         */
 181        if (ops->pin_config_group_set) {
 182                ret = ops->pin_config_group_set(pctldev, selector, config);
 183                /*
 184                 * If the pin controller prefer that a certain group be handled
 185                 * pin-by-pin as well, it returns -EAGAIN.
 186                 */
 187                if (ret != -EAGAIN)
 188                        return ret;
 189        }
 190
 191        /*
 192         * If the controller cannot handle entire groups, we configure each pin
 193         * individually.
 194         */
 195        if (!ops->pin_config_set)
 196                return 0;
 197
 198        for (i = 0; i < num_pins; i++) {
 199                ret = ops->pin_config_set(pctldev, pins[i], config);
 200                if (ret < 0)
 201                        return ret;
 202        }
 203
 204        return 0;
 205}
 206EXPORT_SYMBOL(pin_config_group_set);
 207
 208int pinconf_check_ops(struct pinctrl_dev *pctldev)
 209{
 210        const struct pinconf_ops *ops = pctldev->desc->confops;
 211
 212        /* We must be able to read out pin status */
 213        if (!ops->pin_config_get && !ops->pin_config_group_get)
 214                return -EINVAL;
 215        /* We have to be able to config the pins in SOME way */
 216        if (!ops->pin_config_set && !ops->pin_config_group_set)
 217                return -EINVAL;
 218        return 0;
 219}
 220
 221#ifdef CONFIG_DEBUG_FS
 222
 223static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
 224                             struct seq_file *s, int pin)
 225{
 226        const struct pinconf_ops *ops = pctldev->desc->confops;
 227
 228        if (ops && ops->pin_config_dbg_show)
 229                ops->pin_config_dbg_show(pctldev, s, pin);
 230}
 231
 232static int pinconf_pins_show(struct seq_file *s, void *what)
 233{
 234        struct pinctrl_dev *pctldev = s->private;
 235        unsigned i, pin;
 236
 237        seq_puts(s, "Pin config settings per pin\n");
 238        seq_puts(s, "Format: pin (name): pinmux setting array\n");
 239
 240        /* The pin number can be retrived from the pin controller descriptor */
 241        for (i = 0; i < pctldev->desc->npins; i++) {
 242                struct pin_desc *desc;
 243
 244                pin = pctldev->desc->pins[i].number;
 245                desc = pin_desc_get(pctldev, pin);
 246                /* Skip if we cannot search the pin */
 247                if (desc == NULL)
 248                        continue;
 249
 250                seq_printf(s, "pin %d (%s):", pin,
 251                           desc->name ? desc->name : "unnamed");
 252
 253                pinconf_dump_pin(pctldev, s, pin);
 254
 255                seq_printf(s, "\n");
 256        }
 257
 258        return 0;
 259}
 260
 261static void pinconf_dump_group(struct pinctrl_dev *pctldev,
 262                               struct seq_file *s, unsigned selector,
 263                               const char *gname)
 264{
 265        const struct pinconf_ops *ops = pctldev->desc->confops;
 266
 267        if (ops && ops->pin_config_group_dbg_show)
 268                ops->pin_config_group_dbg_show(pctldev, s, selector);
 269}
 270
 271static int pinconf_groups_show(struct seq_file *s, void *what)
 272{
 273        struct pinctrl_dev *pctldev = s->private;
 274        const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
 275        const struct pinconf_ops *ops = pctldev->desc->confops;
 276        unsigned selector = 0;
 277
 278        if (!ops || !ops->pin_config_group_get)
 279                return 0;
 280
 281        seq_puts(s, "Pin config settings per pin group\n");
 282        seq_puts(s, "Format: group (name): pinmux setting array\n");
 283
 284        while (pctlops->list_groups(pctldev, selector) >= 0) {
 285                const char *gname = pctlops->get_group_name(pctldev, selector);
 286
 287                seq_printf(s, "%u (%s):", selector, gname);
 288                pinconf_dump_group(pctldev, s, selector, gname);
 289                selector++;
 290        }
 291
 292        return 0;
 293}
 294
 295static int pinconf_pins_open(struct inode *inode, struct file *file)
 296{
 297        return single_open(file, pinconf_pins_show, inode->i_private);
 298}
 299
 300static int pinconf_groups_open(struct inode *inode, struct file *file)
 301{
 302        return single_open(file, pinconf_groups_show, inode->i_private);
 303}
 304
 305static const struct file_operations pinconf_pins_ops = {
 306        .open           = pinconf_pins_open,
 307        .read           = seq_read,
 308        .llseek         = seq_lseek,
 309        .release        = single_release,
 310};
 311
 312static const struct file_operations pinconf_groups_ops = {
 313        .open           = pinconf_groups_open,
 314        .read           = seq_read,
 315        .llseek         = seq_lseek,
 316        .release        = single_release,
 317};
 318
 319void pinconf_init_device_debugfs(struct dentry *devroot,
 320                         struct pinctrl_dev *pctldev)
 321{
 322        debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO,
 323                            devroot, pctldev, &pinconf_pins_ops);
 324        debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
 325                            devroot, pctldev, &pinconf_groups_ops);
 326}
 327
 328#endif
 329
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.