~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/char/serial_amba.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/drivers/char/serial_amba.c
  3  *
  4  *  Driver for AMBA serial ports
  5  *
  6  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  7  *
  8  *  Copyright 1999 ARM Limited
  9  *  Copyright (C) 2000 Deep Blue Solutions Ltd.
 10  *
 11  * This program is free software; you can redistribute it and/or modify
 12  * it under the terms of the GNU General Public License as published by
 13  * the Free Software Foundation; either version 2 of the License, or
 14  * (at your option) any later version.
 15  *
 16  * This program is distributed in the hope that it will be useful,
 17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 19  * GNU General Public License for more details.
 20  *
 21  * You should have received a copy of the GNU General Public License
 22  * along with this program; if not, write to the Free Software
 23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 24  *
 25  *
 26  * This is a generic driver for ARM AMBA-type serial ports.  They
 27  * have a lot of 16550-like features, but are not register compatable.
 28  * Note that although they do have CTS, DCD and DSR inputs, they do
 29  * not have an RI input, nor do they have DTR or RTS outputs.  If
 30  * required, these have to be supplied via some other means (eg, GPIO)
 31  * and hooked into this driver.
 32  *
 33  * This could very easily become a generic serial driver for dumb UARTs
 34  * (eg, {82,16x}50, 21285, SA1100).
 35  */
 36 
 37 #include <linux/config.h>
 38 #include <linux/module.h>
 39 #include <linux/errno.h>
 40 #include <linux/signal.h>
 41 #include <linux/sched.h>
 42 #include <linux/interrupt.h>
 43 #include <linux/tty.h>
 44 #include <linux/tty_flip.h>
 45 #include <linux/major.h>
 46 #include <linux/string.h>
 47 #include <linux/fcntl.h>
 48 #include <linux/ptrace.h>
 49 #include <linux/ioport.h>
 50 #include <linux/mm.h>
 51 #include <linux/malloc.h>
 52 #include <linux/init.h>
 53 #include <linux/circ_buf.h>
 54 #include <linux/serial.h>
 55 #include <linux/console.h>
 56 #include <linux/sysrq.h>
 57 
 58 #include <asm/system.h>
 59 #include <asm/io.h>
 60 #include <asm/irq.h>
 61 #include <asm/uaccess.h>
 62 #include <asm/bitops.h>
 63 
 64 #include <asm/hardware/serial_amba.h>
 65 
 66 #define SERIAL_AMBA_NAME        "ttyAM"
 67 #define SERIAL_AMBA_MAJOR       204
 68 #define SERIAL_AMBA_MINOR       16
 69 #define SERIAL_AMBA_NR          2
 70 
 71 #define CALLOUT_AMBA_NAME       "cuaam"
 72 #define CALLOUT_AMBA_MAJOR      205
 73 #define CALLOUT_AMBA_MINOR      16
 74 #define CALLOUT_AMBA_NR         SERIAL_AMBA_NR
 75 
 76 #ifndef TRUE
 77 #define TRUE 1
 78 #endif
 79 #ifndef FALSE
 80 #define FALSE 0
 81 #endif
 82 
 83 #define DEBUG 0
 84 #define DEBUG_LEDS 0
 85 
 86 #if DEBUG_LEDS
 87 extern int get_leds(void);
 88 extern int set_leds(int);
 89 #endif
 90 
 91 /*
 92  * Access routines for the AMBA UARTs
 93  */
 94 #define UART_GET_INT_STATUS(p)  IO_READ((p)->uart_base + AMBA_UARTIIR)
 95 #define UART_GET_FR(p)          IO_READ((p)->uart_base + AMBA_UARTFR)
 96 #define UART_GET_CHAR(p)        IO_READ((p)->uart_base + AMBA_UARTDR)
 97 #define UART_PUT_CHAR(p, c)     IO_WRITE((p)->uart_base + AMBA_UARTDR, (c))
 98 #define UART_GET_RSR(p)         IO_READ((p)->uart_base + AMBA_UARTRSR)
 99 #define UART_GET_CR(p)          IO_READ((p)->uart_base + AMBA_UARTCR)
100 #define UART_PUT_CR(p,c)        IO_WRITE((p)->uart_base + AMBA_UARTCR, (c))
101 #define UART_GET_LCRL(p)        IO_READ((p)->uart_base + AMBA_UARTLCR_L)
102 #define UART_PUT_LCRL(p,c)      IO_WRITE((p)->uart_base + AMBA_UARTLCR_L, (c))
103 #define UART_GET_LCRM(p)        IO_READ((p)->uart_base + AMBA_UARTLCR_M)
104 #define UART_PUT_LCRM(p,c)      IO_WRITE((p)->uart_base + AMBA_UARTLCR_M, (c))
105 #define UART_GET_LCRH(p)        IO_READ((p)->uart_base + AMBA_UARTLCR_H)
106 #define UART_PUT_LCRH(p,c)      IO_WRITE((p)->uart_base + AMBA_UARTLCR_H, (c))
107 #define UART_RX_DATA(s)         (((s) & AMBA_UARTFR_RXFE) == 0)
108 #define UART_TX_READY(s)        (((s) & AMBA_UARTFR_TXFF) == 0)
109 #define UART_TX_EMPTY(p)        ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
110 
111 #define AMBA_UARTRSR_ANY        (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE)
112 #define AMBA_UARTFR_MODEM_ANY   (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS)
113 
114 /*
115  * Things needed by tty driver
116  */
117 static struct tty_driver ambanormal_driver, ambacallout_driver;
118 static int ambauart_refcount;
119 static struct tty_struct *ambauart_table[SERIAL_AMBA_NR];
120 static struct termios *ambauart_termios[SERIAL_AMBA_NR];
121 static struct termios *ambauart_termios_locked[SERIAL_AMBA_NR];
122 
123 #if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
124 #define SUPPORT_SYSRQ
125 #endif
126 
127 /*
128  * Things needed internally to this driver
129  */
130 
131 /*
132  * tmp_buf is used as a temporary buffer by serial_write.  We need to
133  * lock it in case the copy_from_user blocks while swapping in a page,
134  * and some other program tries to do a serial write at the same time.
135  * Since the lock will only come under contention when the system is
136  * swapping and available memory is low, it makes sense to share one
137  * buffer across all the serial ports, since it significantly saves
138  * memory if large numbers of serial ports are open.
139  */
140 static u_char *tmp_buf;
141 static DECLARE_MUTEX(tmp_buf_sem);
142 
143 #define HIGH_BITS_OFFSET        ((sizeof(long)-sizeof(int))*8)
144 
145 /* number of characters left in xmit buffer before we ask for more */
146 #define WAKEUP_CHARS            256
147 #define AMBA_ISR_PASS_LIMIT     256
148 
149 #define EVT_WRITE_WAKEUP        0
150 
151 struct amba_icount {
152         __u32   cts;
153         __u32   dsr;
154         __u32   rng;
155         __u32   dcd;
156         __u32   rx;
157         __u32   tx;
158         __u32   frame;
159         __u32   overrun;
160         __u32   parity;
161         __u32   brk;
162         __u32   buf_overrun;
163 };
164 
165 /*
166  * Static information about the port
167  */
168 struct amba_port {
169         unsigned int            uart_base;
170         unsigned int            irq;
171         unsigned int            uartclk;
172         unsigned int            fifosize;
173         unsigned int            tiocm_support;
174         void (*set_mctrl)(struct amba_port *, u_int mctrl);
175 };      
176 
177 /*
178  * This is the state information which is persistent across opens
179  */
180 struct amba_state {
181         struct amba_icount      icount;
182         unsigned int            line;
183         unsigned int            close_delay;
184         unsigned int            closing_wait;
185         unsigned int            custom_divisor;
186         unsigned int            flags;
187         struct termios          normal_termios;
188         struct termios          callout_termios;
189 
190         int                     count;
191         struct amba_info        *info;
192 };
193 
194 #define AMBA_XMIT_SIZE 1024
195 /*
196  * This is the state information which is only valid when the port is open.
197  */
198 struct amba_info {
199         struct amba_port        *port;
200         struct amba_state       *state;
201         struct tty_struct       *tty;
202         unsigned char           x_char;
203         unsigned char           old_status;
204         unsigned char           read_status_mask;
205         unsigned char           ignore_status_mask;
206         struct circ_buf         xmit;
207         unsigned int            flags;
208 #ifdef SUPPORT_SYSRQ
209         unsigned long           sysrq;
210 #endif
211 
212         unsigned int            event;
213         unsigned int            timeout;
214         unsigned int            lcr_h;
215         unsigned int            mctrl;
216         int                     blocked_open;
217         pid_t                   session;
218         pid_t                   pgrp;
219 
220         struct tasklet_struct   tlet;
221 
222         wait_queue_head_t       open_wait;
223         wait_queue_head_t       close_wait;
224         wait_queue_head_t       delta_msr_wait;
225 };
226 
227 #ifdef CONFIG_SERIAL_AMBA_CONSOLE
228 static struct console ambauart_cons;
229 #endif
230 static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios);
231 static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout);
232 
233 #if 1 //def CONFIG_SERIAL_INTEGRATOR
234 static void amba_set_mctrl_null(struct amba_port *port, u_int mctrl)
235 {
236 }
237 
238 static struct amba_port amba_ports[SERIAL_AMBA_NR] = {
239         {
240                 uart_base:      IO_ADDRESS(INTEGRATOR_UART0_BASE),
241                 irq:            IRQ_UARTINT0,
242                 uartclk:        14745600,
243                 fifosize:       8,
244                 set_mctrl:      amba_set_mctrl_null,
245         },
246         {
247                 uart_base:      IO_ADDRESS(INTEGRATOR_UART1_BASE),
248                 irq:            IRQ_UARTINT1,
249                 uartclk:        14745600,
250                 fifosize:       8,
251                 set_mctrl:      amba_set_mctrl_null,
252         }
253 };
254 #endif
255 
256 static struct amba_state amba_state[SERIAL_AMBA_NR];
257 
258 static void ambauart_enable_rx_interrupt(struct amba_info *info)
259 {
260         unsigned int cr;
261 
262         cr = UART_GET_CR(info->port);
263         cr |= AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE;
264         UART_PUT_CR(info->port, cr);
265 }
266 
267 static void ambauart_disable_rx_interrupt(struct amba_info *info)
268 {
269         unsigned int cr;
270 
271         cr = UART_GET_CR(info->port);
272         cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
273         UART_PUT_CR(info->port, cr);
274 }
275 
276 static void ambauart_enable_tx_interrupt(struct amba_info *info)
277 {
278         unsigned int cr;
279 
280         cr = UART_GET_CR(info->port);
281         cr |= AMBA_UARTCR_TIE;
282         UART_PUT_CR(info->port, cr);
283 }
284 
285 static void ambauart_disable_tx_interrupt(struct amba_info *info)
286 {
287         unsigned int cr;
288 
289         cr = UART_GET_CR(info->port);
290         cr &= ~AMBA_UARTCR_TIE;
291         UART_PUT_CR(info->port, cr);
292 }
293 
294 static void ambauart_stop(struct tty_struct *tty)
295 {
296         struct amba_info *info = tty->driver_data;
297         unsigned long flags;
298 
299         save_flags(flags); cli();
300         ambauart_disable_tx_interrupt(info);
301         restore_flags(flags);
302 }
303 
304 static void ambauart_start(struct tty_struct *tty)
305 {
306         struct amba_info *info = tty->driver_data;
307         unsigned long flags;
308 
309         save_flags(flags); cli();
310         if (info->xmit.head != info->xmit.tail
311             && info->xmit.buf)
312                 ambauart_enable_tx_interrupt(info);
313         restore_flags(flags);
314 }
315 
316 
317 /*
318  * This routine is used by the interrupt handler to schedule
319  * processing in the software interrupt portion of the driver.
320  */
321 static void ambauart_event(struct amba_info *info, int event)
322 {
323         info->event |= 1 << event;
324         tasklet_schedule(&info->tlet);
325 }
326 
327 static void
328 #ifdef SUPPORT_SYSRQ
329 ambauart_rx_chars(struct amba_info *info, struct pt_regs *regs)
330 #else
331 ambauart_rx_chars(struct amba_info *info)
332 #endif
333 {
334         struct tty_struct *tty = info->tty;
335         unsigned int status, ch, rsr, flg, ignored = 0;
336         struct amba_icount *icount = &info->state->icount;
337         struct amba_port *port = info->port;
338 
339         status = UART_GET_FR(port);
340         while (UART_RX_DATA(status)) {
341                 ch = UART_GET_CHAR(port);
342 
343                 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
344                         goto ignore_char;
345                 icount->rx++;
346 
347                 flg = TTY_NORMAL;
348 
349                 /*
350                  * Note that the error handling code is
351                  * out of the main execution path
352                  */
353                 rsr = UART_GET_RSR(port);
354                 if (rsr & AMBA_UARTRSR_ANY)
355                         goto handle_error;
356 #ifdef SUPPORT_SYSRQ
357                 if (info->sysrq) {
358                         if (ch && time_before(jiffies, info->sysrq)) {
359                                 handle_sysrq(ch, regs, NULL, NULL);
360                                 info->sysrq = 0;
361                                 goto ignore_char;
362                         }
363                         info->sysrq = 0;
364                 }
365 #endif
366         error_return:
367                 *tty->flip.flag_buf_ptr++ = flg;
368                 *tty->flip.char_buf_ptr++ = ch;
369                 tty->flip.count++;
370         ignore_char:
371                 status = UART_GET_FR(port);
372         }
373 out:
374         tty_flip_buffer_push(tty);
375         return;
376 
377 handle_error:
378         if (rsr & AMBA_UARTRSR_BE) {
379                 rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
380                 icount->brk++;
381 
382 #ifdef SUPPORT_SYSRQ
383                 if (info->state->line == ambauart_cons.index) {
384                         if (!info->sysrq) {
385                                 info->sysrq = jiffies + HZ*5;
386                                 goto ignore_char;
387                         }
388                 }
389 #endif
390         } else if (rsr & AMBA_UARTRSR_PE)
391                 icount->parity++;
392         else if (rsr & AMBA_UARTRSR_FE)
393                 icount->frame++;
394         if (rsr & AMBA_UARTRSR_OE)
395                 icount->overrun++;
396 
397         if (rsr & info->ignore_status_mask) {
398                 if (++ignored > 100)
399                         goto out;
400                 goto ignore_char;
401         }
402         rsr &= info->read_status_mask;
403 
404         if (rsr & AMBA_UARTRSR_BE)
405                 flg = TTY_BREAK;
406         else if (rsr & AMBA_UARTRSR_PE)
407                 flg = TTY_PARITY;
408         else if (rsr & AMBA_UARTRSR_FE)
409                 flg = TTY_FRAME;
410 
411         if (rsr & AMBA_UARTRSR_OE) {
412                 /*
413                  * CHECK: does overrun affect the current character?
414                  * ASSUMPTION: it does not.
415                  */
416                 *tty->flip.flag_buf_ptr++ = flg;
417                 *tty->flip.char_buf_ptr++ = ch;
418                 tty->flip.count++;
419                 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
420                         goto ignore_char;
421                 ch = 0;
422                 flg = TTY_OVERRUN;
423         }
424 #ifdef SUPPORT_SYSRQ
425         info->sysrq = 0;
426 #endif
427         goto error_return;
428 }
429 
430 static void ambauart_tx_chars(struct amba_info *info)
431 {
432         struct amba_port *port = info->port;
433         int count;
434 
435         if (info->x_char) {
436                 UART_PUT_CHAR(port, info->x_char);
437                 info->state->icount.tx++;
438                 info->x_char = 0;
439                 return;
440         }
441         if (info->xmit.head == info->xmit.tail
442             || info->tty->stopped
443             || info->tty->hw_stopped) {
444                 ambauart_disable_tx_interrupt(info);
445                 return;
446         }
447 
448         count = port->fifosize;
449         do {
450                 UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
451                 info->xmit.tail = (info->xmit.tail + 1) & (AMBA_XMIT_SIZE - 1);
452                 info->state->icount.tx++;
453                 if (info->xmit.head == info->xmit.tail)
454                         break;
455         } while (--count > 0);
456 
457         if (CIRC_CNT(info->xmit.head,
458                      info->xmit.tail,
459                      AMBA_XMIT_SIZE) < WAKEUP_CHARS)
460                 ambauart_event(info, EVT_WRITE_WAKEUP);
461 
462         if (info->xmit.head == info->xmit.tail) {
463                 ambauart_disable_tx_interrupt(info);
464         }
465 }
466 
467 static void ambauart_modem_status(struct amba_info *info)
468 {
469         unsigned int status, delta;
470         struct amba_icount *icount = &info->state->icount;
471 
472         status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
473 
474         delta = status ^ info->old_status;
475         info->old_status = status;
476 
477         if (!delta)
478                 return;
479 
480         if (delta & AMBA_UARTFR_DCD) {
481                 icount->dcd++;
482 #ifdef CONFIG_HARD_PPS
483                 if ((info->flags & ASYNC_HARDPPS_CD) &&
484                     (status & AMBA_UARTFR_DCD)
485                         hardpps();
486 #endif
487                 if (info->flags & ASYNC_CHECK_CD) {
488                         if (status & AMBA_UARTFR_DCD)
489                                 wake_up_interruptible(&info->open_wait);
490                         else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
491                                    (info->flags & ASYNC_CALLOUT_NOHUP))) {
492                                 if (info->tty)
493                                         tty_hangup(info->tty);
494                         }
495                 }
496         }
497 
498         if (delta & AMBA_UARTFR_DSR)
499                 icount->dsr++;
500 
501         if (delta & AMBA_UARTFR_CTS) {
502                 icount->cts++;
503 
504                 if (info->flags & ASYNC_CTS_FLOW) {
505                         status &= AMBA_UARTFR_CTS;
506 
507                         if (info->tty->hw_stopped) {
508                                 if (status) {
509                                         info->tty->hw_stopped = 0;
510                                         ambauart_enable_tx_interrupt(info);
511                                         ambauart_event(info, EVT_WRITE_WAKEUP);
512                                 }
513                         } else {
514                                 if (!status) {
515                                         info->tty->hw_stopped = 1;
516                                         ambauart_disable_tx_interrupt(info);
517                                 }
518                         }
519                 }
520         }
521         wake_up_interruptible(&info->delta_msr_wait);
522 
523 }
524 
525 static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
526 {
527         struct amba_info *info = dev_id;
528         unsigned int status, pass_counter = 0;
529 
530 #if DEBUG_LEDS
531         // tell the world
532         set_leds(get_leds() | RED_LED);
533 #endif
534 
535         status = UART_GET_INT_STATUS(info->port);
536         do {
537                 /*
538                  * FIXME: what about clearing the interrupts?
539                  */
540 
541                 if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
542 #ifdef SUPPORT_SYSRQ
543                         ambauart_rx_chars(info, regs);
544 #else
545                         ambauart_rx_chars(info);
546 #endif
547                 if (status & AMBA_UARTIIR_TIS)
548                         ambauart_tx_chars(info);
549                 if (status & AMBA_UARTIIR_MIS)
550                         ambauart_modem_status(info);
551                 if (pass_counter++ > AMBA_ISR_PASS_LIMIT)
552                         break;
553 
554                 status = UART_GET_INT_STATUS(info->port);
555         } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS));
556 
557 #if DEBUG_LEDS
558         // tell the world
559         set_leds(get_leds() & ~RED_LED);
560 #endif
561 }
562 
563 static void ambauart_tasklet_action(unsigned long data)
564 {
565         struct amba_info *info = (struct amba_info *)data;
566         struct tty_struct *tty;
567 
568         tty = info->tty;
569         if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event))
570                 return;
571 
572         if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
573             tty->ldisc.write_wakeup)
574                 (tty->ldisc.write_wakeup)(tty);
575         wake_up_interruptible(&tty->write_wait);
576 }
577 
578 static int ambauart_startup(struct amba_info *info)
579 {
580         unsigned long flags;
581         unsigned long page;
582         int retval = 0;
583 
584         page = get_zeroed_page(GFP_KERNEL);
585         if (!page)
586                 return -ENOMEM;
587 
588         save_flags(flags); cli();
589 
590         if (info->flags & ASYNC_INITIALIZED) {
591                 free_page(page);
592                 goto errout;
593         }
594 
595         if (info->xmit.buf)
596                 free_page(page);
597         else
598                 info->xmit.buf = (unsigned char *) page;
599 
600         /*
601          * Allocate the IRQ
602          */
603         retval = request_irq(info->port->irq, ambauart_int, 0, "amba", info);
604         if (retval) {
605                 if (capable(CAP_SYS_ADMIN)) {
606                         if (info->tty)
607                                 set_bit(TTY_IO_ERROR, &info->tty->flags);
608                         retval = 0;
609                 }
610                 goto errout;
611         }
612 
613         info->mctrl = 0;
614         if (info->tty->termios->c_cflag & CBAUD)
615                 info->mctrl = TIOCM_RTS | TIOCM_DTR;
616         info->port->set_mctrl(info->port, info->mctrl);
617 
618         /*
619          * initialise the old status of the modem signals
620          */
621         info->old_status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
622 
623         /*
624          * Finally, enable interrupts
625          */
626         ambauart_enable_rx_interrupt(info);
627 
628         if (info->tty)
629                 clear_bit(TTY_IO_ERROR, &info->tty->flags);
630         info->xmit.head = info->xmit.tail = 0;
631 
632         /*
633          * Set up the tty->alt_speed kludge
634          */
635         if (info->tty) {
636                 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
637                         info->tty->alt_speed = 57600;
638                 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
639                         info->tty->alt_speed = 115200;
640                 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
641                         info->tty->alt_speed = 230400;
642                 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
643                         info->tty->alt_speed = 460800;
644         }
645 
646         /*
647          * and set the speed of the serial port
648          */
649         ambauart_change_speed(info, 0);
650 
651         info->flags |= ASYNC_INITIALIZED;
652         restore_flags(flags);
653         return 0;
654 
655 errout:
656         restore_flags(flags);
657         return retval;
658 }
659 
660 /*
661  * This routine will shutdown a serial port; interrupts are disabled, and
662  * DTR is dropped if the hangup on close termio flag is on.
663  */
664 static void ambauart_shutdown(struct amba_info *info)
665 {
666         unsigned long flags;
667 
668         if (!(info->flags & ASYNC_INITIALIZED))
669                 return;
670 
671         save_flags(flags); cli(); /* Disable interrupts */
672 
673         /*
674          * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
675          * here so the queue might never be woken up
676          */
677         wake_up_interruptible(&info->delta_msr_wait);
678 
679         /*
680          * Free the IRQ
681          */
682         free_irq(info->port->irq, info);
683 
684         if (info->xmit.buf) {
685                 unsigned long pg = (unsigned long) info->xmit.buf;
686                 info->xmit.buf = NULL;
687                 free_page(pg);
688         }
689 
690         /*
691          * disable all interrupts, disable the port
692          */
693         UART_PUT_CR(info->port, 0);
694 
695         /* disable break condition and fifos */
696         UART_PUT_LCRH(info->port, UART_GET_LCRH(info->port) &
697                 ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
698 
699         if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
700                 info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS);
701         info->port->set_mctrl(info->port, info->mctrl);
702 
703         /* kill off our tasklet */
704         tasklet_kill(&info->tlet);
705         if (info->tty)
706                 set_bit(TTY_IO_ERROR, &info->tty->flags);
707 
708         info->flags &= ~ASYNC_INITIALIZED;
709         restore_flags(flags);
710 }
711 
712 static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios)
713 {
714         unsigned int lcr_h, baud, quot, cflag, old_cr, bits;
715         unsigned long flags;
716 
717         if (!info->tty || !info->tty->termios)
718                 return;
719 
720         cflag = info->tty->termios->c_cflag;
721 
722 #if DEBUG
723         printk("ambauart_set_cflag(0x%x) called\n", cflag);
724 #endif
725         /* byte size and parity */
726         switch (cflag & CSIZE) {
727         case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; bits = 7;  break;
728         case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; bits = 8;  break;
729         case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; bits = 9;  break;
730         default:  lcr_h = AMBA_UARTLCR_H_WLEN_8; bits = 10; break; // CS8
731         }
732         if (cflag & CSTOPB) {
733                 lcr_h |= AMBA_UARTLCR_H_STP2;
734                 bits ++;
735         }
736         if (cflag & PARENB) {
737                 lcr_h |= AMBA_UARTLCR_H_PEN;
738                 bits++;
739                 if (!(cflag & PARODD))
740                         lcr_h |= AMBA_UARTLCR_H_EPS;
741         }
742         if (info->port->fifosize > 1)
743                 lcr_h |= AMBA_UARTLCR_H_FEN;
744 
745         do {
746                 /* Determine divisor based on baud rate */
747                 baud = tty_get_baud_rate(info->tty);
748                 if (!baud)
749                         baud = 9600;
750 
751                 if (baud == 38400 &&
752                     ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
753                         quot = info->state->custom_divisor;
754                 else
755                         quot = (info->port->uartclk / (16 * baud)) - 1;
756 
757                 if (!quot && old_termios) {
758                         info->tty->termios->c_cflag &= ~CBAUD;
759                         info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
760                         old_termios = NULL;
761                 }
762         } while (quot == 0 && old_termios);
763 
764         /* As a last resort, if the quotient is zero, default to 9600 bps */
765         if (!quot)
766                 quot = (info->port->uartclk / (16 * 9600)) - 1;
767                 
768         info->timeout = (info->port->fifosize * HZ * bits * quot) /
769                          (info->port->uartclk / 16);
770         info->timeout += HZ/50;         /* Add .02 seconds of slop */
771 
772         if (cflag & CRTSCTS)
773                 info->flags |= ASYNC_CTS_FLOW;
774         else
775                 info->flags &= ~ASYNC_CTS_FLOW;
776         if (cflag & CLOCAL)
777                 info->flags &= ~ASYNC_CHECK_CD;
778         else
779                 info->flags |= ASYNC_CHECK_CD;
780 
781         /*
782          * Set up parity check flag
783          */
784 #define RELEVENT_IFLAG(iflag)   ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
785 
786         info->read_status_mask = AMBA_UARTRSR_OE;
787         if (I_INPCK(info->tty))
788                 info->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
789         if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
790                 info->read_status_mask |= AMBA_UARTRSR_BE;
791 
792         /*
793          * Characters to ignore
794          */
795         info->ignore_status_mask = 0;
796         if (I_IGNPAR(info->tty))
797                 info->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
798         if (I_IGNBRK(info->tty)) {
799                 info->ignore_status_mask |= AMBA_UARTRSR_BE;
800                 /*
801                  * If we're ignoring parity and break indicators,
802                  * ignore overruns to (for real raw support).
803                  */
804                 if (I_IGNPAR(info->tty))
805                         info->ignore_status_mask |= AMBA_UARTRSR_OE;
806         }
807 
808         /* first, disable everything */
809         save_flags(flags); cli();
810         old_cr = UART_GET_CR(info->port) &= ~AMBA_UARTCR_MSIE;
811 
812         if ((info->flags & ASYNC_HARDPPS_CD) ||
813             (cflag & CRTSCTS) ||
814             !(cflag & CLOCAL))
815                 old_cr |= AMBA_UARTCR_MSIE;
816 
817         UART_PUT_CR(info->port, 0);
818         restore_flags(flags);
819 
820         /* Set baud rate */
821         UART_PUT_LCRM(info->port, ((quot & 0xf00) >> 8));
822         UART_PUT_LCRL(info->port, (quot & 0xff));
823 
824         /*
825          * ----------v----------v----------v----------v-----
826          * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
827          * ----------^----------^----------^----------^-----
828          */
829         UART_PUT_LCRH(info->port, lcr_h);
830         UART_PUT_CR(info->port, old_cr);
831 }
832 
833 static void ambauart_put_char(struct tty_struct *tty, u_char ch)
834 {
835         struct amba_info *info = tty->driver_data;
836         unsigned long flags;
837 
838         if (!tty || !info->xmit.buf)
839                 return;
840 
841         save_flags(flags); cli();
842         if (CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE) != 0) {
843                 info->xmit.buf[info->xmit.head] = ch;
844                 info->xmit.head = (info->xmit.head + 1) & (AMBA_XMIT_SIZE - 1);
845         }
846         restore_flags(flags);
847 }
848 
849 static void ambauart_flush_chars(struct tty_struct *tty)
850 {
851         struct amba_info *info = tty->driver_data;
852         unsigned long flags;
853 
854         if (info->xmit.head == info->xmit.tail
855             || tty->stopped
856             || tty->hw_stopped
857             || !info->xmit.buf)
858                 return;
859 
860         save_flags(flags); cli();
861         ambauart_enable_tx_interrupt(info);
862         restore_flags(flags);
863 }
864 
865 static int ambauart_write(struct tty_struct *tty, int from_user,
866                           const u_char * buf, int count)
867 {
868         struct amba_info *info = tty->driver_data;
869         unsigned long flags;
870         int c, ret = 0;
871 
872         if (!tty || !info->xmit.buf || !tmp_buf)
873                 return 0;
874 
875         save_flags(flags);
876         if (from_user) {
877                 down(&tmp_buf_sem);
878                 while (1) {
879                         int c1;
880                         c = CIRC_SPACE_TO_END(info->xmit.head,
881                                               info->xmit.tail,
882                                               AMBA_XMIT_SIZE);
883                         if (count < c)
884                                 c = count;
885                         if (c <= 0)
886                                 break;
887 
888                         c -= copy_from_user(tmp_buf, buf, c);
889                         if (!c) {
890                                 if (!ret)
891                                         ret = -EFAULT;
892                                 break;
893                         }
894                         cli();
895                         c1 = CIRC_SPACE_TO_END(info->xmit.head,
896                                                info->xmit.tail,
897                                                AMBA_XMIT_SIZE);
898                         if (c1 < c)
899                                 c = c1;
900                         memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
901                         info->xmit.head = (info->xmit.head + c) &
902                                           (AMBA_XMIT_SIZE - 1);
903                         restore_flags(flags);
904                         buf += c;
905                         count -= c;
906                         ret += c;
907                 }
908                 up(&tmp_buf_sem);
909         } else {
910                 cli();
911                 while (1) {
912                         c = CIRC_SPACE_TO_END(info->xmit.head,
913                                               info->xmit.tail,
914                                               AMBA_XMIT_SIZE);
915                         if (count < c)
916                                 c = count;
917                         if (c <= 0)
918                                 break;
919                         memcpy(info->xmit.buf + info->xmit.head, buf, c);
920                         info->xmit.head = (info->xmit.head + c) &
921                                           (AMBA_XMIT_SIZE - 1);
922                         buf += c;
923                         count -= c;
924                         ret += c;
925                 }
926                 restore_flags(flags);
927         }
928         if (info->xmit.head != info->xmit.tail
929             && !tty->stopped
930             && !tty->hw_stopped)
931                 ambauart_enable_tx_interrupt(info);
932         return ret;
933 }
934 
935 static int ambauart_write_room(struct tty_struct *tty)
936 {
937         struct amba_info *info = tty->driver_data;
938 
939         return CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
940 }
941 
942 static int ambauart_chars_in_buffer(struct tty_struct *tty)
943 {
944         struct amba_info *info = tty->driver_data;
945 
946         return CIRC_CNT(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
947 }
948 
949 static void ambauart_flush_buffer(struct tty_struct *tty)
950 {
951         struct amba_info *info = tty->driver_data;
952         unsigned long flags;
953 
954 #if DEBUG
955         printk("ambauart_flush_buffer(%d) called\n",
956                MINOR(tty->device) - tty->driver.minor_start);
957 #endif
958         save_flags(flags); cli();
959         info->xmit.head = info->xmit.tail = 0;
960         restore_flags(flags);
961         wake_up_interruptible(&tty->write_wait);
962         if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
963             tty->ldisc.write_wakeup)
964                 (tty->ldisc.write_wakeup)(tty);
965 }
966 
967 /*
968  * This function is used to send a high-priority XON/XOFF character to
969  * the device
970  */
971 static void ambauart_send_xchar(struct tty_struct *tty, char ch)
972 {
973         struct amba_info *info = tty->driver_data;
974 
975         info->x_char = ch;
976         if (ch)
977                 ambauart_enable_tx_interrupt(info);
978 }
979 
980 static void ambauart_throttle(struct tty_struct *tty)
981 {
982         struct amba_info *info = tty->driver_data;
983         unsigned long flags;
984 
985         if (I_IXOFF(tty))
986                 ambauart_send_xchar(tty, STOP_CHAR(tty));
987 
988         if (tty->termios->c_cflag & CRTSCTS) {
989                 save_flags(flags); cli();
990                 info->mctrl &= ~TIOCM_RTS;
991                 info->port->set_mctrl(info->port, info->mctrl);
992                 restore_flags(flags);
993         }
994 }
995 
996 static void ambauart_unthrottle(struct tty_struct *tty)
997 {
998         struct amba_info *info = (struct amba_info *) tty->driver_data;
999         unsigned long flags;
1000 
1001         if (I_IXOFF(tty)) {
1002                 if (info->x_char)
1003                         info->x_char = 0;
1004                 else
1005                         ambauart_send_xchar(tty, START_CHAR(tty));
1006         }
1007 
1008         if (tty->termios->c_cflag & CRTSCTS) {
1009                 save_flags(flags); cli();
1010                 info->mctrl |= TIOCM_RTS;
1011                 info->port->set_mctrl(info->port, info->mctrl);
1012                 restore_flags(flags);
1013         }
1014 }
1015 
1016 static int get_serial_info(struct amba_info *info, struct serial_struct *retinfo)
1017 {
1018         struct amba_state *state = info->state;
1019         struct amba_port *port = info->port;
1020         struct serial_struct tmp;
1021 
1022         memset(&tmp, 0, sizeof(tmp));
1023         tmp.type           = 0;
1024         tmp.line           = state->line;
1025         tmp.port           = port->uart_base;
1026         if (HIGH_BITS_OFFSET)
1027                 tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET;
1028         tmp.irq            = port->irq;
1029         tmp.flags          = 0;
1030         tmp.xmit_fifo_size = port->fifosize;
1031         tmp.baud_base      = port->uartclk / 16;
1032         tmp.close_delay    = state->close_delay;
1033         tmp.closing_wait   = state->closing_wait;
1034         tmp.custom_divisor = state->custom_divisor;
1035 
1036         if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
1037                 return -EFAULT;
1038         return 0;
1039 }
1040 
1041 static int set_serial_info(struct amba_info *info,
1042                            struct serial_struct *newinfo)
1043 {
1044         struct serial_struct new_serial;
1045         struct amba_state *state, old_state;
1046         struct amba_port *port;
1047         unsigned long new_port;
1048         unsigned int i, change_irq, change_port;
1049         int retval = 0;
1050 
1051         if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
1052                 return -EFAULT;
1053 
1054         state = info->state;
1055         old_state = *state;
1056         port = info->port;
1057 
1058         new_port = new_serial.port;
1059         if (HIGH_BITS_OFFSET)
1060                 new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
1061 
1062         change_irq  = new_serial.irq != port->irq;
1063         change_port = new_port != port->uart_base;
1064 
1065         if (!capable(CAP_SYS_ADMIN)) {
1066                 if (change_irq || change_port ||
1067                     (new_serial.baud_base != port->uartclk / 16) ||
1068                     (new_serial.close_delay != state->close_delay) ||
1069                     (new_serial.xmit_fifo_size != port->fifosize) ||
1070                     ((new_serial.flags & ~ASYNC_USR_MASK) !=
1071                      (state->flags & ~ASYNC_USR_MASK)))
1072                         return -EPERM;
1073                 state->flags = ((state->flags & ~ASYNC_USR_MASK) |
1074                                 (new_serial.flags & ASYNC_USR_MASK));
1075                 info->flags = ((info->flags & ~ASYNC_USR_MASK) |
1076                                (new_serial.flags & ASYNC_USR_MASK));
1077                 state->custom_divisor = new_serial.custom_divisor;
1078                 goto check_and_exit;
1079         }
1080 
1081         if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
1082             (new_serial.baud_base < 9600))
1083                 return -EINVAL;
1084 
1085         if (new_serial.type && change_port) {
1086                 for (i = 0; i < SERIAL_AMBA_NR; i++)
1087                         if ((port != amba_ports + i) &&
1088                             amba_ports[i].uart_base != new_port)
1089                                 return -EADDRINUSE;
1090         }
1091 
1092         if ((change_port || change_irq) && (state->count > 1))
1093                 return -EBUSY;
1094 
1095         /*
1096          * OK, past this point, all the error checking has been done.
1097          * At this point, we start making changes.....
1098          */
1099         port->uartclk = new_serial.baud_base * 16;
1100         state->flags = ((state->flags & ~ASYNC_FLAGS) |
1101                         (new_serial.flags & ASYNC_FLAGS));
1102         info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
1103                        (info->flags & ASYNC_INTERNAL_FLAGS));
1104         state->custom_divisor = new_serial.custom_divisor;
1105         state->close_delay = new_serial.close_delay * HZ / 100;
1106         state->closing_wait = new_serial.closing_wait * HZ / 100;
1107         info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
1108         port->fifosize = new_serial.xmit_fifo_size;
1109 
1110         if (change_port || change_irq) {
1111                 /*
1112                  * We need to shutdown the serial port at the old
1113                  * port/irq combination.
1114                  */
1115                 ambauart_shutdown(info);
1116                 port->irq = new_serial.irq;
1117                 port->uart_base = new_port;
1118         }
1119 
1120 check_and_exit:
1121         if (!port->uart_base)
1122                 return 0;
1123         if (info->flags & ASYNC_INITIALIZED) {
1124                 if ((old_state.flags & ASYNC_SPD_MASK) !=
1125                     (state->flags & ASYNC_SPD_MASK) ||
1126                     (old_state.custom_divisor != state->custom_divisor)) {
1127                         if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1128                                 info->tty->alt_speed = 57600;
1129                         if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
1130                                 info->tty->alt_speed = 115200;
1131                         if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
1132                                 info->tty->alt_speed = 230400;
1133                         if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
1134                                 info->tty->alt_speed = 460800;
1135                         ambauart_change_speed(info, NULL);
1136                 }
1137         } else
1138                 retval = ambauart_startup(info);
1139         return retval;
1140 }
1141 
1142 
1143 /*
1144  * get_lsr_info - get line status register info
1145  */
1146 static int get_lsr_info(struct amba_info *info, unsigned int *value)
1147 {
1148         unsigned int result, status;
1149         unsigned long flags;
1150 
1151         save_flags(flags); cli();
1152         status = UART_GET_FR(info->port);
1153         restore_flags(flags);
1154         result = status & AMBA_UARTFR_BUSY ? TIOCSER_TEMT : 0;
1155 
1156         /*
1157          * If we're about to load something into the transmit
1158          * register, we'll pretend the transmitter isn't empty to
1159          * avoid a race condition (depending on when the transmit
1160          * interrupt happens).
1161          */
1162         if (info->x_char ||
1163             ((CIRC_CNT(info->xmit.head, info->xmit.tail,
1164                        AMBA_XMIT_SIZE) > 0) &&
1165              !info->tty->stopped && !info->tty->hw_stopped))
1166                 result &= TIOCSER_TEMT;
1167         
1168         return put_user(result, value);
1169 }
1170 
1171 static int get_modem_info(struct amba_info *info, unsigned int *value)
1172 {
1173         unsigned int result = info->mctrl;
1174         unsigned int status;
1175 
1176         status = UART_GET_FR(info->port);
1177         if (status & AMBA_UARTFR_DCD)
1178                 result |= TIOCM_CAR;
1179         if (status & AMBA_UARTFR_DSR)
1180                 result |= TIOCM_DSR;
1181         if (status & AMBA_UARTFR_CTS)
1182                 result |= TIOCM_CTS;
1183 
1184         return put_user(result, value);
1185 }
1186 
1187 static int set_modem_info(struct amba_info *info, unsigned int cmd,
1188                           unsigned int *value)
1189 {
1190         unsigned int arg, old;
1191         unsigned long flags;
1192 
1193         if (get_user(arg, value))
1194                 return -EFAULT;
1195 
1196         old = info->mctrl;
1197         switch (cmd) {
1198         case TIOCMBIS:
1199                 info->mctrl |= arg;
1200                 break;
1201 
1202         case TIOCMBIC:
1203                 info->mctrl &= ~arg;
1204                 break;
1205 
1206         case TIOCMSET:
1207                 info->mctrl = arg;
1208                 break;
1209 
1210         default:
1211                 return -EINVAL;
1212         }
1213         save_flags(flags); cli();
1214         if (old != info->mctrl)
1215                 info->port->set_mctrl(info->port, info->mctrl);
1216         restore_flags(flags);
1217         return 0;
1218 }
1219 
1220 static void ambauart_break_ctl(struct tty_struct *tty, int break_state)
1221 {
1222         struct amba_info *info = tty->driver_data;
1223         unsigned long flags;
1224         unsigned int lcr_h;
1225 
1226         save_flags(flags); cli();
1227         lcr_h = UART_GET_LCRH(info->port);
1228         if (break_state == -1)
1229                 lcr_h |= AMBA_UARTLCR_H_BRK;
1230         else
1231                 lcr_h &= ~AMBA_UARTLCR_H_BRK;
1232         UART_PUT_LCRH(info->port, lcr_h);
1233         restore_flags(flags);
1234 }
1235 
1236 static int ambauart_ioctl(struct tty_struct *tty, struct file *file,
1237                            unsigned int cmd, unsigned long arg)
1238 {
1239         struct amba_info *info = tty->driver_data;
1240         struct amba_icount cprev, cnow;
1241         struct serial_icounter_struct icount;
1242         unsigned long flags;
1243 
1244         if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1245             (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
1246             (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
1247                 if (tty->flags & (1 << TTY_IO_ERROR))
1248                         return -EIO;
1249         }
1250 
1251         switch (cmd) {
1252                 case TIOCMGET:
1253                         return get_modem_info(info, (unsigned int *)arg);
1254                 case TIOCMBIS:
1255                 case TIOCMBIC:
1256                 case TIOCMSET:
1257                         return set_modem_info(info, cmd, (unsigned int *)arg);
1258                 case TIOCGSERIAL:
1259                         return get_serial_info(info,
1260                                                (struct serial_struct *)arg);
1261                 case TIOCSSERIAL:
1262                         return set_serial_info(info,
1263                                                (struct serial_struct *)arg);
1264                 case TIOCSERGETLSR: /* Get line status register */
1265                         return get_lsr_info(info, (unsigned int *)arg);
1266                 /*
1267                  * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
1268                  * - mask passed in arg for lines of interest
1269                  *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
1270                  * Caller should use TIOCGICOUNT to see which one it was
1271                  */
1272                 case TIOCMIWAIT:
1273                         save_flags(flags); cli();
1274                         /* note the counters on entry */
1275                         cprev = info->state->icount;
1276                         /* Force modem status interrupts on */
1277                         UART_PUT_CR(info->port, UART_GET_CR(info->port) | AMBA_UARTCR_MSIE);
1278                         restore_flags(flags);
1279                         while (1) {
1280                                 interruptible_sleep_on(&info->delta_msr_wait);
1281                                 /* see if a signal did it */
1282                                 if (signal_pending(current))
1283                                         return -ERESTARTSYS;
1284                                 save_flags(flags); cli();
1285                                 cnow = info->state->icount; /* atomic copy */
1286                                 restore_flags(flags);
1287                                 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
1288                                     cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
1289                                         return -EIO; /* no change => error */
1290                                 if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
1291                                     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
1292                                     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
1293                                     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
1294                                         return 0;
1295                                 }
1296                                 cprev = cnow;
1297                         }
1298                         /* NOTREACHED */
1299 
1300                 /*
1301                  * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1302                  * Return: write counters to the user passed counter struct
1303                  * NB: both 1->0 and 0->1 transitions are counted except for
1304                  *     RI where only 0->1 is counted.
1305                  */
1306                 case TIOCGICOUNT:
1307                         save_flags(flags); cli();
1308                         cnow = info->state->icount;
1309                         restore_flags(flags);
1310                         icount.cts = cnow.cts;
1311                         icount.dsr = cnow.dsr;
1312                         icount.rng = cnow.rng;
1313                         icount.dcd = cnow.dcd;
1314                         icount.rx  = cnow.rx;
1315                         icount.tx  = cnow.tx;
1316                         icount.frame = cnow.frame;
1317                         icount.overrun = cnow.overrun;
1318                         icount.parity = cnow.parity;
1319                         icount.brk = cnow.brk;
1320                         icount.buf_overrun = cnow.buf_overrun;
1321 
1322                         return copy_to_user((void *)arg, &icount, sizeof(icount))
1323                                         ? -EFAULT : 0;
1324 
1325                 default:
1326                         return -ENOIOCTLCMD;
1327         }
1328         return 0;
1329 }
1330 
1331 static void ambauart_set_termios(struct tty_struct *tty, struct termios *old_termios)
1332 {
1333         struct amba_info *info = tty->driver_data;
1334         unsigned long flags;
1335         unsigned int cflag = tty->termios->c_cflag;
1336 
1337         if ((cflag ^ old_termios->c_cflag) == 0 &&
1338             RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
1339                 return;
1340 
1341         ambauart_change_speed(info, old_termios);
1342 
1343         /* Handle transition to B0 status */
1344         if ((old_termios->c_cflag & CBAUD) &&
1345             !(cflag & CBAUD)) {
1346                 save_flags(flags); cli();
1347                 info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
1348                 info->port->set_mctrl(info->port, info->mctrl);
1349                 restore_flags(flags);
1350         }
1351 
1352         /* Handle transition away from B0 status */
1353         if (!(old_termios->c_cflag & CBAUD) &&
1354             (cflag & CBAUD)) {
1355                 save_flags(flags); cli();
1356                 info->mctrl |= TIOCM_DTR;
1357                 if (!(cflag & CRTSCTS) ||
1358                     !test_bit(TTY_THROTTLED, &tty->flags))
1359                         info->mctrl |= TIOCM_RTS;
1360                 info->port->set_mctrl(info->port, info->mctrl);
1361                 restore_flags(flags);
1362         }
1363 
1364         /* Handle turning off CRTSCTS */
1365         if ((old_termios->c_cflag & CRTSCTS) &&
1366             !(cflag & CRTSCTS)) {
1367                 tty->hw_stopped = 0;
1368                 ambauart_start(tty);
1369         }
1370 
1371 #if 0
1372         /*
1373          * No need to wake up processes in open wait, since they
1374          * sample the CLOCAL flag once, and don't recheck it.
1375          * XXX  It's not clear whether the current behavior is correct
1376          * or not.  Hence, this may change.....
1377          */
1378         if (!(old_termios->c_cflag & CLOCAL) &&
1379             (tty->termios->c_cflag & CLOCAL))
1380                 wake_up_interruptible(&info->open_wait);
1381 #endif
1382 }
1383 
1384 static void ambauart_close(struct tty_struct *tty, struct file *filp)
1385 {
1386         struct amba_info *info = tty->driver_data;
1387         struct amba_state *state;
1388         unsigned long flags;
1389 
1390         if (!info)
1391                 return;
1392 
1393         state = info->state;
1394 
1395 #if DEBUG
1396         printk("ambauart_close() called\n");
1397 #endif
1398 
1399         save_flags(flags); cli();
1400 
1401         if (tty_hung_up_p(filp)) {
1402                 MOD_DEC_USE_COUNT;
1403                 restore_flags(flags);
1404                 return;
1405         }
1406 
1407         if ((tty->count == 1) && (state->count != 1)) {
1408                 /*
1409                  * Uh, oh.  tty->count is 1, which means that the tty
1410                  * structure will be freed.  state->count should always
1411                  * be one in these conditions.  If it's greater than
1412                  * one, we've got real problems, since it means the
1413                  * serial port won't be shutdown.
1414                  */
1415                 printk("ambauart_close: bad serial port count; tty->count is 1, "
1416                        "state->count is %d\n", state->count);
1417                 state->count = 1;
1418         }
1419         if (--state->count < 0) {
1420                 printk("rs_close: bad serial port count for %s%d: %d\n",
1421                        tty->driver.name, info->state->line, state->count);
1422                 state->count = 0;
1423         }
1424         if (state->count) {
1425                 MOD_DEC_USE_COUNT;
1426                 restore_flags(flags);
1427                 return;
1428         }
1429         info->flags |= ASYNC_CLOSING;
1430         restore_flags(flags);
1431         /*
1432          * Save the termios structure, since this port may have
1433          * separate termios for callout and dialin.
1434          */
1435         if (info->flags & ASYNC_NORMAL_ACTIVE)
1436                 info->state->normal_termios = *tty->termios;
1437         if (info->flags & ASYNC_CALLOUT_ACTIVE)
1438                 info->state->callout_termios = *tty->termios;
1439         /*
1440          * Now we wait for the transmit buffer to clear; and we notify
1441          * the line discipline to only process XON/XOFF characters.
1442          */
1443         tty->closing = 1;
1444         if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1445                 tty_wait_until_sent(tty, info->state->closing_wait);
1446         /*
1447          * At this point, we stop accepting input.  To do this, we
1448          * disable the receive line status interrupts.
1449          */
1450         if (info->flags & ASYNC_INITIALIZED) {
1451                 ambauart_disable_rx_interrupt(info);
1452                 /*
1453                  * Before we drop DTR, make sure the UART transmitter
1454                  * has completely drained; this is especially
1455                  * important if there is a transmit FIFO!
1456                  */
1457                 ambauart_wait_until_sent(tty, info->timeout);
1458         }
1459         ambauart_shutdown(info);
1460         if (tty->driver.flush_buffer)
1461                 tty->driver.flush_buffer(tty);
1462         if (tty->ldisc.flush_buffer)
1463                 tty->ldisc.flush_buffer(tty);
1464         tty->closing = 0;
1465         info->event = 0;
1466         info->tty = NULL;
1467         if (info->blocked_open) {
1468                 if (info->state->close_delay) {
1469                         set_current_state(TASK_INTERRUPTIBLE);
1470                         schedule_timeout(info->state->close_delay);
1471                 }
1472                 wake_up_interruptible(&info->open_wait);
1473         }
1474         info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
1475                          ASYNC_CLOSING);
1476         wake_up_interruptible(&info->close_wait);
1477         MOD_DEC_USE_COUNT;
1478 }
1479 
1480 static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout)
1481 {
1482         struct amba_info *info = (struct amba_info *) tty->driver_data;
1483         unsigned long char_time, expire;
1484         unsigned int status;
1485 
1486         if (info->port->fifosize == 0)
1487                 return;
1488 
1489         /*
1490          * Set the check interval to be 1/5 of the estimated time to
1491          * send a single character, and make it at least 1.  The check
1492          * interval should also be less than the timeout.
1493          *
1494          * Note: we have to use pretty tight timings here to satisfy
1495          * the NIST-PCTS.
1496          */
1497         char_time = (info->timeout - HZ/50) / info->port->fifosize;
1498         char_time = char_time / 5;
1499         if (char_time == 0)
1500                 char_time = 1;
1501         if (timeout && timeout < char_time)
1502                 char_time = timeout;
1503         /*
1504          * If the transmitter hasn't cleared in twice the approximate
1505          * amount of time to send the entire FIFO, it probably won't
1506          * ever clear.  This assumes the UART isn't doing flow
1507          * control, which is currently the case.  Hence, if it ever
1508          * takes longer than info->timeout, this is probably due to a
1509          * UART bug of some kind.  So, we clamp the timeout parameter at
1510          * 2*info->timeout.
1511          */
1512         if (!timeout || timeout > 2 * info->timeout)
1513                 timeout = 2 * info->timeout;
1514 
1515         expire = jiffies + timeout;
1516 #if DEBUG
1517         printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n",
1518                MINOR(tty->device) - tty->driver.minor_start, jiffies,
1519                expire);
1520 #endif
1521         while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) {
1522                 set_current_state(TASK_INTERRUPTIBLE);
1523                 schedule_timeout(char_time);
1524                 if (signal_pending(current))
1525                         break;
1526                 if (timeout && time_after(jiffies, expire))
1527                         break;
1528                 status = UART_GET_FR(info->port);
1529         }
1530         set_current_state(TASK_RUNNING);
1531 }
1532 
1533 static void ambauart_hangup(struct tty_struct *tty)
1534 {
1535         struct amba_info *info = tty->driver_data;
1536         struct amba_state *state = info->state;
1537 
1538         ambauart_flush_buffer(tty);
1539         if (info->flags & ASYNC_CLOSING)
1540                 return;
1541         ambauart_shutdown(info);
1542         info->event = 0;
1543         state->count = 0;
1544         info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
1545         info->tty = NULL;
1546         wake_up_interruptible(&info->open_wait);
1547 }
1548 
1549 static int block_til_ready(struct tty_struct *tty, struct file *filp,
1550                            struct amba_info *info)
1551 {
1552         DECLARE_WAITQUEUE(wait, current);
1553         struct amba_state *state = info->state;
1554         unsigned long flags;
1555         int do_clocal = 0, extra_count = 0, retval;
1556 
1557         /*
1558          * If the device is in the middle of being closed, then block
1559          * until it's done, and then try again.
1560          */
1561         if (tty_hung_up_p(filp) ||
1562             (info->flags & ASYNC_CLOSING)) {
1563                 if (info->flags & ASYNC_CLOSING)
1564                         interruptible_sleep_on(&info->close_wait);
1565                 return (info->flags & ASYNC_HUP_NOTIFY) ?
1566                         -EAGAIN : -ERESTARTSYS;
1567         }
1568 
1569         /*
1570          * If this is a callout device, then just make sure the normal
1571          * device isn't being used.
1572          */
1573         if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
1574                 if (info->flags & ASYNC_NORMAL_ACTIVE)
1575                         return -EBUSY;
1576                 if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
1577                     (info->flags & ASYNC_SESSION_LOCKOUT) &&
1578                     (info->session != current->session))
1579                         return -EBUSY;
1580                 if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
1581                     (info->flags & ASYNC_PGRP_LOCKOUT) &&
1582                     (info->pgrp != current->pgrp))
1583                         return -EBUSY;
1584                 info->flags |= ASYNC_CALLOUT_ACTIVE;
1585                 return 0;
1586         }
1587 
1588         /*
1589          * If non-blocking mode is set, or the port is not enabled,
1590          * then make the check up front and then exit.
1591          */
1592         if ((filp->f_flags & O_NONBLOCK) ||
1593             (tty->flags & (1 << TTY_IO_ERROR))) {
1594                 if (info->flags & ASYNC_CALLOUT_ACTIVE)
1595                         return -EBUSY;
1596                 info->flags |= ASYNC_NORMAL_ACTIVE;
1597                 return 0;
1598         }
1599 
1600         if (info->flags & ASYNC_CALLOUT_ACTIVE) {
1601                 if (state->normal_termios.c_cflag & CLOCAL)
1602                         do_clocal = 1;
1603         } else {
1604                 if (tty->termios->c_cflag & CLOCAL)
1605                         do_clocal = 1;
1606         }
1607 
1608         /*
1609          * Block waiting for the carrier detect and the line to become
1610          * free (i.e., not in use by the callout).  While we are in
1611          * this loop, state->count is dropped by one, so that
1612          * rs_close() knows when to free things.  We restore it upon
1613          * exit, either normal or abnormal.
1614          */
1615         retval = 0;
1616         add_wait_queue(&info->open_wait, &wait);
1617         save_flags(flags); cli();
1618         if (!tty_hung_up_p(filp)) {
1619                 extra_count = 1;
1620                 state->count--;
1621         }
1622         restore_flags(flags);
1623         info->blocked_open++;
1624         while (1) {
1625                 save_flags(flags); cli();
1626                 if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
1627                     (tty->termios->c_cflag & CBAUD)) {
1628                         info->mctrl = TIOCM_DTR | TIOCM_RTS;
1629                         info->port->set_mctrl(info->port, info->mctrl);
1630                 }
1631                 restore_flags(flags);
1632                 set_current_state(TASK_INTERRUPTIBLE);
1633                 if (tty_hung_up_p(filp) ||
1634                     !(info->flags & ASYNC_INITIALIZED)) {
1635                         if (info->flags & ASYNC_HUP_NOTIFY)
1636                                 retval = -EAGAIN;
1637                         else
1638                                 retval = -ERESTARTSYS;
1639                         break;
1640                 }
1641                 if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
1642                     !(info->flags & ASYNC_CLOSING) &&
1643                     (do_clocal || (UART_GET_FR(info->port) & AMBA_UARTFR_DCD)))
1644                         break;
1645                 if (signal_pending(current)) {
1646                         retval = -ERESTARTSYS;
1647                         break;
1648                 }
1649                 schedule();
1650         }
1651         set_current_state(TASK_RUNNING);
1652         remove_wait_queue(&info->open_wait, &wait);
1653         if (extra_count)
1654                 state->count++;
1655         info->blocked_open--;
1656         if (retval)
1657                 return retval;
1658         info->flags |= ASYNC_NORMAL_ACTIVE;
1659         return 0;
1660 }
1661 
1662 static struct amba_info *ambauart_get(int line)
1663 {
1664         struct amba_info *info;
1665         struct amba_state *state = amba_state + line;
1666 
1667         state->count++;
1668         if (state->info)
1669                 return state->info;
1670         info = kmalloc(sizeof(struct amba_info), GFP_KERNEL);
1671         if (info) {
1672                 memset(info, 0, sizeof(struct amba_info));
1673                 init_waitqueue_head(&info->open_wait);
1674                 init_waitqueue_head(&info->close_wait);
1675                 init_waitqueue_head(&info->delta_msr_wait);
1676                 info->flags = state->flags;
1677                 info->state = state;
1678                 info->port  = amba_ports + line;
1679                 tasklet_init(&info->tlet, ambauart_tasklet_action,
1680                              (unsigned long)info);
1681         }
1682         if (state->info) {
1683                 kfree(info);
1684                 return state->info;
1685         }
1686         state->info = info;
1687         return info;
1688 }
1689 
1690 static int ambauart_open(struct tty_struct *tty, struct file *filp)
1691 {
1692         struct amba_info *info;
1693         int retval, line = MINOR(tty->device) - tty->driver.minor_start;
1694 
1695 #if DEBUG
1696         printk("ambauart_open(%d) called\n", line);
1697 #endif
1698 
1699         // is this a line that we've got?
1700         MOD_INC_USE_COUNT;
1701         if (line >= SERIAL_AMBA_NR) {
1702                 MOD_DEC_USE_COUNT;
1703                 return -ENODEV;
1704         }
1705 
1706         info = ambauart_get(line);
1707         if (!info)
1708                 return -ENOMEM;
1709 
1710         tty->driver_data = info;
1711         info->tty = tty;
1712         info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
1713 
1714         /*
1715          * Make sure we have the temporary buffer allocated
1716          */
1717         if (!tmp_buf) {
1718                 unsigned long page = get_zeroed_page(GFP_KERNEL);
1719                 if (tmp_buf)
1720                         free_page(page);
1721                 else if (!page) {
1722                         MOD_DEC_USE_COUNT;
1723                         return -ENOMEM;
1724                 }
1725                 tmp_buf = (u_char *)page;
1726         }
1727 
1728         /*
1729          * If the port is in the middle of closing, bail out now.
1730          */
1731         if (tty_hung_up_p(filp) ||
1732             (info->flags & ASYNC_CLOSING)) {
1733                 if (info->flags & ASYNC_CLOSING)
1734                         interruptible_sleep_on(&info->close_wait);
1735                 MOD_DEC_USE_COUNT;
1736                 return -EAGAIN;
1737         }
1738 
1739         /*
1740          * Start up the serial port
1741          */
1742         retval = ambauart_startup(info);
1743         if (retval) {
1744                 MOD_DEC_USE_COUNT;
1745                 return retval;
1746         }
1747 
1748         retval = block_til_ready(tty, filp, info);
1749         if (retval) {
1750                 MOD_DEC_USE_COUNT;
1751                 return retval;
1752         }
1753 
1754         if ((info->state->count == 1) &&
1755             (info->flags & ASYNC_SPLIT_TERMIOS)) {
1756                 if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
1757                         *tty->termios = info->state->normal_termios;
1758                 else
1759                         *tty->termios = info->state->callout_termios;
1760         }
1761 #ifdef CONFIG_SERIAL_AMBA_CONSOLE
1762         if (ambauart_cons.cflag && ambauart_cons.index == line) {
1763                 tty->termios->c_cflag = ambauart_cons.cflag;
1764                 ambauart_cons.cflag = 0;
1765         }
1766 #endif
1767         ambauart_change_speed(info, NULL);
1768         info->session = current->session;
1769         info->pgrp = current->pgrp;
1770         return 0;
1771 }
1772 
1773 int __init ambauart_init(void)
1774 {
1775         int i;
1776 
1777         ambanormal_driver.magic = TTY_DRIVER_MAGIC;
1778         ambanormal_driver.driver_name = "serial_amba";
1779         ambanormal_driver.name = SERIAL_AMBA_NAME;
1780         ambanormal_driver.major = SERIAL_AMBA_MAJOR;
1781         ambanormal_driver.minor_start = SERIAL_AMBA_MINOR;
1782         ambanormal_driver.num = SERIAL_AMBA_NR;
1783         ambanormal_driver.type = TTY_DRIVER_TYPE_SERIAL;
1784         ambanormal_driver.subtype = SERIAL_TYPE_NORMAL;
1785         ambanormal_driver.init_termios = tty_std_termios;
1786         ambanormal_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
1787         ambanormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
1788         ambanormal_driver.refcount = &ambauart_refcount;
1789         ambanormal_driver.table = ambauart_table;
1790         ambanormal_driver.termios = ambauart_termios;
1791         ambanormal_driver.termios_locked = ambauart_termios_locked;
1792 
1793         ambanormal_driver.open = ambauart_open;
1794         ambanormal_driver.close = ambauart_close;
1795         ambanormal_driver.write = ambauart_write;
1796         ambanormal_driver.put_char = ambauart_put_char;
1797         ambanormal_driver.flush_chars = ambauart_flush_chars;
1798         ambanormal_driver.write_room = ambauart_write_room;
1799         ambanormal_driver.chars_in_buffer = ambauart_chars_in_buffer;
1800         ambanormal_driver.flush_buffer  = ambauart_flush_buffer;
1801         ambanormal_driver.ioctl = ambauart_ioctl;
1802         ambanormal_driver.throttle = ambauart_throttle;
1803         ambanormal_driver.unthrottle = ambauart_unthrottle;
1804         ambanormal_driver.send_xchar = ambauart_send_xchar;
1805         ambanormal_driver.set_termios = ambauart_set_termios;
1806         ambanormal_driver.stop = ambauart_stop;
1807         ambanormal_driver.start = ambauart_start;
1808         ambanormal_driver.hangup = ambauart_hangup;
1809         ambanormal_driver.break_ctl = ambauart_break_ctl;
1810         ambanormal_driver.wait_until_sent = ambauart_wait_until_sent;
1811         ambanormal_driver.read_proc = NULL;
1812 
1813         /*
1814          * The callout device is just like the normal device except for
1815          * the major number and the subtype code.
1816          */
1817         ambacallout_driver = ambanormal_driver;
1818         ambacallout_driver.name = CALLOUT_AMBA_NAME;
1819         ambacallout_driver.major = CALLOUT_AMBA_MAJOR;
1820         ambacallout_driver.subtype = SERIAL_TYPE_CALLOUT;
1821         ambacallout_driver.read_proc = NULL;
1822         ambacallout_driver.proc_entry = NULL;
1823 
1824         if (tty_register_driver(&ambanormal_driver))
1825                 panic("Couldn't register AMBA serial driver\n");
1826         if (tty_register_driver(&ambacallout_driver))
1827                 panic("Couldn't register AMBA callout driver\n");
1828 
1829         for (i = 0; i < SERIAL_AMBA_NR; i++) {
1830                 struct amba_state *state = amba_state + i;
1831                 state->line             = i;
1832                 state->close_delay      = 5 * HZ / 10;
1833                 state->closing_wait     = 30 * HZ;
1834                 state->callout_termios  = ambacallout_driver.init_termios;
1835                 state->normal_termios   = ambanormal_driver.init_termios;
1836         }
1837 
1838         return 0;
1839 }
1840 
1841 __initcall(ambauart_init);
1842 
1843 #ifdef CONFIG_SERIAL_AMBA_CONSOLE
1844 /************** console driver *****************/
1845 
1846 /*
1847  * This code is currently never used; console->read is never called.
1848  * Therefore, although we have an implementation, we don't use it.
1849  * FIXME: the "const char *s" should be fixed to "char *s" some day.
1850  * (when the definition in include/linux/console.h is also fixed)
1851  */
1852 #ifdef used_and_not_const_char_pointer
1853 static int ambauart_console_read(struct console *co, const char *s, u_int count)
1854 {
1855         struct amba_port *port = &amba_ports[co->index];
1856         unsigned int status;
1857         char *w;
1858         int c;
1859 #if DEBUG
1860         printk("ambauart_console_read() called\n");
1861 #endif
1862 
1863         c = 0;
1864         w = s;
1865         while (c < count) {
1866                 status = UART_GET_FR(port);
1867                 if (UART_RX_DATA(status)) {
1868                         *w++ = UART_GET_CHAR(port);
1869                         c++;
1870                 } else {
1871                         // nothing more to get, return
1872                         return c;
1873                 }
1874         }
1875         // return the count
1876         return c;
1877 }
1878 #endif
1879 
1880 /*
1881  *      Print a string to the serial port trying not to disturb
1882  *      any possible real use of the port...
1883  *
1884  *      The console_lock must be held when we get here.
1885  */
1886 static void ambauart_console_write(struct console *co, const char *s, u_int count)
1887 {
1888         struct amba_port *port = &amba_ports[co->index];
1889         unsigned int status, old_cr;
1890         int i;
1891 
1892         /*
1893          *      First save the CR then disable the interrupts
1894          */
1895         old_cr = UART_GET_CR(port);
1896         UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
1897 
1898         /*
1899          *      Now, do each character
1900          */
1901         for (i = 0; i < count; i++) {
1902                 do {
1903                         status = UART_GET_FR(port);
1904                 } while (!UART_TX_READY(status));
1905                 UART_PUT_CHAR(port, s[i]);
1906                 if (s[i] == '\n') {
1907                         do {
1908                                 status = UART_GET_FR(port);
1909                         } while (!UART_TX_READY(status));
1910                         UART_PUT_CHAR(port, '\r');
1911                 }
1912         }
1913 
1914         /*
1915          *      Finally, wait for transmitter to become empty
1916          *      and restore the TCR
1917          */
1918         do {
1919                 status = UART_GET_FR(port);
1920         } while (status & AMBA_UARTFR_BUSY);
1921         UART_PUT_CR(port, old_cr);
1922 }
1923 
1924 /*
1925  *      Receive character from the serial port
1926  */
1927 static int ambauart_console_wait_key(struct console *co)
1928 {
1929         struct amba_port *port = &amba_ports[co->index];
1930         unsigned int status;
1931         int c;
1932 
1933         do {
1934                 status = UART_GET_FR(port);
1935         } while (!UART_RX_DATA(status));
1936         c = UART_GET_CHAR(port);
1937         return c;
1938 }
1939 
1940 static kdev_t ambauart_console_device(struct console *c)
1941 {
1942         return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
1943 }
1944 
1945 static int __init ambauart_console_setup(struct console *co, char *options)
1946 {
1947         struct amba_port *port;
1948         int baud = 38400;
1949         int bits = 8;
1950         int parity = 'n';
1951         u_int cflag = CREAD | HUPCL | CLOCAL;
1952         u_int lcr_h, quot;
1953 
1954         if (co->index >= SERIAL_AMBA_NR)
1955                 co->index = 0;
1956 
1957         port = &amba_ports[co->index];
1958 
1959         if (options) {
1960                 char *s = options;
1961                 baud = simple_strtoul(s, NULL, 10);
1962                 while (*s >= '' && *s <= '9')
1963                         s++;
1964                 if (*s) parity = *s++;
1965                 if (*s) bits = *s - '';
1966         }
1967 
1968         /*
1969          *    Now construct a cflag setting.
1970          */
1971         switch (baud) {
1972         case 1200:      cflag |= B1200;                 break;
1973         case 2400:      cflag |= B2400;                 break;
1974         case 4800:      cflag |= B4800;                 break;
1975         default:        cflag |= B9600;   baud = 9600;  break;
1976         case 19200:     cflag |= B19200;                break;
1977         case 38400:     cflag |= B38400;                break;
1978         case 57600:     cflag |= B57600;                break;
1979         case 115200:    cflag |= B115200;               break;
1980         }
1981         switch (bits) {
1982         case 7:   cflag |= CS7; lcr_h = AMBA_UARTLCR_H_WLEN_7;  break;
1983         default:  cflag |= CS8; lcr_h = AMBA_UARTLCR_H_WLEN_8;  break;
1984         }
1985         switch (parity) {
1986         case 'o':
1987         case 'O': cflag |= PARODD; lcr_h |= AMBA_UARTLCR_H_PEN; break;
1988         case 'e':
1989         case 'E': cflag |= PARENB; lcr_h |= AMBA_UARTLCR_H_PEN |
1990                                             AMBA_UARTLCR_H_EPS; break;
1991         }
1992 
1993         co->cflag = cflag;
1994 
1995         if (port->fifosize > 1)
1996                 lcr_h |= AMBA_UARTLCR_H_FEN;
1997 
1998         quot = (port->uartclk / (16 * baud)) - 1;
1999 
2000         UART_PUT_LCRL(port, (quot & 0xff));
2001         UART_PUT_LCRM(port, (quot >> 8));
2002         UART_PUT_LCRH(port, lcr_h);
2003 
2004         /* we will enable the port as we need it */
2005         UART_PUT_CR(port, 0);
2006 
2007         return 0;
2008 }
2009 
2010 static struct console ambauart_cons =
2011 {
2012         name:           SERIAL_AMBA_NAME,
2013         write:          ambauart_console_write,
2014 #ifdef used_and_not_const_char_pointer
2015         read:           ambauart_console_read,
2016 #endif
2017         device:         ambauart_console_device,
2018         wait_key:       ambauart_console_wait_key,
2019         setup:          ambauart_console_setup,
2020         flags:          CON_PRINTBUFFER,
2021         index:          -1,
2022 };
2023 
2024 void __init ambauart_console_init(void)
2025 {
2026         register_console(&ambauart_cons);
2027 }
2028 
2029 #endif /* CONFIG_SERIAL_AMBA_CONSOLE */
2030 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.