gpio-mockup.c 13.7 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0+
2
3
4
5
/*
 * GPIO Testing Device Driver
 *
 * Copyright (C) 2014  Kamlakant Patel <kamlakant.patel@broadcom.com>
6
 * Copyright (C) 2015-2016  Bamvor Jian Zhang <bamv2005@gmail.com>
7
 * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
8
9
10
11
12
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio/driver.h>
13
#include <linux/gpio/consumer.h>
14
#include <linux/platform_device.h>
15
#include <linux/slab.h>
16
17
#include <linux/interrupt.h>
#include <linux/irq.h>
18
#include <linux/irq_sim.h>
19
20
#include <linux/debugfs.h>
#include <linux/uaccess.h>
21
#include <linux/property.h>
22
23

#include "gpiolib.h"
24

25
#define GPIO_MOCKUP_NAME	"gpio-mockup"
26
#define GPIO_MOCKUP_MAX_GC	10
27
28
29
30
31
/*
 * We're storing two values per chip: the GPIO base and the number
 * of GPIO lines.
 */
#define GPIO_MOCKUP_MAX_RANGES	(GPIO_MOCKUP_MAX_GC * 2)
32
33
/* Maximum of three properties + the sentinel. */
#define GPIO_MOCKUP_MAX_PROP	4
34

35
36
#define gpio_mockup_err(...)	pr_err(GPIO_MOCKUP_NAME ": " __VA_ARGS__)

37
enum {
38
39
	GPIO_MOCKUP_DIR_IN = 0,
	GPIO_MOCKUP_DIR_OUT = 1,
40
41
42
43
44
45
46
};

/*
 * struct gpio_pin_status - structure describing a GPIO status
 * @dir:       Configures direction of gpio as "in" or "out", 0=in, 1=out
 * @value:     Configures status of the gpio as 0(low) or 1(high)
 */
47
48
struct gpio_mockup_line_status {
	int dir;
49
	int value;
50
	int pull;
51
52
};

53
struct gpio_mockup_chip {
54
	struct gpio_chip gc;
55
	struct gpio_mockup_line_status *lines;
56
	struct irq_sim irqsim;
57
	struct dentry *dbg_dir;
58
	struct mutex lock;
59
60
61
62
63
};

struct gpio_mockup_dbgfs_private {
	struct gpio_mockup_chip *chip;
	struct gpio_desc *desc;
64
	unsigned int offset;
65
66
};

67
static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_RANGES];
68
69
static int gpio_mockup_num_ranges;
module_param_array(gpio_mockup_ranges, int, &gpio_mockup_num_ranges, 0400);
70

71
72
73
74
static bool gpio_mockup_named_lines;
module_param_named(gpio_mockup_named_lines,
		   gpio_mockup_named_lines, bool, 0400);

75
static struct dentry *gpio_mockup_dbg_dir;
76

77
78
79
80
81
82
83
84
85
86
static int gpio_mockup_range_base(unsigned int index)
{
	return gpio_mockup_ranges[index * 2];
}

static int gpio_mockup_range_ngpio(unsigned int index)
{
	return gpio_mockup_ranges[index * 2 + 1];
}

87
88
static int __gpio_mockup_get(struct gpio_mockup_chip *chip,
			     unsigned int offset)
89
{
90
	return chip->lines[offset].value;
91
92
}

93
94
95
96
97
98
static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset)
{
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
	int val;

	mutex_lock(&chip->lock);
99
	val = __gpio_mockup_get(chip, offset);
100
101
102
103
104
	mutex_unlock(&chip->lock);

	return val;
}

105
106
107
108
109
110
111
112
static int gpio_mockup_get_multiple(struct gpio_chip *gc,
				    unsigned long *mask, unsigned long *bits)
{
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
	unsigned int bit, val;

	mutex_lock(&chip->lock);
	for_each_set_bit(bit, mask, gc->ngpio) {
113
		val = __gpio_mockup_get(chip, bit);
114
115
116
117
118
119
120
		__assign_bit(bit, bits, val);
	}
	mutex_unlock(&chip->lock);

	return 0;
}

121
static void __gpio_mockup_set(struct gpio_mockup_chip *chip,
122
			      unsigned int offset, int value)
123
{
124
	chip->lines[offset].value = !!value;
125
126
}

127
128
129
130
131
132
static void gpio_mockup_set(struct gpio_chip *gc,
			   unsigned int offset, int value)
{
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);

	mutex_lock(&chip->lock);
133
	__gpio_mockup_set(chip, offset, value);
