Commit 64e7112e authored by Kent Gibson's avatar Kent Gibson Committed by Bartosz Golaszewski
Browse files

gpio: mockup: add set_config to support pull up/down



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: default avatarKent Gibson <warthog618@gmail.com>
Signed-off-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
parent 2821ae5f
Loading
Loading
Loading
Loading
+60 −34
Original line number Original line Diff line number Diff line
@@ -141,6 +141,61 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc,
	mutex_unlock(&chip->lock);
	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,
static int gpio_mockup_dirout(struct gpio_chip *gc,
			      unsigned int offset, int value)
			      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)
					 size_t size, loff_t *ppos)
{
{
	struct gpio_mockup_dbgfs_private *priv;
	struct gpio_mockup_dbgfs_private *priv;
	int rv, val, curr, irq, irq_type;
	int rv, val;
	struct gpio_mockup_chip *chip;
	struct seq_file *sfile;
	struct seq_file *sfile;
	struct gpio_desc *desc;
	struct gpio_chip *gc;
	struct irq_sim *sim;


	if (*ppos != 0)
	if (*ppos != 0)
		return -EINVAL;
		return -EINVAL;
@@ -239,35 +290,9 @@ static ssize_t gpio_mockup_debugfs_write(struct file *file,


	sfile = file->private_data;
	sfile = file->private_data;
	priv = sfile->private;
	priv = sfile->private;
	chip = priv->chip;
	rv = gpio_mockup_apply_pull(priv->chip, priv->offset, val);
	gc = &chip->gc;
	if (rv)
	desc = &gc->gpiodev->descs[priv->offset];
		return rv;
	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);


	return size;
	return size;
}
}
@@ -413,6 +438,7 @@ static int gpio_mockup_probe(struct platform_device *pdev)
	gc->direction_output = gpio_mockup_dirout;
	gc->direction_output = gpio_mockup_dirout;
	gc->direction_input = gpio_mockup_dirin;
	gc->direction_input = gpio_mockup_dirin;
	gc->get_direction = gpio_mockup_get_direction;
	gc->get_direction = gpio_mockup_get_direction;
	gc->set_config = gpio_mockup_set_config;
	gc->to_irq = gpio_mockup_to_irq;
	gc->to_irq = gpio_mockup_to_irq;
	gc->free = gpio_mockup_free;
	gc->free = gpio_mockup_free;