uboot/arch/mips/cpu/mips32/incaip/asc_serial.c
<<
>>
Prefs
   1/*
   2 * (INCA) ASC UART support
   3 */
   4
   5#include <config.h>
   6#include <common.h>
   7#include <asm/inca-ip.h>
   8#include "asc_serial.h"
   9
  10
  11#define SET_BIT(reg, mask)                  reg |= (mask)
  12#define CLEAR_BIT(reg, mask)                reg &= (~mask)
  13#define CLEAR_BITS(reg, mask)               CLEAR_BIT(reg, mask)
  14#define SET_BITS(reg, mask)                 SET_BIT(reg, mask)
  15#define SET_BITFIELD(reg, mask, off, val)   {reg &= (~mask); reg |= (val << off);}
  16
  17extern uint incaip_get_fpiclk(void);
  18
  19static int serial_setopt (void);
  20
  21/* pointer to ASC register base address */
  22static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
  23
  24/******************************************************************************
  25*
  26* serial_init - initialize a INCAASC channel
  27*
  28* This routine initializes the number of data bits, parity
  29* and set the selected baud rate. Interrupts are disabled.
  30* Set the modem control signals if the option is selected.
  31*
  32* RETURNS: N/A
  33*/
  34
  35int serial_init (void)
  36{
  37    /* we have to set PMU.EN13 bit to enable an ASC device*/
  38    INCAASC_PMU_ENABLE(13);
  39
  40    /* and we have to set CLC register*/
  41    CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
  42    SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
  43
  44    /* initialy we are in async mode */
  45    pAsc->asc_con = ASCCON_M_8ASYNC;
  46
  47    /* select input port */
  48    pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
  49
  50    /* TXFIFO's filling level */
  51    SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
  52                    ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
  53    /* enable TXFIFO */
  54    SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
  55
  56    /* RXFIFO's filling level */
  57    SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
  58                    ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
  59    /* enable RXFIFO */
  60    SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
  61
  62    /* enable error signals */
  63    SET_BIT(pAsc->asc_con, ASCCON_FEN);
  64    SET_BIT(pAsc->asc_con, ASCCON_OEN);
  65
  66    /* acknowledge ASC interrupts */
  67    ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
  68
  69    /* disable ASC interrupts */
  70    ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
  71
  72    /* set FIFOs into the transparent mode */
  73    SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
  74    SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
  75
  76    /* set baud rate */
  77    serial_setbrg();
  78
  79    /* set the options */
  80    serial_setopt();
  81
  82    return 0;
  83}
  84
  85void serial_setbrg (void)
  86{
  87    ulong      uiReloadValue, fdv;
  88    ulong      f_ASC;
  89
  90    f_ASC = incaip_get_fpiclk();
  91
  92#ifndef INCAASC_USE_FDV
  93    fdv = 2;
  94    uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
  95#else
  96    fdv = INCAASC_FDV_HIGH_BAUDRATE;
  97    uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
  98#endif /* INCAASC_USE_FDV */
  99
 100    if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
 101    {
 102#ifndef INCAASC_USE_FDV
 103        fdv = 3;
 104        uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
 105#else
 106        fdv = INCAASC_FDV_LOW_BAUDRATE;
 107        uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
 108#endif /* INCAASC_USE_FDV */
 109
 110        if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
 111        {
 112            return;    /* can't impossibly generate that baud rate */
 113        }
 114    }
 115
 116    /* Disable Baud Rate Generator; BG should only be written when R=0 */
 117    CLEAR_BIT(pAsc->asc_con, ASCCON_R);
 118
 119#ifndef INCAASC_USE_FDV
 120    /*
 121     * Disable Fractional Divider (FDE)
 122     * Divide clock by reload-value + constant (BRS)
 123     */
 124    /* FDE = 0 */
 125    CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
 126
 127    if ( fdv == 2 )
 128        CLEAR_BIT(pAsc->asc_con, ASCCON_BRS);   /* BRS = 0 */
 129    else
 130        SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
 131
 132#else /* INCAASC_USE_FDV */
 133
 134    /* Enable Fractional Divider */
 135    SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
 136
 137    /* Set fractional divider value */
 138    pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
 139
 140#endif /* INCAASC_USE_FDV */
 141
 142    /* Set reload value in BG */
 143    pAsc->asc_bg = uiReloadValue;
 144
 145    /* Enable Baud Rate Generator */
 146    SET_BIT(pAsc->asc_con, ASCCON_R);           /* R = 1 */
 147}
 148
 149/*******************************************************************************
 150*
 151* serial_setopt - set the serial options
 152*
 153* Set the channel operating mode to that specified. Following options
 154* are supported: CREAD, CSIZE, PARENB, and PARODD.
 155*
 156* Note, this routine disables the transmitter.  The calling routine
 157* may have to re-enable it.
 158*
 159* RETURNS:
 160* Returns 0 to indicate success, otherwise -1 is returned
 161*/
 162
 163static int serial_setopt (void)
 164{
 165    ulong  con;
 166
 167    switch ( ASC_OPTIONS & ASCOPT_CSIZE )
 168    {
 169    /* 7-bit-data */
 170    case ASCOPT_CS7:
 171        con = ASCCON_M_7ASYNCPAR;   /* 7-bit-data and parity bit */
 172        break;
 173
 174    /* 8-bit-data */
 175    case ASCOPT_CS8:
 176        if ( ASC_OPTIONS & ASCOPT_PARENB )
 177            con = ASCCON_M_8ASYNCPAR;   /* 8-bit-data and parity bit */
 178        else
 179            con = ASCCON_M_8ASYNC;      /* 8-bit-data no parity */
 180        break;
 181
 182    /*
 183     *  only 7 and 8-bit frames are supported
 184     *  if we don't use IOCTL extensions
 185     */
 186    default:
 187        return -1;
 188    }
 189
 190    if ( ASC_OPTIONS & ASCOPT_STOPB )
 191        SET_BIT(con, ASCCON_STP);       /* 2 stop bits */
 192    else
 193        CLEAR_BIT(con, ASCCON_STP);     /* 1 stop bit */
 194
 195    if ( ASC_OPTIONS & ASCOPT_PARENB )
 196        SET_BIT(con, ASCCON_PEN);           /* enable parity checking */
 197    else
 198        CLEAR_BIT(con, ASCCON_PEN);         /* disable parity checking */
 199
 200    if ( ASC_OPTIONS & ASCOPT_PARODD )
 201        SET_BIT(con, ASCCON_ODD);       /* odd parity */
 202    else
 203        CLEAR_BIT(con, ASCCON_ODD);     /* even parity */
 204
 205    if ( ASC_OPTIONS & ASCOPT_CREAD )
 206        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
 207
 208    pAsc->asc_con |= con;
 209
 210    return 0;
 211}
 212
 213void serial_putc (const char c)
 214{
 215    uint txFl = 0;
 216
 217    if (c == '\n') serial_putc ('\r');
 218
 219    /* check do we have a free space in the TX FIFO */
 220    /* get current filling level */
 221    do
 222    {
 223        txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
 224    }
 225    while ( txFl == INCAASC_TXFIFO_FULL );
 226
 227    pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
 228
 229    /* check for errors */
 230    if ( pAsc->asc_con & ASCCON_OE )
 231    {
 232        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
 233        return;
 234    }
 235}
 236
 237void serial_puts (const char *s)
 238{
 239    while (*s)
 240    {
 241        serial_putc (*s++);
 242    }
 243}
 244
 245int serial_getc (void)
 246{
 247    ulong symbol_mask;
 248    char c;
 249
 250    while (!serial_tstc());
 251
 252    symbol_mask =
 253        ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
 254
 255    c = (char)(pAsc->asc_rbuf & symbol_mask);
 256
 257    return c;
 258}
 259
 260int serial_tstc (void)
 261{
 262    int res = 1;
 263
 264    if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
 265    {
 266        res = 0;
 267    }
 268    else if ( pAsc->asc_con & ASCCON_FE )
 269    {
 270        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
 271        res = 0;
 272    }
 273    else if ( pAsc->asc_con & ASCCON_PE )
 274    {
 275        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
 276        res = 0;
 277    }
 278    else if ( pAsc->asc_con & ASCCON_OE )
 279    {
 280        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
 281        res = 0;
 282    }
 283
 284    return res;
 285}
 286