diff options
author | William Breathitt Gray <vilhelm.gray@gmail.com> | 2016-05-01 18:45:11 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-05-02 12:32:04 -0400 |
commit | 86ea8a95a42f752fe0aa1c7ad1bfe8ce9be5d30e (patch) | |
tree | 67d094efdf409fe53bdd01f55694f940e1baa242 | |
parent | 72bf7443ba618b9f7a3167c1f591a0dc00faeb2d (diff) |
gpio: 104-idio-16: Utilize the ISA bus driver
The ACCES 104-IDIO-16 series communicates via the ISA bus. As such, it
is more appropriate to use the ISA bus driver over the platform driver
to control the ACCES 104-IDIO-16 GPIO driver.
This patch also adds support for multiple devices via the base and irq
module array parameters. Each element of the base array corresponds to a
discrete device; each element of the irq array corresponds to the
respective device addressed in the respective base array element.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: Alexandre Courbot <gnurou@gmail.com>
Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/gpio/Kconfig | 10 | ||||
-rw-r--r-- | drivers/gpio/gpio-104-idio-16.c | 85 |
2 files changed, 34 insertions, 61 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c96ef58ed9e1..af3237cef81d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -527,12 +527,14 @@ config GPIO_104_DIO_48E | |||
527 | 527 | ||
528 | config GPIO_104_IDIO_16 | 528 | config GPIO_104_IDIO_16 |
529 | tristate "ACCES 104-IDIO-16 GPIO support" | 529 | tristate "ACCES 104-IDIO-16 GPIO support" |
530 | depends on ISA | ||
530 | select GPIOLIB_IRQCHIP | 531 | select GPIOLIB_IRQCHIP |
531 | help | 532 | help |
532 | Enables GPIO support for the ACCES 104-IDIO-16 family. The base port | 533 | Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, |
533 | address for the device may be set via the idio_16_base module | 534 | 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, 104-IDO-8). The |
534 | parameter. The interrupt line number for the device may be set via the | 535 | base port addresses for the devices may be configured via the base |
535 | idio_16_irq module parameter. | 536 | module parameter. The interrupt line numbers for the devices may be |
537 | configured via the irq module parameter. | ||
536 | 538 | ||
537 | config GPIO_104_IDI_48 | 539 | config GPIO_104_IDI_48 |
538 | tristate "ACCES 104-IDI-48 GPIO support" | 540 | tristate "ACCES 104-IDI-48 GPIO support" |
diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index ecc85fe9323d..6787b8fcf0d8 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c | |||
@@ -10,6 +10,9 @@ | |||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | ||
14 | * This driver supports the following ACCES devices: 104-IDIO-16, | ||
15 | * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8. | ||
13 | */ | 16 | */ |
14 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
15 | #include <linux/device.h> | 18 | #include <linux/device.h> |
@@ -19,18 +22,23 @@ | |||
19 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
20 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
21 | #include <linux/irqdesc.h> | 24 | #include <linux/irqdesc.h> |
25 | #include <linux/isa.h> | ||
22 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 27 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
27 | 30 | ||
28 | static unsigned idio_16_base; | 31 | #define IDIO_16_EXTENT 8 |
29 | module_param(idio_16_base, uint, 0); | 32 | #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT) |
30 | MODULE_PARM_DESC(idio_16_base, "ACCES 104-IDIO-16 base address"); | 33 | |
31 | static unsigned idio_16_irq; | 34 | static unsigned int base[MAX_NUM_IDIO_16]; |
32 | module_param(idio_16_irq, uint, 0); | 35 | static unsigned int num_idio_16; |
33 | MODULE_PARM_DESC(idio_16_irq, "ACCES 104-IDIO-16 interrupt line number"); | 36 | module_param_array(base, uint, &num_idio_16, 0); |
37 | MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses"); | ||
38 | |||
39 | static unsigned int irq[MAX_NUM_IDIO_16]; | ||
40 | module_param_array(irq, uint, NULL, 0); | ||
41 | MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers"); | ||
34 | 42 | ||
35 | /** | 43 | /** |
36 | * struct idio_16_gpio - GPIO device private data structure | 44 | * struct idio_16_gpio - GPIO device private data structure |
@@ -185,23 +193,19 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) | |||
185 | return IRQ_HANDLED; | 193 | return IRQ_HANDLED; |
186 | } | 194 | } |
187 | 195 | ||
188 | static int __init idio_16_probe(struct platform_device *pdev) | 196 | static int idio_16_probe(struct device *dev, unsigned int id) |
189 | { | 197 | { |
190 | struct device *dev = &pdev->dev; | ||
191 | struct idio_16_gpio *idio16gpio; | 198 | struct idio_16_gpio *idio16gpio; |
192 | const unsigned base = idio_16_base; | ||
193 | const unsigned extent = 8; | ||
194 | const char *const name = dev_name(dev); | 199 | const char *const name = dev_name(dev); |
195 | int err; | 200 | int err; |
196 | const unsigned irq = idio_16_irq; | ||
197 | 201 | ||
198 | idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); | 202 | idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); |
199 | if (!idio16gpio) | 203 | if (!idio16gpio) |
200 | return -ENOMEM; | 204 | return -ENOMEM; |
201 | 205 | ||
202 | if (!devm_request_region(dev, base, extent, name)) { | 206 | if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) { |
203 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", | 207 | dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", |
204 | base, base + extent); | 208 | base[id], base[id] + IDIO_16_EXTENT); |
205 | return -EBUSY; | 209 | return -EBUSY; |
206 | } | 210 | } |
207 | 211 | ||
@@ -215,8 +219,8 @@ static int __init idio_16_probe(struct platform_device *pdev) | |||
215 | idio16gpio->chip.direction_output = idio_16_gpio_direction_output; | 219 | idio16gpio->chip.direction_output = idio_16_gpio_direction_output; |
216 | idio16gpio->chip.get = idio_16_gpio_get; | 220 | idio16gpio->chip.get = idio_16_gpio_get; |
217 | idio16gpio->chip.set = idio_16_gpio_set; | 221 | idio16gpio->chip.set = idio_16_gpio_set; |
218 | idio16gpio->base = base; | 222 | idio16gpio->base = base[id]; |
219 | idio16gpio->irq = irq; | 223 | idio16gpio->irq = irq[id]; |
220 | idio16gpio->out_state = 0xFFFF; | 224 | idio16gpio->out_state = 0xFFFF; |
221 | 225 | ||
222 | spin_lock_init(&idio16gpio->lock); | 226 | spin_lock_init(&idio16gpio->lock); |
@@ -230,8 +234,8 @@ static int __init idio_16_probe(struct platform_device *pdev) | |||
230 | } | 234 | } |
231 | 235 | ||
232 | /* Disable IRQ by default */ | 236 | /* Disable IRQ by default */ |
233 | outb(0, base + 2); | 237 | outb(0, base[id] + 2); |
234 | outb(0, base + 1); | 238 | outb(0, base[id] + 1); |
235 | 239 | ||
236 | err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0, | 240 | err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0, |
237 | handle_edge_irq, IRQ_TYPE_NONE); | 241 | handle_edge_irq, IRQ_TYPE_NONE); |
@@ -240,7 +244,7 @@ static int __init idio_16_probe(struct platform_device *pdev) | |||
240 | goto err_gpiochip_remove; | 244 | goto err_gpiochip_remove; |
241 | } | 245 | } |
242 | 246 | ||
243 | err = request_irq(irq, idio_16_irq_handler, 0, name, idio16gpio); | 247 | err = request_irq(irq[id], idio_16_irq_handler, 0, name, idio16gpio); |
244 | if (err) { | 248 | if (err) { |
245 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); | 249 | dev_err(dev, "IRQ handler registering failed (%d)\n", err); |
246 | goto err_gpiochip_remove; | 250 | goto err_gpiochip_remove; |
@@ -253,9 +257,9 @@ err_gpiochip_remove: | |||
253 | return err; | 257 | return err; |
254 | } | 258 | } |
255 | 259 | ||
256 | static int idio_16_remove(struct platform_device *pdev) | 260 | static int idio_16_remove(struct device *dev, unsigned int id) |
257 | { | 261 | { |
258 | struct idio_16_gpio *const idio16gpio = platform_get_drvdata(pdev); | 262 | struct idio_16_gpio *const idio16gpio = dev_get_drvdata(dev); |
259 | 263 | ||
260 | free_irq(idio16gpio->irq, idio16gpio); | 264 | free_irq(idio16gpio->irq, idio16gpio); |
261 | gpiochip_remove(&idio16gpio->chip); | 265 | gpiochip_remove(&idio16gpio->chip); |
@@ -263,48 +267,15 @@ static int idio_16_remove(struct platform_device *pdev) | |||
263 | return 0; | 267 | return 0; |
264 | } | 268 | } |
265 | 269 | ||
266 | static struct platform_device *idio_16_device; | 270 | static struct isa_driver idio_16_driver = { |
267 | 271 | .probe = idio_16_probe, | |
268 | static struct platform_driver idio_16_driver = { | ||
269 | .driver = { | 272 | .driver = { |
270 | .name = "104-idio-16" | 273 | .name = "104-idio-16" |
271 | }, | 274 | }, |
272 | .remove = idio_16_remove | 275 | .remove = idio_16_remove |
273 | }; | 276 | }; |
274 | 277 | ||
275 | static void __exit idio_16_exit(void) | 278 | module_isa_driver(idio_16_driver, num_idio_16); |
276 | { | ||
277 | platform_device_unregister(idio_16_device); | ||
278 | platform_driver_unregister(&idio_16_driver); | ||
279 | } | ||
280 | |||
281 | static int __init idio_16_init(void) | ||
282 | { | ||
283 | int err; | ||
284 | |||
285 | idio_16_device = platform_device_alloc(idio_16_driver.driver.name, -1); | ||
286 | if (!idio_16_device) | ||
287 | return -ENOMEM; | ||
288 | |||
289 | err = platform_device_add(idio_16_device); | ||
290 | if (err) | ||
291 | goto err_platform_device; | ||
292 | |||
293 | err = platform_driver_probe(&idio_16_driver, idio_16_probe); | ||
294 | if (err) | ||
295 | goto err_platform_driver; | ||
296 | |||
297 | return 0; | ||
298 | |||
299 | err_platform_driver: | ||
300 | platform_device_del(idio_16_device); | ||
301 | err_platform_device: | ||
302 | platform_device_put(idio_16_device); | ||
303 | return err; | ||
304 | } | ||
305 | |||
306 | module_init(idio_16_init); | ||
307 | module_exit(idio_16_exit); | ||
308 | 279 | ||
309 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); | 280 | MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); |
310 | MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver"); | 281 | MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver"); |