2
* (INCA) ASC UART support
8
#define serial_init asc_serial_init
9
#define serial_putc asc_serial_putc
10
#define serial_puts asc_serial_puts
11
#define serial_getc asc_serial_getc
12
#define serial_tstc asc_serial_tstc
13
#define serial_setbrg asc_serial_setbrg
17
#include <asm/inca-ip.h>
18
#include "asc_serial.h"
22
#undef ASC_FIFO_PRESENT
23
#define TOUT_LOOP 100000
25
/* Set base address for second FPI interrupt control register bank */
26
#define SFPI_INTCON_BASEADDR 0xBF0F0000
28
/* Register offset from base address */
29
#define FBS_ISR 0x00000000 /* Interrupt status register */
30
#define FBS_IMR 0x00000008 /* Interrupt mask register */
31
#define FBS_IDIS 0x00000010 /* Interrupt disable register */
33
/* Interrupt status register bits */
34
#define FBS_ISR_AT 0x00000040 /* ASC transmit interrupt */
35
#define FBS_ISR_AR 0x00000020 /* ASC receive interrupt */
36
#define FBS_ISR_AE 0x00000010 /* ASC error interrupt */
37
#define FBS_ISR_AB 0x00000008 /* ASC transmit buffer interrupt */
38
#define FBS_ISR_AS 0x00000004 /* ASC start of autobaud detection interrupt */
39
#define FBS_ISR_AF 0x00000002 /* ASC end of autobaud detection interrupt */
43
#define ASC_FIFO_PRESENT
48
#define SET_BIT(reg, mask) reg |= (mask)
49
#define CLEAR_BIT(reg, mask) reg &= (~mask)
50
#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
51
#define SET_BITS(reg, mask) SET_BIT(reg, mask)
52
#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
54
extern uint incaip_get_fpiclk(void);
56
static int serial_setopt (void);
58
/* pointer to ASC register base address */
59
static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
61
/******************************************************************************
63
* serial_init - initialize a INCAASC channel
65
* This routine initializes the number of data bits, parity
66
* and set the selected baud rate. Interrupts are disabled.
67
* Set the modem control signals if the option is selected.
72
int serial_init (void)
75
/* we have to set PMU.EN13 bit to enable an ASC device*/
76
INCAASC_PMU_ENABLE(13);
79
/* and we have to set CLC register*/
80
CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
81
SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
83
/* initialy we are in async mode */
84
pAsc->asc_con = ASCCON_M_8ASYNC;
86
/* select input port */
87
pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
89
#ifdef ASC_FIFO_PRESENT
90
/* TXFIFO's filling level */
91
SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
92
ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
94
SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
96
/* RXFIFO's filling level */
97
SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
98
ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
100
SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
103
/* enable error signals */
104
SET_BIT(pAsc->asc_con, ASCCON_FEN);
105
SET_BIT(pAsc->asc_con, ASCCON_OEN);
107
#ifdef CONFIG_INCA_IP
108
/* acknowledge ASC interrupts */
109
ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
111
/* disable ASC interrupts */
112
ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
115
#ifdef ASC_FIFO_PRESENT
116
/* set FIFOs into the transparent mode */
117
SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
118
SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
124
/* set the options */
130
void serial_setbrg (void)
132
ulong uiReloadValue, fdv;
135
#ifdef CONFIG_INCA_IP
136
f_ASC = incaip_get_fpiclk();
138
f_ASC = ASC_CLOCK_RATE;
141
#ifndef INCAASC_USE_FDV
143
uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
145
fdv = INCAASC_FDV_HIGH_BAUDRATE;
146
uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
147
#endif /* INCAASC_USE_FDV */
149
if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
151
#ifndef INCAASC_USE_FDV
153
uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
155
fdv = INCAASC_FDV_LOW_BAUDRATE;
156
uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
157
#endif /* INCAASC_USE_FDV */
159
if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
161
return; /* can't impossibly generate that baud rate */
165
/* Disable Baud Rate Generator; BG should only be written when R=0 */
166
CLEAR_BIT(pAsc->asc_con, ASCCON_R);
168
#ifndef INCAASC_USE_FDV
170
* Disable Fractional Divider (FDE)
171
* Divide clock by reload-value + constant (BRS)
174
CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
177
CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
179
SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
181
#else /* INCAASC_USE_FDV */
183
/* Enable Fractional Divider */
184
SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
186
/* Set fractional divider value */
187
pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
189
#endif /* INCAASC_USE_FDV */
191
/* Set reload value in BG */
192
pAsc->asc_bg = uiReloadValue;
194
/* Enable Baud Rate Generator */
195
SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
198
/*******************************************************************************
200
* serial_setopt - set the serial options
202
* Set the channel operating mode to that specified. Following options
203
* are supported: CREAD, CSIZE, PARENB, and PARODD.
205
* Note, this routine disables the transmitter. The calling routine
206
* may have to re-enable it.
209
* Returns 0 to indicate success, otherwise -1 is returned
212
static int serial_setopt (void)
216
switch ( ASC_OPTIONS & ASCOPT_CSIZE )
220
con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
225
if ( ASC_OPTIONS & ASCOPT_PARENB )
226
con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
228
con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
232
* only 7 and 8-bit frames are supported
233
* if we don't use IOCTL extensions
239
if ( ASC_OPTIONS & ASCOPT_STOPB )
240
SET_BIT(con, ASCCON_STP); /* 2 stop bits */
242
CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
244
if ( ASC_OPTIONS & ASCOPT_PARENB )
245
SET_BIT(con, ASCCON_PEN); /* enable parity checking */
247
CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
249
if ( ASC_OPTIONS & ASCOPT_PARODD )
250
SET_BIT(con, ASCCON_ODD); /* odd parity */
252
CLEAR_BIT(con, ASCCON_ODD); /* even parity */
254
if ( ASC_OPTIONS & ASCOPT_CREAD )
255
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
257
pAsc->asc_con |= con;
262
void serial_putc (const char c)
264
#ifdef ASC_FIFO_PRESENT
270
if (c == '\n') serial_putc ('\r');
272
#ifdef ASC_FIFO_PRESENT
273
/* check do we have a free space in the TX FIFO */
274
/* get current filling level */
277
txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
279
while ( txFl == INCAASC_TXFIFO_FULL );
282
while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
285
if (timeout++ > TOUT_LOOP)
292
pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
294
#ifndef ASC_FIFO_PRESENT
295
*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AB |
299
/* check for errors */
300
if ( pAsc->asc_con & ASCCON_OE )
302
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
307
void serial_puts (const char *s)
315
int serial_getc (void)
320
while (!serial_tstc());
323
((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
325
c = (char)(pAsc->asc_rbuf & symbol_mask);
327
#ifndef ASC_FIFO_PRESENT
328
*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AR;
334
int serial_tstc (void)
338
#ifdef ASC_FIFO_PRESENT
339
if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
344
if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
351
else if ( pAsc->asc_con & ASCCON_FE )
353
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
356
else if ( pAsc->asc_con & ASCCON_PE )
358
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
361
else if ( pAsc->asc_con & ASCCON_OE )
363
SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);