2 * linux/drivers/char/amazon_asc.c
4 * Driver for AMAZONASC serial ports
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>
10 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
11 * Based on drivers/serial/serial_s3c2400.c
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.
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.
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
27 * $Id: amazon_asc.c,v 1.2 2005/04/01 02:40:48 pliu Exp $
29 * This is a generic driver for AMAZONASC-type serial ports.
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>
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>
54 #include <asm/system.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>
62 #define PORT_AMAZONASC 111
64 #if defined(CONFIG_SERIAL_AMAZONASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
68 #include <linux/serial_core.h>
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
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
;
83 static unsigned int uartclk
= 0;
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);}
92 static void amazonasc_tx_chars(struct uart_port
*port
);
94 /* fake flag to indicate CREAD was not set -> throw away all bytes */
95 #define UART_DUMMY_UER_RX 1
97 /* macro to set the bit corresponding to an interrupt number */
98 #define BIT_NO(irq) (1 << (irq - 64))
102 extern unsigned int amazon_get_fpi_hz(void);
103 static int tx_enabled
= 0;
105 static void amazonasc_stop_tx(struct uart_port
*port
)
107 /* fifo underrun shuts up after firing once */
111 static void amazonasc_start_tx(struct uart_port
*port
)
115 local_irq_save(flags
);
116 amazonasc_tx_chars(port
);
117 local_irq_restore(flags
);
122 static void amazonasc_stop_rx(struct uart_port
*port
)
124 /* clear the RX enable bit */
125 *AMAZON_ASC_WHBCON
= ASCWHBCON_CLRREN
;
128 static void amazonasc_enable_ms(struct uart_port
*port
)
130 /* no modem signals */
135 amazonasc_rx_chars(struct uart_port
*port
)
137 struct tty_struct
*tty
= port
->info
->tty
;
138 unsigned int ch
= 0, rsr
= 0, fifocnt
;
141 fifocnt
= *AMAZON_ASC_FSTAT
& ASCFSTAT_RXFFLMASK
;
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
);
151 * Note that the error handling code is
152 * out of the main execution path
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
);
162 if (rsr
& ASCCON_OE
) {
163 port
->icount
.overrun
++;
164 SET_BIT(AMAZON_ASC_WHBCON
, ASCWHBCON_CLROE
);
167 rsr
&= port
->read_status_mask
;
171 else if (rsr
& ASCCON_FE
)
175 if ((rsr
& port
->ignore_status_mask
) == 0)
176 tty_insert_flip_char(tty
, ch
, flag
);
180 * Overrun is special, since it's reported
181 * immediately, and doesn't affect the current
184 tty_insert_flip_char(tty
, 0, TTY_OVERRUN
);
187 tty_flip_buffer_push(tty
);
193 static void amazonasc_tx_chars(struct uart_port
*port
)
195 struct circ_buf
*xmit
= &port
->info
->xmit
;
197 if (uart_tx_stopped(port
)) {
198 amazonasc_stop_tx(port
);
202 while (((*AMAZON_ASC_FSTAT
& ASCFSTAT_TXFFLMASK
)
203 >> ASCFSTAT_TXFFLOFF
) != AMAZONASC_TXFIFO_FULL
)
206 *AMAZON_ASC_TBUF
= port
->x_char
;
212 if (uart_circ_empty(xmit
))
215 *AMAZON_ASC_TBUF
= xmit
->buf
[xmit
->tail
];
216 xmit
->tail
= (xmit
->tail
+ 1) & (UART_XMIT_SIZE
- 1);
220 if (uart_circ_chars_pending(xmit
) < WAKEUP_CHARS
)
221 uart_write_wakeup(port
);
224 static irqreturn_t
amazonasc_tx_int(int irq
, void *port
)
226 *(AMAZON_ASC_IRNCR1
) = ASC_IRNCR_TIR
;
227 amazonasc_start_tx(port
);
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
);
237 static irqreturn_t
amazonasc_er_int(int irq
, void *port
)
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
);
246 static irqreturn_t
amazonasc_rx_int(int irq
, void *port
)
248 *(AMAZON_ASC_IRNCR1
) = ASC_IRNCR_RIR
;
249 amazonasc_rx_chars((struct uart_port
*) port
);
253 static u_int
amazonasc_tx_empty(struct uart_port
*port
)
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.
263 status
= *AMAZON_ASC_FSTAT
& ASCFSTAT_TXFFLMASK
;
264 return status
? 0 : TIOCSER_TEMT
;
267 static u_int
amazonasc_get_mctrl(struct uart_port
*port
)
269 /* no modem control signals - the readme says to pretend all are set */
270 return TIOCM_CTS
|TIOCM_CAR
|TIOCM_DSR
;
273 static void amazonasc_set_mctrl(struct uart_port
*port
, u_int mctrl
)
275 /* no modem control - just return */
279 static void amazonasc_break_ctl(struct uart_port
*port
, int break_state
)
281 /* no way to send a break */
285 static int amazonasc_startup(struct uart_port
*port
)
287 unsigned int con
= 0;
291 /* this assumes: CON.BRS = CON.FDE = 0 */
293 uartclk
= amazon_get_fpi_hz();
295 amazonasc_ports
[0].uartclk
= uartclk
;
298 local_irq_save(flags
);
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
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);
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 */
319 /* choose the line - there's only one */
320 *AMAZON_ASC_PISEL
= 0;
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
);
326 /* TXFIFO's fill level */
327 SET_BITFIELD(AMAZON_ASC_TXFCON
, ASCTXFCON_TXFITLMASK
,
328 ASCTXFCON_TXFITLOFF
, AMAZONASC_TXFIFO_FL
);
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
);
335 SET_BIT(AMAZON_ASC_RXFCON
, ASCRXFCON_RXFEN
);
336 /* now really set CON */
338 SET_BIT(AMAZON_ASC_CON
,con
);
343 retval
= request_irq(AMAZONASC_RIR
, amazonasc_rx_int
, 0, "asc_rx", port
);
345 printk("-------req1 failed\n");
348 retval
= request_irq(AMAZONASC_TIR
, amazonasc_tx_int
, 0, "asc_tx", port
);
350 printk("----------req2 failed\n");
354 retval
= request_irq(AMAZONASC_EIR
, amazonasc_er_int
, 0, "asc_er", port
);
356 printk("---------req3 failed\n");
359 /* unblock the IRQs */
360 local_irq_restore(flags
);
364 free_irq(AMAZONASC_TIR
, port
);
367 free_irq(AMAZONASC_RIR
, port
);
368 local_irq_restore(flags
);
372 static void amazonasc_shutdown(struct uart_port
*port
)
375 * Free the interrupts
377 free_irq(AMAZONASC_RIR
, port
);
378 free_irq(AMAZONASC_TIR
, port
);
379 free_irq(AMAZONASC_EIR
, port
);
381 * disable the baudrate generator to disable the ASC
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
);
392 static void amazonasc_set_termios(struct uart_port
*port
, struct ktermios
*new, struct ktermios
*old
)
396 unsigned int baud
, quot
;
397 unsigned int con
= 0;
400 cflag
= new->c_cflag
;
401 iflag
= new->c_iflag
;
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 */
412 con
= ASCCON_M_8ASYNCPAR
;
414 con
= ASCCON_M_8ASYNC
;
419 if (cflag
& PARENB
) {
420 if (!(cflag
& PARODD
))
426 port
->read_status_mask
= ASCCON_OE
;
428 port
->read_status_mask
|= ASCCON_FE
| ASCCON_PE
;
429 /* the ASC can't really detect or generate a BREAK */
431 if (iflag
& (BRKINT
| PARMRK
))
432 port
->read_status_mask
|= UERSTAT_BREAK
;
435 * Characters to ignore
437 port
->ignore_status_mask
= 0;
439 port
->ignore_status_mask
|= ASCCON_FE
| ASCCON_PE
;
441 /* always ignore breaks - the ASC can't handle them XXXX */
442 port
->ignore_status_mask
|= UERSTAT_BREAK
;
444 if (iflag
& IGNBRK
) {
445 /*port->ignore_status_mask |= UERSTAT_BREAK;*/
447 * If we're ignoring parity and break indicators,
448 * ignore overruns too (for real raw support).
451 port
->ignore_status_mask
|= ASCCON_OE
;
455 * Ignore all characters if CREAD is not set.
457 if ((cflag
& CREAD
) == 0)
458 port
->ignore_status_mask
|= UART_DUMMY_UER_RX
;
460 /* set error signals - framing, parity and overrun */
464 /* enable the receiver */
468 local_irq_save(flags
);
471 *AMAZON_ASC_CON
= con
;
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
);
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
);
490 /* unblock the IRQs */
491 local_irq_restore(flags
);
494 static const char *amazonasc_type(struct uart_port
*port
)
496 return port
->type
== PORT_AMAZONASC
? "AMAZONASC" : NULL
;
500 * Release the memory region(s) being used by 'port'
502 static void amazonasc_release_port(struct uart_port
*port
)
508 * Request the memory region(s) being used by 'port'
510 static int amazonasc_request_port(struct uart_port
*port
)
516 * Configure/autoconfigure the port.
518 static void amazonasc_config_port(struct uart_port
*port
, int flags
)
520 if (flags
& UART_CONFIG_TYPE
) {
521 port
->type
= PORT_AMAZONASC
;
522 amazonasc_request_port(port
);
527 * verify the new serial_struct (for TIOCSSERIAL).
529 static int amazonasc_verify_port(struct uart_port
*port
, struct serial_struct
*ser
)
532 if (ser
->type
!= PORT_UNKNOWN
&& ser
->type
!= PORT_AMAZONASC
)
534 if (ser
->irq
< 0 || ser
->irq
>= NR_IRQS
)
536 if (ser
->baud_base
< 9600)
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
,
560 static struct uart_port amazonasc_ports
[UART_NR
] = {
562 membase
: (void *)AMAZON_ASC
,
564 iotype
: SERIAL_IO_MEM
,
565 irq
: AMAZONASC_RIR
, /* RIR */
566 uartclk
: 0, /* filled in dynamically */
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
,
577 static void amazonasc_console_write(struct console
*co
, const char *s
, u_int count
)
582 local_irq_save(flags
);
584 * Now, do each character
586 for (i
= 0; i
< count
;)
588 /* wait until the FIFO is not full */
591 fifocnt
= (*AMAZON_ASC_FSTAT
& ASCFSTAT_TXFFLMASK
)
592 >> ASCFSTAT_TXFFLOFF
;
593 } while (fifocnt
== AMAZONASC_TXFIFO_FULL
);
602 *AMAZON_ASC_TBUF
= '\r';
605 fifocnt
= (*AMAZON_ASC_FSTAT
&
606 ASCFSTAT_TXFFLMASK
) >> ASCFSTAT_TXFFLOFF
;
607 } while (fifocnt
== AMAZONASC_TXFIFO_FULL
);
609 *AMAZON_ASC_TBUF
= s
[i
];
613 /* restore the IRQ */
614 local_irq_restore(flags
);
618 amazonasc_console_get_options(struct uart_port
*port
, int *baud
, int *parity
, int *bits
)
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
;
628 if ((lcr_h
& ASCCON_MODEMASK
) == ASCCON_M_7ASYNCPAR
||
629 (lcr_h
& ASCCON_MODEMASK
) == ASCCON_M_8ASYNCPAR
) {
630 if (lcr_h
& ASCCON_ODD
)
636 if ((lcr_h
& ASCCON_MODEMASK
) == ASCCON_M_7ASYNCPAR
)
641 quot
= *AMAZON_ASC_BTR
+ 1;
643 /* this gets hairy if the fractional divider is used */
644 if (lcr_h
& ASCCON_FDE
)
647 fdiv
= *AMAZON_ASC_FDV
;
654 div
= lcr_h
& ASCCON_BRS
? 3 : 2;
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.
666 *baud
= frac
* (port
->uartclk
/ (div
* 512 * 16 * quot
));
667 if (*baud
> 1100 && *baud
< 2400)
669 if (*baud
> 2300 && *baud
< 4800)
671 if (*baud
> 4700 && *baud
< 9600)
673 if (*baud
> 9500 && *baud
< 19200)
675 if (*baud
> 19000 && *baud
< 38400)
677 if (*baud
> 38400 && *baud
< 57600)
679 if (*baud
> 57600 && *baud
< 115200)
681 if (*baud
> 115200 && *baud
< 230400)
686 static int __init
amazonasc_console_setup(struct console
*co
, char *options
)
688 struct uart_port
*port
;
694 /* this assumes: CON.BRS = CON.FDE = 0 */
696 uartclk
= amazon_get_fpi_hz();
698 port
= &amazonasc_ports
[0];
699 amazonasc_ports
[0].uartclk
= uartclk
;
700 amazonasc_ports
[0].type
= PORT_AMAZONASC
;
703 uart_parse_options(options
, &baud
, &parity
, &bits
, &flow
);
706 return uart_set_options(port
, co
, baud
, parity
, bits
, flow
);
709 static struct uart_driver amazonasc_reg
;
710 static struct console amazonasc_console
= {
712 write
: amazonasc_console_write
,
713 device
: uart_console_device
,
714 setup
: amazonasc_console_setup
,
715 flags
: CON_PRINTBUFFER
,
717 data
: &amazonasc_reg
,
720 static int __init
amazonasc_console_init(void)
722 register_console(&amazonasc_console
);
725 console_initcall(amazonasc_console_init
);
727 static struct uart_driver amazonasc_reg
= {
728 .owner
= THIS_MODULE
,
729 .driver_name
= "serial",
734 .cons
= &amazonasc_console
,
737 static int __init
amazonasc_init(void)
740 uart_register_driver(&amazonasc_reg
);
741 res
= uart_add_one_port(&amazonasc_reg
, &amazonasc_ports
[0]);
745 static void __exit
amazonasc_exit(void)
747 uart_unregister_driver(&amazonasc_reg
);
750 module_init(amazonasc_init
);
751 module_exit(amazonasc_exit
);
753 MODULE_AUTHOR("Gary Jennejohn, Felix Fietkau, John Crispin");
754 MODULE_DESCRIPTION("MIPS AMAZONASC serial port driver");
755 MODULE_LICENSE("GPL");