]> git.ipfire.org Git - people/ms/u-boot.git/blob - cpu/mpc8xx/serial.c
* LWMON extensions:
[people/ms/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 */