Merge with git://www.denx.de/git/u-boot.git
[platform/kernel/u-boot.git] / cpu / ppc4xx / serial.c
1 /*
2  * (C) Copyright 2000-2006
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 /*------------------------------------------------------------------------------+ */
24 /*
25  * This source code has been made available to you by IBM on an AS-IS
26  * basis.  Anyone receiving this source is licensed under IBM
27  * copyrights to use it in any way he or she deems fit, including
28  * copying it, modifying it, compiling it, and redistributing it either
29  * with or without modifications.  No license under IBM patents or
30  * patent applications is to be implied by the copyright license.
31  *
32  * Any user of this software should understand that IBM cannot provide
33  * technical support for this software and will not be responsible for
34  * any consequences resulting from the use of this software.
35  *
36  * Any person who transfers this source code or any derivative work
37  * must include the IBM copyright notice, this paragraph, and the
38  * preceding two paragraphs in the transferred software.
39  *
40  * COPYRIGHT   I B M   CORPORATION 1995
41  * LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
42  */
43 /*------------------------------------------------------------------------------- */
44 /*
45  * Travis Sawyer 15 September 2004
46  *    Added CONFIG_SERIAL_MULTI support
47  */
48 #include <common.h>
49 #include <commproc.h>
50 #include <asm/processor.h>
51 #include <watchdog.h>
52 #include "vecnum.h"
53
54 #ifdef CONFIG_SERIAL_MULTI
55 #include <serial.h>
56 #endif
57
58 #ifdef CONFIG_SERIAL_SOFTWARE_FIFO
59 #include <malloc.h>
60 #endif
61
62 DECLARE_GLOBAL_DATA_PTR;
63
64 /*****************************************************************************/
65 #ifdef CONFIG_IOP480
66
67 #define SPU_BASE         0x40000000
68
69 #define spu_LineStat_rc  0x00   /* Line Status Register (Read/Clear) */
70 #define spu_LineStat_w   0x04   /* Line Status Register (Set) */
71 #define spu_Handshk_rc   0x08   /* Handshake Status Register (Read/Clear) */
72 #define spu_Handshk_w    0x0c   /* Handshake Status Register (Set) */
73 #define spu_BRateDivh    0x10   /* Baud rate divisor high */
74 #define spu_BRateDivl    0x14   /* Baud rate divisor low */
75 #define spu_CtlReg       0x18   /* Control Register */
76 #define spu_RxCmd        0x1c   /* Rx Command Register */
77 #define spu_TxCmd        0x20   /* Tx Command Register */
78 #define spu_RxBuff       0x24   /* Rx data buffer */
79 #define spu_TxBuff       0x24   /* Tx data buffer */
80
81 /*-----------------------------------------------------------------------------+
82   | Line Status Register.
83   +-----------------------------------------------------------------------------*/
84 #define asyncLSRport1           0x40000000
85 #define asyncLSRport1set        0x40000004
86 #define asyncLSRDataReady             0x80
87 #define asyncLSRFramingError          0x40
88 #define asyncLSROverrunError          0x20
89 #define asyncLSRParityError           0x10
90 #define asyncLSRBreakInterrupt        0x08
91 #define asyncLSRTxHoldEmpty           0x04
92 #define asyncLSRTxShiftEmpty          0x02
93
94 /*-----------------------------------------------------------------------------+
95   | Handshake Status Register.
96   +-----------------------------------------------------------------------------*/
97 #define asyncHSRport1           0x40000008
98 #define asyncHSRport1set        0x4000000c
99 #define asyncHSRDsr                   0x80
100 #define asyncLSRCts                   0x40
101
102 /*-----------------------------------------------------------------------------+
103   | Control Register.
104   +-----------------------------------------------------------------------------*/
105 #define asyncCRport1            0x40000018
106 #define asyncCRNormal                 0x00
107 #define asyncCRLoopback               0x40
108 #define asyncCRAutoEcho               0x80
109 #define asyncCRDtr                    0x20
110 #define asyncCRRts                    0x10
111 #define asyncCRWordLength7            0x00
112 #define asyncCRWordLength8            0x08
113 #define asyncCRParityDisable          0x00
114 #define asyncCRParityEnable           0x04
115 #define asyncCREvenParity             0x00
116 #define asyncCROddParity              0x02
117 #define asyncCRStopBitsOne            0x00
118 #define asyncCRStopBitsTwo            0x01
119 #define asyncCRDisableDtrRts          0x00
120
121 /*-----------------------------------------------------------------------------+
122   | Receiver Command Register.
123   +-----------------------------------------------------------------------------*/
124 #define asyncRCRport1           0x4000001c
125 #define asyncRCRDisable               0x00
126 #define asyncRCREnable                0x80
127 #define asyncRCRIntDisable            0x00
128 #define asyncRCRIntEnabled            0x20
129 #define asyncRCRDMACh2                0x40
130 #define asyncRCRDMACh3                0x60
131 #define asyncRCRErrorInt              0x10
132 #define asyncRCRPauseEnable           0x08
133
134 /*-----------------------------------------------------------------------------+
135   | Transmitter Command Register.
136   +-----------------------------------------------------------------------------*/
137 #define asyncTCRport1           0x40000020
138 #define asyncTCRDisable               0x00
139 #define asyncTCREnable                0x80
140 #define asyncTCRIntDisable            0x00
141 #define asyncTCRIntEnabled            0x20
142 #define asyncTCRDMACh2                0x40
143 #define asyncTCRDMACh3                0x60
144 #define asyncTCRTxEmpty               0x10
145 #define asyncTCRErrorInt              0x08
146 #define asyncTCRStopPause             0x04
147 #define asyncTCRBreakGen              0x02
148
149 /*-----------------------------------------------------------------------------+
150   | Miscellanies defines.
151   +-----------------------------------------------------------------------------*/
152 #define asyncTxBufferport1      0x40000024
153 #define asyncRxBufferport1      0x40000024
154 #define asyncDLABLsbport1       0x40000014
155 #define asyncDLABMsbport1       0x40000010
156 #define asyncXOFFchar                 0x13
157 #define asyncXONchar                  0x11
158
159 /*
160  * Minimal serial functions needed to use one of the SMC ports
161  * as serial console interface.
162  */
163
164 int serial_init (void)
165 {
166         volatile char val;
167         unsigned short br_reg;
168
169         br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1);
170
171         /*
172          * Init onboard UART
173          */
174         out8 (SPU_BASE + spu_LineStat_rc, 0x78); /* Clear all bits in Line Status Reg */
175         out8 (SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */
176         out8 (SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */
177         out8 (SPU_BASE + spu_CtlReg, 0x08);     /* Set 8 bits, no parity and 1 stop bit */
178         out8 (SPU_BASE + spu_RxCmd, 0xb0);      /* Enable Rx */
179         out8 (SPU_BASE + spu_TxCmd, 0x9c);      /* Enable Tx */
180         out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */
181         val = in8 (SPU_BASE + spu_RxBuff);      /* Dummy read, to clear receiver */
182
183         return (0);
184 }
185
186 void serial_setbrg (void)
187 {
188         unsigned short br_reg;
189
190         br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1);
191
192         out8 (SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */
193         out8 (SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */
194 }
195
196 void serial_putc (const char c)
197 {
198         if (c == '\n')
199                 serial_putc ('\r');
200
201         /* load status from handshake register */
202         if (in8 (SPU_BASE + spu_Handshk_rc) != 00)
203                 out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */
204
205         out8 (SPU_BASE + spu_TxBuff, c);        /* Put char */
206
207         while ((in8 (SPU_BASE + spu_LineStat_rc) & 04) != 04) {
208                 if (in8 (SPU_BASE + spu_Handshk_rc) != 00)
209                         out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */
210         }
211 }
212
213 void serial_puts (const char *s)
214 {
215         while (*s) {
216                 serial_putc (*s++);
217         }
218 }
219
220 int serial_getc ()
221 {
222         unsigned char status = 0;
223
224         while (1) {
225                 status = in8 (asyncLSRport1);
226                 if ((status & asyncLSRDataReady) != 0x0) {
227                         break;
228                 }
229                 if ((status & ( asyncLSRFramingError |
230                                 asyncLSROverrunError |
231                                 asyncLSRParityError  |
232                                 asyncLSRBreakInterrupt )) != 0) {
233                         (void) out8 (asyncLSRport1,
234                                      asyncLSRFramingError |
235                                      asyncLSROverrunError |
236                                      asyncLSRParityError  |
237                                      asyncLSRBreakInterrupt );
238                 }
239         }
240         return (0x000000ff & (int) in8 (asyncRxBufferport1));
241 }
242
243 int serial_tstc ()
244 {
245         unsigned char status;
246
247         status = in8 (asyncLSRport1);
248         if ((status & asyncLSRDataReady) != 0x0) {
249                 return (1);
250         }
251         if ((status & ( asyncLSRFramingError |
252                         asyncLSROverrunError |
253                         asyncLSRParityError  |
254                         asyncLSRBreakInterrupt )) != 0) {
255                 (void) out8 (asyncLSRport1,
256                              asyncLSRFramingError |
257                              asyncLSROverrunError |
258                              asyncLSRParityError  |
259                              asyncLSRBreakInterrupt);
260         }
261         return 0;
262 }
263
264 #endif  /* CONFIG_IOP480 */
265
266 /*****************************************************************************/
267 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
268     defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
269     defined(CONFIG_440)
270
271 #if defined(CONFIG_440)
272 #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
273     defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
274 #define UART0_BASE  CFG_PERIPHERAL_BASE + 0x00000300
275 #define UART1_BASE  CFG_PERIPHERAL_BASE + 0x00000400
276 #else
277 #define UART0_BASE  CFG_PERIPHERAL_BASE + 0x00000200
278 #define UART1_BASE  CFG_PERIPHERAL_BASE + 0x00000300
279 #endif
280
281 #if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
282 #define UART2_BASE  CFG_PERIPHERAL_BASE + 0x00000600
283 #endif
284
285 #if defined(CONFIG_440GP)
286 #define CR0_MASK        0x3fff0000
287 #define CR0_EXTCLK_ENA  0x00600000
288 #define CR0_UDIV_POS    16
289 #define UDIV_SUBTRACT   1
290 #define UART0_SDR       cntrl0
291 #define MFREG(a, d)     d = mfdcr(a)
292 #define MTREG(a, d)     mtdcr(a, d)
293 #else /* #if defined(CONFIG_440GP) */
294 /* all other 440 PPC's access clock divider via sdr register */
295 #define CR0_MASK        0xdfffffff
296 #define CR0_EXTCLK_ENA  0x00800000
297 #define CR0_UDIV_POS    0
298 #define UDIV_SUBTRACT   0
299 #define UART0_SDR       sdr_uart0
300 #define UART1_SDR       sdr_uart1
301 #if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
302     defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \
303     defined(CONFIG_440SP) || defined(CONFIG_440SPe)
304 #define UART2_SDR       sdr_uart2
305 #endif
306 #if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
307     defined(CONFIG_440GR) || defined(CONFIG_440GRx)
308 #define UART3_SDR       sdr_uart3
309 #endif
310 #define MFREG(a, d)     mfsdr(a, d)
311 #define MTREG(a, d)     mtsdr(a, d)
312 #endif /* #if defined(CONFIG_440GP) */
313 #elif defined(CONFIG_405EP) || defined(CONFIG_405EZ)
314 #define UART0_BASE      0xef600300
315 #define UART1_BASE      0xef600400
316 #define UCR0_MASK       0x0000007f
317 #define UCR1_MASK       0x00007f00
318 #define UCR0_UDIV_POS   0
319 #define UCR1_UDIV_POS   8
320 #define UDIV_MAX        127
321 #else /* CONFIG_405GP || CONFIG_405CR */
322 #define UART0_BASE      0xef600300
323 #define UART1_BASE      0xef600400
324 #define CR0_MASK        0x00001fff
325 #define CR0_EXTCLK_ENA  0x000000c0
326 #define CR0_UDIV_POS    1
327 #define UDIV_MAX        32
328 #endif
329
330 /* using serial port 0 or 1 as U-Boot console ? */
331 #if defined(CONFIG_UART1_CONSOLE)
332 #define ACTING_UART0_BASE       UART1_BASE
333 #define ACTING_UART1_BASE       UART0_BASE
334 #else
335 #define ACTING_UART0_BASE       UART0_BASE
336 #define ACTING_UART1_BASE       UART1_BASE
337 #endif
338
339 #if defined(CONFIG_SERIAL_MULTI)
340 #define UART_BASE       dev_base
341 #else
342 #define UART_BASE       ACTING_UART0_BASE
343 #endif
344
345 #if defined(CONFIG_405EP) && defined(CFG_EXT_SERIAL_CLOCK)
346 #error "External serial clock not supported on AMCC PPC405EP!"
347 #endif
348
349 #define UART_RBR    0x00
350 #define UART_THR    0x00
351 #define UART_IER    0x01
352 #define UART_IIR    0x02
353 #define UART_FCR    0x02
354 #define UART_LCR    0x03
355 #define UART_MCR    0x04
356 #define UART_LSR    0x05
357 #define UART_MSR    0x06
358 #define UART_SCR    0x07
359 #define UART_DLL    0x00
360 #define UART_DLM    0x01
361
362 /*-----------------------------------------------------------------------------+
363   | Line Status Register.
364   +-----------------------------------------------------------------------------*/
365 /*#define asyncLSRport1           ACTING_UART0_BASE+0x05 */
366 #define asyncLSRDataReady1            0x01
367 #define asyncLSROverrunError1         0x02
368 #define asyncLSRParityError1          0x04
369 #define asyncLSRFramingError1         0x08
370 #define asyncLSRBreakInterrupt1       0x10
371 #define asyncLSRTxHoldEmpty1          0x20
372 #define asyncLSRTxShiftEmpty1         0x40
373 #define asyncLSRRxFifoError1          0x80
374
375 /*-----------------------------------------------------------------------------+
376   | Miscellanies defines.
377   +-----------------------------------------------------------------------------*/
378 /*#define asyncTxBufferport1      ACTING_UART0_BASE+0x00 */
379 /*#define asyncRxBufferport1      ACTING_UART0_BASE+0x00 */
380
381 #ifdef CONFIG_SERIAL_SOFTWARE_FIFO
382 /*-----------------------------------------------------------------------------+
383   | Fifo
384   +-----------------------------------------------------------------------------*/
385 typedef struct {
386         char *rx_buffer;
387         ulong rx_put;
388         ulong rx_get;
389 } serial_buffer_t;
390
391 volatile static serial_buffer_t buf_info;
392 #endif
393
394 #if defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLOCK)
395 static void serial_divs (int baudrate, unsigned long *pudiv,
396                          unsigned short *pbdiv)
397 {
398         sys_info_t sysinfo;
399         unsigned long div;              /* total divisor udiv * bdiv */
400         unsigned long umin;             /* minimum udiv */
401         unsigned short diff;            /* smallest diff */
402         unsigned long udiv;             /* best udiv */
403         unsigned short idiff;           /* current diff */
404         unsigned short ibdiv;           /* current bdiv */
405         unsigned long i;
406         unsigned long est;              /* current estimate */
407
408         get_sys_info(&sysinfo);
409
410         udiv = 32;                      /* Assume lowest possible serial clk */
411         div = sysinfo.freqPLB / (16 * baudrate); /* total divisor */
412         umin = sysinfo.pllOpbDiv << 1;  /* 2 x OPB divisor */
413         diff = 32;                      /* highest possible */
414
415         /* i is the test udiv value -- start with the largest
416          * possible (32) to minimize serial clock and constrain
417          * search to umin.
418          */
419         for (i = 32; i > umin; i--) {
420                 ibdiv = div / i;
421                 est = i * ibdiv;
422                 idiff = (est > div) ? (est-div) : (div-est);
423                 if (idiff == 0) {
424                         udiv = i;
425                         break;      /* can't do better */
426                 } else if (idiff < diff) {
427                         udiv = i;       /* best so far */
428                         diff = idiff;   /* update lowest diff*/
429                 }
430         }
431
432         *pudiv = udiv;
433         *pbdiv = div / udiv;
434 }
435
436 #elif defined(CONFIG_405EZ)
437
438 static void serial_divs (int baudrate, unsigned long *pudiv,
439                          unsigned short *pbdiv)
440 {
441         sys_info_t sysinfo;
442         unsigned long div;              /* total divisor udiv * bdiv */
443         unsigned long umin;             /* minimum udiv */
444         unsigned short diff;            /* smallest diff */
445         unsigned long udiv;             /* best udiv */
446         unsigned short idiff;           /* current diff */
447         unsigned short ibdiv;           /* current bdiv */
448         unsigned long i;
449         unsigned long est;              /* current estimate */
450         unsigned long plloutb;
451         unsigned long cpr_pllc;
452         u32 reg;
453
454         /* check the pll feedback source */
455         mfcpr(cprpllc, cpr_pllc);
456
457         get_sys_info(&sysinfo);
458
459         plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
460                 sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) * sysinfo.pllFbkDiv) /
461                 sysinfo.pllFwdDivB);
462         udiv = 256;                     /* Assume lowest possible serial clk */
463         div = plloutb / (16 * baudrate); /* total divisor */
464         umin = (plloutb / get_OPB_freq()) << 1; /* 2 x OPB divisor */
465         diff = 256;                     /* highest possible */
466
467         /* i is the test udiv value -- start with the largest
468          * possible (256) to minimize serial clock and constrain
469          * search to umin.
470          */
471         for (i = 256; i > umin; i--) {
472                 ibdiv = div / i;
473                 est = i * ibdiv;
474                 idiff = (est > div) ? (est-div) : (div-est);
475                 if (idiff == 0) {
476                         udiv = i;
477                         break;      /* can't do better */
478                 } else if (idiff < diff) {
479                         udiv = i;       /* best so far */
480                         diff = idiff;   /* update lowest diff*/
481                 }
482         }
483
484         *pudiv = udiv;
485         mfcpr(cprperd0, reg);
486         reg &= ~0x0000ffff;
487         reg |= ((udiv - 0) << 8) | (udiv - 0);
488         mtcpr(cprperd0, reg);
489         *pbdiv = div / udiv;
490 }
491 #endif /* defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLK) */
492
493 /*
494  * Minimal serial functions needed to use one of the SMC ports
495  * as serial console interface.
496  */
497
498 #if defined(CONFIG_440)
499 #if defined(CONFIG_SERIAL_MULTI)
500 int serial_init_dev (unsigned long dev_base)
501 #else
502 int serial_init(void)
503 #endif
504 {
505         unsigned long reg;
506         unsigned long udiv;
507         unsigned short bdiv;
508         volatile char val;
509 #ifdef CFG_EXT_SERIAL_CLOCK
510         unsigned long tmp;
511 #endif
512
513         MFREG(UART0_SDR, reg);
514         reg &= ~CR0_MASK;
515
516 #ifdef CFG_EXT_SERIAL_CLOCK
517         reg |= CR0_EXTCLK_ENA;
518         udiv = 1;
519         tmp  = gd->baudrate * 16;
520         bdiv = (CFG_EXT_SERIAL_CLOCK + tmp / 2) / tmp;
521 #else
522         /* For 440, the cpu clock is on divider chain A, UART on divider
523          * chain B ... so cpu clock is irrelevant. Get the "optimized"
524          * values that are subject to the 1/2 opb clock constraint
525          */
526         serial_divs (gd->baudrate, &udiv, &bdiv);
527 #endif
528
529         reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS;  /* set the UART divisor */
530
531         /*
532          * Configure input clock to baudrate generator for all
533          * available serial ports here
534          */
535         MTREG(UART0_SDR, reg);
536 #if defined(UART1_SDR)
537         MTREG(UART1_SDR, reg);
538 #endif
539 #if defined(UART2_SDR)
540         MTREG(UART2_SDR, reg);
541 #endif
542 #if defined(UART3_SDR)
543         MTREG(UART3_SDR, reg);
544 #endif
545
546         out8(UART_BASE + UART_LCR, 0x80);       /* set DLAB bit */
547         out8(UART_BASE + UART_DLL, bdiv);       /* set baudrate divisor */
548         out8(UART_BASE + UART_DLM, bdiv >> 8);  /* set baudrate divisor */
549         out8(UART_BASE + UART_LCR, 0x03);       /* clear DLAB; set 8 bits, no parity */
550         out8(UART_BASE + UART_FCR, 0x00);       /* disable FIFO */
551         out8(UART_BASE + UART_MCR, 0x00);       /* no modem control DTR RTS */
552         val = in8(UART_BASE + UART_LSR);        /* clear line status */
553         val = in8(UART_BASE + UART_RBR);        /* read receive buffer */
554         out8(UART_BASE + UART_SCR, 0x00);       /* set scratchpad */
555         out8(UART_BASE + UART_IER, 0x00);       /* set interrupt enable reg */
556
557         return (0);
558 }
559
560 #else /* !defined(CONFIG_440) */
561
562 #if defined(CONFIG_SERIAL_MULTI)
563 int serial_init_dev (unsigned long dev_base)
564 #else
565 int serial_init (void)
566 #endif
567 {
568         unsigned long reg;
569         unsigned long tmp;
570         unsigned long clk;
571         unsigned long udiv;
572         unsigned short bdiv;
573         volatile char val;
574
575 #if defined(CONFIG_405EZ)
576         serial_divs(gd->baudrate, &udiv, &bdiv);
577         clk = tmp = reg = 0;
578 #else
579 #ifdef CONFIG_405EP
580         reg = mfdcr(cpc0_ucr) & ~(UCR0_MASK | UCR1_MASK);
581         clk = gd->cpu_clk;
582         tmp = CFG_BASE_BAUD * 16;
583         udiv = (clk + tmp / 2) / tmp;
584         if (udiv > UDIV_MAX)                    /* max. n bits for udiv */
585                 udiv = UDIV_MAX;
586         reg |= (udiv) << UCR0_UDIV_POS;         /* set the UART divisor */
587         reg |= (udiv) << UCR1_UDIV_POS;         /* set the UART divisor */
588         mtdcr (cpc0_ucr, reg);
589 #else /* CONFIG_405EP */
590         reg = mfdcr(cntrl0) & ~CR0_MASK;
591 #ifdef CFG_EXT_SERIAL_CLOCK
592         clk = CFG_EXT_SERIAL_CLOCK;
593         udiv = 1;
594         reg |= CR0_EXTCLK_ENA;
595 #else
596         clk = gd->cpu_clk;
597 #ifdef CFG_405_UART_ERRATA_59
598         udiv = 31;                      /* Errata 59: stuck at 31 */
599 #else
600         tmp = CFG_BASE_BAUD * 16;
601         udiv = (clk + tmp / 2) / tmp;
602         if (udiv > UDIV_MAX)                    /* max. n bits for udiv */
603                 udiv = UDIV_MAX;
604 #endif
605 #endif
606         reg |= (udiv - 1) << CR0_UDIV_POS;      /* set the UART divisor */
607         mtdcr (cntrl0, reg);
608 #endif /* CONFIG_405EP */
609         tmp = gd->baudrate * udiv * 16;
610         bdiv = (clk + tmp / 2) / tmp;
611 #endif /* CONFIG_405EZ */
612
613         out8(UART_BASE + UART_LCR, 0x80);       /* set DLAB bit */
614         out8(UART_BASE + UART_DLL, bdiv);       /* set baudrate divisor */
615         out8(UART_BASE + UART_DLM, bdiv >> 8);  /* set baudrate divisor */
616         out8(UART_BASE + UART_LCR, 0x03);       /* clear DLAB; set 8 bits, no parity */
617         out8(UART_BASE + UART_FCR, 0x00);       /* disable FIFO */
618         out8(UART_BASE + UART_MCR, 0x00);       /* no modem control DTR RTS */
619         val = in8(UART_BASE + UART_LSR);        /* clear line status */
620         val = in8(UART_BASE + UART_RBR);        /* read receive buffer */
621         out8(UART_BASE + UART_SCR, 0x00);       /* set scratchpad */
622         out8(UART_BASE + UART_IER, 0x00);       /* set interrupt enable reg */
623
624         return (0);
625 }
626
627 #endif /* if defined(CONFIG_440) */
628
629 #if defined(CONFIG_SERIAL_MULTI)
630 void serial_setbrg_dev (unsigned long dev_base)
631 #else
632 void serial_setbrg (void)
633 #endif
634 {
635 #if defined(CONFIG_SERIAL_MULTI)
636         serial_init_dev(dev_base);
637 #else
638         serial_init();
639 #endif
640 }
641
642 #if defined(CONFIG_SERIAL_MULTI)
643 void serial_putc_dev (unsigned long dev_base, const char c)
644 #else
645 void serial_putc (const char c)
646 #endif
647 {
648         int i;
649
650         if (c == '\n')
651 #if defined(CONFIG_SERIAL_MULTI)
652                 serial_putc_dev (dev_base, '\r');
653 #else
654                 serial_putc ('\r');
655 #endif
656
657         /* check THRE bit, wait for transmiter available */
658         for (i = 1; i < 3500; i++) {
659                 if ((in8 (UART_BASE + UART_LSR) & 0x20) == 0x20)
660                         break;
661                 udelay (100);
662         }
663         out8 (UART_BASE + UART_THR, c); /* put character out */
664 }
665
666 #if defined(CONFIG_SERIAL_MULTI)
667 void serial_puts_dev (unsigned long dev_base, const char *s)
668 #else
669 void serial_puts (const char *s)
670 #endif
671 {
672         while (*s) {
673 #if defined(CONFIG_SERIAL_MULTI)
674                 serial_putc_dev (dev_base, *s++);
675 #else
676                 serial_putc (*s++);
677 #endif
678         }
679 }
680
681 #if defined(CONFIG_SERIAL_MULTI)
682 int serial_getc_dev (unsigned long dev_base)
683 #else
684 int serial_getc (void)
685 #endif
686 {
687         unsigned char status = 0;
688
689         while (1) {
690 #if defined(CONFIG_HW_WATCHDOG)
691                 WATCHDOG_RESET ();      /* Reset HW Watchdog, if needed */
692 #endif  /* CONFIG_HW_WATCHDOG */
693                 status = in8 (UART_BASE + UART_LSR);
694                 if ((status & asyncLSRDataReady1) != 0x0) {
695                         break;
696                 }
697                 if ((status & ( asyncLSRFramingError1 |
698                                 asyncLSROverrunError1 |
699                                 asyncLSRParityError1  |
700                                 asyncLSRBreakInterrupt1 )) != 0) {
701                         out8 (UART_BASE + UART_LSR,
702                               asyncLSRFramingError1 |
703                               asyncLSROverrunError1 |
704                               asyncLSRParityError1  |
705                               asyncLSRBreakInterrupt1);
706                 }
707         }
708         return (0x000000ff & (int) in8 (UART_BASE));
709 }
710
711 #if defined(CONFIG_SERIAL_MULTI)
712 int serial_tstc_dev (unsigned long dev_base)
713 #else
714 int serial_tstc (void)
715 #endif
716 {
717         unsigned char status;
718
719         status = in8 (UART_BASE + UART_LSR);
720         if ((status & asyncLSRDataReady1) != 0x0) {
721                 return (1);
722         }
723         if ((status & ( asyncLSRFramingError1 |
724                         asyncLSROverrunError1 |
725                         asyncLSRParityError1  |
726                         asyncLSRBreakInterrupt1 )) != 0) {
727                 out8 (UART_BASE + UART_LSR,
728                       asyncLSRFramingError1 |
729                       asyncLSROverrunError1 |
730                       asyncLSRParityError1  |
731                       asyncLSRBreakInterrupt1);
732         }
733         return 0;
734 }
735
736 #ifdef CONFIG_SERIAL_SOFTWARE_FIFO
737
738 void serial_isr (void *arg)
739 {
740         int space;
741         int c;
742         const int rx_get = buf_info.rx_get;
743         int rx_put = buf_info.rx_put;
744
745         if (rx_get <= rx_put) {
746                 space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
747         } else {
748                 space = rx_get - rx_put;
749         }
750         while (serial_tstc_dev (ACTING_UART0_BASE)) {
751                 c = serial_getc_dev (ACTING_UART0_BASE);
752                 if (space) {
753                         buf_info.rx_buffer[rx_put++] = c;
754                         space--;
755                 }
756                 if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO)
757                         rx_put = 0;
758                 if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
759                         /* Stop flow by setting RTS inactive */
760                         out8 (ACTING_UART0_BASE + UART_MCR,
761                               in8 (ACTING_UART0_BASE + UART_MCR) & (0xFF ^ 0x02));
762                 }
763         }
764         buf_info.rx_put = rx_put;
765 }
766
767 void serial_buffered_init (void)
768 {
769         serial_puts ("Switching to interrupt driven serial input mode.\n");
770         buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
771         buf_info.rx_put = 0;
772         buf_info.rx_get = 0;
773
774         if (in8 (ACTING_UART0_BASE + UART_MSR) & 0x10) {
775                 serial_puts ("Check CTS signal present on serial port: OK.\n");
776         } else {
777                 serial_puts ("WARNING: CTS signal not present on serial port.\n");
778         }
779
780         irq_install_handler ( VECNUM_U0 /*UART0 */ /*int vec */ ,
781                               serial_isr /*interrupt_handler_t *handler */ ,
782                               (void *) &buf_info /*void *arg */ );
783
784         /* Enable "RX Data Available" Interrupt on UART */
785         /* out8(ACTING_UART0_BASE + UART_IER, in8(ACTING_UART0_BASE + UART_IER) |0x01); */
786         out8 (ACTING_UART0_BASE + UART_IER, 0x01);
787         /* Set DTR active */
788         out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x01);
789         /* Start flow by setting RTS active */
790         out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x02);
791         /* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */
792         out8 (ACTING_UART0_BASE + UART_FCR, (1 << 6) | 1);
793 }
794
795 void serial_buffered_putc (const char c)
796 {
797         /* Wait for CTS */
798 #if defined(CONFIG_HW_WATCHDOG)
799         while (!(in8 (ACTING_UART0_BASE + UART_MSR) & 0x10))
800                 WATCHDOG_RESET ();
801 #else
802         while (!(in8 (ACTING_UART0_BASE + UART_MSR) & 0x10));
803 #endif
804         serial_putc (c);
805 }
806
807 void serial_buffered_puts (const char *s)
808 {
809         serial_puts (s);
810 }
811
812 int serial_buffered_getc (void)
813 {
814         int space;
815         int c;
816         int rx_get = buf_info.rx_get;
817         int rx_put;
818
819 #if defined(CONFIG_HW_WATCHDOG)
820         while (rx_get == buf_info.rx_put)
821                 WATCHDOG_RESET ();
822 #else
823         while (rx_get == buf_info.rx_put);
824 #endif
825         c = buf_info.rx_buffer[rx_get++];
826         if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO)
827                 rx_get = 0;
828         buf_info.rx_get = rx_get;
829
830         rx_put = buf_info.rx_put;
831         if (rx_get <= rx_put) {
832                 space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
833         } else {
834                 space = rx_get - rx_put;
835         }
836         if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) {
837                 /* Start flow by setting RTS active */
838                 out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x02);
839         }
840
841         return c;
842 }
843
844 int serial_buffered_tstc (void)
845 {
846         return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
847 }
848
849 #endif  /* CONFIG_SERIAL_SOFTWARE_FIFO */
850
851 #if defined(CONFIG_CMD_KGDB)
852 /*
853   AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
854   number 0 or number 1
855   - if CONFIG_KGDB_SER_INDEX = 1 => serial port number 0 :
856   configuration has been already done
857   - if CONFIG_KGDB_SER_INDEX = 2 => serial port number 1 :
858   configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE
859 */
860 #if (CONFIG_KGDB_SER_INDEX & 2)
861 void kgdb_serial_init (void)
862 {
863         volatile char val;
864         unsigned short br_reg;
865
866         get_clocks ();
867         br_reg = (((((gd->cpu_clk / 16) / 18) * 10) / CONFIG_KGDB_BAUDRATE) +
868                   5) / 10;
869         /*
870          * Init onboard 16550 UART
871          */
872         out8 (ACTING_UART1_BASE + UART_LCR, 0x80);      /* set DLAB bit */
873         out8 (ACTING_UART1_BASE + UART_DLL, (br_reg & 0x00ff)); /* set divisor for 9600 baud */
874         out8 (ACTING_UART1_BASE + UART_DLM, ((br_reg & 0xff00) >> 8));  /* set divisor for 9600 baud */
875         out8 (ACTING_UART1_BASE + UART_LCR, 0x03);      /* line control 8 bits no parity */
876         out8 (ACTING_UART1_BASE + UART_FCR, 0x00);      /* disable FIFO */
877         out8 (ACTING_UART1_BASE + UART_MCR, 0x00);      /* no modem control DTR RTS */
878         val = in8 (ACTING_UART1_BASE + UART_LSR);       /* clear line status */
879         val = in8 (ACTING_UART1_BASE + UART_RBR);       /* read receive buffer */
880         out8 (ACTING_UART1_BASE + UART_SCR, 0x00);      /* set scratchpad */
881         out8 (ACTING_UART1_BASE + UART_IER, 0x00);      /* set interrupt enable reg */
882 }
883
884 void putDebugChar (const char c)
885 {
886         if (c == '\n')
887                 serial_putc ('\r');
888
889         out8 (ACTING_UART1_BASE + UART_THR, c); /* put character out */
890
891         /* check THRE bit, wait for transfer done */
892         while ((in8 (ACTING_UART1_BASE + UART_LSR) & 0x20) != 0x20);
893 }
894
895 void putDebugStr (const char *s)
896 {
897         while (*s) {
898                 serial_putc (*s++);
899         }
900 }
901
902 int getDebugChar (void)
903 {
904         unsigned char status = 0;
905
906         while (1) {
907                 status = in8 (ACTING_UART1_BASE + UART_LSR);
908                 if ((status & asyncLSRDataReady1) != 0x0) {
909                         break;
910                 }
911                 if ((status & ( asyncLSRFramingError1 |
912                                 asyncLSROverrunError1 |
913                                 asyncLSRParityError1  |
914                                 asyncLSRBreakInterrupt1 )) != 0) {
915                         out8 (ACTING_UART1_BASE + UART_LSR,
916                               asyncLSRFramingError1 |
917                               asyncLSROverrunError1 |
918                               asyncLSRParityError1  |
919                               asyncLSRBreakInterrupt1);
920                 }
921         }
922         return (0x000000ff & (int) in8 (ACTING_UART1_BASE));
923 }
924
925 void kgdb_interruptible (int yes)
926 {
927         return;
928 }
929
930 #else   /* ! (CONFIG_KGDB_SER_INDEX & 2) */
931
932 void kgdb_serial_init (void)
933 {
934         serial_printf ("[on serial] ");
935 }
936
937 void putDebugChar (int c)
938 {
939         serial_putc (c);
940 }
941
942 void putDebugStr (const char *str)
943 {
944         serial_puts (str);
945 }
946
947 int getDebugChar (void)
948 {
949         return serial_getc ();
950 }
951
952 void kgdb_interruptible (int yes)
953 {
954         return;
955 }
956 #endif  /* (CONFIG_KGDB_SER_INDEX & 2) */
957 #endif
958
959
960 #if defined(CONFIG_SERIAL_MULTI)
961 int serial0_init(void)
962 {
963         return (serial_init_dev(UART0_BASE));
964 }
965
966 int serial1_init(void)
967 {
968         return (serial_init_dev(UART1_BASE));
969 }
970 void serial0_setbrg (void)
971 {
972         serial_setbrg_dev(UART0_BASE);
973 }
974 void serial1_setbrg (void)
975 {
976         serial_setbrg_dev(UART1_BASE);
977 }
978
979 void serial0_putc(const char c)
980 {
981         serial_putc_dev(UART0_BASE,c);
982 }
983
984 void serial1_putc(const char c)
985 {
986         serial_putc_dev(UART1_BASE, c);
987 }
988 void serial0_puts(const char *s)
989 {
990         serial_puts_dev(UART0_BASE, s);
991 }
992
993 void serial1_puts(const char *s)
994 {
995         serial_puts_dev(UART1_BASE, s);
996 }
997
998 int serial0_getc(void)
999 {
1000         return(serial_getc_dev(UART0_BASE));
1001 }
1002
1003 int serial1_getc(void)
1004 {
1005         return(serial_getc_dev(UART1_BASE));
1006 }
1007 int serial0_tstc(void)
1008 {
1009         return (serial_tstc_dev(UART0_BASE));
1010 }
1011
1012 int serial1_tstc(void)
1013 {
1014         return (serial_tstc_dev(UART1_BASE));
1015 }
1016
1017 struct serial_device serial0_device =
1018 {
1019         "serial0",
1020         "UART0",
1021         serial0_init,
1022         serial0_setbrg,
1023         serial0_getc,
1024         serial0_tstc,
1025         serial0_putc,
1026         serial0_puts,
1027 };
1028
1029 struct serial_device serial1_device =
1030 {
1031         "serial1",
1032         "UART1",
1033         serial1_init,
1034         serial1_setbrg,
1035         serial1_getc,
1036         serial1_tstc,
1037         serial1_putc,
1038         serial1_puts,
1039 };
1040 #endif /* CONFIG_SERIAL_MULTI */
1041
1042 #endif  /* CONFIG_405GP || CONFIG_405CR */