blob: 2871084fcdd4be978e75316bc989c13c8ae43299 [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>
wdenkd0fb80c2003-01-11 09:48:40 +000027#include <watchdog.h>
wdenk4a9cbbe2002-08-27 09:48:53 +000028
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
78int 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
229void
230serial_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
249void
250serial_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;
wdenk4a9cbbe2002-08-27 09:48:53 +0000269
270 *buf = c;
271 tbdf->cbd_datlen = 1;
272 tbdf->cbd_sc |= BD_SC_READY;
273 __asm__("eieio");
wdenkd0fb80c2003-01-11 09:48:40 +0000274
275 while (tbdf->cbd_sc & BD_SC_READY) {
276 WATCHDOG_RESET ();
wdenk4a9cbbe2002-08-27 09:48:53 +0000277 __asm__("eieio");
wdenkd0fb80c2003-01-11 09:48:40 +0000278 }
wdenk4a9cbbe2002-08-27 09:48:53 +0000279}
280
281int
282serial_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;
wdenkd0fb80c2003-01-11 09:48:40 +0000298
wdenk4a9cbbe2002-08-27 09:48:53 +0000299 while (rbdf->cbd_sc & BD_SC_EMPTY)
wdenkd0fb80c2003-01-11 09:48:40 +0000300 WATCHDOG_RESET ();
301
wdenk4a9cbbe2002-08-27 09:48:53 +0000302 c = *buf;
303 rbdf->cbd_sc |= BD_SC_EMPTY;
304
305 return(c);
306}
307
308int
309serial_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
325int 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
485void
486serial_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
506void
507serial_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;
wdenk4a9cbbe2002-08-27 09:48:53 +0000526
527 *buf = c;
528 tbdf->cbd_datlen = 1;
529 tbdf->cbd_sc |= BD_SC_READY;
530 __asm__("eieio");
wdenkd0fb80c2003-01-11 09:48:40 +0000531
532 while (tbdf->cbd_sc & BD_SC_READY) {
wdenk4a9cbbe2002-08-27 09:48:53 +0000533 __asm__("eieio");
wdenkd0fb80c2003-01-11 09:48:40 +0000534 WATCHDOG_RESET ();
535 }
wdenk4a9cbbe2002-08-27 09:48:53 +0000536}
537
538int
539serial_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;
wdenkd0fb80c2003-01-11 09:48:40 +0000555
wdenk4a9cbbe2002-08-27 09:48:53 +0000556 while (rbdf->cbd_sc & BD_SC_EMPTY)
wdenkd0fb80c2003-01-11 09:48:40 +0000557 WATCHDOG_RESET ();
558
wdenk4a9cbbe2002-08-27 09:48:53 +0000559 c = *buf;
560 rbdf->cbd_sc |= BD_SC_EMPTY;
561
562 return(c);
563}
564
565int
566serial_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
583void
584serial_puts (const char *s)
585{
586 while (*s) {
587 serial_putc (*s++);
588 }
589}
590
591
592#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
593
594void
595kgdb_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
612void
613putDebugChar (int c)
614{
615 serial_putc (c);
616}
617
618void
619putDebugStr (const char *str)
620{
621 serial_puts (str);
622}
623
624int
625getDebugChar (void)
626{
627 return serial_getc();
628}
629
630void
631kgdb_interruptible (int yes)
632{
633 return;
634}
635#endif /* CFG_CMD_KGDB */
636
637#endif /* CONFIG_8xx_CONS_NONE */