uboot/arch/powerpc/cpu/mpc85xx/serial_scc.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003 Motorola Inc.
   3 * Xianghua Xiao (X.Xiao@motorola.com)
   4 * Modified based on 8260 for 8560.
   5 *
   6 * (C) Copyright 2000
   7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   8 *
   9 * SPDX-License-Identifier:     GPL-2.0+
  10 *
  11 * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
  12 */
  13
  14/*
  15 * Minimal serial functions needed to use one of the SCC ports
  16 * as serial console interface.
  17 */
  18
  19#include <common.h>
  20#include <asm/cpm_85xx.h>
  21#include <serial.h>
  22#include <linux/compiler.h>
  23
  24DECLARE_GLOBAL_DATA_PTR;
  25
  26#if defined(CONFIG_CONS_ON_SCC)
  27
  28#if CONFIG_CONS_INDEX == 1      /* Console on SCC1 */
  29
  30#define SCC_INDEX               0
  31#define PROFF_SCC               PROFF_SCC1
  32#define CMXSCR_MASK             (CMXSCR_GR1|CMXSCR_SC1|\
  33                                        CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
  34#define CMXSCR_VALUE            (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
  35#define CPM_CR_SCC_PAGE         CPM_CR_SCC1_PAGE
  36#define CPM_CR_SCC_SBLOCK       CPM_CR_SCC1_SBLOCK
  37
  38#elif CONFIG_CONS_INDEX == 2    /* Console on SCC2 */
  39
  40#define SCC_INDEX               1
  41#define PROFF_SCC               PROFF_SCC2
  42#define CMXSCR_MASK             (CMXSCR_GR2|CMXSCR_SC2|\
  43                                        CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
  44#define CMXSCR_VALUE            (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
  45#define CPM_CR_SCC_PAGE         CPM_CR_SCC2_PAGE
  46#define CPM_CR_SCC_SBLOCK       CPM_CR_SCC2_SBLOCK
  47
  48#elif CONFIG_CONS_INDEX == 3    /* Console on SCC3 */
  49
  50#define SCC_INDEX               2
  51#define PROFF_SCC               PROFF_SCC3
  52#define CMXSCR_MASK             (CMXSCR_GR3|CMXSCR_SC3|\
  53                                        CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
  54#define CMXSCR_VALUE            (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
  55#define CPM_CR_SCC_PAGE         CPM_CR_SCC3_PAGE
  56#define CPM_CR_SCC_SBLOCK       CPM_CR_SCC3_SBLOCK
  57
  58#elif CONFIG_CONS_INDEX == 4    /* Console on SCC4 */
  59
  60#define SCC_INDEX               3
  61#define PROFF_SCC               PROFF_SCC4
  62#define CMXSCR_MASK             (CMXSCR_GR4|CMXSCR_SC4|\
  63                                        CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
  64#define CMXSCR_VALUE            (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
  65#define CPM_CR_SCC_PAGE         CPM_CR_SCC4_PAGE
  66#define CPM_CR_SCC_SBLOCK       CPM_CR_SCC4_SBLOCK
  67
  68#else
  69
  70#error "console not correctly defined"
  71
  72#endif
  73
  74static int mpc85xx_serial_init(void)
  75{
  76        volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
  77        volatile ccsr_cpm_scc_t *sp;
  78        volatile scc_uart_t *up;
  79        volatile cbd_t *tbdf, *rbdf;
  80        volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
  81        uint    dpaddr;
  82
  83        /* initialize pointers to SCC */
  84
  85        sp = (ccsr_cpm_scc_t *) &(cpm->im_cpm_scc[SCC_INDEX]);
  86        up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
  87
  88        /* Disable transmitter/receiver.
  89        */
  90        sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  91
  92        /* put the SCC channel into NMSI (non multiplexd serial interface)
  93         * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
  94         */
  95        cpm->im_cpm_mux.cmxscr = \
  96                (cpm->im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE;
  97
  98        /* Set up the baud rate generator.
  99        */
 100        serial_setbrg ();
 101
 102        /* Allocate space for two buffer descriptors in the DP ram.
 103         * damm: allocating space after the two buffers for rx/tx data
 104         */
 105
 106        dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
 107
 108        /* Set the physical address of the host memory buffers in
 109         * the buffer descriptors.
 110         */
 111        rbdf = (cbd_t *)&(cpm->im_dprambase[dpaddr]);
 112        rbdf->cbd_bufaddr = (uint) (rbdf+2);
 113        rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
 114        tbdf = rbdf + 1;
 115        tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
 116        tbdf->cbd_sc = BD_SC_WRAP;
 117
 118        /* Set up the uart parameters in the parameter ram.
 119        */
 120        up->scc_genscc.scc_rbase = dpaddr;
 121        up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
 122        up->scc_genscc.scc_rfcr = CPMFCR_EB;
 123        up->scc_genscc.scc_tfcr = CPMFCR_EB;
 124        up->scc_genscc.scc_mrblr = 1;
 125        up->scc_maxidl = 0;
 126        up->scc_brkcr = 1;
 127        up->scc_parec = 0;
 128        up->scc_frmec = 0;
 129        up->scc_nosec = 0;
 130        up->scc_brkec = 0;
 131        up->scc_uaddr1 = 0;
 132        up->scc_uaddr2 = 0;
 133        up->scc_toseq = 0;
 134        up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
 135        up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
 136        up->scc_rccm = 0xc0ff;
 137
 138        /* Mask all interrupts and remove anything pending.
 139        */
 140        sp->sccm = 0;
 141        sp->scce = 0xffff;
 142
 143        /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
 144        */
 145        sp->gsmrh = SCC_GSMRH_RFW;      /* 8 bit FIFO */
 146        sp->gsmrl = \
 147                SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
 148
 149        /* Set CTS no flow control, 1 stop bit, 8 bit character length,
 150         * normal async UART mode, no parity
 151         */
 152        sp->psmr = SCU_PSMR_CL;
 153
 154        /* execute the "Init Rx and Tx params" CP command.
 155        */
 156
 157        while (cp->cpcr & CPM_CR_FLG)  /* wait if cp is busy */
 158          ;
 159
 160        cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
 161                                        0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
 162
 163        while (cp->cpcr & CPM_CR_FLG)  /* wait if cp is busy */
 164          ;
 165
 166        /* Enable transmitter/receiver.
 167        */
 168        sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
 169
 170        return (0);
 171}
 172
 173static void mpc85xx_serial_setbrg(void)
 174{
 175#if defined(CONFIG_CONS_USE_EXTC)
 176        m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate,
 177                CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
 178#else
 179        m8560_cpm_setbrg(SCC_INDEX, gd->baudrate);
 180#endif
 181}
 182
 183static void mpc85xx_serial_putc(const char c)
 184{
 185        volatile scc_uart_t     *up;
 186        volatile cbd_t          *tbdf;
 187        volatile ccsr_cpm_t     *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
 188
 189        if (c == '\n')
 190                serial_putc ('\r');
 191
 192        up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
 193        tbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_tbase]);
 194
 195        /* Wait for last character to go.
 196         */
 197        while (tbdf->cbd_sc & BD_SC_READY)
 198                ;
 199
 200        /* Load the character into the transmit buffer.
 201         */
 202        *(volatile char *)tbdf->cbd_bufaddr = c;
 203        tbdf->cbd_datlen = 1;
 204        tbdf->cbd_sc |= BD_SC_READY;
 205}
 206
 207static int mpc85xx_serial_getc(void)
 208{
 209        volatile cbd_t          *rbdf;
 210        volatile scc_uart_t     *up;
 211        volatile ccsr_cpm_t     *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
 212        unsigned char           c;
 213
 214        up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
 215        rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
 216
 217        /* Wait for character to show up.
 218         */
 219        while (rbdf->cbd_sc & BD_SC_EMPTY)
 220                ;
 221
 222        /* Grab the char and clear the buffer again.
 223         */
 224        c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
 225        rbdf->cbd_sc |= BD_SC_EMPTY;
 226
 227        return (c);
 228}
 229
 230static int mpc85xx_serial_tstc(void)
 231{
 232        volatile cbd_t          *rbdf;
 233        volatile scc_uart_t     *up;
 234        volatile ccsr_cpm_t     *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
 235
 236        up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
 237        rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
 238
 239        return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
 240}
 241
 242static struct serial_device mpc85xx_serial_drv = {
 243        .name   = "mpc85xx_serial",
 244        .start  = mpc85xx_serial_init,
 245        .stop   = NULL,
 246        .setbrg = mpc85xx_serial_setbrg,
 247        .putc   = mpc85xx_serial_putc,
 248        .puts   = default_serial_puts,
 249        .getc   = mpc85xx_serial_getc,
 250        .tstc   = mpc85xx_serial_tstc,
 251};
 252
 253void mpc85xx_serial_initialize(void)
 254{
 255        serial_register(&mpc85xx_serial_drv);
 256}
 257
 258__weak struct serial_device *default_serial_console(void)
 259{
 260        return &mpc85xx_serial_drv;
 261}
 262#endif  /* CONFIG_CONS_ON_SCC */
 263