2 * (INCA) ASC UART support
7 #include <asm/inca-ip.h>
8 #include "asc_serial.h"
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);}
17 extern uint incaip_get_fpiclk(void);
19 static int serial_setopt (void);
21 /* pointer to ASC register base address */
22 static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
24 /******************************************************************************
26 * serial_init - initialize a INCAASC channel
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.
35 int serial_init (void)
37 /* we have to set PMU.EN13 bit to enable an ASC device*/
38 INCAASC_PMU_ENABLE(13);
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);
44 /* initialy we are in async mode */
45 pAsc->asc_con = ASCCON_M_8ASYNC;
47 /* select input port */
48 pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
50 /* TXFIFO's filling level */
51 SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
52 ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
54 SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
56 /* RXFIFO's filling level */
57 SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
58 ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
60 SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
62 /* enable error signals */
63 SET_BIT(pAsc->asc_con, ASCCON_FEN);
64 SET_BIT(pAsc->asc_con, ASCCON_OEN);
66 /* acknowledge ASC interrupts */
67 ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
69 /* disable ASC interrupts */
70 ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
72 /* set FIFOs into the transparent mode */
73 SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
74 SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
85 void serial_setbrg (void)
87 ulong uiReloadValue, fdv;
90 f_ASC = incaip_get_fpiclk();
92 #ifndef INCAASC_USE_FDV
94 uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
96 fdv = INCAASC_FDV_HIGH_BAUDRATE;
97 uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
98 #endif /* INCAASC_USE_FDV */
100 if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
102 #ifndef INCAASC_USE_FDV
104 uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
106 fdv = INCAASC_FDV_LOW_BAUDRATE;
107 uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
108 #endif /* INCAASC_USE_FDV */
110 if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
112 return; /* can't impossibly generate that baud rate */
116 /* Disable Baud Rate Generator; BG should only be written when R=0 */
117 CLEAR_BIT(pAsc->asc_con, ASCCON_R);
119 #ifndef INCAASC_USE_FDV
121 * Disable Fractional Divider (FDE)
122 * Divide clock by reload-value + constant (BRS)
125 CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
128 CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
130 SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
132 #else /* INCAASC_USE_FDV */
134 /* Enable Fractional Divider */
135 SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
137 /* Set fractional divider value */
138 pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
140 #endif /* INCAASC_USE_FDV */
142 /* Set reload value in BG */
143 pAsc->asc_bg = uiReloadValue;
145 /* Enable Baud Rate Generator */
146 SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
149 /*******************************************************************************
151 * serial_setopt - set the serial options
153 * Set the channel operating mode to that specified. Following options
154 * are supported: CREAD, CSIZE, PARENB, and PARODD.
156 * Note, this routine disables the transmitter. The calling routine
157 * may have to re-enable it.
160 * Returns 0 to indicate success, otherwise -1 is returned
163 static int serial_setopt (void)
167 switch ( ASC_OPTIONS & ASCOPT_CSIZE )
171 con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
176 if ( ASC_OPTIONS & ASCOPT_PARENB )
177 con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
179 con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
183 * only 7 and 8-bit frames are supported
184 * if we don't use IOCTL extensions
190 if ( ASC_OPTIONS & ASCOPT_STOPB )
191 SET_BIT(con, ASCCON_STP); /* 2 stop bits */
193 CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
195 if ( ASC_OPTIONS & ASCOPT_PARENB )
196 SET_BIT(con, ASCCON_PEN); /* enable parity checking */
198 CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
200 if ( ASC_OPTIONS & ASCOPT_PARODD )
201 SET_BIT(con, ASCCON_ODD); /* odd parity */
203 CLEAR_BIT(con, ASCCON_ODD); /* even parity */
205 if ( ASC_OPTIONS & ASCOPT_CREAD )
206 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
208 pAsc->asc_con |= con;
213 void serial_putc (const char c)
217 if (c == '\n') serial_putc ('\r');
219 /* check do we have a free space in the TX FIFO */
220 /* get current filling level */
223 txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
225 while ( txFl == INCAASC_TXFIFO_FULL );
227 pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
229 /* check for errors */
230 if ( pAsc->asc_con & ASCCON_OE )
232 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
237 void serial_puts (const char *s)
245 int serial_getc (void)
250 while (!serial_tstc());
253 ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
255 c = (char)(pAsc->asc_rbuf & symbol_mask);
260 int serial_tstc (void)
264 if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
268 else if ( pAsc->asc_con & ASCCON_FE )
270 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
273 else if ( pAsc->asc_con & ASCCON_PE )
275 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
278 else if ( pAsc->asc_con & ASCCON_OE )
280 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);