aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Breathitt Gray <vilhelm.gray@gmail.com>2016-05-01 18:44:39 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-05-02 12:32:04 -0400
commit4c23db0f9f7f5e554837f69a849de75777f3fefc (patch)
tree0afe9a95bbffbe1a1bcd6d0ecb1a7815c8e1724d
parent4ef1bec4e4f393aa96d2b5345bb08baabaec8ee1 (diff)
gpio: 104-dio-48e: Utilize the ISA bus driver
The ACCES 104-DIO-48E 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-DIO-48E 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/Kconfig9
-rw-r--r--drivers/gpio/gpio-104-dio-48e.c106
2 files changed, 43 insertions, 72 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 5f3429f0bf46..5aca476c6692 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -517,12 +517,13 @@ menu "Port-mapped I/O GPIO drivers"
517 517
518config GPIO_104_DIO_48E 518config GPIO_104_DIO_48E
519 tristate "ACCES 104-DIO-48E GPIO support" 519 tristate "ACCES 104-DIO-48E GPIO support"
520 depends on ISA
520 select GPIOLIB_IRQCHIP 521 select GPIOLIB_IRQCHIP
521 help 522 help
522 Enables GPIO support for the ACCES 104-DIO-48E family. The base port 523 Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
523 address for the device may be configured via the dio_48e_base module 524 104-DIO-24E). The base port addresses for the devices may be
524 parameter. The interrupt line number for the device may be configured 525 configured via the base module parameter. The interrupt line numbers
525 via the dio_48e_irq module parameter. 526 for the devices may be configured via the irq module parameter.
526 527
527config GPIO_104_IDIO_16 528config GPIO_104_IDIO_16
528 tristate "ACCES 104-IDIO-16 GPIO support" 529 tristate "ACCES 104-IDIO-16 GPIO support"
diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index 448a903089ef..1a647c07be67 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * GPIO driver for the ACCES 104-DIO-48E 2 * GPIO driver for the ACCES 104-DIO-48E series
3 * Copyright (C) 2016 William Breathitt Gray 3 * Copyright (C) 2016 William Breathitt Gray
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
@@ -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-DIO-48E and
15 * 104-DIO-24E.
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
28static unsigned dio_48e_base; 31#define DIO48E_EXTENT 16
29module_param(dio_48e_base, uint, 0); 32#define MAX_NUM_DIO48E max_num_isa_dev(DIO48E_EXTENT)
30MODULE_PARM_DESC(dio_48e_base, "ACCES 104-DIO-48E base address"); 33
31static unsigned dio_48e_irq; 34static unsigned int base[MAX_NUM_DIO48E];
32module_param(dio_48e_irq, uint, 0); 35static unsigned int num_dio48e;
33MODULE_PARM_DESC(dio_48e_irq, "ACCES 104-DIO-48E interrupt line number"); 36module_param_array(base, uint, &num_dio48e, 0);
37MODULE_PARM_DESC(base, "ACCES 104-DIO-48E base addresses");
38
39static unsigned int irq[MAX_NUM_DIO48E];
40module_param_array(irq, uint, NULL, 0);
41MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers");
34 42
35/** 43/**
36 * struct dio48e_gpio - GPIO device private data structure 44 * struct dio48e_gpio - GPIO device private data structure
@@ -294,23 +302,19 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
294 return IRQ_HANDLED; 302 return IRQ_HANDLED;
295} 303}
296 304
297static int __init dio48e_probe(struct platform_device *pdev) 305static int dio48e_probe(struct device *dev, unsigned int id)
298{ 306{
299 struct device *dev = &pdev->dev;
300 struct dio48e_gpio *dio48egpio; 307 struct dio48e_gpio *dio48egpio;
301 const unsigned base = dio_48e_base;
302 const unsigned extent = 16;
303 const char *const name = dev_name(dev); 308 const char *const name = dev_name(dev);
304 int err; 309 int err;
305 const unsigned irq = dio_48e_irq;
306 310
307 dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); 311 dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
308 if (!dio48egpio) 312 if (!dio48egpio)
309 return -ENOMEM; 313 return -ENOMEM;
310 314
311 if (!devm_request_region(dev, base, extent, name)) { 315 if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) {
312 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", 316 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
313 base, base + extent); 317 base[id], base[id] + DIO48E_EXTENT);
314 return -EBUSY; 318 return -EBUSY;
315 } 319 }
316 320
@@ -324,8 +328,8 @@ static int __init dio48e_probe(struct platform_device *pdev)
324 dio48egpio->chip.direction_output = dio48e_gpio_direction_output; 328 dio48egpio->chip.direction_output = dio48e_gpio_direction_output;
325 dio48egpio->chip.get = dio48e_gpio_get; 329 dio48egpio->chip.get = dio48e_gpio_get;
326 dio48egpio->chip.set = dio48e_gpio_set; 330 dio48egpio->chip.set = dio48e_gpio_set;
327 dio48egpio->base = base; 331 dio48egpio->base = base[id];
328 dio48egpio->irq = irq; 332 dio48egpio->irq = irq[id];
329 333
330 spin_lock_init(&dio48egpio->lock); 334 spin_lock_init(&dio48egpio->lock);
331 335
@@ -338,19 +342,19 @@ static int __init dio48e_probe(struct platform_device *pdev)
338 } 342 }
339 343
340 /* initialize all GPIO as output */ 344 /* initialize all GPIO as output */
341 outb(0x80, base + 3); 345 outb(0x80, base[id] + 3);
342 outb(0x00, base); 346 outb(0x00, base[id]);
343 outb(0x00, base + 1); 347 outb(0x00, base[id] + 1);
344 outb(0x00, base + 2); 348 outb(0x00, base[id] + 2);
345 outb(0x00, base + 3); 349 outb(0x00, base[id] + 3);
346 outb(0x80, base + 7); 350 outb(0x80, base[id] + 7);
347 outb(0x00, base + 4); 351 outb(0x00, base[id] + 4);
348 outb(0x00, base + 5); 352 outb(0x00, base[id] + 5);
349 outb(0x00, base + 6); 353 outb(0x00, base[id] + 6);
350 outb(0x00, base + 7); 354 outb(0x00, base[id] + 7);
351 355
352 /* disable IRQ by default */ 356 /* disable IRQ by default */
353 inb(base + 0xB); 357 inb(base[id] + 0xB);
354 358
355 err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0, 359 err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0,
356 handle_edge_irq, IRQ_TYPE_NONE); 360 handle_edge_irq, IRQ_TYPE_NONE);
@@ -359,7 +363,7 @@ static int __init dio48e_probe(struct platform_device *pdev)
359 goto err_gpiochip_remove; 363 goto err_gpiochip_remove;
360 } 364 }
361 365
362 err = request_irq(irq, dio48e_irq_handler, 0, name, dio48egpio); 366 err = request_irq(irq[id], dio48e_irq_handler, 0, name, dio48egpio);
363 if (err) { 367 if (err) {
364 dev_err(dev, "IRQ handler registering failed (%d)\n", err); 368 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
365 goto err_gpiochip_remove; 369 goto err_gpiochip_remove;
@@ -372,9 +376,9 @@ err_gpiochip_remove:
372 return err; 376 return err;
373} 377}
374 378
375static int dio48e_remove(struct platform_device *pdev) 379static int dio48e_remove(struct device *dev, unsigned int id)
376{ 380{
377 struct dio48e_gpio *const dio48egpio = platform_get_drvdata(pdev); 381 struct dio48e_gpio *const dio48egpio = dev_get_drvdata(dev);
378 382
379 free_irq(dio48egpio->irq, dio48egpio); 383 free_irq(dio48egpio->irq, dio48egpio);
380 gpiochip_remove(&dio48egpio->chip); 384 gpiochip_remove(&dio48egpio->chip);
@@ -382,48 +386,14 @@ static int dio48e_remove(struct platform_device *pdev)
382 return 0; 386 return 0;
383} 387}
384 388
385static struct platform_device *dio48e_device; 389static struct isa_driver dio48e_driver = {
386 390 .probe = dio48e_probe,
387static struct platform_driver dio48e_driver = {
388 .driver = { 391 .driver = {
389 .name = "104-dio-48e" 392 .name = "104-dio-48e"
390 }, 393 },
391 .remove = dio48e_remove 394 .remove = dio48e_remove
392}; 395};
393 396module_isa_driver(dio48e_driver, num_dio48e);
394static void __exit dio48e_exit(void)
395{
396 platform_device_unregister(dio48e_device);
397 platform_driver_unregister(&dio48e_driver);
398}
399
400static int __init dio48e_init(void)
401{
402 int err;
403
404 dio48e_device = platform_device_alloc(dio48e_driver.driver.name, -1);
405 if (!dio48e_device)
406 return -ENOMEM;
407
408 err = platform_device_add(dio48e_device);
409 if (err)
410 goto err_platform_device;
411
412 err = platform_driver_probe(&dio48e_driver, dio48e_probe);
413 if (err)
414 goto err_platform_driver;
415
416 return 0;
417
418err_platform_driver:
419 platform_device_del(dio48e_device);
420err_platform_device:
421 platform_device_put(dio48e_device);
422 return err;
423}
424
425module_init(dio48e_init);
426module_exit(dio48e_exit);
427 397
428MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 398MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
429MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver"); 399MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver");