vserver 1.9.3
[linux-2.6.git] / drivers / char / serial_tx3912.c
1 /*
2  *  drivers/char/serial_tx3912.c
3  *
4  *  Copyright (C) 1999 Harald Koerfgen
5  *  Copyright (C) 2000 Jim Pick <jim@jimpick.com>
6  *  Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *  
12  *  Serial driver for TMPR3912/05 and PR31700 processors
13  */
14 #include <linux/init.h>
15 #include <linux/config.h>
16 #include <linux/tty.h>
17 #include <linux/major.h>
18 #include <linux/ptrace.h>
19 #include <linux/console.h>
20 #include <linux/fs.h>
21 #include <linux/mm.h>
22 #include <linux/slab.h>
23 #include <linux/module.h>
24 #include <linux/delay.h>
25 #include <linux/pm.h>
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28 #include <asm/delay.h>
29 #include <asm/wbflush.h>
30 #include <asm/tx3912.h>
31 #include "serial_tx3912.h"
32
33 /*
34  * Forward declarations for serial routines
35  */
36 static void rs_disable_tx_interrupts (void * ptr);
37 static void rs_enable_tx_interrupts (void * ptr); 
38 static void rs_disable_rx_interrupts (void * ptr); 
39 static void rs_enable_rx_interrupts (void * ptr); 
40 static int rs_get_CD (void * ptr); 
41 static void rs_shutdown_port (void * ptr); 
42 static int rs_set_real_termios (void *ptr);
43 static int rs_chars_in_buffer (void * ptr); 
44
45 /*
46  * Used by generic serial driver to access hardware
47  */
48 static struct real_driver rs_real_driver = { 
49         .disable_tx_interrupts = rs_disable_tx_interrupts, 
50         .enable_tx_interrupts  = rs_enable_tx_interrupts, 
51         .disable_rx_interrupts = rs_disable_rx_interrupts, 
52         .enable_rx_interrupts  = rs_enable_rx_interrupts, 
53         .get_CD                = rs_get_CD, 
54         .shutdown_port         = rs_shutdown_port,  
55         .set_real_termios      = rs_set_real_termios,  
56         .chars_in_buffer       = rs_chars_in_buffer, 
57 }; 
58
59 /*
60  * Structures and such for TTY sessions and usage counts
61  */
62 static struct tty_driver *rs_driver;
63 struct rs_port *rs_ports;
64 int rs_initialized = 0;
65
66 /*
67  * ----------------------------------------------------------------------
68  *
69  * Here starts the interrupt handling routines.  All of the following
70  * subroutines are declared as inline and are folded into
71  * rs_interrupt().  They were separated out for readability's sake.
72  *
73  * Note: rs_interrupt() is a "fast" interrupt, which means that it
74  * runs with interrupts turned off.  People who may want to modify
75  * rs_interrupt() should try to keep the interrupt handler as fast as
76  * possible.  After you are done making modifications, it is not a bad
77  * idea to do:
78  * 
79  * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
80  *
81  * and look at the resulting assemble code in serial.s.
82  *
83  *                              - Ted Ts'o (tytso@mit.edu), 7-Mar-93
84  * -----------------------------------------------------------------------
85  */
86 static inline void receive_char_pio(struct rs_port *port)
87 {
88         struct tty_struct *tty = port->gs.tty;
89         unsigned char ch;
90         int counter = 2048;
91
92         /* While there are characters, get them ... */
93         while (counter>0) {
94                 if (!(inl(port->base + TX3912_UART_CTRL1) & UART_RX_HOLD_FULL))
95                         break;
96                 ch = inb(port->base + TX3912_UART_DATA);
97                 if (tty->flip.count < TTY_FLIPBUF_SIZE) {
98                         *tty->flip.char_buf_ptr++ = ch;
99                         *tty->flip.flag_buf_ptr++ = 0;
100                         tty->flip.count++;
101                 }
102                 udelay(1); /* Allow things to happen - it take a while */
103                 counter--;
104         }
105         if (!counter)
106                 printk( "Ugh, looped in receive_char_pio!\n" );
107
108         tty_flip_buffer_push(tty);
109
110 #if 0
111         /* Now handle error conditions */
112         if (*status & (INTTYPE(UART_RXOVERRUN_INT) |
113                         INTTYPE(UART_FRAMEERR_INT) |
114                         INTTYPE(UART_PARITYERR_INT) |
115                         INTTYPE(UART_BREAK_INT))) {
116
117                 /*
118                  * Now check to see if character should be
119                  * ignored, and mask off conditions which
120                  * should be ignored.
121                  */
122                 if (*status & port->ignore_status_mask) {
123                         goto ignore_char;
124                 }
125                 *status &= port->read_status_mask;
126                 
127                 if (*status & INTTYPE(UART_BREAK_INT)) {
128                         rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "handling break....");
129                         *tty->flip.flag_buf_ptr = TTY_BREAK;
130                 }
131                 else if (*status & INTTYPE(UART_PARITYERR_INT)) {
132                         *tty->flip.flag_buf_ptr = TTY_PARITY;
133                 }
134                 else if (*status & INTTYPE(UART_FRAMEERR_INT)) {
135                         *tty->flip.flag_buf_ptr = TTY_FRAME;
136                 }
137                 if (*status & INTTYPE(UART_RXOVERRUN_INT)) {
138                         /*
139                          * Overrun is special, since it's
140                          * reported immediately, and doesn't
141                          * affect the current character
142                          */
143                         if (tty->flip.count < TTY_FLIPBUF_SIZE) {
144                                 tty->flip.count++;
145                                 tty->flip.flag_buf_ptr++;
146                                 tty->flip.char_buf_ptr++;
147                                 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
148                         }
149                 }
150         }
151
152         tty->flip.flag_buf_ptr++;
153         tty->flip.char_buf_ptr++;
154         tty->flip.count++;
155
156 ignore_char:
157         tty_flip_buffer_push(tty);
158 #endif
159 }
160
161 static inline void transmit_char_pio(struct rs_port *port)
162 {
163         /* While I'm able to transmit ... */
164         for (;;) {
165                 if (!(inl(port->base + TX3912_UART_CTRL1) & UART_TX_EMPTY))
166                         break;
167                 else if (port->x_char) {
168                         outb(port->x_char, port->base + TX3912_UART_DATA);
169                         port->icount.tx++;
170                         port->x_char = 0;
171                 }
172                 else if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped ||
173                     port->gs.tty->hw_stopped) {
174                         break;
175                 }
176                 else {
177                         outb(port->gs.xmit_buf[port->gs.xmit_tail++],
178                                 port->base + TX3912_UART_DATA);
179                         port->icount.tx++;
180                         port->gs.xmit_tail &= SERIAL_XMIT_SIZE-1;
181                         if (--port->gs.xmit_cnt <= 0) {
182                                 break;
183                         }
184                 }
185                 udelay(10); /* Allow things to happen - it take a while */
186         }
187
188         if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped ||
189              port->gs.tty->hw_stopped) {
190                 rs_disable_tx_interrupts(port);
191         }
192         
193         if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
194                 tty_wakeup(port->gs.tty);
195                 rs_dprintk (TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
196                             port->gs.wakeup_chars); 
197         }       
198 }
199
200
201
202 static inline void check_modem_status(struct rs_port *port)
203 {
204         /* We don't have a carrier detect line - but just respond
205            like we had one anyways so that open() becomes unblocked */
206         wake_up_interruptible(&port->gs.open_wait);
207 }
208
209 int count = 0;
210
211 /*
212  * This is the serial driver's interrupt routine (inlined, because
213  * there are two different versions of this, one for each serial port,
214  * differing only by the bits used in interrupt status 2 register)
215  */
216
217 static inline void rs_rx_interrupt(int irq, void *dev_id,
218                                   struct pt_regs * regs, int intshift)
219 {
220         struct rs_port * port;
221         unsigned long int2status;
222         unsigned long flags;
223         unsigned long ints;
224
225         save_and_cli(flags);
226
227         port = (struct rs_port *)dev_id;
228         rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "rs_interrupt (port %p, shift %d)...", port, intshift);
229
230         /* Get the interrrupts we have enabled */
231         int2status = IntStatus2 & IntEnable2;
232
233         /* Get interrupts in easy to use form */
234         ints = int2status >> intshift;
235
236         /* Clear any interrupts we might be about to handle */
237         IntClear2 = int2status & (
238                 (INTTYPE(UART_RXOVERRUN_INT) |
239                  INTTYPE(UART_FRAMEERR_INT) |
240                  INTTYPE(UART_BREAK_INT) |
241                  INTTYPE(UART_PARITYERR_INT) |
242                  INTTYPE(UART_RX_INT)) << intshift);
243
244         if (!port || !port->gs.tty) {
245                 restore_flags(flags);
246                 return;
247         }
248
249         /* RX Receiver Holding Register Overrun */
250         if (ints & INTTYPE(UART_RXOVERRUN_INT)) {
251                 rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "overrun");
252                 port->icount.overrun++;
253         }
254
255         /* RX Frame Error */
256         if (ints & INTTYPE(UART_FRAMEERR_INT)) {
257                 rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "frame error");
258                 port->icount.frame++;
259         }
260
261         /* Break signal received */
262         if (ints & INTTYPE(UART_BREAK_INT)) {
263                 rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "break");
264                 port->icount.brk++;
265         }
266
267         /* RX Parity Error */
268         if (ints & INTTYPE(UART_PARITYERR_INT)) {
269                 rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "parity error");
270                 port->icount.parity++;
271         }
272
273         /* Receive byte (non-DMA) */
274         if (ints & INTTYPE(UART_RX_INT)) {
275                 receive_char_pio(port);
276         }
277
278         restore_flags(flags);
279
280         rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "end.\n");
281 }
282
283 static inline void rs_tx_interrupt(int irq, void *dev_id,
284                                   struct pt_regs * regs, int intshift)
285 {
286         struct rs_port * port;
287         unsigned long int2status;
288         unsigned long flags;
289         unsigned long ints;
290
291         save_and_cli(flags);
292
293         port = (struct rs_port *)dev_id;
294         rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "rs_interrupt (port %p, shift %d)...", port, intshift);
295
296         /* Get the interrrupts we have enabled */
297         int2status = IntStatus2 & IntEnable2;
298
299         if (!port || !port->gs.tty) {
300                 restore_flags(flags);
301                 return;
302         }
303
304         /* Get interrupts in easy to use form */
305         ints = int2status >> intshift;
306
307         /* Clear any interrupts we might be about to handle */
308         IntClear2 = int2status & (
309                 (INTTYPE(UART_TX_INT) |
310                  INTTYPE(UART_EMPTY_INT) |
311                  INTTYPE(UART_TXOVERRUN_INT)) << intshift);
312
313         /* TX holding register empty, so transmit byte (non-DMA) */
314         if (ints & (INTTYPE(UART_TX_INT) | INTTYPE(UART_EMPTY_INT))) {
315                 transmit_char_pio(port);
316         }
317
318         /* TX Transmit Holding Register Overrun (shouldn't happen) */
319         if (ints & INTTYPE(UART_TXOVERRUN_INT)) {
320                 printk ( "rs: TX overrun\n");
321         }
322
323         /*
324         check_modem_status();
325         */
326
327         restore_flags(flags);
328
329         rs_dprintk (TX3912_UART_DEBUG_INTERRUPTS, "end.\n");
330 }
331
332 static void rs_rx_interrupt_uarta(int irq, void *dev_id,
333                                          struct pt_regs * regs)
334 {
335         rs_rx_interrupt(irq, dev_id, regs, UARTA_SHIFT);
336 }
337
338 static void rs_tx_interrupt_uarta(int irq, void *dev_id,
339                                          struct pt_regs * regs)
340 {
341         rs_tx_interrupt(irq, dev_id, regs, UARTA_SHIFT);
342 }
343
344 /*
345  ***********************************************************************
346  *                Here are the routines that actually                  *
347  *              interface with the generic_serial driver               *
348  ***********************************************************************
349  */
350 static void rs_disable_tx_interrupts (void * ptr) 
351 {
352         struct rs_port *port = ptr; 
353         unsigned long flags;
354
355         save_and_cli(flags);
356         port->gs.flags &= ~GS_TX_INTEN;
357
358         IntEnable2 &= ~((INTTYPE(UART_TX_INT) |
359                         INTTYPE(UART_EMPTY_INT) |
360                         INTTYPE(UART_TXOVERRUN_INT)) << port->intshift);
361
362         IntClear2 = (INTTYPE(UART_TX_INT) |
363                         INTTYPE(UART_EMPTY_INT) |
364                         INTTYPE(UART_TXOVERRUN_INT)) << port->intshift;
365
366         restore_flags(flags);
367 }
368
369 static void rs_enable_tx_interrupts (void * ptr) 
370 {
371         struct rs_port *port = ptr; 
372         unsigned long flags;
373
374         save_and_cli(flags);
375
376         IntClear2 = (INTTYPE(UART_TX_INT) |
377                         INTTYPE(UART_EMPTY_INT) |
378                         INTTYPE(UART_TXOVERRUN_INT)) << port->intshift;
379
380         IntEnable2 |= (INTTYPE(UART_TX_INT) |
381                         INTTYPE(UART_EMPTY_INT) |
382                         INTTYPE(UART_TXOVERRUN_INT)) << port->intshift;
383
384         /* Send a char to start TX interrupts happening */
385         transmit_char_pio(port);
386
387         restore_flags(flags);
388 }
389
390 static void rs_disable_rx_interrupts (void * ptr) 
391 {
392         struct rs_port *port = ptr;
393         unsigned long flags;
394
395         save_and_cli(flags);
396
397         IntEnable2 &= ~((INTTYPE(UART_RX_INT) |
398                          INTTYPE(UART_RXOVERRUN_INT) |
399                          INTTYPE(UART_FRAMEERR_INT) |
400                          INTTYPE(UART_BREAK_INT) |
401                          INTTYPE(UART_PARITYERR_INT)) << port->intshift);
402
403         IntClear2 = (INTTYPE(UART_RX_INT) |
404                          INTTYPE(UART_RXOVERRUN_INT) |
405                          INTTYPE(UART_FRAMEERR_INT) |
406                          INTTYPE(UART_BREAK_INT) |
407                          INTTYPE(UART_PARITYERR_INT)) << port->intshift;
408
409         restore_flags(flags);
410 }
411
412 static void rs_enable_rx_interrupts (void * ptr) 
413 {
414         struct rs_port *port = ptr;
415         unsigned long flags;
416
417         save_and_cli(flags);
418
419         IntEnable2 |= (INTTYPE(UART_RX_INT) |
420                          INTTYPE(UART_RXOVERRUN_INT) |
421                          INTTYPE(UART_FRAMEERR_INT) |
422                          INTTYPE(UART_BREAK_INT) |
423                          INTTYPE(UART_PARITYERR_INT)) << port->intshift;
424
425         /* Empty the input buffer - apparently this is *vital* */
426         while (inl(port->base + TX3912_UART_CTRL1) & UART_RX_HOLD_FULL) { 
427                 inb(port->base + TX3912_UART_DATA);
428         }
429
430         IntClear2 = (INTTYPE(UART_RX_INT) |
431                          INTTYPE(UART_RXOVERRUN_INT) |
432                          INTTYPE(UART_FRAMEERR_INT) |
433                          INTTYPE(UART_BREAK_INT) |
434                          INTTYPE(UART_PARITYERR_INT)) << port->intshift;
435
436         restore_flags(flags);
437 }
438
439
440 static int rs_get_CD (void * ptr) 
441 {
442         /* No Carried Detect in Hardware - just return true */
443         func_exit();
444         return (1);
445 }
446
447 static void rs_shutdown_port (void * ptr) 
448 {
449         struct rs_port *port = ptr; 
450
451         func_enter();
452
453         port->gs.flags &= ~GS_ACTIVE;
454
455         func_exit();
456 }
457
458 static int rs_set_real_termios (void *ptr)
459 {
460         struct rs_port *port = ptr;
461         int t;
462
463         switch (port->gs.baud) {
464                 /* Save some typing work... */
465 #define e(x) case x:t= TX3912_UART_CTRL2_B ## x ; break
466                 e(300);e(600);e(1200);e(2400);e(4800);e(9600);
467                 e(19200);e(38400);e(57600);e(76800);e(115200);e(230400);
468         case 0      :t = -1;
469                 break;
470         default:
471                 /* Can I return "invalid"? */
472                 t = TX3912_UART_CTRL2_B9600;
473                 printk (KERN_INFO "rs: unsupported baud rate: %d.\n", port->gs.baud);
474                 break;
475         }
476 #undef e
477         if (t >= 0) {
478                 /* Jim: Set Hardware Baud rate - there is some good
479                    code in drivers/char/serial.c */
480
481                 /* Program hardware for parity, data bits, stop bits (note: these are hardcoded to 8N1 */
482                 UartA_Ctrl1 &= 0xf000000f;
483                 UartA_Ctrl1 &= ~(UART_DIS_TXD | SER_SEVEN_BIT | SER_EVEN_PARITY | SER_TWO_STOP);
484
485 #define CFLAG port->gs.tty->termios->c_cflag
486                 if (C_PARENB(port->gs.tty)) {
487                         if (!C_PARODD(port->gs.tty))
488                                 UartA_Ctrl1 |= SER_EVEN_PARITY;
489                         else
490                                 UartA_Ctrl1 |= SER_ODD_PARITY;
491                 }
492                 if ((CFLAG & CSIZE)==CS6)
493                         printk(KERN_ERR "6 bits not supported\n");
494                 if ((CFLAG & CSIZE)==CS5)
495                         printk(KERN_ERR "5 bits not supported\n");
496                 if ((CFLAG & CSIZE)==CS7)
497                         UartA_Ctrl1 |= SER_SEVEN_BIT;
498                 if (C_CSTOPB(port->gs.tty))
499                         UartA_Ctrl1 |= SER_TWO_STOP;
500
501                 outl(t, port->base + TX3912_UART_CTRL2);
502                 outl(0, port->base + TX3912_UART_DMA_CTRL1);
503                 outl(0, port->base + TX3912_UART_DMA_CTRL2);
504                 UartA_Ctrl1 |= TX3912_UART_CTRL1_UARTON;
505
506         /* wait until UARTA is stable */
507         while (~UartA_Ctrl1 & TX3912_UART_CTRL1_UARTON);
508         }
509
510         func_exit ();
511         return 0;
512 }
513
514 static int rs_chars_in_buffer (void * ptr) 
515 {
516         struct rs_port *port = ptr;
517         int scratch;
518
519         scratch = inl(port->base + TX3912_UART_CTRL1);
520
521         return ((scratch & UART_TX_EMPTY) ? 0 : 1);
522 }
523
524 /* ********************************************************************** *
525  *                Here are the routines that actually                     *
526  *               interface with the rest of the system                    *
527  * ********************************************************************** */
528 static int rs_open  (struct tty_struct * tty, struct file * filp)
529 {
530         struct rs_port *port;
531         int retval, line;
532
533         func_enter();
534
535         if (!rs_initialized) {
536                 return -EIO;
537         }
538
539         line = tty->index;
540         rs_dprintk (TX3912_UART_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p)\n", 
541                     (int) current->pid, line, tty, current->tty);
542
543         if ((line < 0) || (line >= TX3912_UART_NPORTS))
544                 return -ENODEV;
545
546         /* Pre-initialized already */
547         port = & rs_ports[line];
548
549         rs_dprintk (TX3912_UART_DEBUG_OPEN, "port = %p\n", port);
550
551         tty->driver_data = port;
552         port->gs.tty = tty;
553         port->gs.count++;
554
555         rs_dprintk (TX3912_UART_DEBUG_OPEN, "starting port\n");
556
557         /*
558          * Start up serial port
559          */
560         retval = gs_init_port(&port->gs);
561         rs_dprintk (TX3912_UART_DEBUG_OPEN, "done gs_init\n");
562         if (retval) {
563                 port->gs.count--;
564                 return retval;
565         }
566
567         port->gs.flags |= GS_ACTIVE;
568
569         rs_dprintk (TX3912_UART_DEBUG_OPEN, "before inc_use_count (count=%d.\n", 
570                     port->gs.count);
571         rs_dprintk (TX3912_UART_DEBUG_OPEN, "after inc_use_count\n");
572
573         /* Jim: Initialize port hardware here */
574
575         /* Enable high-priority interrupts for UARTA */
576         IntEnable6 |= INT6_UARTARXINT; 
577         rs_enable_rx_interrupts(&rs_ports[0]); 
578
579         retval = gs_block_til_ready(&port->gs, filp);
580         rs_dprintk (TX3912_UART_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", 
581                     retval, port->gs.count);
582
583         if (retval) {
584                 port->gs.count--;
585                 return retval;
586         }
587         /* tty->low_latency = 1; */
588
589         func_exit();
590
591         /* Jim */
592 /*      cli(); */
593
594         return 0;
595
596 }
597
598
599 static int rs_ioctl (struct tty_struct * tty, struct file * filp, 
600                      unsigned int cmd, unsigned long arg)
601 {
602         int rc;
603         struct rs_port *port = tty->driver_data;
604         int ival;
605
606         rc = 0;
607         switch (cmd) {
608         case TIOCGSOFTCAR:
609                 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
610                               (unsigned int *) arg);
611                 break;
612         case TIOCSSOFTCAR:
613                 if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
614                         tty->termios->c_cflag =
615                                 (tty->termios->c_cflag & ~CLOCAL) |
616                                 (ival ? CLOCAL : 0);
617                 }
618                 break;
619         case TIOCGSERIAL:
620                 if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
621                                       sizeof(struct serial_struct))) == 0)
622                         rc = gs_getserial(&port->gs, (struct serial_struct *) arg);
623                 break;
624         case TIOCSSERIAL:
625                 if ((rc = verify_area(VERIFY_READ, (void *) arg,
626                                       sizeof(struct serial_struct))) == 0)
627                         rc = gs_setserial(&port->gs, (struct serial_struct *) arg);
628                 break;
629         default:
630                 rc = -ENOIOCTLCMD;
631                 break;
632         }
633
634         /* func_exit(); */
635         return rc;
636 }
637
638
639 /*
640  * This function is used to send a high-priority XON/XOFF character to
641  * the device
642  */
643 static void rs_send_xchar(struct tty_struct * tty, char ch)
644 {
645         struct rs_port *port = (struct rs_port *)tty->driver_data;
646         func_enter ();
647         
648         port->x_char = ch;
649         if (ch) {
650                 /* Make sure transmit interrupts are on */
651                 rs_enable_tx_interrupts(tty);
652         }
653
654         func_exit();
655 }
656
657
658 /*
659  * ------------------------------------------------------------
660  * rs_throttle()
661  * 
662  * This routine is called by the upper-layer tty layer to signal that
663  * incoming characters should be throttled.
664  * ------------------------------------------------------------
665  */
666 static void rs_throttle(struct tty_struct * tty)
667 {
668 #ifdef TX3912_UART_DEBUG_THROTTLE
669         char    buf[64];
670         
671         printk("throttle %s: %d....\n", tty_name(tty, buf),
672                tty->ldisc.chars_in_buffer(tty));
673 #endif
674
675         func_enter ();
676         
677         if (I_IXOFF(tty))
678                 rs_send_xchar(tty, STOP_CHAR(tty));
679
680         func_exit ();
681 }
682
683 static void rs_unthrottle(struct tty_struct * tty)
684 {
685         struct rs_port *port = (struct rs_port *)tty->driver_data;
686 #ifdef TX3912_UART_DEBUG_THROTTLE
687         char    buf[64];
688         
689         printk("unthrottle %s: %d....\n", tty_name(tty, buf),
690                tty->ldisc.chars_in_buffer(tty));
691 #endif
692
693         func_enter();
694         
695         if (I_IXOFF(tty)) {
696                 if (port->x_char)
697                         port->x_char = 0;
698                 else
699                         rs_send_xchar(tty, START_CHAR(tty));
700         }
701
702         func_exit();
703 }
704
705
706
707
708
709 /* ********************************************************************** *
710  *                    Here are the initialization routines.               *
711  * ********************************************************************** */
712
713 void * ckmalloc (int size)
714 {
715         void *p;
716
717         p = kmalloc(size, GFP_KERNEL);
718         if (p) 
719                 memset(p, 0, size);
720         return p;
721 }
722
723
724
725 static int rs_init_portstructs(void)
726 {
727         struct rs_port *port;
728         int i;
729
730         /* Debugging */
731         func_enter();
732
733         rs_ports          = ckmalloc(TX3912_UART_NPORTS * sizeof (struct rs_port));
734         if (!rs_ports)
735                 return -ENOMEM;
736
737         port = rs_ports;
738         for (i=0; i < TX3912_UART_NPORTS;i++) {
739                 rs_dprintk (TX3912_UART_DEBUG_INIT, "initing port %d\n", i);
740                 port->gs.magic = SERIAL_MAGIC;
741                 port->gs.close_delay = HZ/2;
742                 port->gs.closing_wait = 30 * HZ;
743                 port->gs.rd = &rs_real_driver;
744 #ifdef NEW_WRITE_LOCKING
745                 port->gs.port_write_sem = MUTEX;
746 #endif
747 #ifdef DECLARE_WAITQUEUE
748                 init_waitqueue_head(&port->gs.open_wait);
749                 init_waitqueue_head(&port->gs.close_wait);
750 #endif
751                 port->base = (i == 0) ? TX3912_UARTA_BASE : TX3912_UARTB_BASE;
752                 port->intshift = (i == 0) ? UARTA_SHIFT : UARTB_SHIFT;
753                 rs_dprintk (TX3912_UART_DEBUG_INIT, "base 0x%08lx intshift %d\n",
754                             port->base, port->intshift);
755                 port++;
756         }
757
758         func_exit();
759         return 0;
760 }
761
762 static struct tty_operations rs_ops = {
763         .open   = rs_open,
764         .close = gs_close,
765         .write = gs_write,
766         .put_char = gs_put_char, 
767         .flush_chars = gs_flush_chars,
768         .write_room = gs_write_room,
769         .chars_in_buffer = gs_chars_in_buffer,
770         .flush_buffer = gs_flush_buffer,
771         .ioctl = rs_ioctl,
772         .throttle = rs_throttle,
773         .unthrottle = rs_unthrottle,
774         .set_termios = gs_set_termios,
775         .stop = gs_stop,
776         .start = gs_start,
777         .hangup = gs_hangup,
778 };
779
780 static int rs_init_drivers(void)
781 {
782         int error;
783
784         func_enter();
785
786         rs_driver = alloc_tty_driver(TX3912_UART_NPORTS);
787         if (!rs_driver)
788                 return -ENOMEM;
789         rs_driver->owner = THIS_MODULE;
790         rs_driver->driver_name = "serial";
791         rs_driver->name = "ttyS";
792         rs_driver->major = TTY_MAJOR;
793         rs_driver->minor_start = 64;
794         rs_driver->type = TTY_DRIVER_TYPE_SERIAL;
795         rs_driver->subtype = SERIAL_TYPE_NORMAL;
796         rs_driver->init_termios = tty_std_termios;
797         rs_driver->init_termios.c_cflag =
798                 B115200 | CS8 | CREAD | HUPCL | CLOCAL;
799         tty_set_operations(rs_driver, &rs_ops);
800         if ((error = tty_register_driver(rs_driver))) {
801                 printk(KERN_ERR "Couldn't register serial driver, error = %d\n",
802                        error);
803                 put_tty_driver(rs_driver);
804                 return 1;
805         }
806         return 0;
807 }
808
809
810 static void __init tx3912_rs_init(void)
811 {
812         int rc;
813
814
815         func_enter();
816         rs_dprintk (TX3912_UART_DEBUG_INIT, "Initing serial module... (rs_debug=%d)\n", rs_debug);
817
818         rc = rs_init_portstructs ();
819         rs_init_drivers ();
820         if (request_irq(2, rs_tx_interrupt_uarta, SA_SHIRQ | SA_INTERRUPT,
821                         "serial", &rs_ports[0])) {
822                 printk(KERN_ERR "rs: Cannot allocate irq for UARTA.\n");
823                 rc = 0;
824         }
825         if (request_irq(3, rs_rx_interrupt_uarta, SA_SHIRQ | SA_INTERRUPT,
826                         "serial", &rs_ports[0])) {
827                 printk(KERN_ERR "rs: Cannot allocate irq for UARTA.\n");
828                 rc = 0;
829         }
830
831         IntEnable6 |= INT6_UARTARXINT; 
832         rs_enable_rx_interrupts(&rs_ports[0]); 
833
834 #ifndef CONFIG_SERIAL_TX3912_CONSOLE
835 {
836         unsigned int scratch = 0;
837
838         /* Setup master clock for UART */
839         scratch = inl(TX3912_CLK_CTRL_BASE);
840         scratch &= ~TX3912_CLK_CTRL_SIBMCLKDIV_MASK;
841         scratch |= ((0x2 << TX3912_CLK_CTRL_SIBMCLKDIV_SHIFT) &
842                                 TX3912_CLK_CTRL_SIBMCLKDIV_MASK)
843                         | TX3912_CLK_CTRL_SIBMCLKDIR
844                         | TX3912_CLK_CTRL_ENSIBMCLK
845                         | TX3912_CLK_CTRL_CSERSEL;
846         outl(scratch, TX3912_CLK_CTRL_BASE);
847
848         /* Configure UARTA clock */
849         scratch = inl(TX3912_CLK_CTRL_BASE);
850         scratch |= ((0x3 << TX3912_CLK_CTRL_CSERDIV_SHIFT) &
851                                 TX3912_CLK_CTRL_CSERDIV_MASK)
852                         | TX3912_CLK_CTRL_ENCSERCLK
853                         | TX3912_CLK_CTRL_ENUARTACLK;
854         outl(scratch, TX3912_CLK_CTRL_BASE);
855                 
856         /* Setup UARTA for 115200,8N1 */
857         outl(0, TX3912_UARTA_BASE + TX3912_UART_CTRL1);
858         outl(TX3912_UART_CTRL2_B115200, TX3912_UARTA_BASE + TX3912_UART_CTRL2);
859         outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL1);
860         outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL2);
861
862         /* Enable UARTA */
863         outl(TX3912_UART_CTRL1_ENUART, TX3912_UARTA_BASE + TX3912_UART_CTRL1);
864         while (~inl(TX3912_UARTA_BASE + TX3912_UART_CTRL1) &
865                 TX3912_UART_CTRL1_UARTON);
866 }
867 #endif
868
869         /* Note: I didn't do anything to enable the second UART */
870         if (rc >= 0) 
871                 rs_initialized++;
872
873         func_exit();
874 }
875 module_init(tx3912_rs_init);
876
877 /*
878  * Begin serial console routines
879  */
880 #ifdef CONFIG_SERIAL_TX3912_CONSOLE
881
882 void serial_outc(unsigned char c)
883 {
884         int i;
885         unsigned long int2;
886         #define BUSY_WAIT 10000
887
888         /*
889          * Turn UARTA interrupts off
890          */
891         int2 = IntEnable2;
892         IntEnable2 &=
893                 ~(INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY);
894
895         /*
896          * The UART_TX_EMPTY bit in UartA_Ctrl1 seems
897          * not to be very reliable :-(
898          *
899          * Wait for the Tx register to become empty
900          */
901         for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < BUSY_WAIT); i++);
902
903         IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY;
904         UartA_Data = c;
905         for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < BUSY_WAIT); i++);
906         IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY;
907
908         IntEnable2 = int2;
909 }
910
911 static void serial_console_write(struct console *co, const char *s,
912                 unsigned count)
913 {
914         unsigned int i;
915
916         for (i = 0; i < count; i++) {
917                 if (*s == '\n')
918                         serial_outc('\r');
919                 serial_outc(*s++);
920         }
921 }
922
923 static struct tty_driver *serial_console_device(struct console *c, int *index)
924 {
925         *index = c->index;
926         return rs_driver;
927 }
928
929 static __init int serial_console_setup(struct console *co, char *options)
930 {
931         unsigned int scratch = 0;
932
933         /* Setup master clock for UART */
934         scratch = inl(TX3912_CLK_CTRL_BASE);
935         scratch &= ~TX3912_CLK_CTRL_SIBMCLKDIV_MASK;
936         scratch |= ((0x2 << TX3912_CLK_CTRL_SIBMCLKDIV_SHIFT) &
937                                 TX3912_CLK_CTRL_SIBMCLKDIV_MASK)
938                         | TX3912_CLK_CTRL_SIBMCLKDIR
939                         | TX3912_CLK_CTRL_ENSIBMCLK
940                         | TX3912_CLK_CTRL_CSERSEL;
941         outl(scratch, TX3912_CLK_CTRL_BASE);
942
943         /* Configure UARTA clock */
944         scratch = inl(TX3912_CLK_CTRL_BASE);
945         scratch |= ((0x3 << TX3912_CLK_CTRL_CSERDIV_SHIFT) &
946                                 TX3912_CLK_CTRL_CSERDIV_MASK)
947                         | TX3912_CLK_CTRL_ENCSERCLK
948                         | TX3912_CLK_CTRL_ENUARTACLK;
949         outl(scratch, TX3912_CLK_CTRL_BASE);
950                 
951         /* Setup UARTA for 115200,8N1 */
952         outl(0, TX3912_UARTA_BASE + TX3912_UART_CTRL1);
953         outl(TX3912_UART_CTRL2_B115200, TX3912_UARTA_BASE + TX3912_UART_CTRL2);
954         outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL1);
955         outl(0, TX3912_UARTA_BASE + TX3912_UART_DMA_CTRL2);
956
957         /* Enable UARTA */
958         outl(TX3912_UART_CTRL1_ENUART, TX3912_UARTA_BASE + TX3912_UART_CTRL1);
959         while (~inl(TX3912_UARTA_BASE + TX3912_UART_CTRL1) &
960                 TX3912_UART_CTRL1_UARTON);
961
962         return 0;
963 }
964
965 static struct console sercons = {
966         .name     = "ttyS",
967         .write    = serial_console_write,
968         .device   = serial_console_device,
969         .setup    = serial_console_setup,
970         .flags    = CON_PRINTBUFFER,
971         .index    = -1
972 };
973
974 static int __init tx3912_console_init(void)
975 {
976         register_console(&sercons);
977         return 0;
978 }
979 console_initcall(tx3912_console_init);
980
981 #endif