create release branch for 8.09
[openwrt/svn-archive/archive.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 @@
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 @@
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 @@
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