~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/post/cpu/mpc8xx/uart.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2002
 
3
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
4
 *
 
5
 * SPDX-License-Identifier:     GPL-2.0+
 
6
 */
 
7
 
 
8
#include <common.h>
 
9
 
 
10
/*
 
11
 * UART test
 
12
 *
 
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
 
21
 */
 
22
 
 
23
#include <post.h>
 
24
#if CONFIG_POST & CONFIG_SYS_POST_UART
 
25
#if defined(CONFIG_8xx)
 
26
#include <commproc.h>
 
27
#elif defined(CONFIG_MPC8260)
 
28
#include <asm/cpm_8260.h>
 
29
#else
 
30
#error "Apparently a bad configuration, please fix."
 
31
#endif
 
32
#include <command.h>
 
33
#include <serial.h>
 
34
 
 
35
DECLARE_GLOBAL_DATA_PTR;
 
36
 
 
37
#define CTLR_SMC 0
 
38
#define CTLR_SCC 1
 
39
 
 
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} };
 
44
#else
 
45
static int ctlr_list[][2] = { };
 
46
#endif
 
47
 
 
48
static struct {
 
49
        void (*init) (int index);
 
50
        void (*halt) (int index);
 
51
        void (*putc) (int index, const char c);
 
52
        int (*getc) (int index);
 
53
} ctlr_proc[2];
 
54
 
 
55
static char *ctlr_name[2] = { "SMC", "SCC" };
 
56
 
 
57
static int proff_smc[] = { PROFF_SMC1, PROFF_SMC2 };
 
58
static int proff_scc[] =
 
59
                { PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 };
 
60
 
 
61
/*
 
62
 * SMC callbacks
 
63
 */
 
64
 
 
65
static void smc_init (int smc_index)
 
66
{
 
67
        static int cpm_cr_ch[] = { CPM_CR_CH_SMC1, CPM_CR_CH_SMC2 };
 
68
 
 
69
        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 
70
        volatile smc_t *sp;
 
71
        volatile smc_uart_t *up;
 
72
        volatile cbd_t *tbdf, *rbdf;
 
73
        volatile cpm8xx_t *cp = &(im->im_cpm);
 
74
        uint dpaddr;
 
75
 
 
76
        /* initialize pointers to SMC */
 
77
 
 
78
        sp = (smc_t *) & (cp->cp_smc[smc_index]);
 
79
        up = (smc_uart_t *) & cp->cp_dparam[proff_smc[smc_index]];
 
80
 
 
81
        /* Disable transmitter/receiver.
 
82
         */
 
83
        sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 
84
 
 
85
        /* Enable SDMA.
 
86
         */
 
87
        im->im_siu_conf.sc_sdcr = 1;
 
88
 
 
89
        /* clear error conditions */
 
90
#ifdef  CONFIG_SYS_SDSR
 
91
        im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR;
 
92
#else
 
93
        im->im_sdma.sdma_sdsr = 0x83;
 
94
#endif
 
95
 
 
96
        /* clear SDMA interrupt mask */
 
97
#ifdef  CONFIG_SYS_SDMR
 
98
        im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR;
 
99
#else
 
100
        im->im_sdma.sdma_sdmr = 0x00;
 
101
#endif
 
102
 
 
103
#if defined(CONFIG_FADS)
 
104
        /* Enable RS232 */
 
105
        *((uint *) BCSR1) &=
 
106
                        ~(smc_index == 1 ? BCSR1_RS232EN_1 : BCSR1_RS232EN_2);
 
107
#endif
 
108
 
 
109
#if defined(CONFIG_RPXLITE)
 
110
        /* Enable Monitor Port Transceiver */
 
111
        *((uchar *) BCSR0) |= BCSR0_ENMONXCVR;
 
112
#endif
 
113
 
 
114
        /* Set the physical address of the host memory buffers in
 
115
         * the buffer descriptors.
 
116
         */
 
117
 
 
118
#ifdef CONFIG_SYS_ALLOC_DPRAM
 
119
        dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8);
 
120
#else
 
121
        dpaddr = CPM_POST_BASE;
 
122
#endif
 
123
 
 
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
 
128
         */
 
129
 
 
130
        rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr];
 
131
        rbdf->cbd_bufaddr = (uint) (rbdf + 2);
 
132
        rbdf->cbd_sc = 0;
 
