mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Sean Young <sean@mess.org>
To: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: linux-kernel@vger.kernel.org, jesse.barnes@intel.com,
	"David Härdeman" <david@hardeman.nu>
Subject: [PATCH v2] Fix Winbond CIR and nsc-ircc driver initialisation
Date: Thu, 11 Nov 2010 21:24:07 +0000	[thread overview]
Message-ID: <20101111212407.GA96337@atlantis.8hz.com> (raw)

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);
 

                 reply	other threads:[~2010-11-11 21:24 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101111212407.GA96337@atlantis.8hz.com \
    --to=sean@mess.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=david@hardeman.nu \
    --cc=jesse.barnes@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®