Merge branch 'master' of git://git.denx.de/u-boot-blackfin
[platform/kernel/u-boot.git] / arch / powerpc / cpu / mpc8xx / serial.c
1 /*
2  * (C) Copyright 2000
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 #include <common.h>
25 #include <commproc.h>
26 #include <command.h>
27 #include <serial.h>
28 #include <watchdog.h>
29 #include <linux/compiler.h>
30
31 DECLARE_GLOBAL_DATA_PTR;
32
33 #if !defined(CONFIG_8xx_CONS_NONE)      /* No Console at all */
34
35 #if defined(CONFIG_8xx_CONS_SMC1)       /* Console on SMC1 */
36 #define SMC_INDEX       0
37 #define PROFF_SMC       PROFF_SMC1
38 #define CPM_CR_CH_SMC   CPM_CR_CH_SMC1
39
40 #elif defined(CONFIG_8xx_CONS_SMC2)     /* Console on SMC2 */
41 #define SMC_INDEX       1
42 #define PROFF_SMC       PROFF_SMC2
43 #define CPM_CR_CH_SMC   CPM_CR_CH_SMC2
44
45 #endif /* CONFIG_8xx_CONS_SMCx */
46
47 #if defined(CONFIG_8xx_CONS_SCC1)       /* Console on SCC1 */
48 #define SCC_INDEX       0
49 #define PROFF_SCC       PROFF_SCC1
50 #define CPM_CR_CH_SCC   CPM_CR_CH_SCC1
51
52 #elif defined(CONFIG_8xx_CONS_SCC2)     /* Console on SCC2 */
53 #define SCC_INDEX       1
54 #define PROFF_SCC       PROFF_SCC2
55 #define CPM_CR_CH_SCC   CPM_CR_CH_SCC2
56
57 #elif defined(CONFIG_8xx_CONS_SCC3)     /* Console on SCC3 */
58 #define SCC_INDEX       2
59 #define PROFF_SCC       PROFF_SCC3
60 #define CPM_CR_CH_SCC   CPM_CR_CH_SCC3
61
62 #elif defined(CONFIG_8xx_CONS_SCC4)     /* Console on SCC4 */
63 #define SCC_INDEX       3
64 #define PROFF_SCC       PROFF_SCC4
65 #define CPM_CR_CH_SCC   CPM_CR_CH_SCC4
66
67 #endif /* CONFIG_8xx_CONS_SCCx */
68
69 #if !defined(CONFIG_SYS_SMC_RXBUFLEN)
70 #define CONFIG_SYS_SMC_RXBUFLEN 1
71 #define CONFIG_SYS_MAXIDLE      0
72 #else
73 #if !defined(CONFIG_SYS_MAXIDLE)
74 #error "you must define CONFIG_SYS_MAXIDLE"
75 #endif
76 #endif
77
78 typedef volatile struct serialbuffer {
79         cbd_t   rxbd;           /* Rx BD */
80         cbd_t   txbd;           /* Tx BD */
81         uint    rxindex;        /* index for next character to read */
82         volatile uchar  rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */
83         volatile uchar  txbuf;  /* tx buffers */
84 } serialbuffer_t;
85
86 static void serial_setdivisor(volatile cpm8xx_t *cp)
87 {
88         int divisor=(gd->cpu_clk + 8*gd->baudrate)/16/gd->baudrate;
89
90         if(divisor/16>0x1000) {
91                 /* bad divisor, assume 50MHz clock and 9600 baud */
92                 divisor=(50*1000*1000 + 8*9600)/16/9600;
93         }
94
95 #ifdef CONFIG_SYS_BRGCLK_PRESCALE
96         divisor /= CONFIG_SYS_BRGCLK_PRESCALE;
97 #endif
98
99         if(divisor<=0x1000) {
100                 cp->cp_brgc1=((divisor-1)<<1) | CPM_BRG_EN;
101         } else {
102                 cp->cp_brgc1=((divisor/16-1)<<1) | CPM_BRG_EN | CPM_BRG_DIV16;
103         }
104 }
105
106 #if (defined (CONFIG_8xx_CONS_SMC1) || defined (CONFIG_8xx_CONS_SMC2))
107
108 /*
109  * Minimal serial functions needed to use one of the SMC ports
110  * as serial console interface.
111  */
112
113 static void smc_setbrg (void)
114 {
115         volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
116         volatile cpm8xx_t *cp = &(im->im_cpm);
117
118         /* Set up the baud rate generator.
119          * See 8xx_io/commproc.c for details.
120          *
121          * Wire BRG1 to SMCx
122          */
123
124         cp->cp_simode = 0x00000000;
125
126         serial_setdivisor(cp);
127 }
128
129 static int smc_init (void)
130 {
131         volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
132         volatile smc_t *sp;
133         volatile smc_uart_t *up;
134         volatile cpm8xx_t *cp = &(im->im_cpm);
135 #if (!defined(CONFIG_8xx_CONS_SMC1)) && (defined(CONFIG_MPC823) || defined(CONFIG_MPC850))
136         volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
137 #endif
138         uint    dpaddr;
139         volatile serialbuffer_t *rtx;
140
141         /* initialize pointers to SMC */
142
143         sp = (smc_t *) &(cp->cp_smc[SMC_INDEX]);
144         up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC];
145 #ifdef CONFIG_SYS_SMC_UCODE_PATCH
146         up = (smc_uart_t *) &cp->cp_dpmem[up->smc_rpbase];
147 #else
148         /* Disable relocation */
149         up->smc_rpbase = 0;
150 #endif
151
152         /* Disable transmitter/receiver. */
153         sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
154
155         /* Enable SDMA. */
156         im->im_siu_conf.sc_sdcr = 1;
157
158         /* clear error conditions */
159 #ifdef  CONFIG_SYS_SDSR
160         im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR;
161 #else
162         im->im_sdma.sdma_sdsr = 0x83;
163 #endif
164
165         /* clear SDMA interrupt mask */
166 #ifdef  CONFIG_SYS_SDMR
167         im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR;
168 #else
169         im->im_sdma.sdma_sdmr = 0x00;
170 #endif
171
172 #if defined(CONFIG_8xx_CONS_SMC1)
173         /* Use Port B for SMC1 instead of other functions. */
174         cp->cp_pbpar |=  0x000000c0;
175         cp->cp_pbdir &= ~0x000000c0;
176         cp->cp_pbodr &= ~0x000000c0;
177 #else   /* CONFIG_8xx_CONS_SMC2 */
178 # if defined(CONFIG_MPC823) || defined(CONFIG_MPC850)
179         /* Use Port A for SMC2 instead of other functions. */
180         ip->iop_papar |=  0x00c0;
181         ip->iop_padir &= ~0x00c0;
182         ip->iop_paodr &= ~0x00c0;
183 # else  /* must be a 860 then */
184         /* Use Port B for SMC2 instead of other functions.
185          */
186         cp->cp_pbpar |=  0x00000c00;
187         cp->cp_pbdir &= ~0x00000c00;
188         cp->cp_pbodr &= ~0x00000c00;
189 # endif
190 #endif
191
192 #if defined(CONFIG_FADS) || defined(CONFIG_ADS)
193         /* Enable RS232 */
194 #if defined(CONFIG_8xx_CONS_SMC1)
195         *((uint *) BCSR1) &= ~BCSR1_RS232EN_1;
196 #else
197         *((uint *) BCSR1) &= ~BCSR1_RS232EN_2;
198 #endif
199 #endif  /* CONFIG_FADS */
200
201 #if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
202         /* Enable Monitor Port Transceiver */
203         *((uchar *) BCSR0) |= BCSR0_ENMONXCVR ;
204 #endif /* CONFIG_RPXLITE */
205
206         /* Set the physical address of the host memory buffers in
207          * the buffer descriptors.
208          */
209
210 #ifdef CONFIG_SYS_ALLOC_DPRAM
211         /* allocate
212          * size of struct serialbuffer with bd rx/tx, buffer rx/tx and rx index
213          */
214         dpaddr = dpram_alloc_align((sizeof(serialbuffer_t)), 8);
215 #else
216         dpaddr = CPM_SERIAL_BASE ;
217 #endif
218
219         rtx = (serialbuffer_t *)&cp->cp_dpmem[dpaddr];
220         /* Allocate space for two buffer descriptors in the DP ram.
221          * For now, this address seems OK, but it may have to
222          * change with newer versions of the firmware.
223          * damm: allocating space after the two buffers for rx/tx data
224          */
225
226         rtx->rxbd.cbd_bufaddr = (uint) &rtx->rxbuf;
227         rtx->rxbd.cbd_sc      = 0;
228
229         rtx->txbd.cbd_bufaddr = (uint) &rtx->txbuf;
230         rtx->txbd.cbd_sc      = 0;
231
232         /* Set up the uart parameters in the parameter ram. */
233         up->smc_rbase = dpaddr;
234         up->smc_tbase = dpaddr+sizeof(cbd_t);
235         up->smc_rfcr = SMC_EB;
236         up->smc_tfcr = SMC_EB;
237 #if defined (CONFIG_SYS_SMC_UCODE_PATCH)
238         up->smc_rbptr = up->smc_rbase;
239         up->smc_tbptr = up->smc_tbase;
240         up->smc_rstate = 0;
241         up->smc_tstate = 0;
242 #endif
243
244 #if defined(CONFIG_MBX)
245         board_serial_init();
246 #endif  /* CONFIG_MBX */
247
248         /* Set UART mode, 8 bit, no parity, one stop.
249          * Enable receive and transmit.
250          */
251         sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
252
253         /* Mask all interrupts and remove anything pending.
254         */
255         sp->smc_smcm = 0;
256         sp->smc_smce = 0xff;
257
258 #ifdef CONFIG_SYS_SPC1920_SMC1_CLK4
259         /* clock source is PLD */
260
261         /* set freq to 19200 Baud */
262         *((volatile uchar *) CONFIG_SYS_SPC1920_PLD_BASE+6) = 0x3;
263         /* configure clk4 as input */
264         im->im_ioport.iop_pdpar |= 0x800;
265         im->im_ioport.iop_pddir &= ~0x800;
266
267         cp->cp_simode = ((cp->cp_simode & ~0xf000) | 0x7000);
268 #else
269         /* Set up the baud rate generator */
270         smc_setbrg ();
271 #endif
272
273         /* Make the first buffer the only buffer. */
274         rtx->txbd.cbd_sc |= BD_SC_WRAP;
275         rtx->rxbd.cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
276
277         /* single/multi character receive. */
278         up->smc_mrblr = CONFIG_SYS_SMC_RXBUFLEN;
279         up->smc_maxidl = CONFIG_SYS_MAXIDLE;
280         rtx->rxindex = 0;
281
282         /* Initialize Tx/Rx parameters. */
283         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
284           ;
285
286         cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
287
288         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
289           ;
290
291         /* Enable transmitter/receiver. */
292         sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
293
294         return (0);
295 }
296
297 static void
298 smc_putc(const char c)
299 {
300         volatile smc_uart_t     *up;
301         volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
302         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
303         volatile serialbuffer_t *rtx;
304
305 #ifdef CONFIG_MODEM_SUPPORT
306         if (gd->be_quiet)
307                 return;
308 #endif
309
310         if (c == '\n')
311                 smc_putc ('\r');
312
313         up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
314 #ifdef CONFIG_SYS_SMC_UCODE_PATCH
315         up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
316 #endif
317
318         rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
319
320         /* Wait for last character to go. */
321         rtx->txbuf = c;
322         rtx->txbd.cbd_datlen = 1;
323         rtx->txbd.cbd_sc |= BD_SC_READY;
324         __asm__("eieio");
325
326         while (rtx->txbd.cbd_sc & BD_SC_READY) {
327                 WATCHDOG_RESET ();
328                 __asm__("eieio");
329         }
330 }
331
332 static void
333 smc_puts (const char *s)
334 {
335         while (*s) {
336                 smc_putc (*s++);
337         }
338 }
339
340 static int
341 smc_getc(void)
342 {
343         volatile smc_uart_t     *up;
344         volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
345         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
346         volatile serialbuffer_t *rtx;
347         unsigned char  c;
348
349         up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
350 #ifdef CONFIG_SYS_SMC_UCODE_PATCH
351         up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
352 #endif
353         rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
354
355         /* Wait for character to show up. */
356         while (rtx->rxbd.cbd_sc & BD_SC_EMPTY)
357                 WATCHDOG_RESET ();
358
359         /* the characters are read one by one,
360          * use the rxindex to know the next char to deliver
361          */
362         c = *(unsigned char *) (rtx->rxbd.cbd_bufaddr+rtx->rxindex);
363         rtx->rxindex++;
364
365         /* check if all char are readout, then make prepare for next receive */
366         if (rtx->rxindex >= rtx->rxbd.cbd_datlen) {
367                 rtx->rxindex = 0;
368                 rtx->rxbd.cbd_sc |= BD_SC_EMPTY;
369         }
370         return(c);
371 }
372
373 static int
374 smc_tstc(void)
375 {
376         volatile smc_uart_t     *up;
377         volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
378         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
379         volatile serialbuffer_t *rtx;
380
381         up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
382 #ifdef CONFIG_SYS_SMC_UCODE_PATCH
383         up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
384 #endif
385
386         rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
387
388         return !(rtx->rxbd.cbd_sc & BD_SC_EMPTY);
389 }
390
391 struct serial_device serial_smc_device =
392 {
393         "serial_smc",
394         smc_init,
395         NULL,
396         smc_setbrg,
397         smc_getc,
398         smc_tstc,
399         smc_putc,
400         smc_puts,
401 };
402
403 #endif /* CONFIG_8xx_CONS_SMC1 || CONFIG_8xx_CONS_SMC2 */
404
405 #if defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) || \
406     defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
407
408 static void
409 scc_setbrg (void)
410 {
411         volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
412         volatile cpm8xx_t *cp = &(im->im_cpm);
413
414         /* Set up the baud rate generator.
415          * See 8xx_io/commproc.c for details.
416          *
417          * Wire BRG1 to SCCx
418          */
419
420         cp->cp_sicr &= ~(0x000000FF << (8 * SCC_INDEX));
421
422         serial_setdivisor(cp);
423 }
424
425 static int scc_init (void)
426 {
427         volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
428         volatile scc_t *sp;
429         volatile scc_uart_t *up;
430         volatile cbd_t *tbdf, *rbdf;
431         volatile cpm8xx_t *cp = &(im->im_cpm);
432         uint     dpaddr;
433 #if (SCC_INDEX != 2) || !defined(CONFIG_MPC850)
434         volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
435 #endif
436
437         /* initialize pointers to SCC */
438
439         sp = (scc_t *) &(cp->cp_scc[SCC_INDEX]);
440         up = (scc_uart_t *) &cp->cp_dparam[PROFF_SCC];
441
442 #if defined(CONFIG_LWMON) && defined(CONFIG_8xx_CONS_SCC2)
443     {   /* Disable Ethernet, enable Serial */
444         uchar c;
445
446         c = pic_read  (0x61);
447         c &= ~0x40;     /* enable COM3 */
448         c |=  0x80;     /* disable Ethernet */
449         pic_write (0x61, c);
450
451         /* enable RTS2 */
452         cp->cp_pbpar |=  0x2000;
453         cp->cp_pbdat |=  0x2000;
454         cp->cp_pbdir |=  0x2000;
455     }
456 #endif  /* CONFIG_LWMON */
457
458         /* Disable transmitter/receiver. */
459         sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
460
461 #if (SCC_INDEX == 2) && defined(CONFIG_MPC850)
462         /*
463          * The MPC850 has SCC3 on Port B
464          */
465         cp->cp_pbpar |=  0x06;
466         cp->cp_pbdir &= ~0x06;
467         cp->cp_pbodr &= ~0x06;
468
469 #elif (SCC_INDEX < 2) || !defined(CONFIG_IP860)
470         /*
471          * Standard configuration for SCC's is on Part A
472          */
473         ip->iop_papar |=  ((3 << (2 * SCC_INDEX)));
474         ip->iop_padir &= ~((3 << (2 * SCC_INDEX)));
475         ip->iop_paodr &= ~((3 << (2 * SCC_INDEX)));
476 #else
477         /*
478          * The IP860 has SCC3 and SCC4 on Port D
479          */
480         ip->iop_pdpar |=  ((3 << (2 * SCC_INDEX)));
481 #endif
482
483         /* Allocate space for two buffer descriptors in the DP ram. */
484
485 #ifdef CONFIG_SYS_ALLOC_DPRAM
486         dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
487 #else
488         dpaddr = CPM_SERIAL2_BASE ;
489 #endif
490
491         /* Enable SDMA. */
492         im->im_siu_conf.sc_sdcr = 0x0001;
493
494         /* Set the physical address of the host memory buffers in
495          * the buffer descriptors.
496          */
497
498         rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
499         rbdf->cbd_bufaddr = (uint) (rbdf+2);
500         rbdf->cbd_sc = 0;
501         tbdf = rbdf + 1;
502         tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
503         tbdf->cbd_sc = 0;
504
505         /* Set up the baud rate generator. */
506         scc_setbrg ();
507
508         /* Set up the uart parameters in the parameter ram. */
509         up->scc_genscc.scc_rbase = dpaddr;
510         up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
511
512         /* Initialize Tx/Rx parameters. */
513         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
514                 ;
515         cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
516
517         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
518                 ;
519
520         up->scc_genscc.scc_rfcr  = SCC_EB | 0x05;
521         up->scc_genscc.scc_tfcr  = SCC_EB | 0x05;
522
523         up->scc_genscc.scc_mrblr = 1;   /* Single character receive */
524         up->scc_maxidl = 0;             /* disable max idle */
525         up->scc_brkcr  = 1;             /* send one break character on stop TX */
526         up->scc_parec  = 0;
527         up->scc_frmec  = 0;
528         up->scc_nosec  = 0;
529         up->scc_brkec  = 0;
530         up->scc_uaddr1 = 0;
531         up->scc_uaddr2 = 0;
532         up->scc_toseq  = 0;
533         up->scc_char1  = 0x8000;
534         up->scc_char2  = 0x8000;
535         up->scc_char3  = 0x8000;
536         up->scc_char4  = 0x8000;
537         up->scc_char5  = 0x8000;
538         up->scc_char6  = 0x8000;
539         up->scc_char7  = 0x8000;
540         up->scc_char8  = 0x8000;
541         up->scc_rccm   = 0xc0ff;
542
543         /* Set low latency / small fifo. */
544         sp->scc_gsmrh = SCC_GSMRH_RFW;
545
546         /* Set SCC(x) clock mode to 16x
547          * See 8xx_io/commproc.c for details.
548          *
549          * Wire BRG1 to SCCn
550          */
551
552         /* Set UART mode, clock divider 16 on Tx and Rx */
553         sp->scc_gsmrl &= ~0xF;
554         sp->scc_gsmrl |=
555                 (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
556
557         sp->scc_psmr  = 0;
558         sp->scc_psmr  |= SCU_PSMR_CL;
559
560         /* Mask all interrupts and remove anything pending. */
561         sp->scc_sccm = 0;
562         sp->scc_scce = 0xffff;
563         sp->scc_dsr  = 0x7e7e;
564         sp->scc_psmr = 0x3000;
565
566         /* Make the first buffer the only buffer. */
567         tbdf->cbd_sc |= BD_SC_WRAP;
568         rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
569
570         /* Enable transmitter/receiver. */
571         sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
572
573         return (0);
574 }
575
576 static void
577 scc_putc(const char c)
578 {
579         volatile cbd_t          *tbdf;
580         volatile char           *buf;
581         volatile scc_uart_t     *up;
582         volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
583         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
584
585 #ifdef CONFIG_MODEM_SUPPORT
586         if (gd->be_quiet)
587                 return;
588 #endif
589
590         if (c == '\n')
591                 scc_putc ('\r');
592
593         up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
594
595         tbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
596
597         /* Wait for last character to go. */
598
599         buf = (char *)tbdf->cbd_bufaddr;
600
601         *buf = c;
602         tbdf->cbd_datlen = 1;
603         tbdf->cbd_sc |= BD_SC_READY;
604         __asm__("eieio");
605
606         while (tbdf->cbd_sc & BD_SC_READY) {
607                 __asm__("eieio");
608                 WATCHDOG_RESET ();
609         }
610 }
611
612 static void
613 scc_puts (const char *s)
614 {
615         while (*s) {
616                 scc_putc (*s++);
617         }
618 }
619
620 static int
621 scc_getc(void)
622 {
623         volatile cbd_t          *rbdf;
624         volatile unsigned char  *buf;
625         volatile scc_uart_t     *up;
626         volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
627         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
628         unsigned char           c;
629
630         up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
631
632         rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
633
634         /* Wait for character to show up. */
635         buf = (unsigned char *)rbdf->cbd_bufaddr;
636
637         while (rbdf->cbd_sc & BD_SC_EMPTY)
638                 WATCHDOG_RESET ();
639
640         c = *buf;
641         rbdf->cbd_sc |= BD_SC_EMPTY;
642
643         return(c);
644 }
645
646 static int
647 scc_tstc(void)
648 {
649         volatile cbd_t          *rbdf;
650         volatile scc_uart_t     *up;
651         volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
652         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
653
654         up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
655
656         rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
657
658         return(!(rbdf->cbd_sc & BD_SC_EMPTY));
659 }
660
661 struct serial_device serial_scc_device =
662 {
663         "serial_scc",
664         scc_init,
665         NULL,
666         scc_setbrg,
667         scc_getc,
668         scc_tstc,
669         scc_putc,
670         scc_puts,
671 };
672
673 #endif  /* CONFIG_8xx_CONS_SCCx */
674
675 __weak struct serial_device *default_serial_console(void)
676 {
677 #if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2)
678         return &serial_smc_device;
679 #else
680         return &serial_scc_device;
681 #endif
682 }
683
684 #ifdef CONFIG_MODEM_SUPPORT
685 void disable_putc(void)
686 {
687         gd->be_quiet = 1;
688 }
689
690 void enable_putc(void)
691 {
692         gd->be_quiet = 0;
693 }
694 #endif
695
696 #if defined(CONFIG_CMD_KGDB)
697
698 void
699 kgdb_serial_init(void)
700 {
701         int i = -1;
702
703         if (strcmp(default_serial_console()->name, "serial_smc") == 0)
704         {
705 #if defined(CONFIG_8xx_CONS_SMC1)
706                 i = 1;
707 #elif defined(CONFIG_8xx_CONS_SMC2)
708                 i = 2;
709 #endif
710         }
711         else if (strcmp(default_serial_console()->name, "serial_scc") == 0)
712         {
713 #if defined(CONFIG_8xx_CONS_SCC1)
714                 i = 1;
715 #elif defined(CONFIG_8xx_CONS_SCC2)
716                 i = 2;
717 #elif defined(CONFIG_8xx_CONS_SCC3)
718                 i = 3;
719 #elif defined(CONFIG_8xx_CONS_SCC4)
720                 i = 4;
721 #endif
722         }
723
724         if (i >= 0)
725         {
726                 serial_printf("[on %s%d] ", default_serial_console()->name, i);
727         }
728 }
729
730 void
731 putDebugChar (int c)
732 {
733         serial_putc (c);
734 }
735
736 void
737 putDebugStr (const char *str)
738 {
739         serial_puts (str);
740 }
741
742 int
743 getDebugChar (void)
744 {
745         return serial_getc();
746 }
747
748 void
749 kgdb_interruptible (int yes)
750 {
751         return;
752 }
753 #endif
754
755 #endif  /* CONFIG_8xx_CONS_NONE */