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.
Unified · Split
| @@ -141,6 +141,61 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc, · 140 unmodified lines | ||
| 141 | 141 | mutex_unlock(&chip->lock); |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | +static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, | |
| 145 | + unsigned int offset, int value) | |
| 146 | +{ | |
| 147 | + struct gpio_desc *desc; | |
| 148 | + struct gpio_chip *gc; | |
| 149 | + struct irq_sim *sim; | |
| 150 | + int curr, irq, irq_type; | |
| 151 | + | |
| 152 | + gc = &chip->gc; | |
| 153 | + desc = &gc->gpiodev->descs[offset]; | |
| 154 | + sim = &chip->irqsim; | |
| 155 | + | |
| 156 | + mutex_lock(&chip->lock); | |
| 157 | + | |
| 158 | + if (test_bit(FLAG_REQUESTED, &desc->flags) && | |
| 159 | + !test_bit(FLAG_IS_OUT, &desc->flags)) { | |
| 160 | + curr = __gpio_mockup_get(chip, offset); | |
| 161 | + if (curr == value) | |
| 162 | + goto out; | |
| 163 | + | |
| 164 | + irq = irq_sim_irqnum(sim, offset); | |
| 165 | + irq_type = irq_get_trigger_type(irq); | |
| 166 | + | |
| 167 | + if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) || | |
| 168 | + (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) | |
| 169 | + irq_sim_fire(sim, offset); | |
| 170 | + } | |
| 171 | + | |
| 172 | + /* Change the value unless we're actively driving the line. */ | |
| 173 | + if (!test_bit(FLAG_REQUESTED, &desc->flags) || | |
| 174 | + !test_bit(FLAG_IS_OUT, &desc->flags)) | |
| 175 | + __gpio_mockup_set(chip, offset, value); | |
| 176 | + | |
| 177 | +out: | |
| 178 | + chip->lines[offset].pull = value; | |
| 179 | + mutex_unlock(&chip->lock); | |
| 180 | + return 0; | |
| 181 | +} | |
| 182 | + | |
| 183 | +static int gpio_mockup_set_config(struct gpio_chip *gc, | |
| 184 | + unsigned int offset, unsigned long config) | |
| 185 | +{ | |
| 186 | + struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | |
| 187 | + | |
| 188 | + switch (pinconf_to_config_param(config)) { | |
| 189 | + case PIN_CONFIG_BIAS_PULL_UP: | |
| 190 | + return gpio_mockup_apply_pull(chip, offset, 1); | |
| 191 | + case PIN_CONFIG_BIAS_PULL_DOWN: | |
| 192 | + return gpio_mockup_apply_pull(chip, offset, 0); | |
| 193 | + default: | |
| 194 | + break; | |
| 195 | + } | |
| 196 | + return -ENOTSUPP; | |
| 197 | +} | |
| 198 | + | |
| 144 | 199 | static int gpio_mockup_dirout(struct gpio_chip *gc, |
| 145 | 200 | unsigned int offset, int value) |
| 146 | 201 | { |
| @@ -221,12 +276,8 @@ static ssize_t gpio_mockup_debugfs_write(struct file *file, · 74 unmodified lines | ||
| 221 | 276 | size_t size, loff_t *ppos) |
| 222 | 277 | { |
| 223 | 278 | struct gpio_mockup_dbgfs_private *priv; |
| 224 | − int rv, val, curr, irq, irq_type; | |
| 225 | − struct gpio_mockup_chip *chip; | |
| 279 | + int rv, val; | |
| 226 | 280 | struct seq_file *sfile; |
| 227 | − struct gpio_desc *desc; | |
| 228 | − struct gpio_chip *gc; | |
| 229 | − struct irq_sim *sim; | |
| 230 | 281 | |
| 231 | 282 | if (*ppos != 0) |
| 232 | 283 | return -EINVAL; |
| @@ -239,35 +290,9 @@ static ssize_t gpio_mockup_debugfs_write(struct file *file, · 6 unmodified lines | ||
| 239 | 290 | |
| 240 | 291 | sfile = file->private_data; |
| 241 | 292 | priv = sfile->private; |
| 242 | − chip = priv->chip; | |
| 243 | − gc = &chip->gc; | |
| 244 | − desc = &gc->gpiodev->descs[priv->offset]; | |
| 245 | − sim = &chip->irqsim; | |
| 246 | − | |
| 247 | − mutex_lock(&chip->lock); | |
| 248 | − | |
| 249 | − if (test_bit(FLAG_REQUESTED, &desc->flags) && | |
| 250 | − !test_bit(FLAG_IS_OUT, &desc->flags)) { | |
| 251 | − curr = __gpio_mockup_get(chip, priv->offset); | |
| 252 | − if (curr == val) | |
| 253 | − goto out; | |
| 254 | − | |
| 255 | − irq = irq_sim_irqnum(sim, priv->offset); | |
| 256 | − irq_type = irq_get_trigger_type(irq); | |
| 257 | − | |
| 258 | − if ((val == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) || | |
| 259 | − (val == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) | |
| 260 | − irq_sim_fire(sim, priv->offset); | |
| 261 | − } | |
| 262 | − | |
| 263 | − /* Change the value unless we're actively driving the line. */ | |
| 264 | − if (!test_bit(FLAG_REQUESTED, &desc->flags) || | |
| 265 | − !test_bit(FLAG_IS_OUT, &desc->flags)) | |
| 266 | − __gpio_mockup_set(chip, priv->offset, val); | |
| 267 | − | |
| 268 | −out: | |
| 269 | − chip->lines[priv->offset].pull = val; | |
| 270 | − mutex_unlock(&chip->lock); | |
| 293 | + rv = gpio_mockup_apply_pull(priv->chip, priv->offset, val); | |
| 294 | + if (rv) | |
| 295 | + return rv; | |
| 271 | 296 | |
| 272 | 297 | return size; |
| 273 | 298 | } |
| @@ -413,6 +438,7 @@ static int gpio_mockup_probe(struct platform_device *pdev) · 139 unmodified lines | ||
| 413 | 438 | gc->direction_output = gpio_mockup_dirout; |
| 414 | 439 | gc->direction_input = gpio_mockup_dirin; |
| 415 | 440 | gc->get_direction = gpio_mockup_get_direction; |
| 441 | + gc->set_config = gpio_mockup_set_config; | |
| 416 | 442 | gc->to_irq = gpio_mockup_to_irq; |
| 417 | 443 | gc->free = gpio_mockup_free; |
| 418 | 444 | |