linux-cvs-patches
[Top] [All Lists]

CVS Update@linux-mips.org: linux

To: linux-cvs-patches@linux-mips.org
Subject: CVS Update@linux-mips.org: linux
From: ppopov@linux-mips.org
Date: Fri, 05 Aug 2005 02:14:48 +0100
Reply-to: linux-mips@linux-mips.org
Sender: linux-cvs-patches-bounce@linux-mips.org
CVSROOT:        /home/cvs
Module name:    linux
Changes by:     ppopov@ftp.linux-mips.org       05/08/05 02:14:41

Modified files:
        arch/mips/configs: pnx8550-jbs_defconfig 
        arch/mips/philips/pnx8550/common: gdb_hook.c int.c pci.c 
                                          platform.c proc.c prom.c 
                                          reset.c setup.c time.c 
        arch/mips/philips/pnx8550/jbs: board_setup.c init.c irqmap.c 
        drivers/serial : Kconfig Makefile 
        include/asm-mips/mach-pnx8550: uart.h 
        include/linux  : serial_core.h 
Added files:
        drivers/serial : ip3106_uart.c 
        include/linux  : serial_ip3106.h 
Removed files:
        drivers/serial : pnx8550_uart.c 

Log message:
        - Cleaned up .h include path names
        - Cleaned up uart driver and further abstracted out the SoC
        hardware dependencies so the driver can be used across different SoCs.
        - Renamed the driver to ip3106_uart.c to match the name of the
        Philips IP block.

diff -urN linux/arch/mips/configs/pnx8550-jbs_defconfig 
linux/arch/mips/configs/pnx8550-jbs_defconfig
--- linux/arch/mips/configs/pnx8550-jbs_defconfig       2005/08/03 15:50:26     
1.5
+++ linux/arch/mips/configs/pnx8550-jbs_defconfig       2005/08/05 01:14:40     
1.6
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.13-rc5
-# Wed Aug  3 11:18:42 2005
+# Thu Aug  4 17:26:05 2005
 #
 CONFIG_MIPS=y
 
@@ -626,8 +626,8 @@
 #
 # Non-8250 serial port support
 #
-CONFIG_SERIAL_PNX8550=y
-CONFIG_SERIAL_PNX8550_CONSOLE=y
+CONFIG_SERIAL_IP3106=y
+CONFIG_SERIAL_IP3106_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
diff -urN linux/arch/mips/philips/pnx8550/common/gdb_hook.c 
linux/arch/mips/philips/pnx8550/common/gdb_hook.c
--- linux/arch/mips/philips/pnx8550/common/gdb_hook.c   2005/07/25 21:36:00     
1.2
+++ linux/arch/mips/philips/pnx8550/common/gdb_hook.c   2005/08/05 01:14:41     
1.3
@@ -27,30 +27,16 @@
 #include <linux/serial.h>
 #include <linux/serialP.h>
 #include <linux/serial_reg.h>
+#include <linux/serial_ip3106.h>
 
 #include <asm/serial.h>
 #include <asm/io.h>
 
-#include <asm/mach-pnx8550/uart.h>
+#include <uart.h>
 
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
-       SERIAL_PORT_DFNS        /* Defined in serial.h */
+static struct serial_state rs_table[IP3106_NR_PORTS] = {
 };
