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