summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorWilliam Breathitt Gray <vilhelm.gray@gmail.com>2016-05-01 18:44:55 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-05-02 12:32:04 -0400
commit72bf7443ba618b9f7a3167c1f591a0dc00faeb2d (patch)
tree2420e1d2e633c5606d4cd164c98db80cec8485d9 /drivers/gpio
parent4c23db0f9f7f5e554837f69a849de75777f3fefc (diff)
gpio: 104-idi-48: Utilize the ISA bus driver
The ACCES 104-IDI-48 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-IDI-48 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>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig10
-rw-r--r--drivers/gpio/gpio-104-idi-48.c86
2 files changed, 34 insertions, 62 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 5aca476c6692..c96ef58ed9e1 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -536,12 +536,14 @@ config GPIO_104_IDIO_16
536 536
537config GPIO_104_IDI_48 537config GPIO_104_IDI_48
538 tristate "ACCES 104-IDI-48 GPIO support" 538 tristate "ACCES 104-IDI-48 GPIO support"
539 depends on ISA
539 select GPIOLIB_IRQCHIP 540 select GPIOLIB_IRQCHIP
540 help 541 help
541 Enables GPIO support for the ACCES 104-IDI-48 family. The base port 542 Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
542 address for the device may be configured via the idi_48_base module 543 104-IDI-48AC, 104-IDI-48B, 104-IDI-48BC). The base port addresses for
543 parameter. The interrupt line number for the device may be configured 544 the devices may be configured via the base module parameter. The
544 via the idi_48_irq module parameter. 545 interrupt line numbers for the devices may be configured via the irq
546 module parameter.
545 547
546config GPIO_F7188X 548config GPIO_F7188X
547 tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support" 549 tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support"
diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index e37cd4cdda35..6c75c83baf5a 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.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-IDI-48A,
15 * 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
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 idi_48_base; 31#define IDI_48_EXTENT 8
29module_param(idi_48_base, uint, 0); 32#define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT)
30MODULE_PARM_DESC(idi_48_base, "ACCES 104-IDI-48 base address"); 33
31static unsigned idi_48_irq; 34static unsigned int base[MAX_NUM_IDI_48];
32module_param(idi_48_irq, uint, 0); 35static unsigned int num_idi_48;
33MODULE_PARM_DESC(idi_48_irq, "ACCES 104-IDI-48 interrupt line number"); 36module_param_array(base, uint, &num_idi_48, 0);
37MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses");
38
39static unsigned int irq[MAX_NUM_IDI_48];
40module_param_array(irq, uint, NULL, 0);
41MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
34 42
35/** 43/**
36 * struct idi_48_gpio - GPIO device private data structure 44 * struct idi_48_gpio - GPIO device private data structure
@@ -211,23 +219,19 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
211 return IRQ_HANDLED; 219 return IRQ_HANDLED;
212} 220}
213 221
214static int __init idi_48_probe(struct platform_device *pdev) 222static int idi_48_probe(struct device *dev, unsigned int id)
215{ 223{
216 struct device *dev = &pdev->dev;
217 struct idi_48_gpio *idi48gpio; 224 struct idi_48_gpio *idi48gpio;
218 const unsigned base = idi_48_base;
219 const unsigned extent = 8;
220 const char *const name = dev_name(dev); 225 const char *const name = dev_name(dev);
221 int err; 226 int err;
222 const unsigned irq = idi_48_irq;
223 227
224 idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL); 228 idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL);
225 if (!idi48gpio) 229 if (!idi48gpio)
226 return -ENOMEM; 230 return -ENOMEM;
227 231
228 if (!devm_request_region(dev, base, extent, name)) { 232 if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) {
229 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", 233 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
230 base, base + extent); 234 base[id], base[id] + IDI_48_EXTENT);
231 return -EBUSY; 235 return -EBUSY;
232 } 236 }
233 237
@@ -239,8 +243,8 @@ static int __init idi_48_probe(struct platform_device *pdev)
239 idi48gpio->chip.get_direction = idi_48_gpio_get_direction; 243 idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
240 idi48gpio->chip.direction_input = idi_48_gpio_direction_input; 244 idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
241 idi48gpio->chip.get = idi_48_gpio_get; 245 idi48gpio->chip.get = idi_48_gpio_get;
242 idi48gpio->base = base; 246 idi48gpio->base = base[id];
243 idi48gpio->irq = irq; 247 idi48gpio->irq = irq[id];
244 248
245 spin_lock_init(&idi48gpio->lock); 249 spin_lock_init(&idi48gpio->lock);
246 250
@@ -253,8 +257,8 @@ static int __init idi_48_probe(struct platform_device *pdev)
253 } 257 }
254 258
255 /* Disable IRQ by default */ 259 /* Disable IRQ by default */
256 outb(0, base + 7); 260 outb(0, base[id] + 7);
257 inb(base + 7); 261 inb(base[id] + 7);
258 262
259 err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0, 263 err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0,
260 handle_edge_irq, IRQ_TYPE_NONE); 264 handle_edge_irq, IRQ_TYPE_NONE);
@@ -263,7 +267,7 @@ static int __init idi_48_probe(struct platform_device *pdev)
263 goto err_gpiochip_remove; 267 goto err_gpiochip_remove;
264 } 268 }
265 269
266 err = request_irq(irq, idi_48_irq_handler, IRQF_SHARED, name, 270 err = request_irq(irq[id], idi_48_irq_handler, IRQF_SHARED, name,
267 idi48gpio); 271 idi48gpio);
268 if (err) { 272 if (err) {
269 dev_err(dev, "IRQ handler registering failed (%d)\n", err); 273 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
@@ -277,9 +281,9 @@ err_gpiochip_remove:
277 return err; 281 return err;
278} 282}
279 283
280static int idi_48_remove(struct platform_device *pdev) 284static int idi_48_remove(struct device *dev, unsigned int id)
281{ 285{
282 struct idi_48_gpio *const idi48gpio = platform_get_drvdata(pdev); 286 struct idi_48_gpio *const idi48gpio = dev_get_drvdata(dev);
283 287
284 free_irq(idi48gpio->irq, idi48gpio); 288 free_irq(idi48gpio->irq, idi48gpio);
285 gpiochip_remove(&idi48gpio->chip); 289 gpiochip_remove(&idi48gpio->chip);
@@ -287,48 +291,14 @@ static int idi_48_remove(struct platform_device *pdev)
287 return 0; 291 return 0;
288} 292}
289 293
290static struct platform_device *idi_48_device; 294static struct isa_driver idi_48_driver = {
291 295 .probe = idi_48_probe,
292static struct platform_driver idi_48_driver = {
293 .driver = { 296 .driver = {
294 .name = "104-idi-48" 297 .name = "104-idi-48"
295 }, 298 },
296 .remove = idi_48_remove 299 .remove = idi_48_remove
297}; 300};
298 301module_isa_driver(idi_48_driver, num_idi_48);
299static void __exit idi_48_exit(void)
300{
301 platform_device_unregister(idi_48_device);
302 platform_driver_unregister(&idi_48_driver);
303}
304
305static int __init idi_48_init(void)
306{
307 int err;
308
309 idi_48_device = platform_device_alloc(idi_48_driver.driver.name, -1);
310 if (!idi_48_device)
311 return -ENOMEM;
312
313 err = platform_device_add(idi_48_device);
314 if (err)
315 goto err_platform_device;
316
317 err = platform_driver_probe(&idi_48_driver, idi_48_probe);
318 if (err)
319 goto err_platform_driver;
320
321 return 0;
322
323err_platform_driver:
324 platform_device_del(idi_48_device);
325err_platform_device:
326 platform_device_put(idi_48_device);
327 return err;
328}
329
330module_init(idi_48_init);
331module_exit(idi_48_exit);
332 302
333MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 303MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
334MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver"); 304MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");