-
-static struct async_struct kdb_port_info = {
-       .port   = PNX8550_CONSOLE_PORT,
-};
-
-static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
-{
-       return inb(info->port + offset);
-}
-
-static __inline__ void serial_out(struct async_struct *info, int offset,
-                                 int value)
-{
-       outb(value, info->port + offset);
-}
+static struct async_struct kdb_port_info = {0};
 
 void rs_kgdb_hook(int tty_no)
 {
@@ -65,27 +51,27 @@
         * Clear all interrupts
         */
        /* Clear all the transmitter FIFO counters (pointer and status) */
-       PNX8550_UART_LCR(tty_no) |= PNX8550_UART_LCR_TX_RST;
+       IP3106_UART_LCR(tty_no) |= IP3106_UART_LCR_TX_RST;
        /* Clear all the receiver FIFO counters (pointer and status) */
-       PNX8550_UART_LCR(tty_no) |= PNX8550_UART_LCR_RX_RST;
+       IP3106_UART_LCR(tty_no) |= IP3106_UART_LCR_RX_RST;
        /* Clear all interrupts */
-       PNX8550_UART_ICLR(tty_no) = PNX8550_UART_INT_ALLRX |
-               PNX8550_UART_INT_ALLTX;
+       IP3106_UART_ICLR(tty_no) = IP3106_UART_INT_ALLRX |
+               IP3106_UART_INT_ALLTX;
 
        /*
         * Now, initialize the UART
         */
-       PNX8550_UART_LCR(tty_no) = PNX8550_UART_LCR_8BIT;
-       PNX8550_UART_BAUD(tty_no) = 5; // 38400 Baud
+       IP3106_UART_LCR(tty_no) = IP3106_UART_LCR_8BIT;
+       IP3106_UART_BAUD(tty_no) = 5; // 38400 Baud
 }
 
 int putDebugChar(char c)
 {
        /* Wait until FIFO not full */
-       while (((PNX8550_UART_FIFO(kdb_port_info.port) & 
PNX8550_UART_FIFO_TXFIFO) >> 16) >= 16)
+       while (((IP3106_UART_FIFO(kdb_port_info.port) & 
IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
                ;
        /* Send one char */
-       PNX8550_UART_FIFO(kdb_port_info.port) = c;
+       IP3106_UART_FIFO(kdb_port_info.port) = c;
 
        return 1;
 }
@@ -95,29 +81,29 @@
        char ch;
 
        /* Wait until there is a char in the FIFO */
-       while (!((PNX8550_UART_FIFO(kdb_port_info.port) &
-                                       PNX8550_UART_FIFO_RXFIFO) >> 8))
+       while (!((IP3106_UART_FIFO(kdb_port_info.port) &
+                                       IP3106_UART_FIFO_RXFIFO) >> 8))
                ;
        /* Read one char */
-       ch = PNX8550_UART_FIFO(kdb_port_info.port) & PNX8550_UART_FIFO_RBRTHR;
+       ch = IP3106_UART_FIFO(kdb_port_info.port) & IP3106_UART_FIFO_RBRTHR;
        /* Advance the RX FIFO read pointer */
-       PNX8550_UART_LCR(kdb_port_info.port) |= PNX8550_UART_LCR_RX_NEXT;
+       IP3106_UART_LCR(kdb_port_info.port) |= IP3106_UART_LCR_RX_NEXT;
        return (ch);
 }
 
 void rs_disable_debug_interrupts(void)
 {
-       PNX8550_UART_IEN(kdb_port_info.port) = 0; /* Disable all interrupts */
+       IP3106_UART_IEN(kdb_port_info.port) = 0; /* Disable all interrupts */
 }
 
 void rs_enable_debug_interrupts(void)
 {
        /* Clear all the transmitter FIFO counters (pointer and status) */
-       PNX8550_UART_LCR(kdb_port_info.port) |= PNX8550_UART_LCR_TX_RST;
+       IP3106_UART_LCR(kdb_port_info.port) |= IP3106_UART_LCR_TX_RST;
        /* Clear all the receiver FIFO counters (pointer and status) */
-       PNX8550_UART_LCR(kdb_port_info.port) |= PNX8550_UART_LCR_RX_RST;
+       IP3106_UART_LCR(kdb_port_info.port) |= IP3106_UART_LCR_RX_RST;
        /* Clear all interrupts */
-       PNX8550_UART_ICLR(kdb_port_info.port) = PNX8550_UART_INT_ALLRX |
-               PNX8550_UART_INT_ALLTX;
-       PNX8550_UART_IEN(kdb_port_info.port)  = PNX8550_UART_INT_ALLRX; /* 
Enable RX interrupts */
+       IP3106_UART_ICLR(kdb_port_info.port) = IP3106_UART_INT_ALLRX |
+               IP3106_UART_INT_ALLTX;
+       IP3106_UART_IEN(kdb_port_info.port)  = IP3106_UART_INT_ALLRX;   /* 
Enable RX interrupts */
 }
diff -urN linux/arch/mips/philips/pnx8550/common/int.c 
linux/arch/mips/philips/pnx8550/common/int.c
--- linux/arch/mips/philips/pnx8550/common/int.c        2005/07/25 21:36:00     
1.2
+++ linux/arch/mips/philips/pnx8550/common/int.c        2005/08/05 01:14:41     
1.3
@@ -35,8 +35,8 @@
 
 #include <asm/io.h>
 #include <asm/gdb-stub.h>
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/uart.h>
+#include <int.h>
+#include <uart.h>
 
 extern asmlinkage void cp0_irqdispatch(void);
 
diff -urN linux/arch/mips/philips/pnx8550/common/pci.c 
linux/arch/mips/philips/pnx8550/common/pci.c
--- linux/arch/mips/philips/pnx8550/common/pci.c        2005/07/25 21:36:00     
1.2
+++ linux/arch/mips/philips/pnx8550/common/pci.c        2005/08/05 01:14:41     
1.3
@@ -24,9 +24,9 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/mach-pnx8550/pci.h>
-#include <asm/mach-pnx8550/glb.h>
-#include <asm/mach-pnx8550/nand.h>
+#include <pci.h>
+#include <glb.h>
+#include <nand.h>
 
 static struct resource pci_io_resource = {
        "pci IO space",
diff -urN linux/arch/mips/philips/pnx8550/common/platform.c 
linux/arch/mips/philips/pnx8550/common/platform.c
--- linux/arch/mips/philips/pnx8550/common/platform.c   2005/07/14 17:47:58     
1.1
+++ linux/arch/mips/philips/pnx8550/common/platform.c   2005/08/05 01:14:41     
1.2
@@ -16,10 +16,14 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/resource.h>
+#include <linux/serial.h>
+#include <linux/serial_ip3106.h>
 
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/usb.h>
-#include <asm/mach-pnx8550/uart.h>
+#include <int.h>
+#include <usb.h>
+#include <uart.h>
+
+extern struct uart_ops ip3106_pops;
 
 static struct resource pnx8550_usb_ohci_resources[] = {
        [0] = {
@@ -58,6 +62,37 @@
        },
 };
 
+struct ip3106_port ip3106_ports[] = {
+       [0] = {
+               .port   = {
+                       .type           = PORT_IP3106,
+                       .iotype         = SERIAL_IO_MEM,
+                       .membase        = (void __iomem *)PNX8550_UART_PORT0,
+                       .mapbase        = PNX8550_UART_PORT0,
+                       .irq            = PNX8550_UART_INT(0),
+                       .uartclk        = 3692300,
+                       .fifosize       = 16,
+                       .ops            = &ip3106_pops,
+                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .line           = 0,
+               },
+       },
+       [1] = {
+               .port   = {
+                       .type           = PORT_IP3106,
+                       .iotype         = SERIAL_IO_MEM,
+                       .membase        = (void __iomem *)PNX8550_UART_PORT1,
+                       .mapbase        = PNX8550_UART_PORT1,
+                       .irq            = PNX8550_UART_INT(1),
+                       .uartclk        = 3692300,
+                       .fifosize       = 16,
+                       .ops            = &ip3106_pops,
+                       .flags          = ASYNC_BOOT_AUTOCONF,
+                       .line           = 1,
+               },
+       },
+};
+
 /* The dmamask must be set for OHCI to work */
 static u64 ohci_dmamask = ~(u32)0;
 
@@ -75,11 +110,12 @@
 };
 
 static struct platform_device pnx8550_uart_device = {
-       .name           = "pnx8550-uart",
+       .name           = "ip3106-uart",
        .id             = -1,
        .dev = {
                .dma_mask               = &uart_dmamask,
                .coherent_dma_mask      = 0xffffffff,
+               .platform_data = ip3106_ports,
        },
        .num_resources  = ARRAY_SIZE(pnx8550_uart_resources),
        .resource       = pnx8550_uart_resources,
diff -urN linux/arch/mips/philips/pnx8550/common/proc.c 
linux/arch/mips/philips/pnx8550/common/proc.c
--- linux/arch/mips/philips/pnx8550/common/proc.c       2005/07/25 21:36:00     
1.2
+++ linux/arch/mips/philips/pnx8550/common/proc.c       2005/08/05 01:14:41     
1.3
@@ -24,8 +24,8 @@
 
 #include <asm/io.h>
 #include <asm/gdb-stub.h>
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/uart.h>
+#include <int.h>
+#include <uart.h>
 
 
 static int pnx8550_timers_read (char* page, char** start, off_t offset, int 
count, int* eof, void* data)
diff -urN linux/arch/mips/philips/pnx8550/common/prom.c 
linux/arch/mips/philips/pnx8550/common/prom.c
--- linux/arch/mips/philips/pnx8550/common/prom.c       2005/07/25 21:36:00     
1.2
+++ linux/arch/mips/philips/pnx8550/common/prom.c       2005/08/05 01:14:41     
1.3
@@ -13,9 +13,10 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/serial_ip3106.h>
 
 #include <asm/bootinfo.h>
-#include <asm/mach-pnx8550/uart.h>
+#include <uart.h>
 
 /* #define DEBUG_CMDLINE */
 
@@ -118,14 +119,19 @@
        return 0;
 }
 
+extern int pnx8550_console_port;
+
+/* used by prom_printf */
 void prom_putchar(char c)
 {
-       /* Wait until FIFO not full */
-       while( ((PNX8550_UART_FIFO(PNX8550_CONSOLE_PORT)
-                & PNX8550_UART_FIFO_TXFIFO) >> 16) >= 16)
-               ;
-       /* Send one char */
-       PNX8550_UART_FIFO(PNX8550_CONSOLE_PORT) = c;
+       if (pnx8550_console_port != -1) {
+               /* Wait until FIFO not full */
+               while( ((IP3106_UART_FIFO(1)
+                       & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
+                       ;
+               /* Send one char */
+               IP3106_UART_FIFO(1) = c;
+       }
 }
 
 EXPORT_SYMBOL(prom_getcmdline);
diff -urN linux/arch/mips/philips/pnx8550/common/reset.c 
linux/arch/mips/philips/pnx8550/common/reset.c
--- linux/arch/mips/philips/pnx8550/common/reset.c      2005/07/14 17:47:58     
1.1
+++ linux/arch/mips/philips/pnx8550/common/reset.c      2005/08/05 01:14:41     
1.2
@@ -23,7 +23,7 @@
 #include <linux/config.h>
 #include <linux/slab.h>
 #include <asm/reboot.h>
-#include <asm/mach-pnx8550/glb.h>
+#include <glb.h>
 
 void pnx8550_machine_restart(char *command)
 {
diff -urN linux/arch/mips/philips/pnx8550/common/setup.c 
linux/arch/mips/philips/pnx8550/common/setup.c
--- linux/arch/mips/philips/pnx8550/common/setup.c      2005/07/25 21:36:00     
1.2
+++ linux/arch/mips/philips/pnx8550/common/setup.c      2005/08/05 01:14:41     
1.3
@@ -24,6 +24,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/serial_ip3106.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
@@ -33,15 +34,14 @@
 #include <asm/pgtable.h>
 #include <asm/time.h>
 
-#include <asm/mach-pnx8550/glb.h>
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/pci.h>
-#include <asm/mach-pnx8550/uart.h>
-#include <asm/mach-pnx8550/nand.h>
+#include <glb.h>
+#include <int.h>
+#include <pci.h>
+#include <uart.h>
+#include <nand.h>
 
 extern void prom_printf(char *fmt, ...);
 
-extern char * __init prom_getcmdline(void);
 extern void __init board_setup(void);
 extern void pnx8550_machine_restart(char *);
 extern void pnx8550_machine_halt(void);
@@ -52,10 +52,7 @@
 extern void pnx8550_time_init(void);
 extern void (*board_timer_setup)(struct irqaction *irq);
 extern void pnx8550_timer_setup(struct irqaction *irq);
-
-extern void set_cpuspec(void);
-
-extern void pnx8550_irq_setup(void);
+extern void rs_kgdb_hook(int tty_no);
 extern void prom_printf(char *fmt, ...);
 extern char *prom_getcmdline(void);
 
@@ -82,10 +79,12 @@
        return dram_r1_hi - dram_r0_lo + 1;
 }
 
+int pnx8550_console_port = -1;
+
 void __init plat_setup(void)
 {
-       char* argptr;
        int i;
+       char* argptr;
 
        board_setup();  /* board specific setup */
 
@@ -124,19 +123,25 @@
                        PNX8550_GPIO_MC1);
 
        argptr = prom_getcmdline();
+       if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
+               argptr += strlen("console=ttyS");
+               pnx8550_console_port = *argptr == '0' ? 0 : 1;
+
+               /* We must initialize the UART (console) before prom_printf */
+               /* Set LCR to 8-bit and BAUD to 38400 (no 5)                */
+               IP3106_UART_LCR(pnx8550_console_port) = IP3106_UART_LCR_8BIT;
+               IP3106_UART_BAUD(pnx8550_console_port) = 5;
+       }
+
 #ifdef CONFIG_KGDB
+       argptr = prom_getcmdline();
        if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
                int line;
                argptr += strlen("kgdb=ttyS");
                line = *argptr == '0' ? 0 : 1;
                rs_kgdb_hook(line);
-
-               /* We must initialize the UART (console) before prom_printf */
-               /* Set LCR to 8-bit and BAUD to 38400 (no 5)                */
-               PNX8550_UART_LCR(PNX8550_CONSOLE_PORT) = PNX8550_UART_LCR_8BIT;
-               PNX8550_UART_BAUD(PNX8550_CONSOLE_PORT) = 5;
-               prom_printf("KGDB: Using serial line /dev/ttyS%i for session, "
-                           "please connect your debugger\n", line ? 1 : 0);
+               prom_printf("KGDB: Using ttyS%i for session, "
+                               "please connect your debugger\n", line ? 1 : 0);
        }
 #endif
        return;
diff -urN linux/arch/mips/philips/pnx8550/common/time.c 
linux/arch/mips/philips/pnx8550/common/time.c
--- linux/arch/mips/philips/pnx8550/common/time.c       2005/07/14 17:47:58     
1.1
+++ linux/arch/mips/philips/pnx8550/common/time.c       2005/08/05 01:14:41     
1.2
@@ -31,8 +31,8 @@
 #include <asm/div64.h>
 #include <asm/debug.h>
 
-#include <asm/mach-pnx8550/int.h>
-#include <asm/mach-pnx8550/cm.h>
+#include <int.h>
+#include <cm.h>
 
 extern unsigned int mips_hpt_frequency;
 
diff -urN linux/arch/mips/philips/pnx8550/jbs/board_setup.c 
linux/arch/mips/philips/pnx8550/jbs/board_setup.c
--- linux/arch/mips/philips/pnx8550/jbs/board_setup.c   2005/07/25 21:36:00     
1.2
+++ linux/arch/mips/philips/pnx8550/jbs/board_setup.c   2005/08/05 01:14:41     
1.3
@@ -39,7 +39,7 @@
 #include <asm/reboot.h>
 #include <asm/pgtable.h>
 
-#include <asm/mach-pnx8550/glb.h>
+#include <glb.h>
 
 /* CP0 hazard avoidance. */
 #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
diff -urN linux/arch/mips/philips/pnx8550/jbs/init.c 
linux/arch/mips/philips/pnx8550/jbs/init.c
--- linux/arch/mips/philips/pnx8550/jbs/init.c  2005/07/25 21:36:00     1.2
+++ linux/arch/mips/philips/pnx8550/jbs/init.c  2005/08/05 01:14:41     1.3
@@ -52,6 +52,7 @@
        mips_machgroup = MACH_GROUP_PHILIPS;
        mips_machtype = MACH_PHILIPS_JBS;
 
-       memsize = 0x02800000; /* Trimedia uses memory above */
+       //memsize = 0x02800000; /* Trimedia uses memory above */
+       memsize = 0x08000000; /* Trimedia uses memory above */
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
diff -urN linux/arch/mips/philips/pnx8550/jbs/irqmap.c 
linux/arch/mips/philips/pnx8550/jbs/irqmap.c
--- linux/arch/mips/philips/pnx8550/jbs/irqmap.c        2005/07/14 17:47:59     
1.1
+++ linux/arch/mips/philips/pnx8550/jbs/irqmap.c        2005/08/05 01:14:41     
1.2
@@ -26,7 +26,7 @@
  */
 
 #include <linux/init.h>
-#include <asm/mach-pnx8550/int.h>
+#include <int.h>
 
 char irq_tab_jbs[][5] __initdata = {
  [8] = { -1, PNX8550_INT_PCI_INTA, 0xff, 0xff, 0xff},
diff -urN linux/drivers/serial/ip3106_uart.c linux/drivers/serial/ip3106_uart.c
--- linux/drivers/serial/ip3106_uart.c  1970/01/01 00:00:00
+++ linux/drivers/serial/ip3106_uart.c  2005-08-05 02:14:41.557529000 +0100     
1.1
@@ -0,0 +1,912 @@
+/*
+ * Initially based on linux-2.4.20_mvl31-pnx8xx0/drivers/char/serial_pnx8550.c
+ *
+ * Complete rewrite to drivers/serial/pnx8550_uart.c by
+ * Embedded Alley Solutions, source@embeddedalley.com as part of the
+ * PNX8550 2.6 port, and then drivers/serial/ip3106_uart.c to work
+ * with other Philips SoCs.
+ *
+ * Existing copyrights from files used to write this driver:
+ * Author: Per Hallsmark per.hallsmark@mvista.com
+ *
+ * and
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_IP3106_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/serial_ip3106.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <uart.h>
+
+/* We've been assigned a range on the "Low-density serial ports" major */
+#define SERIAL_IP3106_MAJOR    204
+#define MINOR_START            5
+
+#define NR_PORTS               2
+
+#define IP3106_ISR_PASS_LIMIT  256
+
+/*
+ * Convert from ignore_status_mask or read_status_mask to FIFO
+ * and interrupt status bits
+ */
+#define SM_TO_FIFO(x)  ((x) >> 10)
+#define SM_TO_ISTAT(x) ((x) & 0x000001ff)
+#define FIFO_TO_SM(x)  ((x) << 10)
+#define ISTAT_TO_SM(x) ((x) & 0x000001ff)
+
+/*
+ * This is the size of our serial port register set.
+ */
+#define UART_PORT_SIZE 0x1000
+
+/*
+ * This determines how often we check the modem status signals
+ * for any change.  They generally aren't connected to an IRQ
+ * so we have to poll them.  We also check immediately before
+ * filling the TX fifo incase CTS has been dropped.
+ */
+#define MCTRL_TIMEOUT  (250*HZ/1000)
+
+
+extern struct ip3106_port ip3106_ports[];
+
+static inline int serial_in(struct ip3106_port *sport, int offset)
+{
+       return (__raw_readl(sport->port.membase + offset));
+}
+
+static inline void serial_out(struct ip3106_port *sport, int offset, int value)
+{
+       __raw_writel(value, sport->port.membase + offset);
+}
+
+/*
+ * Handle any change of modem status signal since we were last called.
+ */
+static void ip3106_mctrl_check(struct ip3106_port *sport)
+{
+       unsigned int status, changed;
+
+       status = sport->port.ops->get_mctrl(&sport->port);
+       changed = status ^ sport->old_status;
+
+       if (changed == 0)
+               return;
+
+       sport->old_status = status;
+
+       if (changed & TIOCM_RI)
+               sport->port.icount.rng++;
+       if (changed & TIOCM_DSR)
+               sport->port.icount.dsr++;
+       if (changed & TIOCM_CAR)
+               uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
+       if (changed & TIOCM_CTS)
+               uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
+
+       wake_up_interruptible(&sport->port.info->delta_msr_wait);
+}
+
+/*
+ * This is our per-port timeout handler, for checking the
+ * modem status signals.
+ */
+static void ip3106_timeout(unsigned long data)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)data;
+       unsigned long flags;
+
+       if (sport->port.info) {
+               spin_lock_irqsave(&sport->port.lock, flags);
+               ip3106_mctrl_check(sport);
+               spin_unlock_irqrestore(&sport->port.lock, flags);
+
+               mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
+       }
+}
+
+/*
+ * interrupts disabled on entry
+ */
+static void ip3106_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       u32 ien;
+
+       /* Disable TX intr */
+       ien = serial_in(sport, IP3106_IEN);
+       serial_out(sport, IP3106_IEN, ien & ~IP3106_UART_INT_ALLTX);
+
+       /* Clear all pending TX intr */
+       serial_out(sport, IP3106_ICLR, IP3106_UART_INT_ALLTX);
+}
+
+/*
+ * interrupts may not be disabled on entry
+ */
+static void ip3106_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       unsigned long flags;
+       u32 ien;
+
+       spin_lock_irqsave(&sport->port.lock, flags);
+
+       /* Clear all pending TX intr */
+       serial_out(sport, IP3106_ICLR, IP3106_UART_INT_ALLTX);
+
+       /* Enable TX intr */
+       ien = serial_in(sport, IP3106_IEN);
+       serial_out(sport, IP3106_IEN, ien | IP3106_UART_INT_ALLTX);
+
+       spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+/*
+ * Interrupts enabled
+ */
+static void ip3106_stop_rx(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       u32 ien;
+
+       /* Disable RX intr */
+       ien = serial_in(sport, IP3106_IEN);
+       serial_out(sport, IP3106_IEN, ien & ~IP3106_UART_INT_ALLRX);
+
+       /* Clear all pending RX intr */
+       serial_out(sport, IP3106_ICLR, IP3106_UART_INT_ALLRX);
+}
+
+/*
+ * Set the modem control timer to fire immediately.
+ */
+static void ip3106_enable_ms(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+
+       mod_timer(&sport->timer, jiffies);
+}
+
+static void
+ip3106_rx_chars(struct ip3106_port *sport, struct pt_regs *regs)
+{
+       struct tty_struct *tty = sport->port.info->tty;
+       unsigned int status, ch, flg, ignored = 0;
+
+       status = FIFO_TO_SM(serial_in(sport, IP3106_FIFO)) |
+                ISTAT_TO_SM(serial_in(sport, IP3106_ISTAT));
+       while (status & FIFO_TO_SM(IP3106_UART_FIFO_RXFIFO)) {
+               ch = serial_in(sport, IP3106_FIFO);
+
+               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+                       goto ignore_char;
+               sport->port.icount.rx++;
+
+               flg = TTY_NORMAL;
+
+               /*
+                * note that the error handling code is
+                * out of the main execution path
+                */
+               if (status & FIFO_TO_SM(IP3106_UART_FIFO_RXFE |
+                                       IP3106_UART_FIFO_RXPAR))
+                       goto handle_error;
+
+               if (uart_handle_sysrq_char(&sport->port, ch, regs))
+                       goto ignore_char;
+
+       error_return:
+               tty_insert_flip_char(tty, ch, flg);
+       ignore_char:
+               serial_out(sport, IP3106_LCR, serial_in(sport, IP3106_LCR) |
+                               IP3106_UART_LCR_RX_NEXT);
+               status = FIFO_TO_SM(serial_in(sport, IP3106_FIFO)) |
+                        ISTAT_TO_SM(serial_in(sport, IP3106_ISTAT));
+       }
+ out:
+       tty_flip_buffer_push(tty);
+       return;
+
+ handle_error:
+       if (status & FIFO_TO_SM(IP3106_UART_FIFO_RXPAR))
+               sport->port.icount.parity++;
+       else if (status & FIFO_TO_SM(IP3106_UART_FIFO_RXFE))
+               sport->port.icount.frame++;
+       if (status & ISTAT_TO_SM(IP3106_UART_INT_RXOVRN))
+               sport->port.icount.overrun++;
+
+       if (status & sport->port.ignore_status_mask) {
+               if (++ignored > 100)
+                       goto out;
+               goto ignore_char;
+       }
+
+//     status &= sport->port.read_status_mask;
+
+       if (status & FIFO_TO_SM(IP3106_UART_FIFO_RXPAR))
+               flg = TTY_PARITY;
+       else if (status & FIFO_TO_SM(IP3106_UART_FIFO_RXFE))
+               flg = TTY_FRAME;
+
+       if (status & ISTAT_TO_SM(IP3106_UART_INT_RXOVRN)) {
+               /*
+                * overrun does *not* affect the character
+                * we read from the FIFO
+                */
+               tty_insert_flip_char(tty, ch, flg);
+               ch = 0;
+               flg = TTY_OVERRUN;
+       }
+#ifdef SUPPORT_SYSRQ
+       sport->port.sysrq = 0;
+#endif
+       goto error_return;
+}
+
+static void ip3106_tx_chars(struct ip3106_port *sport)
+{
+       struct circ_buf *xmit = &sport->port.info->xmit;
+
+       if (sport->port.x_char) {
+               serial_out(sport, IP3106_FIFO, sport->port.x_char);
+               sport->port.icount.tx++;
+               sport->port.x_char = 0;
+               return;
+       }
+
+       /*
+        * Check the modem control lines before
+        * transmitting anything.
+        */
+       ip3106_mctrl_check(sport);
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
+               ip3106_stop_tx(&sport->port, 0);
+               return;
+       }
+
+       /*
+        * TX while bytes available
+        */
+       while (((serial_in(sport, IP3106_FIFO) &
+                                       IP3106_UART_FIFO_TXFIFO) >> 16) < 16) {
+               serial_out(sport, IP3106_FIFO, xmit->buf[xmit->tail]);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               sport->port.icount.tx++;
+               if (uart_circ_empty(xmit))
+                       break;
+       }
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&sport->port);
+
+       if (uart_circ_empty(xmit))
+               ip3106_stop_tx(&sport->port, 0);
+}
+
+static irqreturn_t ip3106_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct ip3106_port *sport = dev_id;
+       unsigned int status;
+
+       spin_lock(&sport->port.lock);
+       /* Get the interrupts */
+       status  = serial_in(sport, IP3106_ISTAT) & serial_in(sport, IP3106_IEN);
+
+       /* RX Receiver Holding Register Overrun */
+       if (status & IP3106_UART_INT_RXOVRN) {
+               sport->port.icount.overrun++;
+               serial_out(sport, IP3106_ICLR, IP3106_UART_INT_RXOVRN);
+       }
+
+       /* RX Frame Error */
+       if (status & IP3106_UART_INT_FRERR) {
+               sport->port.icount.frame++;
+               serial_out(sport, IP3106_ICLR, IP3106_UART_INT_FRERR);
+       }
+
+       /* Break signal received */
+       if (status & IP3106_UART_INT_BREAK) {
+               sport->port.icount.brk++;
+               serial_out(sport, IP3106_ICLR, IP3106_UART_INT_BREAK);
+       }
+
+       /* RX Parity Error */
+       if (status & IP3106_UART_INT_PARITY) {
+               sport->port.icount.parity++;
+               serial_out(sport, IP3106_ICLR, IP3106_UART_INT_PARITY);
+       }
+
+       /* Byte received */
+       if (status & IP3106_UART_INT_RX) {
+               ip3106_rx_chars(sport, regs);
+               serial_out(sport, IP3106_ICLR, IP3106_UART_INT_RX);
+       }
+
+       /* TX holding register empty - transmit a byte */
+       if (status & IP3106_UART_INT_TX) {
+               ip3106_tx_chars(sport);
+               serial_out(sport, IP3106_ICLR, IP3106_UART_INT_TX);
+       }
+
+       /* TX shift register and holding register empty  */
+       if (status & IP3106_UART_INT_EMPTY) {
+               serial_out(sport, IP3106_ICLR, IP3106_UART_INT_EMPTY);
+       }
+
+       /* Receiver time out */
+       if (status & IP3106_UART_INT_RCVTO) {
+               serial_out(sport, IP3106_ICLR, IP3106_UART_INT_RCVTO);
+       }
+       spin_unlock(&sport->port.lock);
+       return IRQ_HANDLED;
+}
+
+/*
+ * Return TIOCSER_TEMT when transmitter is not busy.
+ */
+static unsigned int ip3106_tx_empty(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+
+       return serial_in(sport, IP3106_FIFO) & IP3106_UART_FIFO_TXFIFO_STA ? 0 
: TIOCSER_TEMT;
+}
+
+static unsigned int ip3106_get_mctrl(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       unsigned int mctrl = TIOCM_DSR;
+       unsigned int msr;
+
+       /* REVISIT */
+
+       msr = serial_in(sport, IP3106_MCR);
+
+       mctrl |= msr & IP3106_UART_MCR_CTS ? TIOCM_CTS : 0;
+       mctrl |= msr & IP3106_UART_MCR_DCD ? TIOCM_CAR : 0;
+
+       return mctrl;
+}
+
+static void ip3106_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+#if    0       /* FIXME */
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       unsigned int msr;
+#endif
+}
+
+/*
+ * Interrupts always disabled.
+ */
+static void ip3106_break_ctl(struct uart_port *port, int break_state)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       unsigned long flags;
+       unsigned int lcr;
+
+       spin_lock_irqsave(&sport->port.lock, flags);
+       lcr = serial_in(sport, IP3106_LCR);
+       if (break_state == -1)
+               lcr |= IP3106_UART_LCR_TXBREAK;
+       else
+               lcr &= ~IP3106_UART_LCR_TXBREAK;
+       serial_out(sport, IP3106_LCR, lcr);
+       spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static int ip3106_startup(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       int retval;
+
+       /*
+        * Allocate the IRQ
+        */
+       retval = request_irq(sport->port.irq, ip3106_int, 0,
+                            "ip3106-uart", sport);
+       if (retval)
+               return retval;
+
+       /*
+        * Finally, clear and enable interrupts
+        */
+
+       serial_out(sport, IP3106_ICLR, IP3106_UART_INT_ALLRX |
+                            IP3106_UART_INT_ALLTX);
+
+       serial_out(sport, IP3106_IEN, serial_in(sport, IP3106_IEN) |
+                           IP3106_UART_INT_ALLRX |
+                           IP3106_UART_INT_ALLTX);
+
+       /*
+        * Enable modem status interrupts
+        */
+       spin_lock_irq(&sport->port.lock);
+       ip3106_enable_ms(&sport->port);
+       spin_unlock_irq(&sport->port.lock);
+
+       return 0;
+}
+
+static void ip3106_shutdown(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+
+       /*
+        * Stop our timer.
+        */
+       del_timer_sync(&sport->timer);
+
+       /*
+        * Disable all interrupts, port and break condition.
+        */
+       serial_out(sport, IP3106_IEN, 0);
+
+       /*
+        * Reset the Tx and Rx FIFOS
+        */
+       serial_out(sport, IP3106_LCR, serial_in(sport, IP3106_LCR) |
+                           IP3106_UART_LCR_TX_RST |
+                           IP3106_UART_LCR_RX_RST);
+
+       /*
+        * Clear all interrupts
+        */
+       serial_out(sport, IP3106_ICLR, IP3106_UART_INT_ALLRX |
+                            IP3106_UART_INT_ALLTX);
+
+       /*
+        * Free the interrupt
+        */
+       free_irq(sport->port.irq, sport);
+}
+
+static void
+ip3106_set_termios(struct uart_port *port, struct termios *termios,
+                  struct termios *old)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       unsigned long flags;
+       unsigned int lcr_fcr, old_ien, baud, quot;
+       unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+
+       /*
+        * We only support CS7 and CS8.
+        */
+       while ((termios->c_cflag & CSIZE) != CS7 &&
+              (termios->c_cflag & CSIZE) != CS8) {
+               termios->c_cflag &= ~CSIZE;
+               termios->c_cflag |= old_csize;
+               old_csize = CS8;
+       }
+
+       if ((termios->c_cflag & CSIZE) == CS8)
+               lcr_fcr = IP3106_UART_LCR_8BIT;
+       else
+               lcr_fcr = 0;
+
+       if (termios->c_cflag & CSTOPB)
+               lcr_fcr |= IP3106_UART_LCR_2STOPB;
+       if (termios->c_cflag & PARENB) {
+               lcr_fcr |= IP3106_UART_LCR_PAREN;
+               if (!(termios->c_cflag & PARODD))
+                       lcr_fcr |= IP3106_UART_LCR_PAREVN;
+       }
+
+       /*
+        * 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);
+
+       spin_lock_irqsave(&sport->port.lock, flags);
+
+#if    0       /* REVISIT */
+       sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
+       sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
+       if (termios->c_iflag & INPCK)
+               sport->port.read_status_mask |=
+                               UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
+       if (termios->c_iflag & (BRKINT | PARMRK))
+               sport->port.read_status_mask |=
+                               UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
+
+       /*
+        * Characters to ignore
+        */
+       sport->port.ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               sport->port.ignore_status_mask |=
+                               UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
+       if (termios->c_iflag & IGNBRK) {
+               sport->port.ignore_status_mask |=
+                               UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
+               /*
+                * If we're ignoring parity and break indicators,
+                * ignore overruns too (for real raw support).
+                */
+               if (termios->c_iflag & IGNPAR)
+                       sport->port.ignore_status_mask |=
+                               UTSR1_TO_SM(UTSR1_ROR);
+       }
+#endif
+
+       del_timer_sync(&sport->timer);
+
+       /*
+        * Update the per-port timeout.
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       /*
+        * disable interrupts and drain transmitter
+        */
+       old_ien = serial_in(sport, IP3106_IEN);
+       serial_out(sport, IP3106_IEN, old_ien & ~(IP3106_UART_INT_ALLTX |
+                                       IP3106_UART_INT_ALLRX));
+
+       while (serial_in(sport, IP3106_FIFO) & IP3106_UART_FIFO_TXFIFO_STA)
+               barrier();
+
+       /* then, disable everything */
+       serial_out(sport, IP3106_IEN, 0);
+
+       /* Reset the Rx and Tx FIFOs too */
+       lcr_fcr |= IP3106_UART_LCR_TX_RST;
+       lcr_fcr |= IP3106_UART_LCR_RX_RST;
+
+       /* set the parity, stop bits and data size */
+       serial_out(sport, IP3106_LCR, lcr_fcr);
+
+       /* set the baud rate */
+       quot -= 1;
+       serial_out(sport, IP3106_BAUD, quot);
+
+       serial_out(sport, IP3106_ICLR, -1);
+
+       serial_out(sport, IP3106_IEN, old_ien);
+
+       if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
+               ip3106_enable_ms(&sport->port);
+
+       spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
+static const char *ip3106_type(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+
+       return sport->port.type == PORT_IP3106 ? "IP3106" : NULL;
+}
+
+/*
+ * Release the memory region(s) being used by 'port'.
+ */
+static void ip3106_release_port(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+
+       release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
+}
+
+/*
+ * Request the memory region(s) being used by 'port'.
+ */
+static int ip3106_request_port(struct uart_port *port)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+
+       return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
+                       "ip3106-uart") != NULL ? 0 : -EBUSY;
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void ip3106_config_port(struct uart_port *port, int flags)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+
+       if (flags & UART_CONFIG_TYPE &&
+           ip3106_request_port(&sport->port) == 0)
+               sport->port.type = PORT_IP3106;
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ * The only change we allow are to the flags and type, and
+ * even then only between PORT_IP3106 and PORT_UNKNOWN
+ */
+static int
+ip3106_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       struct ip3106_port *sport = (struct ip3106_port *)port;
+       int ret = 0;
+
+       if (ser->type != PORT_UNKNOWN && ser->type != PORT_IP3106)
+               ret = -EINVAL;
+       if (sport->port.irq != ser->irq)
+               ret = -EINVAL;
+       if (ser->io_type != SERIAL_IO_MEM)
+               ret = -EINVAL;
+       if (sport->port.uartclk / 16 != ser->baud_base)
+               ret = -EINVAL;
+       if ((void *)sport->port.mapbase != ser->iomem_base)
+               ret = -EINVAL;
+       if (sport->port.iobase != ser->port)
+               ret = -EINVAL;
+       if (ser->hub6 != 0)
+               ret = -EINVAL;
+       return ret;
+}
+
+struct uart_ops ip3106_pops = {
+       .tx_empty       = ip3106_tx_empty,
+       .set_mctrl      = ip3106_set_mctrl,
+       .get_mctrl      = ip3106_get_mctrl,
+       .stop_tx        = ip3106_stop_tx,
+       .start_tx       = ip3106_start_tx,
+       .stop_rx        = ip3106_stop_rx,
+       .enable_ms      = ip3106_enable_ms,
+       .break_ctl      = ip3106_break_ctl,
+       .startup        = ip3106_startup,
+       .shutdown       = ip3106_shutdown,
+       .set_termios    = ip3106_set_termios,
+       .type           = ip3106_type,
+       .release_port   = ip3106_release_port,
+       .request_port   = ip3106_request_port,
+       .config_port    = ip3106_config_port,
+       .verify_port    = ip3106_verify_port,
+};
+
+
+/*
+ * Setup the IP3106 serial ports.
+ *
+ * Note also that we support "console=ttySx" where "x" is either 0 or 1.
+ */
+static void __init ip3106_init_ports(void)
+{
+       static int first = 1;
+       int i;
+
+       if (!first)
+               return;
+       first = 0;
+
+       for (i = 0; i < NR_PORTS; i++) {
+               init_timer(&ip3106_ports[i].timer);
+               ip3106_ports[i].timer.function = ip3106_timeout;
+               ip3106_ports[i].timer.data     = (unsigned 
long)&ip3106_ports[i];
+       }
+}
+
+#ifdef CONFIG_SERIAL_IP3106_CONSOLE
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void
+ip3106_console_write(struct console *co, const char *s, unsigned int count)
+{
+       struct ip3106_port *sport = &ip3106_ports[co->index];
+       unsigned int old_ien, status, i;
+
+       /*
+        *      First, save IEN and then disable interrupts
+        */
+       old_ien = serial_in(sport, IP3106_IEN);
+       serial_out(sport, IP3106_IEN, old_ien & ~(IP3106_UART_INT_ALLTX |
+                                       IP3106_UART_INT_ALLRX));
+
+       /*
+        *      Now, do each character
+        */
+       for (i = 0; i < count; i++) {
+               do {
+                       /* Wait for UART_TX register to empty */
+                       status = serial_in(sport, IP3106_FIFO);
+               } while (status & IP3106_UART_FIFO_TXFIFO);
+               serial_out(sport, IP3106_FIFO, s[i]);
+               if (s[i] == '\n') {
+                       do {
+                               status = serial_in(sport, IP3106_FIFO);
+                       } while (status & IP3106_UART_FIFO_TXFIFO);
+                       serial_out(sport, IP3106_FIFO, '\r');
+               }
+       }
+
+       /*
+        *      Finally, wait for transmitter to become empty
+        *      and restore IEN
+        */
+       do {
+               /* Wait for UART_TX register to empty */
+               status = serial_in(sport, IP3106_FIFO);
+       } while (status & IP3106_UART_FIFO_TXFIFO);
+
+       /* Clear TX and EMPTY interrupt */
+       serial_out(sport, IP3106_ICLR, IP3106_UART_INT_TX |
+                            IP3106_UART_INT_EMPTY);
+
+       serial_out(sport, IP3106_IEN, old_ien);
+}
+
+static int __init
+ip3106_console_setup(struct console *co, char *options)
+{
+       struct ip3106_port *sport;
+       int baud = 38400;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       /*
+        * Check whether an invalid uart number has been specified, and
+        * if so, search for the first available port that does have
+        * console support.
+        */
+       if (co->index == -1 || co->index >= NR_PORTS)
+               co->index = 0;
+       sport = &ip3106_ports[co->index];
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+       return uart_set_options(&sport->port, co, baud, parity, bits, flow);
+}
+
+extern struct uart_driver ip3106_reg;
+static struct console ip3106_console = {
+       .name           = "ttyS",
+       .write          = ip3106_console_write,
+       .device         = uart_console_device,
+       .setup          = ip3106_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+       .data           = &ip3106_reg,
+};
+
+static int __init ip3106_rs_console_init(void)
+{
+       ip3106_init_ports();
+       register_console(&ip3106_console);
+       return 0;
+}
+console_initcall(ip3106_rs_console_init);
+
+#define IP3106_CONSOLE &ip3106_console
+#else
+#define IP3106_CONSOLE NULL
+#endif
+
+static struct uart_driver ip3106_reg = {
+       .owner                  = THIS_MODULE,
+       .driver_name            = "ttyS",
+       .dev_name               = "ttyS",
+       .devfs_name             = "tts/",
+       .major                  = SERIAL_IP3106_MAJOR,
+       .minor                  = MINOR_START,
+       .nr                     = NR_PORTS,
+       .cons                   = IP3106_CONSOLE,
+};
+
+static int ip3106_serial_suspend(struct device *_dev, u32 state, u32 level)
+{
+       struct ip3106_port *sport = dev_get_drvdata(_dev);
+
+       if (sport && level == SUSPEND_DISABLE)
+               uart_suspend_port(&ip3106_reg, &sport->port);
+
+       return 0;
+}
+
+static int ip3106_serial_resume(struct device *_dev, u32 level)
+{
+       struct ip3106_port *sport = dev_get_drvdata(_dev);
+
+       if (sport && level == RESUME_ENABLE)
+               uart_resume_port(&ip3106_reg, &sport->port);
+
+       return 0;
+}
+
+static int ip3106_serial_probe(struct device *_dev)
+{
+       struct platform_device *dev = to_platform_device(_dev);
+       struct resource *res = dev->resource;
+       int i;
+
+       for (i = 0; i < dev->num_resources; i++, res++) {
+               if (!(res->flags & IORESOURCE_MEM))
+                       continue;
+
+               for (i = 0; i < NR_PORTS; i++) {
+                       if (ip3106_ports[i].port.mapbase != res->start)
+                               continue;
+
+                       ip3106_ports[i].port.dev = _dev;
+                       uart_add_one_port(&ip3106_reg, &ip3106_ports[i].port);
+                       dev_set_drvdata(_dev, &ip3106_ports[i]);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int ip3106_serial_remove(struct device *_dev)
+{
+       struct ip3106_port *sport = dev_get_drvdata(_dev);
+
+       dev_set_drvdata(_dev, NULL);
+
+       if (sport)
+               uart_remove_one_port(&ip3106_reg, &sport->port);
+
+       return 0;
+}
+
+static struct device_driver ip3106_serial_driver = {
+       .name           = "ip3106-uart",
+       .bus            = &platform_bus_type,
+       .probe          = ip3106_serial_probe,
+       .remove         = ip3106_serial_remove,
+       .suspend        = ip3106_serial_suspend,
+       .resume         = ip3106_serial_resume,
+};
+
+static int __init ip3106_serial_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "Serial: IP3106 driver $Revision: 1.1 $\n");
+
+       ip3106_init_ports();
+
+       ret = uart_register_driver(&ip3106_reg);
+       if (ret == 0) {
+               ret = driver_register(&ip3106_serial_driver);
+               if (ret)
+                       uart_unregister_driver(&ip3106_reg);
+       }
+       return ret;
+}
+
+static void __exit ip3106_serial_exit(void)
+{
+       driver_unregister(&ip3106_serial_driver);
+       uart_unregister_driver(&ip3106_reg);
+}
+
+module_init(ip3106_serial_init);
+module_exit(ip3106_serial_exit);
+
+MODULE_AUTHOR("Embedded Alley Solutions, Inc.");
+MODULE_DESCRIPTION("IP3106 generic serial port driver $Revision: 1.1 $");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_IP3106_MAJOR);
diff -urN linux/drivers/serial/Kconfig linux/drivers/serial/Kconfig
--- linux/drivers/serial/Kconfig        2005/08/01 18:24:37     1.46
+++ linux/drivers/serial/Kconfig        2005/08/05 01:14:41     1.47
@@ -608,21 +608,24 @@
          If you have an Alchemy AU1X00 processor (MIPS based) and you want
          to use a console on a serial port, say Y.  Otherwise, say N.
 
