]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
gpio: mockup: add set_config to support pull up/down
authorKent Gibson <warthog618@gmail.com>
Tue, 5 Nov 2019 02:04:27 +0000 (10:04 +0800)
committerBartosz Golaszewski <bgolaszewski@baylibre.com>
Tue, 12 Nov 2019 15:30:30 +0000 (16:30 +0100)
Add support for the pull up/down state set via gpiolib line requests to
be reflected in the state of the mockup.
Use case is for testing of the GPIO uAPI, specifically the pull up/down
flags.

Signed-off-by: Kent Gibson <warthog618@gmail.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
drivers/gpio/gpio-mockup.c

index 47c172b2f5ad656c329ec6313cc00e2242b67b33..56d647a30e3eafee0178b6d416952e697635a745 100644 (file)
@@ -141,6 +141,61 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc,
        mutex_unlock(&chip->lock);
 }
 
+static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
+                                 unsigned int offset, int value)
+{
+       struct gpio_desc *desc;
+       struct gpio_chip *gc;
+       struct irq_sim *sim;
+       int curr, irq, irq_type;
+
+       gc = &chip->gc;
+       desc = &gc->gpiodev->descs[offset];
+       sim = &chip->irqsim;
+
+       mutex_lock(&chip->lock);
+
+       if (test_bit(FLAG_REQUESTED, &desc->flags) &&
+               !test_bit(FLAG_IS_OUT, &desc->flags)) {
+               curr = __gpio_mockup_get(chip, offset);
+               if (curr == value)
+                       goto out;
+
+               irq = irq_sim_irqnum(sim, offset);
+               irq_type = irq_get_trigger_type(irq);
+
+               if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
+                       (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
+                       irq_sim_fire(sim, offset);
+       }
+
+       /* Change the value unless we're actively driving the line. */
+       if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
+               !test_bit(FLAG_IS_OUT, &desc->flags))
+               __gpio_mockup_set(chip, offset, value);
+
+out:
+       chip->lines[offset].pull = value;
+       mutex_unlock(&chip->lock);
+       return 0;
+}
+
+static int gpio_mockup_set_config(struct gpio_chip *gc,
+                                 unsigned int offset, unsigned long config)
+{
+       struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
+
+       switch (pinconf_to_config_param(config)) {
+       case PIN_CONFIG_BIAS_PULL_UP:
+               return gpio_mockup_apply_pull(chip, offset, 1);
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               return gpio_mockup_apply_pull(chip, offset, 0);
+       default:
+               break;
+       }
+       return -ENOTSUPP;
+}
+
 static int gpio_mockup_dirout(struct gpio_chip *gc,
                              unsigned int offset, int value)
 {
@@ -221,12 +276,8 @@ static ssize_t gpio_mockup_debugfs_write(struct file *file,
                                         size_t size, loff_t *ppos)
 {
        struct gpio_mockup_dbgfs_private *priv;
-       int rv, val, curr, irq, irq_type;
-       struct gpio_mockup_chip *chip;
+       int rv, val;
        struct seq_file *sfile;
-       struct gpio_desc *desc;
-       struct gpio_chip *gc;
-       struct irq_sim *sim;
 
        if (*ppos != 0)
                return -EINVAL;
@@ -239,35 +290,9 @@ static ssize_t gpio_mockup_debugfs_write(struct file *file,
 
        sfile = file->private_data;
        priv = sfile->private;
-       chip = priv->chip;
-       gc = &chip->gc;
-       desc = &gc->gpiodev->descs[priv->offset];
-       sim = &chip->irqsim;
-
-       mutex_lock(&chip->lock);
-
-       if (test_bit(FLAG_REQUESTED, &desc->flags) &&
-           !test_bit(FLAG_IS_OUT, &desc->flags)) {
-               curr = __gpio_mockup_get(chip, priv->offset);
-               if (curr == val)
-                       goto out;
-
-               irq = irq_sim_irqnum(sim, priv->offset);
-               irq_type = irq_get_trigger_type(irq);
-
-               if ((val == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
-                   (val == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
-                       irq_sim_fire(sim, priv->offset);
-       }
-
-       /* Change the value unless we're actively driving the line. */
-       if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
-           !test_bit(FLAG_IS_OUT, &desc->flags))
-               __gpio_mockup_set(chip, priv->offset, val);
-
-out:
-       chip->lines[priv->offset].pull = val;
-       mutex_unlock(&chip->lock);
+       rv = gpio_mockup_apply_pull(priv->chip, priv->offset, val);
+       if (rv)
+               return rv;
 
        return size;
 }
@@ -413,6 +438,7 @@ static int gpio_mockup_probe(struct platform_device *pdev)
        gc->direction_output = gpio_mockup_dirout;
        gc->direction_input = gpio_mockup_dirin;
        gc->get_direction = gpio_mockup_get_direction;
+       gc->set_config = gpio_mockup_set_config;
        gc->to_irq = gpio_mockup_to_irq;
        gc->free = gpio_mockup_free;