summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2007-05-08 00:36:05 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 11:15:23 -0700
commitd0d4f69bb65a8c1c1430c577a583632709b874c6 (patch)
treeede912558cb84976579f9e9c22c05c6a66941fe7
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>
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--drivers/net/irda/smsc-ircc2.c98
2 files changed, 86 insertions, 23 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 38d7db3262c..fa885174fd7 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1578,6 +1578,17 @@ and is between 256 and 4096 characters. It is defined in the file
smp-alt-once [IA-32,SMP] On a hotplug CPU system, only
attempt to substitute SMP alternatives once at boot.
+ smsc-ircc2.nopnp [HW] Don't use PNP to discover SMC devices
+ smsc-ircc2.ircc_cfg= [HW] Device configuration I/O port
+ smsc-ircc2.ircc_sir= [HW] SIR base I/O port
+ smsc-ircc2.ircc_fir= [HW] FIR base I/O port
+ smsc-ircc2.ircc_irq= [HW] IRQ line
+ smsc-ircc2.ircc_dma= [HW] DMA channel
+ smsc-ircc2.ircc_transceiver= [HW] Transceiver type:
+ 0: Toshiba Satellite 1800 (GP data pin select)
+ 1: Fast pin select (default)
+ 2: ATC IRMode
+
snd-ad1816a= [HW,ALSA]
snd-ad1848= [HW,ALSA]
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 1d249737f96..9043bf4aa49 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>");
MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
MODULE_LICENSE("GPL");
+static int smsc_nopnp;
+module_param_named(nopnp, smsc_nopnp, bool, 0);
+MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
+
#define DMA_INVAL 255
static int ircc_dma = DMA_INVAL;
module_param(ircc_dma, int, 0);
@@ -362,7 +366,6 @@ static inline void register_bank(int iobase, int bank)
iobase + IRCC_MASTER);
}
-#ifdef CONFIG_PNP
/* PNP hotplug support */
static const struct pnp_device_id smsc_ircc_pnp_table[] = {
{ .id = "SMCf010", .driver_data = 0 },
@@ -370,7 +373,35 @@ static const struct pnp_device_id smsc_ircc_pnp_table[] = {
{ }
};
MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
-#endif
+
+static int pnp_driver_registered;
+
+static int __init smsc_ircc_pnp_probe(struct pnp_dev *dev,
+ const struct pnp_device_id *dev_id)
+{
+ unsigned int firbase, sirbase;
+ u8 dma, irq;
+
+ if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
+ pnp_dma_valid(dev, 0) && pnp_irq_valid(dev, 0)))
+ return -EINVAL;
+
+ sirbase = pnp_port_start(dev, 0);
+ firbase = pnp_port_start(dev, 1);
+ dma = pnp_dma(dev, 0);
+ irq = pnp_irq(dev, 0);
+
+ if (smsc_ircc_open(firbase, sirbase, dma, irq))
+ return -ENODEV;
+
+ return 0;
+}
+
+static struct pnp_driver smsc_ircc_pnp_driver = {
+ .name = "smsc-ircc2",
+ .id_table = smsc_ircc_pnp_table,
+ .probe = smsc_ircc_pnp_probe,
+};
/*******************************************************************************
@@ -381,6 +412,35 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
*
*******************************************************************************/
+static int __init smsc_ircc_legacy_probe(void)
+{
+ int ret = 0;
+
+ if (ircc_fir > 0 && ircc_sir > 0) {
+ IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
+ IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
+
+ if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
+ ret = -ENODEV;
+ } else {
+ ret = -ENODEV;
+
+ /* try user provided configuration register base address */
+ if (ircc_cfg > 0) {
+ IRDA_MESSAGE(" Overriding configuration address "
+ "0x%04x\n", ircc_cfg);
+ if (!smsc_superio_fdc(ircc_cfg))
+ ret = 0;
+ if (!smsc_superio_lpc(ircc_cfg))
+ ret = 0;
+ }
+
+ if (smsc_ircc_look_for_chips() > 0)
+ ret = 0;
+ }
+ return ret;
+}
+
/*
* Function smsc_ircc_init ()
*
@@ -408,31 +468,20 @@ static int __init smsc_ircc_init(void)
dev_count = 0;
- if (ircc_fir > 0 && ircc_sir > 0) {
- IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
- IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
-
- if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
- ret = -ENODEV;
+ if (smsc_nopnp || !pnp_platform_devices ||
+ ircc_cfg || ircc_fir || ircc_sir ||
+ ircc_dma != DMA_INVAL || ircc_irq != IRQ_INVAL) {
+ ret = smsc_ircc_legacy_probe();
} else {
- ret = -ENODEV;
-
- /* try user provided configuration register base address */
- if (ircc_cfg > 0) {
- IRDA_MESSAGE(" Overriding configuration address "
- "0x%04x\n", ircc_cfg);
- if (!smsc_superio_fdc(ircc_cfg))
- ret = 0;
- if (!smsc_superio_lpc(ircc_cfg))
- ret = 0;
- }
-
- if (smsc_ircc_look_for_chips() > 0)
- ret = 0;
+ if (pnp_register_driver(&smsc_ircc_pnp_driver) == 0)
+ pnp_driver_registered = 1;
}
- if (ret)
+ if (ret) {
+ if (pnp_driver_registered)
+ pnp_unregister_driver(&smsc_ircc_pnp_driver);
platform_driver_unregister(&smsc_ircc_driver);
+ }
return ret;
}
@@ -1842,6 +1891,9 @@ static void __exit smsc_ircc_cleanup(void)
smsc_ircc_close(dev_self[i]);
}
+ if (pnp_driver_registered)
+ pnp_unregister_driver(&smsc_ircc_pnp_driver);
+
platform_driver_unregister(&smsc_ircc_driver);
}