1220297Sadrian/* $NetBSD: uart.c,v 1.2 2007/03/23 20:05:47 dogcow Exp $ */
2220297Sadrian
3220297Sadrian/*-
4220297Sadrian * Copyright (c) 2010 Aleksandr Rybalko.
5220297Sadrian * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko.
6220297Sadrian * Copyright (c) 2007 Oleksandr Tymoshenko.
7220297Sadrian * All rights reserved.
8220297Sadrian *
9220297Sadrian * Redistribution and use in source and binary forms, with or
10220297Sadrian * without modification, are permitted provided that the following
11220297Sadrian * conditions are met:
12220297Sadrian * 1. Redistributions of source code must retain the above copyright
13220297Sadrian *    notice, this list of conditions and the following disclaimer.
14220297Sadrian * 2. Redistributions in binary form must reproduce the above
15220297Sadrian *    copyright notice, this list of conditions and the following
16220297Sadrian *    disclaimer in the documentation and/or other materials provided
17220297Sadrian *    with the distribution.
18220297Sadrian *
19220297Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY
20220297Sadrian * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21220297Sadrian * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22220297Sadrian * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS
23220297Sadrian * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24220297Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25220297Sadrian * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
26220297Sadrian * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27220297Sadrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
28220297Sadrian * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29220297Sadrian * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30220297Sadrian * OF SUCH DAMAGE.
31220297Sadrian */
32220297Sadrian
33220297Sadrian#include <sys/cdefs.h>
34220297Sadrian__FBSDID("$FreeBSD: releng/10.2/sys/mips/rt305x/uart_dev_rt305x.c 262649 2014-03-01 04:16:54Z imp $");
35220297Sadrian
36220297Sadrian#include "opt_ddb.h"
37220297Sadrian
38220297Sadrian#include <sys/param.h>
39220297Sadrian#include <sys/systm.h>
40220297Sadrian#include <sys/bus.h>
41220297Sadrian#include <sys/conf.h>
42220297Sadrian#include <sys/kdb.h>
43220297Sadrian#include <sys/reboot.h>
44220297Sadrian#include <sys/sysctl.h>
45220297Sadrian#include <sys/kernel.h>
46220297Sadrian#include <machine/bus.h>
47220297Sadrian
48220297Sadrian#include <dev/uart/uart.h>
49220297Sadrian#include <dev/uart/uart_cpu.h>
50220297Sadrian#include <dev/uart/uart_bus.h>
51220297Sadrian
52220297Sadrian#include <mips/rt305x/uart_dev_rt305x.h>
53220297Sadrian#include <mips/rt305x/rt305xreg.h>
54220297Sadrian
55220297Sadrian#include "uart_if.h"
56220297Sadrian/*
57220297Sadrian * Low-level UART interface.
58220297Sadrian */
59220297Sadrianstatic int rt305x_uart_probe(struct uart_bas *bas);
60220297Sadrianstatic void rt305x_uart_init(struct uart_bas *bas, int, int, int, int);
61220297Sadrianstatic void rt305x_uart_term(struct uart_bas *bas);
62220297Sadrianstatic void rt305x_uart_putc(struct uart_bas *bas, int);
63220297Sadrianstatic int rt305x_uart_rxready(struct uart_bas *bas);
64220297Sadrianstatic int rt305x_uart_getc(struct uart_bas *bas, struct mtx *);
65220297Sadrian
66220297Sadrianstatic struct uart_ops uart_rt305x_uart_ops = {
67220297Sadrian	.probe = rt305x_uart_probe,
68220297Sadrian	.init = rt305x_uart_init,
69220297Sadrian	.term = rt305x_uart_term,
70220297Sadrian	.putc = rt305x_uart_putc,
71220297Sadrian	.rxready = rt305x_uart_rxready,
72220297Sadrian	.getc = rt305x_uart_getc,
73220297Sadrian};
74220297Sadrian
75220297Sadrianstatic int	uart_output = 1;
76220297SadrianTUNABLE_INT("kern.uart_output", &uart_output);
77220297SadrianSYSCTL_INT(_kern, OID_AUTO, uart_output, CTLFLAG_RW,
78220297Sadrian    &uart_output, 0, "UART output enabled.");
79220297Sadrian
80220297Sadrian
81220297Sadrian
82220297Sadrian
83220297Sadrianstatic int
84220297Sadrianrt305x_uart_probe(struct uart_bas *bas)
85220297Sadrian{
86220297Sadrian
87220297Sadrian	return (0);
88220297Sadrian}
89220297Sadrian
90220297Sadrianstatic void
91220297Sadrianrt305x_uart_init(struct uart_bas *bas, int baudrate, int databits,
92220297Sadrian    int stopbits, int parity)
93220297Sadrian{
94220297Sadrian#ifdef notyet
95220297Sadrian        /* CLKDIV  = 384000000/ 3/ 16/ br */
96220297Sadrian        /* for 384MHz CLKDIV = 8000000 / baudrate; */
97220297Sadrian        switch (databits) {
98220297Sadrian        case 5:
99220297Sadrian    		databits = UART_LCR_5B;
100220297Sadrian    		break;
101220297Sadrian        case 6:
102220297Sadrian    		databits = UART_LCR_6B;
103220297Sadrian    		break;
104220297Sadrian        case 7:
105220297Sadrian    		databits = UART_LCR_7B;
106220297Sadrian    		break;
107220297Sadrian        case 8:
108220297Sadrian    		databits = UART_LCR_8B;
109220297Sadrian    		break;
110220297Sadrian    	default:
111220297Sadrian    		/* Unsupported */
112220297Sadrian    		return;
113220297Sadrian        }
114220297Sadrian	switch (parity) {
115220297Sadrian	case UART_PARITY_EVEN:	parity = (UART_LCR_PEN|UART_LCR_EVEN); break;
116220297Sadrian	case UART_PARITY_NONE:	parity = (UART_LCR_PEN); break;
117220297Sadrian	case UART_PARITY_ODD:	parity = 0; break;
118220297Sadrian	/* Unsupported */
119220297Sadrian	default:		return;
120220297Sadrian	}
121220297Sadrian        uart_setreg(bas, UART_CDDL_REG, 8000000/baudrate);
122220297Sadrian	uart_barrier(bas);
123220297Sadrian        uart_setreg(bas, UART_LCR_REG, databits | (stopbits==1?0:4) | parity);
124220297Sadrian	uart_barrier(bas);
125220297Sadrian#endif
126220297Sadrian}
127220297Sadrian
128220297Sadrianstatic void
129220297Sadrianrt305x_uart_term(struct uart_bas *bas)
130220297Sadrian{
131220297Sadrian        uart_setreg(bas, UART_MCR_REG, 0);
132220297Sadrian	uart_barrier(bas);
133220297Sadrian}
134220297Sadrian
135220297Sadrianstatic void
136220297Sadrianrt305x_uart_putc(struct uart_bas *bas, int c)
137220297Sadrian{
138220297Sadrian	char chr;
139220297Sadrian	if (!uart_output) return;
140220297Sadrian	chr = c;
141220297Sadrian	while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE));
142220297Sadrian	uart_setreg(bas, UART_TX_REG, c);
143220297Sadrian	uart_barrier(bas);
144220297Sadrian	while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE));
145220297Sadrian}
146220297Sadrian
147220297Sadrianstatic int
148220297Sadrianrt305x_uart_rxready(struct uart_bas *bas)
149220297Sadrian{
150220297Sadrian#ifdef notyet
151220297Sadrian	if (uart_getreg(bas, UART_LSR_REG) & UART_LSR_DR)
152220297Sadrian		return (1);
153220297Sadrian
154220297Sadrian	return (0);
155220297Sadrian#else
156220297Sadrian	return (1);
157220297Sadrian#endif
158220297Sadrian}
159220297Sadrian
160220297Sadrianstatic int
161220297Sadrianrt305x_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
162220297Sadrian{
163220297Sadrian	int c;
164220297Sadrian
165220297Sadrian	uart_lock(hwmtx);
166220297Sadrian
167220297Sadrian	while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_DR)) {
168220297Sadrian		uart_unlock(hwmtx);
169220297Sadrian		DELAY(10);
170220297Sadrian		uart_lock(hwmtx);
171220297Sadrian	}
172220297Sadrian
173220297Sadrian	c = uart_getreg(bas, UART_RX_REG);
174220297Sadrian
175220297Sadrian	uart_unlock(hwmtx);
176220297Sadrian
177220297Sadrian	return (c);
178220297Sadrian}
179220297Sadrian
180220297Sadrian/*
181220297Sadrian * High-level UART interface.
182220297Sadrian */
183220297Sadrianstruct rt305x_uart_softc {
184220297Sadrian	struct uart_softc base;
185220297Sadrian};
186220297Sadrian
187220297Sadrianstatic int rt305x_uart_bus_attach(struct uart_softc *);
188220297Sadrianstatic int rt305x_uart_bus_detach(struct uart_softc *);
189220297Sadrianstatic int rt305x_uart_bus_flush(struct uart_softc *, int);
190220297Sadrianstatic int rt305x_uart_bus_getsig(struct uart_softc *);
191220297Sadrianstatic int rt305x_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
192220297Sadrianstatic int rt305x_uart_bus_ipend(struct uart_softc *);
193220297Sadrianstatic int rt305x_uart_bus_param(struct uart_softc *, int, int, int, int);
194220297Sadrianstatic int rt305x_uart_bus_probe(struct uart_softc *);
195220297Sadrianstatic int rt305x_uart_bus_receive(struct uart_softc *);
196220297Sadrianstatic int rt305x_uart_bus_setsig(struct uart_softc *, int);
197220297Sadrianstatic int rt305x_uart_bus_transmit(struct uart_softc *);
198262649Simpstatic void rt305x_uart_bus_grab(struct uart_softc *);
199262649Simpstatic void rt305x_uart_bus_ungrab(struct uart_softc *);
200220297Sadrian
201220297Sadrianstatic kobj_method_t rt305x_uart_methods[] = {
202220297Sadrian	KOBJMETHOD(uart_attach,		rt305x_uart_bus_attach),
203220297Sadrian	KOBJMETHOD(uart_detach,		rt305x_uart_bus_detach),
204220297Sadrian	KOBJMETHOD(uart_flush,		rt305x_uart_bus_flush),
205220297Sadrian	KOBJMETHOD(uart_getsig,		rt305x_uart_bus_getsig),
206220297Sadrian	KOBJMETHOD(uart_ioctl,		rt305x_uart_bus_ioctl),
207220297Sadrian	KOBJMETHOD(uart_ipend,		rt305x_uart_bus_ipend),
208220297Sadrian	KOBJMETHOD(uart_param,		rt305x_uart_bus_param),
209220297Sadrian	KOBJMETHOD(uart_probe,		rt305x_uart_bus_probe),
210220297Sadrian	KOBJMETHOD(uart_receive,	rt305x_uart_bus_receive),
211220297Sadrian	KOBJMETHOD(uart_setsig,		rt305x_uart_bus_setsig),
212220297Sadrian	KOBJMETHOD(uart_transmit,	rt305x_uart_bus_transmit),
213262649Simp	KOBJMETHOD(uart_grab,		rt305x_uart_bus_grab),
214262649Simp	KOBJMETHOD(uart_ungrab,		rt305x_uart_bus_ungrab),
215220297Sadrian	{ 0, 0 }
216220297Sadrian};
217220297Sadrian
218220297Sadrianstruct uart_class uart_rt305x_uart_class = {
219220297Sadrian	"rt305x",
220220297Sadrian	rt305x_uart_methods,
221220297Sadrian	sizeof(struct rt305x_uart_softc),
222220297Sadrian	.uc_ops = &uart_rt305x_uart_ops,
223220297Sadrian	.uc_range = 1, /* use hinted range */
224220297Sadrian	.uc_rclk = SYSTEM_CLOCK
225220297Sadrian};
226220297Sadrian
227220297Sadrian#define	SIGCHG(c, i, s, d)				\
228220297Sadrian	if (c) {					\
229220297Sadrian		i |= (i & s) ? s : s | d;		\
230220297Sadrian	} else {					\
231220297Sadrian		i = (i & s) ? (i & ~s) | d : i;		\
232220297Sadrian	}
233220297Sadrian
234220297Sadrian/*
235220297Sadrian * Disable TX interrupt. uart should be locked
236220297Sadrian */
237220297Sadrianstatic __inline void
238220297Sadrianrt305x_uart_disable_txintr(struct uart_softc *sc)
239220297Sadrian{
240220297Sadrian	struct uart_bas *bas = &sc->sc_bas;
241220297Sadrian	uint8_t cr;
242220297Sadrian
243220297Sadrian	cr = uart_getreg(bas, UART_IER_REG);
244220297Sadrian	cr &= ~UART_IER_ETBEI;
245220297Sadrian	uart_setreg(bas, UART_IER_REG, cr);
246220297Sadrian	uart_barrier(bas);
247220297Sadrian}
248220297Sadrian
249220297Sadrian/*
250220297Sadrian * Enable TX interrupt. uart should be locked
251220297Sadrian */
252220297Sadrianstatic __inline void
253220297Sadrianrt305x_uart_enable_txintr(struct uart_softc *sc)
254220297Sadrian{
255220297Sadrian	struct uart_bas *bas = &sc->sc_bas;
256220297Sadrian	uint8_t cr;
257220297Sadrian
258220297Sadrian	cr = uart_getreg(bas, UART_IER_REG);
259220297Sadrian	cr |= UART_IER_ETBEI;
260220297Sadrian	uart_setreg(bas, UART_IER_REG, cr);
261220297Sadrian	uart_barrier(bas);
262220297Sadrian}
263220297Sadrian
264220297Sadrianstatic int
265220297Sadrianrt305x_uart_bus_attach(struct uart_softc *sc)
266220297Sadrian{
267220297Sadrian	struct uart_bas *bas;
268220297Sadrian	struct uart_devinfo *di;
269220297Sadrian
270220297Sadrian	bas = &sc->sc_bas;
271220297Sadrian	if (sc->sc_sysdev != NULL) {
272220297Sadrian		di = sc->sc_sysdev;
273220297Sadrian		rt305x_uart_init(bas, di->baudrate, di->databits, di->stopbits,
274220297Sadrian		    di->parity);
275220297Sadrian	} else {
276220297Sadrian		rt305x_uart_init(bas, 115200, 8, 1, 0);
277220297Sadrian	}
278220297Sadrian
279220297Sadrian	(void)rt305x_uart_bus_getsig(sc);
280220297Sadrian
281220297Sadrian	/* Enable FIFO */
282220297Sadrian	uart_setreg(bas, UART_FCR_REG,
283220297Sadrian	    uart_getreg(bas, UART_FCR_REG) |
284220297Sadrian	    UART_FCR_FIFOEN | UART_FCR_TXTGR_1 | UART_FCR_RXTGR_1);
285262649Simp 	uart_barrier(bas);
286220297Sadrian	/* Enable interrupts */
287220297Sadrian	uart_setreg(bas, UART_IER_REG,
288220297Sadrian	    UART_IER_EDSSI | UART_IER_ELSI | UART_IER_ERBFI);
289220297Sadrian	uart_barrier(bas);
290220297Sadrian
291220297Sadrian	return (0);
292220297Sadrian}
293220297Sadrian
294220297Sadrianstatic int
295220297Sadrianrt305x_uart_bus_detach(struct uart_softc *sc)
296220297Sadrian{
297220297Sadrian
298220297Sadrian	return (0);
299220297Sadrian}
300220297Sadrian
301220297Sadrianstatic int
302220297Sadrianrt305x_uart_bus_flush(struct uart_softc *sc, int what)
303220297Sadrian{
304220297Sadrian	struct uart_bas *bas = &sc->sc_bas;
305220297Sadrian	uint32_t fcr = uart_getreg(bas, UART_FCR_REG);
306220297Sadrian	if (what & UART_FLUSH_TRANSMITTER) {
307220297Sadrian		uart_setreg(bas, UART_FCR_REG, fcr|UART_FCR_TXRST);
308220297Sadrian		uart_barrier(bas);
309220297Sadrian	}
310220297Sadrian	if (what & UART_FLUSH_RECEIVER) {
311220297Sadrian		uart_setreg(bas, UART_FCR_REG, fcr|UART_FCR_RXRST);
312220297Sadrian		uart_barrier(bas);
313220297Sadrian	}
314220297Sadrian	uart_setreg(bas, UART_FCR_REG, fcr);
315220297Sadrian	uart_barrier(bas);
316220297Sadrian	return (0);
317220297Sadrian}
318220297Sadrian
319220297Sadrianstatic int
320220297Sadrianrt305x_uart_bus_getsig(struct uart_softc *sc)
321220297Sadrian{
322220297Sadrian	uint32_t new, old, sig;
323220297Sadrian	uint8_t bes;
324220297Sadrian
325220297Sadrian	do {
326220297Sadrian		old = sc->sc_hwsig;
327220297Sadrian		sig = old;
328220297Sadrian		uart_lock(sc->sc_hwmtx);
329220297Sadrian		bes = uart_getreg(&sc->sc_bas, UART_MSR_REG);
330220297Sadrian		uart_unlock(sc->sc_hwmtx);
331220297Sadrian		/* XXX: chip can show delta */
332220297Sadrian		SIGCHG(bes & UART_MSR_CTS, sig, SER_CTS, SER_DCTS);
333220297Sadrian		SIGCHG(bes & UART_MSR_DCD, sig, SER_DCD, SER_DDCD);
334220297Sadrian		SIGCHG(bes & UART_MSR_DSR, sig, SER_DSR, SER_DDSR);
335220297Sadrian		new = sig & ~SER_MASK_DELTA;
336220297Sadrian	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
337220297Sadrian
338220297Sadrian	return (sig);
339220297Sadrian}
340220297Sadrian
341220297Sadrianstatic int
342220297Sadrianrt305x_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
343220297Sadrian{
344220297Sadrian	struct uart_bas *bas;
345220297Sadrian	int baudrate, divisor, error;
346220297Sadrian
347220297Sadrian	bas = &sc->sc_bas;
348220297Sadrian	error = 0;
349220297Sadrian	uart_lock(sc->sc_hwmtx);
350220297Sadrian	switch (request) {
351220297Sadrian	case UART_IOCTL_BREAK:
352220297Sadrian		/* TODO: Send BREAK */
353220297Sadrian		break;
354220297Sadrian	case UART_IOCTL_BAUD:
355220297Sadrian		divisor = uart_getreg(bas, UART_CDDL_REG);
356220297Sadrian		baudrate = bas->rclk / (divisor * 16);
357220297Sadrian		*(int*)data = baudrate;
358220297Sadrian		break;
359220297Sadrian	default:
360220297Sadrian		error = EINVAL;
361220297Sadrian		break;
362220297Sadrian	}
363220297Sadrian	uart_unlock(sc->sc_hwmtx);
364220297Sadrian	return (error);
365220297Sadrian}
366220297Sadrian
367220297Sadrianstatic int
368220297Sadrianrt305x_uart_bus_ipend(struct uart_softc *sc)
369220297Sadrian{
370220297Sadrian	struct uart_bas *bas;
371220297Sadrian	int ipend;
372220297Sadrian	uint8_t iir, lsr, msr;
373220297Sadrian
374220297Sadrian	bas = &sc->sc_bas;
375220297Sadrian	ipend = 0;
376220297Sadrian
377220297Sadrian	uart_lock(sc->sc_hwmtx);
378220297Sadrian	iir = uart_getreg(&sc->sc_bas, UART_IIR_REG);
379220297Sadrian	lsr = uart_getreg(&sc->sc_bas, UART_LSR_REG);
380220297Sadrian	uart_setreg(&sc->sc_bas, UART_LSR_REG, lsr);
381220297Sadrian	msr = uart_getreg(&sc->sc_bas, UART_MSR_REG);
382220297Sadrian	uart_setreg(&sc->sc_bas, UART_MSR_REG, msr);
383220297Sadrian	if (iir & UART_IIR_INTP) {
384220297Sadrian		uart_unlock(sc->sc_hwmtx);
385220297Sadrian		return (0);
386220297Sadrian	}
387220297Sadrian
388220297Sadrian
389220297Sadrian	switch ((iir >> 1) & 0x07) {
390220297Sadrian	case UART_IIR_ID_THRE:
391220297Sadrian		ipend |= SER_INT_TXIDLE;
392220297Sadrian		break;
393220297Sadrian	case UART_IIR_ID_DR2:
394220297Sadrian		rt305x_uart_bus_flush(sc, UART_FLUSH_RECEIVER);
395220297Sadrian		/* passthrough */
396220297Sadrian	case UART_IIR_ID_DR:
397220297Sadrian		ipend |= SER_INT_RXREADY;
398220297Sadrian		break;
399220297Sadrian	case UART_IIR_ID_MST:
400220297Sadrian	case UART_IIR_ID_LINESTATUS:
401220297Sadrian		ipend |= SER_INT_SIGCHG;
402220297Sadrian		if (lsr & UART_LSR_BI)
403220297Sadrian		{
404220297Sadrian			ipend |= SER_INT_BREAK;
405220297Sadrian#ifdef KDB
406220297Sadrian			breakpoint();
407220297Sadrian#endif
408220297Sadrian		}
409220297Sadrian		if (lsr & UART_LSR_OE)
410220297Sadrian			ipend |= SER_INT_OVERRUN;
411220297Sadrian		break;
412220297Sadrian	default:
413220297Sadrian		/* XXX: maybe return error here */
414220297Sadrian		break;
415220297Sadrian	}
416220297Sadrian
417220297Sadrian	uart_unlock(sc->sc_hwmtx);
418220297Sadrian
419220297Sadrian	return (ipend);
420220297Sadrian}
421220297Sadrian
422220297Sadrianstatic int
423220297Sadrianrt305x_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
424220297Sadrian    int stopbits, int parity)
425220297Sadrian{
426220297Sadrian	uart_lock(sc->sc_hwmtx);
427220297Sadrian	rt305x_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity);
428220297Sadrian	uart_unlock(sc->sc_hwmtx);
429220297Sadrian	return (0);
430220297Sadrian}
431220297Sadrian
432220297Sadrianstatic int
433220297Sadrianrt305x_uart_bus_probe(struct uart_softc *sc)
434220297Sadrian{
435220297Sadrian	char buf[80];
436220297Sadrian	int error;
437220297Sadrian
438220297Sadrian	error = rt305x_uart_probe(&sc->sc_bas);
439220297Sadrian	if (error)
440220297Sadrian		return (error);
441220297Sadrian
442248965Sian	sc->sc_rxfifosz = 16;
443248965Sian	sc->sc_txfifosz = 16;
444248965Sian
445220297Sadrian	snprintf(buf, sizeof(buf), "rt305x_uart");
446220297Sadrian	device_set_desc_copy(sc->sc_dev, buf);
447220297Sadrian
448220297Sadrian	return (0);
449220297Sadrian}
450220297Sadrian
451220297Sadrianstatic int
452220297Sadrianrt305x_uart_bus_receive(struct uart_softc *sc)
453220297Sadrian{
454220297Sadrian	struct uart_bas *bas;
455220297Sadrian	int xc;
456220297Sadrian	uint8_t lsr;
457220297Sadrian
458220297Sadrian	bas = &sc->sc_bas;
459220297Sadrian	uart_lock(sc->sc_hwmtx);
460220297Sadrian	lsr = uart_getreg(bas, UART_LSR_REG);
461220297Sadrian	while ((lsr & UART_LSR_DR)) {
462220297Sadrian		if (uart_rx_full(sc)) {
463220297Sadrian			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
464220297Sadrian			break;
465220297Sadrian		}
466220297Sadrian		xc = 0;
467220297Sadrian		xc = uart_getreg(bas, UART_RX_REG);
468220297Sadrian		if (lsr & UART_LSR_FE)
469220297Sadrian			xc |= UART_STAT_FRAMERR;
470220297Sadrian		if (lsr & UART_LSR_PE)
471220297Sadrian			xc |= UART_STAT_PARERR;
472220297Sadrian		if (lsr & UART_LSR_OE)
473220297Sadrian			xc |= UART_STAT_OVERRUN;
474220297Sadrian		uart_barrier(bas);
475220297Sadrian		uart_rx_put(sc, xc);
476220297Sadrian		lsr = uart_getreg(bas, UART_LSR_REG);
477220297Sadrian	}
478220297Sadrian
479220297Sadrian	uart_unlock(sc->sc_hwmtx);
480220297Sadrian	return (0);
481220297Sadrian}
482220297Sadrian
483220297Sadrianstatic int
484220297Sadrianrt305x_uart_bus_setsig(struct uart_softc *sc, int sig)
485220297Sadrian{
486220297Sadrian
487220297Sadrian	/* TODO: implement (?) */
488220297Sadrian	return (0);
489220297Sadrian}
490220297Sadrian
491220297Sadrianstatic int
492220297Sadrianrt305x_uart_bus_transmit(struct uart_softc *sc)
493220297Sadrian{
494220297Sadrian	struct uart_bas *bas = &sc->sc_bas;
495220297Sadrian	int i;
496220297Sadrian
497220297Sadrian	if (!uart_output) return (0);
498220297Sadrian
499220297Sadrian	bas = &sc->sc_bas;
500220297Sadrian	uart_lock(sc->sc_hwmtx);
501220297Sadrian	while ((uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE) == 0)
502220297Sadrian		;
503220297Sadrian	rt305x_uart_enable_txintr(sc);
504220297Sadrian	for (i = 0; i < sc->sc_txdatasz; i++) {
505220297Sadrian		uart_setreg(bas, UART_TX_REG, sc->sc_txbuf[i]);
506220297Sadrian		uart_barrier(bas);
507220297Sadrian	}
508220297Sadrian	sc->sc_txbusy = 1;
509220297Sadrian	uart_unlock(sc->sc_hwmtx);
510220297Sadrian	return (0);
511220297Sadrian}
512262649Simp
513262649Simpstatic void
514262649Simprt305x_uart_bus_grab(struct uart_softc *sc)
515262649Simp{
516262649Simp	struct uart_bas *bas = &sc->sc_bas;
517262649Simp
518262649Simp	/* disable interrupts -- XXX not sure which one is RX, so kill them all */
519262649Simp	uart_lock(sc->sc_hwmtx);
520262649Simp	uart_setreg(bas, UART_IER_REG, 0);
521262649Simp	uart_barrier(bas);
522262649Simp	uart_unlock(sc->sc_hwmtx);
523262649Simp}
524262649Simp
525262649Simpstatic void
526262649Simprt305x_uart_bus_ungrab(struct uart_softc *sc)
527262649Simp{
528262649Simp	struct uart_bas *bas = &sc->sc_bas;
529262649Simp
530262649Simp	/* Enable interrupts */
531262649Simp	uart_lock(sc->sc_hwmtx);
532262649Simp	uart_setreg(bas, UART_IER_REG,
533262649Simp	    UART_IER_EDSSI | UART_IER_ELSI | UART_IER_ERBFI);
534262649Simp	uart_barrier(bas);
535262649Simp	uart_unlock(sc->sc_hwmtx);
536262649Simp}
537