]>
Commit | Line | Data |
---|---|---|
8993e54b | 1 | /* |
57ae8a5c | 2 | * (C) Copyright 2000 - 2010 |
8993e54b RJ |
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> | |
843efb11 WD |
33 | #include <asm/io.h> |
34 | #include <asm/processor.h> | |
8993e54b RJ |
35 | |
36 | DECLARE_GLOBAL_DATA_PTR; | |
37 | ||
38 | #if defined(CONFIG_PSC_CONSOLE) | |
39 | ||
40 | static void fifo_init (volatile psc512x_t *psc) | |
41 | { | |
6d0f6bcf | 42 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
8993e54b RJ |
43 | |
44 | /* reset Rx & Tx fifo slice */ | |
843efb11 WD |
45 | out_be32(&psc->rfcmd, PSC_FIFO_RESET_SLICE); |
46 | out_be32(&psc->tfcmd, PSC_FIFO_RESET_SLICE); | |
8993e54b RJ |
47 | |
48 | /* disable Tx & Rx FIFO interrupts */ | |
843efb11 WD |
49 | out_be32(&psc->rfintmask, 0); |
50 | out_be32(&psc->tfintmask, 0); | |
8993e54b | 51 | |
843efb11 WD |
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)); | |
8993e54b RJ |
54 | |
55 | /* enable Tx & Rx FIFO slice */ | |
843efb11 WD |
56 | out_be32(&psc->rfcmd, PSC_FIFO_ENABLE_SLICE); |
57 | out_be32(&psc->tfcmd, PSC_FIFO_ENABLE_SLICE); | |
8993e54b | 58 | |
843efb11 | 59 | out_be32(&im->fifoc.fifoc_cmd, FIFOC_DISABLE_CLOCK_GATE); |
8993e54b RJ |
60 | __asm__ volatile ("sync"); |
61 | } | |
62 | ||
ba4feae9 SR |
63 | void serial_setbrg(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, div; | |
68 | ||
69 | /* calculate dividor for setting PSC CTUR and CTLR registers */ | |
70 | baseclk = (gd->ips_clk + 8) / 16; | |
71 | div = (baseclk + (gd->baudrate / 2)) / gd->baudrate; | |
72 | ||
73 | out_8(&psc->ctur, (div >> 8) & 0xff); | |
74 | out_8(&psc->ctlr, div & 0xff); /* set baudrate */ | |
75 | } | |
76 | ||
8993e54b RJ |
77 | int serial_init(void) |
78 | { | |
6d0f6bcf | 79 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
8993e54b | 80 | volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; |
8993e54b RJ |
81 | |
82 | fifo_init (psc); | |
83 | ||
84 | /* set MR register to point to MR1 */ | |
843efb11 | 85 | out_8(&psc->command, PSC_SEL_MODE_REG_1); |
8993e54b RJ |
86 | |
87 | /* disable Tx/Rx */ | |
843efb11 | 88 | out_8(&psc->command, PSC_TX_DISABLE | PSC_RX_DISABLE); |
8993e54b RJ |
89 | |
90 | /* choose the prescaler by 16 for the Tx/Rx clock generation */ | |
843efb11 | 91 | out_be16(&psc->psc_clock_select, 0xdd00); |
8993e54b RJ |
92 | |
93 | /* switch to UART mode */ | |
843efb11 | 94 | out_be32(&psc->sicr, 0); |
8993e54b RJ |
95 | |
96 | /* mode register points to mr1 */ | |
97 | /* configure parity, bit length and so on in mode register 1*/ | |
843efb11 | 98 | out_8(&psc->mode, PSC_MODE_8_BITS | PSC_MODE_PARNONE); |
8993e54b | 99 | /* now, mode register points to mr2 */ |
843efb11 | 100 | out_8(&psc->mode, PSC_MODE_1_STOPBIT); |
8993e54b | 101 | |
8993e54b | 102 | /* set baudrate */ |
ba4feae9 | 103 | serial_setbrg(); |
8993e54b RJ |
104 | |
105 | /* disable all interrupts */ | |
843efb11 | 106 | out_be16(&psc->psc_imr, 0); |
8993e54b RJ |
107 | |
108 | /* reset and enable Rx/Tx */ | |
843efb11 WD |
109 | out_8(&psc->command, PSC_RST_RX); |
110 | out_8(&psc->command, PSC_RST_TX); | |
111 | out_8(&psc->command, PSC_RX_ENABLE | PSC_TX_ENABLE); | |
8993e54b RJ |
112 | |
113 | return 0; | |
114 | } | |
115 | ||
116 | void serial_putc (const char c) | |
117 | { | |
6d0f6bcf | 118 | volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
8993e54b RJ |
119 | volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; |
120 | ||
121 | if (c == '\n') | |
122 | serial_putc ('\r'); | |
123 | ||
124 | /* Wait for last character to go. */ | |
843efb11 | 125 | while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP)) |
8993e54b RJ |
126 | ; |
127 | ||
57ae8a5c | 128 | out_8(&psc->tfdata_8, c); |
8993e54b RJ |
129 | } |
130 | ||
131 | void serial_putc_raw (const char c) | |
132 | { | |
6d0f6bcf | 133 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
8993e54b RJ |
134 | volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; |
135 | ||
136 | /* Wait for last character to go. */ | |
843efb11 | 137 | while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP)) |
8993e54b RJ |
138 | ; |
139 | ||
57ae8a5c | 140 | out_8(&psc->tfdata_8, c); |
8993e54b RJ |
141 | } |
142 | ||
143 | ||
144 | void serial_puts (const char *s) | |
145 | { | |
146 | while (*s) { | |
147 | serial_putc (*s++); | |
148 | } | |
149 | } | |
150 | ||
151 | int serial_getc (void) | |
152 | { | |
6d0f6bcf | 153 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
8993e54b RJ |
154 | volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; |
155 | ||
156 | /* Wait for a character to arrive. */ | |
843efb11 | 157 | while (in_be32(&psc->rfstat) & PSC_FIFO_EMPTY) |
8993e54b RJ |
158 | ; |
159 | ||
57ae8a5c | 160 | return in_8(&psc->rfdata_8); |
8993e54b RJ |
161 | } |
162 | ||
163 | int serial_tstc (void) | |
164 | { | |
6d0f6bcf | 165 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
8993e54b RJ |
166 | volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; |
167 | ||
843efb11 | 168 | return !(in_be32(&psc->rfstat) & PSC_FIFO_EMPTY); |
8993e54b RJ |
169 | } |
170 | ||
8993e54b RJ |
171 | void serial_setrts(int s) |
172 | { | |
6d0f6bcf | 173 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
8993e54b RJ |
174 | volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; |
175 | ||
176 | if (s) { | |
177 | /* Assert RTS (become LOW) */ | |
843efb11 | 178 | out_8(&psc->op1, 0x1); |
8993e54b RJ |
179 | } |
180 | else { | |
181 | /* Negate RTS (become HIGH) */ | |
843efb11 | 182 | out_8(&psc->op0, 0x1); |
8993e54b RJ |
183 | } |
184 | } | |
185 | ||
186 | int serial_getcts(void) | |
187 | { | |
6d0f6bcf | 188 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
8993e54b RJ |
189 | volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE]; |
190 | ||
843efb11 | 191 | return (in_8(&psc->ip) & 0x1) ? 0 : 1; |
8993e54b RJ |
192 | } |
193 | #endif /* CONFIG_PSC_CONSOLE */ |