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$");
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_z8530.h>
40
41 #include "uart_if.h"
42
43 #define DEFAULT_RCLK 307200
44
45 /* Multiplexed I/O. */
46 static __inline void
47 uart_setmreg(struct uart_bas *bas, int reg, int val)
48 {
49
50 uart_setreg(bas, REG_CTRL, reg);
51 uart_barrier(bas);
52 uart_setreg(bas, REG_CTRL, val);
53 }
54
55 static __inline uint8_t
56 uart_getmreg(struct uart_bas *bas, int reg)
57 {
58
59 uart_setreg(bas, REG_CTRL, reg);
60 uart_barrier(bas);
61 return (uart_getreg(bas, REG_CTRL));
62 }
63
64 static int
65 z8530_divisor(int rclk, int baudrate)
66 {
67 int act_baud, divisor, error;
68
69 if (baudrate == 0)
70 return (0);
71
72 divisor = (rclk + baudrate) / (baudrate << 1) - 2;
73 if (divisor >= 65536)
74 return (0);
75 act_baud = rclk / 2 / (divisor + 2);
76
77 /* 10 times error in percent: */
78 error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1;
79
80 /* 3.0% maximum error tolerance: */
81 if (error < -30 || error > 30)
82 return (0);
83
84 return (divisor);
85 }
86
87 static int
88 z8530_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
89 int parity, uint8_t *tpcp)
90 {
91 int divisor;
92 uint8_t mpm, rpc, tpc;
93
94 rpc = RPC_RXE;
95 mpm = MPM_CM16;
96 tpc = TPC_TXE | (*tpcp & (TPC_DTR | TPC_RTS));
97
98 if (databits >= 8) {
99 rpc |= RPC_RB8;
100 tpc |= TPC_TB8;
101 } else if (databits == 7) {
102 rpc |= RPC_RB7;
103 tpc |= TPC_TB7;
104 } else if (databits == 6) {
105 rpc |= RPC_RB6;
106 tpc |= TPC_TB6;
107 } else {
108 rpc |= RPC_RB5;
109 tpc |= TPC_TB5;
110 }
111 mpm |= (stopbits > 1) ? MPM_SB2 : MPM_SB1;
112 switch (parity) {
113 case UART_PARITY_EVEN: mpm |= MPM_PE | MPM_EVEN; break;
114 case UART_PARITY_NONE: break;
115 case UART_PARITY_ODD: mpm |= MPM_PE; break;
116 default: return (EINVAL);
117 }
118
119 /* Set baudrate. */
120 if (baudrate > 0) {
121 divisor = z8530_divisor(bas->rclk, baudrate);
122 if (divisor == 0)
123 return (EINVAL);
124 uart_setmreg(bas, WR_TCL, divisor & 0xff);
125 uart_barrier(bas);
126 uart_setmreg(bas, WR_TCH, (divisor >> 8) & 0xff);
127 uart_barrier(bas);
128 }
129
130 uart_setmreg(bas, WR_RPC, rpc);
131 uart_barrier(bas);
132 uart_setmreg(bas, WR_MPM, mpm);
133 uart_barrier(bas);
134 uart_setmreg(bas, WR_TPC, tpc);
135 uart_barrier(bas);
136 *tpcp = tpc;
137 return (0);
138 }
139
140 static int
141 z8530_setup(struct uart_bas *bas, int baudrate, int databits, int stopbits,
142 int parity)
143 {
144 uint8_t tpc;
145
146 if (bas->rclk == 0)
147 bas->rclk = DEFAULT_RCLK;
148
149 /* Assume we don't need to perform a full hardware reset. */
150 switch (bas->chan) {
151 case 1:
152 uart_setmreg(bas, WR_MIC, MIC_NV | MIC_CRA);
153 break;
154 case 2:
155 uart_setmreg(bas, WR_MIC, MIC_NV | MIC_CRB);
156 break;
157 }
158 uart_barrier(bas);
159 /* Set clock sources and enable BRG. */
160 uart_setmreg(bas, WR_CMC, CMC_RC_BRG | CMC_TC_BRG);
161 uart_setmreg(bas, WR_MCB2, MCB2_PCLK | MCB2_BRGE);
162 uart_barrier(bas);
163 /* Set data encoding. */
164 uart_setmreg(bas, WR_MCB1, MCB1_NRZ);
165 uart_barrier(bas);
166
167 tpc = TPC_DTR | TPC_RTS;
168 z8530_param(bas, baudrate, databits, stopbits, parity, &tpc);
169 return (int)tpc;
170 }
171
172 /*
173 * Low-level UART interface.
174 */
175 static int z8530_probe(struct uart_bas *bas);
176 static void z8530_init(struct uart_bas *bas, int, int, int, int);
177 static void z8530_term(struct uart_bas *bas);
178 static void z8530_putc(struct uart_bas *bas, int);
179 static int z8530_poll(struct uart_bas *bas);
180 static int z8530_getc(struct uart_bas *bas);
181
182 struct uart_ops uart_z8530_ops = {
183 .probe = z8530_probe,
184 .init = z8530_init,
185 .term = z8530_term,
186 .putc = z8530_putc,
187 .poll = z8530_poll,
188 .getc = z8530_getc,
189 };
190
191 static int
192 z8530_probe(struct uart_bas *bas)
193 {
194
195 return (0);
196 }
197
198 static void
199 z8530_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
200 int parity)
201 {
202
203 z8530_setup(bas, baudrate, databits, stopbits, parity);
204 }
205
206 static void
207 z8530_term(struct uart_bas *bas)
208 {
209 }
210
211 static void
212 z8530_putc(struct uart_bas *bas, int c)
213 {
214
215 while (!(uart_getreg(bas, REG_CTRL) & BES_TXE))
216 ;
217 uart_setreg(bas, REG_DATA, c);
218 uart_barrier(bas);
219 }
220
221 static int
222 z8530_poll(struct uart_bas *bas)
223 {
224
225 if (!(uart_getreg(bas, REG_CTRL) & BES_RXA))
226 return (-1);
227 return (uart_getreg(bas, REG_DATA));
228 }
229
230 static int
231 z8530_getc(struct uart_bas *bas)
232 {
233
234 while (!(uart_getreg(bas, REG_CTRL) & BES_RXA))
235 ;
236 return (uart_getreg(bas, REG_DATA));
237 }
238
239 /*
240 * High-level UART interface.
241 */
242 struct z8530_softc {
243 struct uart_softc base;
244 uint8_t tpc;
245 uint8_t txidle;
246 };
247
248 static int z8530_bus_attach(struct uart_softc *);
249 static int z8530_bus_detach(struct uart_softc *);
250 static int z8530_bus_flush(struct uart_softc *, int);
251 static int z8530_bus_getsig(struct uart_softc *);
252 static int z8530_bus_ioctl(struct uart_softc *, int, intptr_t);
253 static int z8530_bus_ipend(struct uart_softc *);
254 static int z8530_bus_param(struct uart_softc *, int, int, int, int);
255 static int z8530_bus_probe(struct uart_softc *);
256 static int z8530_bus_receive(struct uart_softc *);
257 static int z8530_bus_setsig(struct uart_softc *, int);
258 static int z8530_bus_transmit(struct uart_softc *);
259
260 static kobj_method_t z8530_methods[] = {
261 KOBJMETHOD(uart_attach, z8530_bus_attach),
262 KOBJMETHOD(uart_detach, z8530_bus_detach),
263 KOBJMETHOD(uart_flush, z8530_bus_flush),
264 KOBJMETHOD(uart_getsig, z8530_bus_getsig),
265 KOBJMETHOD(uart_ioctl, z8530_bus_ioctl),
266 KOBJMETHOD(uart_ipend, z8530_bus_ipend),
267 KOBJMETHOD(uart_param, z8530_bus_param),
268 KOBJMETHOD(uart_probe, z8530_bus_probe),
269 KOBJMETHOD(uart_receive, z8530_bus_receive),
270 KOBJMETHOD(uart_setsig, z8530_bus_setsig),
271 KOBJMETHOD(uart_transmit, z8530_bus_transmit),
272 { 0, 0 }
273 };
274
275 struct uart_class uart_z8530_class = {
276 "z8530 class",
277 z8530_methods,
278 sizeof(struct z8530_softc),
279 .uc_range = 2,
280 .uc_rclk = DEFAULT_RCLK
281 };
282
283 #define SIGCHG(c, i, s, d) \
284 if (c) { \
285 i |= (i & s) ? s : s | d; \
286 } else { \
287 i = (i & s) ? (i & ~s) | d : i; \
288 }
289
290 static int
291 z8530_bus_attach(struct uart_softc *sc)
292 {
293 struct z8530_softc *z8530 = (struct z8530_softc*)sc;
294 struct uart_bas *bas;
295 struct uart_devinfo *di;
296
297 bas = &sc->sc_bas;
298 if (sc->sc_sysdev != NULL) {
299 di = sc->sc_sysdev;
300 z8530->tpc = TPC_DTR|TPC_RTS;
301 z8530_param(bas, di->baudrate, di->databits, di->stopbits,
302 di->parity, &z8530->tpc);
303 } else {
304 z8530->tpc = z8530_setup(bas, 9600, 8, 1, UART_PARITY_NONE);
305 z8530->tpc &= ~(TPC_DTR|TPC_RTS);
306 }
307 z8530->txidle = 1; /* Report UART_IPEND_TXIDLE. */
308
309 sc->sc_rxfifosz = 3;
310 sc->sc_txfifosz = 1;
311
312 (void)z8530_bus_getsig(sc);
313
314 uart_setmreg(bas, WR_IC, IC_BRK | IC_CTS | IC_DCD);
315 uart_barrier(bas);
316 uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE | IDT_RIA);
317 uart_barrier(bas);
318 uart_setmreg(bas, WR_IV, 0);
319 uart_barrier(bas);
320 uart_setmreg(bas, WR_TPC, z8530->tpc);
321 uart_barrier(bas);
322 uart_setmreg(bas, WR_MIC, MIC_NV | MIC_MIE);
323 uart_barrier(bas);
324 return (0);
325 }
326
327 static int
328 z8530_bus_detach(struct uart_softc *sc)
329 {
330
331 return (0);
332 }
333
334 static int
335 z8530_bus_flush(struct uart_softc *sc, int what)
336 {
337
338 return (0);
339 }
340
341 static int
342 z8530_bus_getsig(struct uart_softc *sc)
343 {
344 uint32_t new, old, sig;
345 uint8_t bes;
346
347 do {
348 old = sc->sc_hwsig;
349 sig = old;
350 mtx_lock_spin(&sc->sc_hwmtx);
351 bes = uart_getmreg(&sc->sc_bas, RR_BES);
352 mtx_unlock_spin(&sc->sc_hwmtx);
353 SIGCHG(bes & BES_CTS, sig, SER_CTS, SER_DCTS);
354 SIGCHG(bes & BES_DCD, sig, SER_DCD, SER_DDCD);
355 SIGCHG(bes & BES_SYNC, sig, SER_DSR, SER_DDSR);
356 new = sig & ~UART_SIGMASK_DELTA;
357 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
358 return (sig);
359 }
360
361 static int
362 z8530_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
363 {
364 struct z8530_softc *z8530 = (struct z8530_softc*)sc;
365 struct uart_bas *bas;
366 int error;
367
368 bas = &sc->sc_bas;
369 error = 0;
370 mtx_lock_spin(&sc->sc_hwmtx);
371 switch (request) {
372 case UART_IOCTL_BREAK:
373 if (data)
374 z8530->tpc |= TPC_BRK;
375 else
376 z8530->tpc &= ~TPC_BRK;
377 uart_setmreg(bas, WR_TPC, z8530->tpc);
378 uart_barrier(bas);
379 break;
380 default:
381 error = EINVAL;
382 break;
383 }
384 mtx_unlock_spin(&sc->sc_hwmtx);
385 return (error);
386 }
387
388 static int
389 z8530_bus_ipend(struct uart_softc *sc)
390 {
391 struct z8530_softc *z8530 = (struct z8530_softc*)sc;
392 struct uart_bas *bas;
393 int ipend;
394 uint32_t sig;
395 uint8_t bes, ip, iv, src;
396
397 bas = &sc->sc_bas;
398 ipend = 0;
399
400 mtx_lock_spin(&sc->sc_hwmtx);
401 switch (bas->chan) {
402 case 1:
403 ip = uart_getmreg(bas, RR_IP);
404 break;
405 case 2: /* XXX hack!!! */
406 iv = uart_getmreg(bas, RR_IV) & 0x0E;
407 switch (iv) {
408 case IV_TEB: ip = IP_TIA; break;
409 case IV_XSB: ip = IP_SIA; break;
410 case IV_RAB: ip = IP_RIA; break;
411 default: ip = 0; break;
412 }
413 break;
414 default:
415 ip = 0;
416 break;
417 }
418
419 if (ip & IP_RIA)
420 ipend |= UART_IPEND_RXREADY;
421
422 if (ip & IP_TIA) {
423 uart_setreg(bas, REG_CTRL, CR_RSTTXI);
424 uart_barrier(bas);
425 if (z8530->txidle) {
426 ipend |= UART_IPEND_TXIDLE;
427 z8530->txidle = 0; /* Mask UART_IPEND_TXIDLE. */
428 }
429 }
430
431 if (ip & IP_SIA) {
432 uart_setreg(bas, REG_CTRL, CR_RSTXSI);
433 uart_barrier(bas);
434 bes = uart_getmreg(bas, RR_BES);
435 if (bes & BES_BRK)
436 ipend |= UART_IPEND_BREAK;
437 sig = sc->sc_hwsig;
438 SIGCHG(bes & BES_CTS, sig, SER_CTS, SER_DCTS);
439 SIGCHG(bes & BES_DCD, sig, SER_DCD, SER_DDCD);
440 SIGCHG(bes & BES_SYNC, sig, SER_DSR, SER_DDSR);
441 if (sig & UART_SIGMASK_DELTA)
442 ipend |= UART_IPEND_SIGCHG;
443 src = uart_getmreg(bas, RR_SRC);
444 if (src & SRC_OVR) {
445 uart_setreg(bas, REG_CTRL, CR_RSTERR);
446 uart_barrier(bas);
447 ipend |= UART_IPEND_OVERRUN;
448 }
449 }
450
451 if (ipend) {
452 uart_setreg(bas, REG_CTRL, CR_RSTIUS);
453 uart_barrier(bas);
454 }
455
456 mtx_unlock_spin(&sc->sc_hwmtx);
457
458 return (ipend);
459 }
460
461 static int
462 z8530_bus_param(struct uart_softc *sc, int baudrate, int databits,
463 int stopbits, int parity)
464 {
465 struct z8530_softc *z8530 = (struct z8530_softc*)sc;
466 int error;
467
468 mtx_lock_spin(&sc->sc_hwmtx);
469 error = z8530_param(&sc->sc_bas, baudrate, databits, stopbits, parity,
470 &z8530->tpc);
471 mtx_unlock_spin(&sc->sc_hwmtx);
472 return (error);
473 }
474
475 static int
476 z8530_bus_probe(struct uart_softc *sc)
477 {
478 char buf[80];
479 int error;
480 char ch;
481
482 error = z8530_probe(&sc->sc_bas);
483 if (error)
484 return (error);
485
486 ch = sc->sc_bas.chan - 1 + 'A';
487
488 snprintf(buf, sizeof(buf), "z8530, channel %c", ch);
489 device_set_desc_copy(sc->sc_dev, buf);
490 return (0);
491 }
492
493 static int
494 z8530_bus_receive(struct uart_softc *sc)
495 {
496 struct uart_bas *bas;
497 int xc;
498 uint8_t bes, src;
499
500 bas = &sc->sc_bas;
501 mtx_lock_spin(&sc->sc_hwmtx);
502 bes = uart_getmreg(bas, RR_BES);
503 while (bes & BES_RXA) {
504 if (uart_rx_full(sc)) {
505 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
506 break;
507 }
508 xc = uart_getreg(bas, REG_DATA);
509 uart_barrier(bas);
510 src = uart_getmreg(bas, RR_SRC);
511 if (src & SRC_FE)
512 xc |= UART_STAT_FRAMERR;
513 if (src & SRC_PE)
514 xc |= UART_STAT_PARERR;
515 if (src & SRC_OVR)
516 xc |= UART_STAT_OVERRUN;
517 uart_rx_put(sc, xc);
518 if (src & (SRC_FE | SRC_PE | SRC_OVR)) {
519 uart_setreg(bas, REG_CTRL, CR_RSTERR);
520 uart_barrier(bas);
521 }
522 bes = uart_getmreg(bas, RR_BES);
523 }
524 /* Discard everything left in the Rx FIFO. */
525 while (bes & BES_RXA) {
526 (void)uart_getreg(bas, REG_DATA);
527 uart_barrier(bas);
528 src = uart_getmreg(bas, RR_SRC);
529 if (src & (SRC_FE | SRC_PE | SRC_OVR)) {
530 uart_setreg(bas, REG_CTRL, CR_RSTERR);
531 uart_barrier(bas);
532 }
533 bes = uart_getmreg(bas, RR_BES);
534 }
535 mtx_unlock_spin(&sc->sc_hwmtx);
536 return (0);
537 }
538
539 static int
540 z8530_bus_setsig(struct uart_softc *sc, int sig)
541 {
542 struct z8530_softc *z8530 = (struct z8530_softc*)sc;
543 struct uart_bas *bas;
544 uint32_t new, old;
545
546 bas = &sc->sc_bas;
547 do {
548 old = sc->sc_hwsig;
549 new = old;
550 if (sig & SER_DDTR) {
551 SIGCHG(sig & SER_DTR, new, SER_DTR,
552 SER_DDTR);
553 }
554 if (sig & SER_DRTS) {
555 SIGCHG(sig & SER_RTS, new, SER_RTS,
556 SER_DRTS);
557 }
558 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
559
560 mtx_lock_spin(&sc->sc_hwmtx);
561 if (new & SER_DTR)
562 z8530->tpc |= TPC_DTR;
563 else
564 z8530->tpc &= ~TPC_DTR;
565 if (new & SER_RTS)
566 z8530->tpc |= TPC_RTS;
567 else
568 z8530->tpc &= ~TPC_RTS;
569 uart_setmreg(bas, WR_TPC, z8530->tpc);
570 uart_barrier(bas);
571 mtx_unlock_spin(&sc->sc_hwmtx);
572 return (0);
573 }
574
575 static int
576 z8530_bus_transmit(struct uart_softc *sc)
577 {
578 struct z8530_softc *z8530 = (struct z8530_softc*)sc;
579 struct uart_bas *bas;
580
581 bas = &sc->sc_bas;
582 mtx_lock_spin(&sc->sc_hwmtx);
583 while (!(uart_getmreg(bas, RR_BES) & BES_TXE))
584 ;
585 uart_setreg(bas, REG_DATA, sc->sc_txbuf[0]);
586 uart_barrier(bas);
587 sc->sc_txbusy = 1;
588 z8530->txidle = 1; /* Report UART_IPEND_TXIDLE again. */
589 mtx_unlock_spin(&sc->sc_hwmtx);
590 return (0);
591 }
Cache object: 6a087ffcfa1e53f09e92a6d3f5f0cca4
|