xref: /freebsd-13.1/sys/dev/uart/uart_dev_z8530.c (revision 27d5dc18)
1*27d5dc18SMarcel Moolenaar /*
2*27d5dc18SMarcel Moolenaar  * Copyright (c) 2003 Marcel Moolenaar
3*27d5dc18SMarcel Moolenaar  * All rights reserved.
4*27d5dc18SMarcel Moolenaar  *
5*27d5dc18SMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
6*27d5dc18SMarcel Moolenaar  * modification, are permitted provided that the following conditions
7*27d5dc18SMarcel Moolenaar  * are met:
8*27d5dc18SMarcel Moolenaar  *
9*27d5dc18SMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
10*27d5dc18SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
11*27d5dc18SMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
12*27d5dc18SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
13*27d5dc18SMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
14*27d5dc18SMarcel Moolenaar  *
15*27d5dc18SMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*27d5dc18SMarcel Moolenaar  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*27d5dc18SMarcel Moolenaar  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*27d5dc18SMarcel Moolenaar  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*27d5dc18SMarcel Moolenaar  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*27d5dc18SMarcel Moolenaar  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*27d5dc18SMarcel Moolenaar  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*27d5dc18SMarcel Moolenaar  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*27d5dc18SMarcel Moolenaar  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*27d5dc18SMarcel Moolenaar  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*27d5dc18SMarcel Moolenaar  */
26*27d5dc18SMarcel Moolenaar 
27*27d5dc18SMarcel Moolenaar #include <sys/cdefs.h>
28*27d5dc18SMarcel Moolenaar __FBSDID("$FreeBSD$");
29*27d5dc18SMarcel Moolenaar 
30*27d5dc18SMarcel Moolenaar #include <sys/param.h>
31*27d5dc18SMarcel Moolenaar #include <sys/systm.h>
32*27d5dc18SMarcel Moolenaar #include <sys/bus.h>
33*27d5dc18SMarcel Moolenaar #include <sys/conf.h>
34*27d5dc18SMarcel Moolenaar #include <machine/bus.h>
35*27d5dc18SMarcel Moolenaar 
36*27d5dc18SMarcel Moolenaar #include <dev/uart/uart.h>
37*27d5dc18SMarcel Moolenaar #include <dev/uart/uart_cpu.h>
38*27d5dc18SMarcel Moolenaar #include <dev/uart/uart_bus.h>
39*27d5dc18SMarcel Moolenaar #include <dev/uart/uart_dev_z8530.h>
40*27d5dc18SMarcel Moolenaar 
41*27d5dc18SMarcel Moolenaar #include "uart_if.h"
42*27d5dc18SMarcel Moolenaar 
43*27d5dc18SMarcel Moolenaar #define	DEFAULT_RCLK	307200
44*27d5dc18SMarcel Moolenaar 
45*27d5dc18SMarcel Moolenaar #define	IS_CHANNEL_A(bas)	(((bas)->bsh & 7) != 0)
46*27d5dc18SMarcel Moolenaar #define	IS_CHANNEL_B(bas)	(((bas)->bsh & 7) == 0)
47*27d5dc18SMarcel Moolenaar 
48*27d5dc18SMarcel Moolenaar /* Multiplexed I/O. */
49*27d5dc18SMarcel Moolenaar static __inline void
50*27d5dc18SMarcel Moolenaar uart_setmreg(struct uart_bas *bas, int reg, int val)
51*27d5dc18SMarcel Moolenaar {
52*27d5dc18SMarcel Moolenaar 
53*27d5dc18SMarcel Moolenaar 	uart_setreg(bas, REG_CTRL, reg);
54*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
55*27d5dc18SMarcel Moolenaar 	uart_setreg(bas, REG_CTRL, val);
56*27d5dc18SMarcel Moolenaar }
57*27d5dc18SMarcel Moolenaar 
58*27d5dc18SMarcel Moolenaar static __inline uint8_t
59*27d5dc18SMarcel Moolenaar uart_getmreg(struct uart_bas *bas, int reg)
60*27d5dc18SMarcel Moolenaar {
61*27d5dc18SMarcel Moolenaar 
62*27d5dc18SMarcel Moolenaar 	uart_setreg(bas, REG_CTRL, reg);
63*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
64*27d5dc18SMarcel Moolenaar 	return (uart_getreg(bas, REG_CTRL));
65*27d5dc18SMarcel Moolenaar }
66*27d5dc18SMarcel Moolenaar 
67*27d5dc18SMarcel Moolenaar static int
68*27d5dc18SMarcel Moolenaar z8530_divisor(int rclk, int baudrate)
69*27d5dc18SMarcel Moolenaar {
70*27d5dc18SMarcel Moolenaar 	int act_baud, divisor, error;
71*27d5dc18SMarcel Moolenaar 
72*27d5dc18SMarcel Moolenaar 	if (baudrate == 0)
73*27d5dc18SMarcel Moolenaar 		return (0);
74*27d5dc18SMarcel Moolenaar 
75*27d5dc18SMarcel Moolenaar 	divisor = (rclk + baudrate) / (baudrate << 1) - 2;
76*27d5dc18SMarcel Moolenaar 	if (divisor >= 65536)
77*27d5dc18SMarcel Moolenaar 		return (0);
78*27d5dc18SMarcel Moolenaar 	act_baud = rclk / 2 / (divisor + 2);
79*27d5dc18SMarcel Moolenaar 
80*27d5dc18SMarcel Moolenaar 	/* 10 times error in percent: */
81*27d5dc18SMarcel Moolenaar 	error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1;
82*27d5dc18SMarcel Moolenaar 
83*27d5dc18SMarcel Moolenaar 	/* 3.0% maximum error tolerance: */
84*27d5dc18SMarcel Moolenaar 	if (error < -30 || error > 30)
85*27d5dc18SMarcel Moolenaar 		return (0);
86*27d5dc18SMarcel Moolenaar 
87*27d5dc18SMarcel Moolenaar 	return (divisor);
88*27d5dc18SMarcel Moolenaar }
89*27d5dc18SMarcel Moolenaar 
90*27d5dc18SMarcel Moolenaar static int
91*27d5dc18SMarcel Moolenaar z8530_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
92*27d5dc18SMarcel Moolenaar     int parity, uint8_t *tpcp)
93*27d5dc18SMarcel Moolenaar {
94*27d5dc18SMarcel Moolenaar 	int divisor;
95*27d5dc18SMarcel Moolenaar 	uint8_t mpm, rpc, tpc;
96*27d5dc18SMarcel Moolenaar 
97*27d5dc18SMarcel Moolenaar 	rpc = RPC_RXE;
98*27d5dc18SMarcel Moolenaar 	mpm = MPM_CM16;
99*27d5dc18SMarcel Moolenaar 	tpc = TPC_TXE | (*tpcp & (TPC_DTR | TPC_RTS));
100*27d5dc18SMarcel Moolenaar 
101*27d5dc18SMarcel Moolenaar 	if (databits >= 8) {
102*27d5dc18SMarcel Moolenaar 		rpc |= RPC_RB8;
103*27d5dc18SMarcel Moolenaar 		tpc |= TPC_TB8;
104*27d5dc18SMarcel Moolenaar 	} else if (databits == 7) {
105*27d5dc18SMarcel Moolenaar 		rpc |= RPC_RB7;
106*27d5dc18SMarcel Moolenaar 		tpc |= TPC_TB7;
107*27d5dc18SMarcel Moolenaar 	} else if (databits == 6) {
108*27d5dc18SMarcel Moolenaar 		rpc |= RPC_RB6;
109*27d5dc18SMarcel Moolenaar 		tpc |= TPC_TB6;
110*27d5dc18SMarcel Moolenaar 	} else {
111*27d5dc18SMarcel Moolenaar 		rpc |= RPC_RB5;
112*27d5dc18SMarcel Moolenaar 		tpc |= TPC_TB5;
113*27d5dc18SMarcel Moolenaar 	}
114*27d5dc18SMarcel Moolenaar 	mpm |= (stopbits > 1) ? MPM_SB2 : MPM_SB1;
115*27d5dc18SMarcel Moolenaar 	switch (parity) {
116*27d5dc18SMarcel Moolenaar 	case UART_PARITY_EVEN:	mpm |= MPM_PE | MPM_EVEN; break;
117*27d5dc18SMarcel Moolenaar 	case UART_PARITY_NONE:	break;
118*27d5dc18SMarcel Moolenaar 	case UART_PARITY_ODD:	mpm |= MPM_PE; break;
119*27d5dc18SMarcel Moolenaar 	default:		return (EINVAL);
120*27d5dc18SMarcel Moolenaar 	}
121*27d5dc18SMarcel Moolenaar 
122*27d5dc18SMarcel Moolenaar 	/* Set baudrate. */
123*27d5dc18SMarcel Moolenaar 	if (baudrate > 0) {
124*27d5dc18SMarcel Moolenaar 		divisor = z8530_divisor(bas->rclk, baudrate);
125*27d5dc18SMarcel Moolenaar 		if (divisor == 0)
126*27d5dc18SMarcel Moolenaar 			return (EINVAL);
127*27d5dc18SMarcel Moolenaar 		uart_setmreg(bas, WR_TCL, divisor & 0xff);
128*27d5dc18SMarcel Moolenaar 		uart_barrier(bas);
129*27d5dc18SMarcel Moolenaar 		uart_setmreg(bas, WR_TCH, (divisor >> 8) & 0xff);
130*27d5dc18SMarcel Moolenaar 		uart_barrier(bas);
131*27d5dc18SMarcel Moolenaar 	}
132*27d5dc18SMarcel Moolenaar 
133*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_RPC, rpc);
134*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
135*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_MPM, mpm);
136*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
137*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_TPC, tpc);
138*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
139*27d5dc18SMarcel Moolenaar 	*tpcp = tpc;
140*27d5dc18SMarcel Moolenaar 	return (0);
141*27d5dc18SMarcel Moolenaar }
142*27d5dc18SMarcel Moolenaar 
143*27d5dc18SMarcel Moolenaar static int
144*27d5dc18SMarcel Moolenaar z8530_setup(struct uart_bas *bas, int baudrate, int databits, int stopbits,
145*27d5dc18SMarcel Moolenaar     int parity)
146*27d5dc18SMarcel Moolenaar {
147*27d5dc18SMarcel Moolenaar 	uint8_t tpc;
148*27d5dc18SMarcel Moolenaar 
149*27d5dc18SMarcel Moolenaar 	if (bas->rclk == 0)
150*27d5dc18SMarcel Moolenaar 		bas->rclk = DEFAULT_RCLK;
151*27d5dc18SMarcel Moolenaar 
152*27d5dc18SMarcel Moolenaar 	/* Assume we don't need to perform a full hardware reset. */
153*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_MIC, ((IS_CHANNEL_A(bas)) ? MIC_CRA : MIC_CRB) |
154*27d5dc18SMarcel Moolenaar 	    MIC_MIE | MIC_NV);
155*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
156*27d5dc18SMarcel Moolenaar 	/* Set clock sources and enable BRG. */
157*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_CMC, CMC_RC_BRG | CMC_TC_BRG);
158*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_MCB2, MCB2_PCLK | MCB2_BRGE);
159*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
160*27d5dc18SMarcel Moolenaar 	/* Set data encoding. */
161*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_MCB1, MCB1_NRZ);
162*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
163*27d5dc18SMarcel Moolenaar 
164*27d5dc18SMarcel Moolenaar 	tpc = TPC_DTR | TPC_RTS;
165*27d5dc18SMarcel Moolenaar 	z8530_param(bas, baudrate, databits, stopbits, parity, &tpc);
166*27d5dc18SMarcel Moolenaar 	return (int)tpc;
167*27d5dc18SMarcel Moolenaar }
168*27d5dc18SMarcel Moolenaar 
169*27d5dc18SMarcel Moolenaar /*
170*27d5dc18SMarcel Moolenaar  * Low-level UART interface.
171*27d5dc18SMarcel Moolenaar  */
172*27d5dc18SMarcel Moolenaar static int z8530_probe(struct uart_bas *bas);
173*27d5dc18SMarcel Moolenaar static void z8530_init(struct uart_bas *bas, int, int, int, int);
174*27d5dc18SMarcel Moolenaar static void z8530_term(struct uart_bas *bas);
175*27d5dc18SMarcel Moolenaar static void z8530_putc(struct uart_bas *bas, int);
176*27d5dc18SMarcel Moolenaar static int z8530_poll(struct uart_bas *bas);
177*27d5dc18SMarcel Moolenaar static int z8530_getc(struct uart_bas *bas);
178*27d5dc18SMarcel Moolenaar 
179*27d5dc18SMarcel Moolenaar struct uart_ops uart_z8530_ops = {
180*27d5dc18SMarcel Moolenaar 	.probe = z8530_probe,
181*27d5dc18SMarcel Moolenaar 	.init = z8530_init,
182*27d5dc18SMarcel Moolenaar 	.term = z8530_term,
183*27d5dc18SMarcel Moolenaar 	.putc = z8530_putc,
184*27d5dc18SMarcel Moolenaar 	.poll = z8530_poll,
185*27d5dc18SMarcel Moolenaar 	.getc = z8530_getc,
186*27d5dc18SMarcel Moolenaar };
187*27d5dc18SMarcel Moolenaar 
188*27d5dc18SMarcel Moolenaar static int
189*27d5dc18SMarcel Moolenaar z8530_probe(struct uart_bas *bas)
190*27d5dc18SMarcel Moolenaar {
191*27d5dc18SMarcel Moolenaar 
192*27d5dc18SMarcel Moolenaar 	return (0);
193*27d5dc18SMarcel Moolenaar }
194*27d5dc18SMarcel Moolenaar 
195*27d5dc18SMarcel Moolenaar static void
196*27d5dc18SMarcel Moolenaar z8530_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
197*27d5dc18SMarcel Moolenaar     int parity)
198*27d5dc18SMarcel Moolenaar {
199*27d5dc18SMarcel Moolenaar 
200*27d5dc18SMarcel Moolenaar 	z8530_setup(bas, baudrate, databits, stopbits, parity);
201*27d5dc18SMarcel Moolenaar }
202*27d5dc18SMarcel Moolenaar 
203*27d5dc18SMarcel Moolenaar static void
204*27d5dc18SMarcel Moolenaar z8530_term(struct uart_bas *bas)
205*27d5dc18SMarcel Moolenaar {
206*27d5dc18SMarcel Moolenaar }
207*27d5dc18SMarcel Moolenaar 
208*27d5dc18SMarcel Moolenaar static void
209*27d5dc18SMarcel Moolenaar z8530_putc(struct uart_bas *bas, int c)
210*27d5dc18SMarcel Moolenaar {
211*27d5dc18SMarcel Moolenaar 
212*27d5dc18SMarcel Moolenaar 	while (!(uart_getmreg(bas, RR_BES) & BES_TXE))
213*27d5dc18SMarcel Moolenaar 		;
214*27d5dc18SMarcel Moolenaar 	uart_setreg(bas, REG_DATA, c);
215*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
216*27d5dc18SMarcel Moolenaar }
217*27d5dc18SMarcel Moolenaar 
218*27d5dc18SMarcel Moolenaar static int
219*27d5dc18SMarcel Moolenaar z8530_poll(struct uart_bas *bas)
220*27d5dc18SMarcel Moolenaar {
221*27d5dc18SMarcel Moolenaar 
222*27d5dc18SMarcel Moolenaar 	if (!(uart_getmreg(bas, RR_BES) & BES_RXA))
223*27d5dc18SMarcel Moolenaar 		return (-1);
224*27d5dc18SMarcel Moolenaar 	return (uart_getreg(bas, REG_DATA));
225*27d5dc18SMarcel Moolenaar }
226*27d5dc18SMarcel Moolenaar 
227*27d5dc18SMarcel Moolenaar static int
228*27d5dc18SMarcel Moolenaar z8530_getc(struct uart_bas *bas)
229*27d5dc18SMarcel Moolenaar {
230*27d5dc18SMarcel Moolenaar 
231*27d5dc18SMarcel Moolenaar 	while (!(uart_getmreg(bas, RR_BES) & BES_RXA))
232*27d5dc18SMarcel Moolenaar 		;
233*27d5dc18SMarcel Moolenaar 	return (uart_getreg(bas, REG_DATA));
234*27d5dc18SMarcel Moolenaar }
235*27d5dc18SMarcel Moolenaar 
236*27d5dc18SMarcel Moolenaar /*
237*27d5dc18SMarcel Moolenaar  * High-level UART interface.
238*27d5dc18SMarcel Moolenaar  */
239*27d5dc18SMarcel Moolenaar struct z8530_softc {
240*27d5dc18SMarcel Moolenaar 	struct uart_softc base;
241*27d5dc18SMarcel Moolenaar 	uint8_t	tpc;
242*27d5dc18SMarcel Moolenaar };
243*27d5dc18SMarcel Moolenaar 
244*27d5dc18SMarcel Moolenaar static int z8530_bus_attach(struct uart_softc *);
245*27d5dc18SMarcel Moolenaar static int z8530_bus_detach(struct uart_softc *);
246*27d5dc18SMarcel Moolenaar static int z8530_bus_flush(struct uart_softc *, int);
247*27d5dc18SMarcel Moolenaar static int z8530_bus_getsig(struct uart_softc *);
248*27d5dc18SMarcel Moolenaar static int z8530_bus_ioctl(struct uart_softc *, int, intptr_t);
249*27d5dc18SMarcel Moolenaar static int z8530_bus_ipend(struct uart_softc *);
250*27d5dc18SMarcel Moolenaar static int z8530_bus_param(struct uart_softc *, int, int, int, int);
251*27d5dc18SMarcel Moolenaar static int z8530_bus_probe(struct uart_softc *);
252*27d5dc18SMarcel Moolenaar static int z8530_bus_receive(struct uart_softc *);
253*27d5dc18SMarcel Moolenaar static int z8530_bus_setsig(struct uart_softc *, int);
254*27d5dc18SMarcel Moolenaar static int z8530_bus_transmit(struct uart_softc *);
255*27d5dc18SMarcel Moolenaar 
256*27d5dc18SMarcel Moolenaar static kobj_method_t z8530_methods[] = {
257*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_attach,		z8530_bus_attach),
258*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_detach,		z8530_bus_detach),
259*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_flush,		z8530_bus_flush),
260*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_getsig,		z8530_bus_getsig),
261*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_ioctl,		z8530_bus_ioctl),
262*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_ipend,		z8530_bus_ipend),
263*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_param,		z8530_bus_param),
264*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_probe,		z8530_bus_probe),
265*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_receive,	z8530_bus_receive),
266*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_setsig,		z8530_bus_setsig),
267*27d5dc18SMarcel Moolenaar 	KOBJMETHOD(uart_transmit,	z8530_bus_transmit),
268*27d5dc18SMarcel Moolenaar 	{ 0, 0 }
269*27d5dc18SMarcel Moolenaar };
270*27d5dc18SMarcel Moolenaar 
271*27d5dc18SMarcel Moolenaar struct uart_class uart_z8530_class = {
272*27d5dc18SMarcel Moolenaar 	"z8530 class",
273*27d5dc18SMarcel Moolenaar 	z8530_methods,
274*27d5dc18SMarcel Moolenaar 	sizeof(struct z8530_softc),
275*27d5dc18SMarcel Moolenaar 	.uc_range = 2,
276*27d5dc18SMarcel Moolenaar 	.uc_rclk = DEFAULT_RCLK
277*27d5dc18SMarcel Moolenaar };
278*27d5dc18SMarcel Moolenaar 
279*27d5dc18SMarcel Moolenaar #define	SIGCHG(c, i, s, d)				\
280*27d5dc18SMarcel Moolenaar 	if (c) {					\
281*27d5dc18SMarcel Moolenaar 		i |= (i & s) ? s : s | d;		\
282*27d5dc18SMarcel Moolenaar 	} else {					\
283*27d5dc18SMarcel Moolenaar 		i = (i & s) ? (i & ~s) | d : i;		\
284*27d5dc18SMarcel Moolenaar 	}
285*27d5dc18SMarcel Moolenaar 
286*27d5dc18SMarcel Moolenaar static int
287*27d5dc18SMarcel Moolenaar z8530_bus_attach(struct uart_softc *sc)
288*27d5dc18SMarcel Moolenaar {
289*27d5dc18SMarcel Moolenaar 	struct z8530_softc *z8530 = (struct z8530_softc*)sc;
290*27d5dc18SMarcel Moolenaar 	struct uart_bas *bas;
291*27d5dc18SMarcel Moolenaar 	struct uart_devinfo *di;
292*27d5dc18SMarcel Moolenaar 
293*27d5dc18SMarcel Moolenaar 	bas = &sc->sc_bas;
294*27d5dc18SMarcel Moolenaar 	if (sc->sc_sysdev != NULL) {
295*27d5dc18SMarcel Moolenaar 		di = sc->sc_sysdev;
296*27d5dc18SMarcel Moolenaar 		z8530->tpc = TPC_DTR|TPC_RTS;
297*27d5dc18SMarcel Moolenaar 		z8530_param(bas, di->baudrate, di->databits, di->stopbits,
298*27d5dc18SMarcel Moolenaar 		    di->parity, &z8530->tpc);
299*27d5dc18SMarcel Moolenaar 	} else {
300*27d5dc18SMarcel Moolenaar 		z8530->tpc = z8530_setup(bas, 9600, 8, 1, UART_PARITY_NONE);
301*27d5dc18SMarcel Moolenaar 		z8530->tpc &= ~(TPC_DTR|TPC_RTS);
302*27d5dc18SMarcel Moolenaar 	}
303*27d5dc18SMarcel Moolenaar 
304*27d5dc18SMarcel Moolenaar 	sc->sc_rxfifosz = 3;
305*27d5dc18SMarcel Moolenaar 	sc->sc_txfifosz = 1;
306*27d5dc18SMarcel Moolenaar 
307*27d5dc18SMarcel Moolenaar 	(void)z8530_bus_getsig(sc);
308*27d5dc18SMarcel Moolenaar 
309*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_IC, IC_BRK | IC_CTS | IC_DCD);
310*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
311*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_IDT, IDT_TIE | IDT_RIA);
312*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
313*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_IV, 0);
314*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
315*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_TPC, z8530->tpc);
316*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
317*27d5dc18SMarcel Moolenaar 	return (0);
318*27d5dc18SMarcel Moolenaar }
319*27d5dc18SMarcel Moolenaar 
320*27d5dc18SMarcel Moolenaar static int
321*27d5dc18SMarcel Moolenaar z8530_bus_detach(struct uart_softc *sc)
322*27d5dc18SMarcel Moolenaar {
323*27d5dc18SMarcel Moolenaar 
324*27d5dc18SMarcel Moolenaar 	return (0);
325*27d5dc18SMarcel Moolenaar }
326*27d5dc18SMarcel Moolenaar 
327*27d5dc18SMarcel Moolenaar static int
328*27d5dc18SMarcel Moolenaar z8530_bus_flush(struct uart_softc *sc, int what)
329*27d5dc18SMarcel Moolenaar {
330*27d5dc18SMarcel Moolenaar 
331*27d5dc18SMarcel Moolenaar 	return (0);
332*27d5dc18SMarcel Moolenaar }
333*27d5dc18SMarcel Moolenaar 
334*27d5dc18SMarcel Moolenaar static int
335*27d5dc18SMarcel Moolenaar z8530_bus_getsig(struct uart_softc *sc)
336*27d5dc18SMarcel Moolenaar {
337*27d5dc18SMarcel Moolenaar 	struct uart_bas *bas;
338*27d5dc18SMarcel Moolenaar 	uint32_t new, old, sig;
339*27d5dc18SMarcel Moolenaar 	uint8_t bes;
340*27d5dc18SMarcel Moolenaar 
341*27d5dc18SMarcel Moolenaar 	bas = &sc->sc_bas;
342*27d5dc18SMarcel Moolenaar 	do {
343*27d5dc18SMarcel Moolenaar 		old = sc->sc_hwsig;
344*27d5dc18SMarcel Moolenaar 		sig = old;
345*27d5dc18SMarcel Moolenaar 		bes = uart_getmreg(bas, RR_BES);
346*27d5dc18SMarcel Moolenaar 		SIGCHG(bes & BES_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
347*27d5dc18SMarcel Moolenaar 		SIGCHG(bes & BES_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD);
348*27d5dc18SMarcel Moolenaar 		new = sig & ~UART_SIGMASK_DELTA;
349*27d5dc18SMarcel Moolenaar 	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
350*27d5dc18SMarcel Moolenaar 	return (sig);
351*27d5dc18SMarcel Moolenaar }
352*27d5dc18SMarcel Moolenaar 
353*27d5dc18SMarcel Moolenaar static int
354*27d5dc18SMarcel Moolenaar z8530_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
355*27d5dc18SMarcel Moolenaar {
356*27d5dc18SMarcel Moolenaar 	struct z8530_softc *z8530 = (struct z8530_softc*)sc;
357*27d5dc18SMarcel Moolenaar 	struct uart_bas *bas;
358*27d5dc18SMarcel Moolenaar 
359*27d5dc18SMarcel Moolenaar 	bas = &sc->sc_bas;
360*27d5dc18SMarcel Moolenaar 	switch (request) {
361*27d5dc18SMarcel Moolenaar 	case UART_IOCTL_BREAK:
362*27d5dc18SMarcel Moolenaar 		if (data)
363*27d5dc18SMarcel Moolenaar 			z8530->tpc |= TPC_BRK;
364*27d5dc18SMarcel Moolenaar 		else
365*27d5dc18SMarcel Moolenaar 			z8530->tpc &= ~TPC_BRK;
366*27d5dc18SMarcel Moolenaar 		uart_setmreg(bas, WR_TPC, z8530->tpc);
367*27d5dc18SMarcel Moolenaar 		uart_barrier(bas);
368*27d5dc18SMarcel Moolenaar 		break;
369*27d5dc18SMarcel Moolenaar 	default:
370*27d5dc18SMarcel Moolenaar 		return (EINVAL);
371*27d5dc18SMarcel Moolenaar 	}
372*27d5dc18SMarcel Moolenaar 	return (0);
373*27d5dc18SMarcel Moolenaar }
374*27d5dc18SMarcel Moolenaar 
375*27d5dc18SMarcel Moolenaar static int
376*27d5dc18SMarcel Moolenaar z8530_bus_ipend(struct uart_softc *sc)
377*27d5dc18SMarcel Moolenaar {
378*27d5dc18SMarcel Moolenaar 	struct uart_bas *bas;
379*27d5dc18SMarcel Moolenaar 	int ipend;
380*27d5dc18SMarcel Moolenaar 	uint32_t sig;
381*27d5dc18SMarcel Moolenaar 	uint8_t bes, src;
382*27d5dc18SMarcel Moolenaar 
383*27d5dc18SMarcel Moolenaar 	bas = &sc->sc_bas;
384*27d5dc18SMarcel Moolenaar 	ipend = 0;
385*27d5dc18SMarcel Moolenaar 	uart_setreg(bas, REG_CTRL, CR_RSTIUS);
386*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
387*27d5dc18SMarcel Moolenaar 	bes = uart_getmreg(bas, RR_BES);
388*27d5dc18SMarcel Moolenaar 	if (bes & BES_BRK) {
389*27d5dc18SMarcel Moolenaar 		uart_setreg(bas, REG_CTRL, CR_RSTXSI);
390*27d5dc18SMarcel Moolenaar 		ipend |= UART_IPEND_BREAK;
391*27d5dc18SMarcel Moolenaar 	}
392*27d5dc18SMarcel Moolenaar 	if (bes & BES_TXE) {
393*27d5dc18SMarcel Moolenaar 		uart_setreg(bas, REG_CTRL, CR_RSTTXI);
394*27d5dc18SMarcel Moolenaar 		ipend |= UART_IPEND_TXIDLE;
395*27d5dc18SMarcel Moolenaar 	}
396*27d5dc18SMarcel Moolenaar 	if (bes & BES_RXA)
397*27d5dc18SMarcel Moolenaar 		ipend |= UART_IPEND_RXREADY;
398*27d5dc18SMarcel Moolenaar 	sig = sc->sc_hwsig;
399*27d5dc18SMarcel Moolenaar 	SIGCHG(bes & BES_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
400*27d5dc18SMarcel Moolenaar 	SIGCHG(bes & BES_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD);
401*27d5dc18SMarcel Moolenaar 	if (sig & UART_SIGMASK_DELTA)
402*27d5dc18SMarcel Moolenaar 		ipend |= UART_IPEND_SIGCHG;
403*27d5dc18SMarcel Moolenaar 	src = uart_getmreg(bas, RR_SRC);
404*27d5dc18SMarcel Moolenaar 	if (src & SRC_OVR) {
405*27d5dc18SMarcel Moolenaar 		uart_setreg(bas, REG_CTRL, CR_RSTERR);
406*27d5dc18SMarcel Moolenaar 		ipend |= UART_IPEND_OVERRUN;
407*27d5dc18SMarcel Moolenaar 	}
408*27d5dc18SMarcel Moolenaar 	return (ipend);
409*27d5dc18SMarcel Moolenaar }
410*27d5dc18SMarcel Moolenaar 
411*27d5dc18SMarcel Moolenaar static int
412*27d5dc18SMarcel Moolenaar z8530_bus_param(struct uart_softc *sc, int baudrate, int databits,
413*27d5dc18SMarcel Moolenaar     int stopbits, int parity)
414*27d5dc18SMarcel Moolenaar {
415*27d5dc18SMarcel Moolenaar 	struct z8530_softc *z8530 = (struct z8530_softc*)sc;
416*27d5dc18SMarcel Moolenaar 	int error;
417*27d5dc18SMarcel Moolenaar 
418*27d5dc18SMarcel Moolenaar 	error = z8530_param(&sc->sc_bas, baudrate, databits, stopbits, parity,
419*27d5dc18SMarcel Moolenaar 	    &z8530->tpc);
420*27d5dc18SMarcel Moolenaar 	return (error);
421*27d5dc18SMarcel Moolenaar }
422*27d5dc18SMarcel Moolenaar 
423*27d5dc18SMarcel Moolenaar static int
424*27d5dc18SMarcel Moolenaar z8530_bus_probe(struct uart_softc *sc)
425*27d5dc18SMarcel Moolenaar {
426*27d5dc18SMarcel Moolenaar 	char buf[80];
427*27d5dc18SMarcel Moolenaar 	const char *ch;
428*27d5dc18SMarcel Moolenaar 	int error;
429*27d5dc18SMarcel Moolenaar 
430*27d5dc18SMarcel Moolenaar 	error = z8530_probe(&sc->sc_bas);
431*27d5dc18SMarcel Moolenaar 	if (error)
432*27d5dc18SMarcel Moolenaar 		return (error);
433*27d5dc18SMarcel Moolenaar 
434*27d5dc18SMarcel Moolenaar 	/* Assume the address range is naturally aligned. */
435*27d5dc18SMarcel Moolenaar 	ch = IS_CHANNEL_A(&sc->sc_bas) ? "A" : "B";
436*27d5dc18SMarcel Moolenaar 
437*27d5dc18SMarcel Moolenaar 	snprintf(buf, sizeof(buf), "z8530, channel %s", ch);
438*27d5dc18SMarcel Moolenaar 	device_set_desc_copy(sc->sc_dev, buf);
439*27d5dc18SMarcel Moolenaar 	return (0);
440*27d5dc18SMarcel Moolenaar }
441*27d5dc18SMarcel Moolenaar 
442*27d5dc18SMarcel Moolenaar static int
443*27d5dc18SMarcel Moolenaar z8530_bus_receive(struct uart_softc *sc)
444*27d5dc18SMarcel Moolenaar {
445*27d5dc18SMarcel Moolenaar 	struct uart_bas *bas;
446*27d5dc18SMarcel Moolenaar 	int xc;
447*27d5dc18SMarcel Moolenaar 	uint8_t bes, src;
448*27d5dc18SMarcel Moolenaar 
449*27d5dc18SMarcel Moolenaar 	bas = &sc->sc_bas;
450*27d5dc18SMarcel Moolenaar 	bes = uart_getmreg(bas, RR_BES);
451*27d5dc18SMarcel Moolenaar 	while ((bes & BES_RXA) && !uart_rx_full(sc)) {
452*27d5dc18SMarcel Moolenaar 		src = uart_getmreg(bas, RR_SRC);
453*27d5dc18SMarcel Moolenaar 		xc = uart_getreg(bas, REG_DATA);
454*27d5dc18SMarcel Moolenaar 		if (src & SRC_FE)
455*27d5dc18SMarcel Moolenaar 			xc |= UART_STAT_FRAMERR;
456*27d5dc18SMarcel Moolenaar 		if (src & SRC_PE)
457*27d5dc18SMarcel Moolenaar 			xc |= UART_STAT_PARERR;
458*27d5dc18SMarcel Moolenaar 		uart_rx_put(sc, xc);
459*27d5dc18SMarcel Moolenaar 		if (src & (SRC_FE | SRC_PE))
460*27d5dc18SMarcel Moolenaar 			uart_setreg(bas, REG_CTRL, CR_RSTERR);
461*27d5dc18SMarcel Moolenaar 		bes = uart_getmreg(bas, RR_BES);
462*27d5dc18SMarcel Moolenaar 	}
463*27d5dc18SMarcel Moolenaar 	return (0);
464*27d5dc18SMarcel Moolenaar }
465*27d5dc18SMarcel Moolenaar 
466*27d5dc18SMarcel Moolenaar static int
467*27d5dc18SMarcel Moolenaar z8530_bus_setsig(struct uart_softc *sc, int sig)
468*27d5dc18SMarcel Moolenaar {
469*27d5dc18SMarcel Moolenaar 	struct z8530_softc *z8530 = (struct z8530_softc*)sc;
470*27d5dc18SMarcel Moolenaar 	struct uart_bas *bas;
471*27d5dc18SMarcel Moolenaar 	uint32_t new, old;
472*27d5dc18SMarcel Moolenaar 
473*27d5dc18SMarcel Moolenaar 	bas = &sc->sc_bas;
474*27d5dc18SMarcel Moolenaar 	do {
475*27d5dc18SMarcel Moolenaar 		old = sc->sc_hwsig;
476*27d5dc18SMarcel Moolenaar 		new = old;
477*27d5dc18SMarcel Moolenaar 		if (sig & UART_SIG_DDTR) {
478*27d5dc18SMarcel Moolenaar 			SIGCHG(sig & UART_SIG_DTR, new, UART_SIG_DTR,
479*27d5dc18SMarcel Moolenaar 			    UART_SIG_DDTR);
480*27d5dc18SMarcel Moolenaar 		}
481*27d5dc18SMarcel Moolenaar 		if (sig & UART_SIG_DRTS) {
482*27d5dc18SMarcel Moolenaar 			SIGCHG(sig & UART_SIG_RTS, new, UART_SIG_RTS,
483*27d5dc18SMarcel Moolenaar 			    UART_SIG_DRTS);
484*27d5dc18SMarcel Moolenaar 		}
485*27d5dc18SMarcel Moolenaar 	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
486*27d5dc18SMarcel Moolenaar 
487*27d5dc18SMarcel Moolenaar 	if (new & UART_SIG_DTR)
488*27d5dc18SMarcel Moolenaar 		z8530->tpc |= TPC_DTR;
489*27d5dc18SMarcel Moolenaar 	else
490*27d5dc18SMarcel Moolenaar 		z8530->tpc &= ~TPC_DTR;
491*27d5dc18SMarcel Moolenaar 	if (new & UART_SIG_RTS)
492*27d5dc18SMarcel Moolenaar 		z8530->tpc |= TPC_RTS;
493*27d5dc18SMarcel Moolenaar 	else
494*27d5dc18SMarcel Moolenaar 		z8530->tpc &= ~TPC_RTS;
495*27d5dc18SMarcel Moolenaar 	uart_setmreg(bas, WR_TPC, z8530->tpc);
496*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
497*27d5dc18SMarcel Moolenaar 	return (0);
498*27d5dc18SMarcel Moolenaar }
499*27d5dc18SMarcel Moolenaar 
500*27d5dc18SMarcel Moolenaar static int
501*27d5dc18SMarcel Moolenaar z8530_bus_transmit(struct uart_softc *sc)
502*27d5dc18SMarcel Moolenaar {
503*27d5dc18SMarcel Moolenaar 	struct uart_bas *bas;
504*27d5dc18SMarcel Moolenaar 
505*27d5dc18SMarcel Moolenaar 	bas = &sc->sc_bas;
506*27d5dc18SMarcel Moolenaar 	while (!(uart_getmreg(bas, RR_BES) & BES_TXE))
507*27d5dc18SMarcel Moolenaar 		;
508*27d5dc18SMarcel Moolenaar 	uart_setreg(bas, REG_DATA, sc->sc_txbuf[0]);
509*27d5dc18SMarcel Moolenaar 	uart_barrier(bas);
510*27d5dc18SMarcel Moolenaar 	sc->sc_txbusy = 1;
511*27d5dc18SMarcel Moolenaar 	return (0);
512*27d5dc18SMarcel Moolenaar }
513