xref: /freebsd-14.2/sys/dev/uart/uart_dev_quicc.c (revision e1ef7811)
1*e1ef7811SRafal Jaworowski /*-
2*e1ef7811SRafal Jaworowski  * Copyright (c) 2006 Juniper Networks
3*e1ef7811SRafal Jaworowski  * All rights reserved.
4*e1ef7811SRafal Jaworowski  *
5*e1ef7811SRafal Jaworowski  * Redistribution and use in source and binary forms, with or without
6*e1ef7811SRafal Jaworowski  * modification, are permitted provided that the following conditions
7*e1ef7811SRafal Jaworowski  * are met:
8*e1ef7811SRafal Jaworowski  *
9*e1ef7811SRafal Jaworowski  * 1. Redistributions of source code must retain the above copyright
10*e1ef7811SRafal Jaworowski  *    notice, this list of conditions and the following disclaimer.
11*e1ef7811SRafal Jaworowski  * 2. Redistributions in binary form must reproduce the above copyright
12*e1ef7811SRafal Jaworowski  *    notice, this list of conditions and the following disclaimer in the
13*e1ef7811SRafal Jaworowski  *    documentation and/or other materials provided with the distribution.
14*e1ef7811SRafal Jaworowski  *
15*e1ef7811SRafal Jaworowski  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*e1ef7811SRafal Jaworowski  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*e1ef7811SRafal Jaworowski  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*e1ef7811SRafal Jaworowski  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*e1ef7811SRafal Jaworowski  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*e1ef7811SRafal Jaworowski  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*e1ef7811SRafal Jaworowski  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*e1ef7811SRafal Jaworowski  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*e1ef7811SRafal Jaworowski  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*e1ef7811SRafal Jaworowski  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*e1ef7811SRafal Jaworowski  */
26*e1ef7811SRafal Jaworowski 
27*e1ef7811SRafal Jaworowski #include <sys/cdefs.h>
28*e1ef7811SRafal Jaworowski __FBSDID("$FreeBSD$");
29*e1ef7811SRafal Jaworowski 
30*e1ef7811SRafal Jaworowski #include <sys/param.h>
31*e1ef7811SRafal Jaworowski #include <sys/systm.h>
32*e1ef7811SRafal Jaworowski #include <sys/bus.h>
33*e1ef7811SRafal Jaworowski #include <sys/conf.h>
34*e1ef7811SRafal Jaworowski #include <sys/endian.h>
35*e1ef7811SRafal Jaworowski #include <machine/bus.h>
36*e1ef7811SRafal Jaworowski 
37*e1ef7811SRafal Jaworowski #include <dev/ic/quicc.h>
38*e1ef7811SRafal Jaworowski 
39*e1ef7811SRafal Jaworowski #include <dev/uart/uart.h>
40*e1ef7811SRafal Jaworowski #include <dev/uart/uart_cpu.h>
41*e1ef7811SRafal Jaworowski #include <dev/uart/uart_bus.h>
42*e1ef7811SRafal Jaworowski 
43*e1ef7811SRafal Jaworowski #include "uart_if.h"
44*e1ef7811SRafal Jaworowski 
45*e1ef7811SRafal Jaworowski #define	DEFAULT_RCLK	((266000000 * 2) / 16)
46*e1ef7811SRafal Jaworowski 
47*e1ef7811SRafal Jaworowski #define	quicc_read2(bas, reg)		\
48*e1ef7811SRafal Jaworowski 	bus_space_read_2((bas)->bst, (bas)->bsh, reg)
49*e1ef7811SRafal Jaworowski #define	quicc_read4(bas, reg)		\
50*e1ef7811SRafal Jaworowski 	bus_space_read_4((bas)->bst, (bas)->bsh, reg)
51*e1ef7811SRafal Jaworowski 
52*e1ef7811SRafal Jaworowski #define	quicc_write2(bas, reg, val)	\
53*e1ef7811SRafal Jaworowski 	bus_space_write_2((bas)->bst, (bas)->bsh, reg, val)
54*e1ef7811SRafal Jaworowski #define	quicc_write4(bas, reg, val)	\
55*e1ef7811SRafal Jaworowski 	bus_space_write_4((bas)->bst, (bas)->bsh, reg, val)
56*e1ef7811SRafal Jaworowski 
57*e1ef7811SRafal Jaworowski static int
58*e1ef7811SRafal Jaworowski quicc_divisor(int rclk, int baudrate)
59*e1ef7811SRafal Jaworowski {
60*e1ef7811SRafal Jaworowski 	int act_baud, divisor, error;
61*e1ef7811SRafal Jaworowski 
62*e1ef7811SRafal Jaworowski 	if (baudrate == 0)
63*e1ef7811SRafal Jaworowski 		return (-1);
64*e1ef7811SRafal Jaworowski 
65*e1ef7811SRafal Jaworowski 	divisor = rclk / baudrate / 16;
66*e1ef7811SRafal Jaworowski 	if (divisor > 4096)
67*e1ef7811SRafal Jaworowski 		divisor = ((divisor >> 3) - 2) | 1;
68*e1ef7811SRafal Jaworowski 	else if (divisor >= 0)
69*e1ef7811SRafal Jaworowski 		divisor = (divisor - 1) << 1;
70*e1ef7811SRafal Jaworowski 	if (divisor < 0 || divisor >= 8192)
71*e1ef7811SRafal Jaworowski 		return (-1);
72*e1ef7811SRafal Jaworowski 	act_baud = rclk / (((divisor >> 1) + 1) << ((divisor & 1) ? 8 : 4));
73*e1ef7811SRafal Jaworowski 
74*e1ef7811SRafal Jaworowski 	/* 10 times error in percent: */
75*e1ef7811SRafal Jaworowski 	error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1;
76*e1ef7811SRafal Jaworowski 
77*e1ef7811SRafal Jaworowski 	/* 3.0% maximum error tolerance: */
78*e1ef7811SRafal Jaworowski 	if (error < -30 || error > 30)
79*e1ef7811SRafal Jaworowski 		return (-1);
80*e1ef7811SRafal Jaworowski 
81*e1ef7811SRafal Jaworowski 	return (divisor);
82*e1ef7811SRafal Jaworowski }
83*e1ef7811SRafal Jaworowski 
84*e1ef7811SRafal Jaworowski static int
85*e1ef7811SRafal Jaworowski quicc_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
86*e1ef7811SRafal Jaworowski     int parity)
87*e1ef7811SRafal Jaworowski {
88*e1ef7811SRafal Jaworowski 	int divisor;
89*e1ef7811SRafal Jaworowski 	uint16_t psmr;
90*e1ef7811SRafal Jaworowski 
91*e1ef7811SRafal Jaworowski 	if (baudrate > 0) {
92*e1ef7811SRafal Jaworowski 		divisor = quicc_divisor(bas->rclk, baudrate);
93*e1ef7811SRafal Jaworowski 		if (divisor == -1)
94*e1ef7811SRafal Jaworowski 			return (EINVAL);
95*e1ef7811SRafal Jaworowski 		quicc_write4(bas, QUICC_REG_BRG(bas->chan - 1),
96*e1ef7811SRafal Jaworowski 		    divisor | 0x10000);
97*e1ef7811SRafal Jaworowski 	}
98*e1ef7811SRafal Jaworowski 
99*e1ef7811SRafal Jaworowski 	psmr = 0;
100*e1ef7811SRafal Jaworowski 	switch (databits) {
101*e1ef7811SRafal Jaworowski 	case 5:		psmr |= 0x0000; break;
102*e1ef7811SRafal Jaworowski 	case 6:		psmr |= 0x1000; break;
103*e1ef7811SRafal Jaworowski 	case 7:		psmr |= 0x2000; break;
104*e1ef7811SRafal Jaworowski 	case 8:		psmr |= 0x3000; break;
105*e1ef7811SRafal Jaworowski 	default:	return (EINVAL);
106*e1ef7811SRafal Jaworowski 	}
107*e1ef7811SRafal Jaworowski 	switch (stopbits) {
108*e1ef7811SRafal Jaworowski 	case 1:		psmr |= 0x0000; break;
109*e1ef7811SRafal Jaworowski 	case 2:		psmr |= 0x4000; break;
110*e1ef7811SRafal Jaworowski 	default:	return (EINVAL);
111*e1ef7811SRafal Jaworowski 	}
112*e1ef7811SRafal Jaworowski 	switch (parity) {
113*e1ef7811SRafal Jaworowski 	case UART_PARITY_EVEN:	psmr |= 0x1a; break;
114*e1ef7811SRafal Jaworowski 	case UART_PARITY_MARK:	psmr |= 0x1f; break;
115*e1ef7811SRafal Jaworowski 	case UART_PARITY_NONE:	psmr |= 0x00; break;
116*e1ef7811SRafal Jaworowski 	case UART_PARITY_ODD:	psmr |= 0x10; break;
117*e1ef7811SRafal Jaworowski 	case UART_PARITY_SPACE:	psmr |= 0x15; break;
118*e1ef7811SRafal Jaworowski 	default:		return (EINVAL);
119*e1ef7811SRafal Jaworowski 	}
120*e1ef7811SRafal Jaworowski 	quicc_write2(bas, QUICC_REG_SCC_PSMR(bas->chan - 1), psmr);
121*e1ef7811SRafal Jaworowski 	return (0);
122*e1ef7811SRafal Jaworowski }
123*e1ef7811SRafal Jaworowski 
124*e1ef7811SRafal Jaworowski static void
125*e1ef7811SRafal Jaworowski quicc_setup(struct uart_bas *bas, int baudrate, int databits, int stopbits,
126*e1ef7811SRafal Jaworowski     int parity)
127*e1ef7811SRafal Jaworowski {
128*e1ef7811SRafal Jaworowski 
129*e1ef7811SRafal Jaworowski 	if (bas->rclk == 0)
130*e1ef7811SRafal Jaworowski 		bas->rclk = DEFAULT_RCLK;
131*e1ef7811SRafal Jaworowski 
132*e1ef7811SRafal Jaworowski 	/*
133*e1ef7811SRafal Jaworowski 	 * GSMR_L = 0x00028034
134*e1ef7811SRafal Jaworowski 	 * GSMR_H = 0x00000020
135*e1ef7811SRafal Jaworowski 	 */
136*e1ef7811SRafal Jaworowski 	quicc_param(bas, baudrate, databits, stopbits, parity);
137*e1ef7811SRafal Jaworowski 
138*e1ef7811SRafal Jaworowski 	quicc_write2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1), ~0);
139*e1ef7811SRafal Jaworowski 	quicc_write2(bas, QUICC_REG_SCC_SCCM(bas->chan - 1), 0x0027);
140*e1ef7811SRafal Jaworowski }
141*e1ef7811SRafal Jaworowski 
142*e1ef7811SRafal Jaworowski /*
143*e1ef7811SRafal Jaworowski  * Low-level UART interface.
144*e1ef7811SRafal Jaworowski  */
145*e1ef7811SRafal Jaworowski static int quicc_probe(struct uart_bas *bas);
146*e1ef7811SRafal Jaworowski static void quicc_init(struct uart_bas *bas, int, int, int, int);
147*e1ef7811SRafal Jaworowski static void quicc_term(struct uart_bas *bas);
148*e1ef7811SRafal Jaworowski static void quicc_putc(struct uart_bas *bas, int);
149*e1ef7811SRafal Jaworowski static int quicc_rxready(struct uart_bas *bas);
150*e1ef7811SRafal Jaworowski static int quicc_getc(struct uart_bas *bas, struct mtx *);
151*e1ef7811SRafal Jaworowski 
152*e1ef7811SRafal Jaworowski static struct uart_ops uart_quicc_ops = {
153*e1ef7811SRafal Jaworowski 	.probe = quicc_probe,
154*e1ef7811SRafal Jaworowski 	.init = quicc_init,
155*e1ef7811SRafal Jaworowski 	.term = quicc_term,
156*e1ef7811SRafal Jaworowski 	.putc = quicc_putc,
157*e1ef7811SRafal Jaworowski 	.rxready = quicc_rxready,
158*e1ef7811SRafal Jaworowski 	.getc = quicc_getc,
159*e1ef7811SRafal Jaworowski };
160*e1ef7811SRafal Jaworowski 
161*e1ef7811SRafal Jaworowski static int
162*e1ef7811SRafal Jaworowski quicc_probe(struct uart_bas *bas)
163*e1ef7811SRafal Jaworowski {
164*e1ef7811SRafal Jaworowski 
165*e1ef7811SRafal Jaworowski 	return (0);
166*e1ef7811SRafal Jaworowski }
167*e1ef7811SRafal Jaworowski 
168*e1ef7811SRafal Jaworowski static void
169*e1ef7811SRafal Jaworowski quicc_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
170*e1ef7811SRafal Jaworowski     int parity)
171*e1ef7811SRafal Jaworowski {
172*e1ef7811SRafal Jaworowski 
173*e1ef7811SRafal Jaworowski 	quicc_setup(bas, baudrate, databits, stopbits, parity);
174*e1ef7811SRafal Jaworowski }
175*e1ef7811SRafal Jaworowski 
176*e1ef7811SRafal Jaworowski static void
177*e1ef7811SRafal Jaworowski quicc_term(struct uart_bas *bas)
178*e1ef7811SRafal Jaworowski {
179*e1ef7811SRafal Jaworowski }
180*e1ef7811SRafal Jaworowski 
181*e1ef7811SRafal Jaworowski static void
182*e1ef7811SRafal Jaworowski quicc_putc(struct uart_bas *bas, int c)
183*e1ef7811SRafal Jaworowski {
184*e1ef7811SRafal Jaworowski 	int unit;
185*e1ef7811SRafal Jaworowski 	uint16_t toseq;
186*e1ef7811SRafal Jaworowski 
187*e1ef7811SRafal Jaworowski 	unit = bas->chan - 1;
188*e1ef7811SRafal Jaworowski 	while (quicc_read2(bas, QUICC_PRAM_SCC_UART_TOSEQ(unit)) & 0x2000)
189*e1ef7811SRafal Jaworowski 		DELAY(10);
190*e1ef7811SRafal Jaworowski 
191*e1ef7811SRafal Jaworowski 	toseq = 0x2000 | (c & 0xff);
192*e1ef7811SRafal Jaworowski 	quicc_write2(bas, QUICC_PRAM_SCC_UART_TOSEQ(unit), toseq);
193*e1ef7811SRafal Jaworowski }
194*e1ef7811SRafal Jaworowski 
195*e1ef7811SRafal Jaworowski static int
196*e1ef7811SRafal Jaworowski quicc_rxready(struct uart_bas *bas)
197*e1ef7811SRafal Jaworowski {
198*e1ef7811SRafal Jaworowski 	uint16_t rb;
199*e1ef7811SRafal Jaworowski 
200*e1ef7811SRafal Jaworowski 	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
201*e1ef7811SRafal Jaworowski 	return ((quicc_read2(bas, rb) & 0x8000) ? 0 : 1);
202*e1ef7811SRafal Jaworowski }
203*e1ef7811SRafal Jaworowski 
204*e1ef7811SRafal Jaworowski static int
205*e1ef7811SRafal Jaworowski quicc_getc(struct uart_bas *bas, struct mtx *hwmtx)
206*e1ef7811SRafal Jaworowski {
207*e1ef7811SRafal Jaworowski 	volatile char *buf;
208*e1ef7811SRafal Jaworowski 	int c;
209*e1ef7811SRafal Jaworowski 	uint16_t rb, sc;
210*e1ef7811SRafal Jaworowski 
211*e1ef7811SRafal Jaworowski 	uart_lock(hwmtx);
212*e1ef7811SRafal Jaworowski 
213*e1ef7811SRafal Jaworowski 	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
214*e1ef7811SRafal Jaworowski 
215*e1ef7811SRafal Jaworowski 	while ((sc = quicc_read2(bas, rb)) & 0x8000) {
216*e1ef7811SRafal Jaworowski 		uart_unlock(hwmtx);
217*e1ef7811SRafal Jaworowski 		DELAY(4);
218*e1ef7811SRafal Jaworowski 		uart_lock(hwmtx);
219*e1ef7811SRafal Jaworowski 	}
220*e1ef7811SRafal Jaworowski 
221*e1ef7811SRafal Jaworowski 	buf = (void *)quicc_read4(bas, rb + 4);
222*e1ef7811SRafal Jaworowski 	c = *buf;
223*e1ef7811SRafal Jaworowski 	quicc_write2(bas, rb, sc | 0x8000);
224*e1ef7811SRafal Jaworowski 
225*e1ef7811SRafal Jaworowski 	uart_unlock(hwmtx);
226*e1ef7811SRafal Jaworowski 
227*e1ef7811SRafal Jaworowski 	return (c);
228*e1ef7811SRafal Jaworowski }
229*e1ef7811SRafal Jaworowski 
230*e1ef7811SRafal Jaworowski /*
231*e1ef7811SRafal Jaworowski  * High-level UART interface.
232*e1ef7811SRafal Jaworowski  */
233*e1ef7811SRafal Jaworowski struct quicc_softc {
234*e1ef7811SRafal Jaworowski 	struct uart_softc base;
235*e1ef7811SRafal Jaworowski };
236*e1ef7811SRafal Jaworowski 
237*e1ef7811SRafal Jaworowski static int quicc_bus_attach(struct uart_softc *);
238*e1ef7811SRafal Jaworowski static int quicc_bus_detach(struct uart_softc *);
239*e1ef7811SRafal Jaworowski static int quicc_bus_flush(struct uart_softc *, int);
240*e1ef7811SRafal Jaworowski static int quicc_bus_getsig(struct uart_softc *);
241*e1ef7811SRafal Jaworowski static int quicc_bus_ioctl(struct uart_softc *, int, intptr_t);
242*e1ef7811SRafal Jaworowski static int quicc_bus_ipend(struct uart_softc *);
243*e1ef7811SRafal Jaworowski static int quicc_bus_param(struct uart_softc *, int, int, int, int);
244*e1ef7811SRafal Jaworowski static int quicc_bus_probe(struct uart_softc *);
245*e1ef7811SRafal Jaworowski static int quicc_bus_receive(struct uart_softc *);
246*e1ef7811SRafal Jaworowski static int quicc_bus_setsig(struct uart_softc *, int);
247*e1ef7811SRafal Jaworowski static int quicc_bus_transmit(struct uart_softc *);
248*e1ef7811SRafal Jaworowski 
249*e1ef7811SRafal Jaworowski static kobj_method_t quicc_methods[] = {
250*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_attach,		quicc_bus_attach),
251*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_detach,		quicc_bus_detach),
252*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_flush,		quicc_bus_flush),
253*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_getsig,		quicc_bus_getsig),
254*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_ioctl,		quicc_bus_ioctl),
255*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_ipend,		quicc_bus_ipend),
256*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_param,		quicc_bus_param),
257*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_probe,		quicc_bus_probe),
258*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_receive,	quicc_bus_receive),
259*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_setsig,		quicc_bus_setsig),
260*e1ef7811SRafal Jaworowski 	KOBJMETHOD(uart_transmit,	quicc_bus_transmit),
261*e1ef7811SRafal Jaworowski 	{ 0, 0 }
262*e1ef7811SRafal Jaworowski };
263*e1ef7811SRafal Jaworowski 
264*e1ef7811SRafal Jaworowski struct uart_class uart_quicc_class = {
265*e1ef7811SRafal Jaworowski 	"quicc",
266*e1ef7811SRafal Jaworowski 	quicc_methods,
267*e1ef7811SRafal Jaworowski 	sizeof(struct quicc_softc),
268*e1ef7811SRafal Jaworowski 	.uc_ops = &uart_quicc_ops,
269*e1ef7811SRafal Jaworowski 	.uc_range = 2,
270*e1ef7811SRafal Jaworowski 	.uc_rclk = DEFAULT_RCLK
271*e1ef7811SRafal Jaworowski };
272*e1ef7811SRafal Jaworowski 
273*e1ef7811SRafal Jaworowski #define	SIGCHG(c, i, s, d)				\
274*e1ef7811SRafal Jaworowski 	if (c) {					\
275*e1ef7811SRafal Jaworowski 		i |= (i & s) ? s : s | d;		\
276*e1ef7811SRafal Jaworowski 	} else {					\
277*e1ef7811SRafal Jaworowski 		i = (i & s) ? (i & ~s) | d : i;		\
278*e1ef7811SRafal Jaworowski 	}
279*e1ef7811SRafal Jaworowski 
280*e1ef7811SRafal Jaworowski static int
281*e1ef7811SRafal Jaworowski quicc_bus_attach(struct uart_softc *sc)
282*e1ef7811SRafal Jaworowski {
283*e1ef7811SRafal Jaworowski 	struct uart_bas *bas;
284*e1ef7811SRafal Jaworowski 	struct uart_devinfo *di;
285*e1ef7811SRafal Jaworowski 	uint16_t st, rb;
286*e1ef7811SRafal Jaworowski 
287*e1ef7811SRafal Jaworowski 	bas = &sc->sc_bas;
288*e1ef7811SRafal Jaworowski 	if (sc->sc_sysdev != NULL) {
289*e1ef7811SRafal Jaworowski 		di = sc->sc_sysdev;
290*e1ef7811SRafal Jaworowski 		quicc_param(bas, di->baudrate, di->databits, di->stopbits,
291*e1ef7811SRafal Jaworowski 		    di->parity);
292*e1ef7811SRafal Jaworowski 	} else {
293*e1ef7811SRafal Jaworowski 		quicc_setup(bas, 9600, 8, 1, UART_PARITY_NONE);
294*e1ef7811SRafal Jaworowski 	}
295*e1ef7811SRafal Jaworowski 
296*e1ef7811SRafal Jaworowski 	sc->sc_rxfifosz = 1;
297*e1ef7811SRafal Jaworowski 	sc->sc_txfifosz = 1;
298*e1ef7811SRafal Jaworowski 
299*e1ef7811SRafal Jaworowski 	/* Enable interrupts on the receive buffer. */
300*e1ef7811SRafal Jaworowski 	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
301*e1ef7811SRafal Jaworowski 	st = quicc_read2(bas, rb);
302*e1ef7811SRafal Jaworowski 	quicc_write2(bas, rb, st | 0x9000);
303*e1ef7811SRafal Jaworowski 
304*e1ef7811SRafal Jaworowski 	(void)quicc_bus_getsig(sc);
305*e1ef7811SRafal Jaworowski 
306*e1ef7811SRafal Jaworowski 	return (0);
307*e1ef7811SRafal Jaworowski }
308*e1ef7811SRafal Jaworowski 
309*e1ef7811SRafal Jaworowski static int
310*e1ef7811SRafal Jaworowski quicc_bus_detach(struct uart_softc *sc)
311*e1ef7811SRafal Jaworowski {
312*e1ef7811SRafal Jaworowski 
313*e1ef7811SRafal Jaworowski 	return (0);
314*e1ef7811SRafal Jaworowski }
315*e1ef7811SRafal Jaworowski 
316*e1ef7811SRafal Jaworowski static int
317*e1ef7811SRafal Jaworowski quicc_bus_flush(struct uart_softc *sc, int what)
318*e1ef7811SRafal Jaworowski {
319*e1ef7811SRafal Jaworowski 
320*e1ef7811SRafal Jaworowski 	return (0);
321*e1ef7811SRafal Jaworowski }
322*e1ef7811SRafal Jaworowski 
323*e1ef7811SRafal Jaworowski static int
324*e1ef7811SRafal Jaworowski quicc_bus_getsig(struct uart_softc *sc)
325*e1ef7811SRafal Jaworowski {
326*e1ef7811SRafal Jaworowski 	uint32_t new, old, sig;
327*e1ef7811SRafal Jaworowski 	uint32_t dummy;
328*e1ef7811SRafal Jaworowski 
329*e1ef7811SRafal Jaworowski 	do {
330*e1ef7811SRafal Jaworowski 		old = sc->sc_hwsig;
331*e1ef7811SRafal Jaworowski 		sig = old;
332*e1ef7811SRafal Jaworowski 		uart_lock(sc->sc_hwmtx);
333*e1ef7811SRafal Jaworowski 		/* XXX SIGNALS */
334*e1ef7811SRafal Jaworowski 		dummy = 0;
335*e1ef7811SRafal Jaworowski 		uart_unlock(sc->sc_hwmtx);
336*e1ef7811SRafal Jaworowski 		SIGCHG(dummy, sig, SER_CTS, SER_DCTS);
337*e1ef7811SRafal Jaworowski 		SIGCHG(dummy, sig, SER_DCD, SER_DDCD);
338*e1ef7811SRafal Jaworowski 		SIGCHG(dummy, sig, SER_DSR, SER_DDSR);
339*e1ef7811SRafal Jaworowski 		new = sig & ~SER_MASK_DELTA;
340*e1ef7811SRafal Jaworowski 	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
341*e1ef7811SRafal Jaworowski 	return (sig);
342*e1ef7811SRafal Jaworowski }
343*e1ef7811SRafal Jaworowski 
344*e1ef7811SRafal Jaworowski static int
345*e1ef7811SRafal Jaworowski quicc_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
346*e1ef7811SRafal Jaworowski {
347*e1ef7811SRafal Jaworowski 	struct uart_bas *bas;
348*e1ef7811SRafal Jaworowski 	uint32_t brg;
349*e1ef7811SRafal Jaworowski 	int baudrate, error;
350*e1ef7811SRafal Jaworowski 
351*e1ef7811SRafal Jaworowski 	bas = &sc->sc_bas;
352*e1ef7811SRafal Jaworowski 	error = 0;
353*e1ef7811SRafal Jaworowski 	uart_lock(sc->sc_hwmtx);
354*e1ef7811SRafal Jaworowski 	switch (request) {
355*e1ef7811SRafal Jaworowski 	case UART_IOCTL_BREAK:
356*e1ef7811SRafal Jaworowski 		break;
357*e1ef7811SRafal Jaworowski 	case UART_IOCTL_BAUD:
358*e1ef7811SRafal Jaworowski 		brg = quicc_read4(bas, QUICC_REG_BRG(bas->chan - 1)) & 0x1fff;
359*e1ef7811SRafal Jaworowski 		brg = (brg & 1) ? (brg + 1) << 3 : (brg + 2) >> 1;
360*e1ef7811SRafal Jaworowski 		baudrate = bas->rclk / (brg * 16);
361*e1ef7811SRafal Jaworowski 		*(int*)data = baudrate;
362*e1ef7811SRafal Jaworowski 		break;
363*e1ef7811SRafal Jaworowski 	default:
364*e1ef7811SRafal Jaworowski 		error = EINVAL;
365*e1ef7811SRafal Jaworowski 		break;
366*e1ef7811SRafal Jaworowski 	}
367*e1ef7811SRafal Jaworowski 	uart_unlock(sc->sc_hwmtx);
368*e1ef7811SRafal Jaworowski 	return (error);
369*e1ef7811SRafal Jaworowski }
370*e1ef7811SRafal Jaworowski 
371*e1ef7811SRafal Jaworowski static int
372*e1ef7811SRafal Jaworowski quicc_bus_ipend(struct uart_softc *sc)
373*e1ef7811SRafal Jaworowski {
374*e1ef7811SRafal Jaworowski 	struct uart_bas *bas;
375*e1ef7811SRafal Jaworowski 	int ipend;
376*e1ef7811SRafal Jaworowski 	uint16_t scce;
377*e1ef7811SRafal Jaworowski 
378*e1ef7811SRafal Jaworowski 	bas = &sc->sc_bas;
379*e1ef7811SRafal Jaworowski 	ipend = 0;
380*e1ef7811SRafal Jaworowski 
381*e1ef7811SRafal Jaworowski 	uart_lock(sc->sc_hwmtx);
382*e1ef7811SRafal Jaworowski 	scce = quicc_read2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1));
383*e1ef7811SRafal Jaworowski 	quicc_write2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1), ~0);
384*e1ef7811SRafal Jaworowski 	uart_unlock(sc->sc_hwmtx);
385*e1ef7811SRafal Jaworowski 	if (scce & 0x0001)
386*e1ef7811SRafal Jaworowski 		ipend |= SER_INT_RXREADY;
387*e1ef7811SRafal Jaworowski 	if (scce & 0x0002)
388*e1ef7811SRafal Jaworowski 		ipend |= SER_INT_TXIDLE;
389*e1ef7811SRafal Jaworowski 	if (scce & 0x0004)
390*e1ef7811SRafal Jaworowski 		ipend |= SER_INT_OVERRUN;
391*e1ef7811SRafal Jaworowski 	if (scce & 0x0020)
392*e1ef7811SRafal Jaworowski 		ipend |= SER_INT_BREAK;
393*e1ef7811SRafal Jaworowski 	/* XXX SIGNALS */
394*e1ef7811SRafal Jaworowski 	return (ipend);
395*e1ef7811SRafal Jaworowski }
396*e1ef7811SRafal Jaworowski 
397*e1ef7811SRafal Jaworowski static int
398*e1ef7811SRafal Jaworowski quicc_bus_param(struct uart_softc *sc, int baudrate, int databits,
399*e1ef7811SRafal Jaworowski     int stopbits, int parity)
400*e1ef7811SRafal Jaworowski {
401*e1ef7811SRafal Jaworowski 	int error;
402*e1ef7811SRafal Jaworowski 
403*e1ef7811SRafal Jaworowski 	uart_lock(sc->sc_hwmtx);
404*e1ef7811SRafal Jaworowski 	error = quicc_param(&sc->sc_bas, baudrate, databits, stopbits,
405*e1ef7811SRafal Jaworowski 	    parity);
406*e1ef7811SRafal Jaworowski 	uart_unlock(sc->sc_hwmtx);
407*e1ef7811SRafal Jaworowski 	return (error);
408*e1ef7811SRafal Jaworowski }
409*e1ef7811SRafal Jaworowski 
410*e1ef7811SRafal Jaworowski static int
411*e1ef7811SRafal Jaworowski quicc_bus_probe(struct uart_softc *sc)
412*e1ef7811SRafal Jaworowski {
413*e1ef7811SRafal Jaworowski 	char buf[80];
414*e1ef7811SRafal Jaworowski 	int error;
415*e1ef7811SRafal Jaworowski 
416*e1ef7811SRafal Jaworowski 	error = quicc_probe(&sc->sc_bas);
417*e1ef7811SRafal Jaworowski 	if (error)
418*e1ef7811SRafal Jaworowski 		return (error);
419*e1ef7811SRafal Jaworowski 
420*e1ef7811SRafal Jaworowski 	snprintf(buf, sizeof(buf), "quicc, channel %d", sc->sc_bas.chan);
421*e1ef7811SRafal Jaworowski 	device_set_desc_copy(sc->sc_dev, buf);
422*e1ef7811SRafal Jaworowski 	return (0);
423*e1ef7811SRafal Jaworowski }
424*e1ef7811SRafal Jaworowski 
425*e1ef7811SRafal Jaworowski static int
426*e1ef7811SRafal Jaworowski quicc_bus_receive(struct uart_softc *sc)
427*e1ef7811SRafal Jaworowski {
428*e1ef7811SRafal Jaworowski 	struct uart_bas *bas;
429*e1ef7811SRafal Jaworowski 	volatile char *buf;
430*e1ef7811SRafal Jaworowski 	uint16_t st, rb;
431*e1ef7811SRafal Jaworowski 
432*e1ef7811SRafal Jaworowski 	bas = &sc->sc_bas;
433*e1ef7811SRafal Jaworowski 	uart_lock(sc->sc_hwmtx);
434*e1ef7811SRafal Jaworowski 	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
435*e1ef7811SRafal Jaworowski 	st = quicc_read2(bas, rb);
436*e1ef7811SRafal Jaworowski 	buf = (void *)quicc_read4(bas, rb + 4);
437*e1ef7811SRafal Jaworowski 	uart_rx_put(sc, *buf);
438*e1ef7811SRafal Jaworowski 	quicc_write2(bas, rb, st | 0x9000);
439*e1ef7811SRafal Jaworowski 	uart_unlock(sc->sc_hwmtx);
440*e1ef7811SRafal Jaworowski 	return (0);
441*e1ef7811SRafal Jaworowski }
442*e1ef7811SRafal Jaworowski 
443*e1ef7811SRafal Jaworowski static int
444*e1ef7811SRafal Jaworowski quicc_bus_setsig(struct uart_softc *sc, int sig)
445*e1ef7811SRafal Jaworowski {
446*e1ef7811SRafal Jaworowski 	struct uart_bas *bas;
447*e1ef7811SRafal Jaworowski 	uint32_t new, old;
448*e1ef7811SRafal Jaworowski 
449*e1ef7811SRafal Jaworowski 	bas = &sc->sc_bas;
450*e1ef7811SRafal Jaworowski 	do {
451*e1ef7811SRafal Jaworowski 		old = sc->sc_hwsig;
452*e1ef7811SRafal Jaworowski 		new = old;
453*e1ef7811SRafal Jaworowski 		if (sig & SER_DDTR) {
454*e1ef7811SRafal Jaworowski 			SIGCHG(sig & SER_DTR, new, SER_DTR,
455*e1ef7811SRafal Jaworowski 			    SER_DDTR);
456*e1ef7811SRafal Jaworowski 		}
457*e1ef7811SRafal Jaworowski 		if (sig & SER_DRTS) {
458*e1ef7811SRafal Jaworowski 			SIGCHG(sig & SER_RTS, new, SER_RTS,
459*e1ef7811SRafal Jaworowski 			    SER_DRTS);
460*e1ef7811SRafal Jaworowski 		}
461*e1ef7811SRafal Jaworowski 	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
462*e1ef7811SRafal Jaworowski 
463*e1ef7811SRafal Jaworowski 	uart_lock(sc->sc_hwmtx);
464*e1ef7811SRafal Jaworowski 	/* XXX SIGNALS */
465*e1ef7811SRafal Jaworowski 	uart_unlock(sc->sc_hwmtx);
466*e1ef7811SRafal Jaworowski 	return (0);
467*e1ef7811SRafal Jaworowski }
468*e1ef7811SRafal Jaworowski 
469*e1ef7811SRafal Jaworowski static int
470*e1ef7811SRafal Jaworowski quicc_bus_transmit(struct uart_softc *sc)
471*e1ef7811SRafal Jaworowski {
472*e1ef7811SRafal Jaworowski 	volatile char *buf;
473*e1ef7811SRafal Jaworowski 	struct uart_bas *bas;
474*e1ef7811SRafal Jaworowski 	uint16_t st, tb;
475*e1ef7811SRafal Jaworowski 
476*e1ef7811SRafal Jaworowski 	bas = &sc->sc_bas;
477*e1ef7811SRafal Jaworowski 	uart_lock(sc->sc_hwmtx);
478*e1ef7811SRafal Jaworowski 	tb = quicc_read2(bas, QUICC_PRAM_SCC_TBASE(bas->chan - 1));
479*e1ef7811SRafal Jaworowski 	st = quicc_read2(bas, tb);
480*e1ef7811SRafal Jaworowski 	buf = (void *)quicc_read4(bas, tb + 4);
481*e1ef7811SRafal Jaworowski 	*buf = sc->sc_txbuf[0];
482*e1ef7811SRafal Jaworowski 	quicc_write2(bas, tb + 2, 1);
483*e1ef7811SRafal Jaworowski 	quicc_write2(bas, tb, st | 0x9000);
484*e1ef7811SRafal Jaworowski 	sc->sc_txbusy = 1;
485*e1ef7811SRafal Jaworowski 	uart_unlock(sc->sc_hwmtx);
486*e1ef7811SRafal Jaworowski 	return (0);
487*e1ef7811SRafal Jaworowski }
488