134
135
136
	mutex_unlock(&chip->lock);
}

137
138
139
static void gpio_mockup_set_multiple(struct gpio_chip *gc,
				     unsigned long *mask, unsigned long *bits)
{
140
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
141
142
	unsigned int bit;

143
	mutex_lock(&chip->lock);
144
	for_each_set_bit(bit, mask, gc->ngpio)
145
		__gpio_mockup_set(chip, bit, test_bit(bit, bits));
146
	mutex_unlock(&chip->lock);
147
148
}

149
150
static int gpio_mockup_dirout(struct gpio_chip *gc,
			      unsigned int offset, int value)
151
{
152
153
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);

154
	mutex_lock(&chip->lock);
155
	chip->lines[offset].dir = GPIO_MOCKUP_DIR_OUT;
156
	__gpio_mockup_set(chip, offset, value);
157
	mutex_unlock(&chip->lock);
158
159
160
161

	return 0;
}

162
static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset)
163
{
164
165
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);

166
	mutex_lock(&chip->lock);
167
	chip->lines[offset].dir = GPIO_MOCKUP_DIR_IN;
168
	mutex_unlock(&chip->lock);
169
170
171
172

	return 0;
}

173
static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
174
{
175
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
176
	int direction;
177

178
179
180
181
182
	mutex_lock(&chip->lock);
	direction = !chip->lines[offset].dir;
	mutex_unlock(&chip->lock);

	return direction;
183
184
}

185
static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
186
187
188
{
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);

189
	return irq_sim_irqnum(&chip->irqsim, offset);
190
191
}

192
193
194
195
196
197
198
199
200
201
static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset)
{
	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);

	__gpio_mockup_set(chip, offset, chip->lines[offset].pull);
}

static ssize_t gpio_mockup_debugfs_read(struct file *file,
					char __user *usr_buf,
					size_t size, loff_t *ppos)
202
203
204
205
{
	struct gpio_mockup_dbgfs_private *priv;
	struct gpio_mockup_chip *chip;
	struct seq_file *sfile;
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
	struct gpio_chip *gc;
	char buf[3];
	int val, rv;

	if (*ppos != 0)
		return 0;

	sfile = file->private_data;
	priv = sfile->private;
	chip = priv->chip;
	gc = &chip->gc;

	val = gpio_mockup_get(gc, priv->offset);
	snprintf(buf, sizeof(buf), "%d\n", val);

	rv = copy_to_user(usr_buf, buf, sizeof(buf));
	if (rv)
		return rv;

	return sizeof(buf) - 1;
}

static ssize_t gpio_mockup_debugfs_write(struct file *file,
					 const char __user *usr_buf,
					 size_t size, loff_t *ppos)
{
	struct gpio_mockup_dbgfs_private *priv;
	int rv, val, curr, irq, irq_type;
	struct gpio_mockup_chip *chip;
	struct seq_file *sfile;
236
	struct gpio_desc *desc;
237
238
239
240
241
	struct gpio_chip *gc;
	struct irq_sim *sim;

	if (*ppos != 0)
		return -EINVAL;
242

243
244
245
246
247
248
	rv = kstrtoint_from_user(usr_buf, size, 0, &val);
	if (rv)
		return rv;
	if (val != 0 && val != 1)
		return -EINVAL;

249
250
251
	sfile = file->private_data;
	priv = sfile->private;
	chip = priv->chip;
252
253
254
255
256
257
258
259
260
261
262
	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;
263

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
		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);
280
281
282
283

	return size;
}

284
static int gpio_mockup_debugfs_open(struct inode *inode, struct file *file)
285
286
287
288
{
	return single_open(file, NULL, inode->i_private);
}

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
 * Each mockup chip is represented by a directory named after the chip's device
 * name under /sys/kernel/debug/gpio-mockup/. Each line is represented by
 * a file using the line's offset as the name under the chip's directory.
 *
 * Reading from the line's file yields the current *value*, writing to the
 * line's file changes the current *pull*. Default pull for mockup lines is
 * down.
 *
 * Examples:
 * - when a line pulled down is requested in output mode and driven high, its
 *   value will return to 0 once it's released
 * - when the line is requested in output mode and driven high, writing 0 to
 *   the corresponding debugfs file will change the pull to down but the
 *   reported value will still be 1 until the line is released
 * - line requested in input mode always reports the same value as its pull
 *   configuration
 * - when the line is requested in input mode and monitored for events, writing
 *   the same value to the debugfs file will be a noop, while writing the
 *   opposite value will generate a dummy interrupt with an appropriate edge
 */
