gpio-mockup.c (8a68ea00a62e7ec33e9e4e7f3d9c2a845943c58d) gpio-mockup.c (e2ff7408953f6fe8a341b31ed2d848f73606bbf4)
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/platform_device.h>
18#include <linux/slab.h>
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/platform_device.h>
18#include <linux/slab.h>
19#include <linux/interrupt.h>
20#include <linux/irq.h>
21#include <linux/irq_work.h>
19
20#define GPIO_MOCKUP_NAME "gpio-mockup"
21#define GPIO_MOCKUP_MAX_GC 10
22
23enum {
24 DIR_IN = 0,
25 DIR_OUT,
26};
27
28/*
29 * struct gpio_pin_status - structure describing a GPIO status
30 * @dir: Configures direction of gpio as "in" or "out", 0=in, 1=out
31 * @value: Configures status of the gpio as 0(low) or 1(high)
32 */
33struct gpio_mockup_line_status {
34 int dir;
35 bool value;
36};
37
22
23#define GPIO_MOCKUP_NAME "gpio-mockup"
24#define GPIO_MOCKUP_MAX_GC 10
25
26enum {
27 DIR_IN = 0,
28 DIR_OUT,
29};
30
31/*
32 * struct gpio_pin_status - structure describing a GPIO status
33 * @dir: Configures direction of gpio as "in" or "out", 0=in, 1=out
34 * @value: Configures status of the gpio as 0(low) or 1(high)
35 */
36struct gpio_mockup_line_status {
37 int dir;
38 bool value;
39};
40
41struct gpio_mockup_irq_context {
42 struct irq_work work;
43 int irq;
44};
45
38struct gpio_mockup_chip {
39 struct gpio_chip gc;
40 struct gpio_mockup_line_status *lines;
46struct gpio_mockup_chip {
47 struct gpio_chip gc;
48 struct gpio_mockup_line_status *lines;
49 struct gpio_mockup_irq_context irq_ctx;
41};
42
43static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_GC << 1];
44static int gpio_mockup_params_nr;
45module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400);
46
47static bool gpio_mockup_named_lines;
48module_param_named(gpio_mockup_named_lines,

--- 61 unchanged lines hidden (view full) ---

110 return -ENOMEM;
111 }
112
113 gc->names = (const char *const *)names;
114
115 return 0;
116}
117
50};
51
52static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_GC << 1];
53static int gpio_mockup_params_nr;
54module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400);
55
56static bool gpio_mockup_named_lines;
57module_param_named(gpio_mockup_named_lines,

--- 61 unchanged lines hidden (view full) ---

119 return -ENOMEM;
120 }
121
122 gc->names = (const char *const *)names;
123
124 return 0;
125}
126
127static int gpio_mockup_to_irq(struct gpio_chip *chip, unsigned int offset)
128{
129 return chip->irq_base + offset;
130}
131
132/*
133 * While we should generally support irqmask and irqunmask, this driver is
134 * for testing purposes only so we don't care.
135 */
136static void gpio_mockup_irqmask(struct irq_data *d) { }
137static void gpio_mockup_irqunmask(struct irq_data *d) { }
138
139static struct irq_chip gpio_mockup_irqchip = {
140 .name = GPIO_MOCKUP_NAME,
141 .irq_mask = gpio_mockup_irqmask,
142 .irq_unmask = gpio_mockup_irqunmask,
143};
144
145static void gpio_mockup_handle_irq(struct irq_work *work)
146{
147 struct gpio_mockup_irq_context *irq_ctx;
148
149 irq_ctx = container_of(work, struct gpio_mockup_irq_context, work);
150 handle_simple_irq(irq_to_desc(irq_ctx->irq));
151}
152
153static int gpio_mockup_irqchip_setup(struct device *dev,
154 struct gpio_mockup_chip *chip)
155{
156 struct gpio_chip *gc = &chip->gc;
157 int irq_base, i;
158
159 irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0);
160 if (irq_base < 0)
161 return irq_base;
162
163 gc->irq_base = irq_base;
164 gc->irqchip = &gpio_mockup_irqchip;
165
166 for (i = 0; i < gc->ngpio; i++) {
167 irq_set_chip(irq_base + i, gc->irqchip);
168 irq_set_handler(irq_base + i, &handle_simple_irq);
169 irq_modify_status(irq_base + i,
170 IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
171 }
172
173 init_irq_work(&chip->irq_ctx.work, gpio_mockup_handle_irq);
174
175 return 0;
176}
177
118static int gpio_mockup_add(struct device *dev,
119 struct gpio_mockup_chip *chip,
120 const char *name, int base, int ngpio)
121{
122 struct gpio_chip *gc = &chip->gc;
123 int ret;
124
125 gc->base = base;
126 gc->ngpio = ngpio;
127 gc->label = name;
128 gc->owner = THIS_MODULE;
129 gc->parent = dev;
130 gc->get = gpio_mockup_get;
131 gc->set = gpio_mockup_set;
132 gc->direction_output = gpio_mockup_dirout;
133 gc->direction_input = gpio_mockup_dirin;
134 gc->get_direction = gpio_mockup_get_direction;
178static int gpio_mockup_add(struct device *dev,
179 struct gpio_mockup_chip *chip,
180 const char *name, int base, int ngpio)
181{
182 struct gpio_chip *gc = &chip->gc;
183 int ret;
184
185 gc->base = base;
186 gc->ngpio = ngpio;
187 gc->label = name;
188 gc->owner = THIS_MODULE;
189 gc->parent = dev;
190 gc->get = gpio_mockup_get;
191 gc->set = gpio_mockup_set;
192 gc->direction_output = gpio_mockup_dirout;
193 gc->direction_input = gpio_mockup_dirin;
194 gc->get_direction = gpio_mockup_get_direction;
195 gc->to_irq = gpio_mockup_to_irq;
135
136 chip->lines = devm_kzalloc(dev, sizeof(*chip->lines) * gc->ngpio,
137 GFP_KERNEL);
138 if (!chip->lines)
139 return -ENOMEM;
140
141 if (gpio_mockup_named_lines) {
142 ret = gpio_mockup_name_lines(dev, chip);
143 if (ret)
144 return ret;
145 }
146
196
197 chip->lines = devm_kzalloc(dev, sizeof(*chip->lines) * gc->ngpio,
198 GFP_KERNEL);
199 if (!chip->lines)
200 return -ENOMEM;
201
202 if (gpio_mockup_named_lines) {
203 ret = gpio_mockup_name_lines(dev, chip);
204 if (ret)
205 return ret;
206 }
207
208 ret = gpio_mockup_irqchip_setup(dev, chip);
209 if (ret)
210 return ret;
211
147 return devm_gpiochip_add_data(dev, &chip->gc, chip);
148}
149
150static int gpio_mockup_probe(struct platform_device *pdev)
151{
152 struct gpio_mockup_chip *chips;
153 struct device *dev = &pdev->dev;
154 int ret, i, base, ngpio;

--- 40 unchanged lines hidden (view full) ---

195
196 dev_info(dev, "gpio<%d..%d> add successful!",
197 base, base + ngpio);
198 }
199
200 return 0;
201}
202
212 return devm_gpiochip_add_data(dev, &chip->gc, chip);
213}
214
215static int gpio_mockup_probe(struct platform_device *pdev)
216{
217 struct gpio_mockup_chip *chips;
218 struct device *dev = &pdev->dev;
219 int ret, i, base, ngpio;

--- 40 unchanged lines hidden (view full) ---

260
261 dev_info(dev, "gpio<%d..%d> add successful!",
262 base, base + ngpio);
263 }
264
265 return 0;
266}
267
268static int gpio_mockup_remove(struct platform_device *pdev)
269{
270 struct gpio_mockup_chip *chips;
271 int i;
272
273 chips = platform_get_drvdata(pdev);
274
275 for (i = 0; i < gpio_mockup_params_nr >> 1; i++)
276 irq_free_descs(chips[i].gc.irq_base, chips[i].gc.ngpio);
277
278 return 0;
279}
280
203static struct platform_driver gpio_mockup_driver = {
204 .driver = {
205 .name = GPIO_MOCKUP_NAME,
206 },
207 .probe = gpio_mockup_probe,
281static struct platform_driver gpio_mockup_driver = {
282 .driver = {
283 .name = GPIO_MOCKUP_NAME,
284 },
285 .probe = gpio_mockup_probe,
286 .remove = gpio_mockup_remove,
208};
209
210static struct platform_device *pdev;
211static int __init mock_device_init(void)
212{
213 int err;
214
215 pdev = platform_device_alloc(GPIO_MOCKUP_NAME, -1);

--- 31 unchanged lines hidden ---
287};
288
289static struct platform_device *pdev;
290static int __init mock_device_init(void)
291{
292 int err;
293
294 pdev = platform_device_alloc(GPIO_MOCKUP_NAME, -1);

--- 31 unchanged lines hidden ---