~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to cpu/mips/asc_serial.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (INCA) ASC UART support
 
3
 */
 
4
 
 
5
#include <config.h>
 
6
 
 
7
#ifdef CONFIG_PURPLE
 
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
 
14
#endif
 
15
 
 
16
#include <common.h>
 
17
#include <asm/inca-ip.h>
 
18
#include "asc_serial.h"
 
19
 
 
20
#ifdef CONFIG_PURPLE
 
21
 
 
22
#undef ASC_FIFO_PRESENT
 
23
#define TOUT_LOOP       100000
 
24
 
 
25
/* Set base address for second FPI interrupt control register bank */
 
26
#define SFPI_INTCON_BASEADDR    0xBF0F0000
 
27
 
 
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 */
 
32
 
 
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 */
 
40
 
 
41
#else
 
42
 
 
43
#define ASC_FIFO_PRESENT
 
44
 
 
45
#endif
 
46
 
 
47
 
 
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);}
 
53
 
 
54
extern uint incaip_get_fpiclk(void);
 
55
 
 
56
static int serial_setopt (void);
 
57
 
 
58
/* pointer to ASC register base address */
 
59
static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
 
60
 
 
61
/******************************************************************************
 
62
*
 
63
* serial_init - initialize a INCAASC channel
 
64
*
 
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.
 
68
*
 
69
* RETURNS: N/A
 
70
*/
 
71
 
 
72
int serial_init (void)
 
73
{
 
74
#ifdef CONFIG_INCA_IP
 
75
    /* we have to set PMU.EN13 bit to enable an ASC device*/
 
76
    INCAASC_PMU_ENABLE(13);
 
77
#endif
 
78
 
 
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);
 
82
 
 
83
    /* initialy we are in async mode */
 
84
    pAsc->asc_con = ASCCON_M_8ASYNC;
 
85
 
 
86
    /* select input port */
 
87
    pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
 
88
 
 
89
#ifdef ASC_FIFO_PRESENT
 
90
    /* TXFIFO's filling level */
 
91
    SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
 
92
                    ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
 
93
    /* enable TXFIFO */
 
94
    SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
 
95
 
 
96
    /* RXFIFO's filling level */
 
97
    SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
 
98
                    ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
 
99
    /* enable RXFIFO */
 
100
    SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
 
101
#endif
 
102
 
 
103
    /* enable error signals */
 
104
    SET_BIT(pAsc->asc_con, ASCCON_FEN);
 
105
    SET_BIT(pAsc->asc_con, ASCCON_OEN);
 
106
 
 
107
#ifdef CONFIG_INCA_IP
 
108
    /* acknowledge ASC interrupts */
 
109
    ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
 
110
 
 
111
    /* disable ASC interrupts */
 
112
    ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
 
113
#endif
 
114
 
 
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);
 
119
#endif
 
120
 
 
121
    /* set baud rate */
 
122
    serial_setbrg();
 
123
 
 
124
    /* set the options */
 
125
    serial_setopt();
 
126
 
 
127
    return 0;
 
128
}
 
129
 
 
130
void serial_setbrg (void)
 
131
{
 
132
    ulong      uiReloadValue, fdv;
 
133
    ulong      f_ASC;
 
134
 
 
135
#ifdef CONFIG_INCA_IP
 
136
    f_ASC = incaip_get_fpiclk();
 
137
#else
 
138
    f_ASC = ASC_CLOCK_RATE;
 
139
#endif
 
140
 
 
141
#ifndef INCAASC_USE_FDV
 
142
    fdv = 2;
 
143
    uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
 
144
#else
 
145
    fdv = INCAASC_FDV_HIGH_BAUDRATE;
 
146
    uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
 
147
#endif /* INCAASC_USE_FDV */
 
148
 
 
149
    if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
 
150
    {
 
151
#ifndef INCAASC_USE_FDV
 
152
        fdv = 3;
 
153
        uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
 
154
#else
 
155
        fdv = INCAASC_FDV_LOW_BAUDRATE;
 
156
        uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
 
157
#endif /* INCAASC_USE_FDV */
 
158
 
 
159
        if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
 
160
        {
 
161
            return;    /* can't impossibly generate that baud rate */
 
162
        }
 
163
    }
 
164
 
 
165
    /* Disable Baud Rate Generator; BG should only be written when R=0 */
 
166
    CLEAR_BIT(pAsc->asc_con, ASCCON_R);
 
167
 
 
168
#ifndef INCAASC_USE_FDV
 
169
    /*
 
170
     * Disable Fractional Divider (FDE)
 
171
     * Divide clock by reload-value + constant (BRS)
 
172
     */
 
173
    /* FDE = 0 */
 
174
    CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
 
175
 
 
176
    if ( fdv == 2 )
 
177
        CLEAR_BIT(pAsc->asc_con, ASCCON_BRS);   /* BRS = 0 */
 
178
    else
 
179
        SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
 
180
 
 
181
#else /* INCAASC_USE_FDV */
 
182
 
 
183
    /* Enable Fractional Divider */
 
184
    SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
 
185
 
 
186
    /* Set fractional divider value */
 
187
    pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
 
188
 
 
189
#endif /* INCAASC_USE_FDV */
 
190
 
 
191
    /* Set reload value in BG */
 
192
    pAsc->asc_bg = uiReloadValue;
 
193
 
 
194
    /* Enable Baud Rate Generator */
 
195
    SET_BIT(pAsc->asc_con, ASCCON_R);           /* R = 1 */
 
196
}
 
