Deleted Added
full compact
uart_dev_pl011.c (262649) uart_dev_pl011.c (283321)
1/*-
2 * Copyright (c) 2012 Semihalf.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2012 Semihalf.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_pl011.c 262649 2014-03-01 04:16:54Z imp $");
28__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_pl011.c 283321 2015-05-23 19:27:04Z ian $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/bus.h>
34#include <machine/bus.h>
35
36#include <dev/uart/uart.h>
37#include <dev/uart/uart_cpu.h>
38#include <dev/uart/uart_bus.h>
39#include "uart_if.h"
40
41#include <sys/kdb.h>
42
43/* PL011 UART registers and masks*/
44#define UART_DR 0x00 /* Data register */
45#define DR_FE (1 << 8) /* Framing error */
46#define DR_PE (1 << 9) /* Parity error */
47#define DR_BE (1 << 10) /* Break error */
48#define DR_OE (1 << 11) /* Overrun error */
49
50#define UART_FR 0x06 /* Flag register */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/bus.h>
34#include <machine/bus.h>
35
36#include <dev/uart/uart.h>
37#include <dev/uart/uart_cpu.h>
38#include <dev/uart/uart_bus.h>
39#include "uart_if.h"
40
41#include <sys/kdb.h>
42
43/* PL011 UART registers and masks*/
44#define UART_DR 0x00 /* Data register */
45#define DR_FE (1 << 8) /* Framing error */
46#define DR_PE (1 << 9) /* Parity error */
47#define DR_BE (1 << 10) /* Break error */
48#define DR_OE (1 << 11) /* Overrun error */
49
50#define UART_FR 0x06 /* Flag register */
51#define FR_TXFF (1 << 5) /* Transmit FIFO/reg full */
51#define FR_RXFF (1 << 6) /* Receive FIFO/reg full */
52#define FR_TXFE (1 << 7) /* Transmit FIFO/reg empty */
53
54#define UART_IBRD 0x09 /* Integer baud rate register */
55#define IBRD_BDIVINT 0xffff /* Significant part of int. divisor value */
56
57#define UART_FBRD 0x0a /* Fractional baud rate register */
58#define FBRD_BDIVFRAC 0x3f /* Significant part of frac. divisor value */
59
60#define UART_LCR_H 0x0b /* Line control register */
61#define LCR_H_WLEN8 (0x3 << 5)
62#define LCR_H_WLEN7 (0x2 << 5)
63#define LCR_H_WLEN6 (0x1 << 5)
64#define LCR_H_FEN (1 << 4) /* FIFO mode enable */
65#define LCR_H_STP2 (1 << 3) /* 2 stop frames at the end */
66#define LCR_H_EPS (1 << 2) /* Even parity select */
67#define LCR_H_PEN (1 << 1) /* Parity enable */
68
69#define UART_CR 0x0c /* Control register */
70#define CR_RXE (1 << 9) /* Receive enable */
71#define CR_TXE (1 << 8) /* Transmit enable */
72#define CR_UARTEN (1 << 0) /* UART enable */
73
74#define UART_IMSC 0x0e /* Interrupt mask set/clear register */
75#define IMSC_MASK_ALL 0x7ff /* Mask all interrupts */
76
77#define UART_RIS 0x0f /* Raw interrupt status register */
78#define UART_RXREADY (1 << 4) /* RX buffer full */
79#define UART_TXEMPTY (1 << 5) /* TX buffer empty */
80#define RIS_FE (1 << 7) /* Framing error interrupt status */
81#define RIS_PE (1 << 8) /* Parity error interrupt status */
82#define RIS_BE (1 << 9) /* Break error interrupt status */
83#define RIS_OE (1 << 10) /* Overrun interrupt status */
84
85#define UART_MIS 0x10 /* Masked interrupt status register */
86#define UART_ICR 0x11 /* Interrupt clear register */
87
88/*
89 * FIXME: actual register size is SoC-dependent, we need to handle it
90 */
91#define __uart_getreg(bas, reg) \
92 bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg))
93#define __uart_setreg(bas, reg, value) \
94 bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value)
95
96/*
97 * Low-level UART interface.
98 */
99static int uart_pl011_probe(struct uart_bas *bas);
100static void uart_pl011_init(struct uart_bas *bas, int, int, int, int);
101static void uart_pl011_term(struct uart_bas *bas);
102static void uart_pl011_putc(struct uart_bas *bas, int);
103static int uart_pl011_rxready(struct uart_bas *bas);
104static int uart_pl011_getc(struct uart_bas *bas, struct mtx *);
105
106static struct uart_ops uart_pl011_ops = {
107 .probe = uart_pl011_probe,
108 .init = uart_pl011_init,
109 .term = uart_pl011_term,
110 .putc = uart_pl011_putc,
111 .rxready = uart_pl011_rxready,
112 .getc = uart_pl011_getc,
113};
114
115static int
116uart_pl011_probe(struct uart_bas *bas)
117{
118
119 return (0);
120}
121
122static void
123uart_pl011_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
124 int parity)
125{
126 uint32_t ctrl, line;
127 uint32_t baud;
128
129 /*
130 * Zero all settings to make sure
131 * UART is disabled and not configured
132 */
133 ctrl = line = 0x0;
134 __uart_setreg(bas, UART_CR, ctrl);
135
136 /* As we know UART is disabled we may setup the line */
137 switch (databits) {
138 case 7:
139 line |= LCR_H_WLEN7;
140 break;
141 case 6:
142 line |= LCR_H_WLEN6;
143 break;
144 case 8:
145 default:
146 line |= LCR_H_WLEN8;
147 break;
148 }
149
150 if (stopbits == 2)
151 line |= LCR_H_STP2;
152 else
153 line &= ~LCR_H_STP2;
154
155 if (parity)
156 line |= LCR_H_PEN;
157 else
158 line &= ~LCR_H_PEN;
159
160 /* Configure the rest */
161 line &= ~LCR_H_FEN;
162 ctrl |= (CR_RXE | CR_TXE | CR_UARTEN);
163
164 if (bas->rclk != 0 && baudrate != 0) {
165 baud = bas->rclk * 4 / baudrate;
166 __uart_setreg(bas, UART_IBRD, ((uint32_t)(baud >> 6)) & IBRD_BDIVINT);
167 __uart_setreg(bas, UART_FBRD, (uint32_t)(baud & 0x3F) & FBRD_BDIVFRAC);
168 }
169
170 /* Add config. to line before reenabling UART */
171 __uart_setreg(bas, UART_LCR_H, (__uart_getreg(bas, UART_LCR_H) &
172 ~0xff) | line);
173
174 __uart_setreg(bas, UART_CR, ctrl);
175}
176
177static void
178uart_pl011_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
179 int parity)
180{
181 /* Mask all interrupts */
182 __uart_setreg(bas, UART_IMSC, __uart_getreg(bas, UART_IMSC) &
183 ~IMSC_MASK_ALL);
184
185 uart_pl011_param(bas, baudrate, databits, stopbits, parity);
186}
187
188static void
189uart_pl011_term(struct uart_bas *bas)
190{
191}
192
193static void
194uart_pl011_putc(struct uart_bas *bas, int c)
195{
196
52#define FR_RXFF (1 << 6) /* Receive FIFO/reg full */
53#define FR_TXFE (1 << 7) /* Transmit FIFO/reg empty */
54
55#define UART_IBRD 0x09 /* Integer baud rate register */
56#define IBRD_BDIVINT 0xffff /* Significant part of int. divisor value */
57
58#define UART_FBRD 0x0a /* Fractional baud rate register */
59#define FBRD_BDIVFRAC 0x3f /* Significant part of frac. divisor value */
60
61#define UART_LCR_H 0x0b /* Line control register */
62#define LCR_H_WLEN8 (0x3 << 5)
63#define LCR_H_WLEN7 (0x2 << 5)
64#define LCR_H_WLEN6 (0x1 << 5)
65#define LCR_H_FEN (1 << 4) /* FIFO mode enable */
66#define LCR_H_STP2 (1 << 3) /* 2 stop frames at the end */
67#define LCR_H_EPS (1 << 2) /* Even parity select */
68#define LCR_H_PEN (1 << 1) /* Parity enable */
69
70#define UART_CR 0x0c /* Control register */
71#define CR_RXE (1 << 9) /* Receive enable */
72#define CR_TXE (1 << 8) /* Transmit enable */
73#define CR_UARTEN (1 << 0) /* UART enable */
74
75#define UART_IMSC 0x0e /* Interrupt mask set/clear register */
76#define IMSC_MASK_ALL 0x7ff /* Mask all interrupts */
77
78#define UART_RIS 0x0f /* Raw interrupt status register */
79#define UART_RXREADY (1 << 4) /* RX buffer full */
80#define UART_TXEMPTY (1 << 5) /* TX buffer empty */
81#define RIS_FE (1 << 7) /* Framing error interrupt status */
82#define RIS_PE (1 << 8) /* Parity error interrupt status */
83#define RIS_BE (1 << 9) /* Break error interrupt status */
84#define RIS_OE (1 << 10) /* Overrun interrupt status */
85
86#define UART_MIS 0x10 /* Masked interrupt status register */
87#define UART_ICR 0x11 /* Interrupt clear register */
88
89/*
90 * FIXME: actual register size is SoC-dependent, we need to handle it
91 */
92#define __uart_getreg(bas, reg) \
93 bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg))
94#define __uart_setreg(bas, reg, value) \
95 bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value)
96
97/*
98 * Low-level UART interface.
99 */
100static int uart_pl011_probe(struct uart_bas *bas);
101static void uart_pl011_init(struct uart_bas *bas, int, int, int, int);
102static void uart_pl011_term(struct uart_bas *bas);
103static void uart_pl011_putc(struct uart_bas *bas, int);
104static int uart_pl011_rxready(struct uart_bas *bas);
105static int uart_pl011_getc(struct uart_bas *bas, struct mtx *);
106
107static struct uart_ops uart_pl011_ops = {
108 .probe = uart_pl011_probe,
109 .init = uart_pl011_init,
110 .term = uart_pl011_term,
111 .putc = uart_pl011_putc,
112 .rxready = uart_pl011_rxready,
113 .getc = uart_pl011_getc,
114};
115
116static int
117uart_pl011_probe(struct uart_bas *bas)
118{
119
120 return (0);
121}
122
123static void
124uart_pl011_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
125 int parity)
126{
127 uint32_t ctrl, line;
128 uint32_t baud;
129
130 /*
131 * Zero all settings to make sure
132 * UART is disabled and not configured
133 */
134 ctrl = line = 0x0;
135 __uart_setreg(bas, UART_CR, ctrl);
136
137 /* As we know UART is disabled we may setup the line */
138 switch (databits) {
139 case 7:
140 line |= LCR_H_WLEN7;
141 break;
142 case 6:
143 line |= LCR_H_WLEN6;
144 break;
145 case 8:
146 default:
147 line |= LCR_H_WLEN8;
148 break;
149 }
150
151 if (stopbits == 2)
152 line |= LCR_H_STP2;
153 else
154 line &= ~LCR_H_STP2;
155
156 if (parity)
157 line |= LCR_H_PEN;
158 else
159 line &= ~LCR_H_PEN;
160
161 /* Configure the rest */
162 line &= ~LCR_H_FEN;
163 ctrl |= (CR_RXE | CR_TXE | CR_UARTEN);
164
165 if (bas->rclk != 0 && baudrate != 0) {
166 baud = bas->rclk * 4 / baudrate;
167 __uart_setreg(bas, UART_IBRD, ((uint32_t)(baud >> 6)) & IBRD_BDIVINT);
168 __uart_setreg(bas, UART_FBRD, (uint32_t)(baud & 0x3F) & FBRD_BDIVFRAC);
169 }
170
171 /* Add config. to line before reenabling UART */
172 __uart_setreg(bas, UART_LCR_H, (__uart_getreg(bas, UART_LCR_H) &
173 ~0xff) | line);
174
175 __uart_setreg(bas, UART_CR, ctrl);
176}
177
178static void
179uart_pl011_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
180 int parity)
181{
182 /* Mask all interrupts */
183 __uart_setreg(bas, UART_IMSC, __uart_getreg(bas, UART_IMSC) &
184 ~IMSC_MASK_ALL);
185
186 uart_pl011_param(bas, baudrate, databits, stopbits, parity);
187}
188
189static void
190uart_pl011_term(struct uart_bas *bas)
191{
192}
193
194static void
195uart_pl011_putc(struct uart_bas *bas, int c)
196{
197
197 while (!(__uart_getreg(bas, UART_FR) & FR_TXFE))
198 /* Wait when TX FIFO full. Push character otherwise. */
199 while (__uart_getreg(bas, UART_FR) & FR_TXFF)
198 ;
199 __uart_setreg(bas, UART_DR, c & 0xff);
200}
201
202static int
203uart_pl011_rxready(struct uart_bas *bas)
204{
205
206 return (__uart_getreg(bas, UART_FR) & FR_RXFF);
207}
208
209static int
210uart_pl011_getc(struct uart_bas *bas, struct mtx *hwmtx)
211{
212 int c;
213
214 while (!uart_pl011_rxready(bas))
215 ;
216 c = __uart_getreg(bas, UART_DR) & 0xff;
217
218 return (c);
219}
220
221/*
222 * High-level UART interface.
223 */
224struct uart_pl011_softc {
225 struct uart_softc base;
226 uint8_t fcr;
227 uint8_t ier;
228 uint8_t mcr;
229
230 uint8_t ier_mask;
231 uint8_t ier_rxbits;
232};
233
234static int uart_pl011_bus_attach(struct uart_softc *);
235static int uart_pl011_bus_detach(struct uart_softc *);
236static int uart_pl011_bus_flush(struct uart_softc *, int);
237static int uart_pl011_bus_getsig(struct uart_softc *);
238static int uart_pl011_bus_ioctl(struct uart_softc *, int, intptr_t);
239static int uart_pl011_bus_ipend(struct uart_softc *);
240static int uart_pl011_bus_param(struct uart_softc *, int, int, int, int);
241static int uart_pl011_bus_probe(struct uart_softc *);
242static int uart_pl011_bus_receive(struct uart_softc *);
243static int uart_pl011_bus_setsig(struct uart_softc *, int);
244static int uart_pl011_bus_transmit(struct uart_softc *);
245static void uart_pl011_bus_grab(struct uart_softc *);
246static void uart_pl011_bus_ungrab(struct uart_softc *);
247
248static kobj_method_t uart_pl011_methods[] = {
249 KOBJMETHOD(uart_attach, uart_pl011_bus_attach),
250 KOBJMETHOD(uart_detach, uart_pl011_bus_detach),
251 KOBJMETHOD(uart_flush, uart_pl011_bus_flush),
252 KOBJMETHOD(uart_getsig, uart_pl011_bus_getsig),
253 KOBJMETHOD(uart_ioctl, uart_pl011_bus_ioctl),
254 KOBJMETHOD(uart_ipend, uart_pl011_bus_ipend),
255 KOBJMETHOD(uart_param, uart_pl011_bus_param),
256 KOBJMETHOD(uart_probe, uart_pl011_bus_probe),
257 KOBJMETHOD(uart_receive, uart_pl011_bus_receive),
258 KOBJMETHOD(uart_setsig, uart_pl011_bus_setsig),
259 KOBJMETHOD(uart_transmit, uart_pl011_bus_transmit),
260 KOBJMETHOD(uart_grab, uart_pl011_bus_grab),
261 KOBJMETHOD(uart_ungrab, uart_pl011_bus_ungrab),
262
263 { 0, 0 }
264};
265
266struct uart_class uart_pl011_class = {
267 "uart_pl011",
268 uart_pl011_methods,
269 sizeof(struct uart_pl011_softc),
270 .uc_ops = &uart_pl011_ops,
271 .uc_range = 0x48,
272 .uc_rclk = 0
273};
274
275static int
276uart_pl011_bus_attach(struct uart_softc *sc)
277{
278 struct uart_bas *bas;
279
280 bas = &sc->sc_bas;
281 /* Enable RX & TX interrupts */
282 __uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
283 /* Clear RX & TX interrupts */
284 __uart_setreg(bas, UART_ICR, IMSC_MASK_ALL);
285
286 return (0);
287}
288
289static int
290uart_pl011_bus_detach(struct uart_softc *sc)
291{
292
293 return (0);
294}
295
296static int
297uart_pl011_bus_flush(struct uart_softc *sc, int what)
298{
299
300 return (0);
301}
302
303static int
304uart_pl011_bus_getsig(struct uart_softc *sc)
305{
306
307 return (0);
308}
309
310static int
311uart_pl011_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
312{
313 struct uart_bas *bas;
314 int error;
315
316 bas = &sc->sc_bas;
317 error = 0;
318 uart_lock(sc->sc_hwmtx);
319 switch (request) {
320 case UART_IOCTL_BREAK:
321 break;
322 case UART_IOCTL_BAUD:
323 *(int*)data = 115200;
324 break;
325 default:
326 error = EINVAL;
327 break;
328 }
329 uart_unlock(sc->sc_hwmtx);
330
331 return (error);
332}
333
334static int
335uart_pl011_bus_ipend(struct uart_softc *sc)
336{
337 struct uart_bas *bas;
338 int ipend;
339 uint32_t ints;
340
341 bas = &sc->sc_bas;
342 uart_lock(sc->sc_hwmtx);
343 ints = __uart_getreg(bas, UART_MIS);
344 ipend = 0;
345
346 if (ints & UART_RXREADY)
347 ipend |= SER_INT_RXREADY;
348 if (ints & RIS_BE)
349 ipend |= SER_INT_BREAK;
350 if (ints & RIS_OE)
351 ipend |= SER_INT_OVERRUN;
352 if (ints & UART_TXEMPTY) {
353 if (sc->sc_txbusy)
354 ipend |= SER_INT_TXIDLE;
355
356 __uart_setreg(bas, UART_IMSC, UART_RXREADY);
357 }
358
359 uart_unlock(sc->sc_hwmtx);
360
361 return (ipend);
362}
363
364static int
365uart_pl011_bus_param(struct uart_softc *sc, int baudrate, int databits,
366 int stopbits, int parity)
367{
368
369 uart_lock(sc->sc_hwmtx);
370 uart_pl011_param(&sc->sc_bas, baudrate, databits, stopbits, parity);
371 uart_unlock(sc->sc_hwmtx);
372
373 return (0);
374}
375
376static int
377uart_pl011_bus_probe(struct uart_softc *sc)
378{
379
380 device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)");
381
382 sc->sc_rxfifosz = 1;
383 sc->sc_txfifosz = 1;
384
385 return (0);
386}
387
388static int
389uart_pl011_bus_receive(struct uart_softc *sc)
390{
391 struct uart_bas *bas;
392 int rx;
393 uint32_t ints, xc;
394
395 bas = &sc->sc_bas;
396 uart_lock(sc->sc_hwmtx);
397
398 ints = __uart_getreg(bas, UART_MIS);
399 while (ints & UART_RXREADY) {
400 if (uart_rx_full(sc)) {
401 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
402 break;
403 }
404 xc = __uart_getreg(bas, UART_DR);
405 rx = xc & 0xff;
406
407 if (xc & DR_FE)
408 rx |= UART_STAT_FRAMERR;
409 if (xc & DR_PE)
410 rx |= UART_STAT_PARERR;
411
412 __uart_setreg(bas, UART_ICR, UART_RXREADY);
413
414 uart_rx_put(sc, rx);
415 ints = __uart_getreg(bas, UART_MIS);
416 }
417
418 uart_unlock(sc->sc_hwmtx);
419
420 return (0);
421}
422
423static int
424uart_pl011_bus_setsig(struct uart_softc *sc, int sig)
425{
426
427 return (0);
428}
429
430static int
431uart_pl011_bus_transmit(struct uart_softc *sc)
432{
433 struct uart_bas *bas;
434 int i;
435
436 bas = &sc->sc_bas;
437 uart_lock(sc->sc_hwmtx);
438
439 for (i = 0; i < sc->sc_txdatasz; i++) {
440 __uart_setreg(bas, UART_DR, sc->sc_txbuf[i]);
441 uart_barrier(bas);
442 }
443 sc->sc_txbusy = 1;
444 __uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
445 uart_unlock(sc->sc_hwmtx);
446
447 return (0);
448}
449
450static void
451uart_pl011_bus_grab(struct uart_softc *sc)
452{
453 struct uart_bas *bas;
454
455 bas = &sc->sc_bas;
456 uart_lock(sc->sc_hwmtx);
457 __uart_setreg(bas, UART_IMSC, /* Switch to RX polling while grabbed */
458 ~UART_RXREADY & __uart_getreg(bas, UART_IMSC));
459 uart_unlock(sc->sc_hwmtx);
460}
461
462static void
463uart_pl011_bus_ungrab(struct uart_softc *sc)
464{
465 struct uart_bas *bas;
466
467 bas = &sc->sc_bas;
468 uart_lock(sc->sc_hwmtx);
469 __uart_setreg(bas, UART_IMSC, /* Switch to RX interrupts while not grabbed */
470 UART_RXREADY | __uart_getreg(bas, UART_IMSC));
471 uart_unlock(sc->sc_hwmtx);
472}
200 ;
201 __uart_setreg(bas, UART_DR, c & 0xff);
202}
203
204static int
205uart_pl011_rxready(struct uart_bas *bas)
206{
207
208 return (__uart_getreg(bas, UART_FR) & FR_RXFF);
209}
210
211static int
212uart_pl011_getc(struct uart_bas *bas, struct mtx *hwmtx)
213{
214 int c;
215
216 while (!uart_pl011_rxready(bas))
217 ;
218 c = __uart_getreg(bas, UART_DR) & 0xff;
219
220 return (c);
221}
222
223/*
224 * High-level UART interface.
225 */
226struct uart_pl011_softc {
227 struct uart_softc base;
228 uint8_t fcr;
229 uint8_t ier;
230 uint8_t mcr;
231
232 uint8_t ier_mask;
233 uint8_t ier_rxbits;
234};
235
236static int uart_pl011_bus_attach(struct uart_softc *);
237static int uart_pl011_bus_detach(struct uart_softc *);
238static int uart_pl011_bus_flush(struct uart_softc *, int);
239static int uart_pl011_bus_getsig(struct uart_softc *);
240static int uart_pl011_bus_ioctl(struct uart_softc *, int, intptr_t);
241static int uart_pl011_bus_ipend(struct uart_softc *);
242static int uart_pl011_bus_param(struct uart_softc *, int, int, int, int);
243static int uart_pl011_bus_probe(struct uart_softc *);
244static int uart_pl011_bus_receive(struct uart_softc *);
245static int uart_pl011_bus_setsig(struct uart_softc *, int);
246static int uart_pl011_bus_transmit(struct uart_softc *);
247static void uart_pl011_bus_grab(struct uart_softc *);
248static void uart_pl011_bus_ungrab(struct uart_softc *);
249
250static kobj_method_t uart_pl011_methods[] = {
251 KOBJMETHOD(uart_attach, uart_pl011_bus_attach),
252 KOBJMETHOD(uart_detach, uart_pl011_bus_detach),
253 KOBJMETHOD(uart_flush, uart_pl011_bus_flush),
254 KOBJMETHOD(uart_getsig, uart_pl011_bus_getsig),
255 KOBJMETHOD(uart_ioctl, uart_pl011_bus_ioctl),
256 KOBJMETHOD(uart_ipend, uart_pl011_bus_ipend),
257 KOBJMETHOD(uart_param, uart_pl011_bus_param),
258 KOBJMETHOD(uart_probe, uart_pl011_bus_probe),
259 KOBJMETHOD(uart_receive, uart_pl011_bus_receive),
260 KOBJMETHOD(uart_setsig, uart_pl011_bus_setsig),
261 KOBJMETHOD(uart_transmit, uart_pl011_bus_transmit),
262 KOBJMETHOD(uart_grab, uart_pl011_bus_grab),
263 KOBJMETHOD(uart_ungrab, uart_pl011_bus_ungrab),
264
265 { 0, 0 }
266};
267
268struct uart_class uart_pl011_class = {
269 "uart_pl011",
270 uart_pl011_methods,
271 sizeof(struct uart_pl011_softc),
272 .uc_ops = &uart_pl011_ops,
273 .uc_range = 0x48,
274 .uc_rclk = 0
275};
276
277static int
278uart_pl011_bus_attach(struct uart_softc *sc)
279{
280 struct uart_bas *bas;
281
282 bas = &sc->sc_bas;
283 /* Enable RX & TX interrupts */
284 __uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
285 /* Clear RX & TX interrupts */
286 __uart_setreg(bas, UART_ICR, IMSC_MASK_ALL);
287
288 return (0);
289}
290
291static int
292uart_pl011_bus_detach(struct uart_softc *sc)
293{
294
295 return (0);
296}
297
298static int
299uart_pl011_bus_flush(struct uart_softc *sc, int what)
300{
301
302 return (0);
303}
304
305static int
306uart_pl011_bus_getsig(struct uart_softc *sc)
307{
308
309 return (0);
310}
311
312static int
313uart_pl011_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
314{
315 struct uart_bas *bas;
316 int error;
317
318 bas = &sc->sc_bas;
319 error = 0;
320 uart_lock(sc->sc_hwmtx);
321 switch (request) {
322 case UART_IOCTL_BREAK:
323 break;
324 case UART_IOCTL_BAUD:
325 *(int*)data = 115200;
326 break;
327 default:
328 error = EINVAL;
329 break;
330 }
331 uart_unlock(sc->sc_hwmtx);
332
333 return (error);
334}
335
336static int
337uart_pl011_bus_ipend(struct uart_softc *sc)
338{
339 struct uart_bas *bas;
340 int ipend;
341 uint32_t ints;
342
343 bas = &sc->sc_bas;
344 uart_lock(sc->sc_hwmtx);
345 ints = __uart_getreg(bas, UART_MIS);
346 ipend = 0;
347
348 if (ints & UART_RXREADY)
349 ipend |= SER_INT_RXREADY;
350 if (ints & RIS_BE)
351 ipend |= SER_INT_BREAK;
352 if (ints & RIS_OE)
353 ipend |= SER_INT_OVERRUN;
354 if (ints & UART_TXEMPTY) {
355 if (sc->sc_txbusy)
356 ipend |= SER_INT_TXIDLE;
357
358 __uart_setreg(bas, UART_IMSC, UART_RXREADY);
359 }
360
361 uart_unlock(sc->sc_hwmtx);
362
363 return (ipend);
364}
365
366static int
367uart_pl011_bus_param(struct uart_softc *sc, int baudrate, int databits,
368 int stopbits, int parity)
369{
370
371 uart_lock(sc->sc_hwmtx);
372 uart_pl011_param(&sc->sc_bas, baudrate, databits, stopbits, parity);
373 uart_unlock(sc->sc_hwmtx);
374
375 return (0);
376}
377
378static int
379uart_pl011_bus_probe(struct uart_softc *sc)
380{
381
382 device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)");
383
384 sc->sc_rxfifosz = 1;
385 sc->sc_txfifosz = 1;
386
387 return (0);
388}
389
390static int
391uart_pl011_bus_receive(struct uart_softc *sc)
392{
393 struct uart_bas *bas;
394 int rx;
395 uint32_t ints, xc;
396
397 bas = &sc->sc_bas;
398 uart_lock(sc->sc_hwmtx);
399
400 ints = __uart_getreg(bas, UART_MIS);
401 while (ints & UART_RXREADY) {
402 if (uart_rx_full(sc)) {
403 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
404 break;
405 }
406 xc = __uart_getreg(bas, UART_DR);
407 rx = xc & 0xff;
408
409 if (xc & DR_FE)
410 rx |= UART_STAT_FRAMERR;
411 if (xc & DR_PE)
412 rx |= UART_STAT_PARERR;
413
414 __uart_setreg(bas, UART_ICR, UART_RXREADY);
415
416 uart_rx_put(sc, rx);
417 ints = __uart_getreg(bas, UART_MIS);
418 }
419
420 uart_unlock(sc->sc_hwmtx);
421
422 return (0);
423}
424
425static int
426uart_pl011_bus_setsig(struct uart_softc *sc, int sig)
427{
428
429 return (0);
430}
431
432static int
433uart_pl011_bus_transmit(struct uart_softc *sc)
434{
435 struct uart_bas *bas;
436 int i;
437
438 bas = &sc->sc_bas;
439 uart_lock(sc->sc_hwmtx);
440
441 for (i = 0; i < sc->sc_txdatasz; i++) {
442 __uart_setreg(bas, UART_DR, sc->sc_txbuf[i]);
443 uart_barrier(bas);
444 }
445 sc->sc_txbusy = 1;
446 __uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
447 uart_unlock(sc->sc_hwmtx);
448
449 return (0);
450}
451
452static void
453uart_pl011_bus_grab(struct uart_softc *sc)
454{
455 struct uart_bas *bas;
456
457 bas = &sc->sc_bas;
458 uart_lock(sc->sc_hwmtx);
459 __uart_setreg(bas, UART_IMSC, /* Switch to RX polling while grabbed */
460 ~UART_RXREADY & __uart_getreg(bas, UART_IMSC));
461 uart_unlock(sc->sc_hwmtx);
462}
463
464static void
465uart_pl011_bus_ungrab(struct uart_softc *sc)
466{
467 struct uart_bas *bas;
468
469 bas = &sc->sc_bas;
470 uart_lock(sc->sc_hwmtx);
471 __uart_setreg(bas, UART_IMSC, /* Switch to RX interrupts while not grabbed */
472 UART_RXREADY | __uart_getreg(bas, UART_IMSC));
473 uart_unlock(sc->sc_hwmtx);
474}