diff options
Diffstat (limited to 'drivers/net/irda/smsc-ircc2.c')
-rw-r--r-- | drivers/net/irda/smsc-ircc2.c | 112 |
1 files changed, 83 insertions, 29 deletions
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 198bf3bfa70f..9043bf4aa49e 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c | |||
@@ -79,11 +79,17 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>"); | |||
79 | MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); | 79 | MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); |
80 | MODULE_LICENSE("GPL"); | 80 | MODULE_LICENSE("GPL"); |
81 | 81 | ||
82 | static int ircc_dma = 255; | 82 | static int smsc_nopnp; |
83 | module_param_named(nopnp, smsc_nopnp, bool, 0); | ||
84 | MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); | ||
85 | |||
86 | #define DMA_INVAL 255 | ||
87 | static int ircc_dma = DMA_INVAL; | ||
83 | module_param(ircc_dma, int, 0); | 88 | module_param(ircc_dma, int, 0); |
84 | MODULE_PARM_DESC(ircc_dma, "DMA channel"); | 89 | MODULE_PARM_DESC(ircc_dma, "DMA channel"); |
85 | 90 | ||
86 | static int ircc_irq = 255; | 91 | #define IRQ_INVAL 255 |
92 | static int ircc_irq = IRQ_INVAL; | ||
87 | module_param(ircc_irq, int, 0); | 93 | module_param(ircc_irq, int, 0); |
88 | MODULE_PARM_DESC(ircc_irq, "IRQ line"); | 94 | MODULE_PARM_DESC(ircc_irq, "IRQ line"); |
89 | 95 | ||
@@ -360,7 +366,6 @@ static inline void register_bank(int iobase, int bank) | |||
360 | iobase + IRCC_MASTER); | 366 | iobase + IRCC_MASTER); |
361 | } | 367 | } |
362 | 368 | ||
363 | #ifdef CONFIG_PNP | ||
364 | /* PNP hotplug support */ | 369 | /* PNP hotplug support */ |
365 | static const struct pnp_device_id smsc_ircc_pnp_table[] = { | 370 | static const struct pnp_device_id smsc_ircc_pnp_table[] = { |
366 | { .id = "SMCf010", .driver_data = 0 }, | 371 | { .id = "SMCf010", .driver_data = 0 }, |
@@ -368,7 +373,35 @@ static const struct pnp_device_id smsc_ircc_pnp_table[] = { | |||
368 | { } | 373 | { } |
369 | }; | 374 | }; |
370 | MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table); | 375 | MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table); |
371 | #endif | 376 | |
377 | static int pnp_driver_registered; | ||
378 | |||
379 | static int __init smsc_ircc_pnp_probe(struct pnp_dev *dev, | ||
380 | const struct pnp_device_id *dev_id) | ||
381 | { | ||
382 | unsigned int firbase, sirbase; | ||
383 | u8 dma, irq; | ||
384 | |||
385 | if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && | ||
386 | pnp_dma_valid(dev, 0) && pnp_irq_valid(dev, 0))) | ||
387 | return -EINVAL; | ||
388 | |||
389 | sirbase = pnp_port_start(dev, 0); | ||
390 | firbase = pnp_port_start(dev, 1); | ||
391 | dma = pnp_dma(dev, 0); | ||
392 | irq = pnp_irq(dev, 0); | ||
393 | |||
394 | if (smsc_ircc_open(firbase, sirbase, dma, irq)) | ||
395 | return -ENODEV; | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static struct pnp_driver smsc_ircc_pnp_driver = { | ||
401 | .name = "smsc-ircc2", | ||
402 | .id_table = smsc_ircc_pnp_table, | ||
403 | .probe = smsc_ircc_pnp_probe, | ||
404 | }; | ||
372 | 405 | ||
373 | 406 | ||
374 | /******************************************************************************* | 407 | /******************************************************************************* |
@@ -379,6 +412,35 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table); | |||
379 | * | 412 | * |
380 | *******************************************************************************/ | 413 | *******************************************************************************/ |
381 | 414 | ||
415 | static int __init smsc_ircc_legacy_probe(void) | ||
416 | { | ||
417 | int ret = 0; | ||
418 | |||
419 | if (ircc_fir > 0 && ircc_sir > 0) { | ||
420 | IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); | ||
421 | IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); | ||
422 | |||
423 | if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq)) | ||
424 | ret = -ENODEV; | ||
425 | } else { | ||
426 | ret = -ENODEV; | ||
427 | |||
428 | /* try user provided configuration register base address */ | ||
429 | if (ircc_cfg > 0) { | ||
430 | IRDA_MESSAGE(" Overriding configuration address " | ||
431 | "0x%04x\n", ircc_cfg); | ||
432 | if (!smsc_superio_fdc(ircc_cfg)) | ||
433 | ret = 0; | ||
434 | if (!smsc_superio_lpc(ircc_cfg)) | ||
435 | ret = 0; | ||
436 | } | ||
437 | |||
438 | if (smsc_ircc_look_for_chips() > 0) | ||
439 | ret = 0; | ||
440 | } | ||
441 | return ret; | ||
442 | } | ||
443 | |||
382 | /* | 444 | /* |
383 | * Function smsc_ircc_init () | 445 | * Function smsc_ircc_init () |
384 | * | 446 | * |
@@ -406,31 +468,20 @@ static int __init smsc_ircc_init(void) | |||
406 | 468 | ||
407 | dev_count = 0; | 469 | dev_count = 0; |
408 | 470 | ||
409 | if (ircc_fir > 0 && ircc_sir > 0) { | 471 | if (smsc_nopnp || !pnp_platform_devices || |
410 | IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); | 472 | ircc_cfg || ircc_fir || ircc_sir || |
411 | IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); | 473 | ircc_dma != DMA_INVAL || ircc_irq != IRQ_INVAL) { |
412 | 474 | ret = smsc_ircc_legacy_probe(); | |
413 | if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq)) | ||
414 | ret = -ENODEV; | ||
415 | } else { | 475 | } else { |
416 | ret = -ENODEV; | 476 | if (pnp_register_driver(&smsc_ircc_pnp_driver) == 0) |
417 | 477 | pnp_driver_registered = 1; | |
418 | /* try user provided configuration register base address */ | ||
419 | if (ircc_cfg > 0) { | ||
420 | IRDA_MESSAGE(" Overriding configuration address " | ||
421 | "0x%04x\n", ircc_cfg); | ||
422 | if (!smsc_superio_fdc(ircc_cfg)) | ||
423 | ret = 0; | ||
424 | if (!smsc_superio_lpc(ircc_cfg)) | ||
425 | ret = 0; | ||
426 | } | ||
427 | |||
428 | if (smsc_ircc_look_for_chips() > 0) | ||
429 | ret = 0; | ||
430 | } | 478 | } |
431 | 479 | ||
432 | if (ret) | 480 | if (ret) { |
481 | if (pnp_driver_registered) | ||
482 | pnp_unregister_driver(&smsc_ircc_pnp_driver); | ||
433 | platform_driver_unregister(&smsc_ircc_driver); | 483 | platform_driver_unregister(&smsc_ircc_driver); |
484 | } | ||
434 | 485 | ||
435 | return ret; | 486 | return ret; |
436 | } | 487 | } |
@@ -646,7 +697,7 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, | |||
646 | self->io.fifo_size = SMSC_IRCC2_FIFO_SIZE; | 697 | self->io.fifo_size = SMSC_IRCC2_FIFO_SIZE; |
647 | self->io.speed = SMSC_IRCC2_C_IRDA_FALLBACK_SPEED; | 698 | self->io.speed = SMSC_IRCC2_C_IRDA_FALLBACK_SPEED; |
648 | 699 | ||
649 | if (irq < 255) { | 700 | if (irq != IRQ_INVAL) { |
650 | if (irq != chip_irq) | 701 | if (irq != chip_irq) |
651 | IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n", | 702 | IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n", |
652 | driver_name, chip_irq, irq); | 703 | driver_name, chip_irq, irq); |
@@ -654,7 +705,7 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, | |||
654 | } else | 705 | } else |
655 | self->io.irq = chip_irq; | 706 | self->io.irq = chip_irq; |
656 | 707 | ||
657 | if (dma < 255) { | 708 | if (dma != DMA_INVAL) { |
658 | if (dma != chip_dma) | 709 | if (dma != chip_dma) |
659 | IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n", | 710 | IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n", |
660 | driver_name, chip_dma, dma); | 711 | driver_name, chip_dma, dma); |
@@ -1840,6 +1891,9 @@ static void __exit smsc_ircc_cleanup(void) | |||
1840 | smsc_ircc_close(dev_self[i]); | 1891 | smsc_ircc_close(dev_self[i]); |
1841 | } | 1892 | } |
1842 | 1893 | ||
1894 | if (pnp_driver_registered) | ||
1895 | pnp_unregister_driver(&smsc_ircc_pnp_driver); | ||
1896 | |||
1843 | platform_driver_unregister(&smsc_ircc_driver); | 1897 | platform_driver_unregister(&smsc_ircc_driver); |
1844 | } | 1898 | } |
1845 | 1899 | ||
@@ -2836,9 +2890,9 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, | |||
2836 | tmpconf.fir_io = ircc_fir; | 2890 | tmpconf.fir_io = ircc_fir; |
2837 | if (ircc_sir != 0) | 2891 | if (ircc_sir != 0) |
2838 | tmpconf.sir_io = ircc_sir; | 2892 | tmpconf.sir_io = ircc_sir; |
2839 | if (ircc_dma != 0xff) | 2893 | if (ircc_dma != DMA_INVAL) |
2840 | tmpconf.fir_dma = ircc_dma; | 2894 | tmpconf.fir_dma = ircc_dma; |
2841 | if (ircc_irq != 0xff) | 2895 | if (ircc_irq != IRQ_INVAL) |
2842 | tmpconf.fir_irq = ircc_irq; | 2896 | tmpconf.fir_irq = ircc_irq; |
2843 | 2897 | ||
2844 | IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name); | 2898 | IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name); |