123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- /*
- * (INCA) ASC UART support
- */
- #include <config.h>
- #ifdef CONFIG_PURPLE
- #define serial_init asc_serial_init
- #define serial_putc asc_serial_putc
- #define serial_puts asc_serial_puts
- #define serial_getc asc_serial_getc
- #define serial_tstc asc_serial_tstc
- #define serial_setbrg asc_serial_setbrg
- #endif
- #include <common.h>
- #include <asm/inca-ip.h>
- #include "serial.h"
- #ifdef CONFIG_PURPLE
- #undef ASC_FIFO_PRESENT
- #define TOUT_LOOP 100000
- /* Set base address for second FPI interrupt control register bank */
- #define SFPI_INTCON_BASEADDR 0xBF0F0000
- /* Register offset from base address */
- #define FBS_ISR 0x00000000 /* Interrupt status register */
- #define FBS_IMR 0x00000008 /* Interrupt mask register */
- #define FBS_IDIS 0x00000010 /* Interrupt disable register */
- /* Interrupt status register bits */
- #define FBS_ISR_AT 0x00000040 /* ASC transmit interrupt */
- #define FBS_ISR_AR 0x00000020 /* ASC receive interrupt */
- #define FBS_ISR_AE 0x00000010 /* ASC error interrupt */
- #define FBS_ISR_AB 0x00000008 /* ASC transmit buffer interrupt */
- #define FBS_ISR_AS 0x00000004 /* ASC start of autobaud detection interrupt */
- #define FBS_ISR_AF 0x00000002 /* ASC end of autobaud detection interrupt */
- #else
- #define ASC_FIFO_PRESENT
- #endif
- #define SET_BIT(reg, mask) reg |= (mask)
- #define CLEAR_BIT(reg, mask) reg &= (~mask)
- #define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
- #define SET_BITS(reg, mask) SET_BIT(reg, mask)
- #define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
- extern uint incaip_get_fpiclk(void);
- static int serial_setopt (void);
- /* pointer to ASC register base address */
- static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
- /******************************************************************************
- *
- * serial_init - initialize a INCAASC channel
- *
- * This routine initializes the number of data bits, parity
- * and set the selected baud rate. Interrupts are disabled.
- * Set the modem control signals if the option is selected.
- *
- * RETURNS: N/A
- */
- int serial_init (void)
- {
- #ifdef CONFIG_INCA_IP
- /* we have to set PMU.EN13 bit to enable an ASC device*/
- INCAASC_PMU_ENABLE(13);
- #endif
-
- /* and we have to set CLC register*/
- CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
- SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
-
- /* initialy we are in async mode */
- pAsc->asc_con = ASCCON_M_8ASYNC;
- /* select input port */
- pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
- #ifdef ASC_FIFO_PRESENT
- /* TXFIFO's filling level */
- SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
- ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
- /* enable TXFIFO */
- SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
- /* RXFIFO's filling level */
- SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
- ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
- /* enable RXFIFO */
- SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
- #endif
- /* enable error signals */
- SET_BIT(pAsc->asc_con, ASCCON_FEN);
- SET_BIT(pAsc->asc_con, ASCCON_OEN);
- #ifdef CONFIG_INCA_IP
- /* acknowledge ASC interrupts */
- ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
- /* disable ASC interrupts */
- ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
- #endif
- #ifdef ASC_FIFO_PRESENT
- /* set FIFOs into the transparent mode */
- SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
- SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
- #endif
- /* set baud rate */
- serial_setbrg();
- /* set the options */
- serial_setopt();
-
- return 0;
- }
- void serial_setbrg (void)
- {
- ulong uiReloadValue, fdv;
- ulong f_ASC;
- #ifdef CONFIG_INCA_IP
- f_ASC = incaip_get_fpiclk();
- #else
- f_ASC = ASC_CLOCK_RATE;
- #endif
- #ifndef INCAASC_USE_FDV
- fdv = 2;
- uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
- #else
- fdv = INCAASC_FDV_HIGH_BAUDRATE;
- uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
- #endif /* INCAASC_USE_FDV */
-
- if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
- {
- #ifndef INCAASC_USE_FDV
- fdv = 3;
- uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
- #else
- fdv = INCAASC_FDV_LOW_BAUDRATE;
- uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
- #endif /* INCAASC_USE_FDV */
-
- if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
- {
- return; /* can't impossibly generate that baud rate */
- }
- }
- /* Disable Baud Rate Generator; BG should only be written when R=0 */
- CLEAR_BIT(pAsc->asc_con, ASCCON_R);
- #ifndef INCAASC_USE_FDV
- /*
- * Disable Fractional Divider (FDE)
- * Divide clock by reload-value + constant (BRS)
- */
- /* FDE = 0 */
- CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
- if ( fdv == 2 )
- CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
- else
- SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
- #else /* INCAASC_USE_FDV */
- /* Enable Fractional Divider */
- SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
- /* Set fractional divider value */
- pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
- #endif /* INCAASC_USE_FDV */
- /* Set reload value in BG */
- pAsc->asc_bg = uiReloadValue;
- /* Enable Baud Rate Generator */
- SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
- }
- /*******************************************************************************
- *
- * serial_setopt - set the serial options
- *
- * Set the channel operating mode to that specified. Following options
- * are supported: CREAD, CSIZE, PARENB, and PARODD.
- *
- * Note, this routine disables the transmitter. The calling routine
- * may have to re-enable it.
- *
- * RETURNS:
- * Returns 0 to indicate success, otherwise -1 is returned
- */
- static int serial_setopt (void)
- {
- ulong con;
- switch ( ASC_OPTIONS & ASCOPT_CSIZE )
- {
- /* 7-bit-data */
- case ASCOPT_CS7:
- con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
- break;
- /* 8-bit-data */
- case ASCOPT_CS8:
- if ( ASC_OPTIONS & ASCOPT_PARENB )
- con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
- else
- con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
- break;
-
- /*
- * only 7 and 8-bit frames are supported
- * if we don't use IOCTL extensions
- */
- default:
- return -1;
- }
- if ( ASC_OPTIONS & ASCOPT_STOPB )
- SET_BIT(con, ASCCON_STP); /* 2 stop bits */
- else
- CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
- if ( ASC_OPTIONS & ASCOPT_PARENB )
- SET_BIT(con, ASCCON_PEN); /* enable parity checking */
- else
- CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
-
- if ( ASC_OPTIONS & ASCOPT_PARODD )
- SET_BIT(con, ASCCON_ODD); /* odd parity */
- else
- CLEAR_BIT(con, ASCCON_ODD); /* even parity */
- if ( ASC_OPTIONS & ASCOPT_CREAD )
- SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
- pAsc->asc_con |= con;
- return 0;
- }
- void serial_putc (const char c)
- {
- #ifdef ASC_FIFO_PRESENT
- uint txFl = 0;
- #else
- uint timeout = 0;
- #endif
- if (c == '\n') serial_putc ('\r');
- #ifdef ASC_FIFO_PRESENT
- /* check do we have a free space in the TX FIFO */
- /* get current filling level */
- do
- {
- txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
- }
- while ( txFl == INCAASC_TXFIFO_FULL );
- #else
- while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
- FBS_ISR_AB))
- {
- if (timeout++ > TOUT_LOOP)
- {
- break;
- }
- }
- #endif
- pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
- #ifndef ASC_FIFO_PRESENT
- *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AB |
- FBS_ISR_AT;
- #endif
-
- /* check for errors */
- if ( pAsc->asc_con & ASCCON_OE )
- {
- SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
- return;
- }
- }
- void serial_puts (const char *s)
- {
- while (*s)
- {
- serial_putc (*s++);
- }
- }
- int serial_getc (void)
- {
- ulong symbol_mask;
- char c;
- while (!serial_tstc());
- symbol_mask =
- ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
-
- c = (char)(pAsc->asc_rbuf & symbol_mask);
- #ifndef ASC_FIFO_PRESENT
- *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AR;
- #endif
- return c;
- }
- int serial_tstc (void)
- {
- int res = 1;
- #ifdef ASC_FIFO_PRESENT
- if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
- {
- res = 0;
- }
- #else
- if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
- FBS_ISR_AR))
-
- {
- res = 0;
- }
- #endif
- else if ( pAsc->asc_con & ASCCON_FE )
- {
- SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
- res = 0;
- }
- else if ( pAsc->asc_con & ASCCON_PE )
- {
- SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
- res = 0;
- }
- else if ( pAsc->asc_con & ASCCON_OE )
- {
- SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
- res = 0;
- }
- return res;
- }
|