static const struct file_operations gpio_mockup_debugfs_ops = {
311
	.owner = THIS_MODULE,
312
313
314
	.open = gpio_mockup_debugfs_open,
	.read = gpio_mockup_debugfs_read,
	.write = gpio_mockup_debugfs_write,
315
316
317
318
319
320
321
	.llseek = no_llseek,
};

static void gpio_mockup_debugfs_setup(struct device *dev,
				      struct gpio_mockup_chip *chip)
{
	struct gpio_mockup_dbgfs_private *priv;
322
	struct dentry *evfile;
323
	struct gpio_chip *gc;
324
	const char *devname;
325
326
327
328
	char *name;
	int i;

	gc = &chip->gc;
329
	devname = dev_name(&gc->gpiodev->dev);
330

331
	chip->dbg_dir = debugfs_create_dir(devname, gpio_mockup_dbg_dir);
332
	if (IS_ERR_OR_NULL(chip->dbg_dir))
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
		goto err;

	for (i = 0; i < gc->ngpio; i++) {
		name = devm_kasprintf(dev, GFP_KERNEL, "%d", i);
		if (!name)
			goto err;

		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
		if (!priv)
			goto err;

		priv->chip = chip;
		priv->offset = i;
		priv->desc = &gc->gpiodev->descs[i];

		evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv,
349
					     &gpio_mockup_debugfs_ops);
350
		if (IS_ERR_OR_NULL(evfile))
351
352
353
354
355
356
			goto err;
	}

	return;

err:
357
	dev_err(dev, "error creating debugfs files\n");
358
359
}

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
static int gpio_mockup_name_lines(struct device *dev,
				  struct gpio_mockup_chip *chip)
{
	struct gpio_chip *gc = &chip->gc;
	char **names;
	int i;

	names = devm_kcalloc(dev, gc->ngpio, sizeof(char *), GFP_KERNEL);
	if (!names)
		return -ENOMEM;

	for (i = 0; i < gc->ngpio; i++) {
		names[i] = devm_kasprintf(dev, GFP_KERNEL,
					  "%s-%d", gc->label, i);
		if (!names[i])
			return -ENOMEM;
	}

	gc->names = (const char *const *)names;

	return 0;
}

383
static int gpio_mockup_probe(struct platform_device *pdev)
384
{
385
386
387
	struct gpio_mockup_chip *chip;
	struct gpio_chip *gc;
	struct device *dev;
388
389
390
	const char *name;
	int rv, base;
	u16 ngpio;
391
392

	dev = &pdev->dev;
393
394
395
396
397
398
399
400
401
402
403
404

	rv = device_property_read_u32(dev, "gpio-base", &base);
	if (rv)
		base = -1;

	rv = device_property_read_u16(dev, "nr-gpios", &ngpio);
	if (rv)
		return rv;

	rv = device_property_read_string(dev, "chip-name", &name);
	if (rv)
		name = NULL;
405
406
407
408
409

	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
	if (!chip)
		return -ENOMEM;

410
411
412
413
414
415
	if (!name) {
		name = devm_kasprintf(dev, GFP_KERNEL,
				      "%s-%c", pdev->name, pdev->id + 'A');
		if (!name)
			return -ENOMEM;
	}
416

417
418
	mutex_init(&chip->lock);

419
	gc = &chip->gc;
420
421
422
423
424
425
426
	gc->base = base;
	gc->ngpio = ngpio;
	gc->label = name;
	gc->owner = THIS_MODULE;
	gc->parent = dev;
	gc->get = gpio_mockup_get;
	gc->set = gpio_mockup_set;
427
	gc->get_multiple = gpio_mockup_get_multiple;
428
	gc->set_multiple = gpio_mockup_set_multiple;
429
430
431
	gc->direction_output = gpio_mockup_dirout;
	gc->direction_input = gpio_mockup_dirin;
	gc->get_direction = gpio_mockup_get_direction;
432
	gc->to_irq = gpio_mockup_to_irq;
433
	gc->free = gpio_mockup_free;
434

435
436
	chip->lines = devm_kcalloc(dev, gc->ngpio,
				   sizeof(*chip->lines), GFP_KERNEL);
437
438
	if (!chip->lines)
		return -ENOMEM;
439

440
	if (device_property_read_bool(dev, "named-gpio-lines")) {
441
442
443
		rv = gpio_mockup_name_lines(dev, chip);
		if (rv)
			return rv;
444
445
	}

446
	rv = devm_irq_sim_init(dev, &chip->irqsim, gc->ngpio);
447
	if (rv < 0)
448
		return rv;
449

450
451
452
	rv = devm_gpiochip_add_data(dev, &chip->gc, chip);
	if (rv)
		return rv;
453

454
	if (!IS_ERR_OR_NULL(gpio_mockup_dbg_dir))
455
456
457
		gpio_mockup_debugfs_setup(dev, chip);

	return 0;
458
459
}

