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