aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/irda/smsc-ircc2.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2007-05-08 03:36:05 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:23 -0400
commitd0d4f69bb65a8c1c1430c577a583632709b874c6 (patch)
treeede912558cb84976579f9e9c22c05c6a66941fe7 /drivers/net/irda/smsc-ircc2.c
parent916f11c760fc1c835d3fe10bebc97a02e2ac6b41 (diff)
smsc-ircc2: add PNP support
Claim devices using PNP, unless the user explicitly specified device addresses. This can be disabled with the "smsc-ircc2.nopnp" option. This removes the need for probing legacy addresses and helps untangle IR devices from serial8250 devices. Sometimes the SMC device is at a legacy COM port address but does not use the legacy COM IRQ. In this case, claiming the device using PNP rather than 8250 legacy probe means we can automatically use the correct IRQ rather than forcing the user to use "setserial" to set the IRQ manually. If the PNP claim doesn't work, make sure you don't have a setserial init script, e.g., /etc/init.d/setserial, configured to poke in legacy COM port resources for the IRDA device. That causes the serial driver to claim resources needed by this driver. Based on this patch by Ville Syrjälä: http://www.hpl.hp.com/personal/Jean_Tourrilhes/IrDA/ir260_smsc_pnp.diff Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Cc: Keith Owens <kaos@ocs.com.au> Cc: Len Brown <lenb@kernel.org> Cc: Adam Belay <ambx1@neo.rr.com> Cc: Matthieu CASTET <castet.matthieu@free.fr> Cc: Jean Tourrilhes <jt@hpl.hp.com> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Cc: Ville Syrjala <syrjala@sci.fi> Cc: Russell King <rmk+serial@arm.linux.org.uk> Acked-by: Samuel Ortiz <samuel@sortiz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/net/irda/smsc-ircc2.c')
-rw-r--r--drivers/net/irda/smsc-ircc2.c98
1 files changed, 75 insertions, 23 deletions
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 1d249737f96f..9043bf4aa49e 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -79,6 +79,10 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
79MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); 79MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
80MODULE_LICENSE("GPL"); 80MODULE_LICENSE("GPL");
81 81
82static int smsc_nopnp;
83module_param_named(nopnp, smsc_nopnp, bool, 0);
84MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
85
82#define DMA_INVAL 255 86#define DMA_INVAL 255
83static int ircc_dma = DMA_INVAL; 87static int ircc_dma = DMA_INVAL;
84module_param(ircc_dma, int, 0); 88module_param(ircc_dma, int, 0);
@@ -362,7 +366,6 @@ static inline void register_bank(int iobase, int bank)
362 iobase + IRCC_MASTER); 366 iobase + IRCC_MASTER);
363} 367}
364 368
365#ifdef CONFIG_PNP
366/* PNP hotplug support */ 369/* PNP hotplug support */
367static const struct pnp_device_id smsc_ircc_pnp_table[] = { 370static const struct pnp_device_id smsc_ircc_pnp_table[] = {
368 { .id = "SMCf010", .driver_data = 0 }, 371 { .id = "SMCf010", .driver_data = 0 },
@@ -370,7 +373,35 @@ static const struct pnp_device_id smsc_ircc_pnp_table[] = {
370 { } 373 { }
371}; 374};
372MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table); 375MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
373#endif 376
377static int pnp_driver_registered;
378
379static 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
400static 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};
374 405
375 406
376/******************************************************************************* 407/*******************************************************************************
@@ -381,6 +412,35 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
381 * 412 *
382 *******************************************************************************/ 413 *******************************************************************************/
383 414
415static 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
384/* 444/*
385 * Function smsc_ircc_init () 445 * Function smsc_ircc_init ()
386 * 446 *
@@ -408,31 +468,20 @@ static int __init smsc_ircc_init(void)
408 468
409 dev_count = 0; 469 dev_count = 0;
410 470
411 if (ircc_fir > 0 && ircc_sir > 0) { 471 if (smsc_nopnp || !pnp_platform_devices ||
412 IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); 472 ircc_cfg || ircc_fir || ircc_sir ||
413 IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); 473 ircc_dma != DMA_INVAL || ircc_irq != IRQ_INVAL) {
414 474 ret = smsc_ircc_legacy_probe();
415 if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
416 ret = -ENODEV;
417 } else { 475 } else {
418 ret = -ENODEV; 476 if (pnp_register_driver(&smsc_ircc_pnp_driver) == 0)
419 477 pnp_driver_registered = 1;
420 /* try user provided configuration register base address */
421 if (ircc_cfg > 0) {
422 IRDA_MESSAGE(" Overriding configuration address "
423 "0x%04x\n", ircc_cfg);
424 if (!smsc_superio_fdc(ircc_cfg))
425 ret = 0;
426 if (!smsc_superio_lpc(ircc_cfg))
427 ret = 0;
428 }
429
430 if (smsc_ircc_look_for_chips() > 0)
431 ret = 0;
432 } 478 }
433 479
434 if (ret) 480 if (ret) {
481 if (pnp_driver_registered)
482 pnp_unregister_driver(&smsc_ircc_pnp_driver);
435 platform_driver_unregister(&smsc_ircc_driver); 483 platform_driver_unregister(&smsc_ircc_driver);
484 }
436 485
437 return ret; 486 return ret;
438} 487}
@@ -1842,6 +1891,9 @@ static void __exit smsc_ircc_cleanup(void)
1842 smsc_ircc_close(dev_self[i]); 1891 smsc_ircc_close(dev_self[i]);
1843 } 1892 }
1844 1893
1894 if (pnp_driver_registered)
1895 pnp_unregister_driver(&smsc_ircc_pnp_driver);
1896
1845 platform_driver_unregister(&smsc_ircc_driver); 1897 platform_driver_unregister(&smsc_ircc_driver);
1846} 1898}
1847 1899