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