Deleted Added
sdiff udiff text old ( 232812 ) new ( 242273 )
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 $");
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
642 return (ipend);
643}
644
645static int
646oct16550_bus_param (struct uart_softc *sc, int baudrate, int databits,
647 int stopbits, int parity)
648{
649 struct uart_bas *bas;
650 int error;
651
652 bas = &sc->sc_bas;
653 uart_lock(sc->sc_hwmtx);
654 error = oct16550_param(bas, baudrate, databits, stopbits, parity);
655 uart_unlock(sc->sc_hwmtx);
656 return (error);
657}
658
659static int
660oct16550_bus_probe (struct uart_softc *sc)
661{
662 struct uart_bas *bas;
663 int error;
664
665 bas = &sc->sc_bas;
666 bas->rclk = uart_oct16550_class.uc_rclk = cvmx_sysinfo_get()->cpu_clock_hz;
667
668 error = oct16550_probe(bas);
669 if (error) {
670 return (error);
671 }
672
673 uart_setreg(bas, REG_MCR, (MCR_DTR | MCR_RTS));
674
675 /*
676 * Enable FIFOs. And check that the UART has them. If not, we're
677 * done. Since this is the first time we enable the FIFOs, we reset
678 * them.
679 */
680 oct16550_drain(bas, UART_DRAIN_TRANSMITTER);
681#define ENABLE_OCTEON_FIFO 1
682#ifdef ENABLE_OCTEON_FIFO
683 uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST);
684#endif
685 uart_barrier(bas);
686
687 oct16550_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
688
689 if (device_get_unit(sc->sc_dev)) {
690 device_set_desc(sc->sc_dev, "Octeon-16550 channel 1");
691 } else {
692 device_set_desc(sc->sc_dev, "Octeon-16550 channel 0");
693 }
694#ifdef ENABLE_OCTEON_FIFO
695 sc->sc_rxfifosz = 64;
696 sc->sc_txfifosz = 64;
697#else
698 sc->sc_rxfifosz = 1;
699 sc->sc_txfifosz = 1;
700#endif
701
702
703#if 0
704 /*
705 * XXX there are some issues related to hardware flow control and
706 * it's likely that uart(4) is the cause. This basicly needs more
707 * investigation, but we avoid using for hardware flow control
708 * until then.
709 */
710 /* 16650s or higher have automatic flow control. */
711 if (sc->sc_rxfifosz > 16) {
712 sc->sc_hwiflow = 1;
713 sc->sc_hwoflow = 1;
714 }
715#endif
716
717 return (0);
718}
719
720static int
721oct16550_bus_receive (struct uart_softc *sc)
722{
723 struct uart_bas *bas;
724 int xc;
725 uint8_t lsr;
726
727 bas = &sc->sc_bas;
728 uart_lock(sc->sc_hwmtx);
729 lsr = uart_getreg(bas, REG_LSR);
730
731 while (lsr & LSR_RXRDY) {
732 if (uart_rx_full(sc)) {
733 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
734 break;
735 }
736 xc = uart_getreg(bas, REG_DATA);
737 if (lsr & LSR_FE)
738 xc |= UART_STAT_FRAMERR;
739 if (lsr & LSR_PE)
740 xc |= UART_STAT_PARERR;
741 uart_rx_put(sc, xc);
742 lsr = uart_getreg(bas, REG_LSR);
743 }
744 /* Discard everything left in the Rx FIFO. */
745 /*
746 * First do a dummy read/discard anyway, in case the UART was lying to us.
747 * This problem was seen on board, when IIR said RBR, but LSR said no RXRDY
748 * Results in a stuck ipend loop.
749 */
750 (void)uart_getreg(bas, REG_DATA);
751 while (lsr & LSR_RXRDY) {
752 (void)uart_getreg(bas, REG_DATA);
753 uart_barrier(bas);
754 lsr = uart_getreg(bas, REG_LSR);
755 }
756 uart_unlock(sc->sc_hwmtx);
757 return (0);
758}
759
760static int
761oct16550_bus_setsig (struct uart_softc *sc, int sig)
762{
763 struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
764 struct uart_bas *bas;
765 uint32_t new, old;
766
767 bas = &sc->sc_bas;
768 do {
769 old = sc->sc_hwsig;
770 new = old;
771 if (sig & SER_DDTR) {
772 SIGCHG(sig & SER_DTR, new, SER_DTR,
773 SER_DDTR);
774 }
775 if (sig & SER_DRTS) {
776 SIGCHG(sig & SER_RTS, new, SER_RTS,
777 SER_DRTS);
778 }
779 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
780 uart_lock(sc->sc_hwmtx);
781 oct16550->mcr &= ~(MCR_DTR|MCR_RTS);
782 if (new & SER_DTR)
783 oct16550->mcr |= MCR_DTR;
784 if (new & SER_RTS)
785 oct16550->mcr |= MCR_RTS;
786 uart_setreg(bas, REG_MCR, oct16550->mcr);
787 uart_barrier(bas);
788 uart_unlock(sc->sc_hwmtx);
789 return (0);
790}
791
792static int
793oct16550_bus_transmit (struct uart_softc *sc)
794{
795 struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc;
796 struct uart_bas *bas;
797 int i;
798
799 bas = &sc->sc_bas;
800 uart_lock(sc->sc_hwmtx);
801#ifdef NO_UART_INTERRUPTS
802 for (i = 0; i < sc->sc_txdatasz; i++) {
803 oct16550_putc(bas, sc->sc_txbuf[i]);
804 }
805#else
806
807 oct16550_wait_txhr_empty(bas, 100, oct16550_delay(bas));
808 uart_setreg(bas, REG_IER, oct16550->ier | IER_ETXRDY);
809 uart_barrier(bas);
810
811 for (i = 0; i < sc->sc_txdatasz; i++) {
812 uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
813 uart_barrier(bas);
814 }
815 sc->sc_txbusy = 1;
816#endif
817 uart_unlock(sc->sc_hwmtx);
818 return (0);
819}