133
        tbdf = rbdf + 1;
 
134
        tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1;
 
135
        tbdf->cbd_sc = 0;
 
136
 
 
137
        /* Set up the uart parameters in the parameter ram.
 
138
         */
 
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;
 
143
 
 
144
        /* Set UART mode, 8 bit, no parity, one stop.
 
145
         * Enable receive and transmit.
 
146
         * Set local loopback mode.
 
147
         */
 
148
        sp->smc_smcmr = smcr_mk_clen (9) | SMCMR_SM_UART | (ushort) 0x0004;
 
149
 
 
150
        /* Mask all interrupts and remove anything pending.
 
151
         */
 
152
        sp->smc_smcm = 0;
 
153
        sp->smc_smce = 0xff;
 
154
 
 
155
        /* Set up the baud rate generator.
 
156
         */
 
157
        cp->cp_simode = 0x00000000;
 
158
 
 
159
        cp->cp_brgc1 =
 
160
                        (((gd->cpu_clk / 16 / gd->baudrate) -
 
161
                          1) << 1) | CPM_BRG_EN;
 
162
 
 
163
        /* Make the first buffer the only buffer.
 
164
         */
 
165
        tbdf->cbd_sc |= BD_SC_WRAP;
 
166
        rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
 
167
 
 
168
        /* Single character receive.
 
169
         */
 
170
        up->smc_mrblr = 1;
 
171
        up->smc_maxidl = 0;
 
172
 
 
173
        /* Initialize Tx/Rx parameters.
 
174
         */
 
175
 
 
176
        while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
 
177
                ;
 
178
 
 
179
        cp->cp_cpcr =
 
180
                        mk_cr_cmd (cpm_cr_ch[smc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG;
 
181
 
 
182
        while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
 
183
                ;
 
184
 
 
185
        /* Enable transmitter/receiver.
 
186
         */
 
187
        sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
 
188
}
 
189
 
 
190
static void smc_halt(int smc_index)
 
191
{
 
192
}
 
193
 
 
194
static void smc_putc (int smc_index, const char c)
 
195
{
 
196
        volatile cbd_t *tbdf;
 
197
        volatile char *buf;
 
198
        volatile smc_uart_t *up;
 
199
        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 
200
        volatile cpm8xx_t *cpmp = &(im->im_cpm);
 
201
 
 
202
        up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]];
 
203
 
 
204
        tbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_tbase];
 
205
 
 
206
        /* Wait for last character to go.
 
207
         */
 
208
 
 
209
        buf = (char *) tbdf->cbd_bufaddr;
 
210
#if 0
 
211
        __asm__ ("eieio");
 
212
        while (tbdf->cbd_sc & BD_SC_READY)
 
213
                __asm__ ("eieio");
 
214
#endif
 
215
 
 
216
        *buf = c;
 
217
        tbdf->cbd_datlen = 1;
 
218
        tbdf->cbd_sc |= BD_SC_READY;
 
219
        __asm__ ("eieio");
 
220
#if 1
 
221
        while (tbdf->cbd_sc & BD_SC_READY)
 
222
                __asm__ ("eieio");
 
223
#endif
 
224
}
 
225
 
 
226
static int smc_getc (int smc_index)
 
227
{
 
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);
 
233
        unsigned char c;
 
234
        int i;
 
235
 
 
236
        up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]];
 
237
 
 
238
        rbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_rbase];
 
239
 
 
240
        /* Wait for character to show up.
 
241
         */
 
242
        buf = (unsigned char *) rbdf->cbd_bufaddr;
 
243
#if 0
 
244
        while (rbdf->cbd_sc & BD_SC_EMPTY);
 
245
#else
 
246
        for (i = 100; i > 0; i--) {
 
247
                if (!(rbdf->cbd_sc & BD_SC_EMPTY))
 
248
                        break;
 
249
                udelay (1000);
 
250
        }
 
251
 
 
252
        if (i == 0)
 
253
                return -1;
 
254
#endif
 
255
        c = *buf;
 
256
        rbdf->cbd_sc |= BD_SC_EMPTY;
 
257
 
 
258
        return (c);
 
259
}
 
260
 
 
261
  /*
 
262
   * SCC callbacks
 
263
   */
 
264
 
 
265
static void scc_init (int scc_index)
 
