uart_dev_sab82532.c revision 128631
1/*
2 * Copyright (c) 2003 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/uart/uart_dev_sab82532.c 128631 2004-04-25 04:30:40Z marcel $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/conf.h>
34#include <machine/bus.h>
35
36#include <dev/uart/uart.h>
37#include <dev/uart/uart_cpu.h>
38#include <dev/uart/uart_bus.h>
39#include <dev/uart/uart_dev_sab82532.h>
40
41#include "uart_if.h"
42
43#define	DEFAULT_RCLK	29491200
44
45/*
46 * NOTE: To allow us to read the baudrate divisor from the chip, we
47 * copy the value written to the write-only BGR register to an unused
48 * read-write register. We use TCR for that.
49 */
50
51static int
52sab82532_delay(struct uart_bas *bas)
53{
54	int divisor, m, n;
55	uint8_t bgr, ccr2;
56
57	bgr = uart_getreg(bas, SAB_TCR);
58	ccr2 = uart_getreg(bas, SAB_CCR2);
59	n = (bgr & 0x3f) + 1;
60	m = (bgr >> 6) | ((ccr2 >> 4) & 0xC);
61	divisor = n * (1<<m);
62
63	/* 1/10th the time to transmit 1 character (estimate). */
64	return (16000000 * divisor / bas->rclk);
65}
66
67static int
68sab82532_divisor(int rclk, int baudrate)
69{
70	int act_baud, act_div, divisor;
71	int error, m, n;
72
73	if (baudrate == 0)
74		return (0);
75
76	divisor = (rclk / (baudrate << 3) + 1) >> 1;
77	if (divisor < 2 || divisor >= 1048576)
78		return (0);
79
80	/* Find the best (N+1,M) pair. */
81	for (m = 1; m < 15; m++) {
82		n = divisor / (1<<m);
83		if (n < 1 || n > 63)
84			continue;
85		act_div = n * (1<<m);
86		act_baud = rclk / (act_div << 4);
87
88		/* 10 times error in percent: */
89		error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1;
90
91		/* 3.0% maximum error tolerance: */
92		if (error < -30 || error > 30)
93			continue;
94
95		/* Got it. */
96		return ((n - 1) | (m << 6));
97	}
98
99	return (0);
100}
101
102static void
103sab82532_flush(struct uart_bas *bas, int what)
104{
105
106	if (what & UART_FLUSH_TRANSMITTER) {
107		while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
108			;
109		uart_setreg(bas, SAB_CMDR, SAB_CMDR_XRES);
110		uart_barrier(bas);
111	}
112	if (what & UART_FLUSH_RECEIVER) {
113		while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
114			;
115		uart_setreg(bas, SAB_CMDR, SAB_CMDR_RRES);
116		uart_barrier(bas);
117	}
118}
119
120static int
121sab82532_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
122    int parity)
123{
124	int divisor;
125	uint8_t ccr2, dafo;
126
127	if (databits >= 8)
128		dafo = SAB_DAFO_CHL_CS8;
129	else if (databits == 7)
130		dafo = SAB_DAFO_CHL_CS7;
131	else if (databits == 6)
132		dafo = SAB_DAFO_CHL_CS6;
133	else
134		dafo = SAB_DAFO_CHL_CS5;
135	if (stopbits > 1)
136		dafo |= SAB_DAFO_STOP;
137	switch (parity) {
138	case UART_PARITY_EVEN:	dafo |= SAB_DAFO_PAR_EVEN; break;
139	case UART_PARITY_MARK:	dafo |= SAB_DAFO_PAR_MARK; break;
140	case UART_PARITY_NONE:	dafo |= SAB_DAFO_PAR_NONE; break;
141	case UART_PARITY_ODD:	dafo |= SAB_DAFO_PAR_ODD; break;
142	case UART_PARITY_SPACE:	dafo |= SAB_DAFO_PAR_SPACE; break;
143	default:		return (EINVAL);
144	}
145
146	/* Set baudrate. */
147	if (baudrate > 0) {
148		divisor = sab82532_divisor(bas->rclk, baudrate);
149		if (divisor == 0)
150			return (EINVAL);
151		uart_setreg(bas, SAB_BGR, divisor & 0xff);
152		uart_barrier(bas);
153		/* Allow reading the (n-1,m) tuple from the chip. */
154		uart_setreg(bas, SAB_TCR, divisor & 0xff);
155		uart_barrier(bas);
156		ccr2 = uart_getreg(bas, SAB_CCR2);
157		ccr2 &= ~(SAB_CCR2_BR9 | SAB_CCR2_BR8);
158		ccr2 |= (divisor >> 2) & (SAB_CCR2_BR9 | SAB_CCR2_BR8);
159		uart_setreg(bas, SAB_CCR2, ccr2);
160		uart_barrier(bas);
161	}
162
163	uart_setreg(bas, SAB_DAFO, dafo);
164	uart_barrier(bas);
165	return (0);
166}
167
168/*
169 * Low-level UART interface.
170 */
171static int sab82532_probe(struct uart_bas *bas);
172static void sab82532_init(struct uart_bas *bas, int, int, int, int);
173static void sab82532_term(struct uart_bas *bas);
174static void sab82532_putc(struct uart_bas *bas, int);
175static int sab82532_poll(struct uart_bas *bas);
176static int sab82532_getc(struct uart_bas *bas);
177
178struct uart_ops uart_sab82532_ops = {
179	.probe = sab82532_probe,
180	.init = sab82532_init,
181	.term = sab82532_term,
182	.putc = sab82532_putc,
183	.poll = sab82532_poll,
184	.getc = sab82532_getc,
185};
186
187static int
188sab82532_probe(struct uart_bas *bas)
189{
190
191	return (0);
192}
193
194static void
195sab82532_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
196    int parity)
197{
198	uint8_t ccr0, pvr;
199
200	if (bas->rclk == 0)
201		bas->rclk = DEFAULT_RCLK;
202
203	/*
204	 * Set all pins, except the DTR pins (pin 1 and 2) to be inputs.
205	 * Pin 4 is magical, meaning that I don't know what it does, but
206	 * it too has to be set to output.
207	 */
208	uart_setreg(bas, SAB_PCR,
209	    ~(SAB_PVR_DTR_A|SAB_PVR_DTR_B|SAB_PVR_MAGIC));
210	uart_barrier(bas);
211	/* Disable port interrupts. */
212	uart_setreg(bas, SAB_PIM, 0xff);
213	uart_barrier(bas);
214	/* Interrupts are active low. */
215	uart_setreg(bas, SAB_IPC, SAB_IPC_ICPL);
216	uart_barrier(bas);
217	/* Set DTR. */
218	pvr = uart_getreg(bas, SAB_PVR);
219	switch (bas->chan) {
220	case 1:
221		pvr &= ~SAB_PVR_DTR_A;
222		break;
223	case 2:
224		pvr &= ~SAB_PVR_DTR_B;
225		break;
226	}
227	uart_setreg(bas, SAB_PVR, pvr | SAB_PVR_MAGIC);
228	uart_barrier(bas);
229
230	/* power down */
231	uart_setreg(bas, SAB_CCR0, 0);
232	uart_barrier(bas);
233
234	/* set basic configuration */
235	ccr0 = SAB_CCR0_MCE|SAB_CCR0_SC_NRZ|SAB_CCR0_SM_ASYNC;
236	uart_setreg(bas, SAB_CCR0, ccr0);
237	uart_barrier(bas);
238	uart_setreg(bas, SAB_CCR1, SAB_CCR1_ODS|SAB_CCR1_BCR|SAB_CCR1_CM_7);
239	uart_barrier(bas);
240	uart_setreg(bas, SAB_CCR2, SAB_CCR2_BDF|SAB_CCR2_SSEL|SAB_CCR2_TOE);
241	uart_barrier(bas);
242	uart_setreg(bas, SAB_CCR3, 0);
243	uart_barrier(bas);
244	uart_setreg(bas, SAB_CCR4, SAB_CCR4_MCK4|SAB_CCR4_EBRG|SAB_CCR4_ICD);
245	uart_barrier(bas);
246	uart_setreg(bas, SAB_MODE, SAB_MODE_FCTS|SAB_MODE_RTS|SAB_MODE_RAC);
247	uart_barrier(bas);
248	uart_setreg(bas, SAB_RFC, SAB_RFC_DPS|SAB_RFC_RFDF|
249	    SAB_RFC_RFTH_32CHAR);
250	uart_barrier(bas);
251
252	sab82532_param(bas, baudrate, databits, stopbits, parity);
253
254	/* Clear interrupts. */
255	uart_setreg(bas, SAB_IMR0, (unsigned char)~SAB_IMR0_TCD);
256	uart_setreg(bas, SAB_IMR1, 0xff);
257	uart_barrier(bas);
258	uart_getreg(bas, SAB_ISR0);
259	uart_getreg(bas, SAB_ISR1);
260	uart_barrier(bas);
261
262	sab82532_flush(bas, UART_FLUSH_TRANSMITTER|UART_FLUSH_RECEIVER);
263
264	/* Power up. */
265	uart_setreg(bas, SAB_CCR0, ccr0|SAB_CCR0_PU);
266	uart_barrier(bas);
267}
268
269static void
270sab82532_term(struct uart_bas *bas)
271{
272	uint8_t pvr;
273
274	pvr = uart_getreg(bas, SAB_PVR);
275	switch (bas->chan) {
276	case 1:
277		pvr |= SAB_PVR_DTR_A;
278		break;
279	case 2:
280		pvr |= SAB_PVR_DTR_B;
281		break;
282	}
283	uart_setreg(bas, SAB_PVR, pvr);
284	uart_barrier(bas);
285}
286
287static void
288sab82532_putc(struct uart_bas *bas, int c)
289{
290	int delay, limit;
291
292	/* 1/10th the time to transmit 1 character (estimate). */
293	delay = sab82532_delay(bas);
294
295	limit = 20;
296	while ((uart_getreg(bas, SAB_STAR) & SAB_STAR_TEC) && --limit)
297		DELAY(delay);
298	uart_setreg(bas, SAB_TIC, c);
299	limit = 20;
300	while ((uart_getreg(bas, SAB_STAR) & SAB_STAR_TEC) && --limit)
301		DELAY(delay);
302}
303
304static int
305sab82532_poll(struct uart_bas *bas)
306{
307
308	if (uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE)
309		return (sab82532_getc(bas));
310	return (-1);
311}
312
313static int
314sab82532_getc(struct uart_bas *bas)
315{
316	int c, delay;
317
318	/* 1/10th the time to transmit 1 character (estimate). */
319	delay = sab82532_delay(bas);
320
321	while (!(uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE))
322		DELAY(delay);
323
324	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
325		;
326	uart_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD);
327	uart_barrier(bas);
328
329	while (!(uart_getreg(bas, SAB_ISR0) & SAB_ISR0_TCD))
330		DELAY(delay);
331
332	c = uart_getreg(bas, SAB_RFIFO);
333	uart_barrier(bas);
334
335	/* Blow away everything left in the FIFO... */
336	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
337		;
338	uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC);
339	uart_barrier(bas);
340	return (c);
341}
342
343/*
344 * High-level UART interface.
345 */
346struct sab82532_softc {
347	struct uart_softc base;
348};
349
350static int sab82532_bus_attach(struct uart_softc *);
351static int sab82532_bus_detach(struct uart_softc *);
352static int sab82532_bus_flush(struct uart_softc *, int);
353static int sab82532_bus_getsig(struct uart_softc *);
354static int sab82532_bus_ioctl(struct uart_softc *, int, intptr_t);
355static int sab82532_bus_ipend(struct uart_softc *);
356static int sab82532_bus_param(struct uart_softc *, int, int, int, int);
357static int sab82532_bus_probe(struct uart_softc *);
358static int sab82532_bus_receive(struct uart_softc *);
359static int sab82532_bus_setsig(struct uart_softc *, int);
360static int sab82532_bus_transmit(struct uart_softc *);
361
362static kobj_method_t sab82532_methods[] = {
363	KOBJMETHOD(uart_attach,		sab82532_bus_attach),
364	KOBJMETHOD(uart_detach,		sab82532_bus_detach),
365	KOBJMETHOD(uart_flush,		sab82532_bus_flush),
366	KOBJMETHOD(uart_getsig,		sab82532_bus_getsig),
367	KOBJMETHOD(uart_ioctl,		sab82532_bus_ioctl),
368	KOBJMETHOD(uart_ipend,		sab82532_bus_ipend),
369	KOBJMETHOD(uart_param,		sab82532_bus_param),
370	KOBJMETHOD(uart_probe,		sab82532_bus_probe),
371	KOBJMETHOD(uart_receive,	sab82532_bus_receive),
372	KOBJMETHOD(uart_setsig,		sab82532_bus_setsig),
373	KOBJMETHOD(uart_transmit,	sab82532_bus_transmit),
374	{ 0, 0 }
375};
376
377struct uart_class uart_sab82532_class = {
378	"sab82532 class",
379	sab82532_methods,
380	sizeof(struct sab82532_softc),
381	.uc_range = 64,
382	.uc_rclk = DEFAULT_RCLK
383};
384
385#define	SIGCHG(c, i, s, d)				\
386	if (c) {					\
387		i |= (i & s) ? s : s | d;		\
388	} else {					\
389		i = (i & s) ? (i & ~s) | d : i;		\
390	}
391
392static int
393sab82532_bus_attach(struct uart_softc *sc)
394{
395	struct uart_bas *bas;
396	uint8_t imr0, imr1;
397
398	bas = &sc->sc_bas;
399	if (sc->sc_sysdev == NULL)
400		sab82532_init(bas, 9600, 8, 1, UART_PARITY_NONE);
401
402	sc->sc_rxfifosz = 32;
403	sc->sc_txfifosz = 32;
404
405	imr0 = SAB_IMR0_TCD|SAB_IMR0_TIME|SAB_IMR0_CDSC|SAB_IMR0_RFO|
406	    SAB_IMR0_RPF;
407	uart_setreg(bas, SAB_IMR0, 0xff & ~imr0);
408	imr1 = SAB_IMR1_BRKT|SAB_IMR1_ALLS|SAB_IMR1_CSC;
409	uart_setreg(bas, SAB_IMR1, 0xff & ~imr1);
410	uart_barrier(bas);
411
412	if (sc->sc_sysdev == NULL)
413		sab82532_bus_setsig(sc, UART_SIG_DDTR|UART_SIG_DRTS);
414	(void)sab82532_bus_getsig(sc);
415	return (0);
416}
417
418static int
419sab82532_bus_detach(struct uart_softc *sc)
420{
421	struct uart_bas *bas;
422
423	bas = &sc->sc_bas;
424	uart_setreg(bas, SAB_IMR0, 0xff);
425	uart_setreg(bas, SAB_IMR1, 0xff);
426	uart_barrier(bas);
427	uart_getreg(bas, SAB_ISR0);
428	uart_getreg(bas, SAB_ISR1);
429	uart_barrier(bas);
430	uart_setreg(bas, SAB_CCR0, 0);
431	uart_barrier(bas);
432	return (0);
433}
434
435static int
436sab82532_bus_flush(struct uart_softc *sc, int what)
437{
438
439	mtx_lock_spin(&sc->sc_hwmtx);
440	sab82532_flush(&sc->sc_bas, what);
441	mtx_unlock_spin(&sc->sc_hwmtx);
442	return (0);
443}
444
445static int
446sab82532_bus_getsig(struct uart_softc *sc)
447{
448	struct uart_bas *bas;
449	uint32_t new, old, sig;
450	uint8_t pvr, star, vstr;
451
452	bas = &sc->sc_bas;
453	do {
454		old = sc->sc_hwsig;
455		sig = old;
456		mtx_lock_spin(&sc->sc_hwmtx);
457		star = uart_getreg(bas, SAB_STAR);
458		SIGCHG(star & SAB_STAR_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS);
459		vstr = uart_getreg(bas, SAB_VSTR);
460		SIGCHG(vstr & SAB_VSTR_CD, sig, UART_SIG_DCD, UART_SIG_DDCD);
461		pvr = uart_getreg(bas, SAB_PVR);
462		switch (bas->chan) {
463		case 1:
464			pvr &= SAB_PVR_DSR_A;
465			break;
466		case 2:
467			pvr &= SAB_PVR_DSR_B;
468			break;
469		}
470		SIGCHG(~pvr, sig, UART_SIG_DSR, UART_SIG_DDSR);
471		mtx_unlock_spin(&sc->sc_hwmtx);
472		new = sig & ~UART_SIGMASK_DELTA;
473	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
474	return (sig);
475}
476
477static int
478sab82532_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
479{
480	struct uart_bas *bas;
481	uint8_t dafo, mode;
482	int error;
483
484	bas = &sc->sc_bas;
485	error = 0;
486	mtx_lock_spin(&sc->sc_hwmtx);
487	switch (request) {
488	case UART_IOCTL_BREAK:
489		dafo = uart_getreg(bas, SAB_DAFO);
490		if (data)
491			dafo |= SAB_DAFO_XBRK;
492		else
493			dafo &= ~SAB_DAFO_XBRK;
494		uart_setreg(bas, SAB_DAFO, dafo);
495		uart_barrier(bas);
496		break;
497	case UART_IOCTL_IFLOW:
498		mode = uart_getreg(bas, SAB_MODE);
499		if (data) {
500			mode &= ~SAB_MODE_RTS;
501			mode |= SAB_MODE_FRTS;
502		} else {
503			mode |= SAB_MODE_RTS;
504			mode &= ~SAB_MODE_FRTS;
505		}
506		uart_setreg(bas, SAB_MODE, mode);
507		uart_barrier(bas);
508		break;
509	case UART_IOCTL_OFLOW:
510		mode = uart_getreg(bas, SAB_MODE);
511		if (data)
512			mode &= ~SAB_MODE_FCTS;
513		else
514			mode |= SAB_MODE_FCTS;
515		uart_setreg(bas, SAB_MODE, mode);
516		uart_barrier(bas);
517		break;
518	default:
519		error = EINVAL;
520		break;
521	}
522	mtx_unlock_spin(&sc->sc_hwmtx);
523	return (error);
524}
525
526static int
527sab82532_bus_ipend(struct uart_softc *sc)
528{
529	struct uart_bas *bas;
530	int ipend;
531	uint8_t isr0, isr1;
532
533	bas = &sc->sc_bas;
534	mtx_lock_spin(&sc->sc_hwmtx);
535	isr0 = uart_getreg(bas, SAB_ISR0);
536	isr1 = uart_getreg(bas, SAB_ISR1);
537	uart_barrier(bas);
538	if (isr0 & SAB_ISR0_TIME) {
539		while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
540			;
541		uart_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD);
542		uart_barrier(bas);
543	}
544	mtx_unlock_spin(&sc->sc_hwmtx);
545
546	ipend = 0;
547	if (isr1 & SAB_ISR1_BRKT)
548		ipend |= UART_IPEND_BREAK;
549	if (isr0 & SAB_ISR0_RFO)
550		ipend |= UART_IPEND_OVERRUN;
551	if (isr0 & (SAB_ISR0_TCD|SAB_ISR0_RPF))
552		ipend |= UART_IPEND_RXREADY;
553	if ((isr0 & SAB_ISR0_CDSC) || (isr1 & SAB_ISR1_CSC))
554		ipend |= UART_IPEND_SIGCHG;
555	if (isr1 & SAB_ISR1_ALLS)
556		ipend |= UART_IPEND_TXIDLE;
557
558	return (ipend);
559}
560
561static int
562sab82532_bus_param(struct uart_softc *sc, int baudrate, int databits,
563    int stopbits, int parity)
564{
565	struct uart_bas *bas;
566	int error;
567
568	bas = &sc->sc_bas;
569	mtx_lock_spin(&sc->sc_hwmtx);
570	error = sab82532_param(bas, baudrate, databits, stopbits, parity);
571	mtx_unlock_spin(&sc->sc_hwmtx);
572	return (error);
573}
574
575static int
576sab82532_bus_probe(struct uart_softc *sc)
577{
578	char buf[80];
579	const char *vstr;
580	int error;
581	char ch;
582
583	error = sab82532_probe(&sc->sc_bas);
584	if (error)
585		return (error);
586
587	ch = sc->sc_bas.chan - 1 + 'A';
588
589	switch (uart_getreg(&sc->sc_bas, SAB_VSTR) & SAB_VSTR_VMASK) {
590	case SAB_VSTR_V_1:
591		vstr = "v1";
592		break;
593	case SAB_VSTR_V_2:
594		vstr = "v2";
595		break;
596	case SAB_VSTR_V_32:
597		vstr = "v3.2";
598		sc->sc_hwiflow = 0;	/* CTS doesn't work with RFC:RFDF. */
599		sc->sc_hwoflow = 1;
600		break;
601	default:
602		vstr = "v4?";
603		break;
604	}
605
606	snprintf(buf, sizeof(buf), "SAB 82532 %s, channel %c", vstr, ch);
607	device_set_desc_copy(sc->sc_dev, buf);
608	return (0);
609}
610
611static int
612sab82532_bus_receive(struct uart_softc *sc)
613{
614	struct uart_bas *bas;
615	int i, rbcl, xc;
616	uint8_t s;
617
618	bas = &sc->sc_bas;
619	mtx_lock_spin(&sc->sc_hwmtx);
620	if (uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE) {
621		rbcl = uart_getreg(bas, SAB_RBCL) & 31;
622		if (rbcl == 0)
623			rbcl = 32;
624		for (i = 0; i < rbcl; i += 2) {
625			if (uart_rx_full(sc)) {
626				sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
627				break;
628			}
629			xc = uart_getreg(bas, SAB_RFIFO);
630			s = uart_getreg(bas, SAB_RFIFO + 1);
631			if (s & SAB_RSTAT_FE)
632				xc |= UART_STAT_FRAMERR;
633			if (s & SAB_RSTAT_PE)
634				xc |= UART_STAT_PARERR;
635			uart_rx_put(sc, xc);
636		}
637	}
638
639	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
640		;
641	uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC);
642	uart_barrier(bas);
643	mtx_unlock_spin(&sc->sc_hwmtx);
644	return (0);
645}
646
647static int
648sab82532_bus_setsig(struct uart_softc *sc, int sig)
649{
650	struct uart_bas *bas;
651	uint32_t new, old;
652	uint8_t mode, pvr;
653
654	bas = &sc->sc_bas;
655	do {
656		old = sc->sc_hwsig;
657		new = old;
658		if (sig & UART_SIG_DDTR) {
659			SIGCHG(sig & UART_SIG_DTR, new, UART_SIG_DTR,
660			    UART_SIG_DDTR);
661		}
662		if (sig & UART_SIG_DRTS) {
663			SIGCHG(sig & UART_SIG_RTS, new, UART_SIG_RTS,
664			    UART_SIG_DRTS);
665		}
666	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
667
668	mtx_lock_spin(&sc->sc_hwmtx);
669	/* Set DTR pin. */
670	pvr = uart_getreg(bas, SAB_PVR);
671	switch (bas->chan) {
672	case 1:
673		if (new & UART_SIG_DTR)
674			pvr &= ~SAB_PVR_DTR_A;
675		else
676			pvr |= SAB_PVR_DTR_A;
677		break;
678	case 2:
679		if (new & UART_SIG_DTR)
680			pvr &= ~SAB_PVR_DTR_B;
681		else
682			pvr |= SAB_PVR_DTR_B;
683		break;
684	}
685	uart_setreg(bas, SAB_PVR, pvr);
686
687	/* Set RTS pin. */
688	mode = uart_getreg(bas, SAB_MODE);
689	if (new & UART_SIG_RTS)
690		mode &= ~SAB_MODE_FRTS;
691	else
692		mode |= SAB_MODE_FRTS;
693	uart_setreg(bas, SAB_MODE, mode);
694	uart_barrier(bas);
695	mtx_unlock_spin(&sc->sc_hwmtx);
696	return (0);
697}
698
699static int
700sab82532_bus_transmit(struct uart_softc *sc)
701{
702	struct uart_bas *bas;
703	int i;
704
705	bas = &sc->sc_bas;
706	mtx_lock_spin(&sc->sc_hwmtx);
707	while (!(uart_getreg(bas, SAB_STAR) & SAB_STAR_XFW))
708		;
709	for (i = 0; i < sc->sc_txdatasz; i++)
710		uart_setreg(bas, SAB_XFIFO + i, sc->sc_txbuf[i]);
711	uart_barrier(bas);
712	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
713		;
714	uart_setreg(bas, SAB_CMDR, SAB_CMDR_XF);
715	sc->sc_txbusy = 1;
716	mtx_unlock_spin(&sc->sc_hwmtx);
717	return (0);
718}
719