1194150Simp/*-
2194150Simp * Copyright (c) 2003 Marcel Moolenaar
3194150Simp * All rights reserved.
4194150Simp *
5194150Simp * Redistribution and use in source and binary forms, with or without
6194150Simp * modification, are permitted provided that the following conditions
7194150Simp * are met:
8194150Simp *
9194150Simp * 1. Redistributions of source code must retain the above copyright
10194150Simp *    notice, this list of conditions and the following disclaimer.
11194150Simp * 2. Redistributions in binary form must reproduce the above copyright
12194150Simp *    notice, this list of conditions and the following disclaimer in the
13194150Simp *    documentation and/or other materials provided with the distribution.
14194150Simp *
15194150Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16194150Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17194150Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18194150Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19194150Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20194150Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21194150Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22194150Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23194150Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24194150Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25194150Simp */
26194150Simp
27194150Simp/*
28194150Simp * uart_dev_oct16550.c
29194150Simp *
30194150Simp * Derived from uart_dev_ns8250.c
31194150Simp *
32194150Simp * Redistribution and use in source and binary forms, with or without
33194150Simp * modification, are permitted provided that the following conditions
34194150Simp * are met:
35194150Simp *
36194150Simp * 1. Redistributions of source code must retain the above copyright
37194150Simp *    notice, this list of conditions and the following disclaimer.
38194150Simp * 2. Redistributions in binary form must reproduce the above copyright
39194150Simp *    notice, this list of conditions and the following disclaimer in the
40194150Simp *    documentation and/or other materials provided with the distribution.
41194150Simp *
42194150Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43194150Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44194150Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45194150Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46194150Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47194150Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48194150Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49194150Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50194150Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51194150Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52194150Simp *
53194150Simp *
54194150Simp */
55194150Simp
56194150Simp
57194150Simp#include <sys/cdefs.h>
58194150Simp__FBSDID("$FreeBSD$");
59194150Simp
60194150Simp#include <sys/param.h>
61194150Simp#include <sys/systm.h>
62194150Simp#include <sys/bus.h>
63194150Simp#include <sys/conf.h>
64194150Simp#include <machine/bus.h>
65194150Simp#include <machine/pcpu.h>
66194150Simp
67194150Simp#include <dev/uart/uart.h>
68194150Simp#include <dev/uart/uart_cpu.h>
69194150Simp#include <dev/uart/uart_bus.h>
70194150Simp
71194150Simp#include <dev/ic/ns16550.h>
72194150Simp
73202063Simp#include <mips/cavium/octeon_pcmap_regs.h>
74194150Simp
75210311Sjmallett#include <contrib/octeon-sdk/cvmx.h>
76210311Sjmallett
77194150Simp#include "uart_if.h"
78194150Simp
79194150Simp/*
80194150Simp * Clear pending interrupts. THRE is cleared by reading IIR. Data
81194150Simp * that may have been received gets lost here.
82194150Simp */
83194150Simpstatic void
84194150Simpoct16550_clrint (struct uart_bas *bas)
85194150Simp{
86194150Simp	uint8_t iir;
87194150Simp
88194150Simp	iir = uart_getreg(bas, REG_IIR);
89194150Simp	while ((iir & IIR_NOPEND) == 0) {
90194150Simp		iir &= IIR_IMASK;
91194150Simp		if (iir == IIR_RLS)
92194150Simp			(void)uart_getreg(bas, REG_LSR);
93194150Simp		else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
94194150Simp			(void)uart_getreg(bas, REG_DATA);
95194150Simp		else if (iir == IIR_MLSC)
96194150Simp			(void)uart_getreg(bas, REG_MSR);
97194150Simp                else if (iir == IIR_BUSY)
98194150Simp                    	(void) uart_getreg(bas, REG_USR);
99194150Simp		uart_barrier(bas);
100194150Simp		iir = uart_getreg(bas, REG_IIR);
101194150Simp	}
102194150Simp}
103194150Simp
104194150Simpstatic int delay_changed = 1;
105194150Simp
106194150Simpstatic int
107194150Simpoct16550_delay (struct uart_bas *bas)
108194150Simp{
109194150Simp	int divisor;
110194150Simp	u_char lcr;
111194150Simp        static int delay = 0;
112194150Simp
113194150Simp        if (!delay_changed) return delay;
114194150Simp        delay_changed = 0;
115194150Simp	lcr = uart_getreg(bas, REG_LCR);
116194150Simp	uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
117194150Simp	uart_barrier(bas);
118194150Simp	divisor = uart_getreg(bas, REG_DLL) | (uart_getreg(bas, REG_DLH) << 8);
119194150Simp	uart_barrier(bas);
120194150Simp	uart_setreg(bas, REG_LCR, lcr);
121194150Simp	uart_barrier(bas);
122194150Simp
123194150Simp	if(!bas->rclk)
124194150Simp		return 10; /* return an approx delay value */
125194150Simp
126194150Simp	/* 1/10th the time to transmit 1 character (estimate). */
127194150Simp	if (divisor <= 134)
128194150Simp		return (16000000 * divisor / bas->rclk);
129194150Simp	return (16000 * divisor / (bas->rclk / 1000));
130194150Simp
131194150Simp}
132194150Simp
133194150Simpstatic int
134194150Simpoct16550_divisor (int rclk, int baudrate)
135194150Simp{
136194150Simp	int actual_baud, divisor;
137194150Simp	int error;
138194150Simp
139194150Simp	if (baudrate == 0)
140194150Simp		return (0);
141194150Simp
142194150Simp	divisor = (rclk / (baudrate << 3) + 1) >> 1;
143194150Simp	if (divisor == 0 || divisor >= 65536)
144194150Simp		return (0);
145194150Simp	actual_baud = rclk / (divisor << 4);
146194150Simp
147194150Simp	/* 10 times error in percent: */
148194150Simp	error = ((actual_baud - baudrate) * 2000 / baudrate + 1) >> 1;
149194150Simp
150194150Simp	/* 3.0% maximum error tolerance: */
151194150Simp	if (error < -30 || error > 30)
152194150Simp		return (0);
153194150Simp
154194150Simp	return (divisor);
155194150Simp}
156194150Simp
157194150Simpstatic int
158194150Simpoct16550_drain (struct uart_bas *bas, int what)
159194150Simp{
160194150Simp	int delay, limit;
161194150Simp
162194150Simp	delay = oct16550_delay(bas);
163194150Simp
164194150Simp	if (what & UART_DRAIN_TRANSMITTER) {
165194150Simp		/*
166194150Simp		 * Pick an arbitrary high limit to avoid getting stuck in
167194150Simp		 * an infinite loop when the hardware is broken. Make the
168194150Simp		 * limit high enough to handle large FIFOs.
169194150Simp		 */
170194150Simp		limit = 10*10*10*1024;
171194150Simp		while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
172194150Simp			DELAY(delay);
173194150Simp		if (limit == 0) {
174194150Simp			/* printf("oct16550: transmitter appears stuck... "); */
175194150Simp			return (0);
176194150Simp		}
177194150Simp	}
178194150Simp
179194150Simp	if (what & UART_DRAIN_RECEIVER) {
180194150Simp		/*
181194150Simp		 * Pick an arbitrary high limit to avoid getting stuck in
182194150Simp		 * an infinite loop when the hardware is broken. Make the
183194150Simp		 * limit high enough to handle large FIFOs and integrated
184194150Simp		 * UARTs. The HP rx2600 for example has 3 UARTs on the
185194150Simp		 * management board that tend to get a lot of data send
186194150Simp		 * to it when the UART is first activated.
187194150Simp		 */
188194150Simp		limit=10*4096;
189194150Simp		while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) {
190194150Simp			(void)uart_getreg(bas, REG_DATA);
191194150Simp			uart_barrier(bas);
192194150Simp			DELAY(delay << 2);
193194150Simp		}
194194150Simp		if (limit == 0) {
195194150Simp			/* printf("oct16550: receiver appears broken... "); */
196194150Simp			return (EIO);
197194150Simp		}
198194150Simp	}
199194150Simp
200194150Simp	return (0);
201194150Simp}
202194150Simp
203194150Simp/*
204194150Simp * We can only flush UARTs with FIFOs. UARTs without FIFOs should be
205194150Simp * drained. WARNING: this function clobbers the FIFO setting!
206194150Simp */
207194150Simpstatic void
208194150Simpoct16550_flush (struct uart_bas *bas, int what)
209194150Simp{
210194150Simp	uint8_t fcr;
211194150Simp
212194150Simp	fcr = FCR_ENABLE;
213194150Simp	if (what & UART_FLUSH_TRANSMITTER)
214194150Simp		fcr |= FCR_XMT_RST;
215194150Simp	if (what & UART_FLUSH_RECEIVER)
216194150Simp		fcr |= FCR_RCV_RST;
217194150Simp	uart_setreg(bas, REG_FCR, fcr);
218194150Simp	uart_barrier(bas);
219194150Simp}
220194150Simp
221194150Simpstatic int
222194150Simpoct16550_param (struct uart_bas *bas, int baudrate, int databits, int stopbits,
223194150Simp    int parity)
224194150Simp{
225194150Simp	int divisor;
226194150Simp	uint8_t lcr;
227194150Simp
228194150Simp	lcr = 0;
229194150Simp	if (databits >= 8)
230194150Simp		lcr |= LCR_8BITS;
231194150Simp	else if (databits == 7)
232194150Simp		lcr |= LCR_7BITS;
233194150Simp	else if (databits == 6)
234194150Simp		lcr |= LCR_6BITS;
235194150Simp	else
236194150Simp		lcr |= LCR_5BITS;
237194150Simp	if (stopbits > 1)
238194150Simp		lcr |= LCR_STOPB;
239194150Simp	lcr |= parity << 3;
240194150Simp
241194150Simp	/* Set baudrate. */
242194150Simp	if (baudrate > 0) {
243194150Simp		divisor = oct16550_divisor(bas->rclk, baudrate);
244194150Simp		if (divisor == 0)
245194150Simp			return (EINVAL);
246194150Simp		uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
247194150Simp		uart_barrier(bas);
248194150Simp		uart_setreg(bas, REG_DLL, divisor & 0xff);
249194150Simp		uart_setreg(bas, REG_DLH, (divisor >> 8) & 0xff);
250194150Simp		uart_barrier(bas);
251194150Simp                delay_changed = 1;
252194150Simp	}
253194150Simp
254194150Simp	/* Set LCR and clear DLAB. */
255194150Simp	uart_setreg(bas, REG_LCR, lcr);
256194150Simp	uart_barrier(bas);
257194150Simp	return (0);
258194150Simp}
259194150Simp
260194150Simp/*
261194150Simp * Low-level UART interface.
262194150Simp */
263194150Simpstatic int oct16550_probe(struct uart_bas *bas);
264194150Simpstatic void oct16550_init(struct uart_bas *bas, int, int, int, int);
265194150Simpstatic void oct16550_term(struct uart_bas *bas);
266194150Simpstatic void oct16550_putc(struct uart_bas *bas, int);
267194150Simpstatic int oct16550_rxready(struct uart_bas *bas);
268194150Simpstatic int oct16550_getc(struct uart_bas *bas, struct mtx *);
269194150Simp
270194150Simpstruct uart_ops uart_oct16550_ops = {
271194150Simp	.probe = oct16550_probe,
272194150Simp	.init = oct16550_init,
273194150Simp	.term = oct16550_term,
274194150Simp	.putc = oct16550_putc,
275194150Simp	.rxready = oct16550_rxready,
276194150Simp	.getc = oct16550_getc,
277194150Simp};
278194150Simp
279194150Simpstatic int
280194150Simpoct16550_probe (struct uart_bas *bas)
281194150Simp{
282194150Simp	u_char val;
283194150Simp
284194150Simp	/* Check known 0 bits that don't depend on DLAB. */
285194150Simp	val = uart_getreg(bas, REG_IIR);
286194150Simp	if (val & 0x30)
287194150Simp		return (ENXIO);
288194150Simp	val = uart_getreg(bas, REG_MCR);
289194150Simp	if (val & 0xc0)
290194150Simp		return (ENXIO);
291194150Simp	val = uart_getreg(bas, REG_USR);
292194150Simp        if (val & 0xe0)
293194150Simp            	return (ENXIO);
294194150Simp	return (0);
295194150Simp}
296194150Simp
297194150Simpstatic void
298194150Simpoct16550_init (struct uart_bas *bas, int baudrate, int databits, int stopbits,
299194150Simp    int parity)
300194150Simp{
301194150Simp	u_char	ier;
302194150Simp
303194150Simp	oct16550_param(bas, baudrate, databits, stopbits, parity);
304194150Simp
305194150Simp	/* Disable all interrupt sources. */
306194150Simp	ier = uart_getreg(bas, REG_IER) & 0x0;
307194150Simp	uart_setreg(bas, REG_IER, ier);
308194150Simp	uart_barrier(bas);
309194150Simp
310194150Simp	/* Disable the FIFO (if present). */
311194150Simp//	uart_setreg(bas, REG_FCR, 0);
312194150Simp	uart_barrier(bas);
313194150Simp
314194150Simp	/* Set RTS & DTR. */
315194150Simp	uart_setreg(bas, REG_MCR, MCR_RTS | MCR_DTR);
316194150Simp	uart_barrier(bas);
317194150Simp
318194150Simp	oct16550_clrint(bas);
319194150Simp}
320194150Simp
321194150Simpstatic void
322194150Simpoct16550_term (struct uart_bas *bas)
323194150Simp{
324194150Simp
325194150Simp	/* Clear RTS & DTR. */
326194150Simp	uart_setreg(bas, REG_MCR, 0);
327194150Simp	uart_barrier(bas);
328194150Simp}
329194150Simp
330194150Simpstatic inline void oct16550_wait_txhr_empty (struct uart_bas *bas, int limit, int delay)
331194150Simp{
332194150Simp    while (((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0) &&
333194150Simp           ((uart_getreg(bas, REG_USR) & USR_TXFIFO_NOTFULL) == 0))
334194150Simp        DELAY(delay);
335194150Simp}
336194150Simp
337194150Simpstatic void
338194150Simpoct16550_putc (struct uart_bas *bas, int c)
339194150Simp{
340194150Simp	int delay;
341194150Simp
342194150Simp	/* 1/10th the time to transmit 1 character (estimate). */
343194150Simp	delay = oct16550_delay(bas);
344194150Simp        oct16550_wait_txhr_empty(bas, 100, delay);
345194150Simp	uart_setreg(bas, REG_DATA, c);
346194150Simp	uart_barrier(bas);
347194150Simp        oct16550_wait_txhr_empty(bas, 100, delay);
348194150Simp}
349194150Simp
350194150Simpstatic int
351194150Simpoct16550_rxready (struct uart_bas *bas)
352194150Simp{
353194150Simp
354194150Simp	return ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) != 0 ? 1 : 0);
355194150Simp}
356194150Simp
357194150Simpstatic int
358194150Simpoct16550_getc (struct uart_bas *bas, struct mtx *hwmtx)
359194150Simp{
360194150Simp	int c, delay;
361194150Simp
362194150Simp	uart_lock(hwmtx);
363194150Simp
364194150Simp	/* 1/10th the time to transmit 1 character (estimate). */
365194150Simp	delay = oct16550_delay(bas);
366194150Simp
367194150Simp	while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) {
368194150Simp		uart_unlock(hwmtx);
369194150Simp		DELAY(delay);
370194150Simp		uart_lock(hwmtx);
371194150Simp	}
372194150Simp
373194150Simp	c = uart_getreg(bas, REG_DATA);
374194150Simp
375194150Simp	uart_unlock(hwmtx);
376194150Simp
377194150Simp	return (c);
378194150Simp}
379194150Simp
380194150Simp/*
381194150Simp * High-level UART interface.
382194150Simp */
383194150Simpstruct oct16550_softc {
384194150Simp	struct uart_softc base;
385194150Simp	uint8_t		fcr;
386194150Simp	uint8_t		ier;
387194150Simp	uint8_t		mcr;
388194150Simp};
389194150Simp
390194150Simpstatic int oct16550_bus_attach(struct uart_softc *);
391194150Simpstatic int oct16550_bus_detach(struct uart_softc *);
392194150Simpstatic int oct16550_bus_flush(struct uart_softc *, int);
393194150Simpstatic int oct16550_bus_getsig(struct uart_softc *);
394194150Simpstatic int oct16550_bus_ioctl(struct uart_softc *, int, intptr_t);
395194150Simpstatic int oct16550_bus_ipend(struct uart_softc *);
396194150Simpstatic int oct16550_bus_param(struct uart_softc *, int, int, int, int);
397194150Simpstatic int oct16550_bus_probe(struct uart_softc *);
398194150Simpstatic int oct16550_bus_receive(struct uart_softc *);
399194150Simpstatic int oct16550_bus_setsig(struct uart_softc *, int);
400194150Simpstatic int oct16550_bus_transmit(struct uart_softc *);
401194150Simp
402194150Simpstatic kobj_method_t oct16550_methods[] = {
403194150Simp	KOBJMETHOD(uart_attach,		oct16550_bus_attach),
404194150Simp	KOBJMETHOD(uart_detach,		oct16550_bus_detach),
405194150Simp	KOBJMETHOD(uart_flush,		oct16550_bus_flush),
406194150Simp	KOBJMETHOD(uart_getsig,		oct16550_bus_getsig),
407194150Simp	KOBJMETHOD(uart_ioctl,		oct16550_bus_ioctl),
408194150Simp	KOBJMETHOD(uart_ipend,		oct16550_bus_ipend),
409194150Simp	KOBJMETHOD(uart_param,		oct16550_bus_param),
410194150Simp	KOBJMETHOD(uart_probe,		oct16550_bus_probe),
411194150Simp	KOBJMETHOD(uart_receive,	oct16550_bus_receive),
412194150Simp	KOBJMETHOD(uart_setsig,		oct16550_bus_setsig),
413194150Simp	KOBJMETHOD(uart_transmit,	oct16550_bus_transmit),
414194150Simp	{ 0, 0 }
415194150Simp};
416194150Simp
417194150Simpstruct uart_class uart_oct16550_class = {
418194150Simp	"oct16550 class",
419194150Simp	oct16550_methods,
420194150Simp	sizeof(struct oct16550_softc),
421194150Simp	.uc_ops = &uart_oct16550_ops,
422213345Sjmallett	.uc_range = 8 << 3,
423194150Simp	.uc_rclk = 0
424194150Simp};
425194150Simp
426194150Simp#define	SIGCHG(c, i, s, d)				\
427194150Simp	if (c) {					\
428194150Simp		i |= (i & s) ? s : s | d;		\
429194150Simp	} else {					\
430194150Simp		i = (i & s) ? (i & ~s) | d : i;		\
431194150Simp	}
432194150Simp
433194150Simpstatic int
434194150Simpoct16550_bus_attach (struct uart_softc *sc)
435194150Simp{
436194150Simp	struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
437194150Simp	struct uart_bas *bas;
438194150Simp        int unit;
439194150Simp
440194150Simp        unit = device_get_unit(sc->sc_dev);
441194150Simp	bas = &sc->sc_bas;
442194150Simp
443194150Simp        oct16550_drain(bas, UART_DRAIN_TRANSMITTER);
444194150Simp	oct16550->mcr = uart_getreg(bas, REG_MCR);
445194150Simp	oct16550->fcr = FCR_ENABLE | FCR_RX_HIGH;
446194150Simp	uart_setreg(bas, REG_FCR, oct16550->fcr);
447194150Simp	uart_barrier(bas);
448194150Simp	oct16550_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
449194150Simp
450194150Simp	if (oct16550->mcr & MCR_DTR)
451194150Simp		sc->sc_hwsig |= SER_DTR;
452194150Simp	if (oct16550->mcr & MCR_RTS)
453194150Simp		sc->sc_hwsig |= SER_RTS;
454194150Simp	oct16550_bus_getsig(sc);
455194150Simp
456194150Simp	oct16550_clrint(bas);
457194150Simp	oct16550->ier = uart_getreg(bas, REG_IER) & 0xf0;
458194150Simp	oct16550->ier |= IER_EMSC | IER_ERLS | IER_ERXRDY;
459194150Simp	uart_setreg(bas, REG_IER, oct16550->ier);
460194150Simp	uart_barrier(bas);
461194150Simp
462194150Simp	return (0);
463194150Simp}
464194150Simp
465194150Simpstatic int
466194150Simpoct16550_bus_detach (struct uart_softc *sc)
467194150Simp{
468194150Simp	struct uart_bas *bas;
469194150Simp	u_char ier;
470194150Simp
471194150Simp	bas = &sc->sc_bas;
472194150Simp	ier = uart_getreg(bas, REG_IER) & 0xf0;
473194150Simp	uart_setreg(bas, REG_IER, ier);
474194150Simp	uart_barrier(bas);
475194150Simp	oct16550_clrint(bas);
476194150Simp	return (0);
477194150Simp}
478194150Simp
479194150Simpstatic int
480194150Simpoct16550_bus_flush (struct uart_softc *sc, int what)
481194150Simp{
482194150Simp	struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
483194150Simp	struct uart_bas *bas;
484194150Simp	int error;
485194150Simp
486194150Simp	bas = &sc->sc_bas;
487194150Simp	uart_lock(sc->sc_hwmtx);
488194150Simp	if (sc->sc_rxfifosz > 1) {
489194150Simp		oct16550_flush(bas, what);
490194150Simp		uart_setreg(bas, REG_FCR, oct16550->fcr);
491194150Simp		uart_barrier(bas);
492194150Simp		error = 0;
493194150Simp	} else
494194150Simp		error = oct16550_drain(bas, what);
495194150Simp	uart_unlock(sc->sc_hwmtx);
496194150Simp	return (error);
497194150Simp}
498194150Simp
499194150Simpstatic int
500194150Simpoct16550_bus_getsig (struct uart_softc *sc)
501194150Simp{
502194150Simp	uint32_t new, old, sig;
503194150Simp	uint8_t msr;
504194150Simp
505194150Simp	do {
506194150Simp		old = sc->sc_hwsig;
507194150Simp		sig = old;
508194150Simp		uart_lock(sc->sc_hwmtx);
509194150Simp		msr = uart_getreg(&sc->sc_bas, REG_MSR);
510194150Simp		uart_unlock(sc->sc_hwmtx);
511194150Simp		SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR);
512194150Simp		SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS);
513194150Simp		SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD);
514194150Simp		SIGCHG(msr & MSR_RI,  sig, SER_RI,  SER_DRI);
515194150Simp		new = sig & ~SER_MASK_DELTA;
516194150Simp	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
517194150Simp	return (sig);
518194150Simp}
519194150Simp
520194150Simpstatic int
521194150Simpoct16550_bus_ioctl (struct uart_softc *sc, int request, intptr_t data)
522194150Simp{
523194150Simp	struct uart_bas *bas;
524194150Simp	int baudrate, divisor, error;
525194150Simp	uint8_t efr, lcr;
526194150Simp
527194150Simp	bas = &sc->sc_bas;
528194150Simp	error = 0;
529194150Simp	uart_lock(sc->sc_hwmtx);
530194150Simp	switch (request) {
531194150Simp	case UART_IOCTL_BREAK:
532194150Simp		lcr = uart_getreg(bas, REG_LCR);
533194150Simp		if (data)
534194150Simp			lcr |= LCR_SBREAK;
535194150Simp		else
536194150Simp			lcr &= ~LCR_SBREAK;
537194150Simp		uart_setreg(bas, REG_LCR, lcr);
538194150Simp		uart_barrier(bas);
539194150Simp		break;
540194150Simp	case UART_IOCTL_IFLOW:
541194150Simp		lcr = uart_getreg(bas, REG_LCR);
542194150Simp		uart_barrier(bas);
543194150Simp		uart_setreg(bas, REG_LCR, 0xbf);
544194150Simp		uart_barrier(bas);
545194150Simp		efr = uart_getreg(bas, REG_EFR);
546194150Simp		if (data)
547194150Simp			efr |= EFR_RTS;
548194150Simp		else
549194150Simp			efr &= ~EFR_RTS;
550194150Simp		uart_setreg(bas, REG_EFR, efr);
551194150Simp		uart_barrier(bas);
552194150Simp		uart_setreg(bas, REG_LCR, lcr);
553194150Simp		uart_barrier(bas);
554194150Simp		break;
555194150Simp	case UART_IOCTL_OFLOW:
556194150Simp		lcr = uart_getreg(bas, REG_LCR);
557194150Simp		uart_barrier(bas);
558194150Simp		uart_setreg(bas, REG_LCR, 0xbf);
559194150Simp		uart_barrier(bas);
560194150Simp		efr = uart_getreg(bas, REG_EFR);
561194150Simp		if (data)
562194150Simp			efr |= EFR_CTS;
563194150Simp		else
564194150Simp			efr &= ~EFR_CTS;
565194150Simp		uart_setreg(bas, REG_EFR, efr);
566194150Simp		uart_barrier(bas);
567194150Simp		uart_setreg(bas, REG_LCR, lcr);
568194150Simp		uart_barrier(bas);
569194150Simp		break;
570194150Simp	case UART_IOCTL_BAUD:
571194150Simp		lcr = uart_getreg(bas, REG_LCR);
572194150Simp		uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
573194150Simp		uart_barrier(bas);
574194150Simp		divisor = uart_getreg(bas, REG_DLL) |
575194150Simp		    (uart_getreg(bas, REG_DLH) << 8);
576194150Simp		uart_barrier(bas);
577194150Simp		uart_setreg(bas, REG_LCR, lcr);
578194150Simp		uart_barrier(bas);
579194150Simp		baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0;
580194150Simp                delay_changed = 1;
581194150Simp		if (baudrate > 0)
582194150Simp			*(int*)data = baudrate;
583194150Simp		else
584194150Simp			error = ENXIO;
585194150Simp		break;
586194150Simp	default:
587194150Simp		error = EINVAL;
588194150Simp		break;
589194150Simp	}
590194150Simp	uart_unlock(sc->sc_hwmtx);
591194150Simp	return (error);
592194150Simp}
593194150Simp
594194150Simp
595194150Simpstatic int
596194150Simpoct16550_bus_ipend(struct uart_softc *sc)
597194150Simp{
598194150Simp	struct uart_bas *bas;
599194150Simp	int ipend = 0;
600194150Simp	uint8_t iir, lsr;
601194150Simp
602194150Simp	bas = &sc->sc_bas;
603194150Simp	uart_lock(sc->sc_hwmtx);
604194150Simp
605194150Simp	iir = uart_getreg(bas, REG_IIR) & IIR_IMASK;
606194150Simp	if (iir != IIR_NOPEND) {
607194150Simp
608194150Simp            	if (iir == IIR_RLS) {
609194150Simp                    	lsr = uart_getreg(bas, REG_LSR);
610194150Simp                        if (lsr & LSR_OE)
611194150Simp                            	ipend |= SER_INT_OVERRUN;
612194150Simp                        if (lsr & LSR_BI)
613194150Simp                            	ipend |= SER_INT_BREAK;
614194150Simp                        if (lsr & LSR_RXRDY)
615194150Simp                    		ipend |= SER_INT_RXREADY;
616194150Simp
617194150Simp                } else if (iir == IIR_RXRDY) {
618194150Simp                    	ipend |= SER_INT_RXREADY;
619194150Simp
620194150Simp                } else if (iir == IIR_RXTOUT) {
621194150Simp                    	ipend |= SER_INT_RXREADY;
622194150Simp
623194150Simp                } else if (iir == IIR_TXRDY) {
624194150Simp                    	ipend |= SER_INT_TXIDLE;
625194150Simp
626194150Simp                } else if (iir == IIR_MLSC) {
627194150Simp                    	ipend |= SER_INT_SIGCHG;
628194150Simp
629194150Simp                } else if (iir == IIR_BUSY) {
630194150Simp                    	(void) uart_getreg(bas, REG_USR);
631194150Simp                }
632194150Simp	}
633194150Simp	uart_unlock(sc->sc_hwmtx);
634194150Simp
635207533Smarius	return (ipend);
636194150Simp}
637194150Simp
638194150Simpstatic int
639194150Simpoct16550_bus_param (struct uart_softc *sc, int baudrate, int databits,
640194150Simp    int stopbits, int parity)
641194150Simp{
642194150Simp	struct uart_bas *bas;
643194150Simp	int error;
644194150Simp
645194150Simp	bas = &sc->sc_bas;
646194150Simp	uart_lock(sc->sc_hwmtx);
647194150Simp	error = oct16550_param(bas, baudrate, databits, stopbits, parity);
648194150Simp	uart_unlock(sc->sc_hwmtx);
649194150Simp	return (error);
650194150Simp}
651194150Simp
652194150Simpstatic int
653194150Simpoct16550_bus_probe (struct uart_softc *sc)
654194150Simp{
655194150Simp	struct uart_bas *bas;
656194150Simp	int error;
657194150Simp
658194150Simp	bas = &sc->sc_bas;
659249919Simp	bas->rclk = uart_oct16550_class.uc_rclk = cvmx_clock_get_rate(CVMX_CLOCK_SCLK);
660194150Simp
661194150Simp	error = oct16550_probe(bas);
662194150Simp	if (error) {
663194150Simp		return (error);
664194150Simp        }
665194150Simp
666194150Simp	uart_setreg(bas, REG_MCR, (MCR_DTR | MCR_RTS));
667194150Simp
668194150Simp	/*
669194150Simp	 * Enable FIFOs. And check that the UART has them. If not, we're
670194150Simp	 * done. Since this is the first time we enable the FIFOs, we reset
671194150Simp	 * them.
672194150Simp	 */
673194150Simp        oct16550_drain(bas, UART_DRAIN_TRANSMITTER);
674194150Simp#define ENABLE_OCTEON_FIFO 1
675194150Simp#ifdef ENABLE_OCTEON_FIFO
676194150Simp	uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST);
677194150Simp#endif
678194150Simp	uart_barrier(bas);
679194150Simp
680194150Simp	oct16550_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
681194150Simp
682194150Simp        if (device_get_unit(sc->sc_dev)) {
683194150Simp            	device_set_desc(sc->sc_dev, "Octeon-16550 channel 1");
684194150Simp        } else {
685194150Simp            	device_set_desc(sc->sc_dev, "Octeon-16550 channel 0");
686194150Simp        }
687194150Simp#ifdef ENABLE_OCTEON_FIFO
688194150Simp	sc->sc_rxfifosz = 64;
689194150Simp	sc->sc_txfifosz = 64;
690194150Simp#else
691194150Simp	sc->sc_rxfifosz = 1;
692194150Simp	sc->sc_txfifosz = 1;
693194150Simp#endif
694194150Simp
695194150Simp
696194150Simp#if 0
697194150Simp	/*
698194150Simp	 * XXX there are some issues related to hardware flow control and
699194150Simp	 * it's likely that uart(4) is the cause. This basicly needs more
700194150Simp	 * investigation, but we avoid using for hardware flow control
701194150Simp	 * until then.
702194150Simp	 */
703194150Simp	/* 16650s or higher have automatic flow control. */
704194150Simp	if (sc->sc_rxfifosz > 16) {
705194150Simp		sc->sc_hwiflow = 1;
706194150Simp		sc->sc_hwoflow = 1;
707194150Simp	}
708194150Simp#endif
709194150Simp
710194150Simp	return (0);
711194150Simp}
712194150Simp
713194150Simpstatic int
714194150Simpoct16550_bus_receive (struct uart_softc *sc)
715194150Simp{
716194150Simp	struct uart_bas *bas;
717194150Simp	int xc;
718194150Simp	uint8_t lsr;
719194150Simp
720194150Simp	bas = &sc->sc_bas;
721194150Simp	uart_lock(sc->sc_hwmtx);
722194150Simp	lsr = uart_getreg(bas, REG_LSR);
723194150Simp
724194150Simp	while (lsr & LSR_RXRDY) {
725194150Simp		if (uart_rx_full(sc)) {
726194150Simp			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
727194150Simp			break;
728194150Simp		}
729194150Simp		xc = uart_getreg(bas, REG_DATA);
730194150Simp		if (lsr & LSR_FE)
731194150Simp			xc |= UART_STAT_FRAMERR;
732194150Simp		if (lsr & LSR_PE)
733194150Simp			xc |= UART_STAT_PARERR;
734194150Simp		uart_rx_put(sc, xc);
735194150Simp		lsr = uart_getreg(bas, REG_LSR);
736194150Simp	}
737194150Simp	/* Discard everything left in the Rx FIFO. */
738194150Simp        /*
739194150Simp         * First do a dummy read/discard anyway, in case the UART was lying to us.
740194150Simp         * This problem was seen on board, when IIR said RBR, but LSR said no RXRDY
741194150Simp         * Results in a stuck ipend loop.
742194150Simp         */
743194150Simp        (void)uart_getreg(bas, REG_DATA);
744194150Simp	while (lsr & LSR_RXRDY) {
745194150Simp		(void)uart_getreg(bas, REG_DATA);
746194150Simp		uart_barrier(bas);
747194150Simp		lsr = uart_getreg(bas, REG_LSR);
748194150Simp	}
749194150Simp	uart_unlock(sc->sc_hwmtx);
750194150Simp 	return (0);
751194150Simp}
752194150Simp
753194150Simpstatic int
754194150Simpoct16550_bus_setsig (struct uart_softc *sc, int sig)
755194150Simp{
756194150Simp	struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
757194150Simp	struct uart_bas *bas;
758194150Simp	uint32_t new, old;
759194150Simp
760194150Simp	bas = &sc->sc_bas;
761194150Simp	do {
762194150Simp		old = sc->sc_hwsig;
763194150Simp		new = old;
764194150Simp		if (sig & SER_DDTR) {
765194150Simp			SIGCHG(sig & SER_DTR, new, SER_DTR,
766194150Simp			    SER_DDTR);
767194150Simp		}
768194150Simp		if (sig & SER_DRTS) {
769194150Simp			SIGCHG(sig & SER_RTS, new, SER_RTS,
770194150Simp			    SER_DRTS);
771194150Simp		}
772194150Simp	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
773194150Simp	uart_lock(sc->sc_hwmtx);
774194150Simp	oct16550->mcr &= ~(MCR_DTR|MCR_RTS);
775194150Simp	if (new & SER_DTR)
776194150Simp		oct16550->mcr |= MCR_DTR;
777194150Simp	if (new & SER_RTS)
778194150Simp		oct16550->mcr |= MCR_RTS;
779194150Simp	uart_setreg(bas, REG_MCR, oct16550->mcr);
780194150Simp	uart_barrier(bas);
781194150Simp	uart_unlock(sc->sc_hwmtx);
782194150Simp	return (0);
783194150Simp}
784194150Simp
785194150Simpstatic int
786194150Simpoct16550_bus_transmit (struct uart_softc *sc)
787194150Simp{
788194150Simp	struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
789194150Simp	struct uart_bas *bas;
790194150Simp	int i;
791194150Simp
792194150Simp	bas = &sc->sc_bas;
793194150Simp	uart_lock(sc->sc_hwmtx);
794194150Simp#ifdef NO_UART_INTERRUPTS
795194150Simp        for (i = 0; i < sc->sc_txdatasz; i++) {
796194150Simp            oct16550_putc(bas, sc->sc_txbuf[i]);
797194150Simp        }
798194150Simp#else
799194150Simp
800194150Simp        oct16550_wait_txhr_empty(bas, 100, oct16550_delay(bas));
801194150Simp	uart_setreg(bas, REG_IER, oct16550->ier | IER_ETXRDY);
802194150Simp	uart_barrier(bas);
803194150Simp
804194150Simp	for (i = 0; i < sc->sc_txdatasz; i++) {
805194150Simp		uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
806194150Simp		uart_barrier(bas);
807194150Simp	}
808194150Simp	sc->sc_txbusy = 1;
809194150Simp#endif
810194150Simp	uart_unlock(sc->sc_hwmtx);
811194150Simp	return (0);
812194150Simp}
813