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