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