-config SERIAL_PNX8550
-       bool "Enable PNX8550 UART Support"
-       depends on MIPS && SOC_PNX8550
+config SERIAL_IP3106
+       bool "Enable IP3106 UART Support (Philips PNX 8xx0 SoCs)"
+       depends on MIPS && (SOC_PNX8550 || SOC_PNX8330)
        select SERIAL_CORE
        help
-         If you have an Philips PNX8550 processor (MIPS based) and you want
-         to use serial ports, say Y.  Otherwise, say N.
-
-config SERIAL_PNX8550_CONSOLE
-       bool "Enable PNX8550 serial console"
-       depends on SERIAL_PNX8550
+         If you have a Philips SoC with an IP 3106 UART in it, such as
+         the PNX8550 or PNX8330 (MIPS based) and you want to use
+         serial ports, say Y.  Otherwise, say N.
+
+config SERIAL_IP3106_CONSOLE
+       bool "Enable PNX8XX0 serial console"
+       depends on SERIAL_IP3106
        select SERIAL_CORE_CONSOLE
        help
-         If you have an Philips PNX8550 processor (MIPS based) and you want
-         to use a console on a serial port, say Y.  Otherwise, say N.
+         If you have a Philips SoC with an IP 3106 UART in it, such as
+         the PNX8550 or PNX8330 (MIPS based) and you want to use
+         a serial console, say Y.
+         Otherwise, say N.
 
 config SERIAL_CORE
        tristate
