bk://bk.arm.linux.org.uk/linux-2.6-serial
rmk@flint.arm.linux.org.uk|ChangeSet|20040410110044|30229 rmk

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/04/10 12:00:44+01:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Add extra suspend/resume functionality to serial_cs.
#   
#   This calls into the 8250 driver so that the serial port settings can
#   be saved and restored over a suspend/resume cycle.  Previous kernels
#   have assumed that the port will be re-opened after such an event,
#   which may not be the case.
# 
# drivers/serial/serial_cs.c
#   2004/04/10 11:58:38+01:00 rmk@flint.arm.linux.org.uk +40 -4
#   Add extra suspend/resume functionality to serial_cs.
# 
# ChangeSet
#   2004/04/10 10:28:36+01:00 bjorn.helgaas@com.rmk.(none) 
#   [SERIAL] HCDP IRQ fixup
#   
#   Some pre-production firmware has incorrect GSI values in the
#   HCDP, which tells us where the serial console port is, so we
#   have to do the auto-IRQ thing after all.
# 
# drivers/serial/8250_hcdp.c
#   2004/04/10 10:26:14+01:00 bjorn.helgaas@com.rmk.(none) +2 -0
#   [PATCH] HCDP IRQ fixup
# 
# ChangeSet
#   2004/04/09 23:01:39+01:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Remove UPF_HUP_NOTIFY; this is no longer used.
# 
# include/linux/serial_core.h
#   2004/04/09 22:59:15+01:00 rmk@flint.arm.linux.org.uk +0 -3
#   Remove UPF_HUP_NOTIFY; this is no longer used.
# 
# ChangeSet
#   2004/04/09 22:57:30+01:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Pass sa11x0 struct device through to tty_register_device.
# 
# drivers/serial/sa1100.c
#   2004/04/09 22:55:47+01:00 rmk@flint.arm.linux.org.uk +1 -0
#   Set uart_port dev member to point at the struct device for SA11x0
#   ports.
# 
# ChangeSet
#   2004/04/09 22:52:50+01:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Pass device pointer through to tty_register_device.
#   
#   This allows drivers to pass their struct device through to
#   tty_register_device, which in turn allows sysfs to show which
#   device and driver owns the UART.
# 
# include/linux/serial_core.h
#   2004/04/09 22:51:02+01:00 rmk@flint.arm.linux.org.uk +2 -0
#   Add struct device member to uart_port.
# 
# drivers/serial/serial_core.c
#   2004/04/09 22:51:01+01:00 rmk@flint.arm.linux.org.uk +1 -1
#   Pass struct device through to tty_register_device.
# 
# ChangeSet
#   2004/04/09 22:33:45+01:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Don't try to free resources we didn't request.
# 
# drivers/serial/8250.c
#   2004/04/09 22:32:03+01:00 rmk@flint.arm.linux.org.uk +2 -0
#   If UPF_RESOURCES wasn't set, we didn't request any resources.
#   Therefore, we shouldn't try to free them.
# 
# ChangeSet
#   2004/04/09 22:29:22+01:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Correct minor debugging format string error.
# 
# drivers/serial/8250.c
#   2004/04/09 22:27:34+01:00 rmk@flint.arm.linux.org.uk +1 -1
#   Correct debugging format.
# 
# ChangeSet
#   2004/04/09 22:23:30+01:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Remove some dead declarations.
# 
# drivers/serial/8250.h
#   2004/04/09 22:21:45+01:00 rmk@flint.arm.linux.org.uk +0 -9
#   Remove obsolete declarations; these have never been used nor
#   implemented.
# 
# ChangeSet
#   2004/04/09 22:16:29+01:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Unuse old SERIAL_IO_xxx macros.
#   
#   8250.c should be using the replacement UPIO_xxx macros instead.
# 
# drivers/serial/8250.c
#   2004/04/09 22:14:16+01:00 rmk@flint.arm.linux.org.uk +13 -13
#   Unuse SERIAL_IO_xxx macros; should be using UPIO_xxx macros instead.
# 
# ChangeSet
#   2004/04/08 19:43:18+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 1807/1: S3C2410 - onboard serial
#   
#   Patch from Ben Dooks
#   
#   Serial driver for S3C2410 on board UARTs. Re-post of 1796/1
#   
#   Includes BAST driver to register on-board 16550s.
# 
# include/linux/serial_core.h
#   2004/04/05 17:12:25+01:00 ben-linux@org.rmk.(none) +3 -0
#   [PATCH] 1807/1: S3C2410 - onboard serial
# 
# drivers/serial/s3c2410.c
#   2004/04/08 15:27:21+01:00 ben-linux@org.rmk.(none) +860 -0
#   [PATCH] 1807/1: S3C2410 - onboard serial
# 
# drivers/serial/Makefile
#   2004/04/05 17:20:46+01:00 ben-linux@org.rmk.(none) +2 -0
#   [PATCH] 1807/1: S3C2410 - onboard serial
# 
# drivers/serial/s3c2410.c
#   2004/04/08 15:27:21+01:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-serial/drivers/serial/s3c2410.c
# 
# drivers/serial/Kconfig
#   2004/04/05 17:18:57+01:00 ben-linux@org.rmk.(none) +31 -0
#   [PATCH] 1807/1: S3C2410 - onboard serial
# 
# drivers/serial/bast_sio.c
#   2004/04/05 22:19:09+01:00 ben-linux@org.rmk.(none) +63 -0
#   [PATCH] 1807/1: S3C2410 - onboard serial
# 
# drivers/serial/bast_sio.c
#   2004/04/05 22:19:09+01:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-serial/drivers/serial/bast_sio.c
# 
diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c
--- a/drivers/serial/8250.c	Sat Apr 10 15:38:54 2004
+++ b/drivers/serial/8250.c	Sat Apr 10 15:38:54 2004
@@ -177,11 +177,11 @@
 	offset <<= up->port.regshift;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_HUB6:
