]> git.sur5r.net Git - u-boot/blob - cpu/mpc512x/serial.c
16ce7700f981456f04d8655e6b281cace7a91122
[u-boot] / cpu / mpc512x / serial.c
1 /*
2  * (C) Copyright 2000 - 2009
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  *
23  * Based ont the MPC5200 PSC driver.
24  * Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com>
25  */
26
27 /*
28  * Minimal serial functions needed to use one of the PSC ports
29  * as serial console interface.
30  */
31
32 #include <common.h>
33 #include <asm/io.h>
34 #include <asm/processor.h>
35
36 DECLARE_GLOBAL_DATA_PTR;
37
38 #if defined(CONFIG_PSC_CONSOLE)
39
40 static void fifo_init (volatile psc512x_t *psc)
41 {
42         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
43
44         /* reset Rx & Tx fifo slice */
45         out_be32(&psc->rfcmd, PSC_FIFO_RESET_SLICE);
46         out_be32(&psc->tfcmd, PSC_FIFO_RESET_SLICE);
47
48         /* disable Tx & Rx FIFO interrupts */
49         out_be32(&psc->rfintmask, 0);
50         out_be32(&psc->tfintmask, 0);
51
52         out_be32(&psc->tfsize, CONSOLE_FIFO_TX_SIZE | (CONSOLE_FIFO_TX_ADDR << 16));
53         out_be32(&psc->rfsize, CONSOLE_FIFO_RX_SIZE | (CONSOLE_FIFO_RX_ADDR << 16));
54
55         /* enable Tx & Rx FIFO slice */
56         out_be32(&psc->rfcmd, PSC_FIFO_ENABLE_SLICE);
57         out_be32(&psc->tfcmd, PSC_FIFO_ENABLE_SLICE);
58
59         out_be32(&im->fifoc.fifoc_cmd, FIFOC_DISABLE_CLOCK_GATE);
60         __asm__ volatile ("sync");
61 }
62
63 int serial_init(void)
64 {
65         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
66         volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
67         unsigned long baseclk;
68         int div;
69
70         fifo_init (psc);
71
72         /* set MR register to point to MR1 */
73         out_8(&psc->command, PSC_SEL_MODE_REG_1);
74
75         /* disable Tx/Rx */
76         out_8(&psc->command, PSC_TX_DISABLE | PSC_RX_DISABLE);
77
78         /* choose the prescaler by 16 for the Tx/Rx clock generation */
79         out_be16(&psc->psc_clock_select, 0xdd00);
80
81         /* switch to UART mode */
82         out_be32(&psc->sicr, 0);
83
84         /* mode register points to mr1 */
85         /* configure parity, bit length and so on in mode register 1*/
86         out_8(&psc->mode, PSC_MODE_8_BITS | PSC_MODE_PARNONE);
87         /* now, mode register points to mr2 */
88         out_8(&psc->mode, PSC_MODE_1_STOPBIT);
89
90         /* calculate dividor for setting PSC CTUR and CTLR registers */
91         baseclk = (gd->ips_clk + 8) / 16;
92         div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
93
94         out_8(&psc->ctur, (div >> 8) & 0xff);
95         /* set baudrate */
96         out_8(&psc->ctlr, div & 0xff);
97
98         /* disable all interrupts */
99         out_be16(&psc->psc_imr, 0);
100
101         /* reset and enable Rx/Tx */
102         out_8(&psc->command, PSC_RST_RX);
103         out_8(&psc->command, PSC_RST_TX);
104         out_8(&psc->command, PSC_RX_ENABLE | PSC_TX_ENABLE);
105
106         return 0;
107 }
108
109 void serial_putc (const char c)
110 {
111         volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
112         volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
113
114         if (c == '\n')
115                 serial_putc ('\r');
116
117         /* Wait for last character to go. */
118         while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
119                 ;
120
121         psc->tfdata_8 = c;
122 }
123
124 void serial_putc_raw (const char c)
125 {
126         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
127         volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
128
129         /* Wait for last character to go. */
130         while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
131                 ;
132
133         psc->tfdata_8 = c;
134 }
135
136
137 void serial_puts (const char *s)
138 {
139         while (*s) {
140                 serial_putc (*s++);
141         }
142 }
143
144 int serial_getc (void)
145 {
146         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
147         volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
148
149         /* Wait for a character to arrive. */
150         while (in_be32(&psc->rfstat) & PSC_FIFO_EMPTY)
151                 ;
152
153         return psc->rfdata_8;
154 }
155
156 int serial_tstc (void)
157 {
158         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
159         volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
160
161         return !(in_be32(&psc->rfstat) & PSC_FIFO_EMPTY);
162 }
163
164 void serial_setbrg (void)
165 {
166         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
167         volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
168         unsigned long baseclk, div;
169
170         baseclk = (gd->csb_clk + 8) / 16;
171         div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
172
173         out_8(&psc->ctur, (div >> 8) & 0xFF);
174         out_8(&psc->ctlr,  div & 0xff); /* set baudrate */
175 }
176
177 void serial_setrts(int s)
178 {
179         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
180         volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
181
182         if (s) {
183                 /* Assert RTS (become LOW) */
184                 out_8(&psc->op1, 0x1);
185         }
186         else {
187                 /* Negate RTS (become HIGH) */
188                 out_8(&psc->op0, 0x1);
189         }
190 }
191
192 int serial_getcts(void)
193 {
194         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
195         volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
196
197         return (in_8(&psc->ip) & 0x1) ? 0 : 1;
198 }
199 #endif /* CONFIG_PSC_CONSOLE */