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: Kent Gibson <warthog618@gmail.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
This commit is contained in:
Kent Gibson 2019-11-05 10:04:27 +08:00 committed by Bartosz Golaszewski
parent 2821ae5f30
commit 64e7112ee3
1 changed files with 60 additions and 34 deletions

View 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;