]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/mips/cpu/mips32/incaip/asc_serial.c
nand: remove CONFIG_SYS_NAND_PAGE_SIZE
[karo-tx-uboot.git] / arch / mips / cpu / mips32 / incaip / asc_serial.c
1 /*
2  * (INCA) ASC UART support
3  */
4
5 #include <config.h>
6 #include <common.h>
7 #include <asm/inca-ip.h>
8 #include <serial.h>
9 #include <linux/compiler.h>
10 #include "asc_serial.h"
11
12
13 #define SET_BIT(reg, mask)                  reg |= (mask)
14 #define CLEAR_BIT(reg, mask)                reg &= (~mask)
15 #define CLEAR_BITS(reg, mask)               CLEAR_BIT(reg, mask)
16 #define SET_BITS(reg, mask)                 SET_BIT(reg, mask)
17 #define SET_BITFIELD(reg, mask, off, val)   {reg &= (~mask); reg |= (val << off);}
18
19 extern uint incaip_get_fpiclk(void);
20
21 static int serial_setopt (void);
22
23 /* pointer to ASC register base address */
24 static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
25
26 /******************************************************************************
27 *
28 * serial_init - initialize a INCAASC channel
29 *
30 * This routine initializes the number of data bits, parity
31 * and set the selected baud rate. Interrupts are disabled.
32 * Set the modem control signals if the option is selected.
33 *
34 * RETURNS: N/A
35 */
36
37 static int asc_serial_init(void)
38 {
39     /* we have to set PMU.EN13 bit to enable an ASC device*/
40     INCAASC_PMU_ENABLE(13);
41
42     /* and we have to set CLC register*/
43     CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
44     SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
45
46     /* initialy we are in async mode */
47     pAsc->asc_con = ASCCON_M_8ASYNC;
48
49     /* select input port */
50     pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
51
52     /* TXFIFO's filling level */
53     SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
54                     ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
55     /* enable TXFIFO */
56     SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
57
58     /* RXFIFO's filling level */
59     SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
60                     ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
61     /* enable RXFIFO */
62     SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
63
64     /* enable error signals */
65     SET_BIT(pAsc->asc_con, ASCCON_FEN);
66     SET_BIT(pAsc->asc_con, ASCCON_OEN);
67
68     /* acknowledge ASC interrupts */
69     ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
70
71     /* disable ASC interrupts */
72     ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
73
74     /* set FIFOs into the transparent mode */
75     SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
76     SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
77
78     /* set baud rate */
79     serial_setbrg();
80
81     /* set the options */
82     serial_setopt();
83
84     return 0;
85 }
86
87 static void asc_serial_setbrg(void)
88 {
89     ulong      uiReloadValue, fdv;
90     ulong      f_ASC;
91
92     f_ASC = incaip_get_fpiclk();
93
94 #ifndef INCAASC_USE_FDV
95     fdv = 2;
96     uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
97 #else
98     fdv = INCAASC_FDV_HIGH_BAUDRATE;
99     uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
100 #endif /* INCAASC_USE_FDV */
101
102     if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
103     {
104 #ifndef INCAASC_USE_FDV
105         fdv = 3;
106         uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
107 #else
108         fdv = INCAASC_FDV_LOW_BAUDRATE;
109         uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
110 #endif /* INCAASC_USE_FDV */
111
112         if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
113         {
114             return;    /* can't impossibly generate that baud rate */
115         }
116     }
117
118     /* Disable Baud Rate Generator; BG should only be written when R=0 */
119     CLEAR_BIT(pAsc->asc_con, ASCCON_R);
120
121 #ifndef INCAASC_USE_FDV
122     /*
123      * Disable Fractional Divider (FDE)
124      * Divide clock by reload-value + constant (BRS)
125      */
126     /* FDE = 0 */
127     CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
128
129     if ( fdv == 2 )
130         CLEAR_BIT(pAsc->asc_con, ASCCON_BRS);   /* BRS = 0 */
131     else
132         SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
133
134 #else /* INCAASC_USE_FDV */
135
136     /* Enable Fractional Divider */
137     SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
138
139     /* Set fractional divider value */
140     pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
141
142 #endif /* INCAASC_USE_FDV */
143
144     /* Set reload value in BG */
145     pAsc->asc_bg = uiReloadValue;
146
147     /* Enable Baud Rate Generator */
148     SET_BIT(pAsc->asc_con, ASCCON_R);           /* R = 1 */
149 }
150
151 /*******************************************************************************
152 *
153 * serial_setopt - set the serial options
154 *
155 * Set the channel operating mode to that specified. Following options
156 * are supported: CREAD, CSIZE, PARENB, and PARODD.
157 *
158 * Note, this routine disables the transmitter.  The calling routine
159 * may have to re-enable it.
160 *
161 * RETURNS:
162 * Returns 0 to indicate success, otherwise -1 is returned
163 */
164
165 static int serial_setopt (void)
166 {
167     ulong  con;
168
169     switch ( ASC_OPTIONS & ASCOPT_CSIZE )
170     {
171     /* 7-bit-data */
172     case ASCOPT_CS7:
173         con = ASCCON_M_7ASYNCPAR;   /* 7-bit-data and parity bit */
174         break;
175
176     /* 8-bit-data */
177     case ASCOPT_CS8:
178         if ( ASC_OPTIONS & ASCOPT_PARENB )
179             con = ASCCON_M_8ASYNCPAR;   /* 8-bit-data and parity bit */
180         else
181             con = ASCCON_M_8ASYNC;      /* 8-bit-data no parity */
182         break;
183
184     /*
185      *  only 7 and 8-bit frames are supported
186      *  if we don't use IOCTL extensions
187      */
188     default:
189         return -1;
190     }
191
192     if ( ASC_OPTIONS & ASCOPT_STOPB )
193         SET_BIT(con, ASCCON_STP);       /* 2 stop bits */
194     else
195         CLEAR_BIT(con, ASCCON_STP);     /* 1 stop bit */
196
197     if ( ASC_OPTIONS & ASCOPT_PARENB )
198         SET_BIT(con, ASCCON_PEN);           /* enable parity checking */
199     else
200         CLEAR_BIT(con, ASCCON_PEN);         /* disable parity checking */
201
202     if ( ASC_OPTIONS & ASCOPT_PARODD )
203         SET_BIT(con, ASCCON_ODD);       /* odd parity */
204     else
205         CLEAR_BIT(con, ASCCON_ODD);     /* even parity */
206
207     if ( ASC_OPTIONS & ASCOPT_CREAD )
208         SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
209
210     pAsc->asc_con |= con;
211
212     return 0;
213 }
214
215 static void asc_serial_putc(const char c)
216 {
217     uint txFl = 0;
218
219     if (c == '\n') serial_putc ('\r');
220
221     /* check do we have a free space in the TX FIFO */
222     /* get current filling level */
223     do
224     {
225         txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
226     }
227     while ( txFl == INCAASC_TXFIFO_FULL );
228
229     pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
230
231     /* check for errors */
232     if ( pAsc->asc_con & ASCCON_OE )
233     {
234         SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
235         return;
236     }
237 }
238
239 static int asc_serial_getc(void)
240 {
241     ulong symbol_mask;
242     char c;
243
244     while (!serial_tstc());
245
246     symbol_mask =
247         ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
248
249     c = (char)(pAsc->asc_rbuf & symbol_mask);
250
251     return c;
252 }
253
254 static int asc_serial_tstc(void)
255 {
256     int res = 1;
257
258     if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
259     {
260         res = 0;
261     }
262     else if ( pAsc->asc_con & ASCCON_FE )
263     {
264         SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
265         res = 0;
266     }
267     else if ( pAsc->asc_con & ASCCON_PE )
268     {
269         SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
270         res = 0;
271     }
272     else if ( pAsc->asc_con & ASCCON_OE )
273     {
274         SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
275         res = 0;
276     }
277
278     return res;
279 }
280
281 static struct serial_device asc_serial_drv = {
282         .name   = "asc_serial",
283         .start  = asc_serial_init,
284         .stop   = NULL,
285         .setbrg = asc_serial_setbrg,
286         .putc   = asc_serial_putc,
287         .puts   = default_serial_puts,
288         .getc   = asc_serial_getc,
289         .tstc   = asc_serial_tstc,
290 };
291
292 void asc_serial_initialize(void)
293 {
294         serial_register(&asc_serial_drv);
295 }
296
297 __weak struct serial_device *default_serial_console(void)
298 {
299         return &asc_serial_drv;
300 }