2 * (INCA) ASC UART support
7 #if defined(CONFIG_PURPLE) || defined(CONFIG_INCA_IP)
10 #define serial_init asc_serial_init
11 #define serial_putc asc_serial_putc
12 #define serial_puts asc_serial_puts
13 #define serial_getc asc_serial_getc
14 #define serial_tstc asc_serial_tstc
15 #define serial_setbrg asc_serial_setbrg
19 #include <asm/inca-ip.h>
20 #include "asc_serial.h"
24 #undef ASC_FIFO_PRESENT
25 #define TOUT_LOOP 100000
27 /* Set base address for second FPI interrupt control register bank */
28 #define SFPI_INTCON_BASEADDR 0xBF0F0000
30 /* Register offset from base address */
31 #define FBS_ISR 0x00000000 /* Interrupt status register */
32 #define FBS_IMR 0x00000008 /* Interrupt mask register */
33 #define FBS_IDIS 0x00000010 /* Interrupt disable register */
35 /* Interrupt status register bits */
36 #define FBS_ISR_AT 0x00000040 /* ASC transmit interrupt */
37 #define FBS_ISR_AR 0x00000020 /* ASC receive interrupt */
38 #define FBS_ISR_AE 0x00000010 /* ASC error interrupt */
39 #define FBS_ISR_AB 0x00000008 /* ASC transmit buffer interrupt */
40 #define FBS_ISR_AS 0x00000004 /* ASC start of autobaud detection interrupt */
41 #define FBS_ISR_AF 0x00000002 /* ASC end of autobaud detection interrupt */
45 #define ASC_FIFO_PRESENT
50 #define SET_BIT(reg, mask) reg |= (mask)
51 #define CLEAR_BIT(reg, mask) reg &= (~mask)
52 #define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
53 #define SET_BITS(reg, mask) SET_BIT(reg, mask)
54 #define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
56 extern uint
incaip_get_fpiclk(void);
58 static int serial_setopt (void);
60 /* pointer to ASC register base address */
61 static volatile incaAsc_t
*pAsc
= (incaAsc_t
*)INCA_IP_ASC
;
63 /******************************************************************************
65 * serial_init - initialize a INCAASC channel
67 * This routine initializes the number of data bits, parity
68 * and set the selected baud rate. Interrupts are disabled.
69 * Set the modem control signals if the option is selected.
74 int serial_init (void)
77 /* we have to set PMU.EN13 bit to enable an ASC device*/
78 INCAASC_PMU_ENABLE(13);
81 /* and we have to set CLC register*/
82 CLEAR_BIT(pAsc
->asc_clc
, ASCCLC_DISS
);
83 SET_BITFIELD(pAsc
->asc_clc
, ASCCLC_RMCMASK
, ASCCLC_RMCOFFSET
, 0x0001);
85 /* initialy we are in async mode */
86 pAsc
->asc_con
= ASCCON_M_8ASYNC
;
88 /* select input port */
89 pAsc
->asc_pisel
= (CONSOLE_TTY
& 0x1);
91 #ifdef ASC_FIFO_PRESENT
92 /* TXFIFO's filling level */
93 SET_BITFIELD(pAsc
->asc_txfcon
, ASCTXFCON_TXFITLMASK
,
94 ASCTXFCON_TXFITLOFF
, INCAASC_TXFIFO_FL
);
96 SET_BIT(pAsc
->asc_txfcon
, ASCTXFCON_TXFEN
);
98 /* RXFIFO's filling level */
99 SET_BITFIELD(pAsc
->asc_txfcon
, ASCRXFCON_RXFITLMASK
,
100 ASCRXFCON_RXFITLOFF
, INCAASC_RXFIFO_FL
);
102 SET_BIT(pAsc
->asc_rxfcon
, ASCRXFCON_RXFEN
);
105 /* enable error signals */
106 SET_BIT(pAsc
->asc_con
, ASCCON_FEN
);
107 SET_BIT(pAsc
->asc_con
, ASCCON_OEN
);
109 #ifdef CONFIG_INCA_IP
110 /* acknowledge ASC interrupts */
111 ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL
);
113 /* disable ASC interrupts */
114 ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL
);
117 #ifdef ASC_FIFO_PRESENT
118 /* set FIFOs into the transparent mode */
119 SET_BIT(pAsc
->asc_txfcon
, ASCTXFCON_TXTMEN
);
120 SET_BIT(pAsc
->asc_rxfcon
, ASCRXFCON_RXTMEN
);
126 /* set the options */
132 void serial_setbrg (void)
134 ulong uiReloadValue
, fdv
;
137 #ifdef CONFIG_INCA_IP
138 f_ASC
= incaip_get_fpiclk();
140 f_ASC
= ASC_CLOCK_RATE
;
143 #ifndef INCAASC_USE_FDV
145 uiReloadValue
= (f_ASC
/ (fdv
* 16 * CONFIG_BAUDRATE
)) - 1;
147 fdv
= INCAASC_FDV_HIGH_BAUDRATE
;
148 uiReloadValue
= (f_ASC
/ (8192 * CONFIG_BAUDRATE
/ fdv
)) - 1;
149 #endif /* INCAASC_USE_FDV */
151 if ( (uiReloadValue
< 0) || (uiReloadValue
> 8191) )
153 #ifndef INCAASC_USE_FDV
155 uiReloadValue
= (f_ASC
/ (fdv
* 16 * CONFIG_BAUDRATE
)) - 1;
157 fdv
= INCAASC_FDV_LOW_BAUDRATE
;
158 uiReloadValue
= (f_ASC
/ (8192 * CONFIG_BAUDRATE
/ fdv
)) - 1;
159 #endif /* INCAASC_USE_FDV */
161 if ( (uiReloadValue
< 0) || (uiReloadValue
> 8191) )
163 return; /* can't impossibly generate that baud rate */
167 /* Disable Baud Rate Generator; BG should only be written when R=0 */
168 CLEAR_BIT(pAsc
->asc_con
, ASCCON_R
);
170 #ifndef INCAASC_USE_FDV
172 * Disable Fractional Divider (FDE)
173 * Divide clock by reload-value + constant (BRS)
176 CLEAR_BIT(pAsc
->asc_con
, ASCCON_FDE
);
179 CLEAR_BIT(pAsc
->asc_con
, ASCCON_BRS
); /* BRS = 0 */
181 SET_BIT(pAsc
->asc_con
, ASCCON_BRS
); /* BRS = 1 */
183 #else /* INCAASC_USE_FDV */
185 /* Enable Fractional Divider */
186 SET_BIT(pAsc
->asc_con
, ASCCON_FDE
); /* FDE = 1 */
188 /* Set fractional divider value */
189 pAsc
->asc_fdv
= fdv
& ASCFDV_VALUE_MASK
;
191 #endif /* INCAASC_USE_FDV */
193 /* Set reload value in BG */
194 pAsc
->asc_bg
= uiReloadValue
;
196 /* Enable Baud Rate Generator */
197 SET_BIT(pAsc
->asc_con
, ASCCON_R
); /* R = 1 */
200 /*******************************************************************************
202 * serial_setopt - set the serial options
204 * Set the channel operating mode to that specified. Following options
205 * are supported: CREAD, CSIZE, PARENB, and PARODD.
207 * Note, this routine disables the transmitter. The calling routine
208 * may have to re-enable it.
211 * Returns 0 to indicate success, otherwise -1 is returned
214 static int serial_setopt (void)
218 switch ( ASC_OPTIONS
& ASCOPT_CSIZE
)
222 con
= ASCCON_M_7ASYNCPAR
; /* 7-bit-data and parity bit */
227 if ( ASC_OPTIONS
& ASCOPT_PARENB
)
228 con
= ASCCON_M_8ASYNCPAR
; /* 8-bit-data and parity bit */
230 con
= ASCCON_M_8ASYNC
; /* 8-bit-data no parity */
234 * only 7 and 8-bit frames are supported
235 * if we don't use IOCTL extensions
241 if ( ASC_OPTIONS
& ASCOPT_STOPB
)
242 SET_BIT(con
, ASCCON_STP
); /* 2 stop bits */
244 CLEAR_BIT(con
, ASCCON_STP
); /* 1 stop bit */
246 if ( ASC_OPTIONS
& ASCOPT_PARENB
)
247 SET_BIT(con
, ASCCON_PEN
); /* enable parity checking */
249 CLEAR_BIT(con
, ASCCON_PEN
); /* disable parity checking */
251 if ( ASC_OPTIONS
& ASCOPT_PARODD
)
252 SET_BIT(con
, ASCCON_ODD
); /* odd parity */
254 CLEAR_BIT(con
, ASCCON_ODD
); /* even parity */
256 if ( ASC_OPTIONS
& ASCOPT_CREAD
)
257 SET_BIT(pAsc
->asc_whbcon
, ASCWHBCON_SETREN
); /* Receiver enable */
259 pAsc
->asc_con
|= con
;
264 void serial_putc (const char c
)
266 #ifdef ASC_FIFO_PRESENT
272 if (c
== '\n') serial_putc ('\r');
274 #ifdef ASC_FIFO_PRESENT
275 /* check do we have a free space in the TX FIFO */
276 /* get current filling level */
279 txFl
= ( pAsc
->asc_fstat
& ASCFSTAT_TXFFLMASK
) >> ASCFSTAT_TXFFLOFF
;
281 while ( txFl
== INCAASC_TXFIFO_FULL
);
284 while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR
+ FBS_ISR
) &
287 if (timeout
++ > TOUT_LOOP
)
294 pAsc
->asc_tbuf
= c
; /* write char to Transmit Buffer Register */
296 #ifndef ASC_FIFO_PRESENT
297 *(volatile unsigned long*)(SFPI_INTCON_BASEADDR
+ FBS_ISR
) = FBS_ISR_AB
|
301 /* check for errors */
302 if ( pAsc
->asc_con
& ASCCON_OE
)
304 SET_BIT(pAsc
->asc_whbcon
, ASCWHBCON_CLROE
);
309 void serial_puts (const char *s
)
317 int serial_getc (void)
322 while (!serial_tstc());
325 ((ASC_OPTIONS
& ASCOPT_CSIZE
) == ASCOPT_CS7
) ? (0x7f) : (0xff);
327 c
= (char)(pAsc
->asc_rbuf
& symbol_mask
);
329 #ifndef ASC_FIFO_PRESENT
330 *(volatile unsigned long*)(SFPI_INTCON_BASEADDR
+ FBS_ISR
) = FBS_ISR_AR
;
336 int serial_tstc (void)
340 #ifdef ASC_FIFO_PRESENT
341 if ( (pAsc
->asc_fstat
& ASCFSTAT_RXFFLMASK
) == 0 )
346 if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR
+ FBS_ISR
) &
353 else if ( pAsc
->asc_con
& ASCCON_FE
)
355 SET_BIT(pAsc
->asc_whbcon
, ASCWHBCON_CLRFE
);
358 else if ( pAsc
->asc_con
& ASCCON_PE
)
360 SET_BIT(pAsc
->asc_whbcon
, ASCWHBCON_CLRPE
);
363 else if ( pAsc
->asc_con
& ASCCON_OE
)
365 SET_BIT(pAsc
->asc_whbcon
, ASCWHBCON_CLROE
);
371 #endif /* CONFIG_PURPLE || CONFIG_INCA_IP */