linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] Fix Winbond CIR and nsc-ircc driver initialisation
@ 2010-11-11 21:24 Sean Young
  0 siblings, 0 replies; only message in thread
From: Sean Young @ 2010-11-11 21:24 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel, jesse.barnes, David Härdeman

Booting a vanilla kernel results in:

[    4.771256] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    4.771365] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[    4.771452] serial8250: ttyS1 at I/O 0x2f8 (irq = 3) is a NS16550A
[    4.771674] 00:03: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A

Which prevents the winbond-cir driver from initialising since ttyS1 is
a bastardised serial port, which can only be used for IR using the
winbond-cir driver.

[   13.947470] Winbond CIR 00:03: Region 0x2f8-0x2ff already in use!
[   13.947741] Winbond CIR 00:03: disabled
[   13.947746] Winbond CIR: probe of 00:03 failed with error -16

A workaround is to boot with argument 8250.nr_uarts=1. This is not really
desirable, so this patch makes ttyS1 go away when it's not a real
serial port.

The nsc-ircc suffers from the same problem.

Signed-off-by: Sean Young <sean@mess.org>
---
diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c
index 64f1de7..fa4e9e8 100644
--- a/drivers/input/misc/winbond-cir.c
+++ b/drivers/input/misc/winbond-cir.c
@@ -57,6 +57,7 @@
 #include <linux/bitrev.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
+#include <linux/serial_8250.h>
 
 #define DRVNAME "winbond-cir"
 
@@ -1392,10 +1393,23 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 	}
 
 	if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
-		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
-			data->sbase, data->sbase + SP_IOMEM_LEN - 1);
-		err = -EBUSY;
-		goto exit_release_ebase;
+		bool ok = false;
+#ifdef CONFIG_SERIAL_8250
+		/*
+		 * This device is a hacked serial port which will be
+		 * detected by the serial 8250 driver.
+		 */
+		if (serial8250_port_non_uart(PORT_NS16550A, data->sbase,
+								data->irq)) {
+			ok = request_region(data->sbase, SP_IOMEM_LEN, DRVNAME);
+		}
+#endif
+		if (!ok) {
+			dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+				data->sbase, data->sbase + SP_IOMEM_LEN - 1);
+			err = -EBUSY;
+			goto exit_release_ebase;
+		}
 	}
 
 	err = request_irq(data->irq, wbcir_irq_handler,
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 559fe85..ccfdfd5 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -56,6 +56,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pnp.h>
 #include <linux/platform_device.h>
+#include <linux/serial_8250.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -406,6 +407,13 @@ static int __init nsc_ircc_open(chipio_t *info)
 	
 	/* Reserve the ioports that we need */
 	ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+#ifdef CONFIG_SERIAL_8250
+	if (!ret && serial8250_port_non_uart(PORT_NS16550A, self->io.fir_base,
+								self->io.irq)) {
+		ret = request_region(self->io.fir_base,
+						self->io.fir_ext, driver_name);
+	}
+#endif
 	if (!ret) {
 		IRDA_WARNING("%s(), can't get iobase of 0x%03x\n",
 			     __func__, self->io.fir_base);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 4d8e14b..6a30e05 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -3231,6 +3231,25 @@ void serial8250_unregister_port(int line)
 }
 EXPORT_SYMBOL(serial8250_unregister_port);
 
+bool serial8250_port_non_uart(uint type, uint iobase, uint irq)
+{
+	int i;
+
+	for (i = 0; i < UART_NR; i++) {
+		struct uart_port *p = &serial8250_ports[i].port;
+
+		if (p->iobase == iobase && p->irq == irq && p->type == type) {
+			printk(KERN_INFO "ttyS%d: not in uart mode\n",
+							serial_index(p));
+			serial8250_unregister_port(i);
+			return true;
+		}
+	}
+
+	return false;
+}
+EXPORT_SYMBOL(serial8250_port_non_uart);
+
 static int __init serial8250_init(void)
 {
 	int ret;
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 97f5b45..30cf6df 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -70,6 +70,7 @@ int serial8250_register_port(struct uart_port *);
 void serial8250_unregister_port(int line);
 void serial8250_suspend_port(int line);
 void serial8250_resume_port(int line);
+bool serial8250_port_non_uart(uint type, uint iobase, uint irq);
 
 extern int early_serial_setup(struct uart_port *port);
 

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2010-11-11 21:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-11 21:24 [PATCH v2] Fix Winbond CIR and nsc-ircc driver initialisation Sean Young

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).