mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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
					
				
					 1 changed files with 60 additions and 34 deletions
				
			
		| 
						 | 
					@ -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 a new issue