266
{
 
267
        static int cpm_cr_ch[] = {
 
268
                CPM_CR_CH_SCC1,
 
269
                CPM_CR_CH_SCC2,
 
270
                CPM_CR_CH_SCC3,
 
271
                CPM_CR_CH_SCC4,
 
272
        };
 
273
 
 
274
        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 
275
        volatile scc_t *sp;
 
276
        volatile scc_uart_t *up;
 
277
        volatile cbd_t *tbdf, *rbdf;
 
278
        volatile cpm8xx_t *cp = &(im->im_cpm);
 
279
        uint dpaddr;
 
280
 
 
281
        /* initialize pointers to SCC */
 
282
 
 
283
        sp = (scc_t *) & (cp->cp_scc[scc_index]);
 
284
        up = (scc_uart_t *) & cp->cp_dparam[proff_scc[scc_index]];
 
285
 
 
286
        /* Disable transmitter/receiver.
 
287
         */
 
288
        sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
 
289
 
 
290
 
 
291
        /* Allocate space for two buffer descriptors in the DP ram.
 
292
         */
 
293
 
 
294
#ifdef CONFIG_SYS_ALLOC_DPRAM
 
295
        dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8);
 
296
#else
 
297
        dpaddr = CPM_POST_BASE;
 
298
#endif
 
299
 
 
300
        /* Enable SDMA.
 
301
         */
 
302
        im->im_siu_conf.sc_sdcr = 0x0001;
 
303
 
 
304
        /* Set the physical address of the host memory buffers in
 
305
         * the buffer descriptors.
 
306
         */
 
307
 
 
308
        rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr];
 
309
        rbdf->cbd_bufaddr = (uint) (rbdf + 2);
 
310
        rbdf->cbd_sc = 0;
 
311
        tbdf = rbdf + 1;
 
312
        tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1;
 
313
        tbdf->cbd_sc = 0;
 
314
 
 
315
        /* Set up the baud rate generator.
 
316
         */
 
317
        cp->cp_sicr &= ~(0x000000FF << (8 * scc_index));
 
318
        /* no |= needed, since BRG1 is 000 */
 
319
 
 
320
        cp->cp_brgc1 =
 
321
                        (((gd->cpu_clk / 16 / gd->baudrate) -
 
322
                          1) << 1) | CPM_BRG_EN;
 
323
 
 
324
        /* Set up the uart parameters in the parameter ram.
 
325
         */
 
326
        up->scc_genscc.scc_rbase = dpaddr;
 
327
        up->scc_genscc.scc_tbase = dpaddr + sizeof (cbd_t);
 
328
 
 
329
        /* Initialize Tx/Rx parameters.
 
330
         */
 
331
        while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
 
332
                ;
 
333
        cp->cp_cpcr =
 
334
                        mk_cr_cmd (cpm_cr_ch[scc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG;
 
335
 
 
336
        while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
 
337
                ;
 
338
 
 
339
        up->scc_genscc.scc_rfcr = SCC_EB | 0x05;
 
340
        up->scc_genscc.scc_tfcr = SCC_EB | 0x05;
 
341
 
 
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 */
 
345
        up->scc_parec = 0;
 
346
        up->scc_frmec = 0;
 
347
        up->scc_nosec = 0;
 
348
        up->scc_brkec = 0;
 
349
        up->scc_uaddr1 = 0;
 
350
        up->scc_uaddr2 = 0;
 
351
        up->scc_toseq = 0;
 
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;
 
361
 
 
362
        /* Set low latency / small fifo.
 
363
         */
 
364
        sp->scc_gsmrh = SCC_GSMRH_RFW;
 
365
 
 
366
        /* Set UART mode
 
367
         */
 
368
        sp->scc_gsmrl &= ~0xF;
 
369
        sp->scc_gsmrl |= SCC_GSMRL_MODE_UART;
 
370
 
 
371
        /* Set local loopback mode.
 
372
         */
 
373
        sp->scc_gsmrl &= ~SCC_GSMRL_DIAG_LE;
 
374
        sp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP;
 
375
 
 
376
        /* Set clock divider 16 on Tx and Rx
 
377
         */
 
378
        sp->scc_gsmrl |= (SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
 
379
 
 
380
        sp->scc_psmr |= SCU_PSMR_CL;
 
381
 
 
382
        /* Mask all interrupts and remove anything pending.
 
383
         */
 
384
        sp->scc_sccm = 0;
 
385
        sp->scc_scce = 0xffff;
 
386
        sp->scc_dsr = 0x7e7e;
 
387
        sp->scc_psmr = 0x3000;
 
388
 
 
389
        /* Make the first buffer the only buffer.
 
390
         */
 
391
        tbdf->cbd_sc |= BD_SC_WRAP;
 
392
        rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
 
393
 
 
394
        /* Enable transmitter/receiver.
 
395
         */
 
396
        sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
 
397
}
 
398
 
 
399
static void scc_halt(int scc_index)
 
400
{
 
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]);
 
404
 
 
405
        sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT | SCC_GSMRL_DIAG_LE);
 
