From a4dd1adf4a718f4eec35a561be068e2e8f885ae2 Mon Sep 17 00:00:00 2001
From: Imre Kaloz <kaloz@openwrt.org>
Date: Sun, 27 Apr 2008 17:03:01 +0000
Subject: add preliminary support for Storm SL3512 based devices, not ready yet

SVN-Revision: 10956
---
 target/linux/storm/patches/1021-serial.patch | 2825 ++++++++++++++++++++++++++
 1 file changed, 2825 insertions(+)
 create mode 100644 target/linux/storm/patches/1021-serial.patch

(limited to 'target/linux/storm/patches/1021-serial.patch')

diff --git a/target/linux/storm/patches/1021-serial.patch b/target/linux/storm/patches/1021-serial.patch
new file mode 100644
index 0000000000..90880d6467
--- /dev/null
+++ b/target/linux/storm/patches/1021-serial.patch
@@ -0,0 +1,2825 @@
+Index: linux-2.6.23.16/drivers/serial/it8712.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23.16/drivers/serial/it8712.c	2008-03-15 17:59:53.568330991 +0200
+@@ -0,0 +1,858 @@
++/*
++ *  linux/drivers/char/serial_uart00.c
++ *
++ *  Driver for UART00 serial ports
++ *
++ *  Based on drivers/char/serial_amba.c, by ARM Limited &
++ *                                          Deep Blue Solutions Ltd.
++ *  Copyright 2001 Altera Corporation
++ *
++ * 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: it8712.c,v 1.2 2006/06/06 06:36:04 middle Exp $
++ *
++ */
++#include <linux/module.h>
++#include <linux/tty.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/serial.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++#include <asm/hardware.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/sizes.h>
++
++#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <linux/serial_core.h>
++#include <asm/arch/sl2312.h>
++#include <asm/arch/int_ctrl.h>
++#include <asm/arch/it8712.h>
++#include "it8712.h"
++
++//#define DEBUG           1
++#define UART_NR		1
++
++#define SERIAL_IT8712_NAME	"ttySI"
++#define SERIAL_IT8712_MAJOR	204
++#define SERIAL_IT8712_MINOR	41      /* Temporary - will change in future */
++#define SERIAL_IT8712_NR	UART_NR
++#define UART_PORT_SIZE 0x50
++#define LPC_HOST_CONTINUE_MODE	0x00000040
++
++#define IT8712_NO_PORTS         UART_NR
++#define IT8712_ISR_PASS_LIMIT	256
++
++#define LPC_BUS_CTRL	*(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
++#define LPC_BUS_STATUS	*(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
++#define LPC_SERIAL_IRQ_CTRL	*(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 8))
++#define LPC_SERIAL_IRQ_STATUS	*(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x0c))
++#define LPC_SERIAL_IRQ_TRITYPE *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x10))
++#define LPC_SERIAL_IRQ_POLARITY	*(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x14))
++#define LPC_SERIAL_IRQ_ENABLE	*(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x18))
++
++
++
++
++/*
++ * Access macros for the SL2312 UARTs
++ */
++#define UART_GET_INT_STATUS(p)	(inb(((p)->membase+UART_IIR)) & 0x0F)  // interrupt identification
++#define UART_PUT_IER(p, c)      outb(c,((p)->membase+UART_IER))         // interrupt enable
++#define UART_GET_IER(p)         inb(((p)->membase+UART_IER))
++#define UART_PUT_CHAR(p, c)     outb(c,((p)->membase+UART_TX))         // transmitter holding
++#define UART_GET_CHAR(p)        inb(((p)->membase+UART_RX))            // receive buffer
++#define UART_GET_LSR(p)         inb(((p)->membase+UART_LSR))            // line status
++#define UART_GET_MSR(p)         inb(((p)->membase+UART_MSR))            // modem status
++#define UART_GET_MCR(p)         inb(((p)->membase+UART_MCR))            // modem control
++#define UART_PUT_MCR(p, c)      outb(c,((p)->membase+UART_MCR))
++#define UART_GET_LCR(p)         inb(((p)->membase+UART_LCR))       // mode control
++#define UART_PUT_LCR(p, c)      outb(c,((p)->membase+UART_LCR))
++#define UART_PUT_FCR(p, c)      outb(c,((p)->membase+UART_FCR))       // fifo control
++#define UART_GET_DIV_HI(p)	inb(((p)->membase+UART_DLM))
++#define UART_PUT_DIV_HI(p, c)	outb(c,((p)->membase+UART_DLM))
++#define UART_GET_DIV_LO(p)	inb(((p)->membase+UART_DLL))
++#define UART_PUT_DIV_LO(p, c)	outb(c,((p)->membase+UART_DLL))
++#define UART_PUT_MDR(p, c)      outb(c,UART_MDR((p)->membase))
++#define UART_RX_DATA(s)		((s) & UART_LSR_DR)
++#define UART_TX_READY(s)	((s) & UART_LSR_THRE)
++
++static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
++{
++        unsigned int reg;
++
++        //printk("it8712 stop tx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_THRI);
++	UART_PUT_IER(port, reg);
++}
++
++static void it8712_stop_rx(struct uart_port *port)
++{
++        unsigned int reg;
++
++        //printk("it8712 stop rx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_RDI);
++	UART_PUT_IER(port, reg);
++
++}
++
++static void it8712_enable_ms(struct uart_port *port)
++{
++        unsigned int reg;
++
++        //printk("it8712 enable ms : \n");
++
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_MSI);
++	UART_PUT_IER(port, reg);
++
++}
++
++static void it8712_rx_chars(struct uart_port *port, struct pt_regs *regs)
++{
++	struct tty_struct *tty = port->info->tty;
++	unsigned int status, mask, ch, flg, ignored = 0;
++
++ //       printk("it8712_rx_chars : \n");
++	status = UART_GET_LSR(port);
++	while (UART_RX_DATA(status)) {
++
++		/*
++		 * We need to read rds before reading the
++		 * character from the fifo
++		 */
++		ch = UART_GET_CHAR(port);
++		port->icount.rx++;
++
++		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++			goto ignore_char;
++
++		flg = TTY_NORMAL;
++
++		/*
++		 * Note that the error handling code is
++		 * out of the main execution path
++		 */
++
++		if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
++			goto handle_error;
++		if (uart_handle_sysrq_char(port, ch, regs))
++			goto ignore_char;
++
++	error_return:
++		*tty->flip.flag_buf_ptr++ = flg;
++		*tty->flip.char_buf_ptr++ = ch;
++		tty->flip.count++;
++	ignore_char:
++		status = UART_GET_LSR(port);
++	} // end of while
++out:
++	tty_flip_buffer_push(tty);
++	return;
++
++handle_error:
++	if (status & UART_LSR_BI) {
++		status &= ~(UART_LSR_FE);
++		port->icount.brk++;
++
++#ifdef SUPPORT_SYSRQ
++		if (uart_handle_break(port))
++			goto ignore_char;
++#endif
++	} else if (status & UART_LSR_PE)
++		port->icount.parity++;
++	else if (status & UART_LSR_FE)
++		port->icount.frame++;
++
++	if (status & UART_LSR_OE)
++		port->icount.overrun++;
++
++	if (status & port->ignore_status_mask) {
++		if (++ignored > 100)
++			goto out;
++		goto ignore_char;
++	}
++
++	mask = status & port->read_status_mask;
++
++	if (mask & UART_LSR_BI)
++		flg = TTY_BREAK;
++	else if (mask & UART_LSR_PE)
++		flg = TTY_PARITY;
++	else if (mask & UART_LSR_FE)
++		flg = TTY_FRAME;
++
++	if (status & UART_LSR_OE) {
++		/*
++		 * CHECK: does overrun affect the current character?
++		 * ASSUMPTION: it does not.
++		 */
++		*tty->flip.flag_buf_ptr++ = flg;
++		*tty->flip.char_buf_ptr++ = ch;
++		tty->flip.count++;
++		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++			goto ignore_char;
++		ch = 0;
++		flg = TTY_OVERRUN;
++	}
++#ifdef SUPPORT_SYSRQ
++	port->sysrq = 0;
++#endif
++	goto error_return;
++}
++
++static void it8712_tx_chars(struct uart_port *port)
++{
++        struct circ_buf *xmit = &port->info->xmit;
++	int count;
++
++	if (port->x_char) {
++		while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++		UART_PUT_CHAR(port, port->x_char);
++		port->icount.tx++;
++		port->x_char = 0;
++
++		return;
++	}
++	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
++		it8712_stop_tx(port, 0);
++		return;
++	}
++
++	count = port->fifosize >> 1;
++	do {
++		while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
++		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++		port->icount.tx++;
++		if (uart_circ_empty(xmit))
++			break;
++	} while (--count > 0);
++
++	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++		uart_write_wakeup(port);
++
++	if (uart_circ_empty(xmit))
++		it8712_stop_tx(port, 0);
++}
++
++static void it8712_start_tx(struct uart_port *port, unsigned int tty_start)
++{
++        unsigned int reg;
++
++        //printk("it8712 start tx : \n");
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_THRI);
++	UART_PUT_IER(port, reg);
++	it8712_tx_chars(port);
++}
++
++static void it8712_modem_status(struct uart_port *port)
++{
++	unsigned int status;
++
++//        printk("it8712 modem status : \n");
++
++	status = UART_GET_MSR(port);
++
++	if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
++		       UART_MSR_TERI | UART_MSR_DDCD)))
++		return;
++
++        if (status & UART_MSR_DDCD)
++                uart_handle_dcd_change(port, status & UART_MSR_DCD);
++
++        if (status & UART_MSR_DDSR)
++                port->icount.dsr++;
++
++        if (status & UART_MSR_DCTS)
++                uart_handle_cts_change(port, status & UART_MSR_CTS);
++
++	wake_up_interruptible(&port->info->delta_msr_wait);
++
++}
++
++static irqreturn_t  it8712_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++	struct uart_port *port = dev_id;
++	unsigned int status, pass_counter = 0, data;
++
++
++		data = LPC_SERIAL_IRQ_STATUS;
++	if((data&0x10)==0x10)
++	{
++		status = UART_GET_INT_STATUS(port);
++		do {
++//			     printk("it8712_int: status %x \n", status);
++			switch(status)
++			{
++			   case UART_IIR_RDI:
++			   case UART_IIR_RLSI:
++			   case UART_IIR_RCTO:
++				it8712_rx_chars(port, regs);
++			   break;
++			   case UART_IIR_THRI:
++				it8712_tx_chars(port);
++			   break;
++			   case UART_IIR_MSI:
++				it8712_modem_status(port);
++			   break;
++			   default:
++			   break;
++			}
++			if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
++				break;
++
++			status = UART_GET_INT_STATUS(port);
++		} while (status);
++	}
++
++		status = 0;
++        status |= (IRQ_LPC_MASK);
++        *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = status;
++
++	//cnt=0;
++	//do{
++	//	data = LPC_SERIAL_IRQ_STATUS;
++		LPC_SERIAL_IRQ_STATUS = data;
++	//	cnt++;
++	//}while(data);
++	//if(cnt>2)
++	//	printf("it8712_uart_Isr clear LPC_SERIAL_IRQ_STATUS %x \n", cnt);
++        return IRQ_HANDLED;
++}
++
++static u_int it8712_tx_empty(struct uart_port *port)
++{
++//        printk("it8712 tx empty : \n");
++
++	return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
++}
++
++static u_int it8712_get_mctrl(struct uart_port *port)
++{
++	unsigned int result = 0;
++	unsigned int status;
++
++//        printk("it8712 get mctrl : \n");
++
++	status = UART_GET_MSR(port);
++	if (status & UART_MSR_DCD)
++		result |= TIOCM_CAR;
++	if (status & UART_MSR_DSR)
++		result |= TIOCM_DSR;
++	if (status & UART_MSR_CTS)
++		result |= TIOCM_CTS;
++	if (status & UART_MSR_RI)
++		result |= TIOCM_RI;
++
++	return result;
++}
++
++static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
++{
++}
++
++static void it8712_break_ctl(struct uart_port *port, int break_state)
++{
++	unsigned int lcr;
++
++//        printk("it8712 break ctl : \n");
++
++	lcr = UART_GET_LCR(port);
++	if (break_state == -1)
++		lcr |= UART_LCR_SBC;
++	else
++		lcr &= ~UART_LCR_SBC;
++	UART_PUT_LCR(port, lcr);
++}
++
++static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
++{
++	u_int quot;
++
++	/* Special case: B0 rate */
++	if (!baud)
++		baud = 9600;
++
++	quot = (port->uartclk/(16 * baud)) ;
++
++	return quot;
++}
++static void it8712_set_termios(struct uart_port *port, struct termios *termios,
++                               struct termios *old)
++{
++	unsigned int  uart_mc, old_ier, baud, quot;
++	unsigned long flags;
++
++        termios->c_cflag |= CREAD;
++        termios->c_cflag |= CLOCAL;
++#ifdef DEBUG
++	printk("it8712_set_cflag(0x%x) called\n", cflag);
++#endif
++        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++        quot = uart_get_divisor(port, baud);
++
++	/* byte size and parity */
++	switch (termios->c_cflag & CSIZE) {
++	case CS5:
++              uart_mc = UART_LCR_WLEN5;
++              break;
++	case CS6:
++              uart_mc = UART_LCR_WLEN6;
++              break;
++	case CS7:
++              uart_mc = UART_LCR_WLEN7;
++              break;
++	default: // CS8
++              uart_mc = UART_LCR_WLEN8;
++              break;
++	}
++
++	if (termios->c_cflag & CSTOPB)
++		uart_mc|= UART_LCR_STOP;
++	if (termios->c_cflag & PARENB) {
++		uart_mc |= UART_LCR_EVEN;
++		if (!(termios->c_cflag & PARODD))
++			uart_mc |= UART_LCR_ODD;
++	}
++
++        spin_lock_irqsave(&port->lock, flags);
++        /*
++         * Update the per-port timeout
++         */
++        uart_update_timeout(port, termios->c_cflag, baud);
++	port->read_status_mask = UART_LSR_OE;
++	if (termios->c_iflag & INPCK)
++		port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++	if (termios->c_iflag & (BRKINT | PARMRK))
++		port->read_status_mask |= UART_LSR_BI;
++
++	/*
++	 * Characters to ignore
++	 */
++	port->ignore_status_mask = 0;
++	if (termios->c_iflag & IGNPAR)
++		port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
++	if (termios->c_iflag & IGNBRK) {
++		port->ignore_status_mask |= UART_LSR_BI;
++		/*
++		 * If we're ignoring parity and break indicators,
++		 * ignore overruns to (for real raw support).
++		 */
++		if (termios->c_iflag & IGNPAR)
++			port->ignore_status_mask |= UART_LSR_OE;
++	}
++
++	old_ier = UART_GET_IER(port);
++
++        if(UART_ENABLE_MS(port, termios->c_cflag))
++             old_ier |= UART_IER_MSI;
++
++	/* Set baud rate */
++	quot = quot / 13;
++	UART_PUT_LCR(port, UART_LCR_DLAB);
++	UART_PUT_DIV_LO(port, (quot & 0xff));
++	UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
++
++	UART_PUT_LCR(port, uart_mc);
++//	UART_PUT_LCR(port, 0x07); // ???? it is wired
++        UART_PUT_MCR(port, 0x08);
++        UART_PUT_FCR(port, 0x01);
++	UART_PUT_IER(port, 0x07);
++
++	spin_unlock_irqrestore(&port->lock, flags);
++}
++
++static int it8712_startup(struct uart_port *port)
++{
++	int retval, i;
++	unsigned int regs;
++
++        //printk("it8712 startup : \n");
++
++	/*
++	 * Use iobase to store a pointer to info. We need this to start a
++	 * transmission as the tranmittr interrupt is only generated on
++	 * the transition to the idle state
++	 */
++
++	//	regs = 0;
++    //    regs |= (IRQ_LPC_MASK);
++    //    *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++
++	/*
++	 * Allocate the IRQ
++	 */
++	retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", port);
++	if (retval)
++		return retval;
++
++	//printk("Init LPC int...........\n");
++        /* setup interrupt controller  */
++        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_LPC_MASK);
++        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_LPC_MASK);
++        *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_LPC_MASK);
++
++	LPC_SERIAL_IRQ_POLARITY = 0x10; //0x10; //0x02;
++	LPC_SERIAL_IRQ_TRITYPE = 0x10; //0x10;//
++	LPC_SERIAL_IRQ_ENABLE = 0x10;
++
++	LPC_BUS_CTRL = 0xc0;
++	LPC_SERIAL_IRQ_CTRL = 0xc0;
++	for(i=0;i<1000;i++) ;
++	LPC_SERIAL_IRQ_CTRL = 0x80;
++	/*
++	 * Finally, enable interrupts. Use the TII interrupt to minimise
++	 * the number of interrupts generated. If higher performance is
++	 * needed, consider using the TI interrupt with a suitable FIFO
++	 * threshold
++	 */
++	//UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
++	UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI|UART_IER_RLSI));//middle
++
++	return 0;
++}
++
++static void it8712_shutdown(struct uart_port *port)
++{
++        //printk("it8712 shutdown : \n");
++
++	/*
++	 * disable all interrupts, disable the port
++	 */
++	UART_PUT_IER(port, 0x0);
++
++	/* disable break condition and fifos */
++//	UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
++
++	/*
++	 * Free the interrupt
++	 */
++	free_irq(port->irq, port);
++}
++
++static const char *it8712_type(struct uart_port *port)
++{
++	return port->type == PORT_IT8712 ? "IT8712" : NULL;
++}
++
++/*
++ * Release the memory region(s) being used by 'port'
++ */
++static void it8712_release_port(struct uart_port *port)
++{
++//        printk("it8712 release port : \n");
++
++	release_mem_region(port->mapbase, UART_PORT_SIZE);
++}
++
++/*
++ * Request the memory region(s) being used by 'port'
++ */
++static int it8712_request_port(struct uart_port *port)
++{
++	return request_mem_region(port->mapbase, UART_PORT_SIZE,
++				    "serial_it8712") != NULL ? 0 : -EBUSY;
++}
++
++/*
++ * Configure/autoconfigure the port.
++ */
++static void it8712_config_port(struct uart_port *port, int flags)
++{
++
++	if (flags & UART_CONFIG_TYPE) {
++		if (it8712_request_port(port) == 0)
++			port->type = PORT_IT8712;
++	}
++}
++
++/*
++ * verify the new serial_struct (for TIOCSSERIAL).
++ */
++static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++	int ret = 0;
++
++	if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
++		ret = -EINVAL;
++	if (ser->irq < 0 || ser->irq >= NR_IRQS)
++		ret = -EINVAL;
++	if (ser->baud_base < 9600)
++		ret = -EINVAL;
++	return ret;
++}
++
++static struct uart_ops it8712_pops = {
++	.tx_empty	= it8712_tx_empty,
++	.set_mctrl	= it8712_set_mctrl_null,
++	.get_mctrl	= it8712_get_mctrl,
++	.stop_tx	= it8712_stop_tx,
++	.start_tx	= it8712_start_tx,
++	.stop_rx	= it8712_stop_rx,
++	.enable_ms	= it8712_enable_ms,
++	.break_ctl	= it8712_break_ctl,
++	.startup	= it8712_startup,
++	.shutdown	= it8712_shutdown,
++	.set_termios	= it8712_set_termios,
++	.type		= it8712_type,
++	.release_port	= it8712_release_port,
++	.request_port	= it8712_request_port,
++	.config_port	= it8712_config_port,
++	.verify_port	= it8712_verify_port,
++};
++
++#ifdef CONFIG_ARCH_SL2312
++
++static struct uart_port it8712_ports[UART_NR] = {
++	{
++		membase:	(void *)0,
++		mapbase:	0,
++		iotype:		SERIAL_IO_MEM,
++		irq:		0,
++		uartclk:	UART_CLK/2,
++		fifosize:	16,
++		ops:		&it8712_pops,
++		flags:		ASYNC_BOOT_AUTOCONF,
++	}
++};
++
++#endif
++
++#ifdef CONFIG_SERIAL_IT8712_CONSOLE
++#ifdef used_and_not_const_char_pointer
++static int it8712_console_read(struct uart_port *port, char *s, u_int count)
++{
++	unsigned int status;
++	int c;
++#ifdef DEBUG
++	printk("it8712_console_read() called\n");
++#endif
++
++	c = 0;
++	while (c < count) {
++		status = UART_GET_LSR(port);
++ 		if (UART_RX_DATA(status)) {
++			*s++ = UART_GET_CHAR(port);
++			c++;
++		} else {
++			// nothing more to get, return
++			return c;
++		}
++	}
++	// return the count
++	return c;
++}
++#endif
++static void it8712_console_write(struct console *co, const char *s, unsigned count)
++{
++#ifdef CONFIG_ARCH_SL2312
++	struct uart_port *port = it8712_ports + co->index;
++	unsigned int status, old_ies;
++	int i;
++
++	/*
++	 *	First save the CR then disable the interrupts
++	 */
++	old_ies = UART_GET_IER(port);
++	//if(old_ies!=7)
++	//{
++	//
++	//	printk("old_ies = %x\n",old_ies);
++	//	old_ies = 7;
++	//}
++	UART_PUT_IER(port,0x0);
++
++	/*
++	 *	Now, do each character
++	 */
++	for (i = 0; i < count; i++) {
++		do {
++			status = UART_GET_LSR(port);
++		} while (!UART_TX_READY(status));
++		UART_PUT_CHAR(port, s[i]);
++		if (s[i] == '\n') {
++			do {
++				status = UART_GET_LSR(port);
++			} while (!UART_TX_READY(status));
++			UART_PUT_CHAR(port, '\r');
++		}
++	}
++
++	/*
++	 *	Finally, wait for transmitter to become empty
++	 *	and restore the IES
++	 */
++	do {
++		status = UART_GET_LSR(port);
++	} while (!(status&UART_LSR_THRE));
++	UART_PUT_IER(port, old_ies);
++#endif
++}
++
++static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
++{
++	//printk("it8712 console get options : \n");
++
++	u_int uart_mc, quot;
++	uart_mc= UART_GET_MCR(port);
++
++	*parity = 'n';
++	if (uart_mc & UART_LCR_PARITY) {
++		if (uart_mc & UART_LCR_EVEN)
++			*parity = 'e';
++		else
++			*parity = 'o';
++	}
++
++	switch (uart_mc & UART_LCR_MSK){
++
++	case UART_LCR_WLEN5:
++		*bits = 5;
++		break;
++	case UART_LCR_WLEN6:
++		*bits = 6;
++		break;
++	case UART_LCR_WLEN7:
++		*bits = 7;
++		break;
++	case UART_LCR_WLEN8:
++		*bits = 8;
++		break;
++	}
++	UART_PUT_MCR(port,UART_LCR_DLAB);
++	quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
++	UART_PUT_MCR(port,uart_mc);
++	*baud = (port->uartclk / (16 *quot));
++}
++
++static int __init it8712_console_setup(struct console *co, char *options)
++{
++	struct uart_port *port;
++	int baud = 38400;
++	int bits = 8;
++	int parity = 'n';
++	int flow= 'n';
++	int base;//, irq;
++	int i ;
++
++	printk("it8712 console setup : \n");
++
++	LPCSetConfig(0, 0x02, 0x01);
++        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
++        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
++	base = IT8712_IO_BASE;
++	base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
++	it8712_ports[0].mapbase = base;
++	it8712_ports[0].membase = (void *)IO_ADDRESS(base);
++	it8712_ports[0].irq = IRQ_LPC_OFFSET;
++    //   	irq = LPCGetConfig(LDN_SERIAL1, 0x70);
++	//it8712_ports[0].irq += irq;
++
++	//printk("it8712 irq is %x \n", it8712_ports[0].irq);
++
++	// setup LPC Host 'quiet mode'
++	//*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
++	//for(i=0;i<1000;i++) ;						// delay
++	//*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
++	LPC_BUS_CTRL = 0xc0;
++	LPC_SERIAL_IRQ_CTRL = 0xc0;
++	for(i=0;i<1000;i++) ;
++	LPC_SERIAL_IRQ_CTRL = 0x80;
++
++#ifdef CONFIG_ARCH_SL2312
++	/*
++	 * Check whether an invalid uart number has been specified, and
++	 * if so, search for the first available port that does have
++	 * console support.
++	 */
++	port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
++#else
++	return -ENODEV;
++#endif
++
++	if (options)
++		uart_parse_options(options, &baud, &parity, &bits, &flow);
++	else
++		it8712_console_get_options(port, &baud, &parity, &bits);
++
++	return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++extern struct uart_driver it8712_reg;
++static struct console it8712_console = {
++	.name           = SERIAL_IT8712_NAME,
++	.write		= it8712_console_write,
++	.device		= uart_console_device,
++        .setup          = it8712_console_setup,
++	.flags		= CON_PRINTBUFFER,
++	.index		= 0,
++        .data           = &it8712_reg,
++};
++
++static int __init it8712_console_init(void)
++{
++	register_console(&it8712_console);
++        return 0;
++}
++
++console_initcall(it8712_console_init);
++
++#define IT8712_CONSOLE	&it8712_console
++#else
++#define IT8712_CONSOLE	NULL
++#endif
++
++static struct uart_driver it8712_reg = {
++	.owner                  = NULL,
++	.driver_name		= SERIAL_IT8712_NAME,
++	.dev_name		= SERIAL_IT8712_NAME,
++        .major                  = SERIAL_IT8712_MAJOR,
++	.minor			= SERIAL_IT8712_MINOR,
++	.nr			= UART_NR,
++	.cons			= IT8712_CONSOLE,
++};
++
++static int __init it8712_init(void)
++{
++        int result;
++	//printk("serial_it8712: it871212_init \n");
++
++
++        result = uart_register_driver(&it8712_reg);
++        if(result)
++             return result;
++	result = uart_add_one_port(&it8712_reg, &it8712_ports[0]);
++
++        return result;
++
++}
++
++
++__initcall(it8712_init);
+Index: linux-2.6.23.16/drivers/serial/it8712.h
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23.16/drivers/serial/it8712.h	2008-03-15 17:59:53.568330991 +0200
+@@ -0,0 +1,135 @@
++#define UART_RX		0	/* In:  Receive buffer (DLAB=0) */
++#define UART_TX		0	/* Out: Transmit buffer (DLAB=0) */
++#define UART_DLL	0	/* Out: Divisor Latch Low (DLAB=1) */
++#define UART_TRG	0	/* (LCR=BF) FCTR bit 7 selects Rx or Tx
++				 * In: Fifo count
++				 * Out: Fifo custom trigger levels
++				 * XR16C85x only */
++
++#define UART_DLM	1	/* Out: Divisor Latch High (DLAB=1) */
++#define UART_IER	1	/* Out: Interrupt Enable Register */
++#define UART_FCTR	1	/* (LCR=BF) Feature Control Register
++				 * XR16C85x only */
++
++#define UART_IIR	2	/* In:  Interrupt ID Register */
++#define UART_FCR	2	/* Out: FIFO Control Register */
++#define UART_EFR	2	/* I/O: Extended Features Register */
++				/* (DLAB=1, 16C660 only) */
++
++#define UART_LCR	3	/* Out: Line Control Register */
++#define UART_MCR	4	/* Out: Modem Control Register */
++#define UART_LSR	5	/* In:  Line Status Register */
++#define UART_MSR	6	/* In:  Modem Status Register */
++#define UART_SCR	7	/* I/O: Scratch Register */
++#define UART_EMSR	7	/* (LCR=BF) Extended Mode Select Register
++				 * FCTR bit 6 selects SCR or EMSR
++				 * XR16c85x only */
++
++/*
++ * These are the definitions for the FIFO Control Register
++ * (16650 only)
++ */
++#define UART_FCR_ENABLE_FIFO	0x01 /* Enable the FIFO */
++#define UART_FCR_CLEAR_RCVR	0x02 /* Clear the RCVR FIFO */
++#define UART_FCR_CLEAR_XMIT	0x04 /* Clear the XMIT FIFO */
++#define UART_FCR_DMA_SELECT	0x08 /* For DMA applications */
++#define UART_FCR_TRIGGER_MASK	0xC0 /* Mask for the FIFO trigger range */
++#define UART_FCR_TRIGGER_1	0x00 /* Mask for trigger set at 1 */
++#define UART_FCR_TRIGGER_4	0x40 /* Mask for trigger set at 4 */
++#define UART_FCR_TRIGGER_8	0x80 /* Mask for trigger set at 8 */
++#define UART_FCR_TRIGGER_14	0xC0 /* Mask for trigger set at 14 */
++/* 16650 redefinitions */
++#define UART_FCR6_R_TRIGGER_8	0x00 /* Mask for receive trigger set at 1 */
++#define UART_FCR6_R_TRIGGER_16	0x40 /* Mask for receive trigger set at 4 */
++#define UART_FCR6_R_TRIGGER_24  0x80 /* Mask for receive trigger set at 8 */
++#define UART_FCR6_R_TRIGGER_28	0xC0 /* Mask for receive trigger set at 14 */
++#define UART_FCR6_T_TRIGGER_16	0x00 /* Mask for transmit trigger set at 16 */
++#define UART_FCR6_T_TRIGGER_8	0x10 /* Mask for transmit trigger set at 8 */
++#define UART_FCR6_T_TRIGGER_24  0x20 /* Mask for transmit trigger set at 24 */
++#define UART_FCR6_T_TRIGGER_30	0x30 /* Mask for transmit trigger set at 30 */
++/* TI 16750 definitions */
++#define UART_FCR7_64BYTE	0x20 /* Go into 64 byte mode */
++
++/*
++ * These are the definitions for the Line Control Register
++ *
++ * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
++ * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
++ */
++#define UART_LCR_DLAB	0x80	/* Divisor latch access bit */
++#define UART_LCR_SBC	0x40	/* Set break control */
++#define UART_LCR_SPAR	0x20	/* Stick parity (?) */
++#define UART_LCR_EPAR	0x10	/* Even parity select */
++#define UART_LCR_PARITY	0x08	/* Parity Enable */
++#define UART_LCR_STOP	0x04	/* Stop bits: 0=1 stop bit, 1= 2 stop bits */
++#define UART_LCR_WLEN5  0x00	/* Wordlength: 5 bits */
++#define UART_LCR_WLEN6  0x01	/* Wordlength: 6 bits */
++#define UART_LCR_WLEN7  0x02	/* Wordlength: 7 bits */
++#define UART_LCR_WLEN8  0x03	/* Wordlength: 8 bits */
++#define UART_LCR_EVEN   0x18    /* Even parity */
++#define UART_LCR_ODD    0x08    /* Odd parity */
++#define UART_LCR_MSK    0x03
++/*
++ * These are the definitions for the Line Status Register
++ */
++#define UART_LSR_DE     0x80    /* FIFO Data Error */
++#define UART_LSR_TEMT	0x40	/* Transmitter empty */
++#define UART_LSR_THRE	0x20	/* Transmit-hold-register empty */
++#define UART_LSR_BI	0x10	/* Break interrupt indicator */
++#define UART_LSR_FE	0x08	/* Frame error indicator */
++#define UART_LSR_PE	0x04	/* Parity error indicator */
++#define UART_LSR_OE	0x02	/* Overrun error indicator */
++#define UART_LSR_DR	0x01	/* Receiver data ready */
++
++/*
++ * These are the definitions for the Interrupt Identification Register
++ */
++#define UART_IIR_NO_INT	0x01	/* No interrupts pending */
++#define UART_IIR_ID	0x06	/* Mask for the interrupt ID */
++
++#define UART_IIR_MSI	0x00	/* Modem status interrupt */
++#define UART_IIR_THRI	0x02	/* Transmitter holding register empty */
++#define UART_IIR_RDI	0x04	/* Receiver data interrupt */
++#define UART_IIR_RLSI	0x06	/* Receiver line status interrupt */
++#define UART_IIR_RCTO	0x0c	/* Receiver character timeout interrupt */
++/*
++ * These are the definitions for the Interrupt Enable Register
++ */
++#define UART_IER_MSI	0x08	/* Enable Modem status interrupt */
++#define UART_IER_RLSI	0x04	/* Enable receiver line status interrupt */
++#define UART_IER_THRI	0x02	/* Enable Transmitter holding register int. */
++#define UART_IER_RDI	0x01	/* Enable receiver data interrupt */
++/*
++ * Sleep mode for ST16650 and TI16750.
++ * Note that for 16650, EFR-bit 4 must be selected as well.
++ */
++#define UART_IERX_SLEEP  0x10	/* Enable sleep mode */
++
++/*
++ * These are the definitions for the Modem Control Register
++ */
++#define UART_MCR_LOOP	0x10	/* Enable loopback test mode */
++#define UART_MCR_OUT2	0x08	/* Out2 complement */
++#define UART_MCR_OUT1	0x04	/* Out1 complement */
++#define UART_MCR_RTS	0x02	/* RTS complement */
++#define UART_MCR_DTR	0x01	/* DTR complement */
++
++/*
++ * These are the definitions for the Modem Status Register
++ */
++#define UART_MSR_DCD	0x80	/* Data Carrier Detect */
++#define UART_MSR_RI	0x40	/* Ring Indicator */
++#define UART_MSR_DSR	0x20	/* Data Set Ready */
++#define UART_MSR_CTS	0x10	/* Clear to Send */
++#define UART_MSR_DDCD	0x08	/* Delta DCD */
++#define UART_MSR_TERI	0x04	/* Trailing edge ring indicator */
++#define UART_MSR_DDSR	0x02	/* Delta DSR */
++#define UART_MSR_DCTS	0x01	/* Delta CTS */
++#define UART_MSR_ANY_DELTA 0x0F	/* Any of the delta bits! */
++
++#define UART_PARITY_NONE	0x00
++#define UART_PARITY_ODD		0x01
++#define UART_PARITY_EVEN	0x02
++
++
++
+Index: linux-2.6.23.16/drivers/serial/serial_it8712.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23.16/drivers/serial/serial_it8712.c	2008-03-15 17:59:53.568330991 +0200
+@@ -0,0 +1,876 @@
++/*
++ *  linux/drivers/char/serial_uart00.c
++ *
++ *  Driver for UART00 serial ports
++ *
++ *  Based on drivers/char/serial_amba.c, by ARM Limited &
++ *                                          Deep Blue Solutions Ltd.
++ *  Copyright 2001 Altera Corporation
++ *
++ * 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: serial_it8712.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
++ *
++ */
++#include <linux/module.h>
++
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/major.h>
++#include <linux/string.h>
++#include <linux/fcntl.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/circ_buf.h>
++#include <linux/serial.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/sizes.h>
++
++#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <linux/serial_core.h>
++#include <asm/arch/sl2312.h>
++#include <asm/arch/int_ctrl.h>
++#include <asm/arch/it8712.h>
++#include "serial_it8712.h"
++
++//#define DEBUG           1
++#define UART_NR		1
++
++#define SERIAL_IT8712_NAME	"ttySI"
++#define SERIAL_IT8712_MAJOR	204
++#define SERIAL_IT8712_MINOR	41      /* Temporary - will change in future */
++#define SERIAL_IT8712_NR	UART_NR
++#define UART_PORT_SIZE 0x50
++
++#define CALLOUT_IT8712_NAME	"cuaslI"
++#define CALLOUT_IT8712_MAJOR	205
++#define CALLOUT_IT8712_MINOR	41      /* Temporary - will change in future */
++#define CALLOUT_IT8712_NR	UART_NR
++#define LPC_HOST_CONTINUE_MODE	0x00000040
++
++#define IT8712_NO_PORTS         UART_NR
++
++static struct tty_driver normal, callout;
++static struct tty_struct *it8712_table[UART_NR];
++static struct termios *it8712_termios[UART_NR], *it8712_termios_locked[UART_NR];
++static struct console it8712_console;
++
++#define IT8712_ISR_PASS_LIMIT	256
++
++/*
++ * Access macros for the SL2312 UARTs
++ */
++#define UART_GET_INT_STATUS(p)	(inb(((p)->membase+UART_IIR)) & 0x0F)  // interrupt identification
++#define UART_PUT_IER(p, c)      outb(c,((p)->membase+UART_IER))         // interrupt enable
++#define UART_GET_IER(p)         inb(((p)->membase+UART_IER))
++#define UART_PUT_CHAR(p, c)     outb(c,((p)->membase+UART_TX))         // transmitter holding
++#define UART_GET_CHAR(p)        inb(((p)->membase+UART_RX))            // receive buffer
++#define UART_GET_LSR(p)         inb(((p)->membase+UART_LSR))            // line status
++#define UART_GET_MSR(p)         inb(((p)->membase+UART_MSR))            // modem status
++#define UART_GET_MCR(p)         inb(((p)->membase+UART_MCR))            // modem control
++#define UART_PUT_MCR(p, c)      outb(c,((p)->membase+UART_MCR))
++#define UART_GET_LCR(p)         inb(((p)->membase+UART_LCR))       // mode control
++#define UART_PUT_LCR(p, c)      outb(c,((p)->membase+UART_LCR))
++#define UART_PUT_FCR(p, c)      outb(c,((p)->membase+UART_FCR))       // fifo control
++#define UART_GET_DIV_HI(p)	inb(((p)->membase+UART_DLM))
++#define UART_PUT_DIV_HI(p, c)	outb(c,((p)->membase+UART_DLM))
++#define UART_GET_DIV_LO(p)	inb(((p)->membase+UART_DLL))
++#define UART_PUT_DIV_LO(p, c)	outb(c,((p)->membase+UART_DLL))
++#define UART_PUT_MDR(p, c)      outb(c,UART_MDR((p)->membase))
++#define UART_RX_DATA(s)		((s) & UART_LSR_DR)
++#define UART_TX_READY(s)	((s) & UART_LSR_THRE)
++
++static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
++{
++        unsigned int reg;
++
++//        printk("it8712 stop tx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_THRI);
++	UART_PUT_IER(port, reg);
++}
++
++static void it8712_stop_rx(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("it8712 stop rx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_RDI);
++	UART_PUT_IER(port, reg);
++
++}
++
++static void it8712_enable_ms(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("it8712 enable ms : \n");
++
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_MSI);
++	UART_PUT_IER(port, reg);
++
++}
++
++static void
++it8712_rx_chars(struct uart_info *info, struct pt_regs *regs)
++{
++	struct tty_struct *tty = info->tty;
++	unsigned int status, mask, ch, flg, ignored = 0;
++	struct uart_port *port = info->port;
++
++ //       printk("it8712_rx_chars : \n");
++	status = UART_GET_LSR(port);
++	while (UART_RX_DATA(status)) {
++
++		/*
++		 * We need to read rds before reading the
++		 * character from the fifo
++		 */
++		ch = UART_GET_CHAR(port);
++		port->icount.rx++;
++
++		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++			goto ignore_char;
++
++		flg = TTY_NORMAL;
++
++		/*
++		 * Note that the error handling code is
++		 * out of the main execution path
++		 */
++
++		if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
++			goto handle_error;
++		if (uart_handle_sysrq_char(info, ch, regs))
++			goto ignore_char;
++
++	error_return:
++		*tty->flip.flag_buf_ptr++ = flg;
++		*tty->flip.char_buf_ptr++ = ch;
++		tty->flip.count++;
++	ignore_char:
++		status = UART_GET_LSR(port);
++	} // end of while
++out:
++	tty_flip_buffer_push(tty);
++	return;
++
++handle_error:
++	if (status & UART_LSR_BI) {
++		status &= ~(UART_LSR_FE);
++		port->icount.brk++;
++
++#ifdef SUPPORT_SYSRQ
++		if (uart_handle_break(info, &it8712_console))
++			goto ignore_char;
++#endif
++	} else if (status & UART_LSR_PE)
++		port->icount.parity++;
++	else if (status & UART_LSR_FE)
++		port->icount.frame++;
++
++	if (status & UART_LSR_OE)
++		port->icount.overrun++;
++
++	if (status & port->ignore_status_mask) {
++		if (++ignored > 100)
++			goto out;
++		goto ignore_char;
++	}
++
++	mask = status & port->read_status_mask;
++
++	if (mask & UART_LSR_BI)
++		flg = TTY_BREAK;
++	else if (mask & UART_LSR_PE)
++		flg = TTY_PARITY;
++	else if (mask & UART_LSR_FE)
++		flg = TTY_FRAME;
++
++	if (status & UART_LSR_OE) {
++		/*
++		 * CHECK: does overrun affect the current character?
++		 * ASSUMPTION: it does not.
++		 */
++		*tty->flip.flag_buf_ptr++ = flg;
++		*tty->flip.char_buf_ptr++ = ch;
++		tty->flip.count++;
++		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++			goto ignore_char;
++		ch = 0;
++		flg = TTY_OVERRUN;
++	}
++#ifdef SUPPORT_SYSRQ
++	info->sysrq = 0;
++#endif
++	goto error_return;
++}
++
++static void it8712_tx_chars(struct uart_info *info)
++{
++	int count;
++	struct uart_port *port=info->port;
++
++	if (port->x_char) {
++		while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++		UART_PUT_CHAR(port, port->x_char);
++		port->icount.tx++;
++		port->x_char = 0;
++
++		return;
++	}
++	if (info->xmit.head == info->xmit.tail
++	    || info->tty->stopped
++	    || info->tty->hw_stopped) {
++		it8712_stop_tx(info->port, 0);
++		return;
++	}
++
++	count = port->fifosize >> 1;
++	do {
++		while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++		UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
++		info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
++		port->icount.tx++;
++		if (info->xmit.head == info->xmit.tail)
++			break;
++	} while (--count > 0);
++
++	if (CIRC_CNT(info->xmit.head,
++		     info->xmit.tail,
++		     UART_XMIT_SIZE) < WAKEUP_CHARS)
++		uart_event(info, EVT_WRITE_WAKEUP);
++
++	if (info->xmit.head == info->xmit.tail)
++		it8712_stop_tx(info->port, 0);
++}
++
++static void it8712_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
++{
++        unsigned int reg;
++	struct uart_info *info=(struct uart_info*)(port->iobase);
++
++//        printk("it8712 start tx : \n");
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_THRI);
++	UART_PUT_IER(port, reg);
++	it8712_tx_chars(info);
++}
++
++static void it8712_modem_status(struct uart_info *info)
++{
++	unsigned int status;
++	struct uart_icount *icount = &info->port->icount;
++
++//        printk("it8712 modem status : \n");
++
++	status = UART_GET_MSR(info->port);
++
++	if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
++		       UART_MSR_TERI | UART_MSR_DDCD)))
++		return;
++
++	if (status & UART_MSR_DCD) {
++		icount->dcd++;
++#ifdef CONFIG_HARD_PPS
++		if ((info->flags & ASYNC_HARDPPS_CD) &&
++		    (status & UART_MSR_DCD_MSK))
++			hardpps();
++#endif
++		if (info->flags & ASYNC_CHECK_CD) {
++			if (status & UART_MSR_DCD)
++				wake_up_interruptible(&info->open_wait);
++			else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
++				   (info->flags & ASYNC_CALLOUT_NOHUP))) {
++				if (info->tty)
++					tty_hangup(info->tty);
++			}
++		}
++	}
++
++	if (status & UART_MSR_DDSR)
++		icount->dsr++;
++
++	if (status & UART_MSR_DCTS) {
++		icount->cts++;
++
++		if (info->flags & ASYNC_CTS_FLOW) {
++			status &= UART_MSR_CTS;
++
++			if (info->tty->hw_stopped) {
++				if (status) {
++					info->tty->hw_stopped = 0;
++					info->ops->start_tx(info->port, 1, 0);
++					uart_event(info, EVT_WRITE_WAKEUP);
++				}
++			} else {
++				if (!status) {
++					info->tty->hw_stopped = 1;
++					info->ops->stop_tx(info->port, 0);
++				}
++			}
++		}
++	}
++	wake_up_interruptible(&info->delta_msr_wait);
++
++}
++
++static void it8712_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++	struct uart_info *info = dev_id;
++	unsigned int status, pass_counter = 0;
++
++	status = UART_GET_INT_STATUS(info->port);
++	do {
++//		     printk("it8712_int: status %x \n", status);
++		switch(status)
++		{
++		   case UART_IIR_RDI:
++		   case UART_IIR_RLSI:
++		   case UART_IIR_RCTO:
++			it8712_rx_chars(info, regs);
++		   break;
++		   case UART_IIR_THRI:
++			it8712_tx_chars(info);
++		   break;
++		   case UART_IIR_MSI:
++			it8712_modem_status(info);
++		   break;
++		   default:
++		   break;
++		}
++		if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
++			break;
++
++		status = UART_GET_INT_STATUS(info->port);
++	} while (status);
++}
++
++static u_int it8712_tx_empty(struct uart_port *port)
++{
++//        printk("it8712 tx empty : \n");
++
++	return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
++}
++
++static u_int it8712_get_mctrl(struct uart_port *port)
++{
++	unsigned int result = 0;
++	unsigned int status;
++
++//        printk("it8712 get mctrl : \n");
++
++	status = UART_GET_MSR(port);
++	if (status & UART_MSR_DCD)
++		result |= TIOCM_CAR;
++	if (status & UART_MSR_DSR)
++		result |= TIOCM_DSR;
++	if (status & UART_MSR_CTS)
++		result |= TIOCM_CTS;
++	if (status & UART_MSR_RI)
++		result |= TIOCM_RI;
++
++	return result;
++}
++
++static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
++{
++}
++
++static void it8712_break_ctl(struct uart_port *port, int break_state)
++{
++	unsigned int lcr;
++
++//        printk("it8712 break ctl : \n");
++
++	lcr = UART_GET_LCR(port);
++	if (break_state == -1)
++		lcr |= UART_LCR_SBC;
++	else
++		lcr &= ~UART_LCR_SBC;
++	UART_PUT_LCR(port, lcr);
++}
++
++static inline u_int uart_calculate_quot(struct uart_info *info, u_int baud)
++{
++	u_int quot;
++
++	/* Special case: B0 rate */
++	if (!baud)
++		baud = 9600;
++
++	quot = (info->port->uartclk/(16 * baud)) ;
++
++	return quot;
++}
++static void it8712_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
++{
++	u_int uart_mc=0, old_ier;
++	unsigned long flags;
++
++#ifdef DEBUG
++	printk("it8712_set_cflag(0x%x) called\n", cflag);
++#endif
++
++
++	/* byte size and parity */
++	switch (cflag & CSIZE) {
++	case CS5: uart_mc = UART_LCR_WLEN5; break;
++	case CS6: uart_mc = UART_LCR_WLEN6; break;
++	case CS7: uart_mc = UART_LCR_WLEN7; break;
++	default:  uart_mc = UART_LCR_WLEN8; break; // CS8
++	}
++	if (cflag & CSTOPB)
++		uart_mc|= UART_LCR_STOP;
++	if (cflag & PARENB) {
++		uart_mc |= UART_LCR_EVEN;
++		if (!(cflag & PARODD))
++			uart_mc |= UART_LCR_ODD;
++	}
++
++	port->read_status_mask = UART_LSR_OE;
++	if (iflag & INPCK)
++		port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++	if (iflag & (BRKINT | PARMRK))
++		port->read_status_mask |= UART_LSR_BI;
++
++	/*
++	 * Characters to ignore
++	 */
++	port->ignore_status_mask = 0;
++	if (iflag & IGNPAR)
++		port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
++	if (iflag & IGNBRK) {
++		port->ignore_status_mask |= UART_LSR_BI;
++		/*
++		 * If we're ignoring parity and break indicators,
++		 * ignore overruns to (for real raw support).
++		 */
++		if (iflag & IGNPAR)
++			port->ignore_status_mask |= UART_LSR_OE;
++	}
++
++	/* first, disable everything */
++	save_flags(flags); cli();
++	old_ier = UART_GET_IER(port);
++
++	if ((port->flags & ASYNC_HARDPPS_CD) ||
++	    (cflag & CRTSCTS) || !(cflag & CLOCAL))
++		old_ier |= UART_IER_MSI;
++
++	/* Set baud rate */
++	quot = quot / 13;
++	UART_PUT_LCR(port, UART_LCR_DLAB);
++	UART_PUT_DIV_LO(port, (quot & 0xff));
++	UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
++
++	UART_PUT_LCR(port, uart_mc);
++//	UART_PUT_LCR(port, 0x07); // ???? it is wired
++        UART_PUT_MCR(port, 0x08);
++        UART_PUT_FCR(port, 0x01);
++	UART_PUT_IER(port, 0x05);
++
++	restore_flags(flags);
++}
++
++static int it8712_startup(struct uart_port *port, struct uart_info *info)
++{
++	int retval;
++	unsigned int regs;
++
++//        printk("it8712 startup : \n");
++
++	/*
++	 * Use iobase to store a pointer to info. We need this to start a
++	 * transmission as the tranmittr interrupt is only generated on
++	 * the transition to the idle state
++	 */
++
++	port->iobase=(u_int)info;
++
++	/*
++	 * Allocate the IRQ
++	 */
++	retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", info);
++	if (retval)
++		return retval;
++
++        /* setup interrupt controller  */
++        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs |= (IRQ_SERIRQ0_MASK);
++        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        regs = *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_SERIRQ0_MASK);
++        *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_SERIRQ0_MASK);
++
++	/*
++	 * Finally, enable interrupts. Use the TII interrupt to minimise
++	 * the number of interrupts generated. If higher performance is
++	 * needed, consider using the TI interrupt with a suitable FIFO
++	 * threshold
++	 */
++	UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
++
++	return 0;
++}
++
++static void it8712_shutdown(struct uart_port *port, struct uart_info *info)
++{
++//        printk("it8712 shutdown : \n");
++
++	/*
++	 * disable all interrupts, disable the port
++	 */
++	UART_PUT_IER(port, 0x0);
++
++	/* disable break condition and fifos */
++//	UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
++
++	/*
++	 * Free the interrupt
++	 */
++	free_irq(port->irq, info);
++}
++
++static const char *it8712_type(struct uart_port *port)
++{
++	return port->type == PORT_IT8712 ? "IT8712" : NULL;
++}
++
++/*
++ * Release the memory region(s) being used by 'port'
++ */
++static void it8712_release_port(struct uart_port *port)
++{
++//        printk("it8712 release port : \n");
++
++	release_mem_region(port->mapbase, UART_PORT_SIZE);
++}
++
++/*
++ * Request the memory region(s) being used by 'port'
++ */
++static int it8712_request_port(struct uart_port *port)
++{
++	return request_mem_region(port->mapbase, UART_PORT_SIZE,
++				    "serial_it8712") != NULL ? 0 : -EBUSY;
++}
++
++/*
++ * Configure/autoconfigure the port.
++ */
++static void it8712_config_port(struct uart_port *port, int flags)
++{
++
++	if (flags & UART_CONFIG_TYPE) {
++		if (it8712_request_port(port) == 0)
++			port->type = PORT_IT8712;
++	}
++}
++
++/*
++ * verify the new serial_struct (for TIOCSSERIAL).
++ */
++static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++	int ret = 0;
++
++	if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
++		ret = -EINVAL;
++	if (ser->irq < 0 || ser->irq >= NR_IRQS)
++		ret = -EINVAL;
++	if (ser->baud_base < 9600)
++		ret = -EINVAL;
++	return ret;
++}
++
++static struct uart_ops it8712_pops = {
++	tx_empty:	it8712_tx_empty,
++	set_mctrl:	it8712_set_mctrl_null,
++	get_mctrl:	it8712_get_mctrl,
++	stop_tx:	it8712_stop_tx,
++	start_tx:	it8712_start_tx,
++	stop_rx:	it8712_stop_rx,
++	enable_ms:	it8712_enable_ms,
++	break_ctl:	it8712_break_ctl,
++	startup:	it8712_startup,
++	shutdown:	it8712_shutdown,
++	change_speed:	it8712_change_speed,
++	type:		it8712_type,
++	release_port:	it8712_release_port,
++	request_port:	it8712_request_port,
++	config_port:	it8712_config_port,
++	verify_port:	it8712_verify_port,
++};
++
++#ifdef CONFIG_ARCH_SL2312
++
++static struct uart_port it8712_ports[UART_NR] = {
++	{
++		membase:	(void *)0,
++		mapbase:	0,
++		iotype:		SERIAL_IO_MEM,
++		irq:		0,
++		uartclk:	UART_CLK/2,
++		fifosize:	16,
++		ops:		&it8712_pops,
++		flags:		ASYNC_BOOT_AUTOCONF,
++	}
++};
++
++#endif
++
++#ifdef CONFIG_SERIAL_IT8712_CONSOLE
++#ifdef used_and_not_const_char_pointer
++static int it8712_console_read(struct uart_port *port, char *s, u_int count)
++{
++	unsigned int status;
++	int c;
++#ifdef DEBUG
++	printk("it8712_console_read() called\n");
++#endif
++
++	c = 0;
++	while (c < count) {
++		status = UART_GET_LSR(port);
++ 		if (UART_RX_DATA(status)) {
++			*s++ = UART_GET_CHAR(port);
++			c++;
++		} else {
++			// nothing more to get, return
++			return c;
++		}
++	}
++	// return the count
++	return c;
++}
++#endif
++static void it8712_console_write(struct console *co, const char *s, unsigned count)
++{
++#ifdef CONFIG_ARCH_SL2312
++	struct uart_port *port = it8712_ports + co->index;
++	unsigned int status, old_ies;
++	int i;
++
++	/*
++	 *	First save the CR then disable the interrupts
++	 */
++	old_ies = UART_GET_IER(port);
++	UART_PUT_IER(port,0x0);
++
++	/*
++	 *	Now, do each character
++	 */
++	for (i = 0; i < count; i++) {
++		do {
++			status = UART_GET_LSR(port);
++		} while (!UART_TX_READY(status));
++		UART_PUT_CHAR(port, s[i]);
++		if (s[i] == '\n') {
++			do {
++				status = UART_GET_LSR(port);
++			} while (!UART_TX_READY(status));
++			UART_PUT_CHAR(port, '\r');
++		}
++	}
++
++	/*
++	 *	Finally, wait for transmitter to become empty
++	 *	and restore the IES
++	 */
++	do {
++		status = UART_GET_LSR(port);
++	} while (!(status&UART_LSR_THRE));
++	UART_PUT_IER(port, old_ies);
++#endif
++}
++
++static kdev_t it8712_console_device(struct console *co)
++{
++	return MKDEV(SERIAL_IT8712_MAJOR, SERIAL_IT8712_MINOR + co->index);
++}
++
++static int it8712_console_wait_key(struct console *co)
++{
++#ifdef CONFIG_ARCH_SL2312
++	struct uart_port *port = (it8712_ports + co->index);
++	unsigned int status;
++
++	do {
++		status = UART_GET_LSR(port);
++	} while (!UART_RX_DATA(status));
++	return UART_GET_CHAR(port);
++#else
++	return 0;
++#endif
++}
++
++static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
++{
++	printk("it8712 console get options : \n");
++
++	u_int uart_mc, quot;
++	uart_mc= UART_GET_MCR(port);
++
++	*parity = 'n';
++	if (uart_mc & UART_LCR_PARITY) {
++		if (uart_mc & UART_LCR_EVEN)
++			*parity = 'e';
++		else
++			*parity = 'o';
++	}
++
++	switch (uart_mc & UART_LCR_MSK){
++
++	case UART_LCR_WLEN5:
++		*bits = 5;
++		break;
++	case UART_LCR_WLEN6:
++		*bits = 6;
++		break;
++	case UART_LCR_WLEN7:
++		*bits = 7;
++		break;
++	case UART_LCR_WLEN8:
++		*bits = 8;
++		break;
++	}
++	UART_PUT_MCR(port,UART_LCR_DLAB);
++	quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
++	UART_PUT_MCR(port,uart_mc);
++	*baud = (port->uartclk / (16 *quot));
++}
++
++static int __init it8712_console_setup(struct console *co, char *options)
++{
++	struct uart_port *port;
++	int baud = 38400;
++	int bits = 8;
++	int parity = 'n';
++	int flow= 'n';
++	int base, irq;
++	int i ;
++
++//	printk("it8712 console setup : \n");
++
++	LPCSetConfig(0, 0x02, 0x01);
++        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
++        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
++	base = IT8712_IO_BASE;
++	base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
++	it8712_ports[0].mapbase = base;
++	it8712_ports[0].membase = IO_ADDRESS(base);
++	it8712_ports[0].irq = IRQ_SERIRQ0_OFFSET;
++       	irq = LPCGetConfig(LDN_SERIAL1, 0x70);
++	it8712_ports[0].irq += irq;
++
++	printk("it8712 irq is %x %x \n", it8712_ports[0].irq, irq);
++
++	// setup LPC Host 'quiet mode'
++	*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
++	for(i=0;i<1000;i++) ;						// delay
++	*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
++
++#ifdef CONFIG_ARCH_SL2312
++	/*
++	 * Check whether an invalid uart number has been specified, and
++	 * if so, search for the first available port that does have
++	 * console support.
++	 */
++	port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
++#else
++	return -ENODEV;
++#endif
++
++	if (options)
++		uart_parse_options(options, &baud, &parity, &bits, &flow);
++	else
++		it8712_console_get_options(port, &baud, &parity, &bits);
++
++	return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++static struct console it8712_console = {
++	name:           SERIAL_IT8712_NAME,
++	write:		it8712_console_write,
++#ifdef used_and_not_const_char_pointer
++	read:		it8712_console_read,
++#endif
++	device:		it8712_console_device,
++//	wait_key:	it8712_console_wait_key,
++	setup:		it8712_console_setup,
++	flags:		(CON_PRINTBUFFER|CON_ENABLED),
++	index:		-1,
++};
++
++void __init it8712_console_init(void)
++{
++	register_console(&it8712_console);
++}
++
++#define IT8712_CONSOLE	&it8712_console
++#else
++#define IT8712_CONSOLE	NULL
++#endif
++
++static struct uart_driver it8712_reg = {
++	owner:                  NULL,
++	normal_major:		SERIAL_IT8712_MAJOR,
++	normal_name:		SERIAL_IT8712_NAME,
++	normal_driver:		&normal,
++	callout_major:		CALLOUT_IT8712_MAJOR,
++	callout_name:		CALLOUT_IT8712_NAME,
++	callout_driver:		&callout,
++	table:			it8712_table,
++	termios:		it8712_termios,
++	termios_locked:		it8712_termios_locked,
++	minor:			SERIAL_IT8712_MINOR,
++	nr:			UART_NR,
++#ifdef CONFIG_ARCH_SL2312
++	port:			it8712_ports,
++#endif
++	state:			NULL,
++	cons:			IT8712_CONSOLE,
++};
++
++static int __init it8712_init(void)
++{
++//	printk("serial_it8712: it871212_init \n");
++
++	return uart_register_driver(&it8712_reg);
++}
++
++
++__initcall(it8712_init);
+Index: linux-2.6.23.16/drivers/serial/serial_sl2312.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23.16/drivers/serial/serial_sl2312.c	2008-03-17 12:30:50.290536619 +0200
+@@ -0,0 +1,827 @@
++/*
++ *  linux/drivers/char/serial_uart00.c
++ *
++ *  Driver for UART00 serial ports
++ *
++ *  Based on drivers/char/serial_amba.c, by ARM Limited &
++ *                                          Deep Blue Solutions Ltd.
++ *  Copyright 2001 Altera Corporation
++ *
++ * 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: serial_sl2312.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
++ *
++ */
++#include <linux/module.h>
++
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/major.h>
++#include <linux/string.h>
++#include <linux/fcntl.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/circ_buf.h>
++#include <linux/serial.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++#include <linux/serial_core.h>
++
++#include <asm/system.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
++#include <asm/sizes.h>
++#include <linux/spinlock.h>
++#include <linux/irq.h>
++
++
++#if defined(CONFIG_SERIAL_SL2312_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <asm/arch/sl2312.h>
++#define UART_TYPE (volatile unsigned int*)
++#include <asm/arch/uart.h>
++#include <asm/arch/int_ctrl.h>
++
++// #define DEBUG           1
++#define UART_NR		1
++
++
++#define SERIAL_SL2312_NAME	"ttySL"
++#define SERIAL_SL2312_MAJOR	204
++#define SERIAL_SL2312_MINOR	40      /* Temporary - will change in future */
++#define SERIAL_SL2312_NR	UART_NR
++#define UART_PORT_SIZE 0x50
++
++#define SL2312_NO_PORTS         UART_NR
++#define SL2312_ISR_PASS_LIMIT	256
++
++/*
++ * Access macros for the SL2312 UARTs
++ */
++#define UART_GET_INT_STATUS(p)	(inl(UART_IIR((p)->membase)) & 0x0F)      // interrupt identification
++#define UART_PUT_IER(p, c)      outl(c,UART_IER((p)->membase))    // interrupt enable
++#define UART_GET_IER(p)         inl(UART_IER((p)->membase))
++#define UART_PUT_CHAR(p, c)     outl(c,UART_THR((p)->membase))    // transmitter holding
++#define UART_GET_CHAR(p)        inl(UART_RBR((p)->membase))       // receive buffer
++#define UART_GET_LSR(p)         inl(UART_LSR((p)->membase))       // line status
++#define UART_GET_MSR(p)         inl(UART_MSR((p)->membase))       // modem status
++#define UART_GET_MCR(p)         inl(UART_MCR((p)->membase))       // modem control
++#define UART_PUT_MCR(p, c)      outl(c,UART_MCR((p)->membase))
++#define UART_GET_LCR(p)         inl(UART_LCR((p)->membase))       // mode control
++#define UART_PUT_LCR(p, c)      outl(c,UART_LCR((p)->membase))
++#define UART_GET_DIV_HI(p)	inl(UART_DIV_HI((p)->membase))
++#define UART_PUT_DIV_HI(p, c)	outl(c,UART_DIV_HI((p)->membase))
++#define UART_GET_DIV_LO(p)	inl(UART_DIV_LO((p)->membase))
++#define UART_PUT_DIV_LO(p, c)	outl(c,UART_DIV_LO((p)->membase))
++#define UART_PUT_MDR(p, c)      outl(c,UART_MDR((p)->membase))
++#define UART_RX_DATA(s)		((s) & UART_LSR_DR)
++#define UART_TX_READY(s)	((s) & UART_LSR_THRE)
++
++
++static void sl2312_stop_tx(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("sl2312 stop tx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_TE);
++	UART_PUT_IER(port, reg);
++}
++
++static void sl2312_stop_rx(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("sl2312 stop rx : \n");
++        reg = UART_GET_IER(port);
++        reg &= ~(UART_IER_DR);
++	UART_PUT_IER(port, reg);
++
++}
++
++static void sl2312_enable_ms(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("sl2312 enable ms : \n");
++
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_MS);
++	UART_PUT_IER(port, reg);
++
++}
++
++static void
++sl2312_rx_chars(struct uart_port *port)
++{
++	struct tty_struct *tty = port->info->tty;
++	unsigned int status, mask, ch, flg, ignored = 0;
++
++
++ //       printk("sl2312_rx_chars : \n");
++	status = UART_GET_LSR(port);
++	while (UART_RX_DATA(status)) {
++
++		/*
++		 * We need to read rds before reading the
++		 * character from the fifo
++		 */
++		ch = UART_GET_CHAR(port);
++		port->icount.rx++;
++
++		//if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++		if (tty && !tty_buffer_request_room(tty, 1))
++			goto ignore_char;
++
++		flg = TTY_NORMAL;
++
++		/*
++		 * Note that the error handling code is
++		 * out of the main execution path
++		 */
++
++		if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
++			goto handle_error;
++		if (uart_handle_sysrq_char(port, ch))
++			goto ignore_char;
++
++	error_return:
++		//*tty->flip.flag_buf_ptr++ = flg;
++		//*tty->flip.char_buf_ptr++ = ch;
++		//tty->flip.count++;
++		tty_insert_flip_char(tty, ch, flg);
++	ignore_char:
++		status = UART_GET_LSR(port);
++	} // end of while
++out:
++	tty_flip_buffer_push(tty);
++	return;
++
++handle_error:
++	if (status & UART_LSR_BI) {
++		status &= ~(UART_LSR_FE);
++		port->icount.brk++;
++
++#ifdef SUPPORT_SYSRQ
++		if (uart_handle_break(port))
++			goto ignore_char;
++#endif
++	} else if (status & UART_LSR_PE)
++		port->icount.parity++;
++	else if (status & UART_LSR_FE)
++		port->icount.frame++;
++
++	if (status & UART_LSR_OE)
++		port->icount.overrun++;
++
++	if (status & port->ignore_status_mask) {
++		if (++ignored > 100)
++			goto out;
++		goto ignore_char;
++	}
++
++	mask = status & port->read_status_mask;
++
++	if (mask & UART_LSR_BI)
++		flg = TTY_BREAK;
++	else if (mask & UART_LSR_PE)
++		flg = TTY_PARITY;
++	else if (mask & UART_LSR_FE)
++		flg = TTY_FRAME;
++
++	if (status & UART_LSR_OE) {
++		/*
++		 * CHECK: does overrun affect the current character?
++		 * ASSUMPTION: it does not.
++		 */
++		//*tty->flip.flag_buf_ptr++ = flg;
++		//*tty->flip.char_buf_ptr++ = ch;
++		//tty->flip.count++;
++
++		tty_insert_flip_char(tty, 0, TTY_BREAK);
++
++		// if (tty->flip.count >= TTY_FLIPBUF_SIZE)
++		if (tty_buffer_request_room(tty, 1))
++			goto ignore_char;
++		ch = 0;
++		flg = TTY_OVERRUN;
++	}
++#ifdef SUPPORT_SYSRQ
++	port->sysrq = 0;
++#endif
++	goto error_return;
++}
++
++static void sl2312_tx_chars(struct uart_port *port)
++{
++	struct circ_buf *xmit = &port->info->xmit;
++	int count;
++
++
++	if (port->x_char) {
++		while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++		UART_PUT_CHAR(port, port->x_char);
++		port->icount.tx++;
++		port->x_char = 0;
++
++		return;
++	}
++	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
++		sl2312_stop_tx(port);
++
++		return;
++	}
++
++	count = port->fifosize >> 1;
++	do {
++		while(!(UART_GET_LSR(port)&UART_LSR_THRE));
++		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
++		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++		port->icount.tx++;
++		if (uart_circ_empty(xmit))
++			break;
++	} while (--count > 0);
++
++	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++		uart_write_wakeup(port);
++
++	if (uart_circ_empty(xmit))
++		sl2312_stop_tx(port);
++
++}
++
++static void sl2312_start_tx(struct uart_port *port)
++{
++        unsigned int reg;
++
++//        printk("sl2312 start tx : \n");
++        reg = UART_GET_IER(port);
++        reg |= (UART_IER_TE);
++	UART_PUT_IER(port, reg);
++
++	sl2312_tx_chars(port);
++}
++
++static void sl2312_modem_status(struct uart_port *port)
++{
++	unsigned int status;
++
++//        printk("it8712 modem status : \n");
++
++	status = UART_GET_MSR(port);
++
++	if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
++		       UART_MSR_TERI | UART_MSR_DDCD)))
++		return;
++
++        if (status & UART_MSR_DDCD)
++                uart_handle_dcd_change(port, status & UART_MSR_DCD);
++
++        if (status & UART_MSR_DDSR)
++                port->icount.dsr++;
++
++        if (status & UART_MSR_DCTS)
++                uart_handle_cts_change(port, status & UART_MSR_CTS);
++
++	wake_up_interruptible(&port->info->delta_msr_wait);
++
++}
++
++static irqreturn_t sl2312_int(int irq, void *dev_id)
++{
++	struct uart_port *port = dev_id;
++	unsigned int status, pass_counter = 0;
++
++	status = UART_GET_INT_STATUS(port);
++	do {
++		switch(status)
++		{
++		   case UART_IIR_DR:
++		   case UART_IIR_RLS:
++			sl2312_rx_chars(port);
++		   break;
++		   case UART_IIR_TE:
++			sl2312_tx_chars(port);
++		   break;
++		   case UART_IIR_MODEM:
++			sl2312_modem_status(port);
++		   break;
++		   default:
++		   break;
++		}
++		if (pass_counter++ > SL2312_ISR_PASS_LIMIT)
++			break;
++
++		status = UART_GET_INT_STATUS(port);
++	} while (status);
++
++	return IRQ_HANDLED;
++}
++
++static u_int sl2312_tx_empty(struct uart_port *port)
++{
++//        printk("sl2312 tx empty : \n");
++
++	return ((UART_GET_LSR(port) & UART_LSR_TE)? TIOCSER_TEMT : 0);
++}
++
++static u_int sl2312_get_mctrl(struct uart_port *port)
++{
++	unsigned int result = 0;
++	unsigned int status;
++
++//        printk("sl2312 get mctrl : \n");
++
++	status = UART_GET_MSR(port);
++	if (status & UART_MSR_DCD)
++		result |= TIOCM_CAR;
++	if (status & UART_MSR_DSR)
++		result |= TIOCM_DSR;
++	if (status & UART_MSR_CTS)
++		result |= TIOCM_CTS;
++	if (status & UART_MSR_RI)
++		result |= TIOCM_RI;
++
++	return result;
++}
++
++static void sl2312_set_mctrl_null(struct uart_port *port, u_int mctrl)
++{
++}
++
++static void sl2312_break_ctl(struct uart_port *port, int break_state)
++{
++	unsigned int lcr;
++
++//        printk("sl2312 break ctl : \n");
++
++	lcr = UART_GET_LCR(port);
++	if (break_state == -1)
++		lcr |= UART_LCR_SETBREAK;
++	else
++		lcr &= ~UART_LCR_SETBREAK;
++	UART_PUT_LCR(port, lcr);
++}
++
++static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
++{
++	u_int quot;
++
++	/* Special case: B0 rate */
++	if (!baud)
++		baud = 9600;
++
++	quot = (port->uartclk / (16 * baud)-1)  ;
++
++	return quot;
++}
++
++static void sl2312_set_termios(struct uart_port *port, struct ktermios *termios,
++                               struct ktermios *old)
++{
++	unsigned int  uart_mc, old_ier, baud, quot;
++	unsigned long flags;
++
++        termios->c_cflag |= CREAD;
++#ifdef DEBUG
++	printk("it8712_set_cflag(0x%x) called\n", cflag);
++#endif
++        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
++        quot = (port->uartclk / (16 * baud))  ;
++        //uart_get_divisor(port, baud);
++
++	/* byte size and parity */
++	switch (termios->c_cflag & CSIZE) {
++	case CS5:
++              uart_mc = UART_LCR_LEN5;
++              break;
++	case CS6:
++              uart_mc = UART_LCR_LEN6;
++              break;
++	case CS7:
++              uart_mc = UART_LCR_LEN7;
++              break;
++	default: // CS8
++              uart_mc = UART_LCR_LEN8;
++              break;
++	}
++
++	if (termios->c_cflag & CSTOPB)
++		uart_mc|= UART_LCR_STOP;
++	if (termios->c_cflag & PARENB) {
++		uart_mc |= UART_LCR_EVEN;
++		if (!(termios->c_cflag & PARODD))
++			uart_mc |= UART_LCR_ODD;
++	}
++
++    spin_lock_irqsave(&port->lock, flags);
++        /*
++         * Update the per-port timeout
++         */
++        uart_update_timeout(port, termios->c_cflag, baud);
++	port->read_status_mask = UART_LSR_OE;
++	if (termios->c_iflag & INPCK)
++		port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++	if (termios->c_iflag & (BRKINT | PARMRK))
++		port->read_status_mask |= UART_LSR_BI;
++
++	/*
++	 * Characters to ignore
++	 */
++	port->ignore_status_mask = 0;
++	if (termios->c_iflag & IGNPAR)
++		port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
++	if (termios->c_iflag & IGNBRK) {
++		port->ignore_status_mask |= UART_LSR_BI;
++		/*
++		 * If we're ignoring parity and break indicators,
++		 * ignore overruns to (for real raw support).
++		 */
++		if (termios->c_iflag & IGNPAR)
++			port->ignore_status_mask |= UART_LSR_OE;
++	}
++
++	//save_flags(flags); cli();
++	old_ier = UART_GET_IER(port);
++
++        if(UART_ENABLE_MS(port, termios->c_cflag))
++             old_ier |= UART_IER_MS;
++
++	/* Set baud rate */
++	UART_PUT_LCR(port, UART_LCR_DLAB);
++	UART_PUT_DIV_LO(port, (quot & 0xff));
++	UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
++
++	UART_PUT_LCR(port, uart_mc);
++	UART_PUT_IER(port, old_ier);
++
++	//restore_flags(flags);
++	spin_unlock_irqrestore(&port->lock, flags);
++}
++
++
++
++static int sl2312_startup(struct uart_port *port)
++{
++	int retval;
++	unsigned int regs;
++
++//        printk("sl2312 startup : \n");
++
++	/*
++	 * Use iobase to store a pointer to info. We need this to start a
++	 * transmission as the tranmittr interrupt is only generated on
++	 * the transition to the idle state
++	 */
++
++	/*
++	 * Allocate the IRQ
++	 */
++	retval = request_irq(port->irq, sl2312_int, IRQF_DISABLED, "sl2312", port);
++	if (retval)
++		return retval;
++
++        /* setup interrupt controller  */
++        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_UART_MASK);
++        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
++        regs &= ~(IRQ_UART_MASK);
++        *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
++        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_UART_MASK);
++
++	/*
++	 * Finally, enable interrupts. Use the TII interrupt to minimise
++	 * the number of interrupts generated. If higher performance is
++	 * needed, consider using the TI interrupt with a suitable FIFO
++	 * threshold
++	 */
++	UART_PUT_IER(port, (UART_IER_DR|UART_IER_TE));
++
++	return 0;
++}
++
++static void sl2312_shutdown(struct uart_port *port)
++{
++//        printk("sl2312 shutdown : \n");
++
++	/*
++	 * disable all interrupts, disable the port
++	 */
++	UART_PUT_IER(port, 0x0);
++
++	/* disable break condition and fifos */
++//	UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
++
++	/*
++	 * Free the interrupt
++	 */
++	free_irq(port->irq, port);
++}
++
++static const char *sl2312_type(struct uart_port *port)
++{
++	return port->type == PORT_SL2312 ? "SL2312" : NULL;
++}
++
++/*
++ * Release the memory region(s) being used by 'port'
++ */
++static void sl2312_release_port(struct uart_port *port)
++{
++//        printk("sl2312 release port : \n");
++
++	release_mem_region(port->mapbase, UART_PORT_SIZE);
++}
++
++/*
++ * Request the memory region(s) being used by 'port'
++ */
++static int sl2312_request_port(struct uart_port *port)
++{
++	return request_mem_region(port->mapbase, UART_PORT_SIZE,
++				    "serial_sl2312") != NULL ? 0 : -EBUSY;
++}
++
++/*
++ * Configure/autoconfigure the port.
++ */
++static void sl2312_config_port(struct uart_port *port, int flags)
++{
++
++	if (flags & UART_CONFIG_TYPE) {
++		if (sl2312_request_port(port) == 0)
++			port->type = PORT_SL2312;
++	}
++}
++
++/*
++ * verify the new serial_struct (for TIOCSSERIAL).
++ */
++static int sl2312_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++	int ret = 0;
++
++	if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
++		ret = -EINVAL;
++	if (ser->irq < 0 || ser->irq >= NR_IRQS)
++		ret = -EINVAL;
++	if (ser->baud_base < 9600)
++		ret = -EINVAL;
++	return ret;
++}
++
++static struct uart_ops sl2312_pops = {
++	.tx_empty		=sl2312_tx_empty,
++	.set_mctrl		=sl2312_set_mctrl_null,
++	.get_mctrl		=sl2312_get_mctrl,
++	.stop_tx		=sl2312_stop_tx,
++	.start_tx		=sl2312_start_tx,
++	.stop_rx		=sl2312_stop_rx,
++	.enable_ms		=sl2312_enable_ms,
++	.break_ctl		=sl2312_break_ctl,
++	.startup		=sl2312_startup,
++	.shutdown		=sl2312_shutdown,
++	.set_termios	=sl2312_set_termios,
++	.type			=sl2312_type,
++	.release_port	=sl2312_release_port,
++	.request_port	=sl2312_request_port,
++	.config_port	=sl2312_config_port,
++	.verify_port	=sl2312_verify_port,
++};
++
++#ifdef CONFIG_ARCH_SL2312
++
++static struct uart_port sl2312_ports[UART_NR] = {
++	{
++		membase:	(void *)IO_ADDRESS(SL2312_UART_BASE),
++		mapbase:	SL2312_UART_BASE,
++		iotype:		SERIAL_IO_MEM,
++		irq:		IRQ_UART,
++		uartclk:	UART_CLK,
++		fifosize:	16,
++		ops:		&sl2312_pops,
++		flags:		ASYNC_BOOT_AUTOCONF,
++	}
++};
++
++#endif
++
++#ifdef CONFIG_SERIAL_SL2312_CONSOLE
++#ifdef used_and_not_const_char_pointer
++static int sl2312_console_read(struct uart_port *port, char *s, u_int count)
++{
++	unsigned int status;
++	int c;
++#ifdef DEBUG
++	printk("sl2312_console_read() called\n");
++#endif
++
++	c = 0;
++	while (c < count) {
++		status = UART_GET_LSR(port);
++ 		if (UART_RX_DATA(status)) {
++			*s++ = UART_GET_CHAR(port);
++			c++;
++		} else {
++			// nothing more to get, return
++			return c;
++		}
++	}
++	// return the count
++	return c;
++}
++#endif
++static void sl2312_console_write(struct console *co, const char *s, unsigned count)
++{
++#ifdef CONFIG_ARCH_SL2312
++	struct uart_port *port = sl2312_ports + co->index;
++	unsigned int status, old_ies;
++	int i;
++
++	/*
++	 *	First save the CR then disable the interrupts
++	 */
++	old_ies = UART_GET_IER(port);
++	UART_PUT_IER(port,0x0);
++
++	/*
++	 *	Now, do each character
++	 */
++	for (i = 0; i < count; i++) {
++		do {
++			status = UART_GET_LSR(port);
++		} while (!UART_TX_READY(status));
++		UART_PUT_CHAR(port, s[i]);
++		if (s[i] == '\n') {
++			do {
++				status = UART_GET_LSR(port);
++			} while (!UART_TX_READY(status));
++			UART_PUT_CHAR(port, '\r');
++		}
++	}
++
++	/*
++	 *	Finally, wait for transmitter to become empty
++	 *	and restore the IES
++	 */
++	do {
++		status = UART_GET_LSR(port);
++	} while (!(status&UART_LSR_TE));
++	UART_PUT_IER(port, old_ies);
++#endif
++}
++
++#if 0
++static void sl2312_console_device(struct console *co,int *index)
++{
++
++	struct uart_driver *p = co->data;
++    *index = co->index;
++    return p->tty_driver;
++
++}
++#endif
++
++static void /*__init*/ sl2312_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
++{
++//	printk("sl2312 console get options : \n");
++
++	u_int uart_mc, quot;
++	uart_mc= UART_GET_MCR(port);
++
++	*parity = 'n';
++	if (uart_mc & UART_LCR_PE) {
++		if (uart_mc & UART_LCR_EVEN)
++			*parity = 'e';
++		else
++			*parity = 'o';
++	}
++
++	switch (uart_mc & UART_LCR_MSK){
++
++	case UART_LCR_LEN5:
++		*bits = 5;
++		break;
++	case UART_LCR_LEN6:
++		*bits = 6;
++		break;
++	case UART_LCR_LEN7:
++		*bits = 7;
++		break;
++	case UART_LCR_LEN8:
++		*bits = 8;
++		break;
++	}
++	UART_PUT_MCR(port,UART_LCR_DLAB);
++	quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
++	UART_PUT_MCR(port,uart_mc);
++	*baud = port->uartclk / (16 *quot );
++}
++
++static int __init sl2312_console_setup(struct console *co, char *options)
++{
++	struct uart_port *port;
++	int baud = 19200;
++	int bits = 8;
++	int parity = 'n';
++	int flow= 'n';
++
++	printk("sl2312 console setup : \n");
++
++#ifdef CONFIG_ARCH_SL2312
++	/*
++	 * Check whether an invalid uart number has been specified, and
++	 * if so, search for the first available port that does have
++	 * console support.
++	 */
++	port = uart_get_console(sl2312_ports,SL2312_NO_PORTS,co);
++#else
++	return -ENODEV;
++#endif
++
++	if (options)
++		uart_parse_options(options, &baud, &parity, &bits, &flow);
++	else
++		sl2312_console_get_options(port, &baud, &parity, &bits);
++
++	return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++extern struct uart_driver sl2312_reg;
++static struct console sl2312_console = {
++	.name      = SERIAL_SL2312_NAME,
++	.write		= sl2312_console_write,
++	.device		= uart_console_device,
++//	.device		= sl2312_console_device,
++	.setup		= sl2312_console_setup,
++//	.flags		= (CON_PRINTBUFFER|CON_ENABLED),
++	.flags		= CON_PRINTBUFFER,
++	.index		= -1,
++	.data       = &sl2312_reg,
++};
++
++static int __init sl2312_console_init(void)
++{
++	register_console(&sl2312_console);
++	return 0;
++
++}
++
++console_initcall(sl2312_console_init);
++
++#define SL2312_CONSOLE	&sl2312_console
++#else
++#define SL2312_CONSOLE	NULL
++#endif
++
++// static
++struct uart_driver sl2312_reg = {
++	.owner         = NULL,
++	.driver_name	= SERIAL_SL2312_NAME,
++	.dev_name		= SERIAL_SL2312_NAME,
++	.major          = SERIAL_SL2312_MAJOR,
++	.minor			= SERIAL_SL2312_MINOR,
++	.nr				= UART_NR,
++	.cons			= SL2312_CONSOLE,
++};
++
++static int __init sl2312_init(void)
++{
++       int result;
++	//printk("serial_it8712: it871212_init \n");
++
++        result = uart_register_driver(&sl2312_reg);
++        if(result)
++             return result;
++	result = uart_add_one_port(&sl2312_reg, &sl2312_ports[0]);
++
++        return result;
++}
++
++
++__initcall(sl2312_init);
+Index: linux-2.6.23.16/include/linux/serial_core.h
+===================================================================
+--- linux-2.6.23.16.orig/include/linux/serial_core.h	2008-03-15 17:59:22.566564448 +0200
++++ linux-2.6.23.16/include/linux/serial_core.h	2008-03-15 17:59:53.568330991 +0200
+@@ -147,6 +147,10 @@
+ #define PORT_SB1250_DUART	77
+ 
+ 
++/* Storlink Soc */
++#define PORT_SL2312     72
++#define PORT_IT8712     73
++
+ #ifdef __KERNEL__
+ 
+ #include <linux/compiler.h>
+Index: linux-2.6.23.16/drivers/char/Makefile
+===================================================================
+--- linux-2.6.23.16.orig/drivers/char/Makefile	2008-03-15 17:59:22.566564448 +0200
++++ linux-2.6.23.16/drivers/char/Makefile	2008-03-17 12:19:43.252524398 +0200
+@@ -70,6 +70,16 @@
+ obj-$(CONFIG_APPLICOM)		+= applicom.o
+ obj-$(CONFIG_SONYPI)		+= sonypi.o
+ obj-$(CONFIG_RTC)		+= rtc.o
++
++###  for Storlink SoC ###
++obj-$(CONFIG_SL2312_RTC) += sl2312_rtc.o
++obj-$(CONFIG_IT8712_GPIO)   += it8712_gpio.o
++obj-$(CONFIG_GEMINI_GPIO)   += gemini_gpio.o
++obj-$(CONFIG_GEMINI_PWC) += gemini_pwr.o
++obj-$(CONFIG_GEMINI_CIR)    += gemini_cir.o
++obj-$(CONFIG_GEMINI_I2S)    += gemini_i2s.o
++obj-$(CONFIG_SL2312_WATCHDOG) += sl2312_wd.o
++
+ obj-$(CONFIG_HPET)		+= hpet.o
+ obj-$(CONFIG_GEN_RTC)		+= genrtc.o
+ obj-$(CONFIG_EFI_RTC)		+= efirtc.o
+Index: linux-2.6.23.16/drivers/serial/Kconfig
+===================================================================
+--- linux-2.6.23.16.orig/drivers/serial/Kconfig	2008-03-15 17:59:22.566564448 +0200
++++ linux-2.6.23.16/drivers/serial/Kconfig	2008-03-15 17:59:53.568330991 +0200
+@@ -280,6 +280,56 @@
+ 
+ comment "Non-8250 serial port support"
+ 
++config SERIAL_SL2312
++	bool "SL2312  serial port (sl2312) support"
++	depends on ARCH_SL2312
++	select SERIAL_CORE
++	select SERIAL_SL2312_CONSOLE
++	help
++         Say Y here if you want to use the hard logic uart on SWORD. This
++         driver also supports soft logic implentations of this uart core.
++
++config SERIAL_SL2312_CONSOLE
++	bool "Support for console on SL2312 serial port"
++	depends on SERIAL_SL2312
++	select SERIAL_CORE_CONSOLE
++	help
++        Say Y here if you want to support a serial console on an SWORD
++        hard logic uart or uart00 IP core.
++
++        Even if you say Y here, the currently visible virtual console
++        (/dev/tty0) will still be used as the system console by default, but
++        you can alter that using a kernel command line option such as
++        "console=ttySL0". (Try "man bootparam" or see the documentation of
++        your boot loader (lilo or loadlin) about how to pass options to the
++        kernel at boot time.)
++
++
++config SERIAL_IT8712
++	bool "Sl2312 serial port(IT8712) support"
++	depends on ARM && ARCH_SL2312 && SL2312_LPC
++	select SERIAL_CORE
++	select SERIAL_IT8712_CONSOLE
++	help
++	  Say Y here if you want to use the hard logic uart on Excalibur. This
++	  driver also supports soft logic implentations of this uart core.
++
++config SERIAL_IT8712_CONSOLE
++	bool "Support for console on Sword serial port(IT8712)"
++	depends on SERIAL_IT8712
++	select SERIAL_CORE_CONSOLE
++	help
++	  Say Y here if you want to support a serial console on an Excalibur
++	  hard logic uart or uart00 IP core.
++
++	  Even if you say Y here, the currently visible virtual console
++	  (/dev/tty0) will still be used as the system console by default, but
++	  you can alter that using a kernel command line option such as
++	  "console=ttySI0". (Try "man bootparam" or see the documentation of
++	  your boot loader (lilo or loadlin) about how to pass options to the
++	  kernel at boot time.)
++
++
+ config SERIAL_AMBA_PL010
+ 	tristate "ARM AMBA PL010 serial port support"
+ 	depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
+Index: linux-2.6.23.16/drivers/serial/Makefile
+===================================================================
+--- linux-2.6.23.16.orig/drivers/serial/Makefile	2008-03-15 17:59:22.566564448 +0200
++++ linux-2.6.23.16/drivers/serial/Makefile	2008-03-15 17:59:53.568330991 +0200
+@@ -62,5 +62,7 @@
+ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
+ obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
+ obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
++obj-$(CONFIG_SERIAL_IT8712) += it8712.o
++obj-$(CONFIG_SERIAL_SL2312) += serial_sl2312.o
+ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
+ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
-- 
cgit v1.2.3