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:
parent
2821ae5f30
commit
64e7112ee3
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user