Deleted Added
full compact
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/*
28 * uart_dev_oct16550.c
29 *
30 * Derived from uart_dev_ns8250.c
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 *
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 *
53 *
54 */
55
56
57#include <sys/cdefs.h>
58__FBSDID("$FreeBSD: head/sys/mips/cavium/uart_dev_oct16550.c 232812 2012-03-11 06:17:49Z jmallett $");
58__FBSDID("$FreeBSD: head/sys/mips/cavium/uart_dev_oct16550.c 242273 2012-10-29 00:51:53Z jmallett $");
59
60#include <sys/param.h>
61#include <sys/systm.h>
62#include <sys/bus.h>
63#include <sys/conf.h>
64#include <machine/bus.h>
65#include <machine/pcpu.h>
66
67#include <dev/uart/uart.h>
68#include <dev/uart/uart_cpu.h>
69#include <dev/uart/uart_bus.h>
70
71#include <dev/ic/ns16550.h>
72
73#include <mips/cavium/octeon_pcmap_regs.h>
74
75#include <contrib/octeon-sdk/cvmx.h>
76
77#include "uart_if.h"
78
79/*
80 * Clear pending interrupts. THRE is cleared by reading IIR. Data
81 * that may have been received gets lost here.
82 */
83static void
84oct16550_clrint (struct uart_bas *bas)
85{
86 uint8_t iir;
87
88 iir = uart_getreg(bas, REG_IIR);
89 while ((iir & IIR_NOPEND) == 0) {
90 iir &= IIR_IMASK;
91 if (iir == IIR_RLS)
92 (void)uart_getreg(bas, REG_LSR);
93 else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
94 (void)uart_getreg(bas, REG_DATA);
95 else if (iir == IIR_MLSC)
96 (void)uart_getreg(bas, REG_MSR);
97 else if (iir == IIR_BUSY)
98 (void) uart_getreg(bas, REG_USR);
99 uart_barrier(bas);
100 iir = uart_getreg(bas, REG_IIR);
101 }
102}
103
104static int delay_changed = 1;
105
106static int
107oct16550_delay (struct uart_bas *bas)
108{
109 int divisor;
110 u_char lcr;
111 static int delay = 0;
112
113 if (!delay_changed) return delay;
114 delay_changed = 0;
115 lcr = uart_getreg(bas, REG_LCR);
116 uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
117 uart_barrier(bas);
118 divisor = uart_getreg(bas, REG_DLL) | (uart_getreg(bas, REG_DLH) << 8);
119 uart_barrier(bas);
120 uart_setreg(bas, REG_LCR, lcr);
121 uart_barrier(bas);
122
123 if(!bas->rclk)
124 return 10; /* return an approx delay value */
125
126 /* 1/10th the time to transmit 1 character (estimate). */
127 if (divisor <= 134)
128 return (16000000 * divisor / bas->rclk);
129 return (16000 * divisor / (bas->rclk / 1000));
130
131}
132
133static int
134oct16550_divisor (int rclk, int baudrate)
135{
136 int actual_baud, divisor;
137 int error;
138
139 if (baudrate == 0)
140 return (0);
141
142 divisor = (rclk / (baudrate << 3) + 1) >> 1;
143 if (divisor == 0 || divisor >= 65536)
144 return (0);
145 actual_baud = rclk / (divisor << 4);
146
147 /* 10 times error in percent: */
148 error = ((actual_baud - baudrate) * 2000 / baudrate + 1) >> 1;
149
150 /* 3.0% maximum error tolerance: */
151 if (error < -30 || error > 30)
152 return (0);
153
154 return (divisor);
155}
156
157static int
158oct16550_drain (struct uart_bas *bas, int what)
159{
160 int delay, limit;
161
162 delay = oct16550_delay(bas);
163
164 if (what & UART_DRAIN_TRANSMITTER) {
165 /*
166 * Pick an arbitrary high limit to avoid getting stuck in
167 * an infinite loop when the hardware is broken. Make the
168 * limit high enough to handle large FIFOs.
169 */
170 limit = 10*10*10*1024;
171 while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
172 DELAY(delay);
173 if (limit == 0) {
174 /* printf("oct16550: transmitter appears stuck... "); */
175 return (0);
176 }
177 }
178
179 if (what & UART_DRAIN_RECEIVER) {
180 /*
181 * Pick an arbitrary high limit to avoid getting stuck in
182 * an infinite loop when the hardware is broken. Make the
183 * limit high enough to handle large FIFOs and integrated
184 * UARTs. The HP rx2600 for example has 3 UARTs on the
185 * management board that tend to get a lot of data send
186 * to it when the UART is first activated.
187 */
188 limit=10*4096;
189 while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) {
190 (void)uart_getreg(bas, REG_DATA);
191 uart_barrier(bas);
192 DELAY(delay << 2);
193 }
194 if (limit == 0) {
195 /* printf("oct16550: receiver appears broken... "); */
196 return (EIO);
197 }
198 }
199
200 return (0);
201}
202
203/*
204 * We can only flush UARTs with FIFOs. UARTs without FIFOs should be
205 * drained. WARNING: this function clobbers the FIFO setting!
206 */
207static void
208oct16550_flush (struct uart_bas *bas, int what)
209{
210 uint8_t fcr;
211
212 fcr = FCR_ENABLE;
213 if (what & UART_FLUSH_TRANSMITTER)
214 fcr |= FCR_XMT_RST;
215 if (what & UART_FLUSH_RECEIVER)
216 fcr |= FCR_RCV_RST;
217 uart_setreg(bas, REG_FCR, fcr);
218 uart_barrier(bas);
219}
220
221static int
222oct16550_param (struct uart_bas *bas, int baudrate, int databits, int stopbits,
223 int parity)
224{
225 int divisor;
226 uint8_t lcr;
227
228 lcr = 0;
229 if (databits >= 8)
230 lcr |= LCR_8BITS;
231 else if (databits == 7)
232 lcr |= LCR_7BITS;
233 else if (databits == 6)
234 lcr |= LCR_6BITS;
235 else
236 lcr |= LCR_5BITS;
237 if (stopbits > 1)
238 lcr |= LCR_STOPB;
239 lcr |= parity << 3;
240
241 /* Set baudrate. */
242 if (baudrate > 0) {
243 divisor = oct16550_divisor(bas->rclk, baudrate);
244 if (divisor == 0)
245 return (EINVAL);
246 uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
247 uart_barrier(bas);
248 uart_setreg(bas, REG_DLL, divisor & 0xff);
249 uart_setreg(bas, REG_DLH, (divisor >> 8) & 0xff);
250 uart_barrier(bas);
251 delay_changed = 1;
252 }
253
254 /* Set LCR and clear DLAB. */
255 uart_setreg(bas, REG_LCR, lcr);
256 uart_barrier(bas);
257 return (0);
258}
259
260/*
261 * Low-level UART interface.
262 */
263static int oct16550_probe(struct uart_bas *bas);
264static void oct16550_init(struct uart_bas *bas, int, int, int, int);
265static void oct16550_term(struct uart_bas *bas);
266static void oct16550_putc(struct uart_bas *bas, int);
267static int oct16550_rxready(struct uart_bas *bas);
268static int oct16550_getc(struct uart_bas *bas, struct mtx *);
269
270struct uart_ops uart_oct16550_ops = {
271 .probe = oct16550_probe,
272 .init = oct16550_init,
273 .term = oct16550_term,
274 .putc = oct16550_putc,
275 .rxready = oct16550_rxready,
276 .getc = oct16550_getc,
277};
278
279static int
280oct16550_probe (struct uart_bas *bas)
281{
282 u_char val;
283
284 /* Check known 0 bits that don't depend on DLAB. */
285 val = uart_getreg(bas, REG_IIR);
286 if (val & 0x30)
287 return (ENXIO);
288 val = uart_getreg(bas, REG_MCR);
289 if (val & 0xc0)
290 return (ENXIO);
291 val = uart_getreg(bas, REG_USR);
292 if (val & 0xe0)
293 return (ENXIO);
294 return (0);
295}
296
297static void
298oct16550_init (struct uart_bas *bas, int baudrate, int databits, int stopbits,
299 int parity)
300{
301 u_char ier;
302
303 oct16550_param(bas, baudrate, databits, stopbits, parity);
304
305 /* Disable all interrupt sources. */
306 ier = uart_getreg(bas, REG_IER) & 0x0;
307 uart_setreg(bas, REG_IER, ier);
308 uart_barrier(bas);
309
310 /* Disable the FIFO (if present). */
311// uart_setreg(bas, REG_FCR, 0);
312 uart_barrier(bas);
313
314 /* Set RTS & DTR. */
315 uart_setreg(bas, REG_MCR, MCR_RTS | MCR_DTR);
316 uart_barrier(bas);
317
318 oct16550_clrint(bas);
319}
320
321static void
322oct16550_term (struct uart_bas *bas)
323{
324
325 /* Clear RTS & DTR. */
326 uart_setreg(bas, REG_MCR, 0);
327 uart_barrier(bas);
328}
329
330static inline void oct16550_wait_txhr_empty (struct uart_bas *bas, int limit, int delay)
331{
332 while (((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0) &&
333 ((uart_getreg(bas, REG_USR) & USR_TXFIFO_NOTFULL) == 0))
334 DELAY(delay);
335}
336
337static void
338oct16550_putc (struct uart_bas *bas, int c)
339{
340 int delay;
341
342 /* 1/10th the time to transmit 1 character (estimate). */
343 delay = oct16550_delay(bas);
344 oct16550_wait_txhr_empty(bas, 100, delay);
345 uart_setreg(bas, REG_DATA, c);
346 uart_barrier(bas);
347 oct16550_wait_txhr_empty(bas, 100, delay);
348}
349
350static int
351oct16550_rxready (struct uart_bas *bas)
352{
353
354 return ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) != 0 ? 1 : 0);
355}
356
357static int
358oct16550_getc (struct uart_bas *bas, struct mtx *hwmtx)
359{
360 int c, delay;
361
362 uart_lock(hwmtx);
363
364 /* 1/10th the time to transmit 1 character (estimate). */
365 delay = oct16550_delay(bas);
366
367 while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) {
368 uart_unlock(hwmtx);
369 DELAY(delay);
370 uart_lock(hwmtx);
371 }
372
373 c = uart_getreg(bas, REG_DATA);
374
375 uart_unlock(hwmtx);
376
377 return (c);
378}
379
380/*
381 * High-level UART interface.
382 */
383struct oct16550_softc {
384 struct uart_softc base;
385 uint8_t fcr;
386 uint8_t ier;
387 uint8_t mcr;
388};
389
390static int oct16550_bus_attach(struct uart_softc *);
391static int oct16550_bus_detach(struct uart_softc *);
392static int oct16550_bus_flush(struct uart_softc *, int);
393static int oct16550_bus_getsig(struct uart_softc *);
394static int oct16550_bus_ioctl(struct uart_softc *, int, intptr_t);
395static int oct16550_bus_ipend(struct uart_softc *);
396static int oct16550_bus_param(struct uart_softc *, int, int, int, int);
397static int oct16550_bus_probe(struct uart_softc *);
398static int oct16550_bus_receive(struct uart_softc *);
399static int oct16550_bus_setsig(struct uart_softc *, int);
400static int oct16550_bus_transmit(struct uart_softc *);
401
402static kobj_method_t oct16550_methods[] = {
403 KOBJMETHOD(uart_attach, oct16550_bus_attach),
404 KOBJMETHOD(uart_detach, oct16550_bus_detach),
405 KOBJMETHOD(uart_flush, oct16550_bus_flush),
406 KOBJMETHOD(uart_getsig, oct16550_bus_getsig),
407 KOBJMETHOD(uart_ioctl, oct16550_bus_ioctl),
408 KOBJMETHOD(uart_ipend, oct16550_bus_ipend),
409 KOBJMETHOD(uart_param, oct16550_bus_param),
410 KOBJMETHOD(uart_probe, oct16550_bus_probe),
411 KOBJMETHOD(uart_receive, oct16550_bus_receive),
412 KOBJMETHOD(uart_setsig, oct16550_bus_setsig),
413 KOBJMETHOD(uart_transmit, oct16550_bus_transmit),
414 { 0, 0 }
415};
416
417struct uart_class uart_oct16550_class = {
418 "oct16550 class",
419 oct16550_methods,
420 sizeof(struct oct16550_softc),
421 .uc_ops = &uart_oct16550_ops,
422 .uc_range = 8 << 3,
423 .uc_rclk = 0
424};
425
426#define SIGCHG(c, i, s, d) \
427 if (c) { \
428 i |= (i & s) ? s : s | d; \
429 } else { \
430 i = (i & s) ? (i & ~s) | d : i; \
431 }
432
433static int
434oct16550_bus_attach (struct uart_softc *sc)
435{
436 struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
437 struct uart_bas *bas;
438 int unit;
439
440 unit = device_get_unit(sc->sc_dev);
441 bas = &sc->sc_bas;
442
443 oct16550_drain(bas, UART_DRAIN_TRANSMITTER);
444 oct16550->mcr = uart_getreg(bas, REG_MCR);
445 oct16550->fcr = FCR_ENABLE | FCR_RX_HIGH;
446 uart_setreg(bas, REG_FCR, oct16550->fcr);
447 uart_barrier(bas);
448 oct16550_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
449
450 if (oct16550->mcr & MCR_DTR)
451 sc->sc_hwsig |= SER_DTR;
452 if (oct16550->mcr & MCR_RTS)
453 sc->sc_hwsig |= SER_RTS;
454 oct16550_bus_getsig(sc);
455
456 oct16550_clrint(bas);
457 oct16550->ier = uart_getreg(bas, REG_IER) & 0xf0;
458 oct16550->ier |= IER_EMSC | IER_ERLS | IER_ERXRDY;
459 uart_setreg(bas, REG_IER, oct16550->ier);
460 uart_barrier(bas);
461
462 return (0);
463}
464
465static int
466oct16550_bus_detach (struct uart_softc *sc)
467{
468 struct uart_bas *bas;
469 u_char ier;
470
471 bas = &sc->sc_bas;
472 ier = uart_getreg(bas, REG_IER) & 0xf0;
473 uart_setreg(bas, REG_IER, ier);
474 uart_barrier(bas);
475 oct16550_clrint(bas);
476 return (0);
477}
478
479static int
480oct16550_bus_flush (struct uart_softc *sc, int what)
481{
482 struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
483 struct uart_bas *bas;
484 int error;
485
486 bas = &sc->sc_bas;
487 uart_lock(sc->sc_hwmtx);
488 if (sc->sc_rxfifosz > 1) {
489 oct16550_flush(bas, what);
490 uart_setreg(bas, REG_FCR, oct16550->fcr);
491 uart_barrier(bas);
492 error = 0;
493 } else
494 error = oct16550_drain(bas, what);
495 uart_unlock(sc->sc_hwmtx);
496 return (error);
497}
498
499static int
500oct16550_bus_getsig (struct uart_softc *sc)
501{
502 uint32_t new, old, sig;
503 uint8_t msr;
504
505 do {
506 old = sc->sc_hwsig;
507 sig = old;
508 uart_lock(sc->sc_hwmtx);
509 msr = uart_getreg(&sc->sc_bas, REG_MSR);
510 uart_unlock(sc->sc_hwmtx);
511 SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR);
512 SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS);
513 SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD);
514 SIGCHG(msr & MSR_RI, sig, SER_RI, SER_DRI);
515 new = sig & ~SER_MASK_DELTA;
516 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
517 return (sig);
518}
519
520static int
521oct16550_bus_ioctl (struct uart_softc *sc, int request, intptr_t data)
522{
523 struct uart_bas *bas;
524 int baudrate, divisor, error;
525 uint8_t efr, lcr;
526
527 bas = &sc->sc_bas;
528 error = 0;
529 uart_lock(sc->sc_hwmtx);
530 switch (request) {
531 case UART_IOCTL_BREAK:
532 lcr = uart_getreg(bas, REG_LCR);
533 if (data)
534 lcr |= LCR_SBREAK;
535 else
536 lcr &= ~LCR_SBREAK;
537 uart_setreg(bas, REG_LCR, lcr);
538 uart_barrier(bas);
539 break;
540 case UART_IOCTL_IFLOW:
541 lcr = uart_getreg(bas, REG_LCR);
542 uart_barrier(bas);
543 uart_setreg(bas, REG_LCR, 0xbf);
544 uart_barrier(bas);
545 efr = uart_getreg(bas, REG_EFR);
546 if (data)
547 efr |= EFR_RTS;
548 else
549 efr &= ~EFR_RTS;
550 uart_setreg(bas, REG_EFR, efr);
551 uart_barrier(bas);
552 uart_setreg(bas, REG_LCR, lcr);
553 uart_barrier(bas);
554 break;
555 case UART_IOCTL_OFLOW:
556 lcr = uart_getreg(bas, REG_LCR);
557 uart_barrier(bas);
558 uart_setreg(bas, REG_LCR, 0xbf);
559 uart_barrier(bas);
560 efr = uart_getreg(bas, REG_EFR);
561 if (data)
562 efr |= EFR_CTS;
563 else
564 efr &= ~EFR_CTS;
565 uart_setreg(bas, REG_EFR, efr);
566 uart_barrier(bas);
567 uart_setreg(bas, REG_LCR, lcr);
568 uart_barrier(bas);
569 break;
570 case UART_IOCTL_BAUD:
571 lcr = uart_getreg(bas, REG_LCR);
572 uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
573 uart_barrier(bas);
574 divisor = uart_getreg(bas, REG_DLL) |
575 (uart_getreg(bas, REG_DLH) << 8);
576 uart_barrier(bas);
577 uart_setreg(bas, REG_LCR, lcr);
578 uart_barrier(bas);
579 baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0;
580 delay_changed = 1;
581 if (baudrate > 0)
582 *(int*)data = baudrate;
583 else
584 error = ENXIO;
585 break;
586 default:
587 error = EINVAL;
588 break;
589 }
590 uart_unlock(sc->sc_hwmtx);
591 return (error);
592}
593
594
595static int
596oct16550_bus_ipend(struct uart_softc *sc)
597{
598 struct uart_bas *bas;
599 int ipend = 0;
600 uint8_t iir, lsr;
601
602 bas = &sc->sc_bas;
603 uart_lock(sc->sc_hwmtx);
604
605 iir = uart_getreg(bas, REG_IIR) & IIR_IMASK;
606 if (iir != IIR_NOPEND) {
607
608 if (iir == IIR_RLS) {
609 lsr = uart_getreg(bas, REG_LSR);
610 if (lsr & LSR_OE)
611 ipend |= SER_INT_OVERRUN;
612 if (lsr & LSR_BI)
613 ipend |= SER_INT_BREAK;
614 if (lsr & LSR_RXRDY)
615 ipend |= SER_INT_RXREADY;
616
617 } else if (iir == IIR_RXRDY) {
618 ipend |= SER_INT_RXREADY;
619
620 } else if (iir == IIR_RXTOUT) {
621 ipend |= SER_INT_RXREADY;
622
623 } else if (iir == IIR_TXRDY) {
624 ipend |= SER_INT_TXIDLE;
625
626 } else if (iir == IIR_MLSC) {
627 ipend |= SER_INT_SIGCHG;
628
629 } else if (iir == IIR_BUSY) {
630 (void) uart_getreg(bas, REG_USR);
631 }
632 }
633 uart_unlock(sc->sc_hwmtx);
634
635//#define OCTEON_VISUAL_UART 1
636#ifdef OCTEON_VISUAL_UART
637 static int where1 = 0;
638
639 if (ipend) octeon_led_run_wheel(&where1, 6 + device_get_unit(sc->sc_dev));
640#endif
641
635 return (ipend);
636}
637
638static int
639oct16550_bus_param (struct uart_softc *sc, int baudrate, int databits,
640 int stopbits, int parity)
641{
642 struct uart_bas *bas;
643 int error;
644
645 bas = &sc->sc_bas;
646 uart_lock(sc->sc_hwmtx);
647 error = oct16550_param(bas, baudrate, databits, stopbits, parity);
648 uart_unlock(sc->sc_hwmtx);
649 return (error);
650}
651
652static int
653oct16550_bus_probe (struct uart_softc *sc)
654{
655 struct uart_bas *bas;
656 int error;
657
658 bas = &sc->sc_bas;
659 bas->rclk = uart_oct16550_class.uc_rclk = cvmx_sysinfo_get()->cpu_clock_hz;
660
661 error = oct16550_probe(bas);
662 if (error) {
663 return (error);
664 }
665
666 uart_setreg(bas, REG_MCR, (MCR_DTR | MCR_RTS));
667
668 /*
669 * Enable FIFOs. And check that the UART has them. If not, we're
670 * done. Since this is the first time we enable the FIFOs, we reset
671 * them.
672 */
673 oct16550_drain(bas, UART_DRAIN_TRANSMITTER);
674#define ENABLE_OCTEON_FIFO 1
675#ifdef ENABLE_OCTEON_FIFO
676 uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST);
677#endif
678 uart_barrier(bas);
679
680 oct16550_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
681
682 if (device_get_unit(sc->sc_dev)) {
683 device_set_desc(sc->sc_dev, "Octeon-16550 channel 1");
684 } else {
685 device_set_desc(sc->sc_dev, "Octeon-16550 channel 0");
686 }
687#ifdef ENABLE_OCTEON_FIFO
688 sc->sc_rxfifosz = 64;
689 sc->sc_txfifosz = 64;
690#else
691 sc->sc_rxfifosz = 1;
692 sc->sc_txfifosz = 1;
693#endif
694
695
696#if 0
697 /*
698 * XXX there are some issues related to hardware flow control and
699 * it's likely that uart(4) is the cause. This basicly needs more
700 * investigation, but we avoid using for hardware flow control
701 * until then.
702 */
703 /* 16650s or higher have automatic flow control. */
704 if (sc->sc_rxfifosz > 16) {
705 sc->sc_hwiflow = 1;
706 sc->sc_hwoflow = 1;
707 }
708#endif
709
710 return (0);
711}
712
713static int
714oct16550_bus_receive (struct uart_softc *sc)
715{
716 struct uart_bas *bas;
717 int xc;
718 uint8_t lsr;
719
720 bas = &sc->sc_bas;
721 uart_lock(sc->sc_hwmtx);
722 lsr = uart_getreg(bas, REG_LSR);
723
724 while (lsr & LSR_RXRDY) {
725 if (uart_rx_full(sc)) {
726 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
727 break;
728 }
729 xc = uart_getreg(bas, REG_DATA);
730 if (lsr & LSR_FE)
731 xc |= UART_STAT_FRAMERR;
732 if (lsr & LSR_PE)
733 xc |= UART_STAT_PARERR;
734 uart_rx_put(sc, xc);
735 lsr = uart_getreg(bas, REG_LSR);
736 }
737 /* Discard everything left in the Rx FIFO. */
738 /*
739 * First do a dummy read/discard anyway, in case the UART was lying to us.
740 * This problem was seen on board, when IIR said RBR, but LSR said no RXRDY
741 * Results in a stuck ipend loop.
742 */
743 (void)uart_getreg(bas, REG_DATA);
744 while (lsr & LSR_RXRDY) {
745 (void)uart_getreg(bas, REG_DATA);
746 uart_barrier(bas);
747 lsr = uart_getreg(bas, REG_LSR);
748 }
749 uart_unlock(sc->sc_hwmtx);
750 return (0);
751}
752
753static int
754oct16550_bus_setsig (struct uart_softc *sc, int sig)
755{
756 struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
757 struct uart_bas *bas;
758 uint32_t new, old;
759
760 bas = &sc->sc_bas;
761 do {
762 old = sc->sc_hwsig;
763 new = old;
764 if (sig & SER_DDTR) {
765 SIGCHG(sig & SER_DTR, new, SER_DTR,
766 SER_DDTR);
767 }
768 if (sig & SER_DRTS) {
769 SIGCHG(sig & SER_RTS, new, SER_RTS,
770 SER_DRTS);
771 }
772 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
773 uart_lock(sc->sc_hwmtx);
774 oct16550->mcr &= ~(MCR_DTR|MCR_RTS);
775 if (new & SER_DTR)
776 oct16550->mcr |= MCR_DTR;
777 if (new & SER_RTS)
778 oct16550->mcr |= MCR_RTS;
779 uart_setreg(bas, REG_MCR, oct16550->mcr);
780 uart_barrier(bas);
781 uart_unlock(sc->sc_hwmtx);
782 return (0);
783}
784
785static int
786oct16550_bus_transmit (struct uart_softc *sc)
787{
788 struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
789 struct uart_bas *bas;
790 int i;
791
792 bas = &sc->sc_bas;
793 uart_lock(sc->sc_hwmtx);
794#ifdef NO_UART_INTERRUPTS
795 for (i = 0; i < sc->sc_txdatasz; i++) {
796 oct16550_putc(bas, sc->sc_txbuf[i]);
797 }
798#else
799
800 oct16550_wait_txhr_empty(bas, 100, oct16550_delay(bas));
801 uart_setreg(bas, REG_IER, oct16550->ier | IER_ETXRDY);
802 uart_barrier(bas);
803
804 for (i = 0; i < sc->sc_txdatasz; i++) {
805 uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
806 uart_barrier(bas);
807 }
808 sc->sc_txbusy = 1;
809#endif
810 uart_unlock(sc->sc_hwmtx);
811 return (0);
812}