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