90880d64674096a99681f5aea858f7a3a2f666f5
[openwrt.git] / target / linux / storm / patches / 1021-serial.patch
1 Index: linux-2.6.23.16/drivers/serial/it8712.c
2 ===================================================================
3 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
4 +++ linux-2.6.23.16/drivers/serial/it8712.c     2008-03-15 17:59:53.568330991 +0200
5 @@ -0,0 +1,858 @@
6 +/*
7 + *  linux/drivers/char/serial_uart00.c
8 + *
9 + *  Driver for UART00 serial ports
10 + *
11 + *  Based on drivers/char/serial_amba.c, by ARM Limited &
12 + *                                          Deep Blue Solutions Ltd.
13 + *  Copyright 2001 Altera Corporation
14 + *
15 + * This program is free software; you can redistribute it and/or modify
16 + * it under the terms of the GNU General Public License as published by
17 + * the Free Software Foundation; either version 2 of the License, or
18 + * (at your option) any later version.
19 + *
20 + * This program is distributed in the hope that it will be useful,
21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 + * GNU General Public License for more details.
24 + *
25 + * You should have received a copy of the GNU General Public License
26 + * along with this program; if not, write to the Free Software
27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 + *
29 + *  $Id: it8712.c,v 1.2 2006/06/06 06:36:04 middle Exp $
30 + *
31 + */
32 +#include <linux/module.h>
33 +#include <linux/tty.h>
34 +#include <linux/ioport.h>
35 +#include <linux/init.h>
36 +#include <linux/serial.h>
37 +#include <linux/console.h>
38 +#include <linux/sysrq.h>
39 +#include <asm/hardware.h>
40 +#include <asm/system.h>
41 +#include <asm/io.h>
42 +#include <asm/irq.h>
43 +#include <asm/uaccess.h>
44 +#include <asm/bitops.h>
45 +#include <asm/sizes.h>
46 +
47 +#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
48 +#define SUPPORT_SYSRQ
49 +#endif
50 +
51 +#include <linux/serial_core.h>
52 +#include <asm/arch/sl2312.h>
53 +#include <asm/arch/int_ctrl.h>
54 +#include <asm/arch/it8712.h>
55 +#include "it8712.h"
56 +
57 +//#define DEBUG           1
58 +#define UART_NR                1
59 +
60 +#define SERIAL_IT8712_NAME     "ttySI"
61 +#define SERIAL_IT8712_MAJOR    204
62 +#define SERIAL_IT8712_MINOR    41      /* Temporary - will change in future */
63 +#define SERIAL_IT8712_NR       UART_NR
64 +#define UART_PORT_SIZE 0x50
65 +#define LPC_HOST_CONTINUE_MODE 0x00000040
66 +
67 +#define IT8712_NO_PORTS         UART_NR
68 +#define IT8712_ISR_PASS_LIMIT  256
69 +
70 +#define LPC_BUS_CTRL   *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
71 +#define LPC_BUS_STATUS *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 4))
72 +#define LPC_SERIAL_IRQ_CTRL    *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 8))
73 +#define LPC_SERIAL_IRQ_STATUS  *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x0c))
74 +#define LPC_SERIAL_IRQ_TRITYPE *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x10))
75 +#define LPC_SERIAL_IRQ_POLARITY        *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x14))
76 +#define LPC_SERIAL_IRQ_ENABLE  *(unsigned int*)(IO_ADDRESS(SL2312_LPC_HOST_BASE + 0x18))
77 +
78 +
79 +
80 +
81 +/*
82 + * Access macros for the SL2312 UARTs
83 + */
84 +#define UART_GET_INT_STATUS(p) (inb(((p)->membase+UART_IIR)) & 0x0F)  // interrupt identification
85 +#define UART_PUT_IER(p, c)      outb(c,((p)->membase+UART_IER))         // interrupt enable
86 +#define UART_GET_IER(p)         inb(((p)->membase+UART_IER))
87 +#define UART_PUT_CHAR(p, c)     outb(c,((p)->membase+UART_TX))         // transmitter holding
88 +#define UART_GET_CHAR(p)        inb(((p)->membase+UART_RX))            // receive buffer
89 +#define UART_GET_LSR(p)         inb(((p)->membase+UART_LSR))            // line status
90 +#define UART_GET_MSR(p)         inb(((p)->membase+UART_MSR))            // modem status
91 +#define UART_GET_MCR(p)         inb(((p)->membase+UART_MCR))            // modem control
92 +#define UART_PUT_MCR(p, c)      outb(c,((p)->membase+UART_MCR))
93 +#define UART_GET_LCR(p)         inb(((p)->membase+UART_LCR))       // mode control
94 +#define UART_PUT_LCR(p, c)      outb(c,((p)->membase+UART_LCR))
95 +#define UART_PUT_FCR(p, c)      outb(c,((p)->membase+UART_FCR))       // fifo control
96 +#define UART_GET_DIV_HI(p)     inb(((p)->membase+UART_DLM))
97 +#define UART_PUT_DIV_HI(p, c)  outb(c,((p)->membase+UART_DLM))
98 +#define UART_GET_DIV_LO(p)     inb(((p)->membase+UART_DLL))
99 +#define UART_PUT_DIV_LO(p, c)  outb(c,((p)->membase+UART_DLL))
100 +#define UART_PUT_MDR(p, c)      outb(c,UART_MDR((p)->membase))
101 +#define UART_RX_DATA(s)                ((s) & UART_LSR_DR)
102 +#define UART_TX_READY(s)       ((s) & UART_LSR_THRE)
103 +
104 +static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
105 +{
106 +        unsigned int reg;
107 +
108 +        //printk("it8712 stop tx : \n");
109 +        reg = UART_GET_IER(port);
110 +        reg &= ~(UART_IER_THRI);
111 +       UART_PUT_IER(port, reg);
112 +}
113 +
114 +static void it8712_stop_rx(struct uart_port *port)
115 +{
116 +        unsigned int reg;
117 +
118 +        //printk("it8712 stop rx : \n");
119 +        reg = UART_GET_IER(port);
120 +        reg &= ~(UART_IER_RDI);
121 +       UART_PUT_IER(port, reg);
122 +
123 +}
124 +
125 +static void it8712_enable_ms(struct uart_port *port)
126 +{
127 +        unsigned int reg;
128 +
129 +        //printk("it8712 enable ms : \n");
130 +
131 +        reg = UART_GET_IER(port);
132 +        reg |= (UART_IER_MSI);
133 +       UART_PUT_IER(port, reg);
134 +
135 +}
136 +
137 +static void it8712_rx_chars(struct uart_port *port, struct pt_regs *regs)
138 +{
139 +       struct tty_struct *tty = port->info->tty;
140 +       unsigned int status, mask, ch, flg, ignored = 0;
141 +
142 + //       printk("it8712_rx_chars : \n");
143 +       status = UART_GET_LSR(port);
144 +       while (UART_RX_DATA(status)) {
145 +
146 +               /*
147 +                * We need to read rds before reading the
148 +                * character from the fifo
149 +                */
150 +               ch = UART_GET_CHAR(port);
151 +               port->icount.rx++;
152 +
153 +               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
154 +                       goto ignore_char;
155 +
156 +               flg = TTY_NORMAL;
157 +
158 +               /*
159 +                * Note that the error handling code is
160 +                * out of the main execution path
161 +                */
162 +
163 +               if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
164 +                       goto handle_error;
165 +               if (uart_handle_sysrq_char(port, ch, regs))
166 +                       goto ignore_char;
167 +
168 +       error_return:
169 +               *tty->flip.flag_buf_ptr++ = flg;
170 +               *tty->flip.char_buf_ptr++ = ch;
171 +               tty->flip.count++;
172 +       ignore_char:
173 +               status = UART_GET_LSR(port);
174 +       } // end of while
175 +out:
176 +       tty_flip_buffer_push(tty);
177 +       return;
178 +
179 +handle_error:
180 +       if (status & UART_LSR_BI) {
181 +               status &= ~(UART_LSR_FE);
182 +               port->icount.brk++;
183 +
184 +#ifdef SUPPORT_SYSRQ
185 +               if (uart_handle_break(port))
186 +                       goto ignore_char;
187 +#endif
188 +       } else if (status & UART_LSR_PE)
189 +               port->icount.parity++;
190 +       else if (status & UART_LSR_FE)
191 +               port->icount.frame++;
192 +
193 +       if (status & UART_LSR_OE)
194 +               port->icount.overrun++;
195 +
196 +       if (status & port->ignore_status_mask) {
197 +               if (++ignored > 100)
198 +                       goto out;
199 +               goto ignore_char;
200 +       }
201 +
202 +       mask = status & port->read_status_mask;
203 +
204 +       if (mask & UART_LSR_BI)
205 +               flg = TTY_BREAK;
206 +       else if (mask & UART_LSR_PE)
207 +               flg = TTY_PARITY;
208 +       else if (mask & UART_LSR_FE)
209 +               flg = TTY_FRAME;
210 +
211 +       if (status & UART_LSR_OE) {
212 +               /*
213 +                * CHECK: does overrun affect the current character?
214 +                * ASSUMPTION: it does not.
215 +                */
216 +               *tty->flip.flag_buf_ptr++ = flg;
217 +               *tty->flip.char_buf_ptr++ = ch;
218 +               tty->flip.count++;
219 +               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
220 +                       goto ignore_char;
221 +               ch = 0;
222 +               flg = TTY_OVERRUN;
223 +       }
224 +#ifdef SUPPORT_SYSRQ
225 +       port->sysrq = 0;
226 +#endif
227 +       goto error_return;
228 +}
229 +
230 +static void it8712_tx_chars(struct uart_port *port)
231 +{
232 +        struct circ_buf *xmit = &port->info->xmit;
233 +       int count;
234 +
235 +       if (port->x_char) {
236 +               while(!(UART_GET_LSR(port)&UART_LSR_THRE));
237 +               UART_PUT_CHAR(port, port->x_char);
238 +               port->icount.tx++;
239 +               port->x_char = 0;
240 +
241 +               return;
242 +       }
243 +       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
244 +               it8712_stop_tx(port, 0);
245 +               return;
246 +       }
247 +
248 +       count = port->fifosize >> 1;
249 +       do {
250 +               while(!(UART_GET_LSR(port)&UART_LSR_THRE));
251 +               UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
252 +               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
253 +               port->icount.tx++;
254 +               if (uart_circ_empty(xmit))
255 +                       break;
256 +       } while (--count > 0);
257 +
258 +       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
259 +               uart_write_wakeup(port);
260 +
261 +       if (uart_circ_empty(xmit))
262 +               it8712_stop_tx(port, 0);
263 +}
264 +
265 +static void it8712_start_tx(struct uart_port *port, unsigned int tty_start)
266 +{
267 +        unsigned int reg;
268 +
269 +        //printk("it8712 start tx : \n");
270 +        reg = UART_GET_IER(port);
271 +        reg |= (UART_IER_THRI);
272 +       UART_PUT_IER(port, reg);
273 +       it8712_tx_chars(port);
274 +}
275 +
276 +static void it8712_modem_status(struct uart_port *port)
277 +{
278 +       unsigned int status;
279 +
280 +//        printk("it8712 modem status : \n");
281 +
282 +       status = UART_GET_MSR(port);
283 +
284 +       if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
285 +                      UART_MSR_TERI | UART_MSR_DDCD)))
286 +               return;
287 +
288 +        if (status & UART_MSR_DDCD)
289 +                uart_handle_dcd_change(port, status & UART_MSR_DCD);
290 +
291 +        if (status & UART_MSR_DDSR)
292 +                port->icount.dsr++;
293 +
294 +        if (status & UART_MSR_DCTS)
295 +                uart_handle_cts_change(port, status & UART_MSR_CTS);
296 +
297 +       wake_up_interruptible(&port->info->delta_msr_wait);
298 +
299 +}
300 +
301 +static irqreturn_t  it8712_int(int irq, void *dev_id, struct pt_regs *regs)
302 +{
303 +       struct uart_port *port = dev_id;
304 +       unsigned int status, pass_counter = 0, data;
305 +
306 +
307 +               data = LPC_SERIAL_IRQ_STATUS;
308 +       if((data&0x10)==0x10)
309 +       {
310 +               status = UART_GET_INT_STATUS(port);
311 +               do {
312 +//                          printk("it8712_int: status %x \n", status);
313 +                       switch(status)
314 +                       {
315 +                          case UART_IIR_RDI:
316 +                          case UART_IIR_RLSI:
317 +                          case UART_IIR_RCTO:
318 +                               it8712_rx_chars(port, regs);
319 +                          break;
320 +                          case UART_IIR_THRI:
321 +                               it8712_tx_chars(port);
322 +                          break;
323 +                          case UART_IIR_MSI:
324 +                               it8712_modem_status(port);
325 +                          break;
326 +                          default:
327 +                          break;
328 +                       }
329 +                       if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
330 +                               break;
331 +
332 +                       status = UART_GET_INT_STATUS(port);
333 +               } while (status);
334 +       }
335 +
336 +               status = 0;
337 +        status |= (IRQ_LPC_MASK);
338 +        *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = status;
339 +
340 +       //cnt=0;
341 +       //do{
342 +       //      data = LPC_SERIAL_IRQ_STATUS;
343 +               LPC_SERIAL_IRQ_STATUS = data;
344 +       //      cnt++;
345 +       //}while(data);
346 +       //if(cnt>2)
347 +       //      printf("it8712_uart_Isr clear LPC_SERIAL_IRQ_STATUS %x \n", cnt);
348 +        return IRQ_HANDLED;
349 +}
350 +
351 +static u_int it8712_tx_empty(struct uart_port *port)
352 +{
353 +//        printk("it8712 tx empty : \n");
354 +
355 +       return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
356 +}
357 +
358 +static u_int it8712_get_mctrl(struct uart_port *port)
359 +{
360 +       unsigned int result = 0;
361 +       unsigned int status;
362 +
363 +//        printk("it8712 get mctrl : \n");
364 +
365 +       status = UART_GET_MSR(port);
366 +       if (status & UART_MSR_DCD)
367 +               result |= TIOCM_CAR;
368 +       if (status & UART_MSR_DSR)
369 +               result |= TIOCM_DSR;
370 +       if (status & UART_MSR_CTS)
371 +               result |= TIOCM_CTS;
372 +       if (status & UART_MSR_RI)
373 +               result |= TIOCM_RI;
374 +
375 +       return result;
376 +}
377 +
378 +static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
379 +{
380 +}
381 +
382 +static void it8712_break_ctl(struct uart_port *port, int break_state)
383 +{
384 +       unsigned int lcr;
385 +
386 +//        printk("it8712 break ctl : \n");
387 +
388 +       lcr = UART_GET_LCR(port);
389 +       if (break_state == -1)
390 +               lcr |= UART_LCR_SBC;
391 +       else
392 +               lcr &= ~UART_LCR_SBC;
393 +       UART_PUT_LCR(port, lcr);
394 +}
395 +
396 +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
397 +{
398 +       u_int quot;
399 +
400 +       /* Special case: B0 rate */
401 +       if (!baud)
402 +               baud = 9600;
403 +
404 +       quot = (port->uartclk/(16 * baud)) ;
405 +
406 +       return quot;
407 +}
408 +static void it8712_set_termios(struct uart_port *port, struct termios *termios,
409 +                               struct termios *old)
410 +{
411 +       unsigned int  uart_mc, old_ier, baud, quot;
412 +       unsigned long flags;
413 +
414 +        termios->c_cflag |= CREAD;
415 +        termios->c_cflag |= CLOCAL;
416 +#ifdef DEBUG
417 +       printk("it8712_set_cflag(0x%x) called\n", cflag);
418 +#endif
419 +        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
420 +        quot = uart_get_divisor(port, baud);
421 +
422 +       /* byte size and parity */
423 +       switch (termios->c_cflag & CSIZE) {
424 +       case CS5:
425 +              uart_mc = UART_LCR_WLEN5;
426 +              break;
427 +       case CS6:
428 +              uart_mc = UART_LCR_WLEN6;
429 +              break;
430 +       case CS7:
431 +              uart_mc = UART_LCR_WLEN7;
432 +              break;
433 +       default: // CS8
434 +              uart_mc = UART_LCR_WLEN8;
435 +              break;
436 +       }
437 +
438 +       if (termios->c_cflag & CSTOPB)
439 +               uart_mc|= UART_LCR_STOP;
440 +       if (termios->c_cflag & PARENB) {
441 +               uart_mc |= UART_LCR_EVEN;
442 +               if (!(termios->c_cflag & PARODD))
443 +                       uart_mc |= UART_LCR_ODD;
444 +       }
445 +
446 +        spin_lock_irqsave(&port->lock, flags);
447 +        /*
448 +         * Update the per-port timeout
449 +         */
450 +        uart_update_timeout(port, termios->c_cflag, baud);
451 +       port->read_status_mask = UART_LSR_OE;
452 +       if (termios->c_iflag & INPCK)
453 +               port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
454 +       if (termios->c_iflag & (BRKINT | PARMRK))
455 +               port->read_status_mask |= UART_LSR_BI;
456 +
457 +       /*
458 +        * Characters to ignore
459 +        */
460 +       port->ignore_status_mask = 0;
461 +       if (termios->c_iflag & IGNPAR)
462 +               port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
463 +       if (termios->c_iflag & IGNBRK) {
464 +               port->ignore_status_mask |= UART_LSR_BI;
465 +               /*
466 +                * If we're ignoring parity and break indicators,
467 +                * ignore overruns to (for real raw support).
468 +                */
469 +               if (termios->c_iflag & IGNPAR)
470 +                       port->ignore_status_mask |= UART_LSR_OE;
471 +       }
472 +
473 +       old_ier = UART_GET_IER(port);
474 +
475 +        if(UART_ENABLE_MS(port, termios->c_cflag))
476 +             old_ier |= UART_IER_MSI;
477 +
478 +       /* Set baud rate */
479 +       quot = quot / 13;
480 +       UART_PUT_LCR(port, UART_LCR_DLAB);
481 +       UART_PUT_DIV_LO(port, (quot & 0xff));
482 +       UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
483 +
484 +       UART_PUT_LCR(port, uart_mc);
485 +//     UART_PUT_LCR(port, 0x07); // ???? it is wired
486 +        UART_PUT_MCR(port, 0x08);
487 +        UART_PUT_FCR(port, 0x01);
488 +       UART_PUT_IER(port, 0x07);
489 +
490 +       spin_unlock_irqrestore(&port->lock, flags);
491 +}
492 +
493 +static int it8712_startup(struct uart_port *port)
494 +{
495 +       int retval, i;
496 +       unsigned int regs;
497 +
498 +        //printk("it8712 startup : \n");
499 +
500 +       /*
501 +        * Use iobase to store a pointer to info. We need this to start a
502 +        * transmission as the tranmittr interrupt is only generated on
503 +        * the transition to the idle state
504 +        */
505 +
506 +       //      regs = 0;
507 +    //    regs |= (IRQ_LPC_MASK);
508 +    //    *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
509 +
510 +       /*
511 +        * Allocate the IRQ
512 +        */
513 +       retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", port);
514 +       if (retval)
515 +               return retval;
516 +
517 +       //printk("Init LPC int...........\n");
518 +        /* setup interrupt controller  */
519 +        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
520 +        regs &= ~(IRQ_LPC_MASK);
521 +        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
522 +        regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
523 +        regs &= ~(IRQ_LPC_MASK);
524 +        *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
525 +        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_LPC_MASK);
526 +
527 +       LPC_SERIAL_IRQ_POLARITY = 0x10; //0x10; //0x02;
528 +       LPC_SERIAL_IRQ_TRITYPE = 0x10; //0x10;//
529 +       LPC_SERIAL_IRQ_ENABLE = 0x10;
530 +
531 +       LPC_BUS_CTRL = 0xc0;
532 +       LPC_SERIAL_IRQ_CTRL = 0xc0;
533 +       for(i=0;i<1000;i++) ;
534 +       LPC_SERIAL_IRQ_CTRL = 0x80;
535 +       /*
536 +        * Finally, enable interrupts. Use the TII interrupt to minimise
537 +        * the number of interrupts generated. If higher performance is
538 +        * needed, consider using the TI interrupt with a suitable FIFO
539 +        * threshold
540 +        */
541 +       //UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
542 +       UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI|UART_IER_RLSI));//middle
543 +
544 +       return 0;
545 +}
546 +
547 +static void it8712_shutdown(struct uart_port *port)
548 +{
549 +        //printk("it8712 shutdown : \n");
550 +
551 +       /*
552 +        * disable all interrupts, disable the port
553 +        */
554 +       UART_PUT_IER(port, 0x0);
555 +
556 +       /* disable break condition and fifos */
557 +//     UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
558 +
559 +       /*
560 +        * Free the interrupt
561 +        */
562 +       free_irq(port->irq, port);
563 +}
564 +
565 +static const char *it8712_type(struct uart_port *port)
566 +{
567 +       return port->type == PORT_IT8712 ? "IT8712" : NULL;
568 +}
569 +
570 +/*
571 + * Release the memory region(s) being used by 'port'
572 + */
573 +static void it8712_release_port(struct uart_port *port)
574 +{
575 +//        printk("it8712 release port : \n");
576 +
577 +       release_mem_region(port->mapbase, UART_PORT_SIZE);
578 +}
579 +
580 +/*
581 + * Request the memory region(s) being used by 'port'
582 + */
583 +static int it8712_request_port(struct uart_port *port)
584 +{
585 +       return request_mem_region(port->mapbase, UART_PORT_SIZE,
586 +                                   "serial_it8712") != NULL ? 0 : -EBUSY;
587 +}
588 +
589 +/*
590 + * Configure/autoconfigure the port.
591 + */
592 +static void it8712_config_port(struct uart_port *port, int flags)
593 +{
594 +
595 +       if (flags & UART_CONFIG_TYPE) {
596 +               if (it8712_request_port(port) == 0)
597 +                       port->type = PORT_IT8712;
598 +       }
599 +}
600 +
601 +/*
602 + * verify the new serial_struct (for TIOCSSERIAL).
603 + */
604 +static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
605 +{
606 +       int ret = 0;
607 +
608 +       if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
609 +               ret = -EINVAL;
610 +       if (ser->irq < 0 || ser->irq >= NR_IRQS)
611 +               ret = -EINVAL;
612 +       if (ser->baud_base < 9600)
613 +               ret = -EINVAL;
614 +       return ret;
615 +}
616 +
617 +static struct uart_ops it8712_pops = {
618 +       .tx_empty       = it8712_tx_empty,
619 +       .set_mctrl      = it8712_set_mctrl_null,
620 +       .get_mctrl      = it8712_get_mctrl,
621 +       .stop_tx        = it8712_stop_tx,
622 +       .start_tx       = it8712_start_tx,
623 +       .stop_rx        = it8712_stop_rx,
624 +       .enable_ms      = it8712_enable_ms,
625 +       .break_ctl      = it8712_break_ctl,
626 +       .startup        = it8712_startup,
627 +       .shutdown       = it8712_shutdown,
628 +       .set_termios    = it8712_set_termios,
629 +       .type           = it8712_type,
630 +       .release_port   = it8712_release_port,
631 +       .request_port   = it8712_request_port,
632 +       .config_port    = it8712_config_port,
633 +       .verify_port    = it8712_verify_port,
634 +};
635 +
636 +#ifdef CONFIG_ARCH_SL2312
637 +
638 +static struct uart_port it8712_ports[UART_NR] = {
639 +       {
640 +               membase:        (void *)0,
641 +               mapbase:        0,
642 +               iotype:         SERIAL_IO_MEM,
643 +               irq:            0,
644 +               uartclk:        UART_CLK/2,
645 +               fifosize:       16,
646 +               ops:            &it8712_pops,
647 +               flags:          ASYNC_BOOT_AUTOCONF,
648 +       }
649 +};
650 +
651 +#endif
652 +
653 +#ifdef CONFIG_SERIAL_IT8712_CONSOLE
654 +#ifdef used_and_not_const_char_pointer
655 +static int it8712_console_read(struct uart_port *port, char *s, u_int count)
656 +{
657 +       unsigned int status;
658 +       int c;
659 +#ifdef DEBUG
660 +       printk("it8712_console_read() called\n");
661 +#endif
662 +
663 +       c = 0;
664 +       while (c < count) {
665 +               status = UART_GET_LSR(port);
666 +               if (UART_RX_DATA(status)) {
667 +                       *s++ = UART_GET_CHAR(port);
668 +                       c++;
669 +               } else {
670 +                       // nothing more to get, return
671 +                       return c;
672 +               }
673 +       }
674 +       // return the count
675 +       return c;
676 +}
677 +#endif
678 +static void it8712_console_write(struct console *co, const char *s, unsigned count)
679 +{
680 +#ifdef CONFIG_ARCH_SL2312
681 +       struct uart_port *port = it8712_ports + co->index;
682 +       unsigned int status, old_ies;
683 +       int i;
684 +
685 +       /*
686 +        *      First save the CR then disable the interrupts
687 +        */
688 +       old_ies = UART_GET_IER(port);
689 +       //if(old_ies!=7)
690 +       //{
691 +       //
692 +       //      printk("old_ies = %x\n",old_ies);
693 +       //      old_ies = 7;
694 +       //}
695 +       UART_PUT_IER(port,0x0);
696 +
697 +       /*
698 +        *      Now, do each character
699 +        */
700 +       for (i = 0; i < count; i++) {
701 +               do {
702 +                       status = UART_GET_LSR(port);
703 +               } while (!UART_TX_READY(status));
704 +               UART_PUT_CHAR(port, s[i]);
705 +               if (s[i] == '\n') {
706 +                       do {
707 +                               status = UART_GET_LSR(port);
708 +                       } while (!UART_TX_READY(status));
709 +                       UART_PUT_CHAR(port, '\r');
710 +               }
711 +       }
712 +
713 +       /*
714 +        *      Finally, wait for transmitter to become empty
715 +        *      and restore the IES
716 +        */
717 +       do {
718 +               status = UART_GET_LSR(port);
719 +       } while (!(status&UART_LSR_THRE));
720 +       UART_PUT_IER(port, old_ies);
721 +#endif
722 +}
723 +
724 +static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
725 +{
726 +       //printk("it8712 console get options : \n");
727 +
728 +       u_int uart_mc, quot;
729 +       uart_mc= UART_GET_MCR(port);
730 +
731 +       *parity = 'n';
732 +       if (uart_mc & UART_LCR_PARITY) {
733 +               if (uart_mc & UART_LCR_EVEN)
734 +                       *parity = 'e';
735 +               else
736 +                       *parity = 'o';
737 +       }
738 +
739 +       switch (uart_mc & UART_LCR_MSK){
740 +
741 +       case UART_LCR_WLEN5:
742 +               *bits = 5;
743 +               break;
744 +       case UART_LCR_WLEN6:
745 +               *bits = 6;
746 +               break;
747 +       case UART_LCR_WLEN7:
748 +               *bits = 7;
749 +               break;
750 +       case UART_LCR_WLEN8:
751 +               *bits = 8;
752 +               break;
753 +       }
754 +       UART_PUT_MCR(port,UART_LCR_DLAB);
755 +       quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
756 +       UART_PUT_MCR(port,uart_mc);
757 +       *baud = (port->uartclk / (16 *quot));
758 +}
759 +
760 +static int __init it8712_console_setup(struct console *co, char *options)
761 +{
762 +       struct uart_port *port;
763 +       int baud = 38400;
764 +       int bits = 8;
765 +       int parity = 'n';
766 +       int flow= 'n';
767 +       int base;//, irq;
768 +       int i ;
769 +
770 +       printk("it8712 console setup : \n");
771 +
772 +       LPCSetConfig(0, 0x02, 0x01);
773 +        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
774 +        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
775 +       base = IT8712_IO_BASE;
776 +       base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
777 +       it8712_ports[0].mapbase = base;
778 +       it8712_ports[0].membase = (void *)IO_ADDRESS(base);
779 +       it8712_ports[0].irq = IRQ_LPC_OFFSET;
780 +    //         irq = LPCGetConfig(LDN_SERIAL1, 0x70);
781 +       //it8712_ports[0].irq += irq;
782 +
783 +       //printk("it8712 irq is %x \n", it8712_ports[0].irq);
784 +
785 +       // setup LPC Host 'quiet mode'
786 +       //*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
787 +       //for(i=0;i<1000;i++) ;                                         // delay
788 +       //*((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
789 +       LPC_BUS_CTRL = 0xc0;
790 +       LPC_SERIAL_IRQ_CTRL = 0xc0;
791 +       for(i=0;i<1000;i++) ;
792 +       LPC_SERIAL_IRQ_CTRL = 0x80;
793 +
794 +#ifdef CONFIG_ARCH_SL2312
795 +       /*
796 +        * Check whether an invalid uart number has been specified, and
797 +        * if so, search for the first available port that does have
798 +        * console support.
799 +        */
800 +       port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
801 +#else
802 +       return -ENODEV;
803 +#endif
804 +
805 +       if (options)
806 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
807 +       else
808 +               it8712_console_get_options(port, &baud, &parity, &bits);
809 +
810 +       return uart_set_options(port, co, baud, parity, bits, flow);
811 +}
812 +
813 +extern struct uart_driver it8712_reg;
814 +static struct console it8712_console = {
815 +       .name           = SERIAL_IT8712_NAME,
816 +       .write          = it8712_console_write,
817 +       .device         = uart_console_device,
818 +        .setup          = it8712_console_setup,
819 +       .flags          = CON_PRINTBUFFER,
820 +       .index          = 0,
821 +        .data           = &it8712_reg,
822 +};
823 +
824 +static int __init it8712_console_init(void)
825 +{
826 +       register_console(&it8712_console);
827 +        return 0;
828 +}
829 +
830 +console_initcall(it8712_console_init);
831 +
832 +#define IT8712_CONSOLE &it8712_console
833 +#else
834 +#define IT8712_CONSOLE NULL
835 +#endif
836 +
837 +static struct uart_driver it8712_reg = {
838 +       .owner                  = NULL,
839 +       .driver_name            = SERIAL_IT8712_NAME,
840 +       .dev_name               = SERIAL_IT8712_NAME,
841 +        .major                  = SERIAL_IT8712_MAJOR,
842 +       .minor                  = SERIAL_IT8712_MINOR,
843 +       .nr                     = UART_NR,
844 +       .cons                   = IT8712_CONSOLE,
845 +};
846 +
847 +static int __init it8712_init(void)
848 +{
849 +        int result;
850 +       //printk("serial_it8712: it871212_init \n");
851 +
852 +
853 +        result = uart_register_driver(&it8712_reg);
854 +        if(result)
855 +             return result;
856 +       result = uart_add_one_port(&it8712_reg, &it8712_ports[0]);
857 +
858 +        return result;
859 +
860 +}
861 +
862 +
863 +__initcall(it8712_init);
864 Index: linux-2.6.23.16/drivers/serial/it8712.h
865 ===================================================================
866 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
867 +++ linux-2.6.23.16/drivers/serial/it8712.h     2008-03-15 17:59:53.568330991 +0200
868 @@ -0,0 +1,135 @@
869 +#define UART_RX                0       /* In:  Receive buffer (DLAB=0) */
870 +#define UART_TX                0       /* Out: Transmit buffer (DLAB=0) */
871 +#define UART_DLL       0       /* Out: Divisor Latch Low (DLAB=1) */
872 +#define UART_TRG       0       /* (LCR=BF) FCTR bit 7 selects Rx or Tx
873 +                                * In: Fifo count
874 +                                * Out: Fifo custom trigger levels
875 +                                * XR16C85x only */
876 +
877 +#define UART_DLM       1       /* Out: Divisor Latch High (DLAB=1) */
878 +#define UART_IER       1       /* Out: Interrupt Enable Register */
879 +#define UART_FCTR      1       /* (LCR=BF) Feature Control Register
880 +                                * XR16C85x only */
881 +
882 +#define UART_IIR       2       /* In:  Interrupt ID Register */
883 +#define UART_FCR       2       /* Out: FIFO Control Register */
884 +#define UART_EFR       2       /* I/O: Extended Features Register */
885 +                               /* (DLAB=1, 16C660 only) */
886 +
887 +#define UART_LCR       3       /* Out: Line Control Register */
888 +#define UART_MCR       4       /* Out: Modem Control Register */
889 +#define UART_LSR       5       /* In:  Line Status Register */
890 +#define UART_MSR       6       /* In:  Modem Status Register */
891 +#define UART_SCR       7       /* I/O: Scratch Register */
892 +#define UART_EMSR      7       /* (LCR=BF) Extended Mode Select Register
893 +                                * FCTR bit 6 selects SCR or EMSR
894 +                                * XR16c85x only */
895 +
896 +/*
897 + * These are the definitions for the FIFO Control Register
898 + * (16650 only)
899 + */
900 +#define UART_FCR_ENABLE_FIFO   0x01 /* Enable the FIFO */
901 +#define UART_FCR_CLEAR_RCVR    0x02 /* Clear the RCVR FIFO */
902 +#define UART_FCR_CLEAR_XMIT    0x04 /* Clear the XMIT FIFO */
903 +#define UART_FCR_DMA_SELECT    0x08 /* For DMA applications */
904 +#define UART_FCR_TRIGGER_MASK  0xC0 /* Mask for the FIFO trigger range */
905 +#define UART_FCR_TRIGGER_1     0x00 /* Mask for trigger set at 1 */
906 +#define UART_FCR_TRIGGER_4     0x40 /* Mask for trigger set at 4 */
907 +#define UART_FCR_TRIGGER_8     0x80 /* Mask for trigger set at 8 */
908 +#define UART_FCR_TRIGGER_14    0xC0 /* Mask for trigger set at 14 */
909 +/* 16650 redefinitions */
910 +#define UART_FCR6_R_TRIGGER_8  0x00 /* Mask for receive trigger set at 1 */
911 +#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */
912 +#define UART_FCR6_R_TRIGGER_24  0x80 /* Mask for receive trigger set at 8 */
913 +#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */
914 +#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */
915 +#define UART_FCR6_T_TRIGGER_8  0x10 /* Mask for transmit trigger set at 8 */
916 +#define UART_FCR6_T_TRIGGER_24  0x20 /* Mask for transmit trigger set at 24 */
917 +#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
918 +/* TI 16750 definitions */
919 +#define UART_FCR7_64BYTE       0x20 /* Go into 64 byte mode */
920 +
921 +/*
922 + * These are the definitions for the Line Control Register
923 + *
924 + * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
925 + * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
926 + */
927 +#define UART_LCR_DLAB  0x80    /* Divisor latch access bit */
928 +#define UART_LCR_SBC   0x40    /* Set break control */
929 +#define UART_LCR_SPAR  0x20    /* Stick parity (?) */
930 +#define UART_LCR_EPAR  0x10    /* Even parity select */
931 +#define UART_LCR_PARITY        0x08    /* Parity Enable */
932 +#define UART_LCR_STOP  0x04    /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
933 +#define UART_LCR_WLEN5  0x00   /* Wordlength: 5 bits */
934 +#define UART_LCR_WLEN6  0x01   /* Wordlength: 6 bits */
935 +#define UART_LCR_WLEN7  0x02   /* Wordlength: 7 bits */
936 +#define UART_LCR_WLEN8  0x03   /* Wordlength: 8 bits */
937 +#define UART_LCR_EVEN   0x18    /* Even parity */
938 +#define UART_LCR_ODD    0x08    /* Odd parity */
939 +#define UART_LCR_MSK    0x03
940 +/*
941 + * These are the definitions for the Line Status Register
942 + */
943 +#define UART_LSR_DE     0x80    /* FIFO Data Error */
944 +#define UART_LSR_TEMT  0x40    /* Transmitter empty */
945 +#define UART_LSR_THRE  0x20    /* Transmit-hold-register empty */
946 +#define UART_LSR_BI    0x10    /* Break interrupt indicator */
947 +#define UART_LSR_FE    0x08    /* Frame error indicator */
948 +#define UART_LSR_PE    0x04    /* Parity error indicator */
949 +#define UART_LSR_OE    0x02    /* Overrun error indicator */
950 +#define UART_LSR_DR    0x01    /* Receiver data ready */
951 +
952 +/*
953 + * These are the definitions for the Interrupt Identification Register
954 + */
955 +#define UART_IIR_NO_INT        0x01    /* No interrupts pending */
956 +#define UART_IIR_ID    0x06    /* Mask for the interrupt ID */
957 +
958 +#define UART_IIR_MSI   0x00    /* Modem status interrupt */
959 +#define UART_IIR_THRI  0x02    /* Transmitter holding register empty */
960 +#define UART_IIR_RDI   0x04    /* Receiver data interrupt */
961 +#define UART_IIR_RLSI  0x06    /* Receiver line status interrupt */
962 +#define UART_IIR_RCTO  0x0c    /* Receiver character timeout interrupt */
963 +/*
964 + * These are the definitions for the Interrupt Enable Register
965 + */
966 +#define UART_IER_MSI   0x08    /* Enable Modem status interrupt */
967 +#define UART_IER_RLSI  0x04    /* Enable receiver line status interrupt */
968 +#define UART_IER_THRI  0x02    /* Enable Transmitter holding register int. */
969 +#define UART_IER_RDI   0x01    /* Enable receiver data interrupt */
970 +/*
971 + * Sleep mode for ST16650 and TI16750.
972 + * Note that for 16650, EFR-bit 4 must be selected as well.
973 + */
974 +#define UART_IERX_SLEEP  0x10  /* Enable sleep mode */
975 +
976 +/*
977 + * These are the definitions for the Modem Control Register
978 + */
979 +#define UART_MCR_LOOP  0x10    /* Enable loopback test mode */
980 +#define UART_MCR_OUT2  0x08    /* Out2 complement */
981 +#define UART_MCR_OUT1  0x04    /* Out1 complement */
982 +#define UART_MCR_RTS   0x02    /* RTS complement */
983 +#define UART_MCR_DTR   0x01    /* DTR complement */
984 +
985 +/*
986 + * These are the definitions for the Modem Status Register
987 + */
988 +#define UART_MSR_DCD   0x80    /* Data Carrier Detect */
989 +#define UART_MSR_RI    0x40    /* Ring Indicator */
990 +#define UART_MSR_DSR   0x20    /* Data Set Ready */
991 +#define UART_MSR_CTS   0x10    /* Clear to Send */
992 +#define UART_MSR_DDCD  0x08    /* Delta DCD */
993 +#define UART_MSR_TERI  0x04    /* Trailing edge ring indicator */
994 +#define UART_MSR_DDSR  0x02    /* Delta DSR */
995 +#define UART_MSR_DCTS  0x01    /* Delta CTS */
996 +#define UART_MSR_ANY_DELTA 0x0F        /* Any of the delta bits! */
997 +
998 +#define UART_PARITY_NONE       0x00
999 +#define UART_PARITY_ODD                0x01
1000 +#define UART_PARITY_EVEN       0x02
1001 +
1002 +
1003 +
1004 Index: linux-2.6.23.16/drivers/serial/serial_it8712.c
1005 ===================================================================
1006 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1007 +++ linux-2.6.23.16/drivers/serial/serial_it8712.c      2008-03-15 17:59:53.568330991 +0200
1008 @@ -0,0 +1,876 @@
1009 +/*
1010 + *  linux/drivers/char/serial_uart00.c
1011 + *
1012 + *  Driver for UART00 serial ports
1013 + *
1014 + *  Based on drivers/char/serial_amba.c, by ARM Limited &
1015 + *                                          Deep Blue Solutions Ltd.
1016 + *  Copyright 2001 Altera Corporation
1017 + *
1018 + * This program is free software; you can redistribute it and/or modify
1019 + * it under the terms of the GNU General Public License as published by
1020 + * the Free Software Foundation; either version 2 of the License, or
1021 + * (at your option) any later version.
1022 + *
1023 + * This program is distributed in the hope that it will be useful,
1024 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1025 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1026 + * GNU General Public License for more details.
1027 + *
1028 + * You should have received a copy of the GNU General Public License
1029 + * along with this program; if not, write to the Free Software
1030 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1031 + *
1032 + *  $Id: serial_it8712.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
1033 + *
1034 + */
1035 +#include <linux/module.h>
1036 +
1037 +#include <linux/errno.h>
1038 +#include <linux/signal.h>
1039 +#include <linux/sched.h>
1040 +#include <linux/interrupt.h>
1041 +#include <linux/tty.h>
1042 +#include <linux/tty_flip.h>
1043 +#include <linux/major.h>
1044 +#include <linux/string.h>
1045 +#include <linux/fcntl.h>
1046 +#include <linux/ptrace.h>
1047 +#include <linux/ioport.h>
1048 +#include <linux/mm.h>
1049 +#include <linux/slab.h>
1050 +#include <linux/init.h>
1051 +#include <linux/circ_buf.h>
1052 +#include <linux/serial.h>
1053 +#include <linux/console.h>
1054 +#include <linux/sysrq.h>
1055 +
1056 +#include <asm/system.h>
1057 +#include <asm/io.h>
1058 +#include <asm/irq.h>
1059 +#include <asm/uaccess.h>
1060 +#include <asm/bitops.h>
1061 +#include <asm/sizes.h>
1062 +
1063 +#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
1064 +#define SUPPORT_SYSRQ
1065 +#endif
1066 +
1067 +#include <linux/serial_core.h>
1068 +#include <asm/arch/sl2312.h>
1069 +#include <asm/arch/int_ctrl.h>
1070 +#include <asm/arch/it8712.h>
1071 +#include "serial_it8712.h"
1072 +
1073 +//#define DEBUG           1
1074 +#define UART_NR                1
1075 +
1076 +#define SERIAL_IT8712_NAME     "ttySI"
1077 +#define SERIAL_IT8712_MAJOR    204
1078 +#define SERIAL_IT8712_MINOR    41      /* Temporary - will change in future */
1079 +#define SERIAL_IT8712_NR       UART_NR
1080 +#define UART_PORT_SIZE 0x50
1081 +
1082 +#define CALLOUT_IT8712_NAME    "cuaslI"
1083 +#define CALLOUT_IT8712_MAJOR   205
1084 +#define CALLOUT_IT8712_MINOR   41      /* Temporary - will change in future */
1085 +#define CALLOUT_IT8712_NR      UART_NR
1086 +#define LPC_HOST_CONTINUE_MODE 0x00000040
1087 +
1088 +#define IT8712_NO_PORTS         UART_NR
1089 +
1090 +static struct tty_driver normal, callout;
1091 +static struct tty_struct *it8712_table[UART_NR];
1092 +static struct termios *it8712_termios[UART_NR], *it8712_termios_locked[UART_NR];
1093 +static struct console it8712_console;
1094 +
1095 +#define IT8712_ISR_PASS_LIMIT  256
1096 +
1097 +/*
1098 + * Access macros for the SL2312 UARTs
1099 + */
1100 +#define UART_GET_INT_STATUS(p) (inb(((p)->membase+UART_IIR)) & 0x0F)  // interrupt identification
1101 +#define UART_PUT_IER(p, c)      outb(c,((p)->membase+UART_IER))         // interrupt enable
1102 +#define UART_GET_IER(p)         inb(((p)->membase+UART_IER))
1103 +#define UART_PUT_CHAR(p, c)     outb(c,((p)->membase+UART_TX))         // transmitter holding
1104 +#define UART_GET_CHAR(p)        inb(((p)->membase+UART_RX))            // receive buffer
1105 +#define UART_GET_LSR(p)         inb(((p)->membase+UART_LSR))            // line status
1106 +#define UART_GET_MSR(p)         inb(((p)->membase+UART_MSR))            // modem status
1107 +#define UART_GET_MCR(p)         inb(((p)->membase+UART_MCR))            // modem control
1108 +#define UART_PUT_MCR(p, c)      outb(c,((p)->membase+UART_MCR))
1109 +#define UART_GET_LCR(p)         inb(((p)->membase+UART_LCR))       // mode control
1110 +#define UART_PUT_LCR(p, c)      outb(c,((p)->membase+UART_LCR))
1111 +#define UART_PUT_FCR(p, c)      outb(c,((p)->membase+UART_FCR))       // fifo control
1112 +#define UART_GET_DIV_HI(p)     inb(((p)->membase+UART_DLM))
1113 +#define UART_PUT_DIV_HI(p, c)  outb(c,((p)->membase+UART_DLM))
1114 +#define UART_GET_DIV_LO(p)     inb(((p)->membase+UART_DLL))
1115 +#define UART_PUT_DIV_LO(p, c)  outb(c,((p)->membase+UART_DLL))
1116 +#define UART_PUT_MDR(p, c)      outb(c,UART_MDR((p)->membase))
1117 +#define UART_RX_DATA(s)                ((s) & UART_LSR_DR)
1118 +#define UART_TX_READY(s)       ((s) & UART_LSR_THRE)
1119 +
1120 +static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
1121 +{
1122 +        unsigned int reg;
1123 +
1124 +//        printk("it8712 stop tx : \n");
1125 +        reg = UART_GET_IER(port);
1126 +        reg &= ~(UART_IER_THRI);
1127 +       UART_PUT_IER(port, reg);
1128 +}
1129 +
1130 +static void it8712_stop_rx(struct uart_port *port)
1131 +{
1132 +        unsigned int reg;
1133 +
1134 +//        printk("it8712 stop rx : \n");
1135 +        reg = UART_GET_IER(port);
1136 +        reg &= ~(UART_IER_RDI);
1137 +       UART_PUT_IER(port, reg);
1138 +
1139 +}
1140 +
1141 +static void it8712_enable_ms(struct uart_port *port)
1142 +{
1143 +        unsigned int reg;
1144 +
1145 +//        printk("it8712 enable ms : \n");
1146 +
1147 +        reg = UART_GET_IER(port);
1148 +        reg |= (UART_IER_MSI);
1149 +       UART_PUT_IER(port, reg);
1150 +
1151 +}
1152 +
1153 +static void
1154 +it8712_rx_chars(struct uart_info *info, struct pt_regs *regs)
1155 +{
1156 +       struct tty_struct *tty = info->tty;
1157 +       unsigned int status, mask, ch, flg, ignored = 0;
1158 +       struct uart_port *port = info->port;
1159 +
1160 + //       printk("it8712_rx_chars : \n");
1161 +       status = UART_GET_LSR(port);
1162 +       while (UART_RX_DATA(status)) {
1163 +
1164 +               /*
1165 +                * We need to read rds before reading the
1166 +                * character from the fifo
1167 +                */
1168 +               ch = UART_GET_CHAR(port);
1169 +               port->icount.rx++;
1170 +
1171 +               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
1172 +                       goto ignore_char;
1173 +
1174 +               flg = TTY_NORMAL;
1175 +
1176 +               /*
1177 +                * Note that the error handling code is
1178 +                * out of the main execution path
1179 +                */
1180 +
1181 +               if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
1182 +                       goto handle_error;
1183 +               if (uart_handle_sysrq_char(info, ch, regs))
1184 +                       goto ignore_char;
1185 +
1186 +       error_return:
1187 +               *tty->flip.flag_buf_ptr++ = flg;
1188 +               *tty->flip.char_buf_ptr++ = ch;
1189 +               tty->flip.count++;
1190 +       ignore_char:
1191 +               status = UART_GET_LSR(port);
1192 +       } // end of while
1193 +out:
1194 +       tty_flip_buffer_push(tty);
1195 +       return;
1196 +
1197 +handle_error:
1198 +       if (status & UART_LSR_BI) {
1199 +               status &= ~(UART_LSR_FE);
1200 +               port->icount.brk++;
1201 +
1202 +#ifdef SUPPORT_SYSRQ
1203 +               if (uart_handle_break(info, &it8712_console))
1204 +                       goto ignore_char;
1205 +#endif
1206 +       } else if (status & UART_LSR_PE)
1207 +               port->icount.parity++;
1208 +       else if (status & UART_LSR_FE)
1209 +               port->icount.frame++;
1210 +
1211 +       if (status & UART_LSR_OE)
1212 +               port->icount.overrun++;
1213 +
1214 +       if (status & port->ignore_status_mask) {
1215 +               if (++ignored > 100)
1216 +                       goto out;
1217 +               goto ignore_char;
1218 +       }
1219 +
1220 +       mask = status & port->read_status_mask;
1221 +
1222 +       if (mask & UART_LSR_BI)
1223 +               flg = TTY_BREAK;
1224 +       else if (mask & UART_LSR_PE)
1225 +               flg = TTY_PARITY;
1226 +       else if (mask & UART_LSR_FE)
1227 +               flg = TTY_FRAME;
1228 +
1229 +       if (status & UART_LSR_OE) {
1230 +               /*
1231 +                * CHECK: does overrun affect the current character?
1232 +                * ASSUMPTION: it does not.
1233 +                */
1234 +               *tty->flip.flag_buf_ptr++ = flg;
1235 +               *tty->flip.char_buf_ptr++ = ch;
1236 +               tty->flip.count++;
1237 +               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
1238 +                       goto ignore_char;
1239 +               ch = 0;
1240 +               flg = TTY_OVERRUN;
1241 +       }
1242 +#ifdef SUPPORT_SYSRQ
1243 +       info->sysrq = 0;
1244 +#endif
1245 +       goto error_return;
1246 +}
1247 +
1248 +static void it8712_tx_chars(struct uart_info *info)
1249 +{
1250 +       int count;
1251 +       struct uart_port *port=info->port;
1252 +
1253 +       if (port->x_char) {
1254 +               while(!(UART_GET_LSR(port)&UART_LSR_THRE));
1255 +               UART_PUT_CHAR(port, port->x_char);
1256 +               port->icount.tx++;
1257 +               port->x_char = 0;
1258 +
1259 +               return;
1260 +       }
1261 +       if (info->xmit.head == info->xmit.tail
1262 +           || info->tty->stopped
1263 +           || info->tty->hw_stopped) {
1264 +               it8712_stop_tx(info->port, 0);
1265 +               return;
1266 +       }
1267 +
1268 +       count = port->fifosize >> 1;
1269 +       do {
1270 +               while(!(UART_GET_LSR(port)&UART_LSR_THRE));
1271 +               UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
1272 +               info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
1273 +               port->icount.tx++;
1274 +               if (info->xmit.head == info->xmit.tail)
1275 +                       break;
1276 +       } while (--count > 0);
1277 +
1278 +       if (CIRC_CNT(info->xmit.head,
1279 +                    info->xmit.tail,
1280 +                    UART_XMIT_SIZE) < WAKEUP_CHARS)
1281 +               uart_event(info, EVT_WRITE_WAKEUP);
1282 +
1283 +       if (info->xmit.head == info->xmit.tail)
1284 +               it8712_stop_tx(info->port, 0);
1285 +}
1286 +
1287 +static void it8712_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
1288 +{
1289 +        unsigned int reg;
1290 +       struct uart_info *info=(struct uart_info*)(port->iobase);
1291 +
1292 +//        printk("it8712 start tx : \n");
1293 +        reg = UART_GET_IER(port);
1294 +        reg |= (UART_IER_THRI);
1295 +       UART_PUT_IER(port, reg);
1296 +       it8712_tx_chars(info);
1297 +}
1298 +
1299 +static void it8712_modem_status(struct uart_info *info)
1300 +{
1301 +       unsigned int status;
1302 +       struct uart_icount *icount = &info->port->icount;
1303 +
1304 +//        printk("it8712 modem status : \n");
1305 +
1306 +       status = UART_GET_MSR(info->port);
1307 +
1308 +       if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
1309 +                      UART_MSR_TERI | UART_MSR_DDCD)))
1310 +               return;
1311 +
1312 +       if (status & UART_MSR_DCD) {
1313 +               icount->dcd++;
1314 +#ifdef CONFIG_HARD_PPS
1315 +               if ((info->flags & ASYNC_HARDPPS_CD) &&
1316 +                   (status & UART_MSR_DCD_MSK))
1317 +                       hardpps();
1318 +#endif
1319 +               if (info->flags & ASYNC_CHECK_CD) {
1320 +                       if (status & UART_MSR_DCD)
1321 +                               wake_up_interruptible(&info->open_wait);
1322 +                       else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
1323 +                                  (info->flags & ASYNC_CALLOUT_NOHUP))) {
1324 +                               if (info->tty)
1325 +                                       tty_hangup(info->tty);
1326 +                       }
1327 +               }
1328 +       }
1329 +
1330 +       if (status & UART_MSR_DDSR)
1331 +               icount->dsr++;
1332 +
1333 +       if (status & UART_MSR_DCTS) {
1334 +               icount->cts++;
1335 +
1336 +               if (info->flags & ASYNC_CTS_FLOW) {
1337 +                       status &= UART_MSR_CTS;
1338 +
1339 +                       if (info->tty->hw_stopped) {
1340 +                               if (status) {
1341 +                                       info->tty->hw_stopped = 0;
1342 +                                       info->ops->start_tx(info->port, 1, 0);
1343 +                                       uart_event(info, EVT_WRITE_WAKEUP);
1344 +                               }
1345 +                       } else {
1346 +                               if (!status) {
1347 +                                       info->tty->hw_stopped = 1;
1348 +                                       info->ops->stop_tx(info->port, 0);
1349 +                               }
1350 +                       }
1351 +               }
1352 +       }
1353 +       wake_up_interruptible(&info->delta_msr_wait);
1354 +
1355 +}
1356 +
1357 +static void it8712_int(int irq, void *dev_id, struct pt_regs *regs)
1358 +{
1359 +       struct uart_info *info = dev_id;
1360 +       unsigned int status, pass_counter = 0;
1361 +
1362 +       status = UART_GET_INT_STATUS(info->port);
1363 +       do {
1364 +//                  printk("it8712_int: status %x \n", status);
1365 +               switch(status)
1366 +               {
1367 +                  case UART_IIR_RDI:
1368 +                  case UART_IIR_RLSI:
1369 +                  case UART_IIR_RCTO:
1370 +                       it8712_rx_chars(info, regs);
1371 +                  break;
1372 +                  case UART_IIR_THRI:
1373 +                       it8712_tx_chars(info);
1374 +                  break;
1375 +                  case UART_IIR_MSI:
1376 +                       it8712_modem_status(info);
1377 +                  break;
1378 +                  default:
1379 +                  break;
1380 +               }
1381 +               if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
1382 +                       break;
1383 +
1384 +               status = UART_GET_INT_STATUS(info->port);
1385 +       } while (status);
1386 +}
1387 +
1388 +static u_int it8712_tx_empty(struct uart_port *port)
1389 +{
1390 +//        printk("it8712 tx empty : \n");
1391 +
1392 +       return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
1393 +}
1394 +
1395 +static u_int it8712_get_mctrl(struct uart_port *port)
1396 +{
1397 +       unsigned int result = 0;
1398 +       unsigned int status;
1399 +
1400 +//        printk("it8712 get mctrl : \n");
1401 +
1402 +       status = UART_GET_MSR(port);
1403 +       if (status & UART_MSR_DCD)
1404 +               result |= TIOCM_CAR;
1405 +       if (status & UART_MSR_DSR)
1406 +               result |= TIOCM_DSR;
1407 +       if (status & UART_MSR_CTS)
1408 +               result |= TIOCM_CTS;
1409 +       if (status & UART_MSR_RI)
1410 +               result |= TIOCM_RI;
1411 +
1412 +       return result;
1413 +}
1414 +
1415 +static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
1416 +{
1417 +}
1418 +
1419 +static void it8712_break_ctl(struct uart_port *port, int break_state)
1420 +{
1421 +       unsigned int lcr;
1422 +
1423 +//        printk("it8712 break ctl : \n");
1424 +
1425 +       lcr = UART_GET_LCR(port);
1426 +       if (break_state == -1)
1427 +               lcr |= UART_LCR_SBC;
1428 +       else
1429 +               lcr &= ~UART_LCR_SBC;
1430 +       UART_PUT_LCR(port, lcr);
1431 +}
1432 +
1433 +static inline u_int uart_calculate_quot(struct uart_info *info, u_int baud)
1434 +{
1435 +       u_int quot;
1436 +
1437 +       /* Special case: B0 rate */
1438 +       if (!baud)
1439 +               baud = 9600;
1440 +
1441 +       quot = (info->port->uartclk/(16 * baud)) ;
1442 +
1443 +       return quot;
1444 +}
1445 +static void it8712_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
1446 +{
1447 +       u_int uart_mc=0, old_ier;
1448 +       unsigned long flags;
1449 +
1450 +#ifdef DEBUG
1451 +       printk("it8712_set_cflag(0x%x) called\n", cflag);
1452 +#endif
1453 +
1454 +
1455 +       /* byte size and parity */
1456 +       switch (cflag & CSIZE) {
1457 +       case CS5: uart_mc = UART_LCR_WLEN5; break;
1458 +       case CS6: uart_mc = UART_LCR_WLEN6; break;
1459 +       case CS7: uart_mc = UART_LCR_WLEN7; break;
1460 +       default:  uart_mc = UART_LCR_WLEN8; break; // CS8
1461 +       }
1462 +       if (cflag & CSTOPB)
1463 +               uart_mc|= UART_LCR_STOP;
1464 +       if (cflag & PARENB) {
1465 +               uart_mc |= UART_LCR_EVEN;
1466 +               if (!(cflag & PARODD))
1467 +                       uart_mc |= UART_LCR_ODD;
1468 +       }
1469 +
1470 +       port->read_status_mask = UART_LSR_OE;
1471 +       if (iflag & INPCK)
1472 +               port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
1473 +       if (iflag & (BRKINT | PARMRK))
1474 +               port->read_status_mask |= UART_LSR_BI;
1475 +
1476 +       /*
1477 +        * Characters to ignore
1478 +        */
1479 +       port->ignore_status_mask = 0;
1480 +       if (iflag & IGNPAR)
1481 +               port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
1482 +       if (iflag & IGNBRK) {
1483 +               port->ignore_status_mask |= UART_LSR_BI;
1484 +               /*
1485 +                * If we're ignoring parity and break indicators,
1486 +                * ignore overruns to (for real raw support).
1487 +                */
1488 +               if (iflag & IGNPAR)
1489 +                       port->ignore_status_mask |= UART_LSR_OE;
1490 +       }
1491 +
1492 +       /* first, disable everything */
1493 +       save_flags(flags); cli();
1494 +       old_ier = UART_GET_IER(port);
1495 +
1496 +       if ((port->flags & ASYNC_HARDPPS_CD) ||
1497 +           (cflag & CRTSCTS) || !(cflag & CLOCAL))
1498 +               old_ier |= UART_IER_MSI;
1499 +
1500 +       /* Set baud rate */
1501 +       quot = quot / 13;
1502 +       UART_PUT_LCR(port, UART_LCR_DLAB);
1503 +       UART_PUT_DIV_LO(port, (quot & 0xff));
1504 +       UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
1505 +
1506 +       UART_PUT_LCR(port, uart_mc);
1507 +//     UART_PUT_LCR(port, 0x07); // ???? it is wired
1508 +        UART_PUT_MCR(port, 0x08);
1509 +        UART_PUT_FCR(port, 0x01);
1510 +       UART_PUT_IER(port, 0x05);
1511 +
1512 +       restore_flags(flags);
1513 +}
1514 +
1515 +static int it8712_startup(struct uart_port *port, struct uart_info *info)
1516 +{
1517 +       int retval;
1518 +       unsigned int regs;
1519 +
1520 +//        printk("it8712 startup : \n");
1521 +
1522 +       /*
1523 +        * Use iobase to store a pointer to info. We need this to start a
1524 +        * transmission as the tranmittr interrupt is only generated on
1525 +        * the transition to the idle state
1526 +        */
1527 +
1528 +       port->iobase=(u_int)info;
1529 +
1530 +       /*
1531 +        * Allocate the IRQ
1532 +        */
1533 +       retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", info);
1534 +       if (retval)
1535 +               return retval;
1536 +
1537 +        /* setup interrupt controller  */
1538 +        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
1539 +        regs |= (IRQ_SERIRQ0_MASK);
1540 +        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
1541 +        regs = *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
1542 +        regs &= ~(IRQ_SERIRQ0_MASK);
1543 +        *((volatile unsigned int *)IRQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
1544 +        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_SERIRQ0_MASK);
1545 +
1546 +       /*
1547 +        * Finally, enable interrupts. Use the TII interrupt to minimise
1548 +        * the number of interrupts generated. If higher performance is
1549 +        * needed, consider using the TI interrupt with a suitable FIFO
1550 +        * threshold
1551 +        */
1552 +       UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
1553 +
1554 +       return 0;
1555 +}
1556 +
1557 +static void it8712_shutdown(struct uart_port *port, struct uart_info *info)
1558 +{
1559 +//        printk("it8712 shutdown : \n");
1560 +
1561 +       /*
1562 +        * disable all interrupts, disable the port
1563 +        */
1564 +       UART_PUT_IER(port, 0x0);
1565 +
1566 +       /* disable break condition and fifos */
1567 +//     UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
1568 +
1569 +       /*
1570 +        * Free the interrupt
1571 +        */
1572 +       free_irq(port->irq, info);
1573 +}
1574 +
1575 +static const char *it8712_type(struct uart_port *port)
1576 +{
1577 +       return port->type == PORT_IT8712 ? "IT8712" : NULL;
1578 +}
1579 +
1580 +/*
1581 + * Release the memory region(s) being used by 'port'
1582 + */
1583 +static void it8712_release_port(struct uart_port *port)
1584 +{
1585 +//        printk("it8712 release port : \n");
1586 +
1587 +       release_mem_region(port->mapbase, UART_PORT_SIZE);
1588 +}
1589 +
1590 +/*
1591 + * Request the memory region(s) being used by 'port'
1592 + */
1593 +static int it8712_request_port(struct uart_port *port)
1594 +{
1595 +       return request_mem_region(port->mapbase, UART_PORT_SIZE,
1596 +                                   "serial_it8712") != NULL ? 0 : -EBUSY;
1597 +}
1598 +
1599 +/*
1600 + * Configure/autoconfigure the port.
1601 + */
1602 +static void it8712_config_port(struct uart_port *port, int flags)
1603 +{
1604 +
1605 +       if (flags & UART_CONFIG_TYPE) {
1606 +               if (it8712_request_port(port) == 0)
1607 +                       port->type = PORT_IT8712;
1608 +       }
1609 +}
1610 +
1611 +/*
1612 + * verify the new serial_struct (for TIOCSSERIAL).
1613 + */
1614 +static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
1615 +{
1616 +       int ret = 0;
1617 +
1618 +       if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
1619 +               ret = -EINVAL;
1620 +       if (ser->irq < 0 || ser->irq >= NR_IRQS)
1621 +               ret = -EINVAL;
1622 +       if (ser->baud_base < 9600)
1623 +               ret = -EINVAL;
1624 +       return ret;
1625 +}
1626 +
1627 +static struct uart_ops it8712_pops = {
1628 +       tx_empty:       it8712_tx_empty,
1629 +       set_mctrl:      it8712_set_mctrl_null,
1630 +       get_mctrl:      it8712_get_mctrl,
1631 +       stop_tx:        it8712_stop_tx,
1632 +       start_tx:       it8712_start_tx,
1633 +       stop_rx:        it8712_stop_rx,
1634 +       enable_ms:      it8712_enable_ms,
1635 +       break_ctl:      it8712_break_ctl,
1636 +       startup:        it8712_startup,
1637 +       shutdown:       it8712_shutdown,
1638 +       change_speed:   it8712_change_speed,
1639 +       type:           it8712_type,
1640 +       release_port:   it8712_release_port,
1641 +       request_port:   it8712_request_port,
1642 +       config_port:    it8712_config_port,
1643 +       verify_port:    it8712_verify_port,
1644 +};
1645 +
1646 +#ifdef CONFIG_ARCH_SL2312
1647 +
1648 +static struct uart_port it8712_ports[UART_NR] = {
1649 +       {
1650 +               membase:        (void *)0,
1651 +               mapbase:        0,
1652 +               iotype:         SERIAL_IO_MEM,
1653 +               irq:            0,
1654 +               uartclk:        UART_CLK/2,
1655 +               fifosize:       16,
1656 +               ops:            &it8712_pops,
1657 +               flags:          ASYNC_BOOT_AUTOCONF,
1658 +       }
1659 +};
1660 +
1661 +#endif
1662 +
1663 +#ifdef CONFIG_SERIAL_IT8712_CONSOLE
1664 +#ifdef used_and_not_const_char_pointer
1665 +static int it8712_console_read(struct uart_port *port, char *s, u_int count)
1666 +{
1667 +       unsigned int status;
1668 +       int c;
1669 +#ifdef DEBUG
1670 +       printk("it8712_console_read() called\n");
1671 +#endif
1672 +
1673 +       c = 0;
1674 +       while (c < count) {
1675 +               status = UART_GET_LSR(port);
1676 +               if (UART_RX_DATA(status)) {
1677 +                       *s++ = UART_GET_CHAR(port);
1678 +                       c++;
1679 +               } else {
1680 +                       // nothing more to get, return
1681 +                       return c;
1682 +               }
1683 +       }
1684 +       // return the count
1685 +       return c;
1686 +}
1687 +#endif
1688 +static void it8712_console_write(struct console *co, const char *s, unsigned count)
1689 +{
1690 +#ifdef CONFIG_ARCH_SL2312
1691 +       struct uart_port *port = it8712_ports + co->index;
1692 +       unsigned int status, old_ies;
1693 +       int i;
1694 +
1695 +       /*
1696 +        *      First save the CR then disable the interrupts
1697 +        */
1698 +       old_ies = UART_GET_IER(port);
1699 +       UART_PUT_IER(port,0x0);
1700 +
1701 +       /*
1702 +        *      Now, do each character
1703 +        */
1704 +       for (i = 0; i < count; i++) {
1705 +               do {
1706 +                       status = UART_GET_LSR(port);
1707 +               } while (!UART_TX_READY(status));
1708 +               UART_PUT_CHAR(port, s[i]);
1709 +               if (s[i] == '\n') {
1710 +                       do {
1711 +                               status = UART_GET_LSR(port);
1712 +                       } while (!UART_TX_READY(status));
1713 +                       UART_PUT_CHAR(port, '\r');
1714 +               }
1715 +       }
1716 +
1717 +       /*
1718 +        *      Finally, wait for transmitter to become empty
1719 +        *      and restore the IES
1720 +        */
1721 +       do {
1722 +               status = UART_GET_LSR(port);
1723 +       } while (!(status&UART_LSR_THRE));
1724 +       UART_PUT_IER(port, old_ies);
1725 +#endif
1726 +}
1727 +
1728 +static kdev_t it8712_console_device(struct console *co)
1729 +{
1730 +       return MKDEV(SERIAL_IT8712_MAJOR, SERIAL_IT8712_MINOR + co->index);
1731 +}
1732 +
1733 +static int it8712_console_wait_key(struct console *co)
1734 +{
1735 +#ifdef CONFIG_ARCH_SL2312
1736 +       struct uart_port *port = (it8712_ports + co->index);
1737 +       unsigned int status;
1738 +
1739 +       do {
1740 +               status = UART_GET_LSR(port);
1741 +       } while (!UART_RX_DATA(status));
1742 +       return UART_GET_CHAR(port);
1743 +#else
1744 +       return 0;
1745 +#endif
1746 +}
1747 +
1748 +static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
1749 +{
1750 +       printk("it8712 console get options : \n");
1751 +
1752 +       u_int uart_mc, quot;
1753 +       uart_mc= UART_GET_MCR(port);
1754 +
1755 +       *parity = 'n';
1756 +       if (uart_mc & UART_LCR_PARITY) {
1757 +               if (uart_mc & UART_LCR_EVEN)
1758 +                       *parity = 'e';
1759 +               else
1760 +                       *parity = 'o';
1761 +       }
1762 +
1763 +       switch (uart_mc & UART_LCR_MSK){
1764 +
1765 +       case UART_LCR_WLEN5:
1766 +               *bits = 5;
1767 +               break;
1768 +       case UART_LCR_WLEN6:
1769 +               *bits = 6;
1770 +               break;
1771 +       case UART_LCR_WLEN7:
1772 +               *bits = 7;
1773 +               break;
1774 +       case UART_LCR_WLEN8:
1775 +               *bits = 8;
1776 +               break;
1777 +       }
1778 +       UART_PUT_MCR(port,UART_LCR_DLAB);
1779 +       quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
1780 +       UART_PUT_MCR(port,uart_mc);
1781 +       *baud = (port->uartclk / (16 *quot));
1782 +}
1783 +
1784 +static int __init it8712_console_setup(struct console *co, char *options)
1785 +{
1786 +       struct uart_port *port;
1787 +       int baud = 38400;
1788 +       int bits = 8;
1789 +       int parity = 'n';
1790 +       int flow= 'n';
1791 +       int base, irq;
1792 +       int i ;
1793 +
1794 +//     printk("it8712 console setup : \n");
1795 +
1796 +       LPCSetConfig(0, 0x02, 0x01);
1797 +        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
1798 +        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
1799 +       base = IT8712_IO_BASE;
1800 +       base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
1801 +       it8712_ports[0].mapbase = base;
1802 +       it8712_ports[0].membase = IO_ADDRESS(base);
1803 +       it8712_ports[0].irq = IRQ_SERIRQ0_OFFSET;
1804 +               irq = LPCGetConfig(LDN_SERIAL1, 0x70);
1805 +       it8712_ports[0].irq += irq;
1806 +
1807 +       printk("it8712 irq is %x %x \n", it8712_ports[0].irq, irq);
1808 +
1809 +       // setup LPC Host 'quiet mode'
1810 +       *((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) |= LPC_HOST_CONTINUE_MODE ;
1811 +       for(i=0;i<1000;i++) ;                                           // delay
1812 +       *((volatile unsigned int *)IO_ADDRESS((SL2312_LPC_HOST_BASE+0x04))) &= ~(LPC_HOST_CONTINUE_MODE) ;
1813 +
1814 +#ifdef CONFIG_ARCH_SL2312
1815 +       /*
1816 +        * Check whether an invalid uart number has been specified, and
1817 +        * if so, search for the first available port that does have
1818 +        * console support.
1819 +        */
1820 +       port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
1821 +#else
1822 +       return -ENODEV;
1823 +#endif
1824 +
1825 +       if (options)
1826 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
1827 +       else
1828 +               it8712_console_get_options(port, &baud, &parity, &bits);
1829 +
1830 +       return uart_set_options(port, co, baud, parity, bits, flow);
1831 +}
1832 +
1833 +static struct console it8712_console = {
1834 +       name:           SERIAL_IT8712_NAME,
1835 +       write:          it8712_console_write,
1836 +#ifdef used_and_not_const_char_pointer
1837 +       read:           it8712_console_read,
1838 +#endif
1839 +       device:         it8712_console_device,
1840 +//     wait_key:       it8712_console_wait_key,
1841 +       setup:          it8712_console_setup,
1842 +       flags:          (CON_PRINTBUFFER|CON_ENABLED),
1843 +       index:          -1,
1844 +};
1845 +
1846 +void __init it8712_console_init(void)
1847 +{
1848 +       register_console(&it8712_console);
1849 +}
1850 +
1851 +#define IT8712_CONSOLE &it8712_console
1852 +#else
1853 +#define IT8712_CONSOLE NULL
1854 +#endif
1855 +
1856 +static struct uart_driver it8712_reg = {
1857 +       owner:                  NULL,
1858 +       normal_major:           SERIAL_IT8712_MAJOR,
1859 +       normal_name:            SERIAL_IT8712_NAME,
1860 +       normal_driver:          &normal,
1861 +       callout_major:          CALLOUT_IT8712_MAJOR,
1862 +       callout_name:           CALLOUT_IT8712_NAME,
1863 +       callout_driver:         &callout,
1864 +       table:                  it8712_table,
1865 +       termios:                it8712_termios,
1866 +       termios_locked:         it8712_termios_locked,
1867 +       minor:                  SERIAL_IT8712_MINOR,
1868 +       nr:                     UART_NR,
1869 +#ifdef CONFIG_ARCH_SL2312
1870 +       port:                   it8712_ports,
1871 +#endif
1872 +       state:                  NULL,
1873 +       cons:                   IT8712_CONSOLE,
1874 +};
1875 +
1876 +static int __init it8712_init(void)
1877 +{
1878 +//     printk("serial_it8712: it871212_init \n");
1879 +
1880 +       return uart_register_driver(&it8712_reg);
1881 +}
1882 +
1883 +
1884 +__initcall(it8712_init);
1885 Index: linux-2.6.23.16/drivers/serial/serial_sl2312.c
1886 ===================================================================
1887 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1888 +++ linux-2.6.23.16/drivers/serial/serial_sl2312.c      2008-03-17 12:30:50.290536619 +0200
1889 @@ -0,0 +1,827 @@
1890 +/*
1891 + *  linux/drivers/char/serial_uart00.c
1892 + *
1893 + *  Driver for UART00 serial ports
1894 + *
1895 + *  Based on drivers/char/serial_amba.c, by ARM Limited &
1896 + *                                          Deep Blue Solutions Ltd.
1897 + *  Copyright 2001 Altera Corporation
1898 + *
1899 + * This program is free software; you can redistribute it and/or modify
1900 + * it under the terms of the GNU General Public License as published by
1901 + * the Free Software Foundation; either version 2 of the License, or
1902 + * (at your option) any later version.
1903 + *
1904 + * This program is distributed in the hope that it will be useful,
1905 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1906 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1907 + * GNU General Public License for more details.
1908 + *
1909 + * You should have received a copy of the GNU General Public License
1910 + * along with this program; if not, write to the Free Software
1911 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1912 + *
1913 + *  $Id: serial_sl2312.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
1914 + *
1915 + */
1916 +#include <linux/module.h>
1917 +
1918 +#include <linux/errno.h>
1919 +#include <linux/signal.h>
1920 +#include <linux/sched.h>
1921 +#include <linux/interrupt.h>
1922 +#include <linux/tty.h>
1923 +#include <linux/tty_flip.h>
1924 +#include <linux/major.h>
1925 +#include <linux/string.h>
1926 +#include <linux/fcntl.h>
1927 +#include <linux/ptrace.h>
1928 +#include <linux/ioport.h>
1929 +#include <linux/mm.h>
1930 +#include <linux/slab.h>
1931 +#include <linux/init.h>
1932 +#include <linux/circ_buf.h>
1933 +#include <linux/serial.h>
1934 +#include <linux/console.h>
1935 +#include <linux/sysrq.h>
1936 +#include <linux/serial_core.h>
1937 +
1938 +#include <asm/system.h>
1939 +#include <asm/hardware.h>
1940 +#include <asm/io.h>
1941 +#include <asm/irq.h>
1942 +#include <asm/uaccess.h>
1943 +#include <asm/bitops.h>
1944 +#include <asm/sizes.h>
1945 +#include <linux/spinlock.h>
1946 +#include <linux/irq.h>
1947 +
1948 +
1949 +#if defined(CONFIG_SERIAL_SL2312_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
1950 +#define SUPPORT_SYSRQ
1951 +#endif
1952 +
1953 +#include <asm/arch/sl2312.h>
1954 +#define UART_TYPE (volatile unsigned int*)
1955 +#include <asm/arch/uart.h>
1956 +#include <asm/arch/int_ctrl.h>
1957 +
1958 +// #define DEBUG           1
1959 +#define UART_NR                1
1960 +
1961 +
1962 +#define SERIAL_SL2312_NAME     "ttySL"
1963 +#define SERIAL_SL2312_MAJOR    204
1964 +#define SERIAL_SL2312_MINOR    40      /* Temporary - will change in future */
1965 +#define SERIAL_SL2312_NR       UART_NR
1966 +#define UART_PORT_SIZE 0x50
1967 +
1968 +#define SL2312_NO_PORTS         UART_NR
1969 +#define SL2312_ISR_PASS_LIMIT  256
1970 +
1971 +/*
1972 + * Access macros for the SL2312 UARTs
1973 + */
1974 +#define UART_GET_INT_STATUS(p) (inl(UART_IIR((p)->membase)) & 0x0F)      // interrupt identification
1975 +#define UART_PUT_IER(p, c)      outl(c,UART_IER((p)->membase))    // interrupt enable
1976 +#define UART_GET_IER(p)         inl(UART_IER((p)->membase))
1977 +#define UART_PUT_CHAR(p, c)     outl(c,UART_THR((p)->membase))    // transmitter holding
1978 +#define UART_GET_CHAR(p)        inl(UART_RBR((p)->membase))       // receive buffer
1979 +#define UART_GET_LSR(p)         inl(UART_LSR((p)->membase))       // line status
1980 +#define UART_GET_MSR(p)         inl(UART_MSR((p)->membase))       // modem status
1981 +#define UART_GET_MCR(p)         inl(UART_MCR((p)->membase))       // modem control
1982 +#define UART_PUT_MCR(p, c)      outl(c,UART_MCR((p)->membase))
1983 +#define UART_GET_LCR(p)         inl(UART_LCR((p)->membase))       // mode control
1984 +#define UART_PUT_LCR(p, c)      outl(c,UART_LCR((p)->membase))
1985 +#define UART_GET_DIV_HI(p)     inl(UART_DIV_HI((p)->membase))
1986 +#define UART_PUT_DIV_HI(p, c)  outl(c,UART_DIV_HI((p)->membase))
1987 +#define UART_GET_DIV_LO(p)     inl(UART_DIV_LO((p)->membase))
1988 +#define UART_PUT_DIV_LO(p, c)  outl(c,UART_DIV_LO((p)->membase))
1989 +#define UART_PUT_MDR(p, c)      outl(c,UART_MDR((p)->membase))
1990 +#define UART_RX_DATA(s)                ((s) & UART_LSR_DR)
1991 +#define UART_TX_READY(s)       ((s) & UART_LSR_THRE)
1992 +
1993 +
1994 +static void sl2312_stop_tx(struct uart_port *port)
1995 +{
1996 +        unsigned int reg;
1997 +
1998 +//        printk("sl2312 stop tx : \n");
1999 +        reg = UART_GET_IER(port);
2000 +        reg &= ~(UART_IER_TE);
2001 +       UART_PUT_IER(port, reg);
2002 +}
2003 +
2004 +static void sl2312_stop_rx(struct uart_port *port)
2005 +{
2006 +        unsigned int reg;
2007 +
2008 +//        printk("sl2312 stop rx : \n");
2009 +        reg = UART_GET_IER(port);
2010 +        reg &= ~(UART_IER_DR);
2011 +       UART_PUT_IER(port, reg);
2012 +
2013 +}
2014 +
2015 +static void sl2312_enable_ms(struct uart_port *port)
2016 +{
2017 +        unsigned int reg;
2018 +
2019 +//        printk("sl2312 enable ms : \n");
2020 +
2021 +        reg = UART_GET_IER(port);
2022 +        reg |= (UART_IER_MS);
2023 +       UART_PUT_IER(port, reg);
2024 +
2025 +}
2026 +
2027 +static void
2028 +sl2312_rx_chars(struct uart_port *port)
2029 +{
2030 +       struct tty_struct *tty = port->info->tty;
2031 +       unsigned int status, mask, ch, flg, ignored = 0;
2032 +
2033 +
2034 + //       printk("sl2312_rx_chars : \n");
2035 +       status = UART_GET_LSR(port);
2036 +       while (UART_RX_DATA(status)) {
2037 +
2038 +               /*
2039 +                * We need to read rds before reading the
2040 +                * character from the fifo
2041 +                */
2042 +               ch = UART_GET_CHAR(port);
2043 +               port->icount.rx++;
2044 +
2045 +               //if (tty->flip.count >= TTY_FLIPBUF_SIZE)
2046 +               if (tty && !tty_buffer_request_room(tty, 1))
2047 +                       goto ignore_char;
2048 +
2049 +               flg = TTY_NORMAL;
2050 +
2051 +               /*
2052 +                * Note that the error handling code is
2053 +                * out of the main execution path
2054 +                */
2055 +
2056 +               if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
2057 +                       goto handle_error;
2058 +               if (uart_handle_sysrq_char(port, ch))
2059 +                       goto ignore_char;
2060 +
2061 +       error_return:
2062 +               //*tty->flip.flag_buf_ptr++ = flg;
2063 +               //*tty->flip.char_buf_ptr++ = ch;
2064 +               //tty->flip.count++;
2065 +               tty_insert_flip_char(tty, ch, flg);
2066 +       ignore_char:
2067 +               status = UART_GET_LSR(port);
2068 +       } // end of while
2069 +out:
2070 +       tty_flip_buffer_push(tty);
2071 +       return;
2072 +
2073 +handle_error:
2074 +       if (status & UART_LSR_BI) {
2075 +               status &= ~(UART_LSR_FE);
2076 +               port->icount.brk++;
2077 +
2078 +#ifdef SUPPORT_SYSRQ
2079 +               if (uart_handle_break(port))
2080 +                       goto ignore_char;
2081 +#endif
2082 +       } else if (status & UART_LSR_PE)
2083 +               port->icount.parity++;
2084 +       else if (status & UART_LSR_FE)
2085 +               port->icount.frame++;
2086 +
2087 +       if (status & UART_LSR_OE)
2088 +               port->icount.overrun++;
2089 +
2090 +       if (status & port->ignore_status_mask) {
2091 +               if (++ignored > 100)
2092 +                       goto out;
2093 +               goto ignore_char;
2094 +       }
2095 +
2096 +       mask = status & port->read_status_mask;
2097 +
2098 +       if (mask & UART_LSR_BI)
2099 +               flg = TTY_BREAK;
2100 +       else if (mask & UART_LSR_PE)
2101 +               flg = TTY_PARITY;
2102 +       else if (mask & UART_LSR_FE)
2103 +               flg = TTY_FRAME;
2104 +
2105 +       if (status & UART_LSR_OE) {
2106 +               /*
2107 +                * CHECK: does overrun affect the current character?
2108 +                * ASSUMPTION: it does not.
2109 +                */
2110 +               //*tty->flip.flag_buf_ptr++ = flg;
2111 +               //*tty->flip.char_buf_ptr++ = ch;
2112 +               //tty->flip.count++;
2113 +
2114 +               tty_insert_flip_char(tty, 0, TTY_BREAK);
2115 +
2116 +               // if (tty->flip.count >= TTY_FLIPBUF_SIZE)
2117 +               if (tty_buffer_request_room(tty, 1))
2118 +                       goto ignore_char;
2119 +               ch = 0;
2120 +               flg = TTY_OVERRUN;
2121 +       }
2122 +#ifdef SUPPORT_SYSRQ
2123 +       port->sysrq = 0;
2124 +#endif
2125 +       goto error_return;
2126 +}
2127 +
2128 +static void sl2312_tx_chars(struct uart_port *port)
2129 +{
2130 +       struct circ_buf *xmit = &port->info->xmit;
2131 +       int count;
2132 +
2133 +
2134 +       if (port->x_char) {
2135 +               while(!(UART_GET_LSR(port)&UART_LSR_THRE));
2136 +               UART_PUT_CHAR(port, port->x_char);
2137 +               port->icount.tx++;
2138 +               port->x_char = 0;
2139 +
2140 +               return;
2141 +       }
2142 +       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
2143 +               sl2312_stop_tx(port);
2144 +
2145 +               return;
2146 +       }
2147 +
2148 +       count = port->fifosize >> 1;
2149 +       do {
2150 +               while(!(UART_GET_LSR(port)&UART_LSR_THRE));
2151 +               UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
2152 +               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
2153 +               port->icount.tx++;
2154 +               if (uart_circ_empty(xmit))
2155 +                       break;
2156 +       } while (--count > 0);
2157 +
2158 +       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
2159 +               uart_write_wakeup(port);
2160 +
2161 +       if (uart_circ_empty(xmit))
2162 +               sl2312_stop_tx(port);
2163 +
2164 +}
2165 +
2166 +static void sl2312_start_tx(struct uart_port *port)
2167 +{
2168 +        unsigned int reg;
2169 +
2170 +//        printk("sl2312 start tx : \n");
2171 +        reg = UART_GET_IER(port);
2172 +        reg |= (UART_IER_TE);
2173 +       UART_PUT_IER(port, reg);
2174 +
2175 +       sl2312_tx_chars(port);
2176 +}
2177 +
2178 +static void sl2312_modem_status(struct uart_port *port)
2179 +{
2180 +       unsigned int status;
2181 +
2182 +//        printk("it8712 modem status : \n");
2183 +
2184 +       status = UART_GET_MSR(port);
2185 +
2186 +       if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
2187 +                      UART_MSR_TERI | UART_MSR_DDCD)))
2188 +               return;
2189 +
2190 +        if (status & UART_MSR_DDCD)
2191 +                uart_handle_dcd_change(port, status & UART_MSR_DCD);
2192 +
2193 +        if (status & UART_MSR_DDSR)
2194 +                port->icount.dsr++;
2195 +
2196 +        if (status & UART_MSR_DCTS)
2197 +                uart_handle_cts_change(port, status & UART_MSR_CTS);
2198 +
2199 +       wake_up_interruptible(&port->info->delta_msr_wait);
2200 +
2201 +}
2202 +
2203 +static irqreturn_t sl2312_int(int irq, void *dev_id)
2204 +{
2205 +       struct uart_port *port = dev_id;
2206 +       unsigned int status, pass_counter = 0;
2207 +
2208 +       status = UART_GET_INT_STATUS(port);
2209 +       do {
2210 +               switch(status)
2211 +               {
2212 +                  case UART_IIR_DR:
2213 +                  case UART_IIR_RLS:
2214 +                       sl2312_rx_chars(port);
2215 +                  break;
2216 +                  case UART_IIR_TE:
2217 +                       sl2312_tx_chars(port);
2218 +                  break;
2219 +                  case UART_IIR_MODEM:
2220 +                       sl2312_modem_status(port);
2221 +                  break;
2222 +                  default:
2223 +                  break;
2224 +               }
2225 +               if (pass_counter++ > SL2312_ISR_PASS_LIMIT)
2226 +                       break;
2227 +
2228 +               status = UART_GET_INT_STATUS(port);
2229 +       } while (status);
2230 +
2231 +       return IRQ_HANDLED;
2232 +}
2233 +
2234 +static u_int sl2312_tx_empty(struct uart_port *port)
2235 +{
2236 +//        printk("sl2312 tx empty : \n");
2237 +
2238 +       return ((UART_GET_LSR(port) & UART_LSR_TE)? TIOCSER_TEMT : 0);
2239 +}
2240 +
2241 +static u_int sl2312_get_mctrl(struct uart_port *port)
2242 +{
2243 +       unsigned int result = 0;
2244 +       unsigned int status;
2245 +
2246 +//        printk("sl2312 get mctrl : \n");
2247 +
2248 +       status = UART_GET_MSR(port);
2249 +       if (status & UART_MSR_DCD)
2250 +               result |= TIOCM_CAR;
2251 +       if (status & UART_MSR_DSR)
2252 +               result |= TIOCM_DSR;
2253 +       if (status & UART_MSR_CTS)
2254 +               result |= TIOCM_CTS;
2255 +       if (status & UART_MSR_RI)
2256 +               result |= TIOCM_RI;
2257 +
2258 +       return result;
2259 +}
2260 +
2261 +static void sl2312_set_mctrl_null(struct uart_port *port, u_int mctrl)
2262 +{
2263 +}
2264 +
2265 +static void sl2312_break_ctl(struct uart_port *port, int break_state)
2266 +{
2267 +       unsigned int lcr;
2268 +
2269 +//        printk("sl2312 break ctl : \n");
2270 +
2271 +       lcr = UART_GET_LCR(port);
2272 +       if (break_state == -1)
2273 +               lcr |= UART_LCR_SETBREAK;
2274 +       else
2275 +               lcr &= ~UART_LCR_SETBREAK;
2276 +       UART_PUT_LCR(port, lcr);
2277 +}
2278 +
2279 +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
2280 +{
2281 +       u_int quot;
2282 +
2283 +       /* Special case: B0 rate */
2284 +       if (!baud)
2285 +               baud = 9600;
2286 +
2287 +       quot = (port->uartclk / (16 * baud)-1)  ;
2288 +
2289 +       return quot;
2290 +}
2291 +
2292 +static void sl2312_set_termios(struct uart_port *port, struct ktermios *termios,
2293 +                               struct ktermios *old)
2294 +{
2295 +       unsigned int  uart_mc, old_ier, baud, quot;
2296 +       unsigned long flags;
2297 +
2298 +        termios->c_cflag |= CREAD;
2299 +#ifdef DEBUG
2300 +       printk("it8712_set_cflag(0x%x) called\n", cflag);
2301 +#endif
2302 +        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
2303 +        quot = (port->uartclk / (16 * baud))  ;
2304 +        //uart_get_divisor(port, baud);
2305 +
2306 +       /* byte size and parity */
2307 +       switch (termios->c_cflag & CSIZE) {
2308 +       case CS5:
2309 +              uart_mc = UART_LCR_LEN5;
2310 +              break;
2311 +       case CS6:
2312 +              uart_mc = UART_LCR_LEN6;
2313 +              break;
2314 +       case CS7:
2315 +              uart_mc = UART_LCR_LEN7;
2316 +              break;
2317 +       default: // CS8
2318 +              uart_mc = UART_LCR_LEN8;
2319 +              break;
2320 +       }
2321 +
2322 +       if (termios->c_cflag & CSTOPB)
2323 +               uart_mc|= UART_LCR_STOP;
2324 +       if (termios->c_cflag & PARENB) {
2325 +               uart_mc |= UART_LCR_EVEN;
2326 +               if (!(termios->c_cflag & PARODD))
2327 +                       uart_mc |= UART_LCR_ODD;
2328 +       }
2329 +
2330 +    spin_lock_irqsave(&port->lock, flags);
2331 +        /*
2332 +         * Update the per-port timeout
2333 +         */
2334 +        uart_update_timeout(port, termios->c_cflag, baud);
2335 +       port->read_status_mask = UART_LSR_OE;
2336 +       if (termios->c_iflag & INPCK)
2337 +               port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
2338 +       if (termios->c_iflag & (BRKINT | PARMRK))
2339 +               port->read_status_mask |= UART_LSR_BI;
2340 +
2341 +       /*
2342 +        * Characters to ignore
2343 +        */
2344 +       port->ignore_status_mask = 0;
2345 +       if (termios->c_iflag & IGNPAR)
2346 +               port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
2347 +       if (termios->c_iflag & IGNBRK) {
2348 +               port->ignore_status_mask |= UART_LSR_BI;
2349 +               /*
2350 +                * If we're ignoring parity and break indicators,
2351 +                * ignore overruns to (for real raw support).
2352 +                */
2353 +               if (termios->c_iflag & IGNPAR)
2354 +                       port->ignore_status_mask |= UART_LSR_OE;
2355 +       }
2356 +
2357 +       //save_flags(flags); cli();
2358 +       old_ier = UART_GET_IER(port);
2359 +
2360 +        if(UART_ENABLE_MS(port, termios->c_cflag))
2361 +             old_ier |= UART_IER_MS;
2362 +
2363 +       /* Set baud rate */
2364 +       UART_PUT_LCR(port, UART_LCR_DLAB);
2365 +       UART_PUT_DIV_LO(port, (quot & 0xff));
2366 +       UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
2367 +
2368 +       UART_PUT_LCR(port, uart_mc);
2369 +       UART_PUT_IER(port, old_ier);
2370 +
2371 +       //restore_flags(flags);
2372 +       spin_unlock_irqrestore(&port->lock, flags);
2373 +}
2374 +
2375 +
2376 +
2377 +static int sl2312_startup(struct uart_port *port)
2378 +{
2379 +       int retval;
2380 +       unsigned int regs;
2381 +
2382 +//        printk("sl2312 startup : \n");
2383 +
2384 +       /*
2385 +        * Use iobase to store a pointer to info. We need this to start a
2386 +        * transmission as the tranmittr interrupt is only generated on
2387 +        * the transition to the idle state
2388 +        */
2389 +
2390 +       /*
2391 +        * Allocate the IRQ
2392 +        */
2393 +       retval = request_irq(port->irq, sl2312_int, IRQF_DISABLED, "sl2312", port);
2394 +       if (retval)
2395 +               return retval;
2396 +
2397 +        /* setup interrupt controller  */
2398 +        regs = *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
2399 +        regs &= ~(IRQ_UART_MASK);
2400 +        *((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
2401 +        regs = *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
2402 +        regs &= ~(IRQ_UART_MASK);
2403 +        *((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
2404 +        *((volatile unsigned int *)IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_UART_MASK);
2405 +
2406 +       /*
2407 +        * Finally, enable interrupts. Use the TII interrupt to minimise
2408 +        * the number of interrupts generated. If higher performance is
2409 +        * needed, consider using the TI interrupt with a suitable FIFO
2410 +        * threshold
2411 +        */
2412 +       UART_PUT_IER(port, (UART_IER_DR|UART_IER_TE));
2413 +
2414 +       return 0;
2415 +}
2416 +
2417 +static void sl2312_shutdown(struct uart_port *port)
2418 +{
2419 +//        printk("sl2312 shutdown : \n");
2420 +
2421 +       /*
2422 +        * disable all interrupts, disable the port
2423 +        */
2424 +       UART_PUT_IER(port, 0x0);
2425 +
2426 +       /* disable break condition and fifos */
2427 +//     UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
2428 +
2429 +       /*
2430 +        * Free the interrupt
2431 +        */
2432 +       free_irq(port->irq, port);
2433 +}
2434 +
2435 +static const char *sl2312_type(struct uart_port *port)
2436 +{
2437 +       return port->type == PORT_SL2312 ? "SL2312" : NULL;
2438 +}
2439 +
2440 +/*
2441 + * Release the memory region(s) being used by 'port'
2442 + */
2443 +static void sl2312_release_port(struct uart_port *port)
2444 +{
2445 +//        printk("sl2312 release port : \n");
2446 +
2447 +       release_mem_region(port->mapbase, UART_PORT_SIZE);
2448 +}
2449 +
2450 +/*
2451 + * Request the memory region(s) being used by 'port'
2452 + */
2453 +static int sl2312_request_port(struct uart_port *port)
2454 +{
2455 +       return request_mem_region(port->mapbase, UART_PORT_SIZE,
2456 +                                   "serial_sl2312") != NULL ? 0 : -EBUSY;
2457 +}
2458 +
2459 +/*
2460 + * Configure/autoconfigure the port.
2461 + */
2462 +static void sl2312_config_port(struct uart_port *port, int flags)
2463 +{
2464 +
2465 +       if (flags & UART_CONFIG_TYPE) {
2466 +               if (sl2312_request_port(port) == 0)
2467 +                       port->type = PORT_SL2312;
2468 +       }
2469 +}
2470 +
2471 +/*
2472 + * verify the new serial_struct (for TIOCSSERIAL).
2473 + */
2474 +static int sl2312_verify_port(struct uart_port *port, struct serial_struct *ser)
2475 +{
2476 +       int ret = 0;
2477 +
2478 +       if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
2479 +               ret = -EINVAL;
2480 +       if (ser->irq < 0 || ser->irq >= NR_IRQS)
2481 +               ret = -EINVAL;
2482 +       if (ser->baud_base < 9600)
2483 +               ret = -EINVAL;
2484 +       return ret;
2485 +}
2486 +
2487 +static struct uart_ops sl2312_pops = {
2488 +       .tx_empty               =sl2312_tx_empty,
2489 +       .set_mctrl              =sl2312_set_mctrl_null,
2490 +       .get_mctrl              =sl2312_get_mctrl,
2491 +       .stop_tx                =sl2312_stop_tx,
2492 +       .start_tx               =sl2312_start_tx,
2493 +       .stop_rx                =sl2312_stop_rx,
2494 +       .enable_ms              =sl2312_enable_ms,
2495 +       .break_ctl              =sl2312_break_ctl,
2496 +       .startup                =sl2312_startup,
2497 +       .shutdown               =sl2312_shutdown,
2498 +       .set_termios    =sl2312_set_termios,
2499 +       .type                   =sl2312_type,
2500 +       .release_port   =sl2312_release_port,
2501 +       .request_port   =sl2312_request_port,
2502 +       .config_port    =sl2312_config_port,
2503 +       .verify_port    =sl2312_verify_port,
2504 +};
2505 +
2506 +#ifdef CONFIG_ARCH_SL2312
2507 +
2508 +static struct uart_port sl2312_ports[UART_NR] = {
2509 +       {
2510 +               membase:        (void *)IO_ADDRESS(SL2312_UART_BASE),
2511 +               mapbase:        SL2312_UART_BASE,
2512 +               iotype:         SERIAL_IO_MEM,
2513 +               irq:            IRQ_UART,
2514 +               uartclk:        UART_CLK,
2515 +               fifosize:       16,
2516 +               ops:            &sl2312_pops,
2517 +               flags:          ASYNC_BOOT_AUTOCONF,
2518 +       }
2519 +};
2520 +
2521 +#endif
2522 +
2523 +#ifdef CONFIG_SERIAL_SL2312_CONSOLE
2524 +#ifdef used_and_not_const_char_pointer
2525 +static int sl2312_console_read(struct uart_port *port, char *s, u_int count)
2526 +{
2527 +       unsigned int status;
2528 +       int c;
2529 +#ifdef DEBUG
2530 +       printk("sl2312_console_read() called\n");
2531 +#endif
2532 +
2533 +       c = 0;
2534 +       while (c < count) {
2535 +               status = UART_GET_LSR(port);
2536 +               if (UART_RX_DATA(status)) {
2537 +                       *s++ = UART_GET_CHAR(port);
2538 +                       c++;
2539 +               } else {
2540 +                       // nothing more to get, return
2541 +                       return c;
2542 +               }
2543 +       }
2544 +       // return the count
2545 +       return c;
2546 +}
2547 +#endif
2548 +static void sl2312_console_write(struct console *co, const char *s, unsigned count)
2549 +{
2550 +#ifdef CONFIG_ARCH_SL2312
2551 +       struct uart_port *port = sl2312_ports + co->index;
2552 +       unsigned int status, old_ies;
2553 +       int i;
2554 +
2555 +       /*
2556 +        *      First save the CR then disable the interrupts
2557 +        */
2558 +       old_ies = UART_GET_IER(port);
2559 +       UART_PUT_IER(port,0x0);
2560 +
2561 +       /*
2562 +        *      Now, do each character
2563 +        */
2564 +       for (i = 0; i < count; i++) {
2565 +               do {
2566 +                       status = UART_GET_LSR(port);
2567 +               } while (!UART_TX_READY(status));
2568 +               UART_PUT_CHAR(port, s[i]);
2569 +               if (s[i] == '\n') {
2570 +                       do {
2571 +                               status = UART_GET_LSR(port);
2572 +                       } while (!UART_TX_READY(status));
2573 +                       UART_PUT_CHAR(port, '\r');
2574 +               }
2575 +       }
2576 +
2577 +       /*
2578 +        *      Finally, wait for transmitter to become empty
2579 +        *      and restore the IES
2580 +        */
2581 +       do {
2582 +               status = UART_GET_LSR(port);
2583 +       } while (!(status&UART_LSR_TE));
2584 +       UART_PUT_IER(port, old_ies);
2585 +#endif
2586 +}
2587 +
2588 +#if 0
2589 +static void sl2312_console_device(struct console *co,int *index)
2590 +{
2591 +
2592 +       struct uart_driver *p = co->data;
2593 +    *index = co->index;
2594 +    return p->tty_driver;
2595 +
2596 +}
2597 +#endif
2598 +
2599 +static void /*__init*/ sl2312_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
2600 +{
2601 +//     printk("sl2312 console get options : \n");
2602 +
2603 +       u_int uart_mc, quot;
2604 +       uart_mc= UART_GET_MCR(port);
2605 +
2606 +       *parity = 'n';
2607 +       if (uart_mc & UART_LCR_PE) {
2608 +               if (uart_mc & UART_LCR_EVEN)
2609 +                       *parity = 'e';
2610 +               else
2611 +                       *parity = 'o';
2612 +       }
2613 +
2614 +       switch (uart_mc & UART_LCR_MSK){
2615 +
2616 +       case UART_LCR_LEN5:
2617 +               *bits = 5;
2618 +               break;
2619 +       case UART_LCR_LEN6:
2620 +               *bits = 6;
2621 +               break;
2622 +       case UART_LCR_LEN7:
2623 +               *bits = 7;
2624 +               break;
2625 +       case UART_LCR_LEN8:
2626 +               *bits = 8;
2627 +               break;
2628 +       }
2629 +       UART_PUT_MCR(port,UART_LCR_DLAB);
2630 +       quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
2631 +       UART_PUT_MCR(port,uart_mc);
2632 +       *baud = port->uartclk / (16 *quot );
2633 +}
2634 +
2635 +static int __init sl2312_console_setup(struct console *co, char *options)
2636 +{
2637 +       struct uart_port *port;
2638 +       int baud = 19200;
2639 +       int bits = 8;
2640 +       int parity = 'n';
2641 +       int flow= 'n';
2642 +
2643 +       printk("sl2312 console setup : \n");
2644 +
2645 +#ifdef CONFIG_ARCH_SL2312
2646 +       /*
2647 +        * Check whether an invalid uart number has been specified, and
2648 +        * if so, search for the first available port that does have
2649 +        * console support.
2650 +        */
2651 +       port = uart_get_console(sl2312_ports,SL2312_NO_PORTS,co);
2652 +#else
2653 +       return -ENODEV;
2654 +#endif
2655 +
2656 +       if (options)
2657 +               uart_parse_options(options, &baud, &parity, &bits, &flow);
2658 +       else
2659 +               sl2312_console_get_options(port, &baud, &parity, &bits);
2660 +
2661 +       return uart_set_options(port, co, baud, parity, bits, flow);
2662 +}
2663 +
2664 +extern struct uart_driver sl2312_reg;
2665 +static struct console sl2312_console = {
2666 +       .name      = SERIAL_SL2312_NAME,
2667 +       .write          = sl2312_console_write,
2668 +       .device         = uart_console_device,
2669 +//     .device         = sl2312_console_device,
2670 +       .setup          = sl2312_console_setup,
2671 +//     .flags          = (CON_PRINTBUFFER|CON_ENABLED),
2672 +       .flags          = CON_PRINTBUFFER,
2673 +       .index          = -1,
2674 +       .data       = &sl2312_reg,
2675 +};
2676 +
2677 +static int __init sl2312_console_init(void)
2678 +{
2679 +       register_console(&sl2312_console);
2680 +       return 0;
2681 +
2682 +}
2683 +
2684 +console_initcall(sl2312_console_init);
2685 +
2686 +#define SL2312_CONSOLE &sl2312_console
2687 +#else
2688 +#define SL2312_CONSOLE NULL
2689 +#endif
2690 +
2691 +// static
2692 +struct uart_driver sl2312_reg = {
2693 +       .owner         = NULL,
2694 +       .driver_name    = SERIAL_SL2312_NAME,
2695 +       .dev_name               = SERIAL_SL2312_NAME,
2696 +       .major          = SERIAL_SL2312_MAJOR,
2697 +       .minor                  = SERIAL_SL2312_MINOR,
2698 +       .nr                             = UART_NR,
2699 +       .cons                   = SL2312_CONSOLE,
2700 +};
2701 +
2702 +static int __init sl2312_init(void)
2703 +{
2704 +       int result;
2705 +       //printk("serial_it8712: it871212_init \n");
2706 +
2707 +        result = uart_register_driver(&sl2312_reg);
2708 +        if(result)
2709 +             return result;
2710 +       result = uart_add_one_port(&sl2312_reg, &sl2312_ports[0]);
2711 +
2712 +        return result;
2713 +}
2714 +
2715 +
2716 +__initcall(sl2312_init);
2717 Index: linux-2.6.23.16/include/linux/serial_core.h
2718 ===================================================================
2719 --- linux-2.6.23.16.orig/include/linux/serial_core.h    2008-03-15 17:59:22.566564448 +0200
2720 +++ linux-2.6.23.16/include/linux/serial_core.h 2008-03-15 17:59:53.568330991 +0200
2721 @@ -147,6 +147,10 @@
2722  #define PORT_SB1250_DUART      77
2723  
2724  
2725 +/* Storlink Soc */
2726 +#define PORT_SL2312     72
2727 +#define PORT_IT8712     73
2728 +
2729  #ifdef __KERNEL__
2730  
2731  #include <linux/compiler.h>
2732 Index: linux-2.6.23.16/drivers/char/Makefile
2733 ===================================================================
2734 --- linux-2.6.23.16.orig/drivers/char/Makefile  2008-03-15 17:59:22.566564448 +0200
2735 +++ linux-2.6.23.16/drivers/char/Makefile       2008-03-17 12:19:43.252524398 +0200
2736 @@ -70,6 +70,16 @@
2737  obj-$(CONFIG_APPLICOM)         += applicom.o
2738  obj-$(CONFIG_SONYPI)           += sonypi.o
2739  obj-$(CONFIG_RTC)              += rtc.o
2740 +
2741 +###  for Storlink SoC ###
2742 +obj-$(CONFIG_SL2312_RTC) += sl2312_rtc.o
2743 +obj-$(CONFIG_IT8712_GPIO)   += it8712_gpio.o
2744 +obj-$(CONFIG_GEMINI_GPIO)   += gemini_gpio.o
2745 +obj-$(CONFIG_GEMINI_PWC) += gemini_pwr.o
2746 +obj-$(CONFIG_GEMINI_CIR)    += gemini_cir.o
2747 +obj-$(CONFIG_GEMINI_I2S)    += gemini_i2s.o
2748 +obj-$(CONFIG_SL2312_WATCHDOG) += sl2312_wd.o
2749 +
2750  obj-$(CONFIG_HPET)             += hpet.o
2751  obj-$(CONFIG_GEN_RTC)          += genrtc.o
2752  obj-$(CONFIG_EFI_RTC)          += efirtc.o
2753 Index: linux-2.6.23.16/drivers/serial/Kconfig
2754 ===================================================================
2755 --- linux-2.6.23.16.orig/drivers/serial/Kconfig 2008-03-15 17:59:22.566564448 +0200
2756 +++ linux-2.6.23.16/drivers/serial/Kconfig      2008-03-15 17:59:53.568330991 +0200
2757 @@ -280,6 +280,56 @@
2758  
2759  comment "Non-8250 serial port support"
2760  
2761 +config SERIAL_SL2312
2762 +       bool "SL2312  serial port (sl2312) support"
2763 +       depends on ARCH_SL2312
2764 +       select SERIAL_CORE
2765 +       select SERIAL_SL2312_CONSOLE
2766 +       help
2767 +         Say Y here if you want to use the hard logic uart on SWORD. This
2768 +         driver also supports soft logic implentations of this uart core.
2769 +
2770 +config SERIAL_SL2312_CONSOLE
2771 +       bool "Support for console on SL2312 serial port"
2772 +       depends on SERIAL_SL2312
2773 +       select SERIAL_CORE_CONSOLE
2774 +       help
2775 +        Say Y here if you want to support a serial console on an SWORD
2776 +        hard logic uart or uart00 IP core.
2777 +
2778 +        Even if you say Y here, the currently visible virtual console
2779 +        (/dev/tty0) will still be used as the system console by default, but
2780 +        you can alter that using a kernel command line option such as
2781 +        "console=ttySL0". (Try "man bootparam" or see the documentation of
2782 +        your boot loader (lilo or loadlin) about how to pass options to the
2783 +        kernel at boot time.)
2784 +
2785 +
2786 +config SERIAL_IT8712
2787 +       bool "Sl2312 serial port(IT8712) support"
2788 +       depends on ARM && ARCH_SL2312 && SL2312_LPC
2789 +       select SERIAL_CORE
2790 +       select SERIAL_IT8712_CONSOLE
2791 +       help
2792 +         Say Y here if you want to use the hard logic uart on Excalibur. This
2793 +         driver also supports soft logic implentations of this uart core.
2794 +
2795 +config SERIAL_IT8712_CONSOLE
2796 +       bool "Support for console on Sword serial port(IT8712)"
2797 +       depends on SERIAL_IT8712
2798 +       select SERIAL_CORE_CONSOLE
2799 +       help
2800 +         Say Y here if you want to support a serial console on an Excalibur
2801 +         hard logic uart or uart00 IP core.
2802 +
2803 +         Even if you say Y here, the currently visible virtual console
2804 +         (/dev/tty0) will still be used as the system console by default, but
2805 +         you can alter that using a kernel command line option such as
2806 +         "console=ttySI0". (Try "man bootparam" or see the documentation of
2807 +         your boot loader (lilo or loadlin) about how to pass options to the
2808 +         kernel at boot time.)
2809 +
2810 +
2811  config SERIAL_AMBA_PL010
2812         tristate "ARM AMBA PL010 serial port support"
2813         depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
2814 Index: linux-2.6.23.16/drivers/serial/Makefile
2815 ===================================================================
2816 --- linux-2.6.23.16.orig/drivers/serial/Makefile        2008-03-15 17:59:22.566564448 +0200
2817 +++ linux-2.6.23.16/drivers/serial/Makefile     2008-03-15 17:59:53.568330991 +0200
2818 @@ -62,5 +62,7 @@
2819  obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
2820  obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
2821  obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
2822 +obj-$(CONFIG_SERIAL_IT8712) += it8712.o
2823 +obj-$(CONFIG_SERIAL_SL2312) += serial_sl2312.o
2824  obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
2825  obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o