1194150Simp/*- 2194150Simp * Copyright (c) 2003 Marcel Moolenaar 3194150Simp * All rights reserved. 4194150Simp * 5194150Simp * Redistribution and use in source and binary forms, with or without 6194150Simp * modification, are permitted provided that the following conditions 7194150Simp * are met: 8194150Simp * 9194150Simp * 1. Redistributions of source code must retain the above copyright 10194150Simp * notice, this list of conditions and the following disclaimer. 11194150Simp * 2. Redistributions in binary form must reproduce the above copyright 12194150Simp * notice, this list of conditions and the following disclaimer in the 13194150Simp * documentation and/or other materials provided with the distribution. 14194150Simp * 15194150Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16194150Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17194150Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18194150Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19194150Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20194150Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21194150Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22194150Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23194150Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24194150Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25194150Simp */ 26194150Simp 27194150Simp/* 28194150Simp * uart_dev_oct16550.c 29194150Simp * 30194150Simp * Derived from uart_dev_ns8250.c 31194150Simp * 32194150Simp * Redistribution and use in source and binary forms, with or without 33194150Simp * modification, are permitted provided that the following conditions 34194150Simp * are met: 35194150Simp * 36194150Simp * 1. Redistributions of source code must retain the above copyright 37194150Simp * notice, this list of conditions and the following disclaimer. 38194150Simp * 2. Redistributions in binary form must reproduce the above copyright 39194150Simp * notice, this list of conditions and the following disclaimer in the 40194150Simp * documentation and/or other materials provided with the distribution. 41194150Simp * 42194150Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 43194150Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 44194150Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 45194150Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 46194150Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47194150Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 48194150Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 49194150Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50194150Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 51194150Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52194150Simp * 53194150Simp * 54194150Simp */ 55194150Simp 56194150Simp 57194150Simp#include <sys/cdefs.h> 58194150Simp__FBSDID("$FreeBSD$"); 59194150Simp 60194150Simp#include <sys/param.h> 61194150Simp#include <sys/systm.h> 62194150Simp#include <sys/bus.h> 63194150Simp#include <sys/conf.h> 64194150Simp#include <machine/bus.h> 65194150Simp#include <machine/pcpu.h> 66194150Simp 67194150Simp#include <dev/uart/uart.h> 68194150Simp#include <dev/uart/uart_cpu.h> 69194150Simp#include <dev/uart/uart_bus.h> 70194150Simp 71194150Simp#include <dev/ic/ns16550.h> 72194150Simp 73202063Simp#include <mips/cavium/octeon_pcmap_regs.h> 74194150Simp 75210311Sjmallett#include <contrib/octeon-sdk/cvmx.h> 76210311Sjmallett 77194150Simp#include "uart_if.h" 78194150Simp 79194150Simp/* 80194150Simp * Clear pending interrupts. THRE is cleared by reading IIR. Data 81194150Simp * that may have been received gets lost here. 82194150Simp */ 83194150Simpstatic void 84194150Simpoct16550_clrint (struct uart_bas *bas) 85194150Simp{ 86194150Simp uint8_t iir; 87194150Simp 88194150Simp iir = uart_getreg(bas, REG_IIR); 89194150Simp while ((iir & IIR_NOPEND) == 0) { 90194150Simp iir &= IIR_IMASK; 91194150Simp if (iir == IIR_RLS) 92194150Simp (void)uart_getreg(bas, REG_LSR); 93194150Simp else if (iir == IIR_RXRDY || iir == IIR_RXTOUT) 94194150Simp (void)uart_getreg(bas, REG_DATA); 95194150Simp else if (iir == IIR_MLSC) 96194150Simp (void)uart_getreg(bas, REG_MSR); 97194150Simp else if (iir == IIR_BUSY) 98194150Simp (void) uart_getreg(bas, REG_USR); 99194150Simp uart_barrier(bas); 100194150Simp iir = uart_getreg(bas, REG_IIR); 101194150Simp } 102194150Simp} 103194150Simp 104194150Simpstatic int delay_changed = 1; 105194150Simp 106194150Simpstatic int 107194150Simpoct16550_delay (struct uart_bas *bas) 108194150Simp{ 109194150Simp int divisor; 110194150Simp u_char lcr; 111194150Simp static int delay = 0; 112194150Simp 113194150Simp if (!delay_changed) return delay; 114194150Simp delay_changed = 0; 115194150Simp lcr = uart_getreg(bas, REG_LCR); 116194150Simp uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); 117194150Simp uart_barrier(bas); 118194150Simp divisor = uart_getreg(bas, REG_DLL) | (uart_getreg(bas, REG_DLH) << 8); 119194150Simp uart_barrier(bas); 120194150Simp uart_setreg(bas, REG_LCR, lcr); 121194150Simp uart_barrier(bas); 122194150Simp 123194150Simp if(!bas->rclk) 124194150Simp return 10; /* return an approx delay value */ 125194150Simp 126194150Simp /* 1/10th the time to transmit 1 character (estimate). */ 127194150Simp if (divisor <= 134) 128194150Simp return (16000000 * divisor / bas->rclk); 129194150Simp return (16000 * divisor / (bas->rclk / 1000)); 130194150Simp 131194150Simp} 132194150Simp 133194150Simpstatic int 134194150Simpoct16550_divisor (int rclk, int baudrate) 135194150Simp{ 136194150Simp int actual_baud, divisor; 137194150Simp int error; 138194150Simp 139194150Simp if (baudrate == 0) 140194150Simp return (0); 141194150Simp 142194150Simp divisor = (rclk / (baudrate << 3) + 1) >> 1; 143194150Simp if (divisor == 0 || divisor >= 65536) 144194150Simp return (0); 145194150Simp actual_baud = rclk / (divisor << 4); 146194150Simp 147194150Simp /* 10 times error in percent: */ 148194150Simp error = ((actual_baud - baudrate) * 2000 / baudrate + 1) >> 1; 149194150Simp 150194150Simp /* 3.0% maximum error tolerance: */ 151194150Simp if (error < -30 || error > 30) 152194150Simp return (0); 153194150Simp 154194150Simp return (divisor); 155194150Simp} 156194150Simp 157194150Simpstatic int 158194150Simpoct16550_drain (struct uart_bas *bas, int what) 159194150Simp{ 160194150Simp int delay, limit; 161194150Simp 162194150Simp delay = oct16550_delay(bas); 163194150Simp 164194150Simp if (what & UART_DRAIN_TRANSMITTER) { 165194150Simp /* 166194150Simp * Pick an arbitrary high limit to avoid getting stuck in 167194150Simp * an infinite loop when the hardware is broken. Make the 168194150Simp * limit high enough to handle large FIFOs. 169194150Simp */ 170194150Simp limit = 10*10*10*1024; 171194150Simp while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit) 172194150Simp DELAY(delay); 173194150Simp if (limit == 0) { 174194150Simp /* printf("oct16550: transmitter appears stuck... "); */ 175194150Simp return (0); 176194150Simp } 177194150Simp } 178194150Simp 179194150Simp if (what & UART_DRAIN_RECEIVER) { 180194150Simp /* 181194150Simp * Pick an arbitrary high limit to avoid getting stuck in 182194150Simp * an infinite loop when the hardware is broken. Make the 183194150Simp * limit high enough to handle large FIFOs and integrated 184194150Simp * UARTs. The HP rx2600 for example has 3 UARTs on the 185194150Simp * management board that tend to get a lot of data send 186194150Simp * to it when the UART is first activated. 187194150Simp */ 188194150Simp limit=10*4096; 189194150Simp while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) { 190194150Simp (void)uart_getreg(bas, REG_DATA); 191194150Simp uart_barrier(bas); 192194150Simp DELAY(delay << 2); 193194150Simp } 194194150Simp if (limit == 0) { 195194150Simp /* printf("oct16550: receiver appears broken... "); */ 196194150Simp return (EIO); 197194150Simp } 198194150Simp } 199194150Simp 200194150Simp return (0); 201194150Simp} 202194150Simp 203194150Simp/* 204194150Simp * We can only flush UARTs with FIFOs. UARTs without FIFOs should be 205194150Simp * drained. WARNING: this function clobbers the FIFO setting! 206194150Simp */ 207194150Simpstatic void 208194150Simpoct16550_flush (struct uart_bas *bas, int what) 209194150Simp{ 210194150Simp uint8_t fcr; 211194150Simp 212194150Simp fcr = FCR_ENABLE; 213194150Simp if (what & UART_FLUSH_TRANSMITTER) 214194150Simp fcr |= FCR_XMT_RST; 215194150Simp if (what & UART_FLUSH_RECEIVER) 216194150Simp fcr |= FCR_RCV_RST; 217194150Simp uart_setreg(bas, REG_FCR, fcr); 218194150Simp uart_barrier(bas); 219194150Simp} 220194150Simp 221194150Simpstatic int 222194150Simpoct16550_param (struct uart_bas *bas, int baudrate, int databits, int stopbits, 223194150Simp int parity) 224194150Simp{ 225194150Simp int divisor; 226194150Simp uint8_t lcr; 227194150Simp 228194150Simp lcr = 0; 229194150Simp if (databits >= 8) 230194150Simp lcr |= LCR_8BITS; 231194150Simp else if (databits == 7) 232194150Simp lcr |= LCR_7BITS; 233194150Simp else if (databits == 6) 234194150Simp lcr |= LCR_6BITS; 235194150Simp else 236194150Simp lcr |= LCR_5BITS; 237194150Simp if (stopbits > 1) 238194150Simp lcr |= LCR_STOPB; 239194150Simp lcr |= parity << 3; 240194150Simp 241194150Simp /* Set baudrate. */ 242194150Simp if (baudrate > 0) { 243194150Simp divisor = oct16550_divisor(bas->rclk, baudrate); 244194150Simp if (divisor == 0) 245194150Simp return (EINVAL); 246194150Simp uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); 247194150Simp uart_barrier(bas); 248194150Simp uart_setreg(bas, REG_DLL, divisor & 0xff); 249194150Simp uart_setreg(bas, REG_DLH, (divisor >> 8) & 0xff); 250194150Simp uart_barrier(bas); 251194150Simp delay_changed = 1; 252194150Simp } 253194150Simp 254194150Simp /* Set LCR and clear DLAB. */ 255194150Simp uart_setreg(bas, REG_LCR, lcr); 256194150Simp uart_barrier(bas); 257194150Simp return (0); 258194150Simp} 259194150Simp 260194150Simp/* 261194150Simp * Low-level UART interface. 262194150Simp */ 263194150Simpstatic int oct16550_probe(struct uart_bas *bas); 264194150Simpstatic void oct16550_init(struct uart_bas *bas, int, int, int, int); 265194150Simpstatic void oct16550_term(struct uart_bas *bas); 266194150Simpstatic void oct16550_putc(struct uart_bas *bas, int); 267194150Simpstatic int oct16550_rxready(struct uart_bas *bas); 268194150Simpstatic int oct16550_getc(struct uart_bas *bas, struct mtx *); 269194150Simp 270194150Simpstruct uart_ops uart_oct16550_ops = { 271194150Simp .probe = oct16550_probe, 272194150Simp .init = oct16550_init, 273194150Simp .term = oct16550_term, 274194150Simp .putc = oct16550_putc, 275194150Simp .rxready = oct16550_rxready, 276194150Simp .getc = oct16550_getc, 277194150Simp}; 278194150Simp 279194150Simpstatic int 280194150Simpoct16550_probe (struct uart_bas *bas) 281194150Simp{ 282194150Simp u_char val; 283194150Simp 284194150Simp /* Check known 0 bits that don't depend on DLAB. */ 285194150Simp val = uart_getreg(bas, REG_IIR); 286194150Simp if (val & 0x30) 287194150Simp return (ENXIO); 288194150Simp val = uart_getreg(bas, REG_MCR); 289194150Simp if (val & 0xc0) 290194150Simp return (ENXIO); 291194150Simp val = uart_getreg(bas, REG_USR); 292194150Simp if (val & 0xe0) 293194150Simp return (ENXIO); 294194150Simp return (0); 295194150Simp} 296194150Simp 297194150Simpstatic void 298194150Simpoct16550_init (struct uart_bas *bas, int baudrate, int databits, int stopbits, 299194150Simp int parity) 300194150Simp{ 301194150Simp u_char ier; 302194150Simp 303194150Simp oct16550_param(bas, baudrate, databits, stopbits, parity); 304194150Simp 305194150Simp /* Disable all interrupt sources. */ 306194150Simp ier = uart_getreg(bas, REG_IER) & 0x0; 307194150Simp uart_setreg(bas, REG_IER, ier); 308194150Simp uart_barrier(bas); 309194150Simp 310194150Simp /* Disable the FIFO (if present). */ 311194150Simp// uart_setreg(bas, REG_FCR, 0); 312194150Simp uart_barrier(bas); 313194150Simp 314194150Simp /* Set RTS & DTR. */ 315194150Simp uart_setreg(bas, REG_MCR, MCR_RTS | MCR_DTR); 316194150Simp uart_barrier(bas); 317194150Simp 318194150Simp oct16550_clrint(bas); 319194150Simp} 320194150Simp 321194150Simpstatic void 322194150Simpoct16550_term (struct uart_bas *bas) 323194150Simp{ 324194150Simp 325194150Simp /* Clear RTS & DTR. */ 326194150Simp uart_setreg(bas, REG_MCR, 0); 327194150Simp uart_barrier(bas); 328194150Simp} 329194150Simp 330194150Simpstatic inline void oct16550_wait_txhr_empty (struct uart_bas *bas, int limit, int delay) 331194150Simp{ 332194150Simp while (((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0) && 333194150Simp ((uart_getreg(bas, REG_USR) & USR_TXFIFO_NOTFULL) == 0)) 334194150Simp DELAY(delay); 335194150Simp} 336194150Simp 337194150Simpstatic void 338194150Simpoct16550_putc (struct uart_bas *bas, int c) 339194150Simp{ 340194150Simp int delay; 341194150Simp 342194150Simp /* 1/10th the time to transmit 1 character (estimate). */ 343194150Simp delay = oct16550_delay(bas); 344194150Simp oct16550_wait_txhr_empty(bas, 100, delay); 345194150Simp uart_setreg(bas, REG_DATA, c); 346194150Simp uart_barrier(bas); 347194150Simp oct16550_wait_txhr_empty(bas, 100, delay); 348194150Simp} 349194150Simp 350194150Simpstatic int 351194150Simpoct16550_rxready (struct uart_bas *bas) 352194150Simp{ 353194150Simp 354194150Simp return ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) != 0 ? 1 : 0); 355194150Simp} 356194150Simp 357194150Simpstatic int 358194150Simpoct16550_getc (struct uart_bas *bas, struct mtx *hwmtx) 359194150Simp{ 360194150Simp int c, delay; 361194150Simp 362194150Simp uart_lock(hwmtx); 363194150Simp 364194150Simp /* 1/10th the time to transmit 1 character (estimate). */ 365194150Simp delay = oct16550_delay(bas); 366194150Simp 367194150Simp while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) { 368194150Simp uart_unlock(hwmtx); 369194150Simp DELAY(delay); 370194150Simp uart_lock(hwmtx); 371194150Simp } 372194150Simp 373194150Simp c = uart_getreg(bas, REG_DATA); 374194150Simp 375194150Simp uart_unlock(hwmtx); 376194150Simp 377194150Simp return (c); 378194150Simp} 379194150Simp 380194150Simp/* 381194150Simp * High-level UART interface. 382194150Simp */ 383194150Simpstruct oct16550_softc { 384194150Simp struct uart_softc base; 385194150Simp uint8_t fcr; 386194150Simp uint8_t ier; 387194150Simp uint8_t mcr; 388194150Simp}; 389194150Simp 390194150Simpstatic int oct16550_bus_attach(struct uart_softc *); 391194150Simpstatic int oct16550_bus_detach(struct uart_softc *); 392194150Simpstatic int oct16550_bus_flush(struct uart_softc *, int); 393194150Simpstatic int oct16550_bus_getsig(struct uart_softc *); 394194150Simpstatic int oct16550_bus_ioctl(struct uart_softc *, int, intptr_t); 395194150Simpstatic int oct16550_bus_ipend(struct uart_softc *); 396194150Simpstatic int oct16550_bus_param(struct uart_softc *, int, int, int, int); 397194150Simpstatic int oct16550_bus_probe(struct uart_softc *); 398194150Simpstatic int oct16550_bus_receive(struct uart_softc *); 399194150Simpstatic int oct16550_bus_setsig(struct uart_softc *, int); 400194150Simpstatic int oct16550_bus_transmit(struct uart_softc *); 401194150Simp 402194150Simpstatic kobj_method_t oct16550_methods[] = { 403194150Simp KOBJMETHOD(uart_attach, oct16550_bus_attach), 404194150Simp KOBJMETHOD(uart_detach, oct16550_bus_detach), 405194150Simp KOBJMETHOD(uart_flush, oct16550_bus_flush), 406194150Simp KOBJMETHOD(uart_getsig, oct16550_bus_getsig), 407194150Simp KOBJMETHOD(uart_ioctl, oct16550_bus_ioctl), 408194150Simp KOBJMETHOD(uart_ipend, oct16550_bus_ipend), 409194150Simp KOBJMETHOD(uart_param, oct16550_bus_param), 410194150Simp KOBJMETHOD(uart_probe, oct16550_bus_probe), 411194150Simp KOBJMETHOD(uart_receive, oct16550_bus_receive), 412194150Simp KOBJMETHOD(uart_setsig, oct16550_bus_setsig), 413194150Simp KOBJMETHOD(uart_transmit, oct16550_bus_transmit), 414194150Simp { 0, 0 } 415194150Simp}; 416194150Simp 417194150Simpstruct uart_class uart_oct16550_class = { 418194150Simp "oct16550 class", 419194150Simp oct16550_methods, 420194150Simp sizeof(struct oct16550_softc), 421194150Simp .uc_ops = &uart_oct16550_ops, 422213345Sjmallett .uc_range = 8 << 3, 423194150Simp .uc_rclk = 0 424194150Simp}; 425194150Simp 426194150Simp#define SIGCHG(c, i, s, d) \ 427194150Simp if (c) { \ 428194150Simp i |= (i & s) ? s : s | d; \ 429194150Simp } else { \ 430194150Simp i = (i & s) ? (i & ~s) | d : i; \ 431194150Simp } 432194150Simp 433194150Simpstatic int 434194150Simpoct16550_bus_attach (struct uart_softc *sc) 435194150Simp{ 436194150Simp struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc; 437194150Simp struct uart_bas *bas; 438194150Simp int unit; 439194150Simp 440194150Simp unit = device_get_unit(sc->sc_dev); 441194150Simp bas = &sc->sc_bas; 442194150Simp 443194150Simp oct16550_drain(bas, UART_DRAIN_TRANSMITTER); 444194150Simp oct16550->mcr = uart_getreg(bas, REG_MCR); 445194150Simp oct16550->fcr = FCR_ENABLE | FCR_RX_HIGH; 446194150Simp uart_setreg(bas, REG_FCR, oct16550->fcr); 447194150Simp uart_barrier(bas); 448194150Simp oct16550_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); 449194150Simp 450194150Simp if (oct16550->mcr & MCR_DTR) 451194150Simp sc->sc_hwsig |= SER_DTR; 452194150Simp if (oct16550->mcr & MCR_RTS) 453194150Simp sc->sc_hwsig |= SER_RTS; 454194150Simp oct16550_bus_getsig(sc); 455194150Simp 456194150Simp oct16550_clrint(bas); 457194150Simp oct16550->ier = uart_getreg(bas, REG_IER) & 0xf0; 458194150Simp oct16550->ier |= IER_EMSC | IER_ERLS | IER_ERXRDY; 459194150Simp uart_setreg(bas, REG_IER, oct16550->ier); 460194150Simp uart_barrier(bas); 461194150Simp 462194150Simp return (0); 463194150Simp} 464194150Simp 465194150Simpstatic int 466194150Simpoct16550_bus_detach (struct uart_softc *sc) 467194150Simp{ 468194150Simp struct uart_bas *bas; 469194150Simp u_char ier; 470194150Simp 471194150Simp bas = &sc->sc_bas; 472194150Simp ier = uart_getreg(bas, REG_IER) & 0xf0; 473194150Simp uart_setreg(bas, REG_IER, ier); 474194150Simp uart_barrier(bas); 475194150Simp oct16550_clrint(bas); 476194150Simp return (0); 477194150Simp} 478194150Simp 479194150Simpstatic int 480194150Simpoct16550_bus_flush (struct uart_softc *sc, int what) 481194150Simp{ 482194150Simp struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc; 483194150Simp struct uart_bas *bas; 484194150Simp int error; 485194150Simp 486194150Simp bas = &sc->sc_bas; 487194150Simp uart_lock(sc->sc_hwmtx); 488194150Simp if (sc->sc_rxfifosz > 1) { 489194150Simp oct16550_flush(bas, what); 490194150Simp uart_setreg(bas, REG_FCR, oct16550->fcr); 491194150Simp uart_barrier(bas); 492194150Simp error = 0; 493194150Simp } else 494194150Simp error = oct16550_drain(bas, what); 495194150Simp uart_unlock(sc->sc_hwmtx); 496194150Simp return (error); 497194150Simp} 498194150Simp 499194150Simpstatic int 500194150Simpoct16550_bus_getsig (struct uart_softc *sc) 501194150Simp{ 502194150Simp uint32_t new, old, sig; 503194150Simp uint8_t msr; 504194150Simp 505194150Simp do { 506194150Simp old = sc->sc_hwsig; 507194150Simp sig = old; 508194150Simp uart_lock(sc->sc_hwmtx); 509194150Simp msr = uart_getreg(&sc->sc_bas, REG_MSR); 510194150Simp uart_unlock(sc->sc_hwmtx); 511194150Simp SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR); 512194150Simp SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS); 513194150Simp SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD); 514194150Simp SIGCHG(msr & MSR_RI, sig, SER_RI, SER_DRI); 515194150Simp new = sig & ~SER_MASK_DELTA; 516194150Simp } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 517194150Simp return (sig); 518194150Simp} 519194150Simp 520194150Simpstatic int 521194150Simpoct16550_bus_ioctl (struct uart_softc *sc, int request, intptr_t data) 522194150Simp{ 523194150Simp struct uart_bas *bas; 524194150Simp int baudrate, divisor, error; 525194150Simp uint8_t efr, lcr; 526194150Simp 527194150Simp bas = &sc->sc_bas; 528194150Simp error = 0; 529194150Simp uart_lock(sc->sc_hwmtx); 530194150Simp switch (request) { 531194150Simp case UART_IOCTL_BREAK: 532194150Simp lcr = uart_getreg(bas, REG_LCR); 533194150Simp if (data) 534194150Simp lcr |= LCR_SBREAK; 535194150Simp else 536194150Simp lcr &= ~LCR_SBREAK; 537194150Simp uart_setreg(bas, REG_LCR, lcr); 538194150Simp uart_barrier(bas); 539194150Simp break; 540194150Simp case UART_IOCTL_IFLOW: 541194150Simp lcr = uart_getreg(bas, REG_LCR); 542194150Simp uart_barrier(bas); 543194150Simp uart_setreg(bas, REG_LCR, 0xbf); 544194150Simp uart_barrier(bas); 545194150Simp efr = uart_getreg(bas, REG_EFR); 546194150Simp if (data) 547194150Simp efr |= EFR_RTS; 548194150Simp else 549194150Simp efr &= ~EFR_RTS; 550194150Simp uart_setreg(bas, REG_EFR, efr); 551194150Simp uart_barrier(bas); 552194150Simp uart_setreg(bas, REG_LCR, lcr); 553194150Simp uart_barrier(bas); 554194150Simp break; 555194150Simp case UART_IOCTL_OFLOW: 556194150Simp lcr = uart_getreg(bas, REG_LCR); 557194150Simp uart_barrier(bas); 558194150Simp uart_setreg(bas, REG_LCR, 0xbf); 559194150Simp uart_barrier(bas); 560194150Simp efr = uart_getreg(bas, REG_EFR); 561194150Simp if (data) 562194150Simp efr |= EFR_CTS; 563194150Simp else 564194150Simp efr &= ~EFR_CTS; 565194150Simp uart_setreg(bas, REG_EFR, efr); 566194150Simp uart_barrier(bas); 567194150Simp uart_setreg(bas, REG_LCR, lcr); 568194150Simp uart_barrier(bas); 569194150Simp break; 570194150Simp case UART_IOCTL_BAUD: 571194150Simp lcr = uart_getreg(bas, REG_LCR); 572194150Simp uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); 573194150Simp uart_barrier(bas); 574194150Simp divisor = uart_getreg(bas, REG_DLL) | 575194150Simp (uart_getreg(bas, REG_DLH) << 8); 576194150Simp uart_barrier(bas); 577194150Simp uart_setreg(bas, REG_LCR, lcr); 578194150Simp uart_barrier(bas); 579194150Simp baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0; 580194150Simp delay_changed = 1; 581194150Simp if (baudrate > 0) 582194150Simp *(int*)data = baudrate; 583194150Simp else 584194150Simp error = ENXIO; 585194150Simp break; 586194150Simp default: 587194150Simp error = EINVAL; 588194150Simp break; 589194150Simp } 590194150Simp uart_unlock(sc->sc_hwmtx); 591194150Simp return (error); 592194150Simp} 593194150Simp 594194150Simp 595194150Simpstatic int 596194150Simpoct16550_bus_ipend(struct uart_softc *sc) 597194150Simp{ 598194150Simp struct uart_bas *bas; 599194150Simp int ipend = 0; 600194150Simp uint8_t iir, lsr; 601194150Simp 602194150Simp bas = &sc->sc_bas; 603194150Simp uart_lock(sc->sc_hwmtx); 604194150Simp 605194150Simp iir = uart_getreg(bas, REG_IIR) & IIR_IMASK; 606194150Simp if (iir != IIR_NOPEND) { 607194150Simp 608194150Simp if (iir == IIR_RLS) { 609194150Simp lsr = uart_getreg(bas, REG_LSR); 610194150Simp if (lsr & LSR_OE) 611194150Simp ipend |= SER_INT_OVERRUN; 612194150Simp if (lsr & LSR_BI) 613194150Simp ipend |= SER_INT_BREAK; 614194150Simp if (lsr & LSR_RXRDY) 615194150Simp ipend |= SER_INT_RXREADY; 616194150Simp 617194150Simp } else if (iir == IIR_RXRDY) { 618194150Simp ipend |= SER_INT_RXREADY; 619194150Simp 620194150Simp } else if (iir == IIR_RXTOUT) { 621194150Simp ipend |= SER_INT_RXREADY; 622194150Simp 623194150Simp } else if (iir == IIR_TXRDY) { 624194150Simp ipend |= SER_INT_TXIDLE; 625194150Simp 626194150Simp } else if (iir == IIR_MLSC) { 627194150Simp ipend |= SER_INT_SIGCHG; 628194150Simp 629194150Simp } else if (iir == IIR_BUSY) { 630194150Simp (void) uart_getreg(bas, REG_USR); 631194150Simp } 632194150Simp } 633194150Simp uart_unlock(sc->sc_hwmtx); 634194150Simp 635207533Smarius return (ipend); 636194150Simp} 637194150Simp 638194150Simpstatic int 639194150Simpoct16550_bus_param (struct uart_softc *sc, int baudrate, int databits, 640194150Simp int stopbits, int parity) 641194150Simp{ 642194150Simp struct uart_bas *bas; 643194150Simp int error; 644194150Simp 645194150Simp bas = &sc->sc_bas; 646194150Simp uart_lock(sc->sc_hwmtx); 647194150Simp error = oct16550_param(bas, baudrate, databits, stopbits, parity); 648194150Simp uart_unlock(sc->sc_hwmtx); 649194150Simp return (error); 650194150Simp} 651194150Simp 652194150Simpstatic int 653194150Simpoct16550_bus_probe (struct uart_softc *sc) 654194150Simp{ 655194150Simp struct uart_bas *bas; 656194150Simp int error; 657194150Simp 658194150Simp bas = &sc->sc_bas; 659249919Simp bas->rclk = uart_oct16550_class.uc_rclk = cvmx_clock_get_rate(CVMX_CLOCK_SCLK); 660194150Simp 661194150Simp error = oct16550_probe(bas); 662194150Simp if (error) { 663194150Simp return (error); 664194150Simp } 665194150Simp 666194150Simp uart_setreg(bas, REG_MCR, (MCR_DTR | MCR_RTS)); 667194150Simp 668194150Simp /* 669194150Simp * Enable FIFOs. And check that the UART has them. If not, we're 670194150Simp * done. Since this is the first time we enable the FIFOs, we reset 671194150Simp * them. 672194150Simp */ 673194150Simp oct16550_drain(bas, UART_DRAIN_TRANSMITTER); 674194150Simp#define ENABLE_OCTEON_FIFO 1 675194150Simp#ifdef ENABLE_OCTEON_FIFO 676194150Simp uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST); 677194150Simp#endif 678194150Simp uart_barrier(bas); 679194150Simp 680194150Simp oct16550_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); 681194150Simp 682194150Simp if (device_get_unit(sc->sc_dev)) { 683194150Simp device_set_desc(sc->sc_dev, "Octeon-16550 channel 1"); 684194150Simp } else { 685194150Simp device_set_desc(sc->sc_dev, "Octeon-16550 channel 0"); 686194150Simp } 687194150Simp#ifdef ENABLE_OCTEON_FIFO 688194150Simp sc->sc_rxfifosz = 64; 689194150Simp sc->sc_txfifosz = 64; 690194150Simp#else 691194150Simp sc->sc_rxfifosz = 1; 692194150Simp sc->sc_txfifosz = 1; 693194150Simp#endif 694194150Simp 695194150Simp 696194150Simp#if 0 697194150Simp /* 698194150Simp * XXX there are some issues related to hardware flow control and 699194150Simp * it's likely that uart(4) is the cause. This basicly needs more 700194150Simp * investigation, but we avoid using for hardware flow control 701194150Simp * until then. 702194150Simp */ 703194150Simp /* 16650s or higher have automatic flow control. */ 704194150Simp if (sc->sc_rxfifosz > 16) { 705194150Simp sc->sc_hwiflow = 1; 706194150Simp sc->sc_hwoflow = 1; 707194150Simp } 708194150Simp#endif 709194150Simp 710194150Simp return (0); 711194150Simp} 712194150Simp 713194150Simpstatic int 714194150Simpoct16550_bus_receive (struct uart_softc *sc) 715194150Simp{ 716194150Simp struct uart_bas *bas; 717194150Simp int xc; 718194150Simp uint8_t lsr; 719194150Simp 720194150Simp bas = &sc->sc_bas; 721194150Simp uart_lock(sc->sc_hwmtx); 722194150Simp lsr = uart_getreg(bas, REG_LSR); 723194150Simp 724194150Simp while (lsr & LSR_RXRDY) { 725194150Simp if (uart_rx_full(sc)) { 726194150Simp sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 727194150Simp break; 728194150Simp } 729194150Simp xc = uart_getreg(bas, REG_DATA); 730194150Simp if (lsr & LSR_FE) 731194150Simp xc |= UART_STAT_FRAMERR; 732194150Simp if (lsr & LSR_PE) 733194150Simp xc |= UART_STAT_PARERR; 734194150Simp uart_rx_put(sc, xc); 735194150Simp lsr = uart_getreg(bas, REG_LSR); 736194150Simp } 737194150Simp /* Discard everything left in the Rx FIFO. */ 738194150Simp /* 739194150Simp * First do a dummy read/discard anyway, in case the UART was lying to us. 740194150Simp * This problem was seen on board, when IIR said RBR, but LSR said no RXRDY 741194150Simp * Results in a stuck ipend loop. 742194150Simp */ 743194150Simp (void)uart_getreg(bas, REG_DATA); 744194150Simp while (lsr & LSR_RXRDY) { 745194150Simp (void)uart_getreg(bas, REG_DATA); 746194150Simp uart_barrier(bas); 747194150Simp lsr = uart_getreg(bas, REG_LSR); 748194150Simp } 749194150Simp uart_unlock(sc->sc_hwmtx); 750194150Simp return (0); 751194150Simp} 752194150Simp 753194150Simpstatic int 754194150Simpoct16550_bus_setsig (struct uart_softc *sc, int sig) 755194150Simp{ 756194150Simp struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc; 757194150Simp struct uart_bas *bas; 758194150Simp uint32_t new, old; 759194150Simp 760194150Simp bas = &sc->sc_bas; 761194150Simp do { 762194150Simp old = sc->sc_hwsig; 763194150Simp new = old; 764194150Simp if (sig & SER_DDTR) { 765194150Simp SIGCHG(sig & SER_DTR, new, SER_DTR, 766194150Simp SER_DDTR); 767194150Simp } 768194150Simp if (sig & SER_DRTS) { 769194150Simp SIGCHG(sig & SER_RTS, new, SER_RTS, 770194150Simp SER_DRTS); 771194150Simp } 772194150Simp } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 773194150Simp uart_lock(sc->sc_hwmtx); 774194150Simp oct16550->mcr &= ~(MCR_DTR|MCR_RTS); 775194150Simp if (new & SER_DTR) 776194150Simp oct16550->mcr |= MCR_DTR; 777194150Simp if (new & SER_RTS) 778194150Simp oct16550->mcr |= MCR_RTS; 779194150Simp uart_setreg(bas, REG_MCR, oct16550->mcr); 780194150Simp uart_barrier(bas); 781194150Simp uart_unlock(sc->sc_hwmtx); 782194150Simp return (0); 783194150Simp} 784194150Simp 785194150Simpstatic int 786194150Simpoct16550_bus_transmit (struct uart_softc *sc) 787194150Simp{ 788194150Simp struct oct16550_softc *oct16550 = (struct oct16550_softc*)sc; 789194150Simp struct uart_bas *bas; 790194150Simp int i; 791194150Simp 792194150Simp bas = &sc->sc_bas; 793194150Simp uart_lock(sc->sc_hwmtx); 794194150Simp#ifdef NO_UART_INTERRUPTS 795194150Simp for (i = 0; i < sc->sc_txdatasz; i++) { 796194150Simp oct16550_putc(bas, sc->sc_txbuf[i]); 797194150Simp } 798194150Simp#else 799194150Simp 800194150Simp oct16550_wait_txhr_empty(bas, 100, oct16550_delay(bas)); 801194150Simp uart_setreg(bas, REG_IER, oct16550->ier | IER_ETXRDY); 802194150Simp uart_barrier(bas); 803194150Simp 804194150Simp for (i = 0; i < sc->sc_txdatasz; i++) { 805194150Simp uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]); 806194150Simp uart_barrier(bas); 807194150Simp } 808194150Simp sc->sc_txbusy = 1; 809194150Simp#endif 810194150Simp uart_unlock(sc->sc_hwmtx); 811194150Simp return (0); 812194150Simp} 813