2 +++ b/drivers/serial/it8712.c
5 + * linux/drivers/char/serial_uart00.c
7 + * Driver for UART00 serial ports
9 + * Based on drivers/char/serial_amba.c, by ARM Limited &
10 + * Deep Blue Solutions Ltd.
11 + * Copyright 2001 Altera Corporation
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.
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.
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
27 + * $Id: it8712.c,v 1.2 2006/06/06 06:36:04 middle Exp $
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>
41 +#include <asm/uaccess.h>
42 +#include <asm/bitops.h>
43 +#include <asm/sizes.h>
45 +#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
46 +#define SUPPORT_SYSRQ
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>
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
65 +#define IT8712_NO_PORTS UART_NR
66 +#define IT8712_ISR_PASS_LIMIT 256
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))
80 + * Access macros for the SL2312 UARTs
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)
102 +static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
106 + //printk("it8712 stop tx : \n");
107 + reg = UART_GET_IER(port);
108 + reg &= ~(UART_IER_THRI);
109 + UART_PUT_IER(port, reg);
112 +static void it8712_stop_rx(struct uart_port *port)
116 + //printk("it8712 stop rx : \n");
117 + reg = UART_GET_IER(port);
118 + reg &= ~(UART_IER_RDI);
119 + UART_PUT_IER(port, reg);
123 +static void it8712_enable_ms(struct uart_port *port)
127 + //printk("it8712 enable ms : \n");
129 + reg = UART_GET_IER(port);
130 + reg |= (UART_IER_MSI);
131 + UART_PUT_IER(port, reg);
135 +static void it8712_rx_chars(struct uart_port *port, struct pt_regs *regs)
137 + struct tty_struct *tty = port->info->tty;
138 + unsigned int status, mask, ch, flg, ignored = 0;
140 + // printk("it8712_rx_chars : \n");
141 + status = UART_GET_LSR(port);
142 + while (UART_RX_DATA(status)) {
145 + * We need to read rds before reading the
146 + * character from the fifo
148 + ch = UART_GET_CHAR(port);
151 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
157 + * Note that the error handling code is
158 + * out of the main execution path
161 + if (status & (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_DE))
163 + if (uart_handle_sysrq_char(port, ch, regs))
167 + *tty->flip.flag_buf_ptr++ = flg;
168 + *tty->flip.char_buf_ptr++ = ch;
171 + status = UART_GET_LSR(port);
174 + tty_flip_buffer_push(tty);
178 + if (status & UART_LSR_BI) {
179 + status &= ~(UART_LSR_FE);
180 + port->icount.brk++;
182 +#ifdef SUPPORT_SYSRQ
183 + if (uart_handle_break(port))
186 + } else if (status & UART_LSR_PE)
187 + port->icount.parity++;
188 + else if (status & UART_LSR_FE)
189 + port->icount.frame++;
191 + if (status & UART_LSR_OE)
192 + port->icount.overrun++;
194 + if (status & port->ignore_status_mask) {
195 + if (++ignored > 100)
200 + mask = status & port->read_status_mask;
202 + if (mask & UART_LSR_BI)
204 + else if (mask & UART_LSR_PE)
206 + else if (mask & UART_LSR_FE)
209 + if (status & UART_LSR_OE) {
211 + * CHECK: does overrun affect the current character?
212 + * ASSUMPTION: it does not.
214 + *tty->flip.flag_buf_ptr++ = flg;
215 + *tty->flip.char_buf_ptr++ = ch;
217 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
222 +#ifdef SUPPORT_SYSRQ
228 +static void it8712_tx_chars(struct uart_port *port)
230 + struct circ_buf *xmit = &port->info->xmit;
233 + if (port->x_char) {
234 + while(!(UART_GET_LSR(port)&UART_LSR_THRE));
235 + UART_PUT_CHAR(port, port->x_char);
241 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
242 + it8712_stop_tx(port, 0);
246 + count = port->fifosize >> 1;
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);
252 + if (uart_circ_empty(xmit))
254 + } while (--count > 0);
256 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
257 + uart_write_wakeup(port);
259 + if (uart_circ_empty(xmit))
260 + it8712_stop_tx(port, 0);
263 +static void it8712_start_tx(struct uart_port *port, unsigned int tty_start)
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);
274 +static void it8712_modem_status(struct uart_port *port)
276 + unsigned int status;
278 +// printk("it8712 modem status : \n");
280 + status = UART_GET_MSR(port);
282 + if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
283 + UART_MSR_TERI | UART_MSR_DDCD)))
286 + if (status & UART_MSR_DDCD)
287 + uart_handle_dcd_change(port, status & UART_MSR_DCD);
289 + if (status & UART_MSR_DDSR)
290 + port->icount.dsr++;
292 + if (status & UART_MSR_DCTS)
293 + uart_handle_cts_change(port, status & UART_MSR_CTS);
295 + wake_up_interruptible(&port->info->delta_msr_wait);
299 +static irqreturn_t it8712_int(int irq, void *dev_id, struct pt_regs *regs)
301 + struct uart_port *port = dev_id;
302 + unsigned int status, pass_counter = 0, data;
305 + data = LPC_SERIAL_IRQ_STATUS;
306 + if((data&0x10)==0x10)
308 + status = UART_GET_INT_STATUS(port);
310 +// printk("it8712_int: status %x \n", status);
314 + case UART_IIR_RLSI:
315 + case UART_IIR_RCTO:
316 + it8712_rx_chars(port, regs);
318 + case UART_IIR_THRI:
319 + it8712_tx_chars(port);
322 + it8712_modem_status(port);
327 + if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
330 + status = UART_GET_INT_STATUS(port);
335 + status |= (IRQ_LPC_MASK);
336 + *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = status;
340 + // data = LPC_SERIAL_IRQ_STATUS;
341 + LPC_SERIAL_IRQ_STATUS = data;
345 + // printf("it8712_uart_Isr clear LPC_SERIAL_IRQ_STATUS %x \n", cnt);
346 + return IRQ_HANDLED;
349 +static u_int it8712_tx_empty(struct uart_port *port)
351 +// printk("it8712 tx empty : \n");
353 + return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
356 +static u_int it8712_get_mctrl(struct uart_port *port)
358 + unsigned int result = 0;
359 + unsigned int status;
361 +// printk("it8712 get mctrl : \n");
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;
376 +static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
380 +static void it8712_break_ctl(struct uart_port *port, int break_state)
384 +// printk("it8712 break ctl : \n");
386 + lcr = UART_GET_LCR(port);
387 + if (break_state == -1)
388 + lcr |= UART_LCR_SBC;
390 + lcr &= ~UART_LCR_SBC;
391 + UART_PUT_LCR(port, lcr);
394 +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
398 + /* Special case: B0 rate */
402 + quot = (port->uartclk/(16 * baud)) ;
406 +static void it8712_set_termios(struct uart_port *port, struct termios *termios,
407 + struct termios *old)
409 + unsigned int uart_mc, old_ier, baud, quot;
410 + unsigned long flags;
412 + termios->c_cflag |= CREAD;
413 + termios->c_cflag |= CLOCAL;
415 + printk("it8712_set_cflag(0x%x) called\n", cflag);
417 + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
418 + quot = uart_get_divisor(port, baud);
420 + /* byte size and parity */
421 + switch (termios->c_cflag & CSIZE) {
423 + uart_mc = UART_LCR_WLEN5;
426 + uart_mc = UART_LCR_WLEN6;
429 + uart_mc = UART_LCR_WLEN7;
432 + uart_mc = UART_LCR_WLEN8;
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;
444 + spin_lock_irqsave(&port->lock, flags);
446 + * Update the per-port timeout
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;
456 + * Characters to ignore
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;
464 + * If we're ignoring parity and break indicators,
465 + * ignore overruns to (for real raw support).
467 + if (termios->c_iflag & IGNPAR)
468 + port->ignore_status_mask |= UART_LSR_OE;
471 + old_ier = UART_GET_IER(port);
473 + if(UART_ENABLE_MS(port, termios->c_cflag))
474 + old_ier |= UART_IER_MSI;
476 + /* Set baud rate */
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));
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);
488 + spin_unlock_irqrestore(&port->lock, flags);
491 +static int it8712_startup(struct uart_port *port)
496 + //printk("it8712 startup : \n");
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
505 + // regs |= (IRQ_LPC_MASK);
506 + // *((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) = regs;
511 + retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", port);
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);
525 + LPC_SERIAL_IRQ_POLARITY = 0x10; //0x10; //0x02;
526 + LPC_SERIAL_IRQ_TRITYPE = 0x10; //0x10;//
527 + LPC_SERIAL_IRQ_ENABLE = 0x10;
529 + LPC_BUS_CTRL = 0xc0;
530 + LPC_SERIAL_IRQ_CTRL = 0xc0;
531 + for(i=0;i<1000;i++) ;
532 + LPC_SERIAL_IRQ_CTRL = 0x80;
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
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
545 +static void it8712_shutdown(struct uart_port *port)
547 + //printk("it8712 shutdown : \n");
550 + * disable all interrupts, disable the port
552 + UART_PUT_IER(port, 0x0);
554 + /* disable break condition and fifos */
555 +// UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
558 + * Free the interrupt
560 + free_irq(port->irq, port);
563 +static const char *it8712_type(struct uart_port *port)
565 + return port->type == PORT_IT8712 ? "IT8712" : NULL;
569 + * Release the memory region(s) being used by 'port'
571 +static void it8712_release_port(struct uart_port *port)
573 +// printk("it8712 release port : \n");
575 + release_mem_region(port->mapbase, UART_PORT_SIZE);
579 + * Request the memory region(s) being used by 'port'
581 +static int it8712_request_port(struct uart_port *port)
583 + return request_mem_region(port->mapbase, UART_PORT_SIZE,
584 + "serial_it8712") != NULL ? 0 : -EBUSY;
588 + * Configure/autoconfigure the port.
590 +static void it8712_config_port(struct uart_port *port, int flags)
593 + if (flags & UART_CONFIG_TYPE) {
594 + if (it8712_request_port(port) == 0)
595 + port->type = PORT_IT8712;
600 + * verify the new serial_struct (for TIOCSSERIAL).
602 +static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
606 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
608 + if (ser->irq < 0 || ser->irq >= NR_IRQS)
610 + if (ser->baud_base < 9600)
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,
634 +#ifdef CONFIG_ARCH_SL2312
636 +static struct uart_port it8712_ports[UART_NR] = {
638 + membase: (void *)0,
640 + iotype: SERIAL_IO_MEM,
642 + uartclk: UART_CLK/2,
645 + flags: ASYNC_BOOT_AUTOCONF,
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)
655 + unsigned int status;
658 + printk("it8712_console_read() called\n");
662 + while (c < count) {
663 + status = UART_GET_LSR(port);
664 + if (UART_RX_DATA(status)) {
665 + *s++ = UART_GET_CHAR(port);
668 + // nothing more to get, return
672 + // return the count
676 +static void it8712_console_write(struct console *co, const char *s, unsigned count)
678 +#ifdef CONFIG_ARCH_SL2312
679 + struct uart_port *port = it8712_ports + co->index;
680 + unsigned int status, old_ies;
684 + * First save the CR then disable the interrupts
686 + old_ies = UART_GET_IER(port);
690 + // printk("old_ies = %x\n",old_ies);
693 + UART_PUT_IER(port,0x0);
696 + * Now, do each character
698 + for (i = 0; i < count; i++) {
700 + status = UART_GET_LSR(port);
701 + } while (!UART_TX_READY(status));
702 + UART_PUT_CHAR(port, s[i]);
703 + if (s[i] == '\n') {
705 + status = UART_GET_LSR(port);
706 + } while (!UART_TX_READY(status));
707 + UART_PUT_CHAR(port, '\r');
712 + * Finally, wait for transmitter to become empty
713 + * and restore the IES
716 + status = UART_GET_LSR(port);
717 + } while (!(status&UART_LSR_THRE));
718 + UART_PUT_IER(port, old_ies);
722 +static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
724 + //printk("it8712 console get options : \n");
726 + u_int uart_mc, quot;
727 + uart_mc= UART_GET_MCR(port);
730 + if (uart_mc & UART_LCR_PARITY) {
731 + if (uart_mc & UART_LCR_EVEN)
737 + switch (uart_mc & UART_LCR_MSK){
739 + case UART_LCR_WLEN5:
742 + case UART_LCR_WLEN6:
745 + case UART_LCR_WLEN7:
748 + case UART_LCR_WLEN8:
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));
758 +static int __init it8712_console_setup(struct console *co, char *options)
760 + struct uart_port *port;
768 + printk("it8712 console setup : \n");
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;
781 + //printk("it8712 irq is %x \n", it8712_ports[0].irq);
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;
792 +#ifdef CONFIG_ARCH_SL2312
794 + * Check whether an invalid uart number has been specified, and
795 + * if so, search for the first available port that does have
798 + port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
804 + uart_parse_options(options, &baud, &parity, &bits, &flow);
806 + it8712_console_get_options(port, &baud, &parity, &bits);
808 + return uart_set_options(port, co, baud, parity, bits, flow);
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,
819 + .data = &it8712_reg,
822 +static int __init it8712_console_init(void)
824 + register_console(&it8712_console);
828 +console_initcall(it8712_console_init);
830 +#define IT8712_CONSOLE &it8712_console
832 +#define IT8712_CONSOLE NULL
835 +static struct uart_driver it8712_reg = {
837 + .driver_name = SERIAL_IT8712_NAME,
838 + .dev_name = SERIAL_IT8712_NAME,
839 + .major = SERIAL_IT8712_MAJOR,
840 + .minor = SERIAL_IT8712_MINOR,
842 + .cons = IT8712_CONSOLE,
845 +static int __init it8712_init(void)
848 + //printk("serial_it8712: it871212_init \n");
851 + result = uart_register_driver(&it8712_reg);
854 + result = uart_add_one_port(&it8712_reg, &it8712_ports[0]);
861 +__initcall(it8712_init);
863 +++ b/drivers/serial/it8712.h
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
870 + * Out: Fifo custom trigger levels
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
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) */
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
893 + * These are the definitions for the FIFO Control Register
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 */
918 + * These are the definitions for the Line Control Register
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.
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
937 + * These are the definitions for the Line Status Register
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 */
949 + * These are the definitions for the Interrupt Identification Register
951 +#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
952 +#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
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 */
960 + * These are the definitions for the Interrupt Enable Register
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 */
967 + * Sleep mode for ST16650 and TI16750.
968 + * Note that for 16650, EFR-bit 4 must be selected as well.
970 +#define UART_IERX_SLEEP 0x10 /* Enable sleep mode */
973 + * These are the definitions for the Modem Control Register
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 */
982 + * These are the definitions for the Modem Status Register
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! */
994 +#define UART_PARITY_NONE 0x00
995 +#define UART_PARITY_ODD 0x01
996 +#define UART_PARITY_EVEN 0x02
1001 +++ b/drivers/serial/serial_it8712.c
1004 + * linux/drivers/char/serial_uart00.c
1006 + * Driver for UART00 serial ports
1008 + * Based on drivers/char/serial_amba.c, by ARM Limited &
1009 + * Deep Blue Solutions Ltd.
1010 + * Copyright 2001 Altera Corporation
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.
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.
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
1026 + * $Id: serial_it8712.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
1029 +#include <linux/module.h>
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>
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>
1057 +#if defined(CONFIG_SERIAL_IT8712_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
1058 +#define SUPPORT_SYSRQ
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"
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
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
1082 +#define IT8712_NO_PORTS UART_NR
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;
1089 +#define IT8712_ISR_PASS_LIMIT 256
1092 + * Access macros for the SL2312 UARTs
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)
1114 +static void it8712_stop_tx(struct uart_port *port, u_int from_tty)
1118 +// printk("it8712 stop tx : \n");
1119 + reg = UART_GET_IER(port);
1120 + reg &= ~(UART_IER_THRI);
1121 + UART_PUT_IER(port, reg);
1124 +static void it8712_stop_rx(struct uart_port *port)
1128 +// printk("it8712 stop rx : \n");
1129 + reg = UART_GET_IER(port);
1130 + reg &= ~(UART_IER_RDI);
1131 + UART_PUT_IER(port, reg);
1135 +static void it8712_enable_ms(struct uart_port *port)
1139 +// printk("it8712 enable ms : \n");
1141 + reg = UART_GET_IER(port);
1142 + reg |= (UART_IER_MSI);
1143 + UART_PUT_IER(port, reg);
1148 +it8712_rx_chars(struct uart_info *info, struct pt_regs *regs)
1150 + struct tty_struct *tty = info->tty;
1151 + unsigned int status, mask, ch, flg, ignored = 0;
1152 + struct uart_port *port = info->port;
1154 + // printk("it8712_rx_chars : \n");
1155 + status = UART_GET_LSR(port);
1156 + while (UART_RX_DATA(status)) {
1159 + * We need to read rds before reading the
1160 + * character from the fifo
1162 + ch = UART_GET_CHAR(port);
1163 + port->icount.rx++;
1165 + if (tty->flip.count >= TTY_FLIPBUF_SIZE)
1171 + * Note that the error handling code is
1172 + * out of the main execution path
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))
1181 + *tty->flip.flag_buf_ptr++ = flg;
1182 + *tty->flip.char_buf_ptr++ = ch;
1183 + tty->flip.count++;
1185 + status = UART_GET_LSR(port);
1188 + tty_flip_buffer_push(tty);
1192 + if (status & UART_LSR_BI) {
1193 + status &= ~(UART_LSR_FE);
1194 + port->icount.brk++;
1196 +#ifdef SUPPORT_SYSRQ
1197 + if (uart_handle_break(info, &it8712_console))
1200 + } else if (status & UART_LSR_PE)
1201 + port->icount.parity++;
1202 + else if (status & UART_LSR_FE)
1203 + port->icount.frame++;
1205 + if (status & UART_LSR_OE)
1206 + port->icount.overrun++;
1208 + if (status & port->ignore_status_mask) {
1209 + if (++ignored > 100)
1214 + mask = status & port->read_status_mask;
1216 + if (mask & UART_LSR_BI)
1218 + else if (mask & UART_LSR_PE)
1220 + else if (mask & UART_LSR_FE)
1223 + if (status & UART_LSR_OE) {
1225 + * CHECK: does overrun affect the current character?
1226 + * ASSUMPTION: it does not.
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)
1234 + flg = TTY_OVERRUN;
1236 +#ifdef SUPPORT_SYSRQ
1239 + goto error_return;
1242 +static void it8712_tx_chars(struct uart_info *info)
1245 + struct uart_port *port=info->port;
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++;
1255 + if (info->xmit.head == info->xmit.tail
1256 + || info->tty->stopped
1257 + || info->tty->hw_stopped) {
1258 + it8712_stop_tx(info->port, 0);
1262 + count = port->fifosize >> 1;
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)
1270 + } while (--count > 0);
1272 + if (CIRC_CNT(info->xmit.head,
1274 + UART_XMIT_SIZE) < WAKEUP_CHARS)
1275 + uart_event(info, EVT_WRITE_WAKEUP);
1277 + if (info->xmit.head == info->xmit.tail)
1278 + it8712_stop_tx(info->port, 0);
1281 +static void it8712_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
1284 + struct uart_info *info=(struct uart_info*)(port->iobase);
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);
1293 +static void it8712_modem_status(struct uart_info *info)
1295 + unsigned int status;
1296 + struct uart_icount *icount = &info->port->icount;
1298 +// printk("it8712 modem status : \n");
1300 + status = UART_GET_MSR(info->port);
1302 + if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
1303 + UART_MSR_TERI | UART_MSR_DDCD)))
1306 + if (status & UART_MSR_DCD) {
1308 +#ifdef CONFIG_HARD_PPS
1309 + if ((info->flags & ASYNC_HARDPPS_CD) &&
1310 + (status & UART_MSR_DCD_MSK))
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))) {
1319 + tty_hangup(info->tty);
1324 + if (status & UART_MSR_DDSR)
1327 + if (status & UART_MSR_DCTS) {
1330 + if (info->flags & ASYNC_CTS_FLOW) {
1331 + status &= UART_MSR_CTS;
1333 + if (info->tty->hw_stopped) {
1335 + info->tty->hw_stopped = 0;
1336 + info->ops->start_tx(info->port, 1, 0);
1337 + uart_event(info, EVT_WRITE_WAKEUP);
1341 + info->tty->hw_stopped = 1;
1342 + info->ops->stop_tx(info->port, 0);
1347 + wake_up_interruptible(&info->delta_msr_wait);
1351 +static void it8712_int(int irq, void *dev_id, struct pt_regs *regs)
1353 + struct uart_info *info = dev_id;
1354 + unsigned int status, pass_counter = 0;
1356 + status = UART_GET_INT_STATUS(info->port);
1358 +// printk("it8712_int: status %x \n", status);
1361 + case UART_IIR_RDI:
1362 + case UART_IIR_RLSI:
1363 + case UART_IIR_RCTO:
1364 + it8712_rx_chars(info, regs);
1366 + case UART_IIR_THRI:
1367 + it8712_tx_chars(info);
1369 + case UART_IIR_MSI:
1370 + it8712_modem_status(info);
1375 + if (pass_counter++ > IT8712_ISR_PASS_LIMIT)
1378 + status = UART_GET_INT_STATUS(info->port);
1382 +static u_int it8712_tx_empty(struct uart_port *port)
1384 +// printk("it8712 tx empty : \n");
1386 + return ((UART_GET_LSR(port) & UART_LSR_THRE)? TIOCSER_TEMT : 0);
1389 +static u_int it8712_get_mctrl(struct uart_port *port)
1391 + unsigned int result = 0;
1392 + unsigned int status;
1394 +// printk("it8712 get mctrl : \n");
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;
1409 +static void it8712_set_mctrl_null(struct uart_port *port, u_int mctrl)
1413 +static void it8712_break_ctl(struct uart_port *port, int break_state)
1417 +// printk("it8712 break ctl : \n");
1419 + lcr = UART_GET_LCR(port);
1420 + if (break_state == -1)
1421 + lcr |= UART_LCR_SBC;
1423 + lcr &= ~UART_LCR_SBC;
1424 + UART_PUT_LCR(port, lcr);
1427 +static inline u_int uart_calculate_quot(struct uart_info *info, u_int baud)
1431 + /* Special case: B0 rate */
1435 + quot = (info->port->uartclk/(16 * baud)) ;
1439 +static void it8712_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
1441 + u_int uart_mc=0, old_ier;
1442 + unsigned long flags;
1445 + printk("it8712_set_cflag(0x%x) called\n", cflag);
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
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;
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;
1471 + * Characters to ignore
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;
1479 + * If we're ignoring parity and break indicators,
1480 + * ignore overruns to (for real raw support).
1482 + if (iflag & IGNPAR)
1483 + port->ignore_status_mask |= UART_LSR_OE;
1486 + /* first, disable everything */
1487 + save_flags(flags); cli();
1488 + old_ier = UART_GET_IER(port);
1490 + if ((port->flags & ASYNC_HARDPPS_CD) ||
1491 + (cflag & CRTSCTS) || !(cflag & CLOCAL))
1492 + old_ier |= UART_IER_MSI;
1494 + /* Set baud rate */
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));
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);
1506 + restore_flags(flags);
1509 +static int it8712_startup(struct uart_port *port, struct uart_info *info)
1512 + unsigned int regs;
1514 +// printk("it8712 startup : \n");
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
1522 + port->iobase=(u_int)info;
1525 + * Allocate the IRQ
1527 + retval = request_irq(port->irq, it8712_int, SA_INTERRUPT, "it8712", info);
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);
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
1546 + UART_PUT_IER(port, (UART_IER_RDI|UART_IER_THRI));
1551 +static void it8712_shutdown(struct uart_port *port, struct uart_info *info)
1553 +// printk("it8712 shutdown : \n");
1556 + * disable all interrupts, disable the port
1558 + UART_PUT_IER(port, 0x0);
1560 + /* disable break condition and fifos */
1561 +// UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
1564 + * Free the interrupt
1566 + free_irq(port->irq, info);
1569 +static const char *it8712_type(struct uart_port *port)
1571 + return port->type == PORT_IT8712 ? "IT8712" : NULL;
1575 + * Release the memory region(s) being used by 'port'
1577 +static void it8712_release_port(struct uart_port *port)
1579 +// printk("it8712 release port : \n");
1581 + release_mem_region(port->mapbase, UART_PORT_SIZE);
1585 + * Request the memory region(s) being used by 'port'
1587 +static int it8712_request_port(struct uart_port *port)
1589 + return request_mem_region(port->mapbase, UART_PORT_SIZE,
1590 + "serial_it8712") != NULL ? 0 : -EBUSY;
1594 + * Configure/autoconfigure the port.
1596 +static void it8712_config_port(struct uart_port *port, int flags)
1599 + if (flags & UART_CONFIG_TYPE) {
1600 + if (it8712_request_port(port) == 0)
1601 + port->type = PORT_IT8712;
1606 + * verify the new serial_struct (for TIOCSSERIAL).
1608 +static int it8712_verify_port(struct uart_port *port, struct serial_struct *ser)
1612 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
1614 + if (ser->irq < 0 || ser->irq >= NR_IRQS)
1616 + if (ser->baud_base < 9600)
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,
1640 +#ifdef CONFIG_ARCH_SL2312
1642 +static struct uart_port it8712_ports[UART_NR] = {
1644 + membase: (void *)0,
1646 + iotype: SERIAL_IO_MEM,
1648 + uartclk: UART_CLK/2,
1650 + ops: &it8712_pops,
1651 + flags: ASYNC_BOOT_AUTOCONF,
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)
1661 + unsigned int status;
1664 + printk("it8712_console_read() called\n");
1668 + while (c < count) {
1669 + status = UART_GET_LSR(port);
1670 + if (UART_RX_DATA(status)) {
1671 + *s++ = UART_GET_CHAR(port);
1674 + // nothing more to get, return
1678 + // return the count
1682 +static void it8712_console_write(struct console *co, const char *s, unsigned count)
1684 +#ifdef CONFIG_ARCH_SL2312
1685 + struct uart_port *port = it8712_ports + co->index;
1686 + unsigned int status, old_ies;
1690 + * First save the CR then disable the interrupts
1692 + old_ies = UART_GET_IER(port);
1693 + UART_PUT_IER(port,0x0);
1696 + * Now, do each character
1698 + for (i = 0; i < count; i++) {
1700 + status = UART_GET_LSR(port);
1701 + } while (!UART_TX_READY(status));
1702 + UART_PUT_CHAR(port, s[i]);
1703 + if (s[i] == '\n') {
1705 + status = UART_GET_LSR(port);
1706 + } while (!UART_TX_READY(status));
1707 + UART_PUT_CHAR(port, '\r');
1712 + * Finally, wait for transmitter to become empty
1713 + * and restore the IES
1716 + status = UART_GET_LSR(port);
1717 + } while (!(status&UART_LSR_THRE));
1718 + UART_PUT_IER(port, old_ies);
1722 +static kdev_t it8712_console_device(struct console *co)
1724 + return MKDEV(SERIAL_IT8712_MAJOR, SERIAL_IT8712_MINOR + co->index);
1727 +static int it8712_console_wait_key(struct console *co)
1729 +#ifdef CONFIG_ARCH_SL2312
1730 + struct uart_port *port = (it8712_ports + co->index);
1731 + unsigned int status;
1734 + status = UART_GET_LSR(port);
1735 + } while (!UART_RX_DATA(status));
1736 + return UART_GET_CHAR(port);
1742 +static void /*__init*/ it8712_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
1744 + printk("it8712 console get options : \n");
1746 + u_int uart_mc, quot;
1747 + uart_mc= UART_GET_MCR(port);
1750 + if (uart_mc & UART_LCR_PARITY) {
1751 + if (uart_mc & UART_LCR_EVEN)
1757 + switch (uart_mc & UART_LCR_MSK){
1759 + case UART_LCR_WLEN5:
1762 + case UART_LCR_WLEN6:
1765 + case UART_LCR_WLEN7:
1768 + case UART_LCR_WLEN8:
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));
1778 +static int __init it8712_console_setup(struct console *co, char *options)
1780 + struct uart_port *port;
1788 +// printk("it8712 console setup : \n");
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;
1801 + printk("it8712 irq is %x %x \n", it8712_ports[0].irq, irq);
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) ;
1808 +#ifdef CONFIG_ARCH_SL2312
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.
1814 + port = uart_get_console(it8712_ports,IT8712_NO_PORTS,co);
1820 + uart_parse_options(options, &baud, &parity, &bits, &flow);
1822 + it8712_console_get_options(port, &baud, &parity, &bits);
1824 + return uart_set_options(port, co, baud, parity, bits, flow);
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,
1833 + device: it8712_console_device,
1834 +// wait_key: it8712_console_wait_key,
1835 + setup: it8712_console_setup,
1836 + flags: (CON_PRINTBUFFER|CON_ENABLED),
1840 +void __init it8712_console_init(void)
1842 + register_console(&it8712_console);
1845 +#define IT8712_CONSOLE &it8712_console
1847 +#define IT8712_CONSOLE NULL
1850 +static struct uart_driver it8712_reg = {
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,
1863 +#ifdef CONFIG_ARCH_SL2312
1864 + port: it8712_ports,
1867 + cons: IT8712_CONSOLE,
1870 +static int __init it8712_init(void)
1872 +// printk("serial_it8712: it871212_init \n");
1874 + return uart_register_driver(&it8712_reg);
1878 +__initcall(it8712_init);
1880 +++ b/drivers/serial/serial_sl2312.c
1883 + * linux/drivers/char/serial_uart00.c
1885 + * Driver for UART00 serial ports
1887 + * Based on drivers/char/serial_amba.c, by ARM Limited &
1888 + * Deep Blue Solutions Ltd.
1889 + * Copyright 2001 Altera Corporation
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.
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.
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
1905 + * $Id: serial_sl2312.c,v 1.1.1.1 2006/04/03 08:41:00 amos_lee Exp $
1908 +#include <linux/module.h>
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>
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>
1941 +#if defined(CONFIG_SERIAL_SL2312_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
1942 +#define SUPPORT_SYSRQ
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>
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
1960 +#define SL2312_NO_PORTS UART_NR
1961 +#define SL2312_ISR_PASS_LIMIT 256
1964 + * Access macros for the SL2312 UARTs
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)
1986 +static void sl2312_stop_tx(struct uart_port *port)
1990 +// printk("sl2312 stop tx : \n");
1991 + reg = UART_GET_IER(port);
1992 + reg &= ~(UART_IER_TE);
1993 + UART_PUT_IER(port, reg);
1996 +static void sl2312_stop_rx(struct uart_port *port)
2000 +// printk("sl2312 stop rx : \n");
2001 + reg = UART_GET_IER(port);
2002 + reg &= ~(UART_IER_DR);
2003 + UART_PUT_IER(port, reg);
2007 +static void sl2312_enable_ms(struct uart_port *port)
2011 +// printk("sl2312 enable ms : \n");
2013 + reg = UART_GET_IER(port);
2014 + reg |= (UART_IER_MS);
2015 + UART_PUT_IER(port, reg);
2020 +sl2312_rx_chars(struct uart_port *port)
2022 + struct tty_struct *tty = port->info->tty;
2023 + unsigned int status, mask, ch, flg, ignored = 0;
2026 + // printk("sl2312_rx_chars : \n");
2027 + status = UART_GET_LSR(port);
2028 + while (UART_RX_DATA(status)) {
2031 + * We need to read rds before reading the
2032 + * character from the fifo
2034 + ch = UART_GET_CHAR(port);
2035 + port->icount.rx++;
2037 + //if (tty->flip.count >= TTY_FLIPBUF_SIZE)
2038 + if (tty && !tty_buffer_request_room(tty, 1))
2044 + * Note that the error handling code is
2045 + * out of the main execution path
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))
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);
2059 + status = UART_GET_LSR(port);
2062 + tty_flip_buffer_push(tty);
2066 + if (status & UART_LSR_BI) {
2067 + status &= ~(UART_LSR_FE);
2068 + port->icount.brk++;
2070 +#ifdef SUPPORT_SYSRQ
2071 + if (uart_handle_break(port))
2074 + } else if (status & UART_LSR_PE)
2075 + port->icount.parity++;
2076 + else if (status & UART_LSR_FE)
2077 + port->icount.frame++;
2079 + if (status & UART_LSR_OE)
2080 + port->icount.overrun++;
2082 + if (status & port->ignore_status_mask) {
2083 + if (++ignored > 100)
2088 + mask = status & port->read_status_mask;
2090 + if (mask & UART_LSR_BI)
2092 + else if (mask & UART_LSR_PE)
2094 + else if (mask & UART_LSR_FE)
2097 + if (status & UART_LSR_OE) {
2099 + * CHECK: does overrun affect the current character?
2100 + * ASSUMPTION: it does not.
2102 + //*tty->flip.flag_buf_ptr++ = flg;
2103 + //*tty->flip.char_buf_ptr++ = ch;
2104 + //tty->flip.count++;
2106 + tty_insert_flip_char(tty, 0, TTY_BREAK);
2108 + // if (tty->flip.count >= TTY_FLIPBUF_SIZE)
2109 + if (tty_buffer_request_room(tty, 1))
2112 + flg = TTY_OVERRUN;
2114 +#ifdef SUPPORT_SYSRQ
2117 + goto error_return;
2120 +static void sl2312_tx_chars(struct uart_port *port)
2122 + struct circ_buf *xmit = &port->info->xmit;
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++;
2134 + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
2135 + sl2312_stop_tx(port);
2140 + count = port->fifosize >> 1;
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))
2148 + } while (--count > 0);
2150 + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
2151 + uart_write_wakeup(port);
2153 + if (uart_circ_empty(xmit))
2154 + sl2312_stop_tx(port);
2158 +static void sl2312_start_tx(struct uart_port *port)
2162 +// printk("sl2312 start tx : \n");
2163 + reg = UART_GET_IER(port);
2164 + reg |= (UART_IER_TE);
2165 + UART_PUT_IER(port, reg);
2167 + sl2312_tx_chars(port);
2170 +static void sl2312_modem_status(struct uart_port *port)
2172 + unsigned int status;
2174 +// printk("it8712 modem status : \n");
2176 + status = UART_GET_MSR(port);
2178 + if (!(status & (UART_MSR_DCTS | UART_MSR_DDSR |
2179 + UART_MSR_TERI | UART_MSR_DDCD)))
2182 + if (status & UART_MSR_DDCD)
2183 + uart_handle_dcd_change(port, status & UART_MSR_DCD);
2185 + if (status & UART_MSR_DDSR)
2186 + port->icount.dsr++;
2188 + if (status & UART_MSR_DCTS)
2189 + uart_handle_cts_change(port, status & UART_MSR_CTS);
2191 + wake_up_interruptible(&port->info->delta_msr_wait);
2195 +static irqreturn_t sl2312_int(int irq, void *dev_id)
2197 + struct uart_port *port = dev_id;
2198 + unsigned int status, pass_counter = 0;
2200 + status = UART_GET_INT_STATUS(port);
2205 + case UART_IIR_RLS:
2206 + sl2312_rx_chars(port);
2209 + sl2312_tx_chars(port);
2211 + case UART_IIR_MODEM:
2212 + sl2312_modem_status(port);
2217 + if (pass_counter++ > SL2312_ISR_PASS_LIMIT)
2220 + status = UART_GET_INT_STATUS(port);
2223 + return IRQ_HANDLED;
2226 +static u_int sl2312_tx_empty(struct uart_port *port)
2228 +// printk("sl2312 tx empty : \n");
2230 + return ((UART_GET_LSR(port) & UART_LSR_TE)? TIOCSER_TEMT : 0);
2233 +static u_int sl2312_get_mctrl(struct uart_port *port)
2235 + unsigned int result = 0;
2236 + unsigned int status;
2238 +// printk("sl2312 get mctrl : \n");
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;
2253 +static void sl2312_set_mctrl_null(struct uart_port *port, u_int mctrl)
2257 +static void sl2312_break_ctl(struct uart_port *port, int break_state)
2261 +// printk("sl2312 break ctl : \n");
2263 + lcr = UART_GET_LCR(port);
2264 + if (break_state == -1)
2265 + lcr |= UART_LCR_SETBREAK;
2267 + lcr &= ~UART_LCR_SETBREAK;
2268 + UART_PUT_LCR(port, lcr);
2271 +static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
2275 + /* Special case: B0 rate */
2279 + quot = (port->uartclk / (16 * baud)-1) ;
2284 +static void sl2312_set_termios(struct uart_port *port, struct ktermios *termios,
2285 + struct ktermios *old)
2287 + unsigned int uart_mc, old_ier, baud, quot;
2288 + unsigned long flags;
2290 + termios->c_cflag |= CREAD;
2292 + printk("it8712_set_cflag(0x%x) called\n", cflag);
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);
2298 + /* byte size and parity */
2299 + switch (termios->c_cflag & CSIZE) {
2301 + uart_mc = UART_LCR_LEN5;
2304 + uart_mc = UART_LCR_LEN6;
2307 + uart_mc = UART_LCR_LEN7;
2310 + uart_mc = UART_LCR_LEN8;
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;
2322 + spin_lock_irqsave(&port->lock, flags);
2324 + * Update the per-port timeout
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;
2334 + * Characters to ignore
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;
2342 + * If we're ignoring parity and break indicators,
2343 + * ignore overruns to (for real raw support).
2345 + if (termios->c_iflag & IGNPAR)
2346 + port->ignore_status_mask |= UART_LSR_OE;
2349 + //save_flags(flags); cli();
2350 + old_ier = UART_GET_IER(port);
2352 + if(UART_ENABLE_MS(port, termios->c_cflag))
2353 + old_ier |= UART_IER_MS;
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));
2360 + UART_PUT_LCR(port, uart_mc);
2361 + UART_PUT_IER(port, old_ier);
2363 + //restore_flags(flags);
2364 + spin_unlock_irqrestore(&port->lock, flags);
2369 +static int sl2312_startup(struct uart_port *port)
2372 + unsigned int regs;
2374 +// printk("sl2312 startup : \n");
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
2383 + * Allocate the IRQ
2385 + retval = request_irq(port->irq, sl2312_int, IRQF_DISABLED, "sl2312", port);
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);
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
2404 + UART_PUT_IER(port, (UART_IER_DR|UART_IER_TE));
2409 +static void sl2312_shutdown(struct uart_port *port)
2411 +// printk("sl2312 shutdown : \n");
2414 + * disable all interrupts, disable the port
2416 + UART_PUT_IER(port, 0x0);
2418 + /* disable break condition and fifos */
2419 +// UART_PUT_MCR(port, (UART_GET_MCR(port)&UART_MCR_MASK));
2422 + * Free the interrupt
2424 + free_irq(port->irq, port);
2427 +static const char *sl2312_type(struct uart_port *port)
2429 + return port->type == PORT_SL2312 ? "SL2312" : NULL;
2433 + * Release the memory region(s) being used by 'port'
2435 +static void sl2312_release_port(struct uart_port *port)
2437 +// printk("sl2312 release port : \n");
2439 + release_mem_region(port->mapbase, UART_PORT_SIZE);
2443 + * Request the memory region(s) being used by 'port'
2445 +static int sl2312_request_port(struct uart_port *port)
2447 + return request_mem_region(port->mapbase, UART_PORT_SIZE,
2448 + "serial_sl2312") != NULL ? 0 : -EBUSY;
2452 + * Configure/autoconfigure the port.
2454 +static void sl2312_config_port(struct uart_port *port, int flags)
2457 + if (flags & UART_CONFIG_TYPE) {
2458 + if (sl2312_request_port(port) == 0)
2459 + port->type = PORT_SL2312;
2464 + * verify the new serial_struct (for TIOCSSERIAL).
2466 +static int sl2312_verify_port(struct uart_port *port, struct serial_struct *ser)
2470 + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
2472 + if (ser->irq < 0 || ser->irq >= NR_IRQS)
2474 + if (ser->baud_base < 9600)
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,
2498 +#ifdef CONFIG_ARCH_SL2312
2500 +static struct uart_port sl2312_ports[UART_NR] = {
2502 + membase: (void *)IO_ADDRESS(SL2312_UART_BASE),
2503 + mapbase: SL2312_UART_BASE,
2504 + iotype: SERIAL_IO_MEM,
2506 + uartclk: UART_CLK,
2508 + ops: &sl2312_pops,
2509 + flags: ASYNC_BOOT_AUTOCONF,
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)
2519 + unsigned int status;
2522 + printk("sl2312_console_read() called\n");
2526 + while (c < count) {
2527 + status = UART_GET_LSR(port);
2528 + if (UART_RX_DATA(status)) {
2529 + *s++ = UART_GET_CHAR(port);
2532 + // nothing more to get, return
2536 + // return the count
2540 +static void sl2312_console_write(struct console *co, const char *s, unsigned count)
2542 +#ifdef CONFIG_ARCH_SL2312
2543 + struct uart_port *port = sl2312_ports + co->index;
2544 + unsigned int status, old_ies;
2548 + * First save the CR then disable the interrupts
2550 + old_ies = UART_GET_IER(port);
2551 + UART_PUT_IER(port,0x0);
2554 + * Now, do each character
2556 + for (i = 0; i < count; i++) {
2558 + status = UART_GET_LSR(port);
2559 + } while (!UART_TX_READY(status));
2560 + UART_PUT_CHAR(port, s[i]);
2561 + if (s[i] == '\n') {
2563 + status = UART_GET_LSR(port);
2564 + } while (!UART_TX_READY(status));
2565 + UART_PUT_CHAR(port, '\r');
2570 + * Finally, wait for transmitter to become empty
2571 + * and restore the IES
2574 + status = UART_GET_LSR(port);
2575 + } while (!(status&UART_LSR_TE));
2576 + UART_PUT_IER(port, old_ies);
2581 +static void sl2312_console_device(struct console *co,int *index)
2584 + struct uart_driver *p = co->data;
2585 + *index = co->index;
2586 + return p->tty_driver;
2591 +static void /*__init*/ sl2312_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
2593 +// printk("sl2312 console get options : \n");
2595 + u_int uart_mc, quot;
2596 + uart_mc= UART_GET_MCR(port);
2599 + if (uart_mc & UART_LCR_PE) {
2600 + if (uart_mc & UART_LCR_EVEN)
2606 + switch (uart_mc & UART_LCR_MSK){
2608 + case UART_LCR_LEN5:
2611 + case UART_LCR_LEN6:
2614 + case UART_LCR_LEN7:
2617 + case UART_LCR_LEN8:
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 );
2627 +static int __init sl2312_console_setup(struct console *co, char *options)
2629 + struct uart_port *port;
2635 + printk("sl2312 console setup : \n");
2637 +#ifdef CONFIG_ARCH_SL2312
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.
2643 + port = uart_get_console(sl2312_ports,SL2312_NO_PORTS,co);
2649 + uart_parse_options(options, &baud, &parity, &bits, &flow);
2651 + sl2312_console_get_options(port, &baud, &parity, &bits);
2653 + return uart_set_options(port, co, baud, parity, bits, flow);
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,
2666 + .data = &sl2312_reg,
2669 +static int __init sl2312_console_init(void)
2671 + register_console(&sl2312_console);
2676 +console_initcall(sl2312_console_init);
2678 +#define SL2312_CONSOLE &sl2312_console
2680 +#define SL2312_CONSOLE NULL
2684 +struct uart_driver sl2312_reg = {
2686 + .driver_name = SERIAL_SL2312_NAME,
2687 + .dev_name = SERIAL_SL2312_NAME,
2688 + .major = SERIAL_SL2312_MAJOR,
2689 + .minor = SERIAL_SL2312_MINOR,
2691 + .cons = SL2312_CONSOLE,
2694 +static int __init sl2312_init(void)
2697 + //printk("serial_it8712: it871212_init \n");
2699 + result = uart_register_driver(&sl2312_reg);
2702 + result = uart_add_one_port(&sl2312_reg, &sl2312_ports[0]);
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
2716 +#define PORT_SL2312 72
2717 +#define PORT_IT8712 73
2721 #include <linux/compiler.h>
2722 --- a/drivers/char/Makefile
2723 +++ b/drivers/char/Makefile
2725 obj-$(CONFIG_APPLICOM) += applicom.o
2726 obj-$(CONFIG_SONYPI) += sonypi.o
2727 obj-$(CONFIG_RTC) += rtc.o
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
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 @@
2745 comment "Non-8250 serial port support"
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
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.
2756 +config SERIAL_SL2312_CONSOLE
2757 + bool "Support for console on SL2312 serial port"
2758 + depends on SERIAL_SL2312
2759 + select SERIAL_CORE_CONSOLE
2761 + Say Y here if you want to support a serial console on an SWORD
2762 + hard logic uart or uart00 IP core.
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.)
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
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.
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
2786 + Say Y here if you want to support a serial console on an Excalibur
2787 + hard logic uart or uart00 IP core.
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.)
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
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