2 * (INCA) ASC UART support
6 #include <asm/inca-ip.h>
9 #define SET_BIT(reg, mask) reg |= (mask)
10 #define CLEAR_BIT(reg, mask) reg &= (~mask)
11 #define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
12 #define SET_BITS(reg, mask) SET_BIT(reg, mask)
13 #define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
15 extern uint incaip_get_fpiclk(void);
17 static int serial_setopt (void);
19 /* pointer to ASC register base address */
20 static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
22 /******************************************************************************
24 * serial_init - initialize a INCAASC channel
26 * This routine initializes the number of data bits, parity
27 * and set the selected baud rate. Interrupts are disabled.
28 * Set the modem control signals if the option is selected.
33 int serial_init (void)
35 /* we have to set PMU.EN13 bit to enable an ASC device*/
36 INCAASC_PMU_ENABLE(13);
38 /* and we have to set CLC register*/
39 CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
40 SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
42 /* initialy we are in async mode */
43 pAsc->asc_con = ASCCON_M_8ASYNC;
45 /* select input port */
46 pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
48 /* TXFIFO's filling level */
49 SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
50 ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
52 SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
54 /* RXFIFO's filling level */
55 SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
56 ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
58 SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
60 /* enable error signals */
61 SET_BIT(pAsc->asc_con, ASCCON_FEN);
62 SET_BIT(pAsc->asc_con, ASCCON_OEN);
64 /* acknowledge ASC interrupts */
65 ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
67 /* disable ASC interrupts */
68 ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
70 /* set FIFOs into the transparent mode */
71 SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
72 SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
83 void serial_setbrg (void)
85 ulong uiReloadValue, fdv;
88 f_ASC = incaip_get_fpiclk();
90 #ifndef INCAASC_USE_FDV
92 uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
94 fdv = INCAASC_FDV_HIGH_BAUDRATE;
95 uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
96 #endif /* INCAASC_USE_FDV */
98 if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
100 #ifndef INCAASC_USE_FDV
102 uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
104 fdv = INCAASC_FDV_LOW_BAUDRATE;
105 uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
106 #endif /* INCAASC_USE_FDV */
108 if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
110 return; /* can't impossibly generate that baud rate */
114 /* Disable Baud Rate Generator; BG should only be written when R=0 */
115 CLEAR_BIT(pAsc->asc_con, ASCCON_R);
117 #ifndef INCAASC_USE_FDV
119 * Disable Fractional Divider (FDE)
120 * Divide clock by reload-value + constant (BRS)
123 CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
126 CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
128 SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
130 #else /* INCAASC_USE_FDV */
132 /* Enable Fractional Divider */
133 SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
135 /* Set fractional divider value */
136 pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
138 #endif /* INCAASC_USE_FDV */
140 /* Set reload value in BG */
141 pAsc->asc_bg = uiReloadValue;
143 /* Enable Baud Rate Generator */
144 SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
147 /*******************************************************************************
149 * serial_setopt - set the serial options
151 * Set the channel operating mode to that specified. Following options
152 * are supported: CREAD, CSIZE, PARENB, and PARODD.
154 * Note, this routine disables the transmitter. The calling routine
155 * may have to re-enable it.
158 * Returns 0 to indicate success, otherwise -1 is returned
161 static int serial_setopt (void)
165 switch ( ASC_OPTIONS & ASCOPT_CSIZE )
169 con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
174 if ( ASC_OPTIONS & ASCOPT_PARENB )
175 con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
177 con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
181 * only 7 and 8-bit frames are supported
182 * if we don't use IOCTL extensions
188 if ( ASC_OPTIONS & ASCOPT_STOPB )
189 SET_BIT(con, ASCCON_STP); /* 2 stop bits */
191 CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
193 if ( ASC_OPTIONS & ASCOPT_PARENB )
194 SET_BIT(con, ASCCON_PEN); /* enable parity checking */
196 CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
198 if ( ASC_OPTIONS & ASCOPT_PARODD )
199 SET_BIT(con, ASCCON_ODD); /* odd parity */
201 CLEAR_BIT(con, ASCCON_ODD); /* even parity */
203 if ( ASC_OPTIONS & ASCOPT_CREAD )
204 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
206 pAsc->asc_con |= con;
211 void serial_putc (const char c)
215 if (c == '\n') serial_putc ('\r');
217 /* check do we have a free space in the TX FIFO */
218 /* get current filling level */
221 txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
223 while ( txFl == INCAASC_TXFIFO_FULL );
225 pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
226 /* check for errors */
227 if ( pAsc->asc_con & ASCCON_OE )
229 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
234 void serial_puts (const char *s)
242 int serial_getc (void)
247 while (!serial_tstc());
250 ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
252 c = (char)(pAsc->asc_rbuf & symbol_mask);
257 int serial_tstc (void)
261 if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
265 else if ( pAsc->asc_con & ASCCON_FE )
267 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
270 else if ( pAsc->asc_con & ASCCON_PE )
272 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
275 else if ( pAsc->asc_con & ASCCON_OE )
277 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);