uboot/arch/powerpc/cpu/mpc8260/serial_smc.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000, 2001, 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 * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
  24 * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
  25 * Linux/PPC sources (m8260_tty.c had no copyright info in it).
  26 */
  27
  28/*
  29 * Minimal serial functions needed to use one of the SMC ports
  30 * as serial console interface.
  31 */
  32
  33#include <common.h>
  34#include <mpc8260.h>
  35#include <asm/cpm_8260.h>
  36
  37DECLARE_GLOBAL_DATA_PTR;
  38
  39#if defined(CONFIG_CONS_ON_SMC)
  40
  41#if CONFIG_CONS_INDEX == 1      /* Console on SMC1 */
  42
  43#define SMC_INDEX               0
  44#define PROFF_SMC_BASE          PROFF_SMC1_BASE
  45#define PROFF_SMC               PROFF_SMC1
  46#define CPM_CR_SMC_PAGE         CPM_CR_SMC1_PAGE
  47#define CPM_CR_SMC_SBLOCK       CPM_CR_SMC1_SBLOCK
  48#define CMXSMR_MASK             (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
  49#define CMXSMR_VALUE            CMXSMR_SMC1CS_BRG7
  50
  51#elif CONFIG_CONS_INDEX == 2    /* Console on SMC2 */
  52
  53#define SMC_INDEX               1
  54#define PROFF_SMC_BASE          PROFF_SMC2_BASE
  55#define PROFF_SMC               PROFF_SMC2
  56#define CPM_CR_SMC_PAGE         CPM_CR_SMC2_PAGE
  57#define CPM_CR_SMC_SBLOCK       CPM_CR_SMC2_SBLOCK
  58#define CMXSMR_MASK             (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
  59#define CMXSMR_VALUE            CMXSMR_SMC2CS_BRG8
  60
  61#else
  62
  63#error "console not correctly defined"
  64
  65#endif
  66
  67#if !defined(CONFIG_SYS_SMC_RXBUFLEN)
  68#define CONFIG_SYS_SMC_RXBUFLEN 1
  69#define CONFIG_SYS_MAXIDLE      0
  70#else
  71#if !defined(CONFIG_SYS_MAXIDLE)
  72#error "you must define CONFIG_SYS_MAXIDLE"
  73#endif
  74#endif
  75
  76typedef volatile struct serialbuffer {
  77        cbd_t   rxbd;           /* Rx BD */
  78        cbd_t   txbd;           /* Tx BD */
  79        uint    rxindex;        /* index for next character to read */
  80        volatile uchar  rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */
  81        volatile uchar  txbuf;  /* tx buffers */
  82} serialbuffer_t;
  83
  84/* map rs_table index to baud rate generator index */
  85static unsigned char brg_map[] = {
  86        6,      /* BRG7 for SMC1 */
  87        7,      /* BRG8 for SMC2 */
  88        0,      /* BRG1 for SCC1 */
  89        1,      /* BRG1 for SCC2 */
  90        2,      /* BRG1 for SCC3 */
  91        3,      /* BRG1 for SCC4 */
  92};
  93
  94int serial_init (void)
  95{
  96        volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
  97        volatile smc_t *sp;
  98        volatile smc_uart_t *up;
  99        volatile cpm8260_t *cp = &(im->im_cpm);
 100        uint    dpaddr;
 101        volatile serialbuffer_t *rtx;
 102
 103        /* initialize pointers to SMC */
 104
 105        sp = (smc_t *) &(im->im_smc[SMC_INDEX]);
 106        *(ushort *)(&im->im_dprambase[PROFF_SMC_BASE]) = PROFF_SMC;
 107        up = (smc_uart_t *)&im->im_dprambase[PROFF_SMC];
 108
 109        /* Disable transmitter/receiver. */
 110        sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 111
 112        /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
 113
 114        /* Allocate space for two buffer descriptors in the DP ram.
 115         * damm: allocating space after the two buffers for rx/tx data
 116         */
 117
 118        /* allocate size of struct serialbuffer with bd rx/tx,
 119         * buffer rx/tx and rx index
 120         */
 121        dpaddr = m8260_cpm_dpalloc((sizeof(serialbuffer_t)), 16);
 122
 123        rtx = (serialbuffer_t *)&im->im_dprambase[dpaddr];
 124
 125        /* Set the physical address of the host memory buffers in
 126         * the buffer descriptors.
 127         */
 128        rtx->rxbd.cbd_bufaddr = (uint) &rtx->rxbuf;
 129        rtx->rxbd.cbd_sc      = 0;
 130
 131        rtx->txbd.cbd_bufaddr = (uint) &rtx->txbuf;
 132        rtx->txbd.cbd_sc      = 0;
 133
 134        /* Set up the uart parameters in the parameter ram. */
 135        up->smc_rbase = dpaddr;
 136        up->smc_tbase = dpaddr+sizeof(cbd_t);
 137        up->smc_rfcr = CPMFCR_EB;
 138        up->smc_tfcr = CPMFCR_EB;
 139        up->smc_brklen = 0;
 140        up->smc_brkec = 0;
 141        up->smc_brkcr = 0;
 142
 143        /* Set UART mode, 8 bit, no parity, one stop.
 144         * Enable receive and transmit.
 145         */
 146        sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
 147
 148        /* Mask all interrupts and remove anything pending. */
 149        sp->smc_smcm = 0;
 150        sp->smc_smce = 0xff;
 151
 152        /* put the SMC channel into NMSI (non multiplexd serial interface)
 153         * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
 154         */
 155        im->im_cpmux.cmx_smr = (im->im_cpmux.cmx_smr&~CMXSMR_MASK)|CMXSMR_VALUE;
 156
 157        /* Set up the baud rate generator. */
 158        serial_setbrg ();
 159
 160        /* Make the first buffer the only buffer. */
 161        rtx->txbd.cbd_sc |= BD_SC_WRAP;
 162        rtx->rxbd.cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
 163
 164        /* single/multi character receive. */
 165        up->smc_mrblr = CONFIG_SYS_SMC_RXBUFLEN;
 166        up->smc_maxidl = CONFIG_SYS_MAXIDLE;
 167        rtx->rxindex = 0;
 168
 169        /* Initialize Tx/Rx parameters. */
 170
 171        while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
 172          ;
 173
 174        cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC_PAGE, CPM_CR_SMC_SBLOCK,
 175                                        0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
 176
 177        while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
 178          ;
 179
 180        /* Enable transmitter/receiver. */
 181        sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
 182
 183        return (0);
 184}
 185
 186void
 187serial_setbrg (void)
 188{
 189#if defined(CONFIG_CONS_USE_EXTC)
 190        m8260_cpm_extcbrg(brg_map[SMC_INDEX], gd->baudrate,
 191                CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
 192#else
 193        m8260_cpm_setbrg(brg_map[SMC_INDEX], gd->baudrate);
 194#endif
 195}
 196
 197void
 198serial_putc(const char c)
 199{
 200        volatile smc_uart_t     *up;
 201        volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
 202        volatile serialbuffer_t *rtx;
 203
 204        if (c == '\n')
 205                serial_putc ('\r');
 206
 207        up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
 208
 209        rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
 210
 211        /* Wait for last character to go. */
 212        while (rtx->txbd.cbd_sc & BD_SC_READY & BD_SC_READY)
 213                ;
 214        rtx->txbuf = c;
 215        rtx->txbd.cbd_datlen = 1;
 216        rtx->txbd.cbd_sc |= BD_SC_READY;
 217}
 218
 219void
 220serial_puts (const char *s)
 221{
 222        while (*s) {
 223                serial_putc (*s++);
 224        }
 225}
 226
 227int
 228serial_getc(void)
 229{
 230        volatile smc_uart_t     *up;
 231        volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
 232        volatile serialbuffer_t *rtx;
 233        unsigned char  c;
 234
 235        up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
 236
 237        rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
 238
 239        /* Wait for character to show up. */
 240        while (rtx->rxbd.cbd_sc & BD_SC_EMPTY)
 241                ;
 242
 243        /* the characters are read one by one,
 244         * use the rxindex to know the next char to deliver
 245         */
 246        c = *(unsigned char *) (rtx->rxbd.cbd_bufaddr + rtx->rxindex);
 247        rtx->rxindex++;
 248
 249        /* check if all char are readout, then make prepare for next receive */
 250        if (rtx->rxindex >= rtx->rxbd.cbd_datlen) {
 251                rtx->rxindex = 0;
 252                rtx->rxbd.cbd_sc |= BD_SC_EMPTY;
 253        }
 254        return(c);
 255}
 256
 257int
 258serial_tstc()
 259{
 260        volatile smc_uart_t     *up;
 261        volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
 262        volatile serialbuffer_t *rtx;
 263
 264        up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
 265        rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
 266
 267        return !(rtx->rxbd.cbd_sc & BD_SC_EMPTY);
 268}
 269
 270#endif  /* CONFIG_CONS_ON_SMC */
 271
 272#if defined(CONFIG_KGDB_ON_SMC)
 273
 274#if defined(CONFIG_CONS_ON_SMC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
 275#error Whoops! serial console and kgdb are on the same smc serial port
 276#endif
 277
 278#if CONFIG_KGDB_INDEX == 1      /* KGDB Port on SMC1 */
 279
 280#define KGDB_SMC_INDEX          0
 281#define KGDB_PROFF_SMC_BASE     PROFF_SMC1_BASE
 282#define KGDB_PROFF_SMC          PROFF_SMC1
 283#define KGDB_CPM_CR_SMC_PAGE    CPM_CR_SMC1_PAGE
 284#define KGDB_CPM_CR_SMC_SBLOCK  CPM_CR_SMC1_SBLOCK
 285#define KGDB_CMXSMR_MASK        (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
 286#define KGDB_CMXSMR_VALUE       CMXSMR_SMC1CS_BRG7
 287
 288#elif CONFIG_KGDB_INDEX == 2    /* KGDB Port on SMC2 */
 289
 290#define KGDB_SMC_INDEX          1
 291#define KGDB_PROFF_SMC_BASE     PROFF_SMC2_BASE
 292#define KGDB_PROFF_SMC          PROFF_SMC2
 293#define KGDB_CPM_CR_SMC_PAGE    CPM_CR_SMC2_PAGE
 294#define KGDB_CPM_CR_SMC_SBLOCK  CPM_CR_SMC2_SBLOCK
 295#define KGDB_CMXSMR_MASK        (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
 296#define KGDB_CMXSMR_VALUE       CMXSMR_SMC2CS_BRG8
 297
 298#else
 299
 300#error "console not correctly defined"
 301
 302#endif
 303
 304void
 305kgdb_serial_init (void)
 306{
 307        volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
 308        volatile smc_t *sp;
 309        volatile smc_uart_t *up;
 310        volatile cbd_t *tbdf, *rbdf;
 311        volatile cpm8260_t *cp = &(im->im_cpm);
 312        uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
 313        char *s, *e;
 314
 315        if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
 316                ulong rate = simple_strtoul(s, &e, 10);
 317                if (e > s && *e == '\0')
 318                        speed = rate;
 319        }
 320
 321        /* initialize pointers to SMC */
 322
 323        sp = (smc_t *) &(im->im_smc[KGDB_SMC_INDEX]);
 324        *(ushort *)(&im->im_dprambase[KGDB_PROFF_SMC_BASE]) = KGDB_PROFF_SMC;
 325        up = (smc_uart_t *)&im->im_dprambase[KGDB_PROFF_SMC];
 326
 327        /* Disable transmitter/receiver. */
 328        sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 329
 330        /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
 331
 332        /* Allocate space for two buffer descriptors in the DP ram.
 333         * damm: allocating space after the two buffers for rx/tx data
 334         */
 335
 336        dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
 337
 338        /* Set the physical address of the host memory buffers in
 339         * the buffer descriptors.
 340         */
 341        rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
 342        rbdf->cbd_bufaddr = (uint) (rbdf+2);
 343        rbdf->cbd_sc = 0;
 344        tbdf = rbdf + 1;
 345        tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
 346        tbdf->cbd_sc = 0;
 347
 348        /* Set up the uart parameters in the parameter ram. */
 349        up->smc_rbase = dpaddr;
 350        up->smc_tbase = dpaddr+sizeof(cbd_t);
 351        up->smc_rfcr = CPMFCR_EB;
 352        up->smc_tfcr = CPMFCR_EB;
 353        up->smc_brklen = 0;
 354        up->smc_brkec = 0;
 355        up->smc_brkcr = 0;
 356
 357        /* Set UART mode, 8 bit, no parity, one stop.
 358         * Enable receive and transmit.
 359         */
 360        sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
 361
 362        /* Mask all interrupts and remove anything pending. */
 363        sp->smc_smcm = 0;
 364        sp->smc_smce = 0xff;
 365
 366        /* put the SMC channel into NMSI (non multiplexd serial interface)
 367         * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
 368         */
 369        im->im_cpmux.cmx_smr =
 370                (im->im_cpmux.cmx_smr & ~KGDB_CMXSMR_MASK) | KGDB_CMXSMR_VALUE;
 371
 372        /* Set up the baud rate generator. */
 373#if defined(CONFIG_KGDB_USE_EXTC)
 374        m8260_cpm_extcbrg(brg_map[KGDB_SMC_INDEX], speed,
 375                CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
 376#else
 377        m8260_cpm_setbrg(brg_map[KGDB_SMC_INDEX], speed);
 378#endif
 379
 380        /* Make the first buffer the only buffer. */
 381        tbdf->cbd_sc |= BD_SC_WRAP;
 382        rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
 383
 384        /* Single character receive. */
 385        up->smc_mrblr = 1;
 386        up->smc_maxidl = 0;
 387
 388        /* Initialize Tx/Rx parameters. */
 389
 390        while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
 391          ;
 392
 393        cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SMC_PAGE, KGDB_CPM_CR_SMC_SBLOCK,
 394                                        0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
 395
 396        while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
 397          ;
 398
 399        /* Enable transmitter/receiver. */
 400        sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
 401
 402        printf("SMC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
 403}
 404
 405void
 406putDebugChar(const char c)
 407{
 408        volatile cbd_t          *tbdf;
 409        volatile char           *buf;
 410        volatile smc_uart_t     *up;
 411        volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
 412
 413        if (c == '\n')
 414                putDebugChar ('\r');
 415
 416        up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
 417
 418        tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
 419
 420        /* Wait for last character to go. */
 421        buf = (char *)tbdf->cbd_bufaddr;
 422        while (tbdf->cbd_sc & BD_SC_READY)
 423                ;
 424
 425        *buf = c;
 426        tbdf->cbd_datlen = 1;
 427        tbdf->cbd_sc |= BD_SC_READY;
 428}
 429
 430void
 431putDebugStr (const char *s)
 432{
 433        while (*s) {
 434                putDebugChar (*s++);
 435        }
 436}
 437
 438int
 439getDebugChar(void)
 440{
 441        volatile cbd_t          *rbdf;
 442        volatile unsigned char  *buf;
 443        volatile smc_uart_t     *up;
 444        volatile immap_t        *im = (immap_t *)CONFIG_SYS_IMMR;
 445        unsigned char           c;
 446
 447        up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
 448
 449        rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
 450
 451        /* Wait for character to show up. */
 452        buf = (unsigned char *)rbdf->cbd_bufaddr;
 453        while (rbdf->cbd_sc & BD_SC_EMPTY)
 454                ;
 455        c = *buf;
 456        rbdf->cbd_sc |= BD_SC_EMPTY;
 457
 458        return(c);
 459}
 460
 461void
 462kgdb_interruptible(int yes)
 463{
 464        return;
 465}
 466
 467#endif  /* CONFIG_KGDB_ON_SMC */
 468