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