]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/powerpc/cpu/mpc8260/serial_scc.c
serial: Implement default_serial_puts()
[people/ms/u-boot.git] / arch / powerpc / cpu / mpc8260 / serial_scc.c
CommitLineData
4a9cbbe8
WD
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 * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
24 */
25
26/*
27 * Minimal serial functions needed to use one of the SCC ports
28 * as serial console interface.
29 */
30
31#include <common.h>
32#include <mpc8260.h>
33#include <asm/cpm_8260.h>
d68f4da2
MV
34#include <serial.h>
35#include <linux/compiler.h>
4a9cbbe8 36
d87080b7
WD
37DECLARE_GLOBAL_DATA_PTR;
38
4a9cbbe8
WD
39#if defined(CONFIG_CONS_ON_SCC)
40
41#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
42
43#define SCC_INDEX 0
44#define PROFF_SCC PROFF_SCC1
45#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
46 CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
47#define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
48#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
49#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
50
51#elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
52
53#define SCC_INDEX 1
54#define PROFF_SCC PROFF_SCC2
55#define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
56 CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
57#define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
58#define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
59#define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
60
61#elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
62
63#define SCC_INDEX 2
64#define PROFF_SCC PROFF_SCC3
65#define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
66 CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
67#define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
68#define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
69#define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
70
71#elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
72
73#define SCC_INDEX 3
74#define PROFF_SCC PROFF_SCC4
75#define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
76 CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
77#define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
78#define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
79#define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
80
81#else
82
83#error "console not correctly defined"
84
85#endif
86
d68f4da2 87static int mpc8260_scc_serial_init(void)
4a9cbbe8 88{
6d0f6bcf 89 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
4a9cbbe8
WD
90 volatile scc_t *sp;
91 volatile scc_uart_t *up;
92 volatile cbd_t *tbdf, *rbdf;
93 volatile cpm8260_t *cp = &(im->im_cpm);
94 uint dpaddr;
95
96 /* initialize pointers to SCC */
97
98 sp = (scc_t *) &(im->im_scc[SCC_INDEX]);
99 up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
100
101 /* Disable transmitter/receiver.
102 */
103 sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
104
105 /* put the SCC channel into NMSI (non multiplexd serial interface)
106 * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
107 */
108 im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr&~CMXSCR_MASK)|CMXSCR_VALUE;
109
110 /* Set up the baud rate generator.
111 */
112 serial_setbrg ();
113
114 /* Allocate space for two buffer descriptors in the DP ram.
115 * damm: allocating space after the two buffers for rx/tx data
116 */
117
118 dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
119
120 /* Set the physical address of the host memory buffers in
121 * the buffer descriptors.
122 */
123 rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
124 rbdf->cbd_bufaddr = (uint) (rbdf+2);
125 rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
126 tbdf = rbdf + 1;
127 tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
128 tbdf->cbd_sc = BD_SC_WRAP;
129
130 /* Set up the uart parameters in the parameter ram.
131 */
132 up->scc_genscc.scc_rbase = dpaddr;
133 up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
134 up->scc_genscc.scc_rfcr = CPMFCR_EB;
135 up->scc_genscc.scc_tfcr = CPMFCR_EB;
136 up->scc_genscc.scc_mrblr = 1;
137 up->scc_maxidl = 0;
138 up->scc_brkcr = 1;
139 up->scc_parec = 0;
140 up->scc_frmec = 0;
141 up->scc_nosec = 0;
142 up->scc_brkec = 0;
143 up->scc_uaddr1 = 0;
144 up->scc_uaddr2 = 0;
145 up->scc_toseq = 0;
146 up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
147 up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
148 up->scc_rccm = 0xc0ff;
149
150 /* Mask all interrupts and remove anything pending.
151 */
152 sp->scc_sccm = 0;
153 sp->scc_scce = 0xffff;
154
155 /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
156 */
157 sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
158 sp->scc_gsmrl = \
159 SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
160
161 /* Set CTS flow control, 1 stop bit, 8 bit character length,
162 * normal async UART mode, no parity
163 */
164 sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
165
166 /* execute the "Init Rx and Tx params" CP command.
167 */
168
169 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
170 ;
171
172 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
173 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
174
175 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
176 ;
177
178 /* Enable transmitter/receiver.
179 */
180 sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
181
182 return (0);
183}
184
d68f4da2 185static void mpc8260_scc_serial_setbrg(void)
4a9cbbe8 186{
4a9cbbe8
WD
187#if defined(CONFIG_CONS_USE_EXTC)
188 m8260_cpm_extcbrg(SCC_INDEX, gd->baudrate,
189 CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
190#else
191 m8260_cpm_setbrg(SCC_INDEX, gd->baudrate);
192#endif
193}
194
d68f4da2 195static void mpc8260_scc_serial_putc(const char c)
4a9cbbe8
WD
196{
197 volatile scc_uart_t *up;
198 volatile cbd_t *tbdf;
8bde7f77 199 volatile immap_t *im;
4a9cbbe8
WD
200
201 if (c == '\n')
202 serial_putc ('\r');
203
6d0f6bcf 204 im = (immap_t *)CONFIG_SYS_IMMR;
4a9cbbe8
WD
205 up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
206 tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
207
208 /* Wait for last character to go.
209 */
210 while (tbdf->cbd_sc & BD_SC_READY)
211 ;
212
213 /* Load the character into the transmit buffer.
214 */
215 *(volatile char *)tbdf->cbd_bufaddr = c;
216 tbdf->cbd_datlen = 1;
217 tbdf->cbd_sc |= BD_SC_READY;
218}
219
d68f4da2 220static void mpc8260_scc_serial_puts(const char *s)
4a9cbbe8
WD
221{
222 while (*s) {
223 serial_putc (*s++);
224 }
225}
226
d68f4da2 227static int mpc8260_scc_serial_getc(void)
4a9cbbe8
WD
228{
229 volatile cbd_t *rbdf;
230 volatile scc_uart_t *up;
8bde7f77 231 volatile immap_t *im;
4a9cbbe8
WD
232 unsigned char c;
233
6d0f6bcf 234 im = (immap_t *)CONFIG_SYS_IMMR;
4a9cbbe8
WD
235 up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
236 rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
237
238 /* Wait for character to show up.
239 */
240 while (rbdf->cbd_sc & BD_SC_EMPTY)
241 ;
242
243 /* Grab the char and clear the buffer again.
244 */
245 c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
246 rbdf->cbd_sc |= BD_SC_EMPTY;
247
248 return (c);
249}
250
d68f4da2 251static int mpc8260_scc_serial_tstc(void)
4a9cbbe8
WD
252{
253 volatile cbd_t *rbdf;
254 volatile scc_uart_t *up;
8bde7f77 255 volatile immap_t *im;
4a9cbbe8 256
6d0f6bcf 257 im = (immap_t *)CONFIG_SYS_IMMR;
4a9cbbe8
WD
258 up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
259 rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
260
261 return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
262}
263
d68f4da2
MV
264static struct serial_device mpc8260_scc_serial_drv = {
265 .name = "mpc8260_scc_uart",
266 .start = mpc8260_scc_serial_init,
267 .stop = NULL,
268 .setbrg = mpc8260_scc_serial_setbrg,
269 .putc = mpc8260_scc_serial_putc,
270 .puts = mpc8260_scc_serial_puts,
271 .getc = mpc8260_scc_serial_getc,
272 .tstc = mpc8260_scc_serial_tstc,
273};
274
275void mpc8260_scc_serial_initialize(void)
276{
277 serial_register(&mpc8260_scc_serial_drv);
278}
279
280__weak struct serial_device *default_serial_console(void)
281{
282 return &mpc8260_scc_serial_drv;
283}
4a9cbbe8
WD
284#endif /* CONFIG_CONS_ON_SCC */
285
286#if defined(CONFIG_KGDB_ON_SCC)
287
288#if defined(CONFIG_CONS_ON_SCC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
289#error Whoops! serial console and kgdb are on the same scc serial port
290#endif
291
292#if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SCC1 */
293
294#define KGDB_SCC_INDEX 0
295#define KGDB_PROFF_SCC PROFF_SCC1
296#define KGDB_CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
297 CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
298#define KGDB_CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
299#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
300#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
301
302#elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SCC2 */
303
304#define KGDB_SCC_INDEX 1
305#define KGDB_PROFF_SCC PROFF_SCC2
306#define KGDB_CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
307 CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
308#define KGDB_CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
309#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
310#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
311
312#elif CONFIG_KGDB_INDEX == 3 /* KGDB Port on SCC3 */
313
314#define KGDB_SCC_INDEX 2
315#define KGDB_PROFF_SCC PROFF_SCC3
316#define KGDB_CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
317 CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
318#define KGDB_CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
319#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
320#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
321
322#elif CONFIG_KGDB_INDEX == 4 /* KGDB Port on SCC4 */
323
324#define KGDB_SCC_INDEX 3
325#define KGDB_PROFF_SCC PROFF_SCC4
326#define KGDB_CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
327 CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
328#define KGDB_CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
329#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
330#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
331
332#else
333
334#error "kgdb serial port not correctly defined"
335
336#endif
337
338void
339kgdb_serial_init (void)
340{
6d0f6bcf 341 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
4a9cbbe8
WD
342 volatile scc_t *sp;
343 volatile scc_uart_t *up;
344 volatile cbd_t *tbdf, *rbdf;
345 volatile cpm8260_t *cp = &(im->im_cpm);
346 uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
347 char *s, *e;
348
349 if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
350 ulong rate = simple_strtoul(s, &e, 10);
351 if (e > s && *e == '\0')
352 speed = rate;
353 }
354
355 /* initialize pointers to SCC */
356
357 sp = (scc_t *) &(im->im_scc[KGDB_SCC_INDEX]);
358 up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
359
360 /* Disable transmitter/receiver.
361 */
362 sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
363
364 /* put the SCC channel into NMSI (non multiplexd serial interface)
365 * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
366 */
367 im->im_cpmux.cmx_scr = \
368 (im->im_cpmux.cmx_scr & ~KGDB_CMXSCR_MASK) | KGDB_CMXSCR_VALUE;
369
370 /* Set up the baud rate generator.
371 */
372#if defined(CONFIG_KGDB_USE_EXTC)
373 m8260_cpm_extcbrg(KGDB_SCC_INDEX, speed,
374 CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
375#else
376 m8260_cpm_setbrg(KGDB_SCC_INDEX, speed);
377#endif
378
379 /* Allocate space for two buffer descriptors in the DP ram.
380 * damm: allocating space after the two buffers for rx/tx data
381 */
382
383 dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
384
385 /* Set the physical address of the host memory buffers in
386 * the buffer descriptors.
387 */
388 rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
389 rbdf->cbd_bufaddr = (uint) (rbdf+2);
390 rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
391 tbdf = rbdf + 1;
392 tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
393 tbdf->cbd_sc = BD_SC_WRAP;
394
395 /* Set up the uart parameters in the parameter ram.
396 */
397 up->scc_genscc.scc_rbase = dpaddr;
398 up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
399 up->scc_genscc.scc_rfcr = CPMFCR_EB;
400 up->scc_genscc.scc_tfcr = CPMFCR_EB;
401 up->scc_genscc.scc_mrblr = 1;
402 up->scc_maxidl = 0;
403 up->scc_brkcr = 1;
404 up->scc_parec = 0;
405 up->scc_frmec = 0;
406 up->scc_nosec = 0;
407 up->scc_brkec = 0;
408 up->scc_uaddr1 = 0;
409 up->scc_uaddr2 = 0;
410 up->scc_toseq = 0;
411 up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
412 up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
413 up->scc_rccm = 0xc0ff;
414
415 /* Mask all interrupts and remove anything pending.
416 */
417 sp->scc_sccm = 0;
418 sp->scc_scce = 0xffff;
419
420 /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
421 */
422 sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
423 sp->scc_gsmrl = \
424 SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
425
426 /* Set CTS flow control, 1 stop bit, 8 bit character length,
427 * normal async UART mode, no parity
428 */
429 sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
430
431 /* execute the "Init Rx and Tx params" CP command.
432 */
433
434 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
435 ;
436
437 cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SCC_PAGE, KGDB_CPM_CR_SCC_SBLOCK,
438 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
439
440 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
441 ;
442
443 /* Enable transmitter/receiver.
444 */
445 sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
446
447 printf("SCC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
448}
449
450void
451putDebugChar(const char c)
452{
453 volatile scc_uart_t *up;
454 volatile cbd_t *tbdf;
8bde7f77 455 volatile immap_t *im;
4a9cbbe8
WD
456
457 if (c == '\n')
458 putDebugChar ('\r');
459
6d0f6bcf 460 im = (immap_t *)CONFIG_SYS_IMMR;
4a9cbbe8
WD
461 up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
462 tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
463
464 /* Wait for last character to go.
465 */
466 while (tbdf->cbd_sc & BD_SC_READY)
467 ;
468
469 /* Load the character into the transmit buffer.
470 */
471 *(volatile char *)tbdf->cbd_bufaddr = c;
472 tbdf->cbd_datlen = 1;
473 tbdf->cbd_sc |= BD_SC_READY;
474}
475
476void
477putDebugStr (const char *s)
478{
479 while (*s) {
480 putDebugChar (*s++);
481 }
482}
483
484int
485getDebugChar(void)
486{
487 volatile cbd_t *rbdf;
488 volatile scc_uart_t *up;
8bde7f77 489 volatile immap_t *im;
4a9cbbe8
WD
490 unsigned char c;
491
6d0f6bcf 492 im = (immap_t *)CONFIG_SYS_IMMR;
4a9cbbe8
WD
493 up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
494 rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
495
496 /* Wait for character to show up.
497 */
498 while (rbdf->cbd_sc & BD_SC_EMPTY)
499 ;
500
501 /* Grab the char and clear the buffer again.
502 */
503 c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
504 rbdf->cbd_sc |= BD_SC_EMPTY;
505
506 return (c);
507}
508
509void
510kgdb_interruptible(int yes)
511{
512 return;
513}
514
515#endif /* CONFIG_KGDB_ON_SCC */