]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc512x/serial.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc512x / serial.c
1 /*
2  * (C) Copyright 2000 - 2010
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 #include <serial.h>
36
37 DECLARE_GLOBAL_DATA_PTR;
38
39 #if defined(CONFIG_PSC_CONSOLE) || defined(CONFIG_SERIAL_MULTI)
40
41 static void fifo_init (volatile psc512x_t *psc)
42 {
43         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
44         u32 tfsize, rfsize;
45
46         /* reset Rx & Tx fifo slice */
47         out_be32(&psc->rfcmd, PSC_FIFO_RESET_SLICE);
48         out_be32(&psc->tfcmd, PSC_FIFO_RESET_SLICE);
49
50         /* disable Tx & Rx FIFO interrupts */
51         out_be32(&psc->rfintmask, 0);
52         out_be32(&psc->tfintmask, 0);
53
54 #if defined(CONFIG_SERIAL_MULTI)
55         switch (((u32)psc & 0xf00) >> 8) {
56         case 0:
57                 tfsize = FIFOC_PSC0_TX_SIZE | (FIFOC_PSC0_TX_ADDR << 16);
58                 rfsize = FIFOC_PSC0_RX_SIZE | (FIFOC_PSC0_RX_ADDR << 16);
59                 break;
60         case 1:
61                 tfsize = FIFOC_PSC1_TX_SIZE | (FIFOC_PSC1_TX_ADDR << 16);
62                 rfsize = FIFOC_PSC1_RX_SIZE | (FIFOC_PSC1_RX_ADDR << 16);
63                 break;
64         case 2:
65                 tfsize = FIFOC_PSC2_TX_SIZE | (FIFOC_PSC2_TX_ADDR << 16);
66                 rfsize = FIFOC_PSC2_RX_SIZE | (FIFOC_PSC2_RX_ADDR << 16);
67                 break;
68         case 3:
69                 tfsize = FIFOC_PSC3_TX_SIZE | (FIFOC_PSC3_TX_ADDR << 16);
70                 rfsize = FIFOC_PSC3_RX_SIZE | (FIFOC_PSC3_RX_ADDR << 16);
71                 break;
72         case 4:
73                 tfsize = FIFOC_PSC4_TX_SIZE | (FIFOC_PSC4_TX_ADDR << 16);
74                 rfsize = FIFOC_PSC4_RX_SIZE | (FIFOC_PSC4_RX_ADDR << 16);
75                 break;
76         case 5:
77                 tfsize = FIFOC_PSC5_TX_SIZE | (FIFOC_PSC5_TX_ADDR << 16);
78                 rfsize = FIFOC_PSC5_RX_SIZE | (FIFOC_PSC5_RX_ADDR << 16);
79                 break;
80         case 6:
81                 tfsize = FIFOC_PSC6_TX_SIZE | (FIFOC_PSC6_TX_ADDR << 16);
82                 rfsize = FIFOC_PSC6_RX_SIZE | (FIFOC_PSC6_RX_ADDR << 16);
83                 break;
84         case 7:
85                 tfsize = FIFOC_PSC7_TX_SIZE | (FIFOC_PSC7_TX_ADDR << 16);
86                 rfsize = FIFOC_PSC7_RX_SIZE | (FIFOC_PSC7_RX_ADDR << 16);
87                 break;
88         case 8:
89                 tfsize = FIFOC_PSC8_TX_SIZE | (FIFOC_PSC8_TX_ADDR << 16);
90                 rfsize = FIFOC_PSC8_RX_SIZE | (FIFOC_PSC8_RX_ADDR << 16);
91                 break;
92         case 9:
93                 tfsize = FIFOC_PSC9_TX_SIZE | (FIFOC_PSC9_TX_ADDR << 16);
94                 rfsize = FIFOC_PSC9_RX_SIZE | (FIFOC_PSC9_RX_ADDR << 16);
95                 break;
96         case 10:
97                 tfsize = FIFOC_PSC10_TX_SIZE | (FIFOC_PSC10_TX_ADDR << 16);
98                 rfsize = FIFOC_PSC10_RX_SIZE | (FIFOC_PSC10_RX_ADDR << 16);
99                 break;
100         case 11:
101                 tfsize = FIFOC_PSC11_TX_SIZE | (FIFOC_PSC11_TX_ADDR << 16);
102                 rfsize = FIFOC_PSC11_RX_SIZE | (FIFOC_PSC11_RX_ADDR << 16);
103                 break;
104         default:
105                 return;
106         }
107 #else
108         tfsize = CONSOLE_FIFO_TX_SIZE | (CONSOLE_FIFO_TX_ADDR << 16);
109         rfsize = CONSOLE_FIFO_RX_SIZE | (CONSOLE_FIFO_RX_ADDR << 16);
110 #endif
111         out_be32(&psc->tfsize, tfsize);
112         out_be32(&psc->rfsize, rfsize);
113
114         /* enable Tx & Rx FIFO slice */
115         out_be32(&psc->rfcmd, PSC_FIFO_ENABLE_SLICE);
116         out_be32(&psc->tfcmd, PSC_FIFO_ENABLE_SLICE);
117
118         out_be32(&im->fifoc.fifoc_cmd, FIFOC_DISABLE_CLOCK_GATE);
119         __asm__ volatile ("sync");
120 }
121
122 void serial_setbrg_dev(unsigned int idx)
123 {
124         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
125         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
126         unsigned long baseclk, div;
127         unsigned long baudrate;
128         char buf[16];
129         char *br_env;
130
131         baudrate = gd->baudrate;
132         if (idx != CONFIG_PSC_CONSOLE) {
133                 /* Allows setting baudrate for other serial devices
134                  * on PSCx using environment. If not specified, use
135                  * the same baudrate as for console.
136                  */
137                 sprintf(buf, "psc%d_baudrate", idx);
138                 br_env = getenv(buf);
139                 if (br_env)
140                         baudrate = simple_strtoul(br_env, NULL, 10);
141
142                 debug("%s: idx %d, baudrate %d\n", __func__, idx, baudrate);
143         }
144
145         /* calculate divisor for setting PSC CTUR and CTLR registers */
146         baseclk = (gd->ips_clk + 8) / 16;
147         div = (baseclk + (baudrate / 2)) / baudrate;
148
149         out_8(&psc->ctur, (div >> 8) & 0xff);
150         out_8(&psc->ctlr,  div & 0xff); /* set baudrate */
151 }
152
153 int serial_init_dev(unsigned int idx)
154 {
155         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
156         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
157 #if defined(CONFIG_SERIAL_MULTI)
158         u32 reg;
159
160         reg = in_be32(&im->clk.sccr[0]);
161         out_be32(&im->clk.sccr[0], reg | CLOCK_SCCR1_PSC_EN(idx));
162 #endif
163
164         fifo_init (psc);
165
166         /* set MR register to point to MR1 */
167         out_8(&psc->command, PSC_SEL_MODE_REG_1);
168
169         /* disable Tx/Rx */
170         out_8(&psc->command, PSC_TX_DISABLE | PSC_RX_DISABLE);
171
172         /* choose the prescaler by 16 for the Tx/Rx clock generation */
173         out_be16(&psc->psc_clock_select, 0xdd00);
174
175         /* switch to UART mode */
176         out_be32(&psc->sicr, 0);
177
178         /* mode register points to mr1 */
179         /* configure parity, bit length and so on in mode register 1*/
180         out_8(&psc->mode, PSC_MODE_8_BITS | PSC_MODE_PARNONE);
181         /* now, mode register points to mr2 */
182         out_8(&psc->mode, PSC_MODE_1_STOPBIT);
183
184         /* set baudrate */
185         serial_setbrg_dev(idx);
186
187         /* disable all interrupts */
188         out_be16(&psc->psc_imr, 0);
189
190         /* reset and enable Rx/Tx */
191         out_8(&psc->command, PSC_RST_RX);
192         out_8(&psc->command, PSC_RST_TX);
193         out_8(&psc->command, PSC_RX_ENABLE | PSC_TX_ENABLE);
194
195         return 0;
196 }
197
198 int serial_uninit_dev(unsigned int idx)
199 {
200         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
201         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
202         u32 reg;
203
204         out_8(&psc->command, PSC_RX_DISABLE | PSC_TX_DISABLE);
205         reg = in_be32(&im->clk.sccr[0]);
206         reg &= ~CLOCK_SCCR1_PSC_EN(idx);
207         out_be32(&im->clk.sccr[0], reg);
208
209         return 0;
210 }
211
212 void serial_putc_dev(unsigned int idx, const char c)
213 {
214         volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
215         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
216
217         if (c == '\n')
218                 serial_putc_dev(idx, '\r');
219
220         /* Wait for last character to go. */
221         while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
222                 ;
223
224         out_8(&psc->tfdata_8, c);
225 }
226
227 void serial_putc_raw_dev(unsigned int idx, const char c)
228 {
229         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
230         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
231
232         /* Wait for last character to go. */
233         while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
234                 ;
235
236         out_8(&psc->tfdata_8, c);
237 }
238
239 void serial_puts_dev(unsigned int idx, const char *s)
240 {
241         while (*s)
242                 serial_putc_dev(idx, *s++);
243 }
244
245 int serial_getc_dev(unsigned int idx)
246 {
247         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
248         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
249
250         /* Wait for a character to arrive. */
251         while (in_be32(&psc->rfstat) & PSC_FIFO_EMPTY)
252                 ;
253
254         return in_8(&psc->rfdata_8);
255 }
256
257 int serial_tstc_dev(unsigned int idx)
258 {
259         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
260         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
261
262         return !(in_be32(&psc->rfstat) & PSC_FIFO_EMPTY);
263 }
264
265 void serial_setrts_dev(unsigned int idx, int s)
266 {
267         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
268         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
269
270         if (s) {
271                 /* Assert RTS (become LOW) */
272                 out_8(&psc->op1, 0x1);
273         }
274         else {
275                 /* Negate RTS (become HIGH) */
276                 out_8(&psc->op0, 0x1);
277         }
278 }
279
280 int serial_getcts_dev(unsigned int idx)
281 {
282         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
283         volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
284
285         return (in_8(&psc->ip) & 0x1) ? 0 : 1;
286 }
287 #endif /* CONFIG_PSC_CONSOLE || CONFIG_SERIAL_MULTI */
288
289 #if defined(CONFIG_SERIAL_MULTI)
290
291 #define DECLARE_PSC_SERIAL_FUNCTIONS(port) \
292         int serial##port##_init(void) \
293         { \
294                 return serial_init_dev(port); \
295         } \
296         int serial##port##_uninit(void) \
297         { \
298                 return serial_uninit_dev(port); \
299         } \
300         void serial##port##_setbrg(void) \
301         { \
302                 serial_setbrg_dev(port); \
303         } \
304         int serial##port##_getc(void) \
305         { \
306                 return serial_getc_dev(port); \
307         } \
308         int serial##port##_tstc(void) \
309         { \
310                 return serial_tstc_dev(port); \
311         } \
312         void serial##port##_putc(const char c) \
313         { \
314                 serial_putc_dev(port, c); \
315         } \
316         void serial##port##_puts(const char *s) \
317         { \
318                 serial_puts_dev(port, s); \
319         }
320
321 #define INIT_PSC_SERIAL_STRUCTURE(port, name, bus) { \
322         name, \
323         bus, \
324         serial##port##_init, \
325         serial##port##_uninit, \
326         serial##port##_setbrg, \
327         serial##port##_getc, \
328         serial##port##_tstc, \
329         serial##port##_putc, \
330         serial##port##_puts, \
331 }
332
333 #if defined(CONFIG_SYS_PSC1)
334 DECLARE_PSC_SERIAL_FUNCTIONS(1);
335 struct serial_device serial1_device =
336 INIT_PSC_SERIAL_STRUCTURE(1, "psc1", "UART1");
337 #endif
338
339 #if defined(CONFIG_SYS_PSC3)
340 DECLARE_PSC_SERIAL_FUNCTIONS(3);
341 struct serial_device serial3_device =
342 INIT_PSC_SERIAL_STRUCTURE(3, "psc3", "UART3");
343 #endif
344
345 #if defined(CONFIG_SYS_PSC4)
346 DECLARE_PSC_SERIAL_FUNCTIONS(4);
347 struct serial_device serial4_device =
348 INIT_PSC_SERIAL_STRUCTURE(4, "psc4", "UART4");
349 #endif
350
351 #if defined(CONFIG_SYS_PSC6)
352 DECLARE_PSC_SERIAL_FUNCTIONS(6);
353 struct serial_device serial6_device =
354 INIT_PSC_SERIAL_STRUCTURE(6, "psc6", "UART6");
355 #endif
356
357 #else
358
359 void serial_setbrg(void)
360 {
361         serial_setbrg_dev(CONFIG_PSC_CONSOLE);
362 }
363
364 int serial_init(void)
365 {
366         return serial_init_dev(CONFIG_PSC_CONSOLE);
367 }
368
369 void serial_putc(const char c)
370 {
371         serial_putc_dev(CONFIG_PSC_CONSOLE, c);
372 }
373
374 void serial_putc_raw(const char c)
375 {
376         serial_putc_raw_dev(CONFIG_PSC_CONSOLE, c);
377 }
378
379 void serial_puts(const char *s)
380 {
381         serial_puts_dev(CONFIG_PSC_CONSOLE, s);
382 }
383
384 int serial_getc(void)
385 {
386         return serial_getc_dev(CONFIG_PSC_CONSOLE);
387 }
388
389 int serial_tstc(void)
390 {
391         return serial_tstc_dev(CONFIG_PSC_CONSOLE);
392 }
393
394 void serial_setrts(int s)
395 {
396         return serial_setrts_dev(CONFIG_PSC_CONSOLE, s);
397 }
398
399 int serial_getcts(void)
400 {
401         return serial_getcts_dev(CONFIG_PSC_CONSOLE);
402 }
403 #endif /* CONFIG_PSC_CONSOLE */
404
405 #if defined(CONFIG_SERIAL_MULTI)
406 #include <stdio_dev.h>
407 /*
408  * Routines for communication with serial devices over PSC
409  */
410 /* Bitfield for initialized PSCs */
411 static unsigned int initialized;
412
413 struct stdio_dev *open_port(int num, int baudrate)
414 {
415         struct stdio_dev *port;
416         char env_var[16];
417         char env_val[10];
418         char name[7];
419
420         if (num < 0 || num > 11)
421                 return NULL;
422
423         sprintf(name, "psc%d", num);
424         port = stdio_get_by_name(name);
425         if (!port)
426                 return NULL;
427
428         if (!test_bit(num, &initialized)) {
429                 sprintf(env_var, "psc%d_baudrate", num);
430                 sprintf(env_val, "%d", baudrate);
431                 setenv(env_var, env_val);
432
433                 if (port->start())
434                         return NULL;
435
436                 set_bit(num, &initialized);
437         }
438
439         return port;
440 }
441
442 int close_port(int num)
443 {
444         struct stdio_dev *port;
445         int ret;
446         char name[7];
447
448         if (num < 0 || num > 11)
449                 return -1;
450
451         sprintf(name, "psc%d", num);
452         port = stdio_get_by_name(name);
453         if (!port)
454                 return -1;
455
456         ret = port->stop();
457         clear_bit(num, &initialized);
458
459         return ret;
460 }
461
462 int write_port(struct stdio_dev *port, char *buf)
463 {
464         if (!port || !buf)
465                 return -1;
466
467         port->puts(buf);
468
469         return 0;
470 }
471
472 int read_port(struct stdio_dev *port, char *buf, int size)
473 {
474         int cnt = 0;
475
476         if (!port || !buf)
477                 return -1;
478
479         if (!size)
480                 return 0;
481
482         while (port->tstc()) {
483                 buf[cnt++] = port->getc();
484                 if (cnt > size)
485                         break;
486         }
487
488         return cnt;
489 }
490 #endif /* CONFIG_SERIAL_MULTI */