+	case UPIO_HUB6:
 		outb(up->port.hub6 - 1 + offset, up->port.iobase);
 		return inb(up->port.iobase + 1);
 
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		return readb(up->port.membase + offset);
 
 	default:
@@ -195,12 +195,12 @@
 	offset <<= up->port.regshift;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_HUB6:
+	case UPIO_HUB6:
 		outb(up->port.hub6 - 1 + offset, up->port.iobase);
 		outb(value, up->port.iobase + 1);
 		break;
 
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		writeb(value, up->port.membase + offset);
 		break;
 
@@ -574,7 +574,7 @@
 	if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
 		return;
 
-	DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ",
+	DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ",
 			up->port.line, up->port.iobase, up->port.membase);
 
 	/*
@@ -1613,7 +1613,7 @@
 	int ret = 0;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		if (up->port.mapbase) {
 			*res = request_mem_region(up->port.mapbase, size, "serial");
 			if (!*res)
@@ -1621,8 +1621,8 @@
 		}
 		break;
 
-	case SERIAL_IO_HUB6:
-	case SERIAL_IO_PORT:
+	case UPIO_HUB6:
+	case UPIO_PORT:
 		*res = request_region(up->port.iobase, size, "serial");
 		if (!*res)
 			ret = -EBUSY;
@@ -1639,7 +1639,7 @@
 	int ret = 0;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		if (up->port.mapbase) {
 			start = up->port.mapbase;
 			start += UART_RSA_BASE << up->port.regshift;
@@ -1649,8 +1649,8 @@
 		}
 		break;
 
-	case SERIAL_IO_HUB6:
-	case SERIAL_IO_PORT:
+	case UPIO_HUB6:
+	case UPIO_PORT:
 		start = up->port.iobase;
 		start += UART_RSA_BASE << up->port.regshift;
 		*res = request_region(start, size, "serial-rsa");
@@ -1667,6 +1667,8 @@
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
 	unsigned long start, offset = 0, size = 0;
 
+	if (!(up->port.flags & UPF_RESOURCES))
+		return;
 	if (up->port.type == PORT_RSA) {
 		offset = UART_RSA_BASE << up->port.regshift;
 		size = 8;
@@ -1675,7 +1677,7 @@
 	size <<= up->port.regshift;
 
 	switch (up->port.iotype) {
-	case SERIAL_IO_MEM:
+	case UPIO_MEM:
 		if (up->port.mapbase) {
 			/*
 			 * Unmap the area.
@@ -1691,8 +1693,8 @@
 		}
 		break;
 
-	case SERIAL_IO_HUB6:
-	case SERIAL_IO_PORT:
+	case UPIO_HUB6:
+	case UPIO_PORT:
 		start = up->port.iobase;
 
 		if (size)
diff -Nru a/drivers/serial/8250.h b/drivers/serial/8250.h
--- a/drivers/serial/8250.h	Sat Apr 10 15:38:54 2004
+++ b/drivers/serial/8250.h	Sat Apr 10 15:38:54 2004
@@ -17,15 +17,6 @@
 
 #include <linux/config.h>
 
-struct serial8250_probe {
-	struct module	*owner;
-	int		(*pci_init_one)(struct pci_dev *dev);
-	void		(*pci_remove_one)(struct pci_dev *dev);
-	void		(*pnp_init)(void);
-};
-
-int serial8250_register_probe(struct serial8250_probe *probe);
-void serial8250_unregister_probe(struct serial8250_probe *probe);
 void serial8250_get_irq_map(unsigned int *map);
 void serial8250_suspend_port(int line);
 void serial8250_resume_port(int line);
diff -Nru a/drivers/serial/8250_hcdp.c b/drivers/serial/8250_hcdp.c
--- a/drivers/serial/8250_hcdp.c	Sat Apr 10 15:38:54 2004
+++ b/drivers/serial/8250_hcdp.c	Sat Apr 10 15:38:54 2004
@@ -186,6 +186,8 @@
 		port.irq = gsi;
 #endif
 		port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_RESOURCES;
+		if (gsi)
+			port.flags |= UPF_AUTO_IRQ;
 
 		/*
 		 * Note: the above memset() initializes port.line to 0,
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	Sat Apr 10 15:38:54 2004
+++ b/drivers/serial/Kconfig	Sat Apr 10 15:38:54 2004
@@ -224,6 +224,37 @@
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
+config SERIAL_S3C2410
+	tristate "Samsung S3C2410 Serial port support"
+	depends on ARM && ARCH_S3C2410
+	select SERIAL_CORE
+	help
+	  Support for the on-chip UARTs on the Samsung S3C2410X CPU,
+	  providing /dev/ttySAC0, 1 and 2 (note, some machines may not
+	  provide all of these ports, depending on how the serial port
+	  pins are configured.
+
+config SERIAL_S3C2410_CONSOLE
+	bool "Support for console on S3C2410 serial port"
+	depends on SERIAL_S3C2410=y
+	help
+	  Allow selection of the S3C2410 on-board serial ports for use as
+	  an virtual console.
+
+	  Even if you say Y here, the currently visible virtual console
+	  (/dev/tty0) will still be used as the system console by default, but
+	  you can alter that using a kernel command line option such as
+	  "console=ttySACx". (Try "man bootparam" or see the documentation of
+	  your boot loader about how to pass options to the kernel at
+	  boot time.)
+
+config SERIAL_BAST_SIO
+	bool "Support for BAST SuperIO serial ports"
+	depends on ARCH_BAST && SERIAL_8250=y
+	help
+	  Support for registerin the SuperIO chip on BAST board with
+	  the 8250/16550 uart code.
+
 config SERIAL_DZ
 	bool "DECstation DZ serial driver"
 	depends on DECSTATION
diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile
--- a/drivers/serial/Makefile	Sat Apr 10 15:38:54 2004
+++ b/drivers/serial/Makefile	Sat Apr 10 15:38:54 2004
@@ -20,6 +20,7 @@
 obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
 obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
+obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
 obj-$(CONFIG_SERIAL_UART00) += uart00.o
 obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
 obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
@@ -36,3 +37,4 @@
 obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o
 obj-$(CONFIG_SERIAL_DZ) += dz.o
 obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
+obj-$(CONFIG_SERIAL_BAST_SIO) += bast_sio.o
diff -Nru a/drivers/serial/bast_sio.c b/drivers/serial/bast_sio.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/serial/bast_sio.c	Sat Apr 10 15:38:54 2004
@@ -0,0 +1,63 @@
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/serial.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/map.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
+
+static int __init serial_bast_register(unsigned long port, unsigned int irq)
+{
+	struct serial_struct serial_req;
+
+#if 0
+	printk("BAST: SuperIO serial (%08lx,%d)\n", port, irq);
+#endif
+
+	serial_req.flags      = UPF_AUTOPROBE | UPF_RESOURCES | UPF_SHARE_IRQ;
+	serial_req.baud_base  = BASE_BAUD;
+	serial_req.irq        = irq;
+	serial_req.io_type    = UPIO_MEM;
+	serial_req.iomap_base = port;
+	serial_req.iomem_base = ioremap(port, 0x10);
+	serial_req.iomem_reg_shift = 0;
+
+	return register_serial(&serial_req);
+}
+
+#define SERIAL_BASE (S3C2410_CS2 + BAST_PA_SUPERIO)
+
+static int __init serial_bast_init(void)
+{
+	if (machine_is_bast()) {
+		serial_bast_register(SERIAL_BASE + 0x2f8, IRQ_PCSERIAL1);
+		serial_bast_register(SERIAL_BASE + 0x3f8, IRQ_PCSERIAL2);
+	}
+
+	return 0;
+}
+
+static void __exit serial_bast_exit(void)
+{
+	/* todo -> remove both our ports */
+}
+
+
+module_init(serial_bast_init);
+module_exit(serial_bast_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Dooks, ben@simtec.co.uk");
+MODULE_DESCRIPTION("BAST Onboard Serial setup");
+
+
diff -Nru a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/serial/s3c2410.c	Sat Apr 10 15:38:54 2004
@@ -0,0 +1,860 @@
+/*
+ * linux/drivers/char/s3c2410.c
+ *
+ * Driver for onboard UARTs on the Samsung S3C2410
+ *
+ * Based on drivers/char/serial.c and drivers/char/21285.c
+ *
+ * Ben Dooks, (c) 2003 Simtec Electronics
+ *
+ * Changelog:
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/regs-serial.h>
+
+#include <asm/mach-types.h>
+
+#if 0
+#include <asm/debug-ll.h>
+#define dbg(x...) llprintk(x)
+#else
+#define dbg(x...)
+#endif
+
+#define SERIAL_S3C2410_NAME	"ttySAC"
+#define SERIAL_S3C2410_MAJOR	204
+#define SERIAL_S3C2410_MINOR	4
+
+/* we can support 3 uarts, but not always use them */
+
+#define NR_PORTS (3)
+
+static const char serial_s3c2410_name[] = "Samsung S3C2410 UART";
+
+/* port irq numbers */
+
+#define TX_IRQ(port) ((port)->irq + 1)
+#define RX_IRQ(port) ((port)->irq)
+
+#define tx_enabled(port) ((port)->unused[0])
+#define rx_enabled(port) ((port)->unused[1])
+
+/* flag to ignore all characters comming in */
+#define RXSTAT_DUMMY_READ (0x10000000)
+
+/* access functions */
+
+#define portaddr(port, reg) ((void *)((port)->membase + (reg)))
+
+#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
+#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
+
+#define wr_regb(port, reg, val) \
+  do { __raw_writeb(val, portaddr(port, reg)); } while(0)
+
+#define wr_regl(port, reg, val) \
+  do { __raw_writel(val, portaddr(port, reg)); } while(0)
+
+
+
+
+/* code */
+
+static void
+serial_s3c2410_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	if (tx_enabled(port)) {
+		disable_irq(TX_IRQ(port));
+		tx_enabled(port) = 0;
+	}
+}
+
+static void
+serial_s3c2410_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	if (!tx_enabled(port)) {
+		enable_irq(TX_IRQ(port));
+		tx_enabled(port) = 1;
+	}
+}
+
+static void serial_s3c2410_stop_rx(struct uart_port *port)
+{
+	if (rx_enabled(port)) {
+		dbg("serial_s3c2410_stop_rx: port=%p\n", port);
+		disable_irq(RX_IRQ(port));
+		rx_enabled(port) = 0;
+	}
+}
+
+static void serial_s3c2410_enable_ms(struct uart_port *port)
+{
+}
+
+/* ? - where has parity gone?? */
+#define S3C2410_UERSTAT_PARITY (0x1000)
+
+static irqreturn_t
+serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = dev_id;
+	struct tty_struct *tty = port->info->tty;
+	unsigned int ufcon, ch, rxs, ufstat;
+	int max_count = 256;
+
+	while (max_count-- > 0) {
+		ufcon = rd_regl(port, S3C2410_UFCON);
+		ufstat = rd_regl(port, S3C2410_UFSTAT);
+
+		if (S3C2410_UFCON_RXC(ufstat) == 0)
+			break;
+
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+			tty->flip.work.func((void *)tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
+				goto out;
+			}
+		}
+
+		ch = rd_regb(port, S3C2410_URXH);
+
+		*tty->flip.char_buf_ptr = ch;
+		*tty->flip.flag_buf_ptr = TTY_NORMAL;
+		port->icount.rx++;
+
+		rxs = rd_regb(port, S3C2410_UERSTAT) | RXSTAT_DUMMY_READ;
+
+		if (rxs & S3C2410_UERSTAT_ANY) {
+			if (rxs & S3C2410_UERSTAT_FRAME)
+				port->icount.frame++;
+			if (rxs & S3C2410_UERSTAT_OVERRUN)
+				port->icount.overrun++;
+
+			rxs &= port->read_status_mask;
+
+			if (rxs & S3C2410_UERSTAT_PARITY)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (rxs & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN))
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+		}
+
+		if ((rxs & port->ignore_status_mask) == 0) {
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+
+		if ((rxs & S3C2410_UERSTAT_OVERRUN) &&
+		    tty->flip.count < TTY_FLIPBUF_SIZE) {
+			/*
+			 * Overrun is special, since it's reported
+			 * immediately, and doesn't affect the current
+			 * character.
+			 */
+			*tty->flip.char_buf_ptr++ = 0;
+			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+			tty->flip.count++;
+		}
+	}
+	tty_flip_buffer_push(tty);
+
+ out:
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+serial_s3c2410_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = (struct uart_port *)dev_id;
+	struct circ_buf *xmit = &port->info->xmit;
+	int count = 256;
+
+	if (port->x_char) {
+		wr_regb(port, S3C2410_UTXH, port->x_char);
+		port->icount.tx++;
+		port->x_char = 0;
+		goto out;
+	}
+
+	/* if there isnt anything more to transmit, or the uart is now
+	 * stopped, disable the uart and exit
+	*/
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		serial_s3c2410_stop_tx(port, 0);
+		goto out;
+	}
+
+	/* try and drain the buffer... */
+
+	while (!uart_circ_empty(xmit) && count-- > 0) {
+		if (rd_regl(port, S3C2410_UFSTAT) & S3C2410_UFSTAT_TXFULL)
+			break;
+
+		wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		serial_s3c2410_stop_tx(port, 0);
+
+ out:
+	return IRQ_HANDLED;
+}
+
+static unsigned int
+serial_s3c2410_tx_empty(struct uart_port *port)
+{
+	unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
+	return (S3C2410_UFCON_TXC(ufcon) != 0) ? 0 : TIOCSER_TEMT;
+}
+
+/* no modem control lines */
+static unsigned int
+serial_s3c2410_get_mctrl(struct uart_port *port)
+{
+	unsigned int umstat = rd_regb(port,S3C2410_UMSTAT);
+
+	if (umstat & S3C2410_UMSTAT_CTS)
+		return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+	else
+		return TIOCM_CAR | TIOCM_DSR;
+}
+
+static void
+serial_s3c2410_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/* todo - possibly remove AFC and do manual CTS */
+}
+
+static void serial_s3c2410_break_ctl(struct uart_port *port, int break_state)
+{
+	unsigned long flags;
+	unsigned int ucon;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	ucon = rd_regl(port, S3C2410_UCON);
+
+	if (break_state)
+		ucon |= S3C2410_UCON_SBREAK;
+	else
+		ucon &= ~S3C2410_UCON_SBREAK;
+
+	wr_regl(port, S3C2410_UCON, ucon);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int serial_s3c2410_startup(struct uart_port *port)
+{
+	int ret;
+
+	tx_enabled(port) = 1;
+	rx_enabled(port) = 1;
+
+	dbg("serial_s3c2410_startup: port=%p (%p)\n",
+	    port, port->mapbase);
+
+	ret = request_irq(RX_IRQ(port), serial_s3c2410_rx_chars, 0,
+			  serial_s3c2410_name, port);
+
+	if (ret != 0)
+		return ret;
+
+	ret = request_irq(TX_IRQ(port), serial_s3c2410_tx_chars, 0,
+			  serial_s3c2410_name, port);
+
+	if (ret) {
+		free_irq(RX_IRQ(port), port);
+		return ret;
+	}
+
+	/* the port reset code should have done the correct
+	 * register setup for the port controls */
+
+	return ret;
+}
+
+static void serial_s3c2410_shutdown(struct uart_port *port)
+{
+	free_irq(TX_IRQ(port), port);
+	free_irq(RX_IRQ(port), port);
+}
+
+static void
+serial_s3c2410_set_termios(struct uart_port *port, struct termios *termios,
+			   struct termios *old)
+{
+	unsigned long flags;
+	unsigned int baud, quot;
+	unsigned int ulcon;
+
+	/*
+	 * We don't support modem control lines.
+	 */
+	termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
+	termios->c_cflag |= CLOCAL;
+
+	/*
+	 * We don't support BREAK character recognition.
+	 */
+	termios->c_iflag &= ~(IGNBRK | BRKINT);
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+	quot = uart_get_divisor(port, baud);
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		dbg("config: 5bits/char\n");
+		ulcon = S3C2410_LCON_CS5;
+		break;
+	case CS6:
+		dbg("config: 6bits/char\n");
+		ulcon = S3C2410_LCON_CS6;
+		break;
+	case CS7:
+		dbg("config: 7bits/char\n");
+		ulcon = S3C2410_LCON_CS7;
+		break;
+	case CS8:
+	default:
+		dbg("config: 8bits/char\n");
+		ulcon = S3C2410_LCON_CS8;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		ulcon |= S3C2410_LCON_STOPB;
+
+	if (termios->c_cflag & PARENB) {
+		if (!(termios->c_cflag & PARODD))
+			ulcon |= S3C2410_LCON_PODD;
+		else
+			ulcon |= S3C2410_LCON_PEVEN;
+	} else {
+		ulcon |= S3C2410_LCON_PNONE;
+	}
+
+	/*
+	if (port->fifosize)
+	enable_fifo()
+	*/
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	dbg("setting ulcon to %08x\n", ulcon);
+	//dbg("<flushing output from serial>\n");
+
+	/* set the ulcon register */
+	wr_regl(port, S3C2410_ULCON, ulcon);
+
+	dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
+	    rd_regl(port, S3C2410_ULCON),
+	    rd_regl(port, S3C2410_UCON),
+	    rd_regl(port, S3C2410_UFCON));
+
+	/*
+	 * Update the per-port timeout.
+	 */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	/*
+	 * Which character status flags are we interested in?
+	 */
+	port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY;
+
+	/*
+	 * Which character status flags should we ignore?
+	 */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN;
+	if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= S3C2410_UERSTAT_FRAME;
+
+	/*
+	 * Ignore all characters if CREAD is not set.
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		port->ignore_status_mask |= RXSTAT_DUMMY_READ;
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *serial_s3c2410_type(struct uart_port *port)
+{
+	return port->type == PORT_S3C2410 ? "S3C2410" : NULL;
+}
+
+#define MAP_SIZE (0x100)
+
+static void
+serial_s3c2410_release_port(struct uart_port *port)
+{
+	release_mem_region(port->mapbase, MAP_SIZE);
+}
+
+static int
+serial_s3c2410_request_port(struct uart_port *port)
+{
+	return request_mem_region(port->mapbase, MAP_SIZE, serial_s3c2410_name)
+		!= NULL ? 0 : -EBUSY;
+}
+
+static void
+serial_s3c2410_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE &&
+	    serial_s3c2410_request_port(port) == 0)
+		port->type = PORT_S3C2410;
+}
+
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int
+serial_s3c2410_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	int ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_S3C2410)
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static struct uart_ops serial_s3c2410_ops = {
+	.tx_empty	= serial_s3c2410_tx_empty,
+	.get_mctrl	= serial_s3c2410_get_mctrl,
+	.set_mctrl	= serial_s3c2410_set_mctrl,
+	.stop_tx	= serial_s3c2410_stop_tx,
+	.start_tx	= serial_s3c2410_start_tx,
+	.stop_rx	= serial_s3c2410_stop_rx,
+	.enable_ms	= serial_s3c2410_enable_ms,
+	.break_ctl	= serial_s3c2410_break_ctl,
+	.startup	= serial_s3c2410_startup,
+	.shutdown	= serial_s3c2410_shutdown,
+	.set_termios	= serial_s3c2410_set_termios,
+	.type		= serial_s3c2410_type,
+	.release_port	= serial_s3c2410_release_port,
+	.request_port	= serial_s3c2410_request_port,
+	.config_port	= serial_s3c2410_config_port,
+	.verify_port	= serial_s3c2410_verify_port,
+};
+
+static struct uart_port serial_s3c2410_ports[NR_PORTS] = {
+	{
+		.membase	= 0,
+		.mapbase	= 0,
+		.iotype		= UPIO_MEM,
+		.irq		= IRQ_S3CUART_RX0,
+		.uartclk	= 0,
+		.fifosize	= 16,
+		.ops		= &serial_s3c2410_ops,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.line		= 0,
+	},
+	{
+		.membase	= 0,
+		.mapbase	= 0,
+		.iotype		= UPIO_MEM,
+		.irq		= IRQ_S3CUART_RX1,
+		.uartclk	= 0,
+		.fifosize	= 16,
+		.ops		= &serial_s3c2410_ops,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.line		= 1,
+	}
+#if NR_PORTS > 2
+	,
+	{
+		.membase	= 0,
+		.mapbase	= 0,
+		.iotype		= UPIO_MEM,
+		.irq		= IRQ_S3CUART_RX2,
+		.uartclk	= 0,
+		.fifosize	= 16,
+		.ops		= &serial_s3c2410_ops,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.line		= 2,
+	}
+#endif
+};
+
+static int
+serial_s3c2410_resetport(struct uart_port *port,
+			 struct s3c2410_uartcfg *cfg)
+{
+	/* ensure registers are setup */
+
+	dbg("serial_s3c2410_resetport: port=%p (%08x), cfg=%p\n",
+	    port, port->mapbase, cfg);
+
+	wr_regl(port, S3C2410_UCON,  cfg->ucon);
+	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+	/* reset both fifos */
+
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+	return 0;
+}
+
+/* serial_s3c2410_init_ports
+ *
+ * initialise the serial ports from the machine provided initialisation
+ * data.
+*/
+
+static int serial_s3c2410_init_ports(void)
+{
+	struct uart_port *ptr = serial_s3c2410_ports;
+	struct s3c2410_uartcfg *cfg = s3c2410_uartcfgs;
+	static int inited = 0;
+	int i;
+
+	if (inited)
+		return 0;
+	inited = 1;
+
+	dbg("serial_s3c2410_init_ports: initialising ports...\n");
+
+	for (i = 0; i < NR_PORTS; i++, ptr++, cfg++) {
+
+		if (cfg->hwport > 3)
+			continue;
+
+		dbg("serial_s3c2410_init_ports: port %d (hw %d)...\n",
+		    i, cfg->hwport);
+
+		if (cfg->clock != NULL)
+			ptr->uartclk = *cfg->clock;
+
+		switch (cfg->hwport) {
+		case 0:
+			ptr->mapbase = S3C2410_PA_UART0;
+			ptr->membase = (char *)S3C2410_VA_UART0;
+			ptr->irq     = IRQ_S3CUART_RX0;
+			break;
+
+		case 1:
+			ptr->mapbase = S3C2410_PA_UART1;
+			ptr->membase = (char *)S3C2410_VA_UART1;
+			ptr->irq     = IRQ_S3CUART_RX1;
+			break;
+
+		case 2:
+			ptr->mapbase = S3C2410_PA_UART2;
+			ptr->membase = (char *)S3C2410_VA_UART2;
+			ptr->irq     = IRQ_S3CUART_RX2;
+			break;
+		}
+
+		if (ptr->mapbase == 0)
+			continue;
+
+		/* reset the fifos (and setup the uart */
+		serial_s3c2410_resetport(ptr, cfg);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SERIAL_S3C2410_CONSOLE
+
+static struct uart_port *cons_uart;
+
+static int
+serial_s3c2410_console_txrdy(struct uart_port *port, unsigned int ufcon)
+{
+	unsigned long ufstat, utrstat;
+
+	if (ufcon & S3C2410_UFCON_FIFOMODE) {
+		/* fifo mode - check ammount of data in fifo registers... */
+
+		ufstat = rd_regl(port, S3C2410_UFSTAT);
+
+		return S3C2410_UFCON_TXC(ufstat) < 12;
+	}
+
+	/* in non-fifo mode, we go and use the tx buffer empty */
+
+	utrstat = rd_regl(port, S3C2410_UTRSTAT);
+
+	return (utrstat & S3C2410_UTRSTAT_TXFE) ? 1 : 0;
+}
+
+static void
+serial_s3c2410_console_write(struct console *co, const char *s,
+			     unsigned int count)
+{
+	int i;
+	unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+
+	for (i = 0; i < count; i++) {
+		while (!serial_s3c2410_console_txrdy(cons_uart, ufcon))
+			barrier();
+
+		wr_regb(cons_uart, S3C2410_UTXH, s[i]);
+
+		if (s[i] == '\n') {
+			while (!serial_s3c2410_console_txrdy(cons_uart, ufcon))
+				barrier();
+
+			wr_regb(cons_uart, S3C2410_UTXH, '\r');
+		}
+	}
+}
+
+static void __init
+serial_s3c2410_get_options(struct uart_port *port, int *baud,
+			   int *parity, int *bits)
+{
+
+	unsigned int ulcon, ucon, ubrdiv;
+
+	ulcon  = rd_regl(port, S3C2410_ULCON);
+	ucon   = rd_regl(port, S3C2410_UCON);
+	ubrdiv = rd_regl(port, S3C2410_UBRDIV);
+
+	dbg("serial_s3c2410_get_options: port=%p\n"
+	    "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
+	    port, ulcon, ucon, ubrdiv);
+
+	if ((ucon & 0xf) != 0) {
+		/* consider the serial port configured if the tx/rx mode set */
+
+		switch (ulcon & S3C2410_LCON_CSMASK) {
+		case S3C2410_LCON_CS5:
+			*bits = 5;
+			break;
+		case S3C2410_LCON_CS6:
+			*bits = 6;
+			break;
+		case S3C2410_LCON_CS7:
+			*bits = 7;
+			break;
+		default:
+		case S3C2410_LCON_CS8:
+			*bits = 8;
+			break;
+		}
+
+		switch (ulcon & S3C2410_LCON_PMASK) {
+		case S3C2410_LCON_PEVEN:
+			*parity = 'e';
+			break;
+
+		case S3C2410_LCON_PODD:
+			*parity = 'o';
+			break;
+
+		default:
+		case S3C2410_LCON_PNONE:
+			/* nothing */
+		}
+
+		/* now calculate the baud rate */
+
+		*baud = port->uartclk / ( 16 * (ubrdiv + 1));
+		dbg("calculated baud %d\n", *baud);
+	}
+
+}
+
+static int __init
+serial_s3c2410_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	/* is this a valid port */
+
+	if (co->index == -1 || co->index >= NR_PORTS)
+		co->index = 0;
+
+	port = &serial_s3c2410_ports[co->index];
+
+	/* is the port configured? */
+
+	if (port->mapbase == 0x0) {
+		co->index = 0;
+		port = &serial_s3c2410_ports[co->index];
+	}
+
+	cons_uart = port;
+
+	dbg("serial_s3c2410_console_setup: port=%p (%d)\n", port, co->index);
+
+	/*
+	 * Check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	else
+		serial_s3c2410_get_options(port, &baud, &parity, &bits);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver s3c2410_uart_drv;
+
+static struct console serial_s3c2410_console =
+{
+	.name		= SERIAL_S3C2410_NAME,
+	.write		= serial_s3c2410_console_write,
+	.device		= uart_console_device,
+	.setup		= serial_s3c2410_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &s3c2410_uart_drv,
+};
+
+static int __init s3c2410_console_init(void)
+{
+	dbg("s3c2410_console_init:\n");
+
+	serial_s3c2410_init_ports();
+	register_console(&serial_s3c2410_console);
+	return 0;
+}
+console_initcall(s3c2410_console_init);
+
+#define SERIAL_S3C2410_CONSOLE	&serial_s3c2410_console
+#else
+#define SERIAL_S3C2410_CONSOLE	NULL
+#endif
+
+static struct uart_driver s3c2410_uart_drv = {
+	.owner			= THIS_MODULE,
+	.driver_name		= SERIAL_S3C2410_NAME,
+	.dev_name		= SERIAL_S3C2410_NAME,
+	.major			= SERIAL_S3C2410_MAJOR,
+	.minor			= SERIAL_S3C2410_MINOR,
+	.nr			= 3,
+	.cons			= SERIAL_S3C2410_CONSOLE,
+};
+
+/* device driver */
+
+static int s3c2410_serial_probe(struct device *_dev);
+static int s3c2410_serial_remove(struct device *_dev);
+
+static struct device_driver s3c2410_serial_drv = {
+	.name		= "s3c2410-uart",
+	.bus		= &platform_bus_type,
+	.probe		= s3c2410_serial_probe,
+	.remove		= s3c2410_serial_remove,
+	.suspend	= NULL,
+	.resume		= NULL,
+};
+
+#define s3c2410_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
+
+static int s3c2410_serial_probe(struct device *_dev)
+{
+	struct platform_device *dev = to_platform_device(_dev);
+	struct resource *res = dev->resource;
+	int i;
+
+	dbg("s3c2410_serial_probe: dev=%p, _dev=%p, res=%p\n", _dev, dev, res);
+
+	for (i = 0; i < dev->num_resources; i++, res++)
+		if (res->flags & IORESOURCE_MEM)
+			break;
+
+	if (i < dev->num_resources) {
+		struct uart_port *ptr = serial_s3c2410_ports;
+
+		for (i = 0; i < NR_PORTS; i++, ptr++) {
+			dbg("s3c2410_serial_probe: ptr=%p (%08x, %08x)\n",
+			    ptr, ptr->mapbase, ptr->membase);
+
+			if (ptr->mapbase != res->start)
+				continue;
+
+			dbg("s3c2410_serial_probe: got device %p: port=%p\n",
+			    _dev, ptr);
+
+			uart_add_one_port(&s3c2410_uart_drv, ptr);
+			dev_set_drvdata(_dev, ptr);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int s3c2410_serial_remove(struct device *_dev)
+{
+	struct uart_port *port = s3c2410_dev_to_port(_dev);
+
+	if (port)
+		uart_remove_one_port(&s3c2410_uart_drv, port);
+
+	return 0;
+}
+
+
+
+static int __init serial_s3c2410_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "S3C2410X Serial, (c) 2003 Simtec Electronics\n");
+
+	ret = uart_register_driver(&s3c2410_uart_drv);
+	if (ret != 0)
+		return ret;
+
+	ret = driver_register(&s3c2410_serial_drv);
+	if (ret) {
+		uart_unregister_driver(&s3c2410_uart_drv);
+	}
+
+	return ret;
+}
+
+static void __exit serial_s3c2410_exit(void)
+{
+	driver_unregister(&s3c2410_serial_drv);
+	uart_unregister_driver(&s3c2410_uart_drv);
+}
+
+module_init(serial_s3c2410_init);
+module_exit(serial_s3c2410_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("Samsung S3C2410X (S3C2410) Serial driver");
diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
--- a/drivers/serial/sa1100.c	Sat Apr 10 15:38:54 2004
+++ b/drivers/serial/sa1100.c	Sat Apr 10 15:38:54 2004
@@ -894,6 +894,7 @@
 			if (sa1100_ports[i].port.mapbase != res->start)
 				continue;
 
+			sa1100_ports[i].port.dev = _dev;
 			uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
 			dev_set_drvdata(_dev, &sa1100_ports[i]);
 			break;
diff -Nru a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
--- a/drivers/serial/serial_core.c	Sat Apr 10 15:38:54 2004
+++ b/drivers/serial/serial_core.c	Sat Apr 10 15:38:54 2004
@@ -2227,7 +2227,7 @@
 	 * Register the port whether it's detected or not.  This allows
 	 * setserial to be used to alter this ports parameters.
 	 */
-	tty_register_device(drv->tty_driver, port->line, NULL);
+	tty_register_device(drv->tty_driver, port->line, port->dev);
 
  out:
 	up(&port_sem);
diff -Nru a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
--- a/drivers/serial/serial_cs.c	Sat Apr 10 15:38:54 2004
+++ b/drivers/serial/serial_cs.c	Sat Apr 10 15:38:54 2004
@@ -54,6 +54,8 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
 
+#include "8250.h"
+
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
@@ -158,6 +160,38 @@
 	}
 }
 
+static void serial_suspend(dev_link_t *link)
+{
+	link->state |= DEV_SUSPEND;
+
+	if (link->state & DEV_CONFIG) {
+		struct serial_info *info = link->priv;
+		int i;
+
+		for (i = 0; i < info->ndev; i++)
+			serial8250_suspend_port(info->line[i]);
+
+		if (!info->slave)
+			pcmcia_release_configuration(link->handle);
+	}
+}
+
+static void serial_resume(dev_link_t *link)
+{
+	link->state &= ~DEV_SUSPEND;
+
+	if (DEV_OK(link)) {
+		struct serial_info *info = link->priv;
+		int i;
+
+		if (!info->slave)
+			pcmcia_request_configuration(link->handle, &link->conf);
+
+		for (i = 0; i < info->ndev; i++)
+			serial8250_resume_port(info->line[i]);
+	}
+}
+
 /*======================================================================
 
     serial_attach() creates an "instance" of the driver, allocating
@@ -674,16 +708,18 @@
 		break;
 
 	case CS_EVENT_PM_SUSPEND:
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
+		serial_suspend(link);
+		break;
+
 	case CS_EVENT_RESET_PHYSICAL:
 		if ((link->state & DEV_CONFIG) && !info->slave)
 			pcmcia_release_configuration(link->handle);
 		break;
 
 	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
+		serial_resume(link);
+		break;
+
 	case CS_EVENT_CARD_RESET:
 		if (DEV_OK(link) && !info->slave)
 			pcmcia_request_configuration(link->handle, &link->conf);
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	Sat Apr 10 15:38:54 2004
+++ b/include/linux/serial_core.h	Sat Apr 10 15:38:54 2004
@@ -16,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *  $Id: serial_core.h,v 1.49 2002/07/20 18:06:32 rmk Exp $
  */
 
 /*
@@ -83,6 +81,9 @@
 #define PORT_SCIF	53
 #define PORT_IRDA	54
 
+/* Samsung S3C2410 SoC and derivatives thereof */
+#define PORT_S3C2410    55
+
 #ifdef __KERNEL__
 
 #include <linux/config.h>
@@ -94,6 +95,7 @@
 struct uart_port;
 struct uart_info;
 struct serial_struct;
+struct device;
 
 /*
  * This structure describes all the operations that can be
@@ -182,7 +184,6 @@
 
 	unsigned int		flags;
 
-#define UPF_HUP_NOTIFY		(1 << 0)
 #define UPF_FOURPORT		(1 << 1)
 #define UPF_SAK			(1 << 2)
 #define UPF_SPD_MASK		(0x1030)
@@ -215,6 +216,7 @@
 	unsigned int		custom_divisor;
 	unsigned int		line;			/* port index */
 	unsigned long		mapbase;		/* for ioremap */
+	struct device		*dev;			/* parent device */
 	unsigned char		hub6;			/* this should be in the 8250 driver */
 	unsigned char		unused[3];
 };
