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