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

« back to all changes in this revision

Viewing changes to drivers/serial/serial_pl01x.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
 * (C) Copyright 2000
 
3
 * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
 
4
 *
 
5
 * (C) Copyright 2004
 
6
 * ARM Ltd.
 
7
 * Philippe Robin, <philippe.robin@arm.com>
 
8
 *
 
9
 * See file CREDITS for list of people who contributed to this
 
10
 * project.
 
11
 *
 
12
 * This program is free software; you can redistribute it and/or
 
13
 * modify it under the terms of the GNU General Public License as
 
14
 * published by the Free Software Foundation; either version 2 of
 
15
 * the License, or (at your option) any later version.
 
16
 *
 
17
 * This program is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 * GNU General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU General Public License
 
23
 * along with this program; if not, write to the Free Software
 
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 
25
 * MA 02111-1307 USA
 
26
 */
 
27
 
 
28
/* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */
 
29
 
 
30
#include <common.h>
 
31
#include <watchdog.h>
 
32
 
 
33
#include "serial_pl01x.h"
 
34
 
 
35
#define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val))
 
36
#define IO_READ(addr) (*(volatile unsigned int *)(addr))
 
37
 
 
38
/*
 
39
 * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1
 
40
 * Integrator CP has two UARTs, use the first one, at 38400-8-N-1
 
41
 * Versatile PB has four UARTs.
 
42
 */
 
43
#define CONSOLE_PORT CONFIG_CONS_INDEX
 
44
#define baudRate CONFIG_BAUDRATE
 
45
static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS;
 
46
#define NUM_PORTS (sizeof(port)/sizeof(port[0]))
 
47
 
 
48
static void pl01x_putc (int portnum, char c);
 
49
static int pl01x_getc (int portnum);
 
50
static int pl01x_tstc (int portnum);
 
51
 
 
52
#ifdef CONFIG_PL010_SERIAL
 
53
 
 
54
int serial_init (void)
 
55
{
 
56
        unsigned int divisor;
 
57
 
 
58
        /*
 
59
         ** First, disable everything.
 
60
         */
 
61
        IO_WRITE (port[CONSOLE_PORT] + UART_PL010_CR, 0x0);
 
62
 
 
63
        /*
 
64
         ** Set baud rate
 
65
         **
 
66
         */
 
67
        switch (baudRate) {
 
68
        case 9600:
 
69
                divisor = UART_PL010_BAUD_9600;
 
70
                break;
 
71
 
 
72
        case 19200:
 
73
                divisor = UART_PL010_BAUD_9600;
 
74
                break;
 
75
 
 
76
        case 38400:
 
77
                divisor = UART_PL010_BAUD_38400;
 
78
                break;
 
79
 
 
80
        case 57600:
 
81
                divisor = UART_PL010_BAUD_57600;
 
82
                break;
 
83
 
 
84
        case 115200:
 
85
                divisor = UART_PL010_BAUD_115200;
 
86
                break;
 
87
 
 
88
        default:
 
89
                divisor = UART_PL010_BAUD_38400;
 
90
        }
 
91
 
 
92
        IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRM,
 
93
                  ((divisor & 0xf00) >> 8));
 
94
        IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRL, (divisor & 0xff));
 
95
 
 
96
        /*
 
97
         ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled.
 
98
         */
 
99
        IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRH,
 
100
                  (UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN));
 
101
 
 
102
        /*
 
103
         ** Finally, enable the UART
 
104
         */
 
105
        IO_WRITE (port[CONSOLE_PORT] + UART_PL010_CR, (UART_PL010_CR_UARTEN));
 
106
 
 
107
        return 0;
 
108
}
 
109
 
 
110
#endif /* CONFIG_PL010_SERIAL */
 
111
 
 
112
#ifdef CONFIG_PL011_SERIAL
 
113
 
 
114
int serial_init (void)
 
115
{
 
116
        unsigned int temp;
 
117
        unsigned int divider;
 
118
        unsigned int remainder;
 
119
        unsigned int fraction;
 
120
 
 
121
        /*
 
122
         ** First, disable everything.
 
123
         */
 
124
        IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR, 0x0);
 
125
 
 
126
        /*
 
127
         ** Set baud rate
 
128
         **
 
129
         ** IBRD = UART_CLK / (16 * BAUD_RATE)
 
130
         ** FBRD = ROUND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE))
 
131
         */
 
132
        temp = 16 * baudRate;
 
133
        divider = CONFIG_PL011_CLOCK / temp;
 
134
        remainder = CONFIG_PL011_CLOCK % temp;
 
135
        temp = (8 * remainder) / baudRate;
 
136
        fraction = (temp >> 1) + (temp & 1);
 
137
 
 
138
        IO_WRITE (port[CONSOLE_PORT] + UART_PL011_IBRD, divider);
 
139
        IO_WRITE (port[CONSOLE_PORT] + UART_PL011_FBRD, fraction);
 
140
 
 
141
        /*
 
142
         ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled.
 
143
         */
 
144
        IO_WRITE (port[CONSOLE_PORT] + UART_PL011_LCRH,
 
145
                  (UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN));
 
146
 
 
147
        /*
 
148
         ** Finally, enable the UART
 
149
         */
 
150
        IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR,
 
151
                  (UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
 
152
                   UART_PL011_CR_RXE));
 
153
 
 
154
        return 0;
 
155
}
 
156
 
 
157
#endif /* CONFIG_PL011_SERIAL */
 
158
 
 
159
void serial_putc (const char c)
 
160
{
 
161
        if (c == '\n')
 
162
                pl01x_putc (CONSOLE_PORT, '\r');
 
163
 
 
164
        pl01x_putc (CONSOLE_PORT, c);
 
165
}
 
166
 
 
167
void serial_puts (const char *s)
 
168
{
 
169
        while (*s) {
 
170
                serial_putc (*s++);
 
171
        }
 
172
}
 
173
 
 
174
int serial_getc (void)
 
175
{
 
176
        return pl01x_getc (CONSOLE_PORT);
 
177
}
 
178
 
 
179
int serial_tstc (void)
 
180
{
 
181
        return pl01x_tstc (CONSOLE_PORT);
 
182
}
 
183
 
 
184
void serial_setbrg (void)
 
185
{
 
186
}
 
187
 
 
188
static void pl01x_putc (int portnum, char c)
 
189
{
 
190
        /* Wait until there is space in the FIFO */
 
191
        while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF)
 
192
                WATCHDOG_RESET();
 
193
 
 
194
        /* Send the character */
 
195
        IO_WRITE (port[portnum] + UART_PL01x_DR, c);
 
196
}
 
197
 
 
198
static int pl01x_getc (int portnum)
 
199
{
 
200
        unsigned int data;
 
201
 
 
202
        /* Wait until there is data in the FIFO */
 
203
        while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE)
 
204
                WATCHDOG_RESET();
 
205
 
 
206
        data = IO_READ (port[portnum] + UART_PL01x_DR);
 
207
 
 
208
        /* Check for an error flag */
 
209
        if (data & 0xFFFFFF00) {
 
210
                /* Clear the error */
 
211
                IO_WRITE (port[portnum] + UART_PL01x_ECR, 0xFFFFFFFF);
 
212
                return -1;
 
213
        }
 
214
 
 
215
        return (int) data;
 
216
}
 
217
 
 
218
static int pl01x_tstc (int portnum)
 
219
{
 
220
        WATCHDOG_RESET();
 
221
        return !(IO_READ (port[portnum] + UART_PL01x_FR) &
 
222
                 UART_PL01x_FR_RXFE);
 
223
}