]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpio/gpio-mockup.c
da76267aa85cdabb4a2d8310b4e5bece48a59573
[linux.git] / drivers / gpio / gpio-mockup.c
1 /*
2  * GPIO Testing Device Driver
3  *
4  * Copyright (C) 2014  Kamlakant Patel <kamlakant.patel@broadcom.com>
5  * Copyright (C) 2015-2016  Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  *
12  */
13
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/gpio/driver.h>
17 #include <linux/gpio/consumer.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #include <linux/interrupt.h>
21 #include <linux/irq.h>
22 #include <linux/irq_work.h>
23 #include <linux/debugfs.h>
24 #include <linux/uaccess.h>
25
26 #include "gpiolib.h"
27
28 #define GPIO_MOCKUP_NAME        "gpio-mockup"
29 #define GPIO_MOCKUP_MAX_GC      10
30
31 enum {
32         GPIO_MOCKUP_DIR_OUT = 0,
33         GPIO_MOCKUP_DIR_IN = 1,
34 };
35
36 /*
37  * struct gpio_pin_status - structure describing a GPIO status
38  * @dir:       Configures direction of gpio as "in" or "out", 0=in, 1=out
39  * @value:     Configures status of the gpio as 0(low) or 1(high)
40  */
41 struct gpio_mockup_line_status {
42         int dir;
43         bool value;
44         bool irq_enabled;
45 };
46
47 struct gpio_mockup_irq_context {
48         struct irq_work work;
49         int irq;
50 };
51
52 struct gpio_mockup_chip {
53         struct gpio_chip gc;
54         struct gpio_mockup_line_status *lines;
55         struct gpio_mockup_irq_context irq_ctx;
56         struct dentry *dbg_dir;
57 };
58
59 struct gpio_mockup_dbgfs_private {
60         struct gpio_mockup_chip *chip;
61         struct gpio_desc *desc;
62         int offset;
63 };
64
65 static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_GC << 1];
66 static int gpio_mockup_params_nr;
67 module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400);
68
69 static bool gpio_mockup_named_lines;
70 module_param_named(gpio_mockup_named_lines,
71                    gpio_mockup_named_lines, bool, 0400);
72
73 static const char gpio_mockup_name_start = 'A';
74 static struct dentry *gpio_mockup_dbg_dir;
75
76 static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset)
77 {
78         struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
79
80         return chip->lines[offset].value;
81 }
82
83 static void gpio_mockup_set(struct gpio_chip *gc, unsigned int offset,
84                             int value)
85 {
86         struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
87
88         chip->lines[offset].value = !!value;
89 }
90
91 static int gpio_mockup_dirout(struct gpio_chip *gc, unsigned int offset,
92                               int value)
93 {
94         struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
95
96         gpio_mockup_set(gc, offset, value);
97         chip->lines[offset].dir = GPIO_MOCKUP_DIR_OUT;
98
99         return 0;
100 }
101
102 static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset)
103 {
104         struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
105
106         chip->lines[offset].dir = GPIO_MOCKUP_DIR_IN;
107
108         return 0;
109 }
110
111 static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
112 {
113         struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
114
115         return chip->lines[offset].dir;
116 }
117
118 static int gpio_mockup_name_lines(struct device *dev,
119                                   struct gpio_mockup_chip *chip)
120 {
121         struct gpio_chip *gc = &chip->gc;
122         char **names;
123         int i;
124
125         names = devm_kzalloc(dev, sizeof(char *) * gc->ngpio, GFP_KERNEL);
126         if (!names)
127                 return -ENOMEM;
128
129         for (i = 0; i < gc->ngpio; i++) {
130                 names[i] = devm_kasprintf(dev, GFP_KERNEL,
131                                           "%s-%d", gc->label, i);
132                 if (!names[i])
133                         return -ENOMEM;
134         }
135
136         gc->names = (const char *const *)names;
137
138         return 0;
139 }
140
141 static int gpio_mockup_to_irq(struct gpio_chip *chip, unsigned int offset)
142 {
143         return chip->irq_base + offset;
144 }
145
146 static void gpio_mockup_irqmask(struct irq_data *data)
147 {
148         struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
149         struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
150
151         chip->lines[data->irq - gc->irq_base].irq_enabled = false;
152 }
153
154 static void gpio_mockup_irqunmask(struct irq_data *data)
155 {
156         struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
157         struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
158
159         chip->lines[data->irq - gc->irq_base].irq_enabled = true;
160 }
161
162 static struct irq_chip gpio_mockup_irqchip = {
163         .name           = GPIO_MOCKUP_NAME,
164         .irq_mask       = gpio_mockup_irqmask,
165         .irq_unmask     = gpio_mockup_irqunmask,
166 };
167
168 static void gpio_mockup_handle_irq(struct irq_work *work)
169 {
170         struct gpio_mockup_irq_context *irq_ctx;
171
172         irq_ctx = container_of(work, struct gpio_mockup_irq_context, work);
173         handle_simple_irq(irq_to_desc(irq_ctx->irq));
174 }
175
176 static int gpio_mockup_irqchip_setup(struct device *dev,
177                                      struct gpio_mockup_chip *chip)
178 {
179         struct gpio_chip *gc = &chip->gc;
180         int irq_base, i;
181
182         irq_base = devm_irq_alloc_descs(dev, -1, 0, gc->ngpio, 0);
183         if (irq_base < 0)
184                 return irq_base;
185
186         gc->irq_base = irq_base;
187         gc->irqchip = &gpio_mockup_irqchip;
188
189         for (i = 0; i < gc->ngpio; i++) {
190                 irq_set_chip(irq_base + i, gc->irqchip);
191                 irq_set_chip_data(irq_base + i, gc);
192                 irq_set_handler(irq_base + i, &handle_simple_irq);
193                 irq_modify_status(irq_base + i,
194                                   IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
195         }
196
197         init_irq_work(&chip->irq_ctx.work, gpio_mockup_handle_irq);
198
199         return 0;
200 }
201
202 static ssize_t gpio_mockup_event_write(struct file *file,
203                                        const char __user *usr_buf,
204                                        size_t size, loff_t *ppos)
205 {
206         struct gpio_mockup_dbgfs_private *priv;
207         struct gpio_mockup_chip *chip;
208         struct seq_file *sfile;
209         struct gpio_desc *desc;
210         struct gpio_chip *gc;
211         int rv, val;
212
213         sfile = file->private_data;
214         priv = sfile->private;
215         desc = priv->desc;
216         chip = priv->chip;
217         gc = &chip->gc;
218
219         rv = kstrtoint_from_user(usr_buf, size, 0, &val);
220         if (rv)
221                 return rv;
222         if (val != 0 && val != 1)
223                 return -EINVAL;
224
225         if (!chip->lines[priv->offset].irq_enabled)
226                 return size;
227
228         gpiod_set_value_cansleep(desc, val);
229         priv->chip->irq_ctx.irq = gc->irq_base + priv->offset;
230         irq_work_queue(&priv->chip->irq_ctx.work);
231
232         return size;
233 }
234
235 static int gpio_mockup_event_open(struct inode *inode, struct file *file)
236 {
237         return single_open(file, NULL, inode->i_private);
238 }
239
240 static const struct file_operations gpio_mockup_event_ops = {
241         .owner = THIS_MODULE,
242         .open = gpio_mockup_event_open,
243         .write = gpio_mockup_event_write,
244         .llseek = no_llseek,
245 };
246
247 static void gpio_mockup_debugfs_setup(struct device *dev,
248                                       struct gpio_mockup_chip *chip)
249 {
250         struct gpio_mockup_dbgfs_private *priv;
251         struct dentry *evfile;
252         struct gpio_chip *gc;
253         char *name;
254         int i;
255
256         gc = &chip->gc;
257
258         chip->dbg_dir = debugfs_create_dir(gc->label, gpio_mockup_dbg_dir);
259         if (!chip->dbg_dir)
260                 goto err;
261
262         for (i = 0; i < gc->ngpio; i++) {
263                 name = devm_kasprintf(dev, GFP_KERNEL, "%d", i);
264                 if (!name)
265                         goto err;
266
267                 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
268                 if (!priv)
269                         goto err;
270
271                 priv->chip = chip;
272                 priv->offset = i;
273                 priv->desc = &gc->gpiodev->descs[i];
274
275                 evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv,
276                                              &gpio_mockup_event_ops);
277                 if (!evfile)
278                         goto err;
279         }
280
281         return;
282
283 err:
284         dev_err(dev, "error creating debugfs directory\n");
285 }
286
287 static int gpio_mockup_add(struct device *dev,
288                            struct gpio_mockup_chip *chip,
289                            const char *name, int base, int ngpio)
290 {
291         struct gpio_chip *gc = &chip->gc;
292         int ret;
293
294         gc->base = base;
295         gc->ngpio = ngpio;
296         gc->label = name;
297         gc->owner = THIS_MODULE;
298         gc->parent = dev;
299         gc->get = gpio_mockup_get;
300         gc->set = gpio_mockup_set;
301         gc->direction_output = gpio_mockup_dirout;
302         gc->direction_input = gpio_mockup_dirin;
303         gc->get_direction = gpio_mockup_get_direction;
304         gc->to_irq = gpio_mockup_to_irq;
305
306         chip->lines = devm_kzalloc(dev, sizeof(*chip->lines) * gc->ngpio,
307                                    GFP_KERNEL);
308         if (!chip->lines)
309                 return -ENOMEM;
310
311         if (gpio_mockup_named_lines) {
312                 ret = gpio_mockup_name_lines(dev, chip);
313                 if (ret)
314                         return ret;
315         }
316
317         ret = gpio_mockup_irqchip_setup(dev, chip);
318         if (ret)
319                 return ret;
320
321         ret = devm_gpiochip_add_data(dev, &chip->gc, chip);
322         if (ret)
323                 return ret;
324
325         if (gpio_mockup_dbg_dir)
326                 gpio_mockup_debugfs_setup(dev, chip);
327
328         return 0;
329 }
330
331 static int gpio_mockup_probe(struct platform_device *pdev)
332 {
333         struct gpio_mockup_chip *chips;
334         struct device *dev = &pdev->dev;
335         int ret, i, base, ngpio;
336         char *chip_name;
337
338         if (gpio_mockup_params_nr < 2)
339                 return -EINVAL;
340
341         chips = devm_kzalloc(dev,
342                              sizeof(*chips) * (gpio_mockup_params_nr >> 1),
343                              GFP_KERNEL);
344         if (!chips)
345                 return -ENOMEM;
346
347         platform_set_drvdata(pdev, chips);
348
349         for (i = 0; i < gpio_mockup_params_nr >> 1; i++) {
350                 base = gpio_mockup_ranges[i * 2];
351
352                 if (base == -1)
353                         ngpio = gpio_mockup_ranges[i * 2 + 1];
354                 else
355                         ngpio = gpio_mockup_ranges[i * 2 + 1] - base;
356
357                 if (ngpio >= 0) {
358                         chip_name = devm_kasprintf(dev, GFP_KERNEL,
359                                                    "%s-%c", GPIO_MOCKUP_NAME,
360                                                    gpio_mockup_name_start + i);
361                         if (!chip_name)
362                                 return -ENOMEM;
363
364                         ret = gpio_mockup_add(dev, &chips[i],
365                                               chip_name, base, ngpio);
366                 } else {
367                         ret = -1;
368                 }
369
370                 if (ret) {
371                         dev_err(dev, "gpio<%d..%d> add failed\n",
372                                 base, base < 0 ? ngpio : base + ngpio);
373
374                         return ret;
375                 }
376         }
377
378         return 0;
379 }
380
381 static struct platform_driver gpio_mockup_driver = {
382         .driver = {
383                 .name = GPIO_MOCKUP_NAME,
384         },
385         .probe = gpio_mockup_probe,
386 };
387
388 static struct platform_device *pdev;
389 static int __init mock_device_init(void)
390 {
391         int err;
392
393         gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup-event", NULL);
394         if (!gpio_mockup_dbg_dir)
395                 pr_err("%s: error creating debugfs directory\n",
396                        GPIO_MOCKUP_NAME);
397
398         pdev = platform_device_alloc(GPIO_MOCKUP_NAME, -1);
399         if (!pdev)
400                 return -ENOMEM;
401
402         err = platform_device_add(pdev);
403         if (err) {
404                 platform_device_put(pdev);
405                 return err;
406         }
407
408         err = platform_driver_register(&gpio_mockup_driver);
409         if (err) {
410                 platform_device_unregister(pdev);
411                 return err;
412         }
413
414         return 0;
415 }
416
417 static void __exit mock_device_exit(void)
418 {
419         debugfs_remove_recursive(gpio_mockup_dbg_dir);
420         platform_driver_unregister(&gpio_mockup_driver);
421         platform_device_unregister(pdev);
422 }
423
424 module_init(mock_device_init);
425 module_exit(mock_device_exit);
426
427 MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>");
428 MODULE_AUTHOR("Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>");
429 MODULE_DESCRIPTION("GPIO Testing driver");
430 MODULE_LICENSE("GPL v2");