]>
Commit | Line | Data |
---|---|---|
945af8d7 WD |
1 | /* |
2 | * (C) Copyright 2000 - 2003 | |
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 | * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with | |
24 | * changes based on the file arch/ppc/mbxboot/m8260_tty.c from the | |
25 | * Linux/PPC sources (m8260_tty.c had no copyright info in it). | |
c12cffc5 WD |
26 | * |
27 | * Martin Krause, 8 Jun 2006 | |
28 | * Added CONFIG_SERIAL_MULTI support | |
945af8d7 WD |
29 | */ |
30 | ||
31 | /* | |
32 | * Minimal serial functions needed to use one of the PSC ports | |
33 | * as serial console interface. | |
34 | */ | |
35 | ||
36 | #include <common.h> | |
37 | #include <mpc5xxx.h> | |
38 | ||
c12cffc5 WD |
39 | #if defined (CONFIG_SERIAL_MULTI) |
40 | #include <serial.h> | |
41 | #endif | |
42 | ||
d87080b7 WD |
43 | DECLARE_GLOBAL_DATA_PTR; |
44 | ||
945af8d7 WD |
45 | #if defined(CONFIG_PSC_CONSOLE) |
46 | ||
47 | #if CONFIG_PSC_CONSOLE == 1 | |
48 | #define PSC_BASE MPC5XXX_PSC1 | |
49 | #elif CONFIG_PSC_CONSOLE == 2 | |
50 | #define PSC_BASE MPC5XXX_PSC2 | |
51 | #elif CONFIG_PSC_CONSOLE == 3 | |
52 | #define PSC_BASE MPC5XXX_PSC3 | |
53 | #elif defined(CONFIG_MGT5100) | |
54 | #error CONFIG_PSC_CONSOLE must be in 1, 2 or 3 | |
55 | #elif CONFIG_PSC_CONSOLE == 4 | |
56 | #define PSC_BASE MPC5XXX_PSC4 | |
57 | #elif CONFIG_PSC_CONSOLE == 5 | |
58 | #define PSC_BASE MPC5XXX_PSC5 | |
59 | #elif CONFIG_PSC_CONSOLE == 6 | |
60 | #define PSC_BASE MPC5XXX_PSC6 | |
61 | #else | |
62 | #error CONFIG_PSC_CONSOLE must be in 1 ... 6 | |
63 | #endif | |
64 | ||
c12cffc5 WD |
65 | #if defined(CONFIG_SERIAL_MULTI) && !defined(CONFIG_PSC_CONSOLE2) |
66 | #error you must define CONFIG_PSC_CONSOLE2 if CONFIG_SERIAL_MULTI is set | |
67 | #endif | |
68 | ||
69 | #if defined(CONFIG_SERIAL_MULTI) | |
70 | #if CONFIG_PSC_CONSOLE2 == 1 | |
71 | #define PSC_BASE2 MPC5XXX_PSC1 | |
72 | #elif CONFIG_PSC_CONSOLE2 == 2 | |
73 | #define PSC_BASE2 MPC5XXX_PSC2 | |
74 | #elif CONFIG_PSC_CONSOLE2 == 3 | |
75 | #define PSC_BASE2 MPC5XXX_PSC3 | |
76 | #elif defined(CONFIG_MGT5100) | |
77 | #error CONFIG_PSC_CONSOLE2 must be in 1, 2 or 3 | |
78 | #elif CONFIG_PSC_CONSOLE2 == 4 | |
79 | #define PSC_BASE2 MPC5XXX_PSC4 | |
80 | #elif CONFIG_PSC_CONSOLE2 == 5 | |
81 | #define PSC_BASE2 MPC5XXX_PSC5 | |
82 | #elif CONFIG_PSC_CONSOLE2 == 6 | |
83 | #define PSC_BASE2 MPC5XXX_PSC6 | |
84 | #else | |
85 | #error CONFIG_PSC_CONSOLE2 must be in 1 ... 6 | |
86 | #endif | |
87 | #endif /* CONFIG_SERIAL_MULTI */ | |
88 | ||
89 | #if defined(CONFIG_SERIAL_MULTI) | |
90 | int serial_init_dev (unsigned long dev_base) | |
91 | #else | |
945af8d7 | 92 | int serial_init (void) |
c12cffc5 | 93 | #endif |
945af8d7 | 94 | { |
c12cffc5 WD |
95 | #if defined(CONFIG_SERIAL_MULTI) |
96 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base; | |
97 | #else | |
945af8d7 | 98 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; |
c12cffc5 | 99 | #endif |
945af8d7 WD |
100 | unsigned long baseclk; |
101 | int div; | |
102 | ||
103 | /* reset PSC */ | |
104 | psc->command = PSC_SEL_MODE_REG_1; | |
105 | ||
106 | /* select clock sources */ | |
107 | #if defined(CONFIG_MGT5100) | |
108 | psc->psc_clock_select = 0xdd00; | |
6d0f6bcf | 109 | baseclk = (CONFIG_SYS_MPC5XXX_CLKIN + 16) / 32; |
945af8d7 WD |
110 | #elif defined(CONFIG_MPC5200) |
111 | psc->psc_clock_select = 0; | |
b98fff1d | 112 | baseclk = (gd->ipb_clk + 16) / 32; |
945af8d7 WD |
113 | #endif |
114 | ||
115 | /* switch to UART mode */ | |
116 | psc->sicr = 0; | |
117 | ||
118 | /* configure parity, bit length and so on */ | |
119 | #if defined(CONFIG_MGT5100) | |
120 | psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE; | |
121 | #elif defined(CONFIG_MPC5200) | |
122 | psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE; | |
123 | #endif | |
124 | psc->mode = PSC_MODE_ONE_STOP; | |
125 | ||
126 | /* set up UART divisor */ | |
b98fff1d WD |
127 | div = (baseclk + (gd->baudrate/2)) / gd->baudrate; |
128 | psc->ctur = (div >> 8) & 0xff; | |
945af8d7 WD |
129 | psc->ctlr = div & 0xff; |
130 | ||
131 | /* disable all interrupts */ | |
132 | psc->psc_imr = 0; | |
133 | ||
134 | /* reset and enable Rx/Tx */ | |
135 | psc->command = PSC_RST_RX; | |
136 | psc->command = PSC_RST_TX; | |
137 | psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE; | |
138 | ||
139 | return (0); | |
140 | } | |
141 | ||
c12cffc5 WD |
142 | #if defined(CONFIG_SERIAL_MULTI) |
143 | void serial_putc_dev (unsigned long dev_base, const char c) | |
144 | #else | |
145 | void serial_putc(const char c) | |
146 | #endif | |
945af8d7 | 147 | { |
c12cffc5 WD |
148 | #if defined(CONFIG_SERIAL_MULTI) |
149 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base; | |
150 | #else | |
945af8d7 | 151 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; |
c12cffc5 | 152 | #endif |
945af8d7 WD |
153 | |
154 | if (c == '\n') | |
c12cffc5 WD |
155 | #if defined(CONFIG_SERIAL_MULTI) |
156 | serial_putc_dev (dev_base, '\r'); | |
157 | #else | |
945af8d7 | 158 | serial_putc('\r'); |
c12cffc5 | 159 | #endif |
945af8d7 WD |
160 | |
161 | /* Wait for last character to go. */ | |
162 | while (!(psc->psc_status & PSC_SR_TXEMP)) | |
163 | ; | |
164 | ||
165 | psc->psc_buffer_8 = c; | |
166 | } | |
167 | ||
e8143e72 WD |
168 | #if defined(CONFIG_SERIAL_MULTI) |
169 | void serial_putc_raw_dev(unsigned long dev_base, const char c) | |
170 | #else | |
171 | void serial_putc_raw(const char c) | |
172 | #endif | |
173 | { | |
174 | #if defined(CONFIG_SERIAL_MULTI) | |
175 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base; | |
176 | #else | |
177 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; | |
178 | #endif | |
179 | /* Wait for last character to go. */ | |
180 | while (!(psc->psc_status & PSC_SR_TXEMP)) | |
181 | ; | |
182 | ||
183 | psc->psc_buffer_8 = c; | |
184 | } | |
185 | ||
186 | ||
c12cffc5 WD |
187 | #if defined(CONFIG_SERIAL_MULTI) |
188 | void serial_puts_dev (unsigned long dev_base, const char *s) | |
189 | #else | |
190 | void serial_puts (const char *s) | |
191 | #endif | |
945af8d7 WD |
192 | { |
193 | while (*s) { | |
c12cffc5 WD |
194 | #if defined(CONFIG_SERIAL_MULTI) |
195 | serial_putc_dev (dev_base, *s++); | |
196 | #else | |
945af8d7 | 197 | serial_putc (*s++); |
c12cffc5 | 198 | #endif |
945af8d7 WD |
199 | } |
200 | } | |
201 | ||
c12cffc5 WD |
202 | #if defined(CONFIG_SERIAL_MULTI) |
203 | int serial_getc_dev (unsigned long dev_base) | |
204 | #else | |
205 | int serial_getc(void) | |
206 | #endif | |
945af8d7 | 207 | { |
c12cffc5 WD |
208 | #if defined(CONFIG_SERIAL_MULTI) |
209 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base; | |
210 | #else | |
945af8d7 | 211 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; |
c12cffc5 | 212 | #endif |
945af8d7 WD |
213 | |
214 | /* Wait for a character to arrive. */ | |
215 | while (!(psc->psc_status & PSC_SR_RXRDY)) | |
216 | ; | |
217 | ||
218 | return psc->psc_buffer_8; | |
219 | } | |
220 | ||
c12cffc5 WD |
221 | #if defined(CONFIG_SERIAL_MULTI) |
222 | int serial_tstc_dev (unsigned long dev_base) | |
223 | #else | |
224 | int serial_tstc(void) | |
225 | #endif | |
945af8d7 | 226 | { |
c12cffc5 WD |
227 | #if defined(CONFIG_SERIAL_MULTI) |
228 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base; | |
229 | #else | |
945af8d7 | 230 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; |
c12cffc5 | 231 | #endif |
945af8d7 WD |
232 | |
233 | return (psc->psc_status & PSC_SR_RXRDY); | |
234 | } | |
235 | ||
c12cffc5 WD |
236 | #if defined(CONFIG_SERIAL_MULTI) |
237 | void serial_setbrg_dev (unsigned long dev_base) | |
238 | #else | |
239 | void serial_setbrg(void) | |
240 | #endif | |
945af8d7 | 241 | { |
c12cffc5 WD |
242 | #if defined(CONFIG_SERIAL_MULTI) |
243 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base; | |
244 | #else | |
945af8d7 | 245 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; |
c12cffc5 | 246 | #endif |
945af8d7 WD |
247 | unsigned long baseclk, div; |
248 | ||
249 | #if defined(CONFIG_MGT5100) | |
6d0f6bcf | 250 | baseclk = (CONFIG_SYS_MPC5XXX_CLKIN + 16) / 32; |
945af8d7 | 251 | #elif defined(CONFIG_MPC5200) |
342717f7 | 252 | baseclk = (gd->ipb_clk + 16) / 32; |
945af8d7 WD |
253 | #endif |
254 | ||
255 | /* set up UART divisor */ | |
342717f7 | 256 | div = (baseclk + (gd->baudrate/2)) / gd->baudrate; |
9f221d07 WD |
257 | psc->ctur = (div >> 8) & 0xFF; |
258 | psc->ctlr = div & 0xff; | |
945af8d7 | 259 | } |
c12cffc5 | 260 | |
e8143e72 WD |
261 | #if defined(CONFIG_SERIAL_MULTI) |
262 | void serial_setrts_dev (unsigned long dev_base, int s) | |
263 | #else | |
264 | void serial_setrts(int s) | |
265 | #endif | |
266 | { | |
267 | #if defined(CONFIG_SERIAL_MULTI) | |
268 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base; | |
269 | #else | |
270 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; | |
271 | #endif | |
272 | ||
273 | if (s) { | |
274 | /* Assert RTS (become LOW) */ | |
275 | psc->op1 = 0x1; | |
276 | } | |
277 | else { | |
278 | /* Negate RTS (become HIGH) */ | |
279 | psc->op0 = 0x1; | |
280 | } | |
281 | } | |
282 | ||
283 | #if defined(CONFIG_SERIAL_MULTI) | |
284 | int serial_getcts_dev (unsigned long dev_base) | |
285 | #else | |
286 | int serial_getcts(void) | |
287 | #endif | |
288 | { | |
289 | #if defined(CONFIG_SERIAL_MULTI) | |
290 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base; | |
291 | #else | |
292 | volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; | |
293 | #endif | |
294 | ||
295 | return (psc->ip & 0x1) ? 0 : 1; | |
296 | } | |
297 | ||
c12cffc5 WD |
298 | #if defined(CONFIG_SERIAL_MULTI) |
299 | int serial0_init(void) | |
300 | { | |
301 | return (serial_init_dev(PSC_BASE)); | |
302 | } | |
303 | ||
304 | int serial1_init(void) | |
305 | { | |
306 | return (serial_init_dev(PSC_BASE2)); | |
307 | } | |
308 | void serial0_setbrg (void) | |
309 | { | |
310 | serial_setbrg_dev(PSC_BASE); | |
311 | } | |
312 | void serial1_setbrg (void) | |
313 | { | |
314 | serial_setbrg_dev(PSC_BASE2); | |
315 | } | |
316 | ||
317 | void serial0_putc(const char c) | |
318 | { | |
319 | serial_putc_dev(PSC_BASE,c); | |
320 | } | |
321 | ||
322 | void serial1_putc(const char c) | |
323 | { | |
324 | serial_putc_dev(PSC_BASE2, c); | |
325 | } | |
326 | void serial0_puts(const char *s) | |
327 | { | |
328 | serial_puts_dev(PSC_BASE, s); | |
329 | } | |
330 | ||
331 | void serial1_puts(const char *s) | |
332 | { | |
333 | serial_puts_dev(PSC_BASE2, s); | |
334 | } | |
335 | ||
336 | int serial0_getc(void) | |
337 | { | |
338 | return(serial_getc_dev(PSC_BASE)); | |
339 | } | |
340 | ||
341 | int serial1_getc(void) | |
342 | { | |
343 | return(serial_getc_dev(PSC_BASE2)); | |
344 | } | |
345 | int serial0_tstc(void) | |
346 | { | |
347 | return (serial_tstc_dev(PSC_BASE)); | |
348 | } | |
349 | ||
350 | int serial1_tstc(void) | |
351 | { | |
352 | return (serial_tstc_dev(PSC_BASE2)); | |
353 | } | |
354 | ||
355 | struct serial_device serial0_device = | |
356 | { | |
357 | "serial0", | |
358 | "UART0", | |
359 | serial0_init, | |
360 | serial0_setbrg, | |
361 | serial0_getc, | |
362 | serial0_tstc, | |
363 | serial0_putc, | |
364 | serial0_puts, | |
365 | }; | |
366 | ||
367 | struct serial_device serial1_device = | |
368 | { | |
369 | "serial1", | |
370 | "UART1", | |
371 | serial1_init, | |
372 | serial1_setbrg, | |
373 | serial1_getc, | |
374 | serial1_tstc, | |
375 | serial1_putc, | |
376 | serial1_puts, | |
377 | }; | |
378 | #endif /* CONFIG_SERIAL_MULTI */ | |
379 | ||
945af8d7 | 380 | #endif /* CONFIG_PSC_CONSOLE */ |