406
}
 
407
 
 
408
static void scc_putc (int scc_index, const char c)
 
409
{
 
410
        volatile cbd_t *tbdf;
 
411
        volatile char *buf;
 
412
        volatile scc_uart_t *up;
 
413
        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 
414
        volatile cpm8xx_t *cpmp = &(im->im_cpm);
 
415
 
 
416
        up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]];
 
417
 
 
418
        tbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
 
419
 
 
420
        /* Wait for last character to go.
 
421
         */
 
422
 
 
423
        buf = (char *) tbdf->cbd_bufaddr;
 
424
#if 0
 
425
        __asm__ ("eieio");
 
426
        while (tbdf->cbd_sc & BD_SC_READY)
 
427
                __asm__ ("eieio");
 
428
#endif
 
429
 
 
430
        *buf = c;
 
431
        tbdf->cbd_datlen = 1;
 
432
        tbdf->cbd_sc |= BD_SC_READY;
 
433
        __asm__ ("eieio");
 
434
#if 1
 
435
        while (tbdf->cbd_sc & BD_SC_READY)
 
436
                __asm__ ("eieio");
 
437
#endif
 
438
}
 
439
 
 
440
static int scc_getc (int scc_index)
 
441
{
 
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);
 
447
        unsigned char c;
 
448
        int i;
 
449
 
 
450
        up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]];
 
451
 
 
452
        rbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
 
453
 
 
454
        /* Wait for character to show up.
 
455
         */
 
456
        buf = (unsigned char *) rbdf->cbd_bufaddr;
 
457
#if 0
 
458
        while (rbdf->cbd_sc & BD_SC_EMPTY);
 
459
#else
 
460
        for (i = 100; i > 0; i--) {
 
461
                if (!(rbdf->cbd_sc & BD_SC_EMPTY))
 
462
                        break;
 
463
                udelay (1000);
 
464
        }
 
465
 
 
466
        if (i == 0)
 
467
                return -1;
 
468
#endif
 
469
        c = *buf;
 
470
        rbdf->cbd_sc |= BD_SC_EMPTY;
 
471
 
 
472
        return (c);
 
473
}
 
474
 
 
475
  /*
 
476
   * Test routines
 
477
   */
 
478
 
 
479
static int test_ctlr (int ctlr, int index)
 
480
{
 
481
        int res = -1;
 
482
        char test_str[] = "*** UART Test String ***\r\n";
 
483
        int i;
 
484
 
 
485
        ctlr_proc[ctlr].init (index);
 
486
 
 
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])
 
490
                        goto Done;
 
491
        }
 
492
 
 
493
        res = 0;
 
494
 
 
495
Done:
 
496
        ctlr_proc[ctlr].halt (index);
 
497
 
 
498
        if (res != 0) {
 
499
                post_log ("uart %s%d test failed\n",
 
500
                                ctlr_name[ctlr], index + 1);
 
501
        }
 
502
 
 
503
        return res;
 
504
}
 
505
 
 
506
int uart_post_test (int flags)
 
507
{
 
508
        int res = 0;
 
509
        int i;
 
510
 
 
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;
 
515
 
 
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;
 
520
 
 
521
        for (i = 0; i < ARRAY_SIZE(ctlr_list); i++) {
 
522
                if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) {
 
523
                        res = -1;
 
524
                }
 
525
        }
 
526
 
 
527
#if !defined(CONFIG_8xx_CONS_NONE)
 
528
        serial_reinit_all ();
 
529
#endif
 
530
 
 
531
        return res;
 
532
}
 
533
 
 
534
#endif /* CONFIG_POST & CONFIG_SYS_POST_UART */