linux/drivers/gpio/gpio-mockup.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * GPIO Testing Device Driver
   4 *
   5 * Copyright (C) 2014  Kamlakant Patel <kamlakant.patel@broadcom.com>
   6 * Copyright (C) 2015-2016  Bamvor Jian Zhang <bamv2005@gmail.com>
   7 * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
   8 */
   9
  10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11
  12#include <linux/debugfs.h>
  13#include <linux/gpio/driver.h>
  14#include <linux/interrupt.h>
  15#include <linux/irq.h>
  16#include <linux/irq_sim.h>
  17#include <linux/irqdomain.h>
  18#include <linux/mod_devicetable.h>
  19#include <linux/module.h>
  20#include <linux/platform_device.h>
  21#include <linux/property.h>
  22#include <linux/slab.h>
  23#include <linux/string_helpers.h>
  24#include <linux/uaccess.h>
  25
  26#include "gpiolib.h"
  27
  28#define GPIO_MOCKUP_MAX_GC      10
  29/*
  30 * We're storing two values per chip: the GPIO base and the number
  31 * of GPIO lines.
  32 */
  33#define GPIO_MOCKUP_MAX_RANGES  (GPIO_MOCKUP_MAX_GC * 2)
  34/* Maximum of four properties + the sentinel. */
  35#define GPIO_MOCKUP_MAX_PROP    5
  36
  37/*
  38 * struct gpio_pin_status - structure describing a GPIO status
  39 * @dir:       Configures direction of gpio as "in" or "out"
  40 * @value:     Configures status of the gpio as 0(low) or 1(high)
  41 */
  42struct gpio_mockup_line_status {
  43        int dir;
  44        int value;
  45        int pull;
  46};
  47
  48struct gpio_mockup_chip {
  49        struct gpio_chip gc;
  50        struct gpio_mockup_line_status *lines;
  51        struct irq_domain *irq_sim_domain;
  52        struct dentry *dbg_dir;
  53        struct mutex lock;
  54};
  55
  56struct gpio_mockup_dbgfs_private {
  57        struct gpio_mockup_chip *chip;
  58        struct gpio_desc *desc;
  59        unsigned int offset;
  60};
  61
  62static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_RANGES];
  63static int gpio_mockup_num_ranges;
  64module_param_array(gpio_mockup_ranges, int, &gpio_mockup_num_ranges, 0400);
  65
  66static bool gpio_mockup_named_lines;
  67module_param_named(gpio_mockup_named_lines,
  68                   gpio_mockup_named_lines, bool, 0400);
  69
  70static struct dentry *gpio_mockup_dbg_dir;
  71
  72static int gpio_mockup_range_base(unsigned int index)
  73{
  74        return gpio_mockup_ranges[index * 2];
  75}
  76
  77static int gpio_mockup_range_ngpio(unsigned int index)
  78{
  79        return gpio_mockup_ranges[index * 2 + 1];
  80}
  81
  82static int __gpio_mockup_get(struct gpio_mockup_chip *chip,
  83                             unsigned int offset)
  84{
  85        return chip->lines[offset].value;
  86}
  87
  88static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset)
  89{
  90        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
  91        int val;
  92
  93        mutex_lock(&chip->lock);
  94        val = __gpio_mockup_get(chip, offset);
  95        mutex_unlock(&chip->lock);
  96
  97        return val;
  98}
  99
 100static int gpio_mockup_get_multiple(struct gpio_chip *gc,
 101                                    unsigned long *mask, unsigned long *bits)
 102{
 103        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 104        unsigned int bit, val;
 105
 106        mutex_lock(&chip->lock);
 107        for_each_set_bit(bit, mask, gc->ngpio) {
 108                val = __gpio_mockup_get(chip, bit);
 109                __assign_bit(bit, bits, val);
 110        }
 111        mutex_unlock(&chip->lock);
 112
 113        return 0;
 114}
 115
 116static void __gpio_mockup_set(struct gpio_mockup_chip *chip,
 117                              unsigned int offset, int value)
 118{
 119        chip->lines[offset].value = !!value;
 120}
 121
 122static void gpio_mockup_set(struct gpio_chip *gc,
 123                           unsigned int offset, int value)
 124{
 125        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 126
 127        mutex_lock(&chip->lock);
 128        __gpio_mockup_set(chip, offset, value);
 129        mutex_unlock(&chip->lock);
 130}
 131
 132static void gpio_mockup_set_multiple(struct gpio_chip *gc,
 133                                     unsigned long *mask, unsigned long *bits)
 134{
 135        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 136        unsigned int bit;
 137
 138        mutex_lock(&chip->lock);
 139        for_each_set_bit(bit, mask, gc->ngpio)
 140                __gpio_mockup_set(chip, bit, test_bit(bit, bits));
 141        mutex_unlock(&chip->lock);
 142}
 143
 144static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
 145                                  unsigned int offset, int value)
 146{
 147        struct gpio_chip *gc = &chip->gc;
 148        struct gpio_desc *desc = gpiochip_get_desc(gc, offset);
 149        int curr, irq, irq_type, ret = 0;
 150
 151        mutex_lock(&chip->lock);
 152
 153        if (test_bit(FLAG_REQUESTED, &desc->flags) &&
 154            !test_bit(FLAG_IS_OUT, &desc->flags)) {
 155                curr = __gpio_mockup_get(chip, offset);
 156                if (curr == value)
 157                        goto out;
 158
 159                irq = irq_find_mapping(chip->irq_sim_domain, offset);
 160                if (!irq)
 161                        /*
 162                         * This is fine - it just means, nobody is listening
 163                         * for interrupts on this line, otherwise
 164                         * irq_create_mapping() would have been called from
 165                         * the to_irq() callback.
 166                         */
 167                        goto set_value;
 168
 169                irq_type = irq_get_trigger_type(irq);
 170
 171                if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
 172                    (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) {
 173                        ret = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING,
 174                                                    true);
 175                        if (ret)
 176                                goto out;
 177                }
 178        }
 179
 180set_value:
 181        /* Change the value unless we're actively driving the line. */
 182        if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
 183            !test_bit(FLAG_IS_OUT, &desc->flags))
 184                __gpio_mockup_set(chip, offset, value);
 185
 186out:
 187        chip->lines[offset].pull = value;
 188        mutex_unlock(&chip->lock);
 189        return ret;
 190}
 191
 192static int gpio_mockup_set_config(struct gpio_chip *gc,
 193                                  unsigned int offset, unsigned long config)
 194{
 195        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 196
 197        switch (pinconf_to_config_param(config)) {
 198        case PIN_CONFIG_BIAS_PULL_UP:
 199                return gpio_mockup_apply_pull(chip, offset, 1);
 200        case PIN_CONFIG_BIAS_PULL_DOWN:
 201                return gpio_mockup_apply_pull(chip, offset, 0);
 202        default:
 203                break;
 204        }
 205        return -ENOTSUPP;
 206}
 207
 208static int gpio_mockup_dirout(struct gpio_chip *gc,
 209                              unsigned int offset, int value)
 210{
 211        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 212
 213        mutex_lock(&chip->lock);
 214        chip->lines[offset].dir = GPIO_LINE_DIRECTION_OUT;
 215        __gpio_mockup_set(chip, offset, value);
 216        mutex_unlock(&chip->lock);
 217
 218        return 0;
 219}
 220
 221static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset)
 222{
 223        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 224
 225        mutex_lock(&chip->lock);
 226        chip->lines[offset].dir = GPIO_LINE_DIRECTION_IN;
 227        mutex_unlock(&chip->lock);
 228
 229        return 0;
 230}
 231
 232static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
 233{
 234        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 235        int direction;
 236
 237        mutex_lock(&chip->lock);
 238        direction = chip->lines[offset].dir;
 239        mutex_unlock(&chip->lock);
 240
 241        return direction;
 242}
 243
 244static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
 245{
 246        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 247
 248        return irq_create_mapping(chip->irq_sim_domain, offset);
 249}
 250
 251static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset)
 252{
 253        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 254
 255        __gpio_mockup_set(chip, offset, chip->lines[offset].pull);
 256}
 257
 258static ssize_t gpio_mockup_debugfs_read(struct file *file,
 259                                        char __user *usr_buf,
 260                                        size_t size, loff_t *ppos)
 261{
 262        struct gpio_mockup_dbgfs_private *priv;
 263        struct gpio_mockup_chip *chip;
 264        struct seq_file *sfile;
 265        struct gpio_chip *gc;
 266        int val, cnt;
 267        char buf[3];
 268
 269        if (*ppos != 0)
 270                return 0;
 271
 272        sfile = file->private_data;
 273        priv = sfile->private;
 274        chip = priv->chip;
 275        gc = &chip->gc;
 276
 277        val = gpio_mockup_get(gc, priv->offset);
 278        cnt = snprintf(buf, sizeof(buf), "%d\n", val);
 279
 280        return simple_read_from_buffer(usr_buf, size, ppos, buf, cnt);
 281}
 282
 283static ssize_t gpio_mockup_debugfs_write(struct file *file,
 284                                         const char __user *usr_buf,
 285                                         size_t size, loff_t *ppos)
 286{
 287        struct gpio_mockup_dbgfs_private *priv;
 288        int rv, val;
 289        struct seq_file *sfile;
 290
 291        if (*ppos != 0)
 292                return -EINVAL;
 293
 294        rv = kstrtoint_from_user(usr_buf, size, 0, &val);
 295        if (rv)
 296                return rv;
 297        if (val != 0 && val != 1)
 298                return -EINVAL;
 299
 300        sfile = file->private_data;
 301        priv = sfile->private;
 302        rv = gpio_mockup_apply_pull(priv->chip, priv->offset, val);
 303        if (rv)
 304                return rv;
 305
 306        return size;
 307}
 308
 309static int gpio_mockup_debugfs_open(struct inode *inode, struct file *file)
 310{
 311        return single_open(file, NULL, inode->i_private);
 312}
 313
 314/*
 315 * Each mockup chip is represented by a directory named after the chip's device
 316 * name under /sys/kernel/debug/gpio-mockup/. Each line is represented by
 317 * a file using the line's offset as the name under the chip's directory.
 318 *
 319 * Reading from the line's file yields the current *value*, writing to the
 320 * line's file changes the current *pull*. Default pull for mockup lines is
 321 * down.
 322 *
 323 * Examples:
 324 * - when a line pulled down is requested in output mode and driven high, its
 325 *   value will return to 0 once it's released
 326 * - when the line is requested in output mode and driven high, writing 0 to
 327 *   the corresponding debugfs file will change the pull to down but the
 328 *   reported value will still be 1 until the line is released
 329 * - line requested in input mode always reports the same value as its pull
 330 *   configuration
 331 * - when the line is requested in input mode and monitored for events, writing
 332 *   the same value to the debugfs file will be a noop, while writing the
 333 *   opposite value will generate a dummy interrupt with an appropriate edge
 334 */
 335static const struct file_operations gpio_mockup_debugfs_ops = {
 336        .owner = THIS_MODULE,
 337        .open = gpio_mockup_debugfs_open,
 338        .read = gpio_mockup_debugfs_read,
 339        .write = gpio_mockup_debugfs_write,
 340        .llseek = no_llseek,
 341        .release = single_release,
 342};
 343
 344static void gpio_mockup_debugfs_setup(struct device *dev,
 345                                      struct gpio_mockup_chip *chip)
 346{
 347        struct gpio_mockup_dbgfs_private *priv;
 348        struct gpio_chip *gc;
 349        const char *devname;
 350        char *name;
 351        int i;
 352
 353        gc = &chip->gc;
 354        devname = dev_name(&gc->gpiodev->dev);
 355
 356        chip->dbg_dir = debugfs_create_dir(devname, gpio_mockup_dbg_dir);
 357
 358        for (i = 0; i < gc->ngpio; i++) {
 359                name = devm_kasprintf(dev, GFP_KERNEL, "%d", i);
 360                if (!name)
 361                        return;
 362
 363                priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 364                if (!priv)
 365                        return;
 366
 367                priv->chip = chip;
 368                priv->offset = i;
 369                priv->desc = gpiochip_get_desc(gc, i);
 370
 371                debugfs_create_file(name, 0200, chip->dbg_dir, priv,
 372                                    &gpio_mockup_debugfs_ops);
 373        }
 374}
 375
 376static void gpio_mockup_dispose_mappings(void *data)
 377{
 378        struct gpio_mockup_chip *chip = data;
 379        struct gpio_chip *gc = &chip->gc;
 380        int i, irq;
 381
 382        for (i = 0; i < gc->ngpio; i++) {
 383                irq = irq_find_mapping(chip->irq_sim_domain, i);
 384                if (irq)
 385                        irq_dispose_mapping(irq);
 386        }
 387}
 388
 389static int gpio_mockup_probe(struct platform_device *pdev)
 390{
 391        struct gpio_mockup_chip *chip;
 392        struct gpio_chip *gc;
 393        struct device *dev;
 394        const char *name;
 395        int rv, base, i;
 396        u16 ngpio;
 397
 398        dev = &pdev->dev;
 399
 400        rv = device_property_read_u32(dev, "gpio-base", &base);
 401        if (rv)
 402                base = -1;
 403
 404        rv = device_property_read_u16(dev, "nr-gpios", &ngpio);
 405        if (rv)
 406                return rv;
 407
 408        rv = device_property_read_string(dev, "chip-label", &name);
 409        if (rv)
 410                name = dev_name(dev);
 411
 412        chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 413        if (!chip)
 414                return -ENOMEM;
 415
 416        mutex_init(&chip->lock);
 417
 418        gc = &chip->gc;
 419        gc->base = base;
 420        gc->ngpio = ngpio;
 421        gc->label = name;
 422        gc->owner = THIS_MODULE;
 423        gc->parent = dev;
 424        gc->get = gpio_mockup_get;
 425        gc->set = gpio_mockup_set;
 426        gc->get_multiple = gpio_mockup_get_multiple;
 427        gc->set_multiple = gpio_mockup_set_multiple;
 428        gc->direction_output = gpio_mockup_dirout;
 429        gc->direction_input = gpio_mockup_dirin;
 430        gc->get_direction = gpio_mockup_get_direction;
 431        gc->set_config = gpio_mockup_set_config;
 432        gc->to_irq = gpio_mockup_to_irq;
 433        gc->free = gpio_mockup_free;
 434
 435        chip->lines = devm_kcalloc(dev, gc->ngpio,
 436                                   sizeof(*chip->lines), GFP_KERNEL);
 437        if (!chip->lines)
 438                return -ENOMEM;
 439
 440        for (i = 0; i < gc->ngpio; i++)
 441                chip->lines[i].dir = GPIO_LINE_DIRECTION_IN;
 442
 443        chip->irq_sim_domain = devm_irq_domain_create_sim(dev, NULL,
 444                                                          gc->ngpio);
 445        if (IS_ERR(chip->irq_sim_domain))
 446                return PTR_ERR(chip->irq_sim_domain);
 447
 448        rv = devm_add_action_or_reset(dev, gpio_mockup_dispose_mappings, chip);
 449        if (rv)
 450                return rv;
 451
 452        rv = devm_gpiochip_add_data(dev, &chip->gc, chip);
 453        if (rv)
 454                return rv;
 455
 456        gpio_mockup_debugfs_setup(dev, chip);
 457
 458        return 0;
 459}
 460
 461static const struct of_device_id gpio_mockup_of_match[] = {
 462        { .compatible = "gpio-mockup", },
 463        {},
 464};
 465MODULE_DEVICE_TABLE(of, gpio_mockup_of_match);
 466
 467static struct platform_driver gpio_mockup_driver = {
 468        .driver = {
 469                .name = "gpio-mockup",
 470                .of_match_table = gpio_mockup_of_match,
 471        },
 472        .probe = gpio_mockup_probe,
 473};
 474
 475static struct platform_device *gpio_mockup_pdevs[GPIO_MOCKUP_MAX_GC];
 476
 477static void gpio_mockup_unregister_pdevs(void)
 478{
 479        int i;
 480
 481        for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++)
 482                platform_device_unregister(gpio_mockup_pdevs[i]);
 483}
 484
 485static __init char **gpio_mockup_make_line_names(const char *label,
 486                                                 unsigned int num_lines)
 487{
 488        unsigned int i;
 489        char **names;
 490
 491        names = kcalloc(num_lines + 1, sizeof(char *), GFP_KERNEL);
 492        if (!names)
 493                return NULL;
 494
 495        for (i = 0; i < num_lines; i++) {
 496                names[i] = kasprintf(GFP_KERNEL, "%s-%u", label, i);
 497                if (!names[i]) {
 498                        kfree_strarray(names, i);
 499                        return NULL;
 500                }
 501        }
 502
 503        return names;
 504}
 505
 506static int __init gpio_mockup_register_chip(int idx)
 507{
 508        struct property_entry properties[GPIO_MOCKUP_MAX_PROP];
 509        struct platform_device_info pdevinfo;
 510        struct platform_device *pdev;
 511        char **line_names = NULL;
 512        char chip_label[32];
 513        int prop = 0, base;
 514        u16 ngpio;
 515
 516        memset(properties, 0, sizeof(properties));
 517        memset(&pdevinfo, 0, sizeof(pdevinfo));
 518
 519        snprintf(chip_label, sizeof(chip_label), "gpio-mockup-%c", idx + 'A');
 520        properties[prop++] = PROPERTY_ENTRY_STRING("chip-label", chip_label);
 521
 522        base = gpio_mockup_range_base(idx);
 523        if (base >= 0)
 524                properties[prop++] = PROPERTY_ENTRY_U32("gpio-base", base);
 525
 526        ngpio = base < 0 ? gpio_mockup_range_ngpio(idx)
 527                         : gpio_mockup_range_ngpio(idx) - base;
 528        properties[prop++] = PROPERTY_ENTRY_U16("nr-gpios", ngpio);
 529
 530        if (gpio_mockup_named_lines) {
 531                line_names = gpio_mockup_make_line_names(chip_label, ngpio);
 532                if (!line_names)
 533                        return -ENOMEM;
 534
 535                properties[prop++] = PROPERTY_ENTRY_STRING_ARRAY_LEN(
 536                                        "gpio-line-names", line_names, ngpio);
 537        }
 538
 539        pdevinfo.name = "gpio-mockup";
 540        pdevinfo.id = idx;
 541        pdevinfo.properties = properties;
 542
 543        pdev = platform_device_register_full(&pdevinfo);
 544        kfree_strarray(line_names, ngpio);
 545        if (IS_ERR(pdev)) {
 546                pr_err("error registering device");
 547                return PTR_ERR(pdev);
 548        }
 549
 550        gpio_mockup_pdevs[idx] = pdev;
 551
 552        return 0;
 553}
 554
 555static int __init gpio_mockup_init(void)
 556{
 557        int i, num_chips, err;
 558
 559        if ((gpio_mockup_num_ranges % 2) ||
 560            (gpio_mockup_num_ranges > GPIO_MOCKUP_MAX_RANGES))
 561                return -EINVAL;
 562
 563        /* Each chip is described by two values. */
 564        num_chips = gpio_mockup_num_ranges / 2;
 565
 566        /*
 567         * The second value in the <base GPIO - number of GPIOS> pair must
 568         * always be greater than 0.
 569         */
 570        for (i = 0; i < num_chips; i++) {
 571                if (gpio_mockup_range_ngpio(i) < 0)
 572                        return -EINVAL;
 573        }
 574
 575        gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL);
 576
 577        err = platform_driver_register(&gpio_mockup_driver);
 578        if (err) {
 579                pr_err("error registering platform driver\n");
 580                debugfs_remove_recursive(gpio_mockup_dbg_dir);
 581                return err;
 582        }
 583
 584        for (i = 0; i < num_chips; i++) {
 585                err = gpio_mockup_register_chip(i);
 586                if (err) {
 587                        platform_driver_unregister(&gpio_mockup_driver);
 588                        gpio_mockup_unregister_pdevs();
 589                        debugfs_remove_recursive(gpio_mockup_dbg_dir);
 590                        return err;
 591                }
 592        }
 593
 594        return 0;
 595}
 596
 597static void __exit gpio_mockup_exit(void)
 598{
 599        debugfs_remove_recursive(gpio_mockup_dbg_dir);
 600        platform_driver_unregister(&gpio_mockup_driver);
 601        gpio_mockup_unregister_pdevs();
 602}
 603
 604module_init(gpio_mockup_init);
 605module_exit(gpio_mockup_exit);
 606
 607MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>");
 608MODULE_AUTHOR("Bamvor Jian Zhang <bamv2005@gmail.com>");
 609MODULE_AUTHOR("Bartosz Golaszewski <brgl@bgdev.pl>");
 610MODULE_DESCRIPTION("GPIO Testing driver");
 611MODULE_LICENSE("GPL v2");
 612