uart_dev_ar933x.c revision 248926
1248843Sadrian/*-
2248843Sadrian * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
3248843Sadrian * All rights reserved.
4248843Sadrian *
5248843Sadrian * Redistribution and use in source and binary forms, with or without
6248843Sadrian * modification, are permitted provided that the following conditions
7248843Sadrian * are met:
8248843Sadrian *
9248843Sadrian * 1. Redistributions of source code must retain the above copyright
10248843Sadrian *    notice, this list of conditions and the following disclaimer.
11248843Sadrian * 2. Redistributions in binary form must reproduce the above copyright
12248843Sadrian *    notice, this list of conditions and the following disclaimer in the
13248843Sadrian *    documentation and/or other materials provided with the distribution.
14248843Sadrian *
15248843Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16248843Sadrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17248843Sadrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18248843Sadrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19248843Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20248843Sadrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21248843Sadrian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22248843Sadrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23248843Sadrian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24248843Sadrian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25248843Sadrian */
26248843Sadrian
27248843Sadrian#include <sys/cdefs.h>
28248843Sadrian__FBSDID("$FreeBSD: head/sys/mips/atheros/uart_dev_ar933x.c 248926 2013-03-30 04:13:47Z adrian $");
29248843Sadrian
30248843Sadrian#include <sys/param.h>
31248843Sadrian#include <sys/systm.h>
32248843Sadrian#include <sys/bus.h>
33248843Sadrian#include <sys/conf.h>
34248843Sadrian#include <machine/bus.h>
35248843Sadrian
36248843Sadrian#include <dev/uart/uart.h>
37248843Sadrian#include <dev/uart/uart_cpu.h>
38248843Sadrian#include <dev/uart/uart_bus.h>
39248843Sadrian
40248843Sadrian#include <mips/atheros/ar933x_uart.h>
41248843Sadrian
42248843Sadrian#include "uart_if.h"
43248843Sadrian
44248926Sadrian/*
45248926Sadrian * Default system clock is 25MHz; see ar933x_chip.c for how
46248926Sadrian * the startup process determines whether it's 25MHz or 40MHz.
47248926Sadrian */
48248926Sadrian#define	DEFAULT_RCLK	(25 * 1000 * 1000)
49248843Sadrian
50248843Sadrian#define	ar933x_getreg(bas, reg)           \
51248926Sadrian	bus_space_read_4((bas)->bst, (bas)->bsh, reg)
52248843Sadrian#define	ar933x_setreg(bas, reg, value)    \
53248926Sadrian	bus_space_write_4((bas)->bst, (bas)->bsh, reg, value)
54248843Sadrian
55248843Sadrian
56248843Sadrian#if 0
57248843Sadrian/*
58248843Sadrian * Clear pending interrupts. THRE is cleared by reading IIR. Data
59248843Sadrian * that may have been received gets lost here.
60248843Sadrian */
61248843Sadrianstatic void
62248843Sadrianar933x_clrint(struct uart_bas *bas)
63248843Sadrian{
64248843Sadrian	uint8_t iir, lsr;
65248843Sadrian
66248843Sadrian	iir = uart_getreg(bas, REG_IIR);
67248843Sadrian	while ((iir & IIR_NOPEND) == 0) {
68248843Sadrian		iir &= IIR_IMASK;
69248843Sadrian		if (iir == IIR_RLS) {
70248843Sadrian			lsr = uart_getreg(bas, REG_LSR);
71248843Sadrian			if (lsr & (LSR_BI|LSR_FE|LSR_PE))
72248843Sadrian				(void)uart_getreg(bas, REG_DATA);
73248843Sadrian		} else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
74248843Sadrian			(void)uart_getreg(bas, REG_DATA);
75248843Sadrian		else if (iir == IIR_MLSC)
76248843Sadrian			(void)uart_getreg(bas, REG_MSR);
77248843Sadrian		uart_barrier(bas);
78248843Sadrian		iir = uart_getreg(bas, REG_IIR);
79248843Sadrian	}
80248843Sadrian}
81248843Sadrian#endif
82248843Sadrian
83248843Sadrian#if 0
84248843Sadrianstatic int
85248843Sadrianar933x_drain(struct uart_bas *bas, int what)
86248843Sadrian{
87248843Sadrian	int delay, limit;
88248843Sadrian
89248843Sadrian	delay = ar933x_delay(bas);
90248843Sadrian
91248843Sadrian	if (what & UART_DRAIN_TRANSMITTER) {
92248843Sadrian		/*
93248843Sadrian		 * Pick an arbitrary high limit to avoid getting stuck in
94248843Sadrian		 * an infinite loop when the hardware is broken. Make the
95248843Sadrian		 * limit high enough to handle large FIFOs.
96248843Sadrian		 */
97248843Sadrian		limit = 10*1024;
98248843Sadrian		while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
99248843Sadrian			DELAY(delay);
100248843Sadrian		if (limit == 0) {
101248843Sadrian			/* printf("ns8250: transmitter appears stuck... "); */
102248843Sadrian			return (EIO);
103248843Sadrian		}
104248843Sadrian	}
105248843Sadrian
106248843Sadrian	if (what & UART_DRAIN_RECEIVER) {
107248843Sadrian		/*
108248843Sadrian		 * Pick an arbitrary high limit to avoid getting stuck in
109248843Sadrian		 * an infinite loop when the hardware is broken. Make the
110248843Sadrian		 * limit high enough to handle large FIFOs and integrated
111248843Sadrian		 * UARTs. The HP rx2600 for example has 3 UARTs on the
112248843Sadrian		 * management board that tend to get a lot of data send
113248843Sadrian		 * to it when the UART is first activated.
114248843Sadrian		 */
115248843Sadrian		limit=10*4096;
116248843Sadrian		while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) {
117248843Sadrian			(void)uart_getreg(bas, REG_DATA);
118248843Sadrian			uart_barrier(bas);
119248843Sadrian			DELAY(delay << 2);
120248843Sadrian		}
121248843Sadrian		if (limit == 0) {
122248843Sadrian			/* printf("ns8250: receiver appears broken... "); */
123248843Sadrian			return (EIO);
124248843Sadrian		}
125248843Sadrian	}
126248843Sadrian	return (0);
127248843Sadrian}
128248843Sadrian#endif
129248843Sadrian
130248843Sadrian#if 0
131248843Sadrian/*
132248843Sadrian * We can only flush UARTs with FIFOs. UARTs without FIFOs should be
133248843Sadrian * drained. WARNING: this function clobbers the FIFO setting!
134248843Sadrian */
135248843Sadrianstatic void
136248843Sadrianar933x_flush(struct uart_bas *bas, int what)
137248843Sadrian{
138248843Sadrian	uint8_t fcr;
139248843Sadrian
140248843Sadrian	fcr = FCR_ENABLE;
141248843Sadrian	if (what & UART_FLUSH_TRANSMITTER)
142248843Sadrian		fcr |= FCR_XMT_RST;
143248843Sadrian	if (what & UART_FLUSH_RECEIVER)
144248843Sadrian		fcr |= FCR_RCV_RST;
145248843Sadrian	uart_setreg(bas, REG_FCR, fcr);
146248843Sadrian	uart_barrier(bas);
147248843Sadrian}
148248843Sadrian#endif
149248843Sadrian
150248843Sadrian#if 0
151248843Sadrianstatic int
152248843Sadrianar933x_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
153248843Sadrian    int parity)
154248843Sadrian{
155248843Sadrian	int divisor;
156248843Sadrian	uint8_t lcr;
157248843Sadrian
158248843Sadrian	lcr = 0;
159248843Sadrian	if (databits >= 8)
160248843Sadrian		lcr |= LCR_8BITS;
161248843Sadrian	else if (databits == 7)
162248843Sadrian		lcr |= LCR_7BITS;
163248843Sadrian	else if (databits == 6)
164248843Sadrian		lcr |= LCR_6BITS;
165248843Sadrian	else
166248843Sadrian		lcr |= LCR_5BITS;
167248843Sadrian	if (stopbits > 1)
168248843Sadrian		lcr |= LCR_STOPB;
169248843Sadrian	lcr |= parity << 3;
170248843Sadrian
171248843Sadrian	/* Set baudrate. */
172248843Sadrian	if (baudrate > 0) {
173248843Sadrian		divisor = ar933x_divisor(bas->rclk, baudrate);
174248843Sadrian		if (divisor == 0)
175248843Sadrian			return (EINVAL);
176248843Sadrian		uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
177248843Sadrian		uart_barrier(bas);
178248843Sadrian		uart_setreg(bas, REG_DLL, divisor & 0xff);
179248843Sadrian		uart_setreg(bas, REG_DLH, (divisor >> 8) & 0xff);
180248843Sadrian		uart_barrier(bas);
181248843Sadrian	}
182248843Sadrian
183248843Sadrian	/* Set LCR and clear DLAB. */
184248843Sadrian	uart_setreg(bas, REG_LCR, lcr);
185248843Sadrian	uart_barrier(bas);
186248843Sadrian	return (0);
187248843Sadrian}
188248843Sadrian#endif
189248843Sadrian
190248843Sadrian/*
191248843Sadrian * Low-level UART interface.
192248843Sadrian */
193248843Sadrianstatic int ar933x_probe(struct uart_bas *bas);
194248843Sadrianstatic void ar933x_init(struct uart_bas *bas, int, int, int, int);
195248843Sadrianstatic void ar933x_term(struct uart_bas *bas);
196248843Sadrianstatic void ar933x_putc(struct uart_bas *bas, int);
197248843Sadrianstatic int ar933x_rxready(struct uart_bas *bas);
198248843Sadrianstatic int ar933x_getc(struct uart_bas *bas, struct mtx *);
199248843Sadrian
200248843Sadrianstatic struct uart_ops uart_ar933x_ops = {
201248843Sadrian	.probe = ar933x_probe,
202248843Sadrian	.init = ar933x_init,
203248843Sadrian	.term = ar933x_term,
204248843Sadrian	.putc = ar933x_putc,
205248843Sadrian	.rxready = ar933x_rxready,
206248843Sadrian	.getc = ar933x_getc,
207248843Sadrian};
208248843Sadrian
209248843Sadrianstatic int
210248843Sadrianar933x_probe(struct uart_bas *bas)
211248843Sadrian{
212248843Sadrian#if 0
213248843Sadrian	u_char val;
214248843Sadrian
215248843Sadrian	/* Check known 0 bits that don't depend on DLAB. */
216248843Sadrian	val = uart_getreg(bas, REG_IIR);
217248843Sadrian	if (val & 0x30)
218248843Sadrian		return (ENXIO);
219248843Sadrian	/*
220248843Sadrian	 * Bit 6 of the MCR (= 0x40) appears to be 1 for the Sun1699
221248843Sadrian	 * chip, but otherwise doesn't seem to have a function. In
222248843Sadrian	 * other words, uart(4) works regardless. Ignore that bit so
223248843Sadrian	 * the probe succeeds.
224248843Sadrian	 */
225248843Sadrian	val = uart_getreg(bas, REG_MCR);
226248843Sadrian	if (val & 0xa0)
227248843Sadrian		return (ENXIO);
228248843Sadrian#endif
229248843Sadrian	return (0);
230248843Sadrian}
231248843Sadrian
232248843Sadrianstatic void
233248843Sadrianar933x_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
234248843Sadrian    int parity)
235248843Sadrian{
236248843Sadrian#if 0
237248843Sadrian	u_char	ier;
238248843Sadrian
239248843Sadrian	if (bas->rclk == 0)
240248843Sadrian		bas->rclk = DEFAULT_RCLK;
241248843Sadrian	ar933x_param(bas, baudrate, databits, stopbits, parity);
242248843Sadrian
243248843Sadrian	/* Disable all interrupt sources. */
244248843Sadrian	/*
245248843Sadrian	 * We use 0xe0 instead of 0xf0 as the mask because the XScale PXA
246248843Sadrian	 * UARTs split the receive time-out interrupt bit out separately as
247248843Sadrian	 * 0x10.  This gets handled by ier_mask and ier_rxbits below.
248248843Sadrian	 */
249248843Sadrian	ier = uart_getreg(bas, REG_IER) & 0xe0;
250248843Sadrian	uart_setreg(bas, REG_IER, ier);
251248843Sadrian	uart_barrier(bas);
252248843Sadrian
253248843Sadrian	/* Disable the FIFO (if present). */
254248843Sadrian	uart_setreg(bas, REG_FCR, 0);
255248843Sadrian	uart_barrier(bas);
256248843Sadrian
257248843Sadrian	/* Set RTS & DTR. */
258248843Sadrian	uart_setreg(bas, REG_MCR, MCR_IE | MCR_RTS | MCR_DTR);
259248843Sadrian	uart_barrier(bas);
260248843Sadrian
261248843Sadrian	ar933x_clrint(bas);
262248843Sadrian#endif
263248843Sadrian}
264248843Sadrian
265248843Sadrianstatic void
266248843Sadrianar933x_term(struct uart_bas *bas)
267248843Sadrian{
268248843Sadrian#if 0
269248843Sadrian	/* Clear RTS & DTR. */
270248843Sadrian	uart_setreg(bas, REG_MCR, MCR_IE);
271248843Sadrian	uart_barrier(bas);
272248843Sadrian#endif
273248843Sadrian}
274248843Sadrian
275248843Sadrianstatic void
276248843Sadrianar933x_putc(struct uart_bas *bas, int c)
277248843Sadrian{
278248843Sadrian	int limit;
279248843Sadrian
280248843Sadrian	limit = 250000;
281248843Sadrian
282248843Sadrian	/* Wait for space in the TX FIFO */
283248843Sadrian	while ( ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
284248843Sadrian	    AR933X_UART_DATA_TX_CSR) == 0) && --limit)
285248843Sadrian		DELAY(4);
286248843Sadrian
287248843Sadrian	/* Write the actual byte */
288248843Sadrian	ar933x_setreg(bas, AR933X_UART_DATA_REG,
289248843Sadrian	    (c & 0xff) | AR933X_UART_DATA_TX_CSR);
290248843Sadrian}
291248843Sadrian
292248843Sadrianstatic int
293248843Sadrianar933x_rxready(struct uart_bas *bas)
294248843Sadrian{
295248843Sadrian
296248843Sadrian	/* Wait for a character to come ready */
297248843Sadrian	return (!!(ar933x_getreg(bas, AR933X_UART_DATA_REG)
298248843Sadrian	    & AR933X_UART_DATA_RX_CSR));
299248843Sadrian}
300248843Sadrian
301248843Sadrianstatic int
302248843Sadrianar933x_getc(struct uart_bas *bas, struct mtx *hwmtx)
303248843Sadrian{
304248843Sadrian	int c;
305248843Sadrian
306248843Sadrian	uart_lock(hwmtx);
307248843Sadrian
308248843Sadrian	/* Wait for a character to come ready */
309248843Sadrian	while ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
310248843Sadrian	    AR933X_UART_DATA_RX_CSR) == 0) {
311248843Sadrian		uart_unlock(hwmtx);
312248843Sadrian		DELAY(4);
313248843Sadrian		uart_lock(hwmtx);
314248843Sadrian	}
315248843Sadrian
316248843Sadrian	/* Read the top of the RX FIFO */
317248843Sadrian	c = ar933x_getreg(bas, AR933X_UART_DATA_REG) & 0xff;
318248843Sadrian
319248843Sadrian	/* Remove that entry from said RX FIFO */
320248843Sadrian	ar933x_setreg(bas, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);
321248843Sadrian
322248843Sadrian	uart_unlock(hwmtx);
323248843Sadrian
324248843Sadrian	return (c);
325248843Sadrian}
326248843Sadrian
327248843Sadrian/*
328248843Sadrian * High-level UART interface.
329248843Sadrian */
330248843Sadrianstruct ar933x_softc {
331248843Sadrian	struct uart_softc base;
332248926Sadrian
333248843Sadrian	uint32_t	u_ier;
334248843Sadrian};
335248843Sadrian
336248843Sadrianstatic int ar933x_bus_attach(struct uart_softc *);
337248843Sadrianstatic int ar933x_bus_detach(struct uart_softc *);
338248843Sadrianstatic int ar933x_bus_flush(struct uart_softc *, int);
339248843Sadrianstatic int ar933x_bus_getsig(struct uart_softc *);
340248843Sadrianstatic int ar933x_bus_ioctl(struct uart_softc *, int, intptr_t);
341248843Sadrianstatic int ar933x_bus_ipend(struct uart_softc *);
342248843Sadrianstatic int ar933x_bus_param(struct uart_softc *, int, int, int, int);
343248843Sadrianstatic int ar933x_bus_probe(struct uart_softc *);
344248843Sadrianstatic int ar933x_bus_receive(struct uart_softc *);
345248843Sadrianstatic int ar933x_bus_setsig(struct uart_softc *, int);
346248843Sadrianstatic int ar933x_bus_transmit(struct uart_softc *);
347248843Sadrian
348248843Sadrianstatic kobj_method_t ar933x_methods[] = {
349248843Sadrian	KOBJMETHOD(uart_attach,		ar933x_bus_attach),
350248843Sadrian	KOBJMETHOD(uart_detach,		ar933x_bus_detach),
351248843Sadrian	KOBJMETHOD(uart_flush,		ar933x_bus_flush),
352248843Sadrian	KOBJMETHOD(uart_getsig,		ar933x_bus_getsig),
353248843Sadrian	KOBJMETHOD(uart_ioctl,		ar933x_bus_ioctl),
354248843Sadrian	KOBJMETHOD(uart_ipend,		ar933x_bus_ipend),
355248843Sadrian	KOBJMETHOD(uart_param,		ar933x_bus_param),
356248843Sadrian	KOBJMETHOD(uart_probe,		ar933x_bus_probe),
357248843Sadrian	KOBJMETHOD(uart_receive,	ar933x_bus_receive),
358248843Sadrian	KOBJMETHOD(uart_setsig,		ar933x_bus_setsig),
359248843Sadrian	KOBJMETHOD(uart_transmit,	ar933x_bus_transmit),
360248843Sadrian	{ 0, 0 }
361248843Sadrian};
362248843Sadrian
363248843Sadrianstruct uart_class uart_ar933x_class = {
364248843Sadrian	"ar933x",
365248843Sadrian	ar933x_methods,
366248843Sadrian	sizeof(struct ar933x_softc),
367248843Sadrian	.uc_ops = &uart_ar933x_ops,
368248843Sadrian	.uc_range = 8,
369248843Sadrian	.uc_rclk = DEFAULT_RCLK
370248843Sadrian};
371248843Sadrian
372248843Sadrian#define	SIGCHG(c, i, s, d)				\
373248843Sadrian	if (c) {					\
374248843Sadrian		i |= (i & s) ? s : s | d;		\
375248843Sadrian	} else {					\
376248843Sadrian		i = (i & s) ? (i & ~s) | d : i;		\
377248843Sadrian	}
378248843Sadrian
379248843Sadrianstatic int
380248843Sadrianar933x_bus_attach(struct uart_softc *sc)
381248843Sadrian{
382248843Sadrian#if 0
383248843Sadrian	struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc;
384248843Sadrian	struct uart_bas *bas;
385248843Sadrian	unsigned int ivar;
386248843Sadrian
387248843Sadrian	bas = &sc->sc_bas;
388248843Sadrian
389248843Sadrian	ns8250->mcr = uart_getreg(bas, REG_MCR);
390248843Sadrian	ns8250->fcr = FCR_ENABLE;
391248843Sadrian	if (!resource_int_value("uart", device_get_unit(sc->sc_dev), "flags",
392248843Sadrian	    &ivar)) {
393248843Sadrian		if (UART_FLAGS_FCR_RX_LOW(ivar))
394248843Sadrian			ns8250->fcr |= FCR_RX_LOW;
395248843Sadrian		else if (UART_FLAGS_FCR_RX_MEDL(ivar))
396248843Sadrian			ns8250->fcr |= FCR_RX_MEDL;
397248843Sadrian		else if (UART_FLAGS_FCR_RX_HIGH(ivar))
398248843Sadrian			ns8250->fcr |= FCR_RX_HIGH;
399248843Sadrian		else
400248843Sadrian			ns8250->fcr |= FCR_RX_MEDH;
401248843Sadrian	} else
402248843Sadrian		ns8250->fcr |= FCR_RX_MEDH;
403248843Sadrian
404248843Sadrian	/* Get IER mask */
405248843Sadrian	ivar = 0xf0;
406248843Sadrian	resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_mask",
407248843Sadrian	    &ivar);
408248843Sadrian	ns8250->ier_mask = (uint8_t)(ivar & 0xff);
409248843Sadrian
410248843Sadrian	/* Get IER RX interrupt bits */
411248843Sadrian	ivar = IER_EMSC | IER_ERLS | IER_ERXRDY;
412248843Sadrian	resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_rxbits",
413248843Sadrian	    &ivar);
414248843Sadrian	ns8250->ier_rxbits = (uint8_t)(ivar & 0xff);
415248843Sadrian
416248843Sadrian	uart_setreg(bas, REG_FCR, ns8250->fcr);
417248843Sadrian	uart_barrier(bas);
418248843Sadrian	ar933x_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
419248843Sadrian
420248843Sadrian	if (ns8250->mcr & MCR_DTR)
421248843Sadrian		sc->sc_hwsig |= SER_DTR;
422248843Sadrian	if (ns8250->mcr & MCR_RTS)
423248843Sadrian		sc->sc_hwsig |= SER_RTS;
424248843Sadrian	ar933x_bus_getsig(sc);
425248843Sadrian
426248843Sadrian	ar933x_clrint(bas);
427248843Sadrian	ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
428248843Sadrian	ns8250->ier |= ns8250->ier_rxbits;
429248843Sadrian	uart_setreg(bas, REG_IER, ns8250->ier);
430248843Sadrian	uart_barrier(bas);
431248843Sadrian#endif
432248843Sadrian	return (0);
433248843Sadrian}
434248843Sadrian
435248843Sadrianstatic int
436248843Sadrianar933x_bus_detach(struct uart_softc *sc)
437248843Sadrian{
438248843Sadrian#if 0
439248843Sadrian	struct ar933x_softc *ns8250;
440248843Sadrian	struct uart_bas *bas;
441248843Sadrian	u_char ier;
442248843Sadrian
443248843Sadrian	ns8250 = (struct ar933x_softc *)sc;
444248843Sadrian	bas = &sc->sc_bas;
445248843Sadrian	ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
446248843Sadrian	uart_setreg(bas, REG_IER, ier);
447248843Sadrian	uart_barrier(bas);
448248843Sadrian	ar933x_clrint(bas);
449248843Sadrian#endif
450248843Sadrian	return (0);
451248843Sadrian}
452248843Sadrian
453248843Sadrianstatic int
454248843Sadrianar933x_bus_flush(struct uart_softc *sc, int what)
455248843Sadrian{
456248843Sadrian#if 0
457248843Sadrian	struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc;
458248843Sadrian	struct uart_bas *bas;
459248843Sadrian	int error;
460248843Sadrian
461248843Sadrian	bas = &sc->sc_bas;
462248843Sadrian	uart_lock(sc->sc_hwmtx);
463248843Sadrian	if (sc->sc_rxfifosz > 1) {
464248843Sadrian		ar933x_flush(bas, what);
465248843Sadrian		uart_setreg(bas, REG_FCR, ns8250->fcr);
466248843Sadrian		uart_barrier(bas);
467248843Sadrian		error = 0;
468248843Sadrian	} else
469248843Sadrian		error = ar933x_drain(bas, what);
470248843Sadrian	uart_unlock(sc->sc_hwmtx);
471248843Sadrian	return (error);
472248843Sadrian#endif
473248843Sadrian	return (ENXIO);
474248843Sadrian}
475248843Sadrian
476248843Sadrianstatic int
477248843Sadrianar933x_bus_getsig(struct uart_softc *sc)
478248843Sadrian{
479248843Sadrian#if 0
480248843Sadrian	uint32_t new, old, sig;
481248843Sadrian	uint8_t msr;
482248843Sadrian
483248843Sadrian	do {
484248843Sadrian		old = sc->sc_hwsig;
485248843Sadrian		sig = old;
486248843Sadrian		uart_lock(sc->sc_hwmtx);
487248843Sadrian		msr = uart_getreg(&sc->sc_bas, REG_MSR);
488248843Sadrian		uart_unlock(sc->sc_hwmtx);
489248843Sadrian		SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR);
490248843Sadrian		SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS);
491248843Sadrian		SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD);
492248843Sadrian		SIGCHG(msr & MSR_RI,  sig, SER_RI,  SER_DRI);
493248843Sadrian		new = sig & ~SER_MASK_DELTA;
494248843Sadrian	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
495248843Sadrian	return (sig);
496248843Sadrian#endif
497248843Sadrian	return (0);
498248843Sadrian}
499248843Sadrian
500248843Sadrianstatic int
501248843Sadrianar933x_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
502248843Sadrian{
503248843Sadrian#if 0
504248843Sadrian	struct uart_bas *bas;
505248843Sadrian	int baudrate, divisor, error;
506248843Sadrian	uint8_t efr, lcr;
507248843Sadrian
508248843Sadrian	bas = &sc->sc_bas;
509248843Sadrian	error = 0;
510248843Sadrian	uart_lock(sc->sc_hwmtx);
511248843Sadrian	switch (request) {
512248843Sadrian	case UART_IOCTL_BREAK:
513248843Sadrian		lcr = uart_getreg(bas, REG_LCR);
514248843Sadrian		if (data)
515248843Sadrian			lcr |= LCR_SBREAK;
516248843Sadrian		else
517248843Sadrian			lcr &= ~LCR_SBREAK;
518248843Sadrian		uart_setreg(bas, REG_LCR, lcr);
519248843Sadrian		uart_barrier(bas);
520248843Sadrian		break;
521248843Sadrian	case UART_IOCTL_IFLOW:
522248843Sadrian		lcr = uart_getreg(bas, REG_LCR);
523248843Sadrian		uart_barrier(bas);
524248843Sadrian		uart_setreg(bas, REG_LCR, 0xbf);
525248843Sadrian		uart_barrier(bas);
526248843Sadrian		efr = uart_getreg(bas, REG_EFR);
527248843Sadrian		if (data)
528248843Sadrian			efr |= EFR_RTS;
529248843Sadrian		else
530248843Sadrian			efr &= ~EFR_RTS;
531248843Sadrian		uart_setreg(bas, REG_EFR, efr);
532248843Sadrian		uart_barrier(bas);
533248843Sadrian		uart_setreg(bas, REG_LCR, lcr);
534248843Sadrian		uart_barrier(bas);
535248843Sadrian		break;
536248843Sadrian	case UART_IOCTL_OFLOW:
537248843Sadrian		lcr = uart_getreg(bas, REG_LCR);
538248843Sadrian		uart_barrier(bas);
539248843Sadrian		uart_setreg(bas, REG_LCR, 0xbf);
540248843Sadrian		uart_barrier(bas);
541248843Sadrian		efr = uart_getreg(bas, REG_EFR);
542248843Sadrian		if (data)
543248843Sadrian			efr |= EFR_CTS;
544248843Sadrian		else
545248843Sadrian			efr &= ~EFR_CTS;
546248843Sadrian		uart_setreg(bas, REG_EFR, efr);
547248843Sadrian		uart_barrier(bas);
548248843Sadrian		uart_setreg(bas, REG_LCR, lcr);
549248843Sadrian		uart_barrier(bas);
550248843Sadrian		break;
551248843Sadrian	case UART_IOCTL_BAUD:
552248843Sadrian		lcr = uart_getreg(bas, REG_LCR);
553248843Sadrian		uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
554248843Sadrian		uart_barrier(bas);
555248843Sadrian		divisor = uart_getreg(bas, REG_DLL) |
556248843Sadrian		    (uart_getreg(bas, REG_DLH) << 8);
557248843Sadrian		uart_barrier(bas);
558248843Sadrian		uart_setreg(bas, REG_LCR, lcr);
559248843Sadrian		uart_barrier(bas);
560248843Sadrian		baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0;
561248843Sadrian		if (baudrate > 0)
562248843Sadrian			*(int*)data = baudrate;
563248843Sadrian		else
564248843Sadrian			error = ENXIO;
565248843Sadrian		break;
566248843Sadrian	default:
567248843Sadrian		error = EINVAL;
568248843Sadrian		break;
569248843Sadrian	}
570248843Sadrian	uart_unlock(sc->sc_hwmtx);
571248843Sadrian	return (error);
572248843Sadrian#endif
573248843Sadrian	return (ENXIO);
574248843Sadrian}
575248843Sadrian
576248843Sadrianstatic int
577248843Sadrianar933x_bus_ipend(struct uart_softc *sc)
578248843Sadrian{
579248843Sadrian#if 0
580248843Sadrian	struct uart_bas *bas;
581248843Sadrian	struct ar933x_softc *ns8250;
582248843Sadrian	int ipend;
583248843Sadrian	uint8_t iir, lsr;
584248843Sadrian
585248843Sadrian	ns8250 = (struct ar933x_softc *)sc;
586248843Sadrian	bas = &sc->sc_bas;
587248843Sadrian	uart_lock(sc->sc_hwmtx);
588248843Sadrian	iir = uart_getreg(bas, REG_IIR);
589248843Sadrian	if (iir & IIR_NOPEND) {
590248843Sadrian		uart_unlock(sc->sc_hwmtx);
591248843Sadrian		return (0);
592248843Sadrian	}
593248843Sadrian	ipend = 0;
594248843Sadrian	if (iir & IIR_RXRDY) {
595248843Sadrian		lsr = uart_getreg(bas, REG_LSR);
596248843Sadrian		if (lsr & LSR_OE)
597248843Sadrian			ipend |= SER_INT_OVERRUN;
598248843Sadrian		if (lsr & LSR_BI)
599248843Sadrian			ipend |= SER_INT_BREAK;
600248843Sadrian		if (lsr & LSR_RXRDY)
601248843Sadrian			ipend |= SER_INT_RXREADY;
602248843Sadrian	} else {
603248843Sadrian		if (iir & IIR_TXRDY) {
604248843Sadrian			ipend |= SER_INT_TXIDLE;
605248843Sadrian			uart_setreg(bas, REG_IER, ns8250->ier);
606248843Sadrian		} else
607248843Sadrian			ipend |= SER_INT_SIGCHG;
608248843Sadrian	}
609248843Sadrian	if (ipend == 0)
610248843Sadrian		ar933x_clrint(bas);
611248843Sadrian	uart_unlock(sc->sc_hwmtx);
612248843Sadrian	return (ipend);
613248843Sadrian#endif
614248843Sadrian	return (0);
615248843Sadrian}
616248843Sadrian
617248843Sadrianstatic int
618248843Sadrianar933x_bus_param(struct uart_softc *sc, int baudrate, int databits,
619248843Sadrian    int stopbits, int parity)
620248843Sadrian{
621248843Sadrian#if 0
622248843Sadrian	struct uart_bas *bas;
623248843Sadrian	int error;
624248843Sadrian
625248843Sadrian	bas = &sc->sc_bas;
626248843Sadrian	uart_lock(sc->sc_hwmtx);
627248843Sadrian	error = ar933x_param(bas, baudrate, databits, stopbits, parity);
628248843Sadrian	uart_unlock(sc->sc_hwmtx);
629248843Sadrian	return (error);
630248843Sadrian#endif
631248843Sadrian	return (ENXIO);
632248843Sadrian}
633248843Sadrian
634248843Sadrianstatic int
635248843Sadrianar933x_bus_probe(struct uart_softc *sc)
636248843Sadrian{
637248843Sadrian#if 0
638248843Sadrian	struct ar933x_softc *ns8250;
639248843Sadrian	struct uart_bas *bas;
640248843Sadrian	int count, delay, error, limit;
641248843Sadrian	uint8_t lsr, mcr, ier;
642248843Sadrian
643248843Sadrian	ns8250 = (struct ar933x_softc *)sc;
644248843Sadrian	bas = &sc->sc_bas;
645248843Sadrian
646248843Sadrian	error = ar933x_probe(bas);
647248843Sadrian	if (error)
648248843Sadrian		return (error);
649248843Sadrian
650248843Sadrian	mcr = MCR_IE;
651248843Sadrian	if (sc->sc_sysdev == NULL) {
652248843Sadrian		/* By using ar933x_init() we also set DTR and RTS. */
653248843Sadrian		ar933x_init(bas, 115200, 8, 1, UART_PARITY_NONE);
654248843Sadrian	} else
655248843Sadrian		mcr |= MCR_DTR | MCR_RTS;
656248843Sadrian
657248843Sadrian	error = ar933x_drain(bas, UART_DRAIN_TRANSMITTER);
658248843Sadrian	if (error)
659248843Sadrian		return (error);
660248843Sadrian
661248843Sadrian	/*
662248843Sadrian	 * Set loopback mode. This avoids having garbage on the wire and
663248843Sadrian	 * also allows us send and receive data. We set DTR and RTS to
664248843Sadrian	 * avoid the possibility that automatic flow-control prevents
665248843Sadrian	 * any data from being sent.
666248843Sadrian	 */
667248843Sadrian	uart_setreg(bas, REG_MCR, MCR_LOOPBACK | MCR_IE | MCR_DTR | MCR_RTS);
668248843Sadrian	uart_barrier(bas);
669248843Sadrian
670248843Sadrian	/*
671248843Sadrian	 * Enable FIFOs. And check that the UART has them. If not, we're
672248843Sadrian	 * done. Since this is the first time we enable the FIFOs, we reset
673248843Sadrian	 * them.
674248843Sadrian	 */
675248843Sadrian	uart_setreg(bas, REG_FCR, FCR_ENABLE);
676248843Sadrian	uart_barrier(bas);
677248843Sadrian	if (!(uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK)) {
678248843Sadrian		/*
679248843Sadrian		 * NS16450 or INS8250. We don't bother to differentiate
680248843Sadrian		 * between them. They're too old to be interesting.
681248843Sadrian		 */
682248843Sadrian		uart_setreg(bas, REG_MCR, mcr);
683248843Sadrian		uart_barrier(bas);
684248843Sadrian		sc->sc_rxfifosz = sc->sc_txfifosz = 1;
685248843Sadrian		device_set_desc(sc->sc_dev, "8250 or 16450 or compatible");
686248843Sadrian		return (0);
687248843Sadrian	}
688248843Sadrian
689248843Sadrian	uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST);
690248843Sadrian	uart_barrier(bas);
691248843Sadrian
692248843Sadrian	count = 0;
693248843Sadrian	delay = ar933x_delay(bas);
694248843Sadrian
695248843Sadrian	/* We have FIFOs. Drain the transmitter and receiver. */
696248843Sadrian	error = ar933x_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER);
697248843Sadrian	if (error) {
698248843Sadrian		uart_setreg(bas, REG_MCR, mcr);
699248843Sadrian		uart_setreg(bas, REG_FCR, 0);
700248843Sadrian		uart_barrier(bas);
701248843Sadrian		goto describe;
702248843Sadrian	}
703248843Sadrian
704248843Sadrian	/*
705248843Sadrian	 * We should have a sufficiently clean "pipe" to determine the
706248843Sadrian	 * size of the FIFOs. We send as much characters as is reasonable
707248843Sadrian	 * and wait for the overflow bit in the LSR register to be
708248843Sadrian	 * asserted, counting the characters as we send them. Based on
709248843Sadrian	 * that count we know the FIFO size.
710248843Sadrian	 */
711248843Sadrian	do {
712248843Sadrian		uart_setreg(bas, REG_DATA, 0);
713248843Sadrian		uart_barrier(bas);
714248843Sadrian		count++;
715248843Sadrian
716248843Sadrian		limit = 30;
717248843Sadrian		lsr = 0;
718248843Sadrian		/*
719248843Sadrian		 * LSR bits are cleared upon read, so we must accumulate
720248843Sadrian		 * them to be able to test LSR_OE below.
721248843Sadrian		 */
722248843Sadrian		while (((lsr |= uart_getreg(bas, REG_LSR)) & LSR_TEMT) == 0 &&
723248843Sadrian		    --limit)
724248843Sadrian			DELAY(delay);
725248843Sadrian		if (limit == 0) {
726248843Sadrian			ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
727248843Sadrian			uart_setreg(bas, REG_IER, ier);
728248843Sadrian			uart_setreg(bas, REG_MCR, mcr);
729248843Sadrian			uart_setreg(bas, REG_FCR, 0);
730248843Sadrian			uart_barrier(bas);
731248843Sadrian			count = 0;
732248843Sadrian			goto describe;
733248843Sadrian		}
734248843Sadrian	} while ((lsr & LSR_OE) == 0 && count < 130);
735248843Sadrian	count--;
736248843Sadrian
737248843Sadrian	uart_setreg(bas, REG_MCR, mcr);
738248843Sadrian
739248843Sadrian	/* Reset FIFOs. */
740248843Sadrian	ar933x_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
741248843Sadrian
742248843Sadrian describe:
743248843Sadrian	if (count >= 14 && count <= 16) {
744248843Sadrian		sc->sc_rxfifosz = 16;
745248843Sadrian		device_set_desc(sc->sc_dev, "16550 or compatible");
746248843Sadrian	} else if (count >= 28 && count <= 32) {
747248843Sadrian		sc->sc_rxfifosz = 32;
748248843Sadrian		device_set_desc(sc->sc_dev, "16650 or compatible");
749248843Sadrian	} else if (count >= 56 && count <= 64) {
750248843Sadrian		sc->sc_rxfifosz = 64;
751248843Sadrian		device_set_desc(sc->sc_dev, "16750 or compatible");
752248843Sadrian	} else if (count >= 112 && count <= 128) {
753248843Sadrian		sc->sc_rxfifosz = 128;
754248843Sadrian		device_set_desc(sc->sc_dev, "16950 or compatible");
755248843Sadrian	} else {
756248843Sadrian		sc->sc_rxfifosz = 16;
757248843Sadrian		device_set_desc(sc->sc_dev,
758248843Sadrian		    "Non-standard ns8250 class UART with FIFOs");
759248843Sadrian	}
760248843Sadrian
761248843Sadrian	/*
762248843Sadrian	 * Force the Tx FIFO size to 16 bytes for now. We don't program the
763248843Sadrian	 * Tx trigger. Also, we assume that all data has been sent when the
764248843Sadrian	 * interrupt happens.
765248843Sadrian	 */
766248843Sadrian	sc->sc_txfifosz = 16;
767248843Sadrian
768248843Sadrian#if 0
769248843Sadrian	/*
770248843Sadrian	 * XXX there are some issues related to hardware flow control and
771248843Sadrian	 * it's likely that uart(4) is the cause. This basicly needs more
772248843Sadrian	 * investigation, but we avoid using for hardware flow control
773248843Sadrian	 * until then.
774248843Sadrian	 */
775248843Sadrian	/* 16650s or higher have automatic flow control. */
776248843Sadrian	if (sc->sc_rxfifosz > 16) {
777248843Sadrian		sc->sc_hwiflow = 1;
778248843Sadrian		sc->sc_hwoflow = 1;
779248843Sadrian	}
780248843Sadrian#endif
781248843Sadrian#endif
782248843Sadrian	return (0);
783248843Sadrian}
784248843Sadrian
785248843Sadrianstatic int
786248843Sadrianar933x_bus_receive(struct uart_softc *sc)
787248843Sadrian{
788248843Sadrian#if 0
789248843Sadrian	struct uart_bas *bas;
790248843Sadrian	int xc;
791248843Sadrian	uint8_t lsr;
792248843Sadrian
793248843Sadrian	bas = &sc->sc_bas;
794248843Sadrian	uart_lock(sc->sc_hwmtx);
795248843Sadrian	lsr = uart_getreg(bas, REG_LSR);
796248843Sadrian	while (lsr & LSR_RXRDY) {
797248843Sadrian		if (uart_rx_full(sc)) {
798248843Sadrian			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
799248843Sadrian			break;
800248843Sadrian		}
801248843Sadrian		xc = uart_getreg(bas, REG_DATA);
802248843Sadrian		if (lsr & LSR_FE)
803248843Sadrian			xc |= UART_STAT_FRAMERR;
804248843Sadrian		if (lsr & LSR_PE)
805248843Sadrian			xc |= UART_STAT_PARERR;
806248843Sadrian		uart_rx_put(sc, xc);
807248843Sadrian		lsr = uart_getreg(bas, REG_LSR);
808248843Sadrian	}
809248843Sadrian	/* Discard everything left in the Rx FIFO. */
810248843Sadrian	while (lsr & LSR_RXRDY) {
811248843Sadrian		(void)uart_getreg(bas, REG_DATA);
812248843Sadrian		uart_barrier(bas);
813248843Sadrian		lsr = uart_getreg(bas, REG_LSR);
814248843Sadrian	}
815248843Sadrian	uart_unlock(sc->sc_hwmtx);
816248843Sadrian#endif
817248843Sadrian	return (0);
818248843Sadrian}
819248843Sadrian
820248843Sadrianstatic int
821248843Sadrianar933x_bus_setsig(struct uart_softc *sc, int sig)
822248843Sadrian{
823248843Sadrian#if 0
824248843Sadrian	struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc;
825248843Sadrian	struct uart_bas *bas;
826248843Sadrian	uint32_t new, old;
827248843Sadrian
828248843Sadrian	bas = &sc->sc_bas;
829248843Sadrian	do {
830248843Sadrian		old = sc->sc_hwsig;
831248843Sadrian		new = old;
832248843Sadrian		if (sig & SER_DDTR) {
833248843Sadrian			SIGCHG(sig & SER_DTR, new, SER_DTR,
834248843Sadrian			    SER_DDTR);
835248843Sadrian		}
836248843Sadrian		if (sig & SER_DRTS) {
837248843Sadrian			SIGCHG(sig & SER_RTS, new, SER_RTS,
838248843Sadrian			    SER_DRTS);
839248843Sadrian		}
840248843Sadrian	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
841248843Sadrian	uart_lock(sc->sc_hwmtx);
842248843Sadrian	ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
843248843Sadrian	if (new & SER_DTR)
844248843Sadrian		ns8250->mcr |= MCR_DTR;
845248843Sadrian	if (new & SER_RTS)
846248843Sadrian		ns8250->mcr |= MCR_RTS;
847248843Sadrian	uart_setreg(bas, REG_MCR, ns8250->mcr);
848248843Sadrian	uart_barrier(bas);
849248843Sadrian	uart_unlock(sc->sc_hwmtx);
850248843Sadrian#endif
851248843Sadrian	return (0);
852248843Sadrian}
853248843Sadrian
854248843Sadrianstatic int
855248843Sadrianar933x_bus_transmit(struct uart_softc *sc)
856248843Sadrian{
857248843Sadrian#if 0
858248843Sadrian	struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc;
859248843Sadrian	struct uart_bas *bas;
860248843Sadrian	int i;
861248843Sadrian
862248843Sadrian	bas = &sc->sc_bas;
863248843Sadrian	uart_lock(sc->sc_hwmtx);
864248843Sadrian	while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
865248843Sadrian		;
866248843Sadrian	uart_setreg(bas, REG_IER, ns8250->ier | IER_ETXRDY);
867248843Sadrian	uart_barrier(bas);
868248843Sadrian	for (i = 0; i < sc->sc_txdatasz; i++) {
869248843Sadrian		uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
870248843Sadrian		uart_barrier(bas);
871248843Sadrian	}
872248843Sadrian	sc->sc_txbusy = 1;
873248843Sadrian	uart_unlock(sc->sc_hwmtx);
874248843Sadrian#endif
875248843Sadrian	return (0);
876248843Sadrian}
877