blob: 0690300b24ebd31ba288a399e41ea54c3eafa88b [file] [log] [blame]
wdenk4a9cbbe2002-08-27 09:48:53 +00001/*
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
77int 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
228void
229serial_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
248void
249serial_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
284int
285serial_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
309int
310serial_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
326int 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
486void
487serial_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
507void
508serial_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
543int
544serial_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
568int
569serial_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
586void
587serial_puts (const char *s)
588{
589 while (*s) {
590 serial_putc (*s++);
591 }
592}
593
594
595#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
596
597void
598kgdb_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
615void
616putDebugChar (int c)
617{
618 serial_putc (c);
619}
620
621void
622putDebugStr (const char *str)
623{
624 serial_puts (str);
625}
626
627int
628getDebugChar (void)
629{
630 return serial_getc();
631}
632
633void
634kgdb_interruptible (int yes)
635{
636 return;
637}
638#endif /* CFG_CMD_KGDB */
639
640#endif /* CONFIG_8xx_CONS_NONE */