]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc8xx/serial.c
2871084fcdd4be978e75316bc989c13c8ae43299
[karo-tx-uboot.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 void
250 serial_putc(const char c)
251 {
252         volatile cbd_t          *tbdf;
253         volatile char           *buf;
254         volatile smc_uart_t     *up;
255         volatile immap_t        *im = (immap_t *)CFG_IMMR;
256         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
257
258         if (c == '\n')
259                 serial_putc ('\r');
260
261         up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
262
263         tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
264
265         /* Wait for last character to go.
266         */
267
268         buf = (char *)tbdf->cbd_bufaddr;
269
270         *buf = c;
271         tbdf->cbd_datlen = 1;
272         tbdf->cbd_sc |= BD_SC_READY;
273         __asm__("eieio");
274
275         while (tbdf->cbd_sc & BD_SC_READY) {
276                 WATCHDOG_RESET ();
277                 __asm__("eieio");
278         }
279 }
280
281 int
282 serial_getc(void)
283 {
284         volatile cbd_t          *rbdf;
285         volatile unsigned char  *buf;
286         volatile smc_uart_t     *up;
287         volatile immap_t        *im = (immap_t *)CFG_IMMR;
288         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
289         unsigned char           c;
290
291         up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
292
293         rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
294
295         /* Wait for character to show up.
296         */
297         buf = (unsigned char *)rbdf->cbd_bufaddr;
298
299         while (rbdf->cbd_sc & BD_SC_EMPTY)
300                 WATCHDOG_RESET ();
301
302         c = *buf;
303         rbdf->cbd_sc |= BD_SC_EMPTY;
304
305         return(c);
306 }
307
308 int
309 serial_tstc()
310 {
311         volatile cbd_t          *rbdf;
312         volatile smc_uart_t     *up;
313         volatile immap_t        *im = (immap_t *)CFG_IMMR;
314         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
315
316         up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
317
318         rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
319
320         return(!(rbdf->cbd_sc & BD_SC_EMPTY));
321 }
322
323 #else   /* ! CONFIG_8xx_CONS_SMC1, CONFIG_8xx_CONS_SMC2 */
324
325 int serial_init (void)
326 {
327         volatile immap_t *im = (immap_t *)CFG_IMMR;
328         volatile scc_t *sp;
329         volatile scc_uart_t *up;
330         volatile cbd_t *tbdf, *rbdf;
331         volatile cpm8xx_t *cp = &(im->im_cpm);
332         uint     dpaddr;
333 #if (SCC_INDEX != 2) || !defined(CONFIG_MPC850)
334         volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
335 #endif
336
337         /* initialize pointers to SCC */
338
339         sp = (scc_t *) &(cp->cp_scc[SCC_INDEX]);
340         up = (scc_uart_t *) &cp->cp_dparam[PROFF_SCC];
341
342 #if defined(CONFIG_LWMON) && defined(CONFIG_8xx_CONS_SCC2)
343     {   /* Disable Ethernet, enable Serial */
344         uchar c;
345
346         c = pic_read  (0x61);
347         c &= ~0x40;     /* enable COM3 */
348         c |=  0x80;     /* disable Ethernet */
349         pic_write (0x61, c);
350
351         /* enable RTS2 */
352         cp->cp_pbpar |=  0x2000;
353         cp->cp_pbdat |=  0x2000;
354         cp->cp_pbdir |=  0x2000;
355     }
356 #endif  /* CONFIG_LWMON */
357
358         /* Disable transmitter/receiver.
359         */
360         sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
361
362 #if (SCC_INDEX == 2) && defined(CONFIG_MPC850)
363         /*
364          * The MPC850 has SCC3 on Port B
365          */
366         cp->cp_pbpar |=  0x06;
367         cp->cp_pbdir &= ~0x06;
368         cp->cp_pbodr &= ~0x06;
369
370 #elif (SCC_INDEX < 2) || !defined(CONFIG_IP860)
371         /*
372          * Standard configuration for SCC's is on Part A
373          */
374         ip->iop_papar |=  ((3 << (2 * SCC_INDEX)));
375         ip->iop_padir &= ~((3 << (2 * SCC_INDEX)));
376         ip->iop_paodr &= ~((3 << (2 * SCC_INDEX)));
377 #else
378         /*
379          * The IP860 has SCC3 and SCC4 on Port D
380          */
381         ip->iop_pdpar |=  ((3 << (2 * SCC_INDEX)));
382 #endif
383
384         /* Allocate space for two buffer descriptors in the DP ram.
385          */
386
387 #ifdef CFG_ALLOC_DPRAM
388         dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
389 #else
390         dpaddr = CPM_SERIAL_BASE ;
391 #endif
392
393         /* Enable SDMA.
394         */
395         im->im_siu_conf.sc_sdcr = 0x0001;
396
397         /* Set the physical address of the host memory buffers in
398          * the buffer descriptors.
399          */
400
401         rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
402         rbdf->cbd_bufaddr = (uint) (rbdf+2);
403         rbdf->cbd_sc = 0;
404         tbdf = rbdf + 1;
405         tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
406         tbdf->cbd_sc = 0;
407
408         /* Set up the baud rate generator.
409         */
410         serial_setbrg ();
411
412         /* Set up the uart parameters in the parameter ram.
413         */
414         up->scc_genscc.scc_rbase = dpaddr;
415         up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
416
417         /* Initialize Tx/Rx parameters.
418         */
419         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
420                 ;
421         cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
422
423         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
424                 ;
425
426         up->scc_genscc.scc_rfcr  = SCC_EB | 0x05;
427         up->scc_genscc.scc_tfcr  = SCC_EB | 0x05;
428
429         up->scc_genscc.scc_mrblr = 1;   /* Single character receive */
430         up->scc_maxidl = 0;             /* disable max idle */
431         up->scc_brkcr  = 1;             /* send one break character on stop TX */
432         up->scc_parec  = 0;
433         up->scc_frmec  = 0;
434         up->scc_nosec  = 0;
435         up->scc_brkec  = 0;
436         up->scc_uaddr1 = 0;
437         up->scc_uaddr2 = 0;
438         up->scc_toseq  = 0;
439         up->scc_char1  = 0x8000;
440         up->scc_char2  = 0x8000;
441         up->scc_char3  = 0x8000;
442         up->scc_char4  = 0x8000;
443         up->scc_char5  = 0x8000;
444         up->scc_char6  = 0x8000;
445         up->scc_char7  = 0x8000;
446         up->scc_char8  = 0x8000;
447         up->scc_rccm   = 0xc0ff;
448
449         /* Set low latency / small fifo.
450          */
451         sp->scc_gsmrh = SCC_GSMRH_RFW;
452
453         /* Set SCC(x) clock mode to 16x
454          * See 8xx_io/commproc.c for details.
455          *
456          * Wire BRG1 to SCCn
457          */
458
459         /* Set UART mode, clock divider 16 on Tx and Rx
460          */
461         sp->scc_gsmrl |=
462                 (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
463
464         sp->scc_psmr  |= SCU_PSMR_CL;
465
466         /* Mask all interrupts and remove anything pending.
467         */
468         sp->scc_sccm = 0;
469         sp->scc_scce = 0xffff;
470         sp->scc_dsr  = 0x7e7e;
471         sp->scc_psmr = 0x3000;
472
473         /* Make the first buffer the only buffer.
474         */
475         tbdf->cbd_sc |= BD_SC_WRAP;
476         rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
477
478         /* Enable transmitter/receiver.
479         */
480         sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
481
482         return (0);
483 }
484
485 void
486 serial_setbrg (void)
487 {
488         DECLARE_GLOBAL_DATA_PTR;
489
490         volatile immap_t *im = (immap_t *)CFG_IMMR;
491         volatile cpm8xx_t *cp = &(im->im_cpm);
492
493         /* Set up the baud rate generator.
494          * See 8xx_io/commproc.c for details.
495          *
496          * Wire BRG1 to SCCx
497          */
498
499         cp->cp_sicr &= ~(0x000000FF << (8 * SCC_INDEX));
500         /* no |= needed, since BRG1 is 000 */
501
502         cp->cp_brgc1 =
503                 (((gd->cpu_clk / 16 / gd->baudrate)-1) << 1) | CPM_BRG_EN;
504 }
505
506 void
507 serial_putc(const char c)
508 {
509         volatile cbd_t          *tbdf;
510         volatile char           *buf;
511         volatile scc_uart_t     *up;
512         volatile immap_t        *im = (immap_t *)CFG_IMMR;
513         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
514
515         if (c == '\n')
516                 serial_putc ('\r');
517
518         up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
519
520         tbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
521
522         /* Wait for last character to go.
523         */
524
525         buf = (char *)tbdf->cbd_bufaddr;
526
527         *buf = c;
528         tbdf->cbd_datlen = 1;
529         tbdf->cbd_sc |= BD_SC_READY;
530         __asm__("eieio");
531
532         while (tbdf->cbd_sc & BD_SC_READY) {
533                 __asm__("eieio");
534                 WATCHDOG_RESET ();
535         }
536 }
537
538 int
539 serial_getc(void)
540 {
541         volatile cbd_t          *rbdf;
542         volatile unsigned char  *buf;
543         volatile scc_uart_t     *up;
544         volatile immap_t        *im = (immap_t *)CFG_IMMR;
545         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
546         unsigned char           c;
547
548         up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
549
550         rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
551
552         /* Wait for character to show up.
553         */
554         buf = (unsigned char *)rbdf->cbd_bufaddr;
555
556         while (rbdf->cbd_sc & BD_SC_EMPTY)
557                 WATCHDOG_RESET ();
558
559         c = *buf;
560         rbdf->cbd_sc |= BD_SC_EMPTY;
561
562         return(c);
563 }
564
565 int
566 serial_tstc()
567 {
568         volatile cbd_t          *rbdf;
569         volatile scc_uart_t     *up;
570         volatile immap_t        *im = (immap_t *)CFG_IMMR;
571         volatile cpm8xx_t       *cpmp = &(im->im_cpm);
572
573         up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
574
575         rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
576
577         return(!(rbdf->cbd_sc & BD_SC_EMPTY));
578 }
579
580 #endif  /* CONFIG_8xx_CONS_SMC1, CONFIG_8xx_CONS_SMC2 */
581
582
583 void
584 serial_puts (const char *s)
585 {
586         while (*s) {
587                 serial_putc (*s++);
588         }
589 }
590
591
592 #if (CONFIG_COMMANDS & CFG_CMD_KGDB)
593
594 void
595 kgdb_serial_init(void)
596 {
597 #if defined(CONFIG_8xx_CONS_SMC1)
598         serial_printf("[on SMC1] ");
599 #elif defined(CONFIG_8xx_CONS_SMC2)
600         serial_printf("[on SMC2] ");
601 #elif defined(CONFIG_8xx_CONS_SCC1)
602         serial_printf("[on SCC1] ");
603 #elif defined(CONFIG_8xx_CONS_SCC2)
604         serial_printf("[on SCC2] ");
605 #elif defined(CONFIG_8xx_CONS_SCC3)
606         serial_printf("[on SCC3] ");
607 #elif defined(CONFIG_8xx_CONS_SCC4)
608         serial_printf("[on SCC4] ");
609 #endif
610 }
611
612 void
613 putDebugChar (int c)
614 {
615         serial_putc (c);
616 }
617
618 void
619 putDebugStr (const char *str)
620 {
621         serial_puts (str);
622 }
623
624 int
625 getDebugChar (void)
626 {
627         return serial_getc();
628 }
629
630 void
631 kgdb_interruptible (int yes)
632 {
633         return;
634 }
635 #endif  /* CFG_CMD_KGDB */
636
637 #endif  /* CONFIG_8xx_CONS_NONE */