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 */
/*
|