197
 
 
198
/*******************************************************************************
 
199
*
 
200
* serial_setopt - set the serial options
 
201
*
 
202
* Set the channel operating mode to that specified. Following options
 
203
* are supported: CREAD, CSIZE, PARENB, and PARODD.
 
204
*
 
205
* Note, this routine disables the transmitter.  The calling routine
 
206
* may have to re-enable it.
 
207
*
 
208
* RETURNS:
 
209
* Returns 0 to indicate success, otherwise -1 is returned
 
210
*/
 
211
 
 
212
static int serial_setopt (void)
 
213
{
 
214
    ulong  con;
 
215
 
 
216
    switch ( ASC_OPTIONS & ASCOPT_CSIZE )
 
217
    {
 
218
    /* 7-bit-data */
 
219
    case ASCOPT_CS7:
 
220
        con = ASCCON_M_7ASYNCPAR;   /* 7-bit-data and parity bit */
 
221
        break;
 
222
 
 
223
    /* 8-bit-data */
 
224
    case ASCOPT_CS8:
 
225
        if ( ASC_OPTIONS & ASCOPT_PARENB )
 
226
            con = ASCCON_M_8ASYNCPAR;   /* 8-bit-data and parity bit */
 
227
        else
 
228
            con = ASCCON_M_8ASYNC;      /* 8-bit-data no parity */
 
229
        break;
 
230
 
 
231
    /*
 
232
     *  only 7 and 8-bit frames are supported
 
233
     *  if we don't use IOCTL extensions
 
234
     */
 
235
    default:
 
236
        return -1;
 
237
    }
 
238
 
 
239
    if ( ASC_OPTIONS & ASCOPT_STOPB )
 
240
        SET_BIT(con, ASCCON_STP);       /* 2 stop bits */
 
241
    else
 
242
        CLEAR_BIT(con, ASCCON_STP);     /* 1 stop bit */
 
243
 
 
244
    if ( ASC_OPTIONS & ASCOPT_PARENB )
 
245
        SET_BIT(con, ASCCON_PEN);           /* enable parity checking */
 
246
    else
 
247
        CLEAR_BIT(con, ASCCON_PEN);         /* disable parity checking */
 
248
 
 
249
    if ( ASC_OPTIONS & ASCOPT_PARODD )
 
250
        SET_BIT(con, ASCCON_ODD);       /* odd parity */
 
251
    else
 
252
        CLEAR_BIT(con, ASCCON_ODD);     /* even parity */
 
253
 
 
254
    if ( ASC_OPTIONS & ASCOPT_CREAD )
 
255
        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
 
256
 
 
257
    pAsc->asc_con |= con;
 
258
 
 
259
    return 0;
 
260
}
 
261
 
 
262
void serial_putc (const char c)
 
263
{
 
264
#ifdef ASC_FIFO_PRESENT
 
265
    uint txFl = 0;
 
266
#else
 
267
    uint timeout = 0;
 
268
#endif
 
269
 
 
270
    if (c == '\n') serial_putc ('\r');
 
271
 
 
272
#ifdef ASC_FIFO_PRESENT
 
273
    /* check do we have a free space in the TX FIFO */
 
274
    /* get current filling level */
 
275
    do
 
276
    {
 
277
        txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
 
278
    }
 
279
    while ( txFl == INCAASC_TXFIFO_FULL );
 
280
#else
 
281
 
 
282
    while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
 
283
                           FBS_ISR_AB))
 
284
    {
 
285
            if (timeout++ > TOUT_LOOP)
 
286
            {
 
287
                    break;
 
288
            }
 
289
    }
 
290
#endif
 
291
 
 
292
    pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
 
293
 
 
294
#ifndef ASC_FIFO_PRESENT
 
295
    *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AB |
 
296
                                                                 FBS_ISR_AT;
 
297
#endif
 
298
 
 
299
    /* check for errors */
 
300
    if ( pAsc->asc_con & ASCCON_OE )
 
301
    {
 
302
        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
 
303
        return;
 
304
    }
 
305
}
 
306
 
 
307
void serial_puts (const char *s)
 
308
{
 
309
    while (*s)
 
310
    {
 
311
        serial_putc (*s++);
 
312
    }
 
313
}
 
314
 
 
315
int serial_getc (void)
 
316
{
 
317
    ulong symbol_mask;
 
318
    char c;
 
319
 
 
320
    while (!serial_tstc());
 
321
 
 
322
    symbol_mask =
 
323
        ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
 
324
 
 
325
    c = (char)(pAsc->asc_rbuf & symbol_mask);
 
326
 
 
327
#ifndef ASC_FIFO_PRESENT
 
328
    *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AR;
 
329
#endif
 
330
 
 
331
    return c;
 
332
}
 
333
 
 
334
int serial_tstc (void)
 
335
{
 
336
    int res = 1;
 
337
 
 
338
#ifdef ASC_FIFO_PRESENT
 
339
    if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
 
340
    {
 
341
        res = 0;
 
342
    }
 
343
#else
 
344
    if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
 
345
                                                                FBS_ISR_AR))
 
346
 
 
347
    {
 
348
        res = 0;
 
349
    }
 
350
#endif
 
351
    else if ( pAsc->asc_con & ASCCON_FE )
 
352
    {
 
353
        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
 
354
        res = 0;
 
355
    }
 
356
    else if ( pAsc->asc_con & ASCCON_PE )
 
357
    {
 
358
        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
 
359
        res = 0;
 
360
    }
 
361
    else if ( pAsc->asc_con & ASCCON_OE )
 
362
    {
 
363
        SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
 
364
        res = 0;
 
365
    }
 
366
 
 
367
    return res;
 
368
}