summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-104-idi-48.c
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/gpio-104-idi-48.c
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/gpio-104-idi-48.c')
-rw-r--r--drivers/gpio/gpio-104-idi-48.c86
1 files changed, 28 insertions, 58 deletions
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");