]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - arch/mips/cpu/xburst/jz_serial.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / mips / cpu / xburst / jz_serial.c
1 /*
2  * Jz4740 UART support
3  * Copyright (c) 2011
4  * Qi Hardware, Xiangfu Liu <xiangfu@sharism.cc>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19  * MA 02111-1307 USA
20  */
21
22 #include <config.h>
23 #include <common.h>
24 #include <asm/io.h>
25 #include <asm/jz4740.h>
26 #include <serial.h>
27 #include <linux/compiler.h>
28
29 /*
30  * serial_init - initialize a channel
31  *
32  * This routine initializes the number of data bits, parity
33  * and set the selected baud rate. Interrupts are disabled.
34  * Set the modem control signals if the option is selected.
35  *
36  * RETURNS: N/A
37  */
38 struct jz4740_uart *uart = (struct jz4740_uart *)CONFIG_SYS_UART_BASE;
39
40 static int jz_serial_init(void)
41 {
42         /* Disable port interrupts while changing hardware */
43         writeb(0, &uart->dlhr_ier);
44
45         /* Disable UART unit function */
46         writeb(~UART_FCR_UUE, &uart->iir_fcr);
47
48         /* Set both receiver and transmitter in UART mode (not SIR) */
49         writeb(~(SIRCR_RSIRE | SIRCR_TSIRE), &uart->isr);
50
51         /*
52          * Set databits, stopbits and parity.
53          * (8-bit data, 1 stopbit, no parity)
54          */
55         writeb(UART_LCR_WLEN_8 | UART_LCR_STOP_1, &uart->lcr);
56
57         /* Set baud rate */
58         serial_setbrg();
59
60         /* Enable UART unit, enable and clear FIFO */
61         writeb(UART_FCR_UUE | UART_FCR_FE | UART_FCR_TFLS | UART_FCR_RFLS,
62                &uart->iir_fcr);
63
64         return 0;
65 }
66
67 static void jz_serial_setbrg(void)
68 {
69         u32 baud_div, tmp;
70
71         baud_div = CONFIG_SYS_EXTAL / 16 / CONFIG_BAUDRATE;
72
73         tmp = readb(&uart->lcr);
74         tmp |= UART_LCR_DLAB;
75         writeb(tmp, &uart->lcr);
76
77         writeb((baud_div >> 8) & 0xff, &uart->dlhr_ier);
78         writeb(baud_div & 0xff, &uart->rbr_thr_dllr);
79
80         tmp &= ~UART_LCR_DLAB;
81         writeb(tmp, &uart->lcr);
82 }
83
84 static int jz_serial_tstc(void)
85 {
86         if (readb(&uart->lsr) & UART_LSR_DR)
87                 return 1;
88
89         return 0;
90 }
91
92 static void jz_serial_putc(const char c)
93 {
94         if (c == '\n')
95                 serial_putc('\r');
96
97         /* Wait for fifo to shift out some bytes */
98         while (!((readb(&uart->lsr) & (UART_LSR_TDRQ | UART_LSR_TEMT)) == 0x60))
99                 ;
100
101         writeb((u8)c, &uart->rbr_thr_dllr);
102 }
103
104 static int jz_serial_getc(void)
105 {
106         while (!serial_tstc())
107                 ;
108
109         return readb(&uart->rbr_thr_dllr);
110 }
111
112 static struct serial_device jz_serial_drv = {
113         .name   = "jz_serial",
114         .start  = jz_serial_init,
115         .stop   = NULL,
116         .setbrg = jz_serial_setbrg,
117         .putc   = jz_serial_putc,
118         .puts   = default_serial_puts,
119         .getc   = jz_serial_getc,
120         .tstc   = jz_serial_tstc,
121 };
122
123 void jz_serial_initialize(void)
124 {
125         serial_register(&jz_serial_drv);
126 }
127
128 __weak struct serial_device *default_serial_console(void)
129 {
130         return &jz_serial_drv;
131 }