3
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5
* SPDX-License-Identifier: GPL-2.0+
13
* The Serial Management Controllers (SMC) and the Serial Communication
14
* Controllers (SCC) listed in ctlr_list array below are tested in
15
* the loopback UART mode.
16
* The controllers are configured accordingly and several characters
17
* are transmitted. The configurable test parameters are:
18
* MIN_PACKET_LENGTH - minimum size of packet to transmit
19
* MAX_PACKET_LENGTH - maximum size of packet to transmit
20
* TEST_NUM - number of tests
24
#if CONFIG_POST & CONFIG_SYS_POST_UART
25
#if defined(CONFIG_8xx)
27
#elif defined(CONFIG_MPC8260)
28
#include <asm/cpm_8260.h>
30
#error "Apparently a bad configuration, please fix."
35
DECLARE_GLOBAL_DATA_PTR;
40
/* The list of controllers to test */
41
#if defined(CONFIG_MPC823)
42
static int ctlr_list[][2] =
43
{ {CTLR_SMC, 0}, {CTLR_SMC, 1}, {CTLR_SCC, 1} };
45
static int ctlr_list[][2] = { };
49
void (*init) (int index);
50
void (*halt) (int index);
51
void (*putc) (int index, const char c);
52
int (*getc) (int index);
55
static char *ctlr_name[2] = { "SMC", "SCC" };
57
static int proff_smc[] = { PROFF_SMC1, PROFF_SMC2 };
58
static int proff_scc[] =
59
{ PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 };
65
static void smc_init (int smc_index)
67
static int cpm_cr_ch[] = { CPM_CR_CH_SMC1, CPM_CR_CH_SMC2 };
69
volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
71
volatile smc_uart_t *up;
72
volatile cbd_t *tbdf, *rbdf;
73
volatile cpm8xx_t *cp = &(im->im_cpm);
76
/* initialize pointers to SMC */
78
sp = (smc_t *) & (cp->cp_smc[smc_index]);
79
up = (smc_uart_t *) & cp->cp_dparam[proff_smc[smc_index]];
81
/* Disable transmitter/receiver.
83
sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
87
im->im_siu_conf.sc_sdcr = 1;
89
/* clear error conditions */
90
#ifdef CONFIG_SYS_SDSR
91
im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR;
93
im->im_sdma.sdma_sdsr = 0x83;
96
/* clear SDMA interrupt mask */
97
#ifdef CONFIG_SYS_SDMR
98
im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR;
100
im->im_sdma.sdma_sdmr = 0x00;
103
#if defined(CONFIG_FADS)
106
~(smc_index == 1 ? BCSR1_RS232EN_1 : BCSR1_RS232EN_2);
109
#if defined(CONFIG_RPXLITE)
110
/* Enable Monitor Port Transceiver */
111
*((uchar *) BCSR0) |= BCSR0_ENMONXCVR;
114
/* Set the physical address of the host memory buffers in
115
* the buffer descriptors.
118
#ifdef CONFIG_SYS_ALLOC_DPRAM
119
dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8);
121
dpaddr = CPM_POST_BASE;
124
/* Allocate space for two buffer descriptors in the DP ram.
125
* For now, this address seems OK, but it may have to
126
* change with newer versions of the firmware.
127
* damm: allocating space after the two buffers for rx/tx data
130
rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr];
131
rbdf->cbd_bufaddr = (uint) (rbdf + 2);
134
tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1;
137
/* Set up the uart parameters in the parameter ram.
139
up->smc_rbase = dpaddr;
140
up->smc_tbase = dpaddr + sizeof (cbd_t);
141
up->smc_rfcr = SMC_EB;
142
up->smc_tfcr = SMC_EB;
144
/* Set UART mode, 8 bit, no parity, one stop.
145
* Enable receive and transmit.
146
* Set local loopback mode.
148
sp->smc_smcmr = smcr_mk_clen (9) | SMCMR_SM_UART | (ushort) 0x0004;
150
/* Mask all interrupts and remove anything pending.
155
/* Set up the baud rate generator.
157
cp->cp_simode = 0x00000000;
160
(((gd->cpu_clk / 16 / gd->baudrate) -
161
1) << 1) | CPM_BRG_EN;
163
/* Make the first buffer the only buffer.
165
tbdf->cbd_sc |= BD_SC_WRAP;
166
rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
168
/* Single character receive.
173
/* Initialize Tx/Rx parameters.
176
while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
180
mk_cr_cmd (cpm_cr_ch[smc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG;
182
while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
185
/* Enable transmitter/receiver.
187
sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
190
static void smc_halt(int smc_index)
194
static void smc_putc (int smc_index, const char c)
196
volatile cbd_t *tbdf;
198
volatile smc_uart_t *up;
199
volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
200
volatile cpm8xx_t *cpmp = &(im->im_cpm);
202
up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]];
204
tbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_tbase];
206
/* Wait for last character to go.
209
buf = (char *) tbdf->cbd_bufaddr;
212
while (tbdf->cbd_sc & BD_SC_READY)
217
tbdf->cbd_datlen = 1;
218
tbdf->cbd_sc |= BD_SC_READY;
221
while (tbdf->cbd_sc & BD_SC_READY)
226
static int smc_getc (int smc_index)
228
volatile cbd_t *rbdf;
229
volatile unsigned char *buf;
230
volatile smc_uart_t *up;
231
volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
232
volatile cpm8xx_t *cpmp = &(im->im_cpm);
236
up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]];
238
rbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_rbase];
240
/* Wait for character to show up.
242
buf = (unsigned char *) rbdf->cbd_bufaddr;
244
while (rbdf->cbd_sc & BD_SC_EMPTY);
246
for (i = 100; i > 0; i--) {
247
if (!(rbdf->cbd_sc & BD_SC_EMPTY))
256
rbdf->cbd_sc |= BD_SC_EMPTY;
265
static void scc_init (int scc_index)
267
static int cpm_cr_ch[] = {
274
volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
276
volatile scc_uart_t *up;
277
volatile cbd_t *tbdf, *rbdf;
278
volatile cpm8xx_t *cp = &(im->im_cpm);
281
/* initialize pointers to SCC */
283
sp = (scc_t *) & (cp->cp_scc[scc_index]);
284
up = (scc_uart_t *) & cp->cp_dparam[proff_scc[scc_index]];
286
/* Disable transmitter/receiver.
288
sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
291
/* Allocate space for two buffer descriptors in the DP ram.
294
#ifdef CONFIG_SYS_ALLOC_DPRAM
295
dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8);
297
dpaddr = CPM_POST_BASE;
302
im->im_siu_conf.sc_sdcr = 0x0001;
304
/* Set the physical address of the host memory buffers in
305
* the buffer descriptors.
308
rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr];
309
rbdf->cbd_bufaddr = (uint) (rbdf + 2);
312
tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1;
315
/* Set up the baud rate generator.
317
cp->cp_sicr &= ~(0x000000FF << (8 * scc_index));
318
/* no |= needed, since BRG1 is 000 */
321
(((gd->cpu_clk / 16 / gd->baudrate) -
322
1) << 1) | CPM_BRG_EN;
324
/* Set up the uart parameters in the parameter ram.
326
up->scc_genscc.scc_rbase = dpaddr;
327
up->scc_genscc.scc_tbase = dpaddr + sizeof (cbd_t);
329
/* Initialize Tx/Rx parameters.
331
while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
334
mk_cr_cmd (cpm_cr_ch[scc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG;
336
while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
339
up->scc_genscc.scc_rfcr = SCC_EB | 0x05;
340
up->scc_genscc.scc_tfcr = SCC_EB | 0x05;
342
up->scc_genscc.scc_mrblr = 1; /* Single character receive */
343
up->scc_maxidl = 0; /* disable max idle */
344
up->scc_brkcr = 1; /* send one break character on stop TX */
352
up->scc_char1 = 0x8000;
353
up->scc_char2 = 0x8000;
354
up->scc_char3 = 0x8000;
355
up->scc_char4 = 0x8000;
356
up->scc_char5 = 0x8000;
357
up->scc_char6 = 0x8000;
358
up->scc_char7 = 0x8000;
359
up->scc_char8 = 0x8000;
360
up->scc_rccm = 0xc0ff;
362
/* Set low latency / small fifo.
364
sp->scc_gsmrh = SCC_GSMRH_RFW;
368
sp->scc_gsmrl &= ~0xF;
369
sp->scc_gsmrl |= SCC_GSMRL_MODE_UART;
371
/* Set local loopback mode.
373
sp->scc_gsmrl &= ~SCC_GSMRL_DIAG_LE;
374
sp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP;
376
/* Set clock divider 16 on Tx and Rx
378
sp->scc_gsmrl |= (SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
380
sp->scc_psmr |= SCU_PSMR_CL;
382
/* Mask all interrupts and remove anything pending.
385
sp->scc_scce = 0xffff;
386
sp->scc_dsr = 0x7e7e;
387
sp->scc_psmr = 0x3000;
389
/* Make the first buffer the only buffer.
391
tbdf->cbd_sc |= BD_SC_WRAP;
392
rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
394
/* Enable transmitter/receiver.
396
sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
399
static void scc_halt(int scc_index)
401
volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
402
volatile cpm8xx_t *cp = &(im->im_cpm);
403
volatile scc_t *sp = (scc_t *) & (cp->cp_scc[scc_index]);
405
sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT | SCC_GSMRL_DIAG_LE);
408
static void scc_putc (int scc_index, const char c)
410
volatile cbd_t *tbdf;
412
volatile scc_uart_t *up;
413
volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
414
volatile cpm8xx_t *cpmp = &(im->im_cpm);
416
up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]];
418
tbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
420
/* Wait for last character to go.
423
buf = (char *) tbdf->cbd_bufaddr;
426
while (tbdf->cbd_sc & BD_SC_READY)
431
tbdf->cbd_datlen = 1;
432
tbdf->cbd_sc |= BD_SC_READY;
435
while (tbdf->cbd_sc & BD_SC_READY)
440
static int scc_getc (int scc_index)
442
volatile cbd_t *rbdf;
443
volatile unsigned char *buf;
444
volatile scc_uart_t *up;
445
volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
446
volatile cpm8xx_t *cpmp = &(im->im_cpm);
450
up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]];
452
rbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
454
/* Wait for character to show up.
456
buf = (unsigned char *) rbdf->cbd_bufaddr;
458
while (rbdf->cbd_sc & BD_SC_EMPTY);
460
for (i = 100; i > 0; i--) {
461
if (!(rbdf->cbd_sc & BD_SC_EMPTY))
470
rbdf->cbd_sc |= BD_SC_EMPTY;
479
static int test_ctlr (int ctlr, int index)
482
char test_str[] = "*** UART Test String ***\r\n";
485
ctlr_proc[ctlr].init (index);
487
for (i = 0; i < sizeof (test_str) - 1; i++) {
488
ctlr_proc[ctlr].putc (index, test_str[i]);
489
if (ctlr_proc[ctlr].getc (index) != test_str[i])
496
ctlr_proc[ctlr].halt (index);
499
post_log ("uart %s%d test failed\n",
500
ctlr_name[ctlr], index + 1);
506
int uart_post_test (int flags)
511
ctlr_proc[CTLR_SMC].init = smc_init;
512
ctlr_proc[CTLR_SMC].halt = smc_halt;
513
ctlr_proc[CTLR_SMC].putc = smc_putc;
514
ctlr_proc[CTLR_SMC].getc = smc_getc;
516
ctlr_proc[CTLR_SCC].init = scc_init;
517
ctlr_proc[CTLR_SCC].halt = scc_halt;
518
ctlr_proc[CTLR_SCC].putc = scc_putc;
519
ctlr_proc[CTLR_SCC].getc = scc_getc;
521
for (i = 0; i < ARRAY_SIZE(ctlr_list); i++) {
522
if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) {
527
#if !defined(CONFIG_8xx_CONS_NONE)
528
serial_reinit_all ();
534
#endif /* CONFIG_POST & CONFIG_SYS_POST_UART */