diff -urN linux/drivers/serial/Makefile linux/drivers/serial/Makefile
--- linux/drivers/serial/Makefile       2005/08/01 18:24:37     1.37
+++ linux/drivers/serial/Makefile       2005/08/05 01:14:41     1.38
@@ -42,7 +42,7 @@
 obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
 obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
 obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o
-obj-$(CONFIG_SERIAL_PNX8550) += pnx8550_uart.o
+obj-$(CONFIG_SERIAL_IP3106) += ip3106_uart.o
 obj-$(CONFIG_SERIAL_DZ) += dz.o
 obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
 obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o
diff -urN linux/drivers/serial/pnx8550_uart.c 
linux/drivers/serial/pnx8550_uart.c
--- linux/drivers/serial/Attic/pnx8550_uart.c   2005-08-05 02:14:41.630739000 
+0100     1.1
+++ linux/drivers/serial/Attic/pnx8550_uart.c   1970/01/01 00:00:00+0100
@@ -1,993 +0,0 @@
-/*
- * Initially based on linux-2.4.20_mvl31-pnx8550/drivers/char/serial_pnx8550.c
- * Complete rewrite to drivers/serial/pnx8550_uart.c by 
- * Embedded Alley Solutions, source@embeddedalley.com.
- */
-/*
- *  drivers/char/serial_pnx8550.c
- *
- *  Author: Per Hallsmark per.hallsmark@mvista.com
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *  
- *  Serial driver for PNX8550
- */
-
-/*
- *  linux/drivers/serial/pnx8550_uart.c
- *
- *  Driver for PNX8550 serial ports
- *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- *  Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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: pnx8550_uart.c,v 1.1 2005/07/14 17:47:59 ppopov Exp $
- *
- */
-#include <linux/config.h>
-
-#if defined(CONFIG_SERIAL_PNX8550_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/mach-pnx8550/uart.h>
-
-/* We've been assigned a range on the "Low-density serial ports" major */
-#define SERIAL_PNX8550_MAJOR   204
-#define MINOR_START            5
-
-#define NR_PORTS               2
-
-#define PNX8550_ISR_PASS_LIMIT 256
-
-/*
- * Convert from ignore_status_mask or read_status_mask to FIFO
- * and interrupt status bits
- */
-#define SM_TO_FIFO(x)  ((x) >> 10)
-#define SM_TO_ISTAT(x) ((x) & 0x000001ff)
-#define FIFO_TO_SM(x)  ((x) << 10)
-#define ISTAT_TO_SM(x) ((x) & 0x000001ff)
-
-/*
- * This is the size of our serial port register set.
- */
-#define UART_PORT_SIZE 0x1000
-
-/*
- * This determines how often we check the modem status signals
- * for any change.  They generally aren't connected to an IRQ
- * so we have to poll them.  We also check immediately before
- * filling the TX fifo incase CTS has been dropped.
- */
-#define MCTRL_TIMEOUT  (250*HZ/1000)
-
-struct pnx8550_port {
-       struct uart_port        port;
-       struct timer_list       timer;
-       unsigned int            old_status;
-};
-
-/*
- * Handle any change of modem status signal since we were last called.
- */
-static void pnx8550_mctrl_check(struct pnx8550_port *sport)
-{
-       unsigned int status, changed;
-
-       status = sport->port.ops->get_mctrl(&sport->port);
-       changed = status ^ sport->old_status;
-
-       if (changed == 0)
-               return;
-
-       sport->old_status = status;
-
-       if (changed & TIOCM_RI)
-               sport->port.icount.rng++;
-       if (changed & TIOCM_DSR)
-               sport->port.icount.dsr++;
-       if (changed & TIOCM_CAR)
-               uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
-       if (changed & TIOCM_CTS)
-               uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
-
-       wake_up_interruptible(&sport->port.info->delta_msr_wait);
-}
-
-/*
- * This is our per-port timeout handler, for checking the
- * modem status signals.
- */
-static void pnx8550_timeout(unsigned long data)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)data;
-       unsigned long flags;
-
-       if (sport->port.info) {
-               spin_lock_irqsave(&sport->port.lock, flags);
-               pnx8550_mctrl_check(sport);
-               spin_unlock_irqrestore(&sport->port.lock, flags);
-
-               mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
-       }
-}
-
-/*
- * interrupts disabled on entry
- */
-static void pnx8550_stop_tx(struct uart_port *port, unsigned int tty_stop)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       u32 ien;
-
-       /* Disable TX intr */
-       ien = UART_GET_IEN(sport);
-       UART_PUT_IEN(sport, ien & ~PNX8550_UART_INT_ALLTX);
-
-       /* Clear all pending TX intr */
-       UART_PUT_ICLR(sport, PNX8550_UART_INT_ALLTX);
-
-//     sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS); /* FIXME */
-}
-
-/*
- * interrupts may not be disabled on entry
- */
-static void pnx8550_start_tx(struct uart_port *port, unsigned int tty_start)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       unsigned long flags;
-       u32 ien;
-
-       spin_lock_irqsave(&sport->port.lock, flags);
-
-       /* Clear all pending TX intr */
-       UART_PUT_ICLR(sport, PNX8550_UART_INT_ALLTX);
-
-       /* Enable TX intr */
-       ien = UART_GET_IEN(sport);
-       UART_PUT_IEN(sport, ien | PNX8550_UART_INT_ALLTX);
-
-//     sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); /* FIXME */
-
-       spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-/*
- * Interrupts enabled
- */
-static void pnx8550_stop_rx(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       u32 ien;
-
-       /* Disable RX intr */
-       ien = UART_GET_IEN(sport);
-       UART_PUT_IEN(sport, ien & ~PNX8550_UART_INT_ALLRX);
-
-       /* Clear all pending RX intr */
-       UART_PUT_ICLR(sport, PNX8550_UART_INT_ALLRX);
-}
-
-/*
- * Set the modem control timer to fire immediately.
- */
-static void pnx8550_enable_ms(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-
-       mod_timer(&sport->timer, jiffies);
-}
-
-static void
-pnx8550_rx_chars(struct pnx8550_port *sport, struct pt_regs *regs)
-{
-       struct tty_struct *tty = sport->port.info->tty;
-       unsigned int status, ch, flg, ignored = 0;
-
-       status = FIFO_TO_SM(UART_GET_FIFO(sport)) |
-                ISTAT_TO_SM(UART_GET_ISTAT(sport));
-       while (status & FIFO_TO_SM(PNX8550_UART_FIFO_RXFIFO)) {
-               ch = UART_GET_FIFO(sport);
-
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                       goto ignore_char;
-               sport->port.icount.rx++;
-
-               flg = TTY_NORMAL;
-
-               /*
-                * note that the error handling code is
-                * out of the main execution path
-                */
-               if (status & FIFO_TO_SM(PNX8550_UART_FIFO_RXFE |
-                                       PNX8550_UART_FIFO_RXPAR))
-                       goto handle_error;
-
-               if (uart_handle_sysrq_char(&sport->port, ch, regs))
-                       goto ignore_char;
-
-       error_return:
-               tty_insert_flip_char(tty, ch, flg);
-       ignore_char:
-               UART_PUT_LCR(sport, UART_GET_LCR(sport) |
-                                   PNX8550_UART_LCR_RX_NEXT);
-               status = FIFO_TO_SM(UART_GET_FIFO(sport)) |
-                        ISTAT_TO_SM(UART_GET_ISTAT(sport));
-       }
- out:
-       tty_flip_buffer_push(tty);
-       return;
-
- handle_error:
-       if (status & FIFO_TO_SM(PNX8550_UART_FIFO_RXPAR))
-               sport->port.icount.parity++;
-       else if (status & FIFO_TO_SM(PNX8550_UART_FIFO_RXFE))
-               sport->port.icount.frame++;
-       if (status & ISTAT_TO_SM(PNX8550_UART_INT_RXOVRN))
-               sport->port.icount.overrun++;
-
-       if (status & sport->port.ignore_status_mask) {
-               if (++ignored > 100)
-                       goto out;
-               goto ignore_char;
-       }
-
-//     status &= sport->port.read_status_mask;
-
-       if (status & FIFO_TO_SM(PNX8550_UART_FIFO_RXPAR))
-               flg = TTY_PARITY;
-       else if (status & FIFO_TO_SM(PNX8550_UART_FIFO_RXFE))
-               flg = TTY_FRAME;
-
-       if (status & ISTAT_TO_SM(PNX8550_UART_INT_RXOVRN)) {
-               /*
-                * overrun does *not* affect the character
-                * we read from the FIFO
-                */
-               tty_insert_flip_char(tty, ch, flg);
-               ch = 0;
-               flg = TTY_OVERRUN;
-       }
-#ifdef SUPPORT_SYSRQ
-       sport->port.sysrq = 0;
-#endif
-       goto error_return;
-}
-
-static void pnx8550_tx_chars(struct pnx8550_port *sport)
-{
-       struct circ_buf *xmit = &sport->port.info->xmit;
-
-       if (sport->port.x_char) {
-               UART_PUT_FIFO(sport, sport->port.x_char);
-               sport->port.icount.tx++;
-               sport->port.x_char = 0;
-               return;
-       }
-
-       /*
-        * Check the modem control lines before
-        * transmitting anything.
-        */
-       pnx8550_mctrl_check(sport);
-
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
-               pnx8550_stop_tx(&sport->port, 0);
-               return;
-       }
-
-       /*
-        * TX while bytes available
-        */
-       while (((UART_GET_FIFO(sport) & PNX8550_UART_FIFO_TXFIFO) >> 16) < 16) {
-               UART_PUT_FIFO(sport, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               sport->port.icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       }
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&sport->port);
-
-       if (uart_circ_empty(xmit))
-               pnx8550_stop_tx(&sport->port, 0);
-}
-
-static irqreturn_t pnx8550_int(int irq, void *dev_id, struct pt_regs *regs)
-{
-       struct pnx8550_port *sport = dev_id;
-       unsigned int status;
-
-       spin_lock(&sport->port.lock);
-#if    0       /* FIXME */
-       status = UART_GET_UTSR0(sport);
-       status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS;
-       do {
-               if (status & (UTSR0_RFS | UTSR0_RID)) {
-                       /* Clear the receiver idle bit, if set */
-                       if (status & UTSR0_RID)
-                               UART_PUT_UTSR0(sport, UTSR0_RID);
-                       pnx8550_rx_chars(sport, regs);
-               }
-
-               /* Clear the relevant break bits */
-               if (status & (UTSR0_RBB | UTSR0_REB))
-                       UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB));
-
-               if (status & UTSR0_RBB)
-                       sport->port.icount.brk++;
-
-               if (status & UTSR0_REB)
-                       uart_handle_break(&sport->port);
-
-               if (status & UTSR0_TFS)
-                       pnx8550_tx_chars(sport);
-               if (pass_counter++ > PNX8550_ISR_PASS_LIMIT)
-                       break;
-               status = UART_GET_UTSR0(sport);
-               status &= SM_TO_UTSR0(sport->port.read_status_mask) |
-                         ~UTSR0_TFS;
-       } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
-#else
-       /* Get the interrupts */
-       status  = UART_GET_ISTAT(sport) & UART_GET_IEN(sport);
-
-       /* RX Receiver Holding Register Overrun */
-       if (status & PNX8550_UART_INT_RXOVRN) {
-               sport->port.icount.overrun++;
-               UART_PUT_ICLR(sport, PNX8550_UART_INT_RXOVRN);
-       }
-
-       /* RX Frame Error */
-       if (status & PNX8550_UART_INT_FRERR) {
-               sport->port.icount.frame++;
-               UART_PUT_ICLR(sport, PNX8550_UART_INT_FRERR);
-       }
-
-       /* Break signal received */
-       if (status & PNX8550_UART_INT_BREAK) {
-               sport->port.icount.brk++;
-               UART_PUT_ICLR(sport, PNX8550_UART_INT_BREAK);
-       }
-
-       /* RX Parity Error */
-       if (status & PNX8550_UART_INT_PARITY) {
-               sport->port.icount.parity++;
-               UART_PUT_ICLR(sport, PNX8550_UART_INT_PARITY);
-       }
-
-       /* Byte received */
-       if (status & PNX8550_UART_INT_RX) {
-               pnx8550_rx_chars(sport, regs);
-               UART_PUT_ICLR(sport, PNX8550_UART_INT_RX);
-       }
-
-       /* TX holding register empty - transmit a byte */
-       if (status & PNX8550_UART_INT_TX) {
-               pnx8550_tx_chars(sport);
-               UART_PUT_ICLR(sport, PNX8550_UART_INT_TX);
-       }
-
-       /* TX shift register and holding register empty  */
-       if (status & PNX8550_UART_INT_EMPTY) {
-               UART_PUT_ICLR(sport, PNX8550_UART_INT_EMPTY);
-       }
-
-       /* Receiver time out */
-       if (status & PNX8550_UART_INT_RCVTO) {
-               UART_PUT_ICLR(sport, PNX8550_UART_INT_RCVTO);
-       }
-#endif
-       spin_unlock(&sport->port.lock);
-       return IRQ_HANDLED;
-}
-
-/*
- * Return TIOCSER_TEMT when transmitter is not busy.
- */
-static unsigned int pnx8550_tx_empty(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-
-       return UART_GET_FIFO(sport) & PNX8550_UART_FIFO_TXFIFO_STA ? 0 : 
TIOCSER_TEMT;
-}
-
-static unsigned int pnx8550_get_mctrl(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       unsigned int mctrl = TIOCM_DSR;
-       unsigned int msr;
-
-       /* REVISIT */
-
-       msr = UART_GET_MCR(sport);
-
-       mctrl |= msr & PNX8550_UART_MCR_CTS ? TIOCM_CTS : 0;
-       mctrl |= msr & PNX8550_UART_MCR_DCD ? TIOCM_CAR : 0;
-
-       return mctrl;
-}
-
-static void pnx8550_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-#if    0       /* FIXME */
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       unsigned int msr;
-#endif
-}
-
-/*
- * Interrupts always disabled.
- */
-static void pnx8550_break_ctl(struct uart_port *port, int break_state)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       unsigned long flags;
-       unsigned int lcr;
-
-       spin_lock_irqsave(&sport->port.lock, flags);
-       lcr = UART_GET_LCR(sport);
-       if (break_state == -1)
-               lcr |= PNX8550_UART_LCR_TXBREAK;
-       else
-               lcr &= ~PNX8550_UART_LCR_TXBREAK;
-       UART_PUT_LCR(sport, lcr);
-       spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-static int pnx8550_startup(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       int retval;
-
-       /*
-        * Allocate the IRQ
-        */
-       retval = request_irq(sport->port.irq, pnx8550_int, 0,
-                            "pnx8550-uart", sport);
-       if (retval)
-               return retval;
-
-       /*
-        * Finally, clear and enable interrupts
-        */
-
-       UART_PUT_ICLR(sport, PNX8550_UART_INT_ALLRX |
-                            PNX8550_UART_INT_ALLTX);
-
-       UART_PUT_IEN(sport, UART_GET_IEN(sport) |
-                           PNX8550_UART_INT_ALLRX |
-                           PNX8550_UART_INT_ALLTX);
-
-       /*
-        * Enable modem status interrupts
-        */
-       spin_lock_irq(&sport->port.lock);
-       pnx8550_enable_ms(&sport->port);
-       spin_unlock_irq(&sport->port.lock);
-
-       return 0;
-}
-
-static void pnx8550_shutdown(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-
-       /*
-        * Stop our timer.
-        */
-       del_timer_sync(&sport->timer);
-
-       /*
-        * Disable all interrupts, port and break condition.
-        */
-       UART_PUT_IEN(sport, 0);
-
-       /*
-        * Reset the Tx and Rx FIFOS
-        */
-       UART_PUT_LCR(sport, UART_GET_LCR(sport) |
-                           PNX8550_UART_LCR_TX_RST |
-                           PNX8550_UART_LCR_RX_RST);
-
-       /*
-        * Clear all interrupts
-        */
-       UART_PUT_ICLR(sport, PNX8550_UART_INT_ALLRX |
-                            PNX8550_UART_INT_ALLTX);
-
-       /*
-        * Free the interrupt
-        */
-       free_irq(sport->port.irq, sport);
-}
-
-static void
-pnx8550_set_termios(struct uart_port *port, struct termios *termios,
-                  struct termios *old)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       unsigned long flags;
-       unsigned int lcr_fcr, old_ien, baud, quot;
-       unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
-
-       /*
-        * We only support CS7 and CS8.
-        */
-       while ((termios->c_cflag & CSIZE) != CS7 &&
-              (termios->c_cflag & CSIZE) != CS8) {
-               termios->c_cflag &= ~CSIZE;
-               termios->c_cflag |= old_csize;
-               old_csize = CS8;
-       }
-
-       if ((termios->c_cflag & CSIZE) == CS8)
-               lcr_fcr = PNX8550_UART_LCR_8BIT;
-       else
-               lcr_fcr = 0;
-
-       if (termios->c_cflag & CSTOPB)
-               lcr_fcr |= PNX8550_UART_LCR_2STOPB;
-       if (termios->c_cflag & PARENB) {
-               lcr_fcr |= PNX8550_UART_LCR_PAREN;
-               if (!(termios->c_cflag & PARODD))
-                       lcr_fcr |= PNX8550_UART_LCR_PAREVN;
-       }
-
-       /*
-        * 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);
-
-       spin_lock_irqsave(&sport->port.lock, flags);
-
-#if    0       /* REVISIT */
-       sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
-       sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
-       if (termios->c_iflag & INPCK)
-               sport->port.read_status_mask |=
-                               UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
-       if (termios->c_iflag & (BRKINT | PARMRK))
-               sport->port.read_status_mask |=
-                               UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
-
-       /*
-        * Characters to ignore
-        */
-       sport->port.ignore_status_mask = 0;
-       if (termios->c_iflag & IGNPAR)
-               sport->port.ignore_status_mask |=
-                               UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
-       if (termios->c_iflag & IGNBRK) {
-               sport->port.ignore_status_mask |=
-                               UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
-               /*
-                * If we're ignoring parity and break indicators,
-                * ignore overruns too (for real raw support).
-                */
-               if (termios->c_iflag & IGNPAR)
-                       sport->port.ignore_status_mask |=
-                               UTSR1_TO_SM(UTSR1_ROR);
-       }
-#endif
-
-       del_timer_sync(&sport->timer);
-
-       /*
-        * Update the per-port timeout.
-        */
-       uart_update_timeout(port, termios->c_cflag, baud);
-
-       /*
-        * disable interrupts and drain transmitter
-        */
-       old_ien = UART_GET_IEN(sport);
-       UART_PUT_IEN(sport, old_ien & ~(PNX8550_UART_INT_ALLTX |
-                                       PNX8550_UART_INT_ALLRX));
-
-       while (UART_GET_FIFO(sport) & PNX8550_UART_FIFO_TXFIFO_STA)
-               barrier();
-
-       /* then, disable everything */
-       UART_PUT_IEN(sport, 0);
-
-       /* Reset the Rx and Tx FIFOs too */
-       lcr_fcr |= PNX8550_UART_LCR_TX_RST;
-       lcr_fcr |= PNX8550_UART_LCR_RX_RST;
-
-       /* set the parity, stop bits and data size */
-       UART_PUT_LCR(sport, lcr_fcr);
-
-       /* set the baud rate */
-       quot -= 1;
-       UART_PUT_BAUD(sport, quot);
-
-       UART_PUT_ICLR(sport, -1);
-
-       UART_PUT_IEN(sport, old_ien);
-
-       if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
-               pnx8550_enable_ms(&sport->port);
-
-       spin_unlock_irqrestore(&sport->port.lock, flags);
-}
-
-static const char *pnx8550_type(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-
-       return sport->port.type == PORT_PNX8550 ? "PNX8550" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'.
- */
-static void pnx8550_release_port(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-
-       release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
-}
-
-/*
- * Request the memory region(s) being used by 'port'.
- */
-static int pnx8550_request_port(struct uart_port *port)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-
-       return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
-                       "pnx8550-uart") != NULL ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void pnx8550_config_port(struct uart_port *port, int flags)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-
-       if (flags & UART_CONFIG_TYPE &&
-           pnx8550_request_port(&sport->port) == 0)
-               sport->port.type = PORT_PNX8550;
-}
-
-/*
- * Verify the new serial_struct (for TIOCSSERIAL).
- * The only change we allow are to the flags and type, and
- * even then only between PORT_PNX8550 and PORT_UNKNOWN
- */
-static int
-pnx8550_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-       struct pnx8550_port *sport = (struct pnx8550_port *)port;
-       int ret = 0;
-
-       if (ser->type != PORT_UNKNOWN && ser->type != PORT_PNX8550)
-               ret = -EINVAL;
-       if (sport->port.irq != ser->irq)
-               ret = -EINVAL;
-       if (ser->io_type != SERIAL_IO_MEM)
-               ret = -EINVAL;
-       if (sport->port.uartclk / 16 != ser->baud_base)
-               ret = -EINVAL;
-       if ((void *)sport->port.mapbase != ser->iomem_base)
-               ret = -EINVAL;
-       if (sport->port.iobase != ser->port)
-               ret = -EINVAL;
-       if (ser->hub6 != 0)
-               ret = -EINVAL;
-       return ret;
-}
-
-static struct uart_ops pnx8550_pops = {
-       .tx_empty       = pnx8550_tx_empty,
-       .set_mctrl      = pnx8550_set_mctrl,
-       .get_mctrl      = pnx8550_get_mctrl,
-       .stop_tx        = pnx8550_stop_tx,
-       .start_tx       = pnx8550_start_tx,
-       .stop_rx        = pnx8550_stop_rx,
-       .enable_ms      = pnx8550_enable_ms,
-       .break_ctl      = pnx8550_break_ctl,
-       .startup        = pnx8550_startup,
-       .shutdown       = pnx8550_shutdown,
-       .set_termios    = pnx8550_set_termios,
-       .type           = pnx8550_type,
-       .release_port   = pnx8550_release_port,
-       .request_port   = pnx8550_request_port,
-       .config_port    = pnx8550_config_port,
-       .verify_port    = pnx8550_verify_port,
-};
-
-static struct pnx8550_port pnx8550_ports[NR_PORTS] = {
-       [0] = {
-               .port   = {
-                       .type           = PORT_PNX8550,
-                       .iotype         = SERIAL_IO_MEM,
-                       .membase        = (void __iomem *)PNX8550_UART_PORT0,
-                       .mapbase        = PNX8550_UART_PORT0,
-                       .irq            = PNX8550_UART_INT(0),
-                       .uartclk        = 3692300,
-                       .fifosize       = 16,
-                       .ops            = &pnx8550_pops,
-                       .flags          = ASYNC_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-       },
-       [1] = {
-               .port   = {
-                       .type           = PORT_PNX8550,
-                       .iotype         = SERIAL_IO_MEM,
-                       .membase        = (void __iomem *)PNX8550_UART_PORT1,
-                       .mapbase        = PNX8550_UART_PORT1,
-                       .irq            = PNX8550_UART_INT(1),
-                       .uartclk        = 3692300,
-                       .fifosize       = 16,
-                       .ops            = &pnx8550_pops,
-                       .flags          = ASYNC_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-       },
-};
-
-/*
- * Setup the PNX8550 serial ports.
- *
- * Note also that we support "console=ttySx" where "x" is either 0 or 1.
- */
-static void __init pnx8550_init_ports(void)
-{
-       static int first = 1;
-       int i;
-
-       if (!first)
-               return;
-       first = 0;
-
-       for (i = 0; i < NR_PORTS; i++) {
-               init_timer(&pnx8550_ports[i].timer);
-               pnx8550_ports[i].timer.function = pnx8550_timeout;
-               pnx8550_ports[i].timer.data     = (unsigned 
long)&pnx8550_ports[i];
-       }
-}
-
-#ifdef CONFIG_SERIAL_PNX8550_CONSOLE
-
-/*
- * Interrupts are disabled on entering
- */
-static void
-pnx8550_console_write(struct console *co, const char *s, unsigned int count)
-{
-       struct pnx8550_port *sport = &pnx8550_ports[co->index];
-       unsigned int old_ien, status, i;
-
-       /*
-        *      First, save IEN and then disable interrupts
-        */
-       old_ien = UART_GET_IEN(sport);
-       UART_PUT_IEN(sport, old_ien & ~(PNX8550_UART_INT_ALLTX |
-                                       PNX8550_UART_INT_ALLRX));
-
-       /*
-        *      Now, do each character
-        */
-       for (i = 0; i < count; i++) {
-               do {
-                       /* Wait for UART_TX register to empty */
-                       status = UART_GET_FIFO(sport);
-               } while (status & PNX8550_UART_FIFO_TXFIFO);
-               UART_PUT_FIFO(sport, s[i]);
-               if (s[i] == '\n') {
-                       do {
-                               status = UART_GET_FIFO(sport);
-                       } while (status & PNX8550_UART_FIFO_TXFIFO);
-                       UART_PUT_FIFO(sport, '\r');
-               }
-       }
-
-       /*
-        *      Finally, wait for transmitter to become empty
-        *      and restore IEN
-        */
-       do {
-               /* Wait for UART_TX register to empty */
-               status = UART_GET_FIFO(sport);
-       } while (status & PNX8550_UART_FIFO_TXFIFO);
-
-       /* Clear TX and EMPTY interrupt */
-       UART_PUT_ICLR(sport, PNX8550_UART_INT_TX |
-                            PNX8550_UART_INT_EMPTY);
-
-       UART_PUT_IEN(sport, old_ien);
-}
-
-static int __init
-pnx8550_console_setup(struct console *co, char *options)
-{
-       struct pnx8550_port *sport;
-       int baud = 38400;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       /*
-        * Check whether an invalid uart number has been specified, and
-        * if so, search for the first available port that does have
-        * console support.
-        */
-       if (co->index == -1 || co->index >= NR_PORTS)
-               co->index = 0;
-       sport = &pnx8550_ports[co->index];
-
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-       return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-}
-
-extern struct uart_driver pnx8550_reg;
-static struct console pnx8550_console = {
-       .name           = "ttyS",
-       .write          = pnx8550_console_write,
-       .device         = uart_console_device,
-       .setup          = pnx8550_console_setup,
-       .flags          = CON_PRINTBUFFER,
-       .index          = -1,
-       .data           = &pnx8550_reg,
-};
-
-static int __init pnx8550_rs_console_init(void)
-{
-       pnx8550_init_ports();
-       register_console(&pnx8550_console);
-       return 0;
-}
-console_initcall(pnx8550_rs_console_init);
-
-#define PNX8550_CONSOLE        &pnx8550_console
-#else
-#define PNX8550_CONSOLE        NULL
-#endif
-
-static struct uart_driver pnx8550_reg = {
-       .owner                  = THIS_MODULE,
-       .driver_name            = "ttyS",
-       .dev_name               = "ttyS",
-       .devfs_name             = "tts/",
-       .major                  = SERIAL_PNX8550_MAJOR,
-       .minor                  = MINOR_START,
-       .nr                     = NR_PORTS,
-       .cons                   = PNX8550_CONSOLE,
-};
-
-static int pnx8550_serial_suspend(struct device *_dev, u32 state, u32 level)
-{
-       struct pnx8550_port *sport = dev_get_drvdata(_dev);
-
-       if (sport && level == SUSPEND_DISABLE)
-               uart_suspend_port(&pnx8550_reg, &sport->port);
-
-       return 0;
-}
-
-static int pnx8550_serial_resume(struct device *_dev, u32 level)
-{
-       struct pnx8550_port *sport = dev_get_drvdata(_dev);
-
-       if (sport && level == RESUME_ENABLE)
-               uart_resume_port(&pnx8550_reg, &sport->port);
-
-       return 0;
-}
-
-static int pnx8550_serial_probe(struct device *_dev)
-{
-       struct platform_device *dev = to_platform_device(_dev);
-       struct resource *res = dev->resource;
-       int i;
-
-       for (i = 0; i < dev->num_resources; i++, res++) {
-               if (!(res->flags & IORESOURCE_MEM))
-                       continue;
-
-               for (i = 0; i < NR_PORTS; i++) {
-                       if (pnx8550_ports[i].port.mapbase != res->start)
-                               continue;
-
-                       pnx8550_ports[i].port.dev = _dev;
-                       uart_add_one_port(&pnx8550_reg, &pnx8550_ports[i].port);
-                       dev_set_drvdata(_dev, &pnx8550_ports[i]);
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-static int pnx8550_serial_remove(struct device *_dev)
-{
-       struct pnx8550_port *sport = dev_get_drvdata(_dev);
-
-       dev_set_drvdata(_dev, NULL);
-
-       if (sport)
-               uart_remove_one_port(&pnx8550_reg, &sport->port);
-
-       return 0;
-}
-
-static struct device_driver pnx8550_serial_driver = {
-       .name           = "pnx8550-uart",
-       .bus            = &platform_bus_type,
-       .probe          = pnx8550_serial_probe,
-       .remove         = pnx8550_serial_remove,
-       .suspend        = pnx8550_serial_suspend,
-       .resume         = pnx8550_serial_resume,
-};
-
-static int __init pnx8550_serial_init(void)
-{
-       int ret;
-
-       printk(KERN_INFO "Serial: PNX8550 driver $Revision: 1.1 $\n");
-
-       pnx8550_init_ports();
-
-       ret = uart_register_driver(&pnx8550_reg);
-       if (ret == 0) {
-               ret = driver_register(&pnx8550_serial_driver);
-               if (ret)
-                       uart_unregister_driver(&pnx8550_reg);
-       }
-       return ret;
-}
-
-static void __exit pnx8550_serial_exit(void)
-{
-       driver_unregister(&pnx8550_serial_driver);
-       uart_unregister_driver(&pnx8550_reg);
-}
-
-module_init(pnx8550_serial_init);
-module_exit(pnx8550_serial_exit);
-
-MODULE_AUTHOR("Embedded Alley Solutions, Inc.");
-MODULE_DESCRIPTION("PNX8550 generic serial port driver $Revision: 1.1 $");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_PNX8550_MAJOR);
diff -urN linux/include/asm-mips/mach-pnx8550/uart.h 
linux/include/asm-mips/mach-pnx8550/uart.h
--- linux/include/asm-mips/mach-pnx8550/uart.h  2005/07/14 17:47:59     1.1
+++ linux/include/asm-mips/mach-pnx8550/uart.h  2005/08/05 01:14:41     1.2
@@ -1,86 +1,26 @@
-#ifndef __PNX8550_UART_H
-#define __PNX8550_UART_H
+#ifndef __IP3106_UART_H
+#define __IP3106_UART_H
 
-#include <asm/mach-pnx8550/int.h>
+#include <int.h>
 
-#define PNX8550_CONSOLE_PORT 1
-#define PNX8550_SERIAL_PORT 0
+/* early macros for kgdb use. fixme: clean this up */
 
-#define PNX8550_UART_BASE      0xbbe4a000
-
-#define PNX8550_UART_PORT0     (PNX8550_UART_BASE)
-#define PNX8550_UART_PORT1     (PNX8550_UART_BASE + 0x1000)
-
-#define PNX8550_UART_LCR(x)    *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0x000)
-#define PNX8550_UART_MCR(x)    *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0x004)
-#define PNX8550_UART_BAUD(x)   *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0x008)
-#define PNX8550_UART_CFG(x)    *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0x00C)
-#define PNX8550_UART_FIFO(x)   *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0x028)
-#define PNX8550_UART_ISTAT(x)  *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0xFE0)
-#define PNX8550_UART_IEN(x)    *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0xFE4)
-#define PNX8550_UART_ICLR(x)   *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0xFE8)
-#define PNX8550_UART_ISET(x)   *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0xFEC)
-#define PNX8550_UART_PD(x)     *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0xFF4)
-#define PNX8550_UART_MID(x)    *(volatile unsigned long 
*)(PNX8550_UART_BASE+(x*0x1000) + 0xFFC)
-
-#define UART_GET_LCR(sport)    __raw_readl((sport)->port.membase + 0x000)
-#define UART_GET_MCR(sport)    __raw_readl((sport)->port.membase + 0x004)
-#define UART_GET_BAUD(sport)   __raw_readl((sport)->port.membase + 0x008)
-#define UART_GET_CFG(sport)    __raw_readl((sport)->port.membase + 0x00c)
-#define UART_GET_FIFO(sport)   __raw_readl((sport)->port.membase + 0x028)
-#define UART_GET_ISTAT(sport)  __raw_readl((sport)->port.membase + 0xfe0)
-#define UART_GET_IEN(sport)    __raw_readl((sport)->port.membase + 0xfe4)
-#define UART_GET_ICLR(sport)   __raw_readl((sport)->port.membase + 0xfe8)
-#define UART_GET_ISET(sport)   __raw_readl((sport)->port.membase + 0xfec)
-#define UART_GET_PD(sport)     __raw_readl((sport)->port.membase + 0xff4)
-#define UART_GET_MID(sport)    __raw_readl((sport)->port.membase + 0xffc)
-
-#define UART_PUT_LCR(sport,v)  __raw_writel((v),(sport)->port.membase + 0x000)
-#define UART_PUT_MCR(sport,v)  __raw_writel((v),(sport)->port.membase + 0x004)
-#define UART_PUT_BAUD(sport,v) __raw_writel((v),(sport)->port.membase + 0x008)
-#define UART_PUT_CFG(sport,v)  __raw_writel((v),(sport)->port.membase + 0x00c)
-#define UART_PUT_FIFO(sport,v) __raw_writel((v),(sport)->port.membase + 0x028)
-#define UART_PUT_ISTAT(sport,v)        __raw_writel((v),(sport)->port.membase 
+ 0xfe0)
-#define UART_PUT_IEN(sport,v)  __raw_writel((v),(sport)->port.membase + 0xfe4)
-#define UART_PUT_ICLR(sport,v) __raw_writel((v),(sport)->port.membase + 0xfe8)
-#define UART_PUT_ISET(sport,v) __raw_writel((v),(sport)->port.membase + 0xfec)
-#define UART_PUT_PD(sport,v)   __raw_writel((v),(sport)->port.membase + 0xff4)
-#define UART_PUT_MID(sport,v)  __raw_writel((v),(sport)->port.membase + 0xffc)
-
-#define PNX8550_UART_LCR_TXBREAK       (1<<30)
-#define PNX8550_UART_LCR_PAREVN                0x10000000
-#define PNX8550_UART_LCR_PAREN         0x08000000
-#define PNX8550_UART_LCR_2STOPB                0x04000000
-#define PNX8550_UART_LCR_8BIT          0x01000000
-#define PNX8550_UART_LCR_TX_RST                0x00040000
-#define PNX8550_UART_LCR_RX_RST                0x00020000
-#define PNX8550_UART_LCR_RX_NEXT       0x00010000
-
-#define PNX8550_UART_MCR_SCR           0xFF000000
-#define PNX8550_UART_MCR_DCD           0x00800000
-#define PNX8550_UART_MCR_CTS           0x00100000
-#define PNX8550_UART_MCR_LOOP          0x00000010
-#define PNX8550_UART_MCR_RTS           0x00000002
-#define PNX8550_UART_MCR_DTR           0x00000001
-
-#define PNX8550_UART_INT_TX            0x00000080
-#define PNX8550_UART_INT_EMPTY         0x00000040
-#define PNX8550_UART_INT_RCVTO         0x00000020
-#define PNX8550_UART_INT_RX            0x00000010
-#define PNX8550_UART_INT_RXOVRN                0x00000008
-#define PNX8550_UART_INT_FRERR         0x00000004
-#define PNX8550_UART_INT_BREAK         0x00000002
-#define PNX8550_UART_INT_PARITY                0x00000001
-#define PNX8550_UART_INT_ALLRX         0x0000003F
-#define PNX8550_UART_INT_ALLTX         0x000000C0
-
-#define PNX8550_UART_FIFO_TXFIFO       0x001F0000
-#define PNX8550_UART_FIFO_TXFIFO_STA   (0x1f<<16)
-#define PNX8550_UART_FIFO_RXBRK                0x00008000
-#define PNX8550_UART_FIFO_RXFE         0x00004000
-#define PNX8550_UART_FIFO_RXPAR                0x00002000
-#define PNX8550_UART_FIFO_RXFIFO       0x00001F00
-#define PNX8550_UART_FIFO_RBRTHR       0x000000FF
+#define UART_BASE              0xbbe4a000      /* PNX8550 */
+
+#define PNX8550_UART_PORT0     (UART_BASE)
+#define PNX8550_UART_PORT1     (UART_BASE + 0x1000)
+
+#define IP3106_UART_LCR(x)     *(volatile u32 *)(UART_BASE+(x*0x1000) + 0x000)
+#define IP3106_UART_MCR(x)     *(volatile u32 *)(UART_BASE+(x*0x1000) + 0x004)
+#define IP3106_UART_BAUD(x)    *(volatile u32 *)(UART_BASE+(x*0x1000) + 0x008)
+#define IP3106_UART_CFG(x)     *(volatile u32 *)(UART_BASE+(x*0x1000) + 0x00C)
+#define IP3106_UART_FIFO(x)    *(volatile u32 *)(UART_BASE+(x*0x1000) + 0x028)
+#define IP3106_UART_ISTAT(x)   *(volatile u32 *)(UART_BASE+(x*0x1000) + 0xFE0)
+#define IP3106_UART_IEN(x)     *(volatile u32 *)(UART_BASE+(x*0x1000) + 0xFE4)
+#define IP3106_UART_ICLR(x)    *(volatile u32 *)(UART_BASE+(x*0x1000) + 0xFE8)
+#define IP3106_UART_ISET(x)    *(volatile u32 *)(UART_BASE+(x*0x1000) + 0xFEC)
+#define IP3106_UART_PD(x)      *(volatile u32 *)(UART_BASE+(x*0x1000) + 0xFF4)
+#define IP3106_UART_MID(x)     *(volatile u32 *)(UART_BASE+(x*0x1000) + 0xFFC)
 
 #define PNX8550_UART_INT(x)            (PNX8550_INT_GIC_MIN+19+x)
 #define IRQ_TO_UART(x)                 (x-PNX8550_INT_GIC_MIN-19)
diff -urN linux/include/linux/serial_ip3106.h 
linux/include/linux/serial_ip3106.h
--- linux/include/linux/serial_ip3106.h 1970/01/01 00:00:00
+++ linux/include/linux/serial_ip3106.h 2005-08-05 02:14:41.792704000 +0100     
1.1
@@ -0,0 +1,81 @@
+/*
+ * Embedded Alley Solutions, source@embeddedalley.com.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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
+ */
+
+#ifndef _LINUX_SERIAL_IP3106_H
+#define _LINUX_SERIAL_IP3106_H
+
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#define IP3106_NR_PORTS                2
+
+struct ip3106_port {
+       struct uart_port        port;
+       struct timer_list       timer;
+       unsigned int            old_status;
+};
+
+/* register offsets */
+#define IP3106_LCR             0
+#define IP3106_MCR             0x004
+#define IP3106_BAUD            0x008
+#define IP3106_CFG             0x00c
+#define IP3106_FIFO            0x028
+#define IP3106_ISTAT           0xfe0
+#define IP3106_IEN             0xfe4
+#define IP3106_ICLR            0xfe8
+#define IP3106_ISET            0xfec
+#define IP3106_PD              0xff4
+#define IP3106_MID             0xffc
+
+#define IP3106_UART_LCR_TXBREAK                (1<<30)
+#define IP3106_UART_LCR_PAREVN         0x10000000
+#define IP3106_UART_LCR_PAREN          0x08000000
+#define IP3106_UART_LCR_2STOPB         0x04000000
+#define IP3106_UART_LCR_8BIT           0x01000000
+#define IP3106_UART_LCR_TX_RST         0x00040000
+#define IP3106_UART_LCR_RX_RST         0x00020000
+#define IP3106_UART_LCR_RX_NEXT                0x00010000
+
+#define IP3106_UART_MCR_SCR            0xFF000000
+#define IP3106_UART_MCR_DCD            0x00800000
+#define IP3106_UART_MCR_CTS            0x00100000
+#define IP3106_UART_MCR_LOOP           0x00000010
+#define IP3106_UART_MCR_RTS            0x00000002
+#define IP3106_UART_MCR_DTR            0x00000001
+
+#define IP3106_UART_INT_TX             0x00000080
+#define IP3106_UART_INT_EMPTY          0x00000040
+#define IP3106_UART_INT_RCVTO          0x00000020
+#define IP3106_UART_INT_RX             0x00000010
+#define IP3106_UART_INT_RXOVRN         0x00000008
+#define IP3106_UART_INT_FRERR          0x00000004
+#define IP3106_UART_INT_BREAK          0x00000002
+#define IP3106_UART_INT_PARITY         0x00000001
+#define IP3106_UART_INT_ALLRX          0x0000003F
+#define IP3106_UART_INT_ALLTX          0x000000C0
+
+#define IP3106_UART_FIFO_TXFIFO                0x001F0000
+#define IP3106_UART_FIFO_TXFIFO_STA    (0x1f<<16)
+#define IP3106_UART_FIFO_RXBRK         0x00008000
+#define IP3106_UART_FIFO_RXFE          0x00004000
+#define IP3106_UART_FIFO_RXPAR         0x00002000
+#define IP3106_UART_FIFO_RXFIFO                0x00001F00
+#define IP3106_UART_FIFO_RBRTHR                0x000000FF
+
+#endif
diff -urN linux/include/linux/serial_core.h linux/include/linux/serial_core.h
--- linux/include/linux/serial_core.h   2005/08/01 18:24:55     1.37
+++ linux/include/linux/serial_core.h   2005/08/05 01:14:41     1.38
@@ -39,7 +39,7 @@
 #define PORT_RSA       13
 #define PORT_NS16550A  14
 #define PORT_XSCALE    15
-#define PORT_PNX8550   16
+#define PORT_IP3106    16
 #define PORT_MAX_8250  16      /* max port ID */
 
 /*

<Prev in Thread] Current Thread [Next in Thread>