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