strip the kernel version suffix from target directories, except for brcm-2.4 (the...
[openwrt.git] / target / linux / amazon / files / drivers / serial / amazon_asc.c
1 /*
2  *  Driver for AMAZONASC serial ports
3  *
4  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
5  *  Based on drivers/serial/serial_s3c2400.c
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * Copyright (C) 2004 Infineon IFAP DC COM CPE
22  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
23  * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
24  */
25
26 #include <linux/module.h>
27 #include <linux/errno.h>
28 #include <linux/signal.h>
29 #include <linux/sched.h>
30 #include <linux/interrupt.h>
31 #include <linux/tty.h>
32 #include <linux/tty_flip.h>
33 #include <linux/major.h>
34 #include <linux/string.h>
35 #include <linux/fcntl.h>
36 #include <linux/ptrace.h>
37 #include <linux/ioport.h>
38 #include <linux/mm.h>
39 #include <linux/slab.h>
40 #include <linux/init.h>
41 #include <linux/circ_buf.h>
42 #include <linux/serial.h>
43 #include <linux/serial_core.h>
44 #include <linux/console.h>
45 #include <linux/sysrq.h>
46 #include <linux/irq.h>
47
48 #include <asm/system.h>
49 #include <asm/io.h>
50 #include <asm/uaccess.h>
51 #include <asm/bitops.h>
52 #include <asm/amazon/amazon.h>
53 #include <asm/amazon/irq.h>
54 #include <asm/amazon/serial.h>
55
56 #define PORT_AMAZONASC  111
57
58 #include <linux/serial_core.h>
59
60 #define UART_NR         1
61
62 #define UART_DUMMY_UER_RX 1
63
64 #define SERIAL_AMAZONASC_MAJOR  TTY_MAJOR
65 #define CALLOUT_AMAZONASC_MAJOR TTYAUX_MAJOR
66 #define SERIAL_AMAZONASC_MINOR  64
67 #define SERIAL_AMAZONASC_NR     UART_NR
68
69 static void amazonasc_tx_chars(struct uart_port *port);
70 extern void prom_printf(const char * fmt, ...);
71 static struct uart_port amazonasc_ports[UART_NR];
72 static struct uart_driver amazonasc_reg;
73 static unsigned int uartclk = 0;
74 extern unsigned int amazon_get_fpi_hz(void);
75
76 static void amazonasc_stop_tx(struct uart_port *port)
77 {
78         /* fifo underrun shuts up after firing once */
79         return;
80 }
81
82 static void amazonasc_start_tx(struct uart_port *port)
83 {
84         unsigned long flags;
85
86         local_irq_save(flags);
87         amazonasc_tx_chars(port);
88         local_irq_restore(flags);
89
90         return;
91 }
92
93 static void amazonasc_stop_rx(struct uart_port *port)
94 {
95         /* clear the RX enable bit */
96         amazon_writel(ASCWHBCON_CLRREN, AMAZON_ASC_WHBCON);
97 }
98
99 static void amazonasc_enable_ms(struct uart_port *port)
100 {
101         /* no modem signals */
102         return;
103 }
104
105 static void
106 amazonasc_rx_chars(struct uart_port *port)
107 {
108         struct tty_struct *tty = port->info->tty;
109         unsigned int ch = 0, rsr = 0, fifocnt;
110
111         fifocnt = amazon_readl(AMAZON_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
112         while (fifocnt--)
113         {
114                 u8 flag = TTY_NORMAL;
115                 ch = amazon_readl(AMAZON_ASC_RBUF);
116                 rsr = (amazon_readl(AMAZON_ASC_CON) & ASCCON_ANY) | UART_DUMMY_UER_RX;
117                 tty_flip_buffer_push(tty);
118                 port->icount.rx++;
119
120                 /*
121                  * Note that the error handling code is
122                  * out of the main execution path
123                  */
124                 if (rsr & ASCCON_ANY) {
125                         if (rsr & ASCCON_PE) {
126                                 port->icount.parity++;
127                                 amazon_writel_masked(AMAZON_ASC_WHBCON, ASCWHBCON_CLRPE, ASCWHBCON_CLRPE);
128                         } else if (rsr & ASCCON_FE) {
129                                 port->icount.frame++;
130                                 amazon_writel_masked(AMAZON_ASC_WHBCON, ASCWHBCON_CLRFE, ASCWHBCON_CLRFE);
131                         }
132                         if (rsr & ASCCON_OE) {
133                                 port->icount.overrun++;
134                                 amazon_writel_masked(AMAZON_ASC_WHBCON, ASCWHBCON_CLROE, ASCWHBCON_CLROE);
135                         }
136
137                         rsr &= port->read_status_mask;
138
139                         if (rsr & ASCCON_PE)
140                                 flag = TTY_PARITY;
141                         else if (rsr & ASCCON_FE)
142                                 flag = TTY_FRAME;
143                 }
144
145                 if ((rsr & port->ignore_status_mask) == 0)
146                         tty_insert_flip_char(tty, ch, flag);
147
148                 if (rsr & ASCCON_OE)
149                         /*
150                          * Overrun is special, since it's reported
151                          * immediately, and doesn't affect the current
152                          * character
153                          */
154                         tty_insert_flip_char(tty, 0, TTY_OVERRUN);
155         }
156         if (ch != 0)
157                 tty_flip_buffer_push(tty);
158
159         return;
160 }
161
162
163 static void amazonasc_tx_chars(struct uart_port *port)
164 {
165         struct circ_buf *xmit = &port->info->xmit;
166
167         if (uart_tx_stopped(port)) {
168                 amazonasc_stop_tx(port);
169                 return;
170         }
171         
172         while (((amazon_readl(AMAZON_ASC_FSTAT) & ASCFSTAT_TXFFLMASK)
173                         >> ASCFSTAT_TXFFLOFF) != AMAZONASC_TXFIFO_FULL)
174         {
175                 if (port->x_char) {
176                         amazon_writel(port->x_char, AMAZON_ASC_TBUF);
177                         port->icount.tx++;
178                         port->x_char = 0;
179                         continue;
180                 }
181
182                 if (uart_circ_empty(xmit))
183                         break;
184
185                 amazon_writel(xmit->buf[xmit->tail], AMAZON_ASC_TBUF);
186                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
187                 port->icount.tx++;
188         }
189
190         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
191                 uart_write_wakeup(port);
192 }
193
194 static irqreturn_t amazonasc_tx_int(int irq, void *port)
195 {
196         amazon_writel(ASC_IRNCR_TIR, AMAZON_ASC_IRNCR1);
197         amazonasc_start_tx(port);
198
199         /* clear any pending interrupts */
200         amazon_writel_masked(AMAZON_ASC_WHBCON, 
201                         (ASCWHBCON_CLRPE | ASCWHBCON_CLRFE | ASCWHBCON_CLROE), 
202                         (ASCWHBCON_CLRPE | ASCWHBCON_CLRFE | ASCWHBCON_CLROE));
203
204         return IRQ_HANDLED;
205 }
206
207 static irqreturn_t amazonasc_er_int(int irq, void *port)
208 {
209         /* clear any pending interrupts */
210         amazon_writel_masked(AMAZON_ASC_WHBCON, 
211                         (ASCWHBCON_CLRPE | ASCWHBCON_CLRFE | ASCWHBCON_CLROE), 
212                         (ASCWHBCON_CLRPE | ASCWHBCON_CLRFE | ASCWHBCON_CLROE));
213         
214         return IRQ_HANDLED;
215 }
216
217 static irqreturn_t amazonasc_rx_int(int irq, void *port)
218 {
219         amazon_writel(ASC_IRNCR_RIR, AMAZON_ASC_IRNCR1);
220         amazonasc_rx_chars((struct uart_port *) port);
221         return IRQ_HANDLED;
222 }
223
224 static u_int amazonasc_tx_empty(struct uart_port *port)
225 {
226         int status;
227
228         /*
229          * FSTAT tells exactly how many bytes are in the FIFO.
230          * The question is whether we really need to wait for all
231          * 16 bytes to be transmitted before reporting that the
232          * transmitter is empty.
233          */
234         status = amazon_readl(AMAZON_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
235         return status ? 0 : TIOCSER_TEMT;
236 }
237
238 static u_int amazonasc_get_mctrl(struct uart_port *port)
239 {
240         /* no modem control signals - the readme says to pretend all are set */
241         return TIOCM_CTS|TIOCM_CAR|TIOCM_DSR;
242 }
243
244 static void amazonasc_set_mctrl(struct uart_port *port, u_int mctrl)
245 {
246         /* no modem control - just return */
247         return;
248 }
249
250 static void amazonasc_break_ctl(struct uart_port *port, int break_state)
251 {
252         /* no way to send a break */
253         return;
254 }
255
256 static int amazonasc_startup(struct uart_port *port)
257 {
258         unsigned int con = 0;
259         unsigned long flags;
260         int retval;
261
262         /* this assumes: CON.BRS = CON.FDE = 0 */
263         if (uartclk == 0)
264                 uartclk = amazon_get_fpi_hz();
265
266         amazonasc_ports[0].uartclk = uartclk;
267
268         local_irq_save(flags);
269
270         /* this setup was probably already done in u-boot */
271         /* ASC and GPIO Port 1 bits 3 and 4 share the same pins
272          * P1.3 (RX) in, Alternate 10
273          * P1.4 (TX) in, Alternate 10
274          */
275          amazon_writel_masked(AMAZON_GPIO_P1_DIR, 0x18, 0x10);  //P1.4 output, P1.3 input
276          amazon_writel_masked(AMAZON_GPIO_P1_ALTSEL0, 0x18, 0x18);              //ALTSETL0 11
277          amazon_writel_masked(AMAZON_GPIO_P1_ALTSEL1, 0x18, 0);         //ALTSETL1 00
278          amazon_writel_masked(AMAZON_GPIO_P1_OD, 0x18, 0x10);
279         
280         /* set up the CLC */
281         amazon_writel_masked(AMAZON_ASC_CLC, AMAZON_ASC_CLC_DISS, 0);
282         amazon_writel_masked(AMAZON_ASC_CLC, ASCCLC_RMCMASK, 1 << ASCCLC_RMCOFFSET);
283         
284         /* asynchronous mode */
285         con = ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_OEN | ASCCON_PEN;
286         
287         /* choose the line - there's only one */
288         amazon_writel(0, AMAZON_ASC_PISEL);
289         amazon_writel(((AMAZONASC_TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, 
290                 AMAZON_ASC_TXFCON);
291         amazon_writel(((AMAZONASC_RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, 
292                 AMAZON_ASC_RXFCON);
293         wmb();
294         
295         amazon_writel_masked(AMAZON_ASC_CON, con, con);
296
297         retval = request_irq(AMAZONASC_RIR, amazonasc_rx_int, 0, "asc_rx", port);
298         if (retval){
299                 printk("failed to request amazonasc_rx_int\n");
300                 return retval;
301         }
302         retval = request_irq(AMAZONASC_TIR, amazonasc_tx_int, 0, "asc_tx", port);
303         if (retval){
304                 printk("failed to request amazonasc_tx_int\n");
305                 goto err1;
306         }
307
308         retval = request_irq(AMAZONASC_EIR, amazonasc_er_int, 0, "asc_er", port);
309         if (retval){
310                 printk("failed to request amazonasc_er_int\n");
311                 goto err2;
312         }
313         
314         local_irq_restore(flags);
315         return 0;
316
317 err2:
318         free_irq(AMAZONASC_TIR, port);
319         
320 err1:
321         free_irq(AMAZONASC_RIR, port);
322         local_irq_restore(flags);
323         return retval;
324 }
325
326 static void amazonasc_shutdown(struct uart_port *port)
327 {
328         free_irq(AMAZONASC_RIR, port);
329         free_irq(AMAZONASC_TIR, port);
330         free_irq(AMAZONASC_EIR, port);
331         /*
332          * disable the baudrate generator to disable the ASC
333          */
334         amazon_writel(0, AMAZON_ASC_CON);
335
336         /* flush and then disable the fifos */
337         amazon_writel_masked(AMAZON_ASC_RXFCON, ASCRXFCON_RXFFLU, ASCRXFCON_RXFFLU);
338         amazon_writel_masked(AMAZON_ASC_RXFCON, ASCRXFCON_RXFEN, 0);
339         amazon_writel_masked(AMAZON_ASC_TXFCON, ASCTXFCON_TXFFLU, ASCTXFCON_TXFFLU);
340         amazon_writel_masked(AMAZON_ASC_TXFCON, ASCTXFCON_TXFEN, 0);
341 }
342
343 static void amazonasc_set_termios(struct uart_port *port, struct ktermios *new, struct ktermios *old)
344 {
345         unsigned int cflag;
346         unsigned int iflag;
347         unsigned int baud, quot;
348         unsigned int con = 0;
349         unsigned long flags;
350
351         cflag = new->c_cflag;
352         iflag = new->c_iflag;
353
354         /* byte size and parity */
355         switch (cflag & CSIZE) {
356         /* 7 bits are always with parity */
357         case CS7: con = ASCCON_M_7ASYNCPAR; break;
358         /* the ASC only suports 7 and 8 bits */
359         case CS5:
360         case CS6:
361         default:
362                 if (cflag & PARENB)
363                         con = ASCCON_M_8ASYNCPAR;
364                 else
365                         con = ASCCON_M_8ASYNC;
366                 break;
367         }
368         if (cflag & CSTOPB)
369                 con |= ASCCON_STP;
370         if (cflag & PARENB) {
371                 if (!(cflag & PARODD))
372                         con &= ~ASCCON_ODD;
373                 else
374                         con |= ASCCON_ODD;
375         }
376
377         port->read_status_mask = ASCCON_OE;
378         if (iflag & INPCK)
379                 port->read_status_mask |= ASCCON_FE | ASCCON_PE;
380         
381         port->ignore_status_mask = 0;
382         if (iflag & IGNPAR)
383                 port->ignore_status_mask |= ASCCON_FE | ASCCON_PE;
384         
385         if (iflag & IGNBRK) {
386                 /*
387                  * If we're ignoring parity and break indicators,
388                  * ignore overruns too (for real raw support).
389                  */
390                 if (iflag & IGNPAR)
391                         port->ignore_status_mask |= ASCCON_OE;
392         }
393
394         /*
395          * Ignore all characters if CREAD is not set.
396          */
397         if ((cflag & CREAD) == 0)
398                 port->ignore_status_mask |= UART_DUMMY_UER_RX;
399
400         /* set error signals  - framing, parity  and overrun */
401         con |= ASCCON_FEN;
402         con |= ASCCON_OEN;
403         con |= ASCCON_PEN;
404         /* enable the receiver */
405         con |= ASCCON_REN;
406
407         /* block the IRQs */
408         local_irq_save(flags);
409
410         /* set up CON */
411         amazon_writel(con, AMAZON_ASC_CON);
412
413         /* Set baud rate - take a divider of 2 into account */
414     baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
415         quot = uart_get_divisor(port, baud);
416         quot = quot/2 - 1;
417
418         /* the next 3 probably already happened when we set CON above */
419         /* disable the baudrate generator */
420         amazon_writel_masked(AMAZON_ASC_CON, ASCCON_R, 0);
421         /* make sure the fractional divider is off */
422         amazon_writel_masked(AMAZON_ASC_CON, ASCCON_FDE, 0);
423         /* set up to use divisor of 2 */
424         amazon_writel_masked(AMAZON_ASC_CON, ASCCON_BRS, 0);
425         /* now we can write the new baudrate into the register */
426         amazon_writel(quot, AMAZON_ASC_BTR);
427         /* turn the baudrate generator back on */
428         amazon_writel_masked(AMAZON_ASC_CON, ASCCON_R, ASCCON_R);
429
430         local_irq_restore(flags);
431 }
432
433 static const char *amazonasc_type(struct uart_port *port)
434 {
435         return port->type == PORT_AMAZONASC ? "AMAZONASC" : NULL;
436 }
437
438 /*
439  * Release the memory region(s) being used by 'port'
440  */
441 static void amazonasc_release_port(struct uart_port *port)
442 {
443         return;
444 }
445
446 /*
447  * Request the memory region(s) being used by 'port'
448  */
449 static int amazonasc_request_port(struct uart_port *port)
450 {
451         return 0;
452 }
453
454 /*
455  * Configure/autoconfigure the port.
456  */
457 static void amazonasc_config_port(struct uart_port *port, int flags)
458 {
459         if (flags & UART_CONFIG_TYPE) {
460                 port->type = PORT_AMAZONASC;
461                 amazonasc_request_port(port);
462         }
463 }
464
465 /*
466  * verify the new serial_struct (for TIOCSSERIAL).
467  */
468 static int amazonasc_verify_port(struct uart_port *port, struct serial_struct *ser)
469 {
470         int ret = 0;
471         if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMAZONASC)
472                 ret = -EINVAL;
473         if (ser->irq < 0 || ser->irq >= NR_IRQS)
474                 ret = -EINVAL;
475         if (ser->baud_base < 9600)
476                 ret = -EINVAL;
477         return ret;
478 }
479
480 static struct uart_ops amazonasc_pops = {
481         .tx_empty =             amazonasc_tx_empty,
482         .set_mctrl =    amazonasc_set_mctrl,
483         .get_mctrl =    amazonasc_get_mctrl,
484         .stop_tx =              amazonasc_stop_tx,
485         .start_tx =             amazonasc_start_tx,
486         .stop_rx =              amazonasc_stop_rx,
487         .enable_ms =    amazonasc_enable_ms,
488         .break_ctl =    amazonasc_break_ctl,
489         .startup =              amazonasc_startup,
490         .shutdown =             amazonasc_shutdown,
491         .set_termios =  amazonasc_set_termios,
492         .type =                 amazonasc_type,
493         .release_port = amazonasc_release_port,
494         .request_port = amazonasc_request_port,
495         .config_port =  amazonasc_config_port,
496         .verify_port =  amazonasc_verify_port,
497 };
498
499 static struct uart_port amazonasc_ports[UART_NR] = {
500         {
501                 membase:        (void *)AMAZON_ASC,
502                 mapbase:        AMAZON_ASC,
503                 iotype:         SERIAL_IO_MEM,
504                 irq:            AMAZONASC_RIR, /* RIR */
505                 uartclk:        0, /* filled in dynamically */
506                 fifosize:       16,
507                 unused:         { AMAZONASC_TIR, AMAZONASC_EIR}, /* xmit/error/xmit-buffer-empty IRQ */
508                 type:           PORT_AMAZONASC,
509                 ops:            &amazonasc_pops,
510                 flags:          ASYNC_BOOT_AUTOCONF,
511         },
512 };
513
514 static void amazonasc_console_write(struct console *co, const char *s, u_int count)
515 {
516         int i, fifocnt;
517         unsigned long flags;
518         local_irq_save(flags);
519         for (i = 0; i < count;)
520         {
521                 /* wait until the FIFO is not full */
522                 do
523                 {
524                         fifocnt = (amazon_readl(AMAZON_ASC_FSTAT) & ASCFSTAT_TXFFLMASK)
525                                         >> ASCFSTAT_TXFFLOFF;
526                 } while (fifocnt == AMAZONASC_TXFIFO_FULL);
527                 if (s[i] == '\0')
528                 {
529                         break;
530                 }
531                 if (s[i] == '\n')
532                 {
533                         amazon_writel('\r', AMAZON_ASC_TBUF);
534                         do
535                         {
536                                 fifocnt = (amazon_readl(AMAZON_ASC_FSTAT) &
537                                 ASCFSTAT_TXFFLMASK) >> ASCFSTAT_TXFFLOFF;
538                         } while (fifocnt == AMAZONASC_TXFIFO_FULL);
539                 }
540                 amazon_writel(s[i], AMAZON_ASC_TBUF);
541                 i++;
542         } 
543
544         local_irq_restore(flags);
545 }
546
547 static void __init
548 amazonasc_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
549 {
550         u_int lcr_h;
551
552         lcr_h = amazon_readl(AMAZON_ASC_CON);
553         /* do this only if the ASC is turned on */
554         if (lcr_h & ASCCON_R) {
555                 u_int quot, div, fdiv, frac;
556
557                 *parity = 'n';
558                 if ((lcr_h & ASCCON_MODEMASK) == ASCCON_M_7ASYNCPAR ||
559                             (lcr_h & ASCCON_MODEMASK) == ASCCON_M_8ASYNCPAR) {
560                         if (lcr_h & ASCCON_ODD)
561                                 *parity = 'o';
562                         else
563                                 *parity = 'e';
564                 }
565
566                 if ((lcr_h & ASCCON_MODEMASK) == ASCCON_M_7ASYNCPAR)
567                         *bits = 7;
568                 else
569                         *bits = 8;
570
571                 quot = amazon_readl(AMAZON_ASC_BTR) + 1;
572                 
573                 /* this gets hairy if the fractional divider is used */
574                 if (lcr_h & ASCCON_FDE)
575                 {
576                         div = 1;
577                         fdiv = amazon_readl(AMAZON_ASC_FDV);
578                         if (fdiv == 0)
579                                 fdiv = 512;
580                         frac = 512;
581                 }
582                 else
583                 {
584                         div = lcr_h & ASCCON_BRS ? 3 : 2;
585                         fdiv = frac = 1;
586                 }
587                 /*
588                  * This doesn't work exactly because we use integer
589                  * math to calculate baud which results in rounding
590                  * errors when we try to go from quot -> baud !!
591                  * Try to make this work for both the fractional divider
592                  * and the simple divider. Also try to avoid rounding
593                  * errors using integer math.
594                  */
595                 
596                 *baud = frac * (port->uartclk / (div * 512 * 16 * quot));
597                 if (*baud > 1100 && *baud < 2400)
598                         *baud = 1200;
599                 if (*baud > 2300 && *baud < 4800)
600                         *baud = 2400;
601                 if (*baud > 4700 && *baud < 9600)
602                         *baud = 4800;
603                 if (*baud > 9500 && *baud < 19200)
604                         *baud = 9600;
605                 if (*baud > 19000 && *baud < 38400)
606                         *baud = 19200;
607                 if (*baud > 38400 && *baud < 57600)
608                         *baud = 38400;
609                 if (*baud > 57600 && *baud < 115200)
610                         *baud = 57600;
611                 if (*baud > 115200 && *baud < 230400)
612                         *baud = 115200;
613         }
614 }
615
616 static int __init amazonasc_console_setup(struct console *co, char *options)
617 {
618         struct uart_port *port;
619         int baud = 115200;
620         int bits = 8;
621         int parity = 'n';
622         int flow = 'n';
623
624         /* this assumes: CON.BRS = CON.FDE = 0 */
625         if (uartclk == 0)
626                 uartclk = amazon_get_fpi_hz();
627         co->index = 0;  
628         port = &amazonasc_ports[0];
629         amazonasc_ports[0].uartclk = uartclk;
630         amazonasc_ports[0].type = PORT_AMAZONASC;
631
632         if (options){
633                 uart_parse_options(options, &baud, &parity, &bits, &flow);
634         }
635
636         return uart_set_options(port, co, baud, parity, bits, flow);
637 }
638
639 static struct uart_driver amazonasc_reg;
640 static struct console amazonasc_console = {
641         name:           "ttyS",
642         write:          amazonasc_console_write,
643         device:         uart_console_device,
644         setup:          amazonasc_console_setup,
645         flags:          CON_PRINTBUFFER,
646         index:          -1,
647         data:           &amazonasc_reg,
648 };
649
650 static int __init amazonasc_console_init(void)
651 {
652         register_console(&amazonasc_console);
653         return 0;
654 }
655 console_initcall(amazonasc_console_init);
656
657 static struct uart_driver amazonasc_reg = {
658         .owner =                        THIS_MODULE,
659         .driver_name =          "serial",
660         .dev_name =                     "ttyS",
661         .major =                        TTY_MAJOR,
662         .minor =                        64,
663         .nr =                           UART_NR,
664         .cons =                         &amazonasc_console,
665 };
666
667 static int __init amazonasc_init(void)
668 {
669         unsigned char res;
670         uart_register_driver(&amazonasc_reg);
671         res = uart_add_one_port(&amazonasc_reg, &amazonasc_ports[0]);
672         return res;
673 }
674
675 static void __exit amazonasc_exit(void)
676 {
677         uart_unregister_driver(&amazonasc_reg);
678 }
679
680 module_init(amazonasc_init);
681 module_exit(amazonasc_exit);
682
683 MODULE_AUTHOR("Gary Jennejohn, Felix Fietkau, John Crispin");
684 MODULE_DESCRIPTION("MIPS AMAZONASC serial port driver");
685 MODULE_LICENSE("GPL");