summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorBartosz Golaszewski <bgolaszewski@baylibre.com>2019-01-17 10:30:27 -0500
committerBartosz Golaszewski <bgolaszewski@baylibre.com>2019-02-19 11:42:29 -0500
commit2a9e27408e12de455b9fcf66b5d0166f2129579e (patch)
treed95436b7b341065e2e28029ff654fe5b5d951eb7 /drivers/gpio
parente09313ce7ea1706d1642c7d5af103915e69fc6d0 (diff)
gpio: mockup: rework debugfs interface
Modify the way the debugfs interface works in gpio-mockup. Introduce the concept of dummy pull config which will keep the mockup lines in known state. The pull values can be modified by writing to the debugfs files corresponding to lines. Lines in input mode always report the current pull value, lines in output mode change the line value but it will revert back to the one specified by current pull when released. Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-mockup.c117
1 files changed, 103 insertions, 14 deletions
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c
index c498b0fbbec8..154d959e8993 100644
--- a/drivers/gpio/gpio-mockup.c
+++ b/drivers/gpio/gpio-mockup.c
@@ -47,6 +47,7 @@ enum {
47struct gpio_mockup_line_status { 47struct gpio_mockup_line_status {
48 int dir; 48 int dir;
49 int value; 49 int value;
50 int pull;
50}; 51};
51 52
52struct gpio_mockup_chip { 53struct gpio_mockup_chip {
@@ -188,15 +189,56 @@ static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
188 return irq_sim_irqnum(&chip->irqsim, offset); 189 return irq_sim_irqnum(&chip->irqsim, offset);
189} 190}
190 191
191static ssize_t gpio_mockup_event_write(struct file *file, 192static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset)
192 const char __user *usr_buf, 193{
193 size_t size, loff_t *ppos) 194 struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
195
196 __gpio_mockup_set(chip, offset, chip->lines[offset].pull);
197}
198
199static ssize_t gpio_mockup_debugfs_read(struct file *file,
200 char __user *usr_buf,
201 size_t size, loff_t *ppos)
194{ 202{
195 struct gpio_mockup_dbgfs_private *priv; 203 struct gpio_mockup_dbgfs_private *priv;
196 struct gpio_mockup_chip *chip; 204 struct gpio_mockup_chip *chip;
197 struct seq_file *sfile; 205 struct seq_file *sfile;
206 struct gpio_chip *gc;
207 char buf[3];
208 int val, rv;
209
210 if (*ppos != 0)
211 return 0;
212
213 sfile = file->private_data;
214 priv = sfile->private;
215 chip = priv->chip;
216 gc = &chip->gc;
217
218 val = gpio_mockup_get(gc, priv->offset);
219 snprintf(buf, sizeof(buf), "%d\n", val);
220
221 rv = copy_to_user(usr_buf, buf, sizeof(buf));
222 if (rv)
223 return rv;
224
225 return sizeof(buf) - 1;
226}
227
228static ssize_t gpio_mockup_debugfs_write(struct file *file,
229 const char __user *usr_buf,
230 size_t size, loff_t *ppos)
231{
232 struct gpio_mockup_dbgfs_private *priv;
233 int rv, val, curr, irq, irq_type;
234 struct gpio_mockup_chip *chip;
235 struct seq_file *sfile;
198 struct gpio_desc *desc; 236 struct gpio_desc *desc;
199 int rv, val; 237 struct gpio_chip *gc;
238 struct irq_sim *sim;
239
240 if (*ppos != 0)
241 return -EINVAL;
200 242
201 rv = kstrtoint_from_user(usr_buf, size, 0, &val); 243 rv = kstrtoint_from_user(usr_buf, size, 0, &val);
202 if (rv) 244 if (rv)
@@ -206,24 +248,70 @@ static ssize_t gpio_mockup_event_write(struct file *file,
206 248
207 sfile = file->private_data; 249 sfile = file->private_data;
208 priv = sfile->private; 250 priv = sfile->private;
209 desc = priv->desc;
210 chip = priv->chip; 251 chip = priv->chip;
252 gc = &chip->gc;
253 desc = &gc->gpiodev->descs[priv->offset];
254 sim = &chip->irqsim;
255
256 mutex_lock(&chip->lock);
257
258 if (test_bit(FLAG_REQUESTED, &desc->flags) &&
259 !test_bit(FLAG_IS_OUT, &desc->flags)) {
260 curr = __gpio_mockup_get(chip, priv->offset);
261 if (curr == val)
262 goto out;
211 263
212 gpiod_set_value_cansleep(desc, val); 264 irq = irq_sim_irqnum(sim, priv->offset);
213 irq_sim_fire(&chip->irqsim, priv->offset); 265 irq_type = irq_get_trigger_type(irq);
266
267 if ((val == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
268 (val == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
269 irq_sim_fire(sim, priv->offset);
270 }
271
272 /* Change the value unless we're actively driving the line. */
273 if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
274 !test_bit(FLAG_IS_OUT, &desc->flags))
275 __gpio_mockup_set(chip, priv->offset, val);
276
277out:
278 chip->lines[priv->offset].pull = val;
279 mutex_unlock(&chip->lock);
214 280
215 return size; 281 return size;
216} 282}
217 283
218static int gpio_mockup_event_open(struct inode *inode, struct file *file) 284static int gpio_mockup_debugfs_open(struct inode *inode, struct file *file)
219{ 285{
220 return single_open(file, NULL, inode->i_private); 286 return single_open(file, NULL, inode->i_private);
221} 287}
222 288
223static const struct file_operations gpio_mockup_event_ops = { 289/*
290 * Each mockup chip is represented by a directory named after the chip's device
291 * name under /sys/kernel/debug/gpio-mockup/. Each line is represented by
292 * a file using the line's offset as the name under the chip's directory.
293 *
294 * Reading from the line's file yields the current *value*, writing to the
295 * line's file changes the current *pull*. Default pull for mockup lines is
296 * down.
297 *
298 * Examples:
299 * - when a line pulled down is requested in output mode and driven high, its
300 * value will return to 0 once it's released
301 * - when the line is requested in output mode and driven high, writing 0 to
302 * the corresponding debugfs file will change the pull to down but the
303 * reported value will still be 1 until the line is released
304 * - line requested in input mode always reports the same value as its pull
305 * configuration
306 * - when the line is requested in input mode and monitored for events, writing
307 * the same value to the debugfs file will be a noop, while writing the
308 * opposite value will generate a dummy interrupt with an appropriate edge
309 */
310static const struct file_operations gpio_mockup_debugfs_ops = {
224 .owner = THIS_MODULE, 311 .owner = THIS_MODULE,
225 .open = gpio_mockup_event_open, 312 .open = gpio_mockup_debugfs_open,
226 .write = gpio_mockup_event_write, 313 .read = gpio_mockup_debugfs_read,
314 .write = gpio_mockup_debugfs_write,
227 .llseek = no_llseek, 315 .llseek = no_llseek,
228}; 316};
229 317
@@ -258,7 +346,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
258 priv->desc = &gc->gpiodev->descs[i]; 346 priv->desc = &gc->gpiodev->descs[i];
259 347
260 evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv, 348 evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv,
261 &gpio_mockup_event_ops); 349 &gpio_mockup_debugfs_ops);
262 if (IS_ERR_OR_NULL(evfile)) 350 if (IS_ERR_OR_NULL(evfile))
263 goto err; 351 goto err;
264 } 352 }
@@ -266,7 +354,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
266 return; 354 return;
267 355
268err: 356err:
269 dev_err(dev, "error creating debugfs event files\n"); 357 dev_err(dev, "error creating debugfs files\n");
270} 358}
271 359
272static int gpio_mockup_name_lines(struct device *dev, 360static int gpio_mockup_name_lines(struct device *dev,
@@ -342,6 +430,7 @@ static int gpio_mockup_probe(struct platform_device *pdev)
342 gc->direction_input = gpio_mockup_dirin; 430 gc->direction_input = gpio_mockup_dirin;
343 gc->get_direction = gpio_mockup_get_direction; 431 gc->get_direction = gpio_mockup_get_direction;
344 gc->to_irq = gpio_mockup_to_irq; 432 gc->to_irq = gpio_mockup_to_irq;
433 gc->free = gpio_mockup_free;
345 434
346 chip->lines = devm_kcalloc(dev, gc->ngpio, 435 chip->lines = devm_kcalloc(dev, gc->ngpio,
347 sizeof(*chip->lines), GFP_KERNEL); 436 sizeof(*chip->lines), GFP_KERNEL);
@@ -415,7 +504,7 @@ static int __init gpio_mockup_init(void)
415 return -EINVAL; 504 return -EINVAL;
416 } 505 }
417 506
418 gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup-event", NULL); 507 gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL);
419 if (IS_ERR_OR_NULL(gpio_mockup_dbg_dir)) 508 if (IS_ERR_OR_NULL(gpio_mockup_dbg_dir))
420 gpio_mockup_err("error creating debugfs directory\n"); 509 gpio_mockup_err("error creating debugfs directory\n");
421 510