OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [src/] [drivers/] [uart/] [pl011/] [uart.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * PL011 UART driver
3
 *
4
 * Copyright (C) 2009 B Labs Ltd.
5
 */
6
#include <l4/drivers/uart/pl011/uart.h>
7
#include INC_ARCH(io.h)
8
 
9
/* Error status bits in receive status register */
10
#define PL011_FE                (1 << 0)
11
#define PL011_PE                (1 << 1)
12
#define PL011_BE                (1 << 2)
13
#define PL011_OE                (1 << 3)
14
 
15
/* Status bits in flag register */
16
#define PL011_TXFE              (1 << 7)
17
#define PL011_RXFF              (1 << 6)
18
#define PL011_TXFF              (1 << 5)
19
#define PL011_RXFE              (1 << 4)
20
#define PL011_BUSY              (1 << 3)
21
#define PL011_DCD               (1 << 2)
22
#define PL011_DSR               (1 << 1)
23
#define PL011_CTS               (1 << 0)
24
 
25
#define PL011_UARTEN    (1 << 0)
26
static inline void pl011_uart_enable(unsigned long base)
27
{
28
        unsigned int val = 0;
29
 
30
        val = read((base + PL011_UARTCR));
31
        val |= PL011_UARTEN;
32
        write(val, (base + PL011_UARTCR));
33
 
34
        return;
35
}
36
 
37
static inline void pl011_uart_disable(unsigned long base)
38
{
39
        unsigned int val = 0;
40
 
41
        val = read((base + PL011_UARTCR));
42
        val &= ~PL011_UARTEN;
43
        write(val, (base + PL011_UARTCR));
44
 
45
        return;
46
}
47
 
48
#define PL011_TXE       (1 << 8)
49
static inline void pl011_tx_enable(unsigned long base)
50
{
51
        unsigned int val = 0;
52
 
53
        val = read((base + PL011_UARTCR));
54
        val |= PL011_TXE;
55
        write(val, (base + PL011_UARTCR));
56
        return;
57
}
58
 
59
static inline void pl011_tx_disable(unsigned long base)
60
{
61
        unsigned int val = 0;
62
 
63
        val =read((base + PL011_UARTCR));
64
        val &= ~PL011_TXE;
65
        write(val, (base + PL011_UARTCR));
66
        return;
67
}
68
 
69
#define PL011_RXE       (1 << 9)
70
static inline void pl011_rx_enable(unsigned long base)
71
{
72
        unsigned int val = 0;
73
 
74
        val = read((base + PL011_UARTCR));
75
        val |= PL011_RXE;
76
        write(val, (base + PL011_UARTCR));
77
        return;
78
}
79
 
80
static inline void pl011_rx_disable(unsigned long base)
81
{
82
        unsigned int val = 0;
83
 
84
        val = read((base + PL011_UARTCR));
85
        val &= ~PL011_RXE;
86
        write(val, (base + PL011_UARTCR));
87
        return;
88
}
89
 
90
#define PL011_TWO_STOPBITS_SELECT       (1 << 3)
91
static inline void pl011_set_stopbits(unsigned long base, int stopbits)
92
{
93
        unsigned int val = 0;
94
 
95
        val = read((base + PL011_UARTLCR_H));
96
 
97
        if(stopbits == 2) {                     /* Set to two bits */
98
                val |= PL011_TWO_STOPBITS_SELECT;
99
        } else {                                /* Default is 1 */
100
                val &= ~PL011_TWO_STOPBITS_SELECT;
101
        }
102
        write(val, (base + PL011_UARTLCR_H));
103
        return;
104
}
105
 
106
#define PL011_PARITY_ENABLE     (1 << 1)
107
static inline void pl011_parity_enable(unsigned long base)
108
{
109
        unsigned int val = 0;
110
 
111
        val = read((base +PL011_UARTLCR_H));
112
        val |= PL011_PARITY_ENABLE;
113
        write(val, (base + PL011_UARTLCR_H));
114
        return;
115
}
116
 
117
static inline void pl011_parity_disable(unsigned long base)
118
{
119
        unsigned int val = 0;
120
 
121
        val = read((base + PL011_UARTLCR_H));
122
        val &= ~PL011_PARITY_ENABLE;
123
        write(val, (base + PL011_UARTLCR_H));
124
        return;
125
}
126
 
127
#define PL011_PARITY_EVEN       (1 << 2)
128
static inline void pl011_set_parity_even(unsigned long base)
129
{
130
        unsigned int val = 0;
131
 
132
        val = read((base + PL011_UARTLCR_H));
133
        val |= PL011_PARITY_EVEN;
134
        write(val, (base + PL011_UARTLCR_H));
135
        return;
136
}
137
 
138
static inline void pl011_set_parity_odd(unsigned long base)
139
{
140
        unsigned int val = 0;
141
 
142
        val = read((base + PL011_UARTLCR_H));
143
        val &= ~PL011_PARITY_EVEN;
144
        write(val, (base + PL011_UARTLCR_H));
145
        return;
146
}
147
 
148
#define PL011_ENABLE_FIFOS      (1 << 4)
149
static inline void pl011_enable_fifos(unsigned long base)
150
{
151
        unsigned int val = 0;
152
 
153
        val = read((base + PL011_UARTLCR_H));
154
        val |= PL011_ENABLE_FIFOS;
155
        write(val, (base + PL011_UARTLCR_H));
156
        return;
157
}
158
 
159
static inline void pl011_disable_fifos(unsigned long base)
160
{
161
        unsigned int val = 0;
162
 
163
        val = read((base + PL011_UARTLCR_H));
164
        val &= ~PL011_ENABLE_FIFOS;
165
        write(val, (base + PL011_UARTLCR_H));
166
        return;
167
}
168
 
169
/* Sets the transfer word width for the data register. */
170
static inline void pl011_set_word_width(unsigned long base, int size)
171
{
172
        unsigned int val = 0;
173
        if(size < 5 || size > 8)        /* Default is 8 */
174
                size = 8;
175
 
176
        /* Clear size field */
177
        val = read((base + PL011_UARTLCR_H));
178
        val &= ~(0x3 << 5);
179
        write(val, (base + PL011_UARTLCR_H));
180
 
181
        /*
182
         * The formula is to write 5 less of size given:
183
         * 11 = 8 bits
184
         * 10 = 7 bits
185
         * 01 = 6 bits
186
         * 00 = 5 bits
187
         */
188
        val = read((base + PL011_UARTLCR_H));
189
        val |= (size - 5) << 5;
190
        write(val, (base + PL011_UARTLCR_H));
191
 
192
        return;
193
}
194
 
195
/*
196
 * Defines at which level of fifo fullness an irq will be generated.
197
 * @xfer: tx fifo = 0, rx fifo = 1
198
 * @level: Generate irq if:
199
 * 0    rxfifo >= 1/8 full      txfifo <= 1/8 full
200
 * 1    rxfifo >= 1/4 full      txfifo <= 1/4 full
201
 * 2    rxfifo >= 1/2 full      txfifo <= 1/2 full
202
 * 3    rxfifo >= 3/4 full      txfifo <= 3/4 full
203
 * 4    rxfifo >= 7/8 full      txfifo <= 7/8 full
204
 * 5-7  reserved                reserved
205
 */
206
static inline void pl011_set_irq_fifolevel(unsigned long base, \
207
                        unsigned int xfer, unsigned int level)
208
{
209
        if(xfer != 1 && xfer != 0)       /* Invalid fifo */
210
                return;
211
        if(level > 4)                   /* Invalid level */
212
                return;
213
 
214
        write(level << (xfer * 3), (base + PL011_UARTIFLS));
215
        return;
216
}
217
 
218
void uart_tx_char(unsigned long base, char c)
219
{
220
        unsigned int val = 0;
221
 
222
        do {
223
                val = read((base + PL011_UARTFR));
224
        } while (val & PL011_TXFF);  /* TX FIFO FULL */
225
 
226
        write(c, (base + PL011_UARTDR));
227
}
228
 
229
char uart_rx_char(unsigned long base)
230
{
231
        unsigned int val = 0;
232
 
233
        do {
234
                val = read(base + PL011_UARTFR);
235
        } while (val & PL011_RXFE); /* RX FIFO Empty */
236
 
237
        return (char)read((base + PL011_UARTDR));
238
}
239
 
240
/*
241
 * Sets the baud rate in kbps. It is recommended to use
242
 * standard rates such as: 1200, 2400, 3600, 4800, 7200,
243
 * 9600, 14400, 19200, 28800, 38400, 57600 76800, 115200.
244
 */
245
void pl011_set_baudrate(unsigned long base, unsigned int baud,
246
                        unsigned int clkrate)
247
{
248
        const unsigned int uartclk = 24000000;  /* 24Mhz clock fixed on pb926 */
249
        unsigned int val = 0, ipart = 0, fpart = 0;
250
 
251
        /* Use default pb926 rate if no rate is supplied */
252
        if (clkrate == 0)
253
                clkrate = uartclk;
254
        if (baud > 115200 || baud < 1200)
255
                baud = 38400;   /* Default rate. */
256
 
257
        /* 24000000 / (38400 * 16) */
258
        ipart = 39;
259
 
260
        write(ipart, base + PL011_UARTIBRD);
261
        write(fpart, base + PL011_UARTFBRD);
262
 
263
        /*
264
         * For the IBAUD and FBAUD to update, we need to
265
         * write to UARTLCR_H because the 3 registers are
266
         * actually part of a single register in hardware
267
         * which only updates by a write to UARTLCR_H
268
         */
269
        val = read(base + PL011_UARTLCR_H);
270
        write(val, base + PL011_UARTLCR_H);
271
 
272
}
273
 
274
void uart_init(unsigned long uart_base)
275
{
276
        /* Initialise data register for 8 bit data read/writes */
277
        pl011_set_word_width(uart_base, 8);
278
 
279
        /*
280
         * Fifos are disabled because by default it is assumed the port
281
         * will be used as a user terminal, and in that case the typed
282
         * characters will only show up when fifos are flushed, rather than
283
         * when each character is typed. We avoid this by not using fifos.
284
         */
285
        pl011_disable_fifos(uart_base);
286
 
287
        /* Set default baud rate of 38400 */
288
        pl011_set_baudrate(uart_base, 38400, 24000000);
289
 
290
        /* Set default settings of 1 stop bit, no parity, no hw flow ctrl */
291
        pl011_set_stopbits(uart_base, 1);
292
        pl011_parity_disable(uart_base);
293
 
294
        /* Enable rx, tx, and uart chip */
295
        pl011_tx_enable(uart_base);
296
        pl011_rx_enable(uart_base);
297
        pl011_uart_enable(uart_base);
298
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.