]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - arch/mips/cpu/xburst/jz_serial.c
serial: mips: Implement CONFIG_SERIAL_MULTI into JZ serial driver
[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 void jz_serial_puts(const char *s)
113 {
114         while (*s)
115                 serial_putc(*s++);
116 }
117
118 #ifdef CONFIG_SERIAL_MULTI
119 static struct serial_device jz_serial_drv = {
120         .name   = "jz_serial",
121         .start  = jz_serial_init,
122         .stop   = NULL,
123         .setbrg = jz_serial_setbrg,
124         .putc   = jz_serial_putc,
125         .puts   = jz_serial_puts,
126         .getc   = jz_serial_getc,
127         .tstc   = jz_serial_tstc,
128 };
129
130 void jz_serial_initialize(void)
131 {
132         serial_register(&jz_serial_drv);
133 }
134
135 __weak struct serial_device *default_serial_console(void)
136 {
137         return &jz_serial_drv;
138 }
139 #else
140 int serial_init(void)
141 {
142         return jz_serial_init();
143 }
144
145 void serial_setbrg(void)
146 {
147         jz_serial_setbrg();
148 }
149
150 void serial_putc(const char c)
151 {
152         jz_serial_putc(c);
153 }
154
155 void serial_puts(const char *s)
156 {
157         jz_serial_puts(s);
158 }
159
160 int serial_getc(void)
161 {
162         return jz_serial_getc();
163 }
164
165 int serial_tstc(void)
166 {
167         return jz_serial_tstc();
168 }
169 #endif