460
static struct platform_driver gpio_mockup_driver = {
461
	.driver = {
462
		.name = GPIO_MOCKUP_NAME,
463
	},
464
	.probe = gpio_mockup_probe,
465
466
};

467
468
469
470
471
472
473
474
475
476
477
478
479
480
static struct platform_device *gpio_mockup_pdevs[GPIO_MOCKUP_MAX_GC];

static void gpio_mockup_unregister_pdevs(void)
{
	struct platform_device *pdev;
	int i;

	for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) {
		pdev = gpio_mockup_pdevs[i];

		if (pdev)
			platform_device_unregister(pdev);
	}
}
481
482

static int __init gpio_mockup_init(void)
483
{
484
485
486
	struct property_entry properties[GPIO_MOCKUP_MAX_PROP];
	int i, prop, num_chips, err = 0, base;
	struct platform_device_info pdevinfo;
487
	struct platform_device *pdev;
488
	u16 ngpio;
489

490
491
492
	if ((gpio_mockup_num_ranges < 2) ||
	    (gpio_mockup_num_ranges % 2) ||
	    (gpio_mockup_num_ranges > GPIO_MOCKUP_MAX_RANGES))
493
494
		return -EINVAL;

495
	/* Each chip is described by two values. */
496
	num_chips = gpio_mockup_num_ranges / 2;
497

498
499
500
501
502
	/*
	 * The second value in the <base GPIO - number of GPIOS> pair must
	 * always be greater than 0.
	 */
	for (i = 0; i < num_chips; i++) {
503
		if (gpio_mockup_range_ngpio(i) < 0)
504
505
506
			return -EINVAL;
	}

507
	gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL);
508
	if (IS_ERR_OR_NULL(gpio_mockup_dbg_dir))
509
		gpio_mockup_err("error creating debugfs directory\n");
510

511
	err = platform_driver_register(&gpio_mockup_driver);
512
	if (err) {
513
		gpio_mockup_err("error registering platform driver\n");
514
515
516
		return err;
	}

517
	for (i = 0; i < num_chips; i++) {
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
		memset(properties, 0, sizeof(properties));
		memset(&pdevinfo, 0, sizeof(pdevinfo));
		prop = 0;

		base = gpio_mockup_range_base(i);
		if (base >= 0)
			properties[prop++] = PROPERTY_ENTRY_U32("gpio-base",
								base);

		ngpio = base < 0 ? gpio_mockup_range_ngpio(i)
				 : gpio_mockup_range_ngpio(i) - base;
		properties[prop++] = PROPERTY_ENTRY_U16("nr-gpios", ngpio);

		if (gpio_mockup_named_lines)
			properties[prop++] = PROPERTY_ENTRY_BOOL(
						"named-gpio-lines");

		pdevinfo.name = GPIO_MOCKUP_NAME;
		pdevinfo.id = i;
		pdevinfo.properties = properties;

		pdev = platform_device_register_full(&pdevinfo);
540
		if (IS_ERR(pdev)) {
541
			gpio_mockup_err("error registering device");
542
543
			platform_driver_unregister(&gpio_mockup_driver);
			gpio_mockup_unregister_pdevs();
544
			return PTR_ERR(pdev);
545
546
547
		}

		gpio_mockup_pdevs[i] = pdev;
548
549
550
551
552
	}

	return 0;
}

553
static void __exit gpio_mockup_exit(void)
554
{
555
	debugfs_remove_recursive(gpio_mockup_dbg_dir);
556
	platform_driver_unregister(&gpio_mockup_driver);
557
	gpio_mockup_unregister_pdevs();
558
559
}

560
561
module_init(gpio_mockup_init);
module_exit(gpio_mockup_exit);
562
563

MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>");
564
MODULE_AUTHOR("Bamvor Jian Zhang <bamv2005@gmail.com>");
565
MODULE_AUTHOR("Bartosz Golaszewski <brgl@bgdev.pl>");
566
567
MODULE_DESCRIPTION("GPIO Testing driver");
MODULE_LICENSE("GPL v2");