uart_dev_ar933x.c revision 248926
1248843Sadrian/*- 2248843Sadrian * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org> 3248843Sadrian * All rights reserved. 4248843Sadrian * 5248843Sadrian * Redistribution and use in source and binary forms, with or without 6248843Sadrian * modification, are permitted provided that the following conditions 7248843Sadrian * are met: 8248843Sadrian * 9248843Sadrian * 1. Redistributions of source code must retain the above copyright 10248843Sadrian * notice, this list of conditions and the following disclaimer. 11248843Sadrian * 2. Redistributions in binary form must reproduce the above copyright 12248843Sadrian * notice, this list of conditions and the following disclaimer in the 13248843Sadrian * documentation and/or other materials provided with the distribution. 14248843Sadrian * 15248843Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16248843Sadrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17248843Sadrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18248843Sadrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19248843Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20248843Sadrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21248843Sadrian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22248843Sadrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23248843Sadrian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24248843Sadrian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25248843Sadrian */ 26248843Sadrian 27248843Sadrian#include <sys/cdefs.h> 28248843Sadrian__FBSDID("$FreeBSD: head/sys/mips/atheros/uart_dev_ar933x.c 248926 2013-03-30 04:13:47Z adrian $"); 29248843Sadrian 30248843Sadrian#include <sys/param.h> 31248843Sadrian#include <sys/systm.h> 32248843Sadrian#include <sys/bus.h> 33248843Sadrian#include <sys/conf.h> 34248843Sadrian#include <machine/bus.h> 35248843Sadrian 36248843Sadrian#include <dev/uart/uart.h> 37248843Sadrian#include <dev/uart/uart_cpu.h> 38248843Sadrian#include <dev/uart/uart_bus.h> 39248843Sadrian 40248843Sadrian#include <mips/atheros/ar933x_uart.h> 41248843Sadrian 42248843Sadrian#include "uart_if.h" 43248843Sadrian 44248926Sadrian/* 45248926Sadrian * Default system clock is 25MHz; see ar933x_chip.c for how 46248926Sadrian * the startup process determines whether it's 25MHz or 40MHz. 47248926Sadrian */ 48248926Sadrian#define DEFAULT_RCLK (25 * 1000 * 1000) 49248843Sadrian 50248843Sadrian#define ar933x_getreg(bas, reg) \ 51248926Sadrian bus_space_read_4((bas)->bst, (bas)->bsh, reg) 52248843Sadrian#define ar933x_setreg(bas, reg, value) \ 53248926Sadrian bus_space_write_4((bas)->bst, (bas)->bsh, reg, value) 54248843Sadrian 55248843Sadrian 56248843Sadrian#if 0 57248843Sadrian/* 58248843Sadrian * Clear pending interrupts. THRE is cleared by reading IIR. Data 59248843Sadrian * that may have been received gets lost here. 60248843Sadrian */ 61248843Sadrianstatic void 62248843Sadrianar933x_clrint(struct uart_bas *bas) 63248843Sadrian{ 64248843Sadrian uint8_t iir, lsr; 65248843Sadrian 66248843Sadrian iir = uart_getreg(bas, REG_IIR); 67248843Sadrian while ((iir & IIR_NOPEND) == 0) { 68248843Sadrian iir &= IIR_IMASK; 69248843Sadrian if (iir == IIR_RLS) { 70248843Sadrian lsr = uart_getreg(bas, REG_LSR); 71248843Sadrian if (lsr & (LSR_BI|LSR_FE|LSR_PE)) 72248843Sadrian (void)uart_getreg(bas, REG_DATA); 73248843Sadrian } else if (iir == IIR_RXRDY || iir == IIR_RXTOUT) 74248843Sadrian (void)uart_getreg(bas, REG_DATA); 75248843Sadrian else if (iir == IIR_MLSC) 76248843Sadrian (void)uart_getreg(bas, REG_MSR); 77248843Sadrian uart_barrier(bas); 78248843Sadrian iir = uart_getreg(bas, REG_IIR); 79248843Sadrian } 80248843Sadrian} 81248843Sadrian#endif 82248843Sadrian 83248843Sadrian#if 0 84248843Sadrianstatic int 85248843Sadrianar933x_drain(struct uart_bas *bas, int what) 86248843Sadrian{ 87248843Sadrian int delay, limit; 88248843Sadrian 89248843Sadrian delay = ar933x_delay(bas); 90248843Sadrian 91248843Sadrian if (what & UART_DRAIN_TRANSMITTER) { 92248843Sadrian /* 93248843Sadrian * Pick an arbitrary high limit to avoid getting stuck in 94248843Sadrian * an infinite loop when the hardware is broken. Make the 95248843Sadrian * limit high enough to handle large FIFOs. 96248843Sadrian */ 97248843Sadrian limit = 10*1024; 98248843Sadrian while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit) 99248843Sadrian DELAY(delay); 100248843Sadrian if (limit == 0) { 101248843Sadrian /* printf("ns8250: transmitter appears stuck... "); */ 102248843Sadrian return (EIO); 103248843Sadrian } 104248843Sadrian } 105248843Sadrian 106248843Sadrian if (what & UART_DRAIN_RECEIVER) { 107248843Sadrian /* 108248843Sadrian * Pick an arbitrary high limit to avoid getting stuck in 109248843Sadrian * an infinite loop when the hardware is broken. Make the 110248843Sadrian * limit high enough to handle large FIFOs and integrated 111248843Sadrian * UARTs. The HP rx2600 for example has 3 UARTs on the 112248843Sadrian * management board that tend to get a lot of data send 113248843Sadrian * to it when the UART is first activated. 114248843Sadrian */ 115248843Sadrian limit=10*4096; 116248843Sadrian while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) { 117248843Sadrian (void)uart_getreg(bas, REG_DATA); 118248843Sadrian uart_barrier(bas); 119248843Sadrian DELAY(delay << 2); 120248843Sadrian } 121248843Sadrian if (limit == 0) { 122248843Sadrian /* printf("ns8250: receiver appears broken... "); */ 123248843Sadrian return (EIO); 124248843Sadrian } 125248843Sadrian } 126248843Sadrian return (0); 127248843Sadrian} 128248843Sadrian#endif 129248843Sadrian 130248843Sadrian#if 0 131248843Sadrian/* 132248843Sadrian * We can only flush UARTs with FIFOs. UARTs without FIFOs should be 133248843Sadrian * drained. WARNING: this function clobbers the FIFO setting! 134248843Sadrian */ 135248843Sadrianstatic void 136248843Sadrianar933x_flush(struct uart_bas *bas, int what) 137248843Sadrian{ 138248843Sadrian uint8_t fcr; 139248843Sadrian 140248843Sadrian fcr = FCR_ENABLE; 141248843Sadrian if (what & UART_FLUSH_TRANSMITTER) 142248843Sadrian fcr |= FCR_XMT_RST; 143248843Sadrian if (what & UART_FLUSH_RECEIVER) 144248843Sadrian fcr |= FCR_RCV_RST; 145248843Sadrian uart_setreg(bas, REG_FCR, fcr); 146248843Sadrian uart_barrier(bas); 147248843Sadrian} 148248843Sadrian#endif 149248843Sadrian 150248843Sadrian#if 0 151248843Sadrianstatic int 152248843Sadrianar933x_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, 153248843Sadrian int parity) 154248843Sadrian{ 155248843Sadrian int divisor; 156248843Sadrian uint8_t lcr; 157248843Sadrian 158248843Sadrian lcr = 0; 159248843Sadrian if (databits >= 8) 160248843Sadrian lcr |= LCR_8BITS; 161248843Sadrian else if (databits == 7) 162248843Sadrian lcr |= LCR_7BITS; 163248843Sadrian else if (databits == 6) 164248843Sadrian lcr |= LCR_6BITS; 165248843Sadrian else 166248843Sadrian lcr |= LCR_5BITS; 167248843Sadrian if (stopbits > 1) 168248843Sadrian lcr |= LCR_STOPB; 169248843Sadrian lcr |= parity << 3; 170248843Sadrian 171248843Sadrian /* Set baudrate. */ 172248843Sadrian if (baudrate > 0) { 173248843Sadrian divisor = ar933x_divisor(bas->rclk, baudrate); 174248843Sadrian if (divisor == 0) 175248843Sadrian return (EINVAL); 176248843Sadrian uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); 177248843Sadrian uart_barrier(bas); 178248843Sadrian uart_setreg(bas, REG_DLL, divisor & 0xff); 179248843Sadrian uart_setreg(bas, REG_DLH, (divisor >> 8) & 0xff); 180248843Sadrian uart_barrier(bas); 181248843Sadrian } 182248843Sadrian 183248843Sadrian /* Set LCR and clear DLAB. */ 184248843Sadrian uart_setreg(bas, REG_LCR, lcr); 185248843Sadrian uart_barrier(bas); 186248843Sadrian return (0); 187248843Sadrian} 188248843Sadrian#endif 189248843Sadrian 190248843Sadrian/* 191248843Sadrian * Low-level UART interface. 192248843Sadrian */ 193248843Sadrianstatic int ar933x_probe(struct uart_bas *bas); 194248843Sadrianstatic void ar933x_init(struct uart_bas *bas, int, int, int, int); 195248843Sadrianstatic void ar933x_term(struct uart_bas *bas); 196248843Sadrianstatic void ar933x_putc(struct uart_bas *bas, int); 197248843Sadrianstatic int ar933x_rxready(struct uart_bas *bas); 198248843Sadrianstatic int ar933x_getc(struct uart_bas *bas, struct mtx *); 199248843Sadrian 200248843Sadrianstatic struct uart_ops uart_ar933x_ops = { 201248843Sadrian .probe = ar933x_probe, 202248843Sadrian .init = ar933x_init, 203248843Sadrian .term = ar933x_term, 204248843Sadrian .putc = ar933x_putc, 205248843Sadrian .rxready = ar933x_rxready, 206248843Sadrian .getc = ar933x_getc, 207248843Sadrian}; 208248843Sadrian 209248843Sadrianstatic int 210248843Sadrianar933x_probe(struct uart_bas *bas) 211248843Sadrian{ 212248843Sadrian#if 0 213248843Sadrian u_char val; 214248843Sadrian 215248843Sadrian /* Check known 0 bits that don't depend on DLAB. */ 216248843Sadrian val = uart_getreg(bas, REG_IIR); 217248843Sadrian if (val & 0x30) 218248843Sadrian return (ENXIO); 219248843Sadrian /* 220248843Sadrian * Bit 6 of the MCR (= 0x40) appears to be 1 for the Sun1699 221248843Sadrian * chip, but otherwise doesn't seem to have a function. In 222248843Sadrian * other words, uart(4) works regardless. Ignore that bit so 223248843Sadrian * the probe succeeds. 224248843Sadrian */ 225248843Sadrian val = uart_getreg(bas, REG_MCR); 226248843Sadrian if (val & 0xa0) 227248843Sadrian return (ENXIO); 228248843Sadrian#endif 229248843Sadrian return (0); 230248843Sadrian} 231248843Sadrian 232248843Sadrianstatic void 233248843Sadrianar933x_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, 234248843Sadrian int parity) 235248843Sadrian{ 236248843Sadrian#if 0 237248843Sadrian u_char ier; 238248843Sadrian 239248843Sadrian if (bas->rclk == 0) 240248843Sadrian bas->rclk = DEFAULT_RCLK; 241248843Sadrian ar933x_param(bas, baudrate, databits, stopbits, parity); 242248843Sadrian 243248843Sadrian /* Disable all interrupt sources. */ 244248843Sadrian /* 245248843Sadrian * We use 0xe0 instead of 0xf0 as the mask because the XScale PXA 246248843Sadrian * UARTs split the receive time-out interrupt bit out separately as 247248843Sadrian * 0x10. This gets handled by ier_mask and ier_rxbits below. 248248843Sadrian */ 249248843Sadrian ier = uart_getreg(bas, REG_IER) & 0xe0; 250248843Sadrian uart_setreg(bas, REG_IER, ier); 251248843Sadrian uart_barrier(bas); 252248843Sadrian 253248843Sadrian /* Disable the FIFO (if present). */ 254248843Sadrian uart_setreg(bas, REG_FCR, 0); 255248843Sadrian uart_barrier(bas); 256248843Sadrian 257248843Sadrian /* Set RTS & DTR. */ 258248843Sadrian uart_setreg(bas, REG_MCR, MCR_IE | MCR_RTS | MCR_DTR); 259248843Sadrian uart_barrier(bas); 260248843Sadrian 261248843Sadrian ar933x_clrint(bas); 262248843Sadrian#endif 263248843Sadrian} 264248843Sadrian 265248843Sadrianstatic void 266248843Sadrianar933x_term(struct uart_bas *bas) 267248843Sadrian{ 268248843Sadrian#if 0 269248843Sadrian /* Clear RTS & DTR. */ 270248843Sadrian uart_setreg(bas, REG_MCR, MCR_IE); 271248843Sadrian uart_barrier(bas); 272248843Sadrian#endif 273248843Sadrian} 274248843Sadrian 275248843Sadrianstatic void 276248843Sadrianar933x_putc(struct uart_bas *bas, int c) 277248843Sadrian{ 278248843Sadrian int limit; 279248843Sadrian 280248843Sadrian limit = 250000; 281248843Sadrian 282248843Sadrian /* Wait for space in the TX FIFO */ 283248843Sadrian while ( ((ar933x_getreg(bas, AR933X_UART_DATA_REG) & 284248843Sadrian AR933X_UART_DATA_TX_CSR) == 0) && --limit) 285248843Sadrian DELAY(4); 286248843Sadrian 287248843Sadrian /* Write the actual byte */ 288248843Sadrian ar933x_setreg(bas, AR933X_UART_DATA_REG, 289248843Sadrian (c & 0xff) | AR933X_UART_DATA_TX_CSR); 290248843Sadrian} 291248843Sadrian 292248843Sadrianstatic int 293248843Sadrianar933x_rxready(struct uart_bas *bas) 294248843Sadrian{ 295248843Sadrian 296248843Sadrian /* Wait for a character to come ready */ 297248843Sadrian return (!!(ar933x_getreg(bas, AR933X_UART_DATA_REG) 298248843Sadrian & AR933X_UART_DATA_RX_CSR)); 299248843Sadrian} 300248843Sadrian 301248843Sadrianstatic int 302248843Sadrianar933x_getc(struct uart_bas *bas, struct mtx *hwmtx) 303248843Sadrian{ 304248843Sadrian int c; 305248843Sadrian 306248843Sadrian uart_lock(hwmtx); 307248843Sadrian 308248843Sadrian /* Wait for a character to come ready */ 309248843Sadrian while ((ar933x_getreg(bas, AR933X_UART_DATA_REG) & 310248843Sadrian AR933X_UART_DATA_RX_CSR) == 0) { 311248843Sadrian uart_unlock(hwmtx); 312248843Sadrian DELAY(4); 313248843Sadrian uart_lock(hwmtx); 314248843Sadrian } 315248843Sadrian 316248843Sadrian /* Read the top of the RX FIFO */ 317248843Sadrian c = ar933x_getreg(bas, AR933X_UART_DATA_REG) & 0xff; 318248843Sadrian 319248843Sadrian /* Remove that entry from said RX FIFO */ 320248843Sadrian ar933x_setreg(bas, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR); 321248843Sadrian 322248843Sadrian uart_unlock(hwmtx); 323248843Sadrian 324248843Sadrian return (c); 325248843Sadrian} 326248843Sadrian 327248843Sadrian/* 328248843Sadrian * High-level UART interface. 329248843Sadrian */ 330248843Sadrianstruct ar933x_softc { 331248843Sadrian struct uart_softc base; 332248926Sadrian 333248843Sadrian uint32_t u_ier; 334248843Sadrian}; 335248843Sadrian 336248843Sadrianstatic int ar933x_bus_attach(struct uart_softc *); 337248843Sadrianstatic int ar933x_bus_detach(struct uart_softc *); 338248843Sadrianstatic int ar933x_bus_flush(struct uart_softc *, int); 339248843Sadrianstatic int ar933x_bus_getsig(struct uart_softc *); 340248843Sadrianstatic int ar933x_bus_ioctl(struct uart_softc *, int, intptr_t); 341248843Sadrianstatic int ar933x_bus_ipend(struct uart_softc *); 342248843Sadrianstatic int ar933x_bus_param(struct uart_softc *, int, int, int, int); 343248843Sadrianstatic int ar933x_bus_probe(struct uart_softc *); 344248843Sadrianstatic int ar933x_bus_receive(struct uart_softc *); 345248843Sadrianstatic int ar933x_bus_setsig(struct uart_softc *, int); 346248843Sadrianstatic int ar933x_bus_transmit(struct uart_softc *); 347248843Sadrian 348248843Sadrianstatic kobj_method_t ar933x_methods[] = { 349248843Sadrian KOBJMETHOD(uart_attach, ar933x_bus_attach), 350248843Sadrian KOBJMETHOD(uart_detach, ar933x_bus_detach), 351248843Sadrian KOBJMETHOD(uart_flush, ar933x_bus_flush), 352248843Sadrian KOBJMETHOD(uart_getsig, ar933x_bus_getsig), 353248843Sadrian KOBJMETHOD(uart_ioctl, ar933x_bus_ioctl), 354248843Sadrian KOBJMETHOD(uart_ipend, ar933x_bus_ipend), 355248843Sadrian KOBJMETHOD(uart_param, ar933x_bus_param), 356248843Sadrian KOBJMETHOD(uart_probe, ar933x_bus_probe), 357248843Sadrian KOBJMETHOD(uart_receive, ar933x_bus_receive), 358248843Sadrian KOBJMETHOD(uart_setsig, ar933x_bus_setsig), 359248843Sadrian KOBJMETHOD(uart_transmit, ar933x_bus_transmit), 360248843Sadrian { 0, 0 } 361248843Sadrian}; 362248843Sadrian 363248843Sadrianstruct uart_class uart_ar933x_class = { 364248843Sadrian "ar933x", 365248843Sadrian ar933x_methods, 366248843Sadrian sizeof(struct ar933x_softc), 367248843Sadrian .uc_ops = &uart_ar933x_ops, 368248843Sadrian .uc_range = 8, 369248843Sadrian .uc_rclk = DEFAULT_RCLK 370248843Sadrian}; 371248843Sadrian 372248843Sadrian#define SIGCHG(c, i, s, d) \ 373248843Sadrian if (c) { \ 374248843Sadrian i |= (i & s) ? s : s | d; \ 375248843Sadrian } else { \ 376248843Sadrian i = (i & s) ? (i & ~s) | d : i; \ 377248843Sadrian } 378248843Sadrian 379248843Sadrianstatic int 380248843Sadrianar933x_bus_attach(struct uart_softc *sc) 381248843Sadrian{ 382248843Sadrian#if 0 383248843Sadrian struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc; 384248843Sadrian struct uart_bas *bas; 385248843Sadrian unsigned int ivar; 386248843Sadrian 387248843Sadrian bas = &sc->sc_bas; 388248843Sadrian 389248843Sadrian ns8250->mcr = uart_getreg(bas, REG_MCR); 390248843Sadrian ns8250->fcr = FCR_ENABLE; 391248843Sadrian if (!resource_int_value("uart", device_get_unit(sc->sc_dev), "flags", 392248843Sadrian &ivar)) { 393248843Sadrian if (UART_FLAGS_FCR_RX_LOW(ivar)) 394248843Sadrian ns8250->fcr |= FCR_RX_LOW; 395248843Sadrian else if (UART_FLAGS_FCR_RX_MEDL(ivar)) 396248843Sadrian ns8250->fcr |= FCR_RX_MEDL; 397248843Sadrian else if (UART_FLAGS_FCR_RX_HIGH(ivar)) 398248843Sadrian ns8250->fcr |= FCR_RX_HIGH; 399248843Sadrian else 400248843Sadrian ns8250->fcr |= FCR_RX_MEDH; 401248843Sadrian } else 402248843Sadrian ns8250->fcr |= FCR_RX_MEDH; 403248843Sadrian 404248843Sadrian /* Get IER mask */ 405248843Sadrian ivar = 0xf0; 406248843Sadrian resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_mask", 407248843Sadrian &ivar); 408248843Sadrian ns8250->ier_mask = (uint8_t)(ivar & 0xff); 409248843Sadrian 410248843Sadrian /* Get IER RX interrupt bits */ 411248843Sadrian ivar = IER_EMSC | IER_ERLS | IER_ERXRDY; 412248843Sadrian resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_rxbits", 413248843Sadrian &ivar); 414248843Sadrian ns8250->ier_rxbits = (uint8_t)(ivar & 0xff); 415248843Sadrian 416248843Sadrian uart_setreg(bas, REG_FCR, ns8250->fcr); 417248843Sadrian uart_barrier(bas); 418248843Sadrian ar933x_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); 419248843Sadrian 420248843Sadrian if (ns8250->mcr & MCR_DTR) 421248843Sadrian sc->sc_hwsig |= SER_DTR; 422248843Sadrian if (ns8250->mcr & MCR_RTS) 423248843Sadrian sc->sc_hwsig |= SER_RTS; 424248843Sadrian ar933x_bus_getsig(sc); 425248843Sadrian 426248843Sadrian ar933x_clrint(bas); 427248843Sadrian ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; 428248843Sadrian ns8250->ier |= ns8250->ier_rxbits; 429248843Sadrian uart_setreg(bas, REG_IER, ns8250->ier); 430248843Sadrian uart_barrier(bas); 431248843Sadrian#endif 432248843Sadrian return (0); 433248843Sadrian} 434248843Sadrian 435248843Sadrianstatic int 436248843Sadrianar933x_bus_detach(struct uart_softc *sc) 437248843Sadrian{ 438248843Sadrian#if 0 439248843Sadrian struct ar933x_softc *ns8250; 440248843Sadrian struct uart_bas *bas; 441248843Sadrian u_char ier; 442248843Sadrian 443248843Sadrian ns8250 = (struct ar933x_softc *)sc; 444248843Sadrian bas = &sc->sc_bas; 445248843Sadrian ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; 446248843Sadrian uart_setreg(bas, REG_IER, ier); 447248843Sadrian uart_barrier(bas); 448248843Sadrian ar933x_clrint(bas); 449248843Sadrian#endif 450248843Sadrian return (0); 451248843Sadrian} 452248843Sadrian 453248843Sadrianstatic int 454248843Sadrianar933x_bus_flush(struct uart_softc *sc, int what) 455248843Sadrian{ 456248843Sadrian#if 0 457248843Sadrian struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc; 458248843Sadrian struct uart_bas *bas; 459248843Sadrian int error; 460248843Sadrian 461248843Sadrian bas = &sc->sc_bas; 462248843Sadrian uart_lock(sc->sc_hwmtx); 463248843Sadrian if (sc->sc_rxfifosz > 1) { 464248843Sadrian ar933x_flush(bas, what); 465248843Sadrian uart_setreg(bas, REG_FCR, ns8250->fcr); 466248843Sadrian uart_barrier(bas); 467248843Sadrian error = 0; 468248843Sadrian } else 469248843Sadrian error = ar933x_drain(bas, what); 470248843Sadrian uart_unlock(sc->sc_hwmtx); 471248843Sadrian return (error); 472248843Sadrian#endif 473248843Sadrian return (ENXIO); 474248843Sadrian} 475248843Sadrian 476248843Sadrianstatic int 477248843Sadrianar933x_bus_getsig(struct uart_softc *sc) 478248843Sadrian{ 479248843Sadrian#if 0 480248843Sadrian uint32_t new, old, sig; 481248843Sadrian uint8_t msr; 482248843Sadrian 483248843Sadrian do { 484248843Sadrian old = sc->sc_hwsig; 485248843Sadrian sig = old; 486248843Sadrian uart_lock(sc->sc_hwmtx); 487248843Sadrian msr = uart_getreg(&sc->sc_bas, REG_MSR); 488248843Sadrian uart_unlock(sc->sc_hwmtx); 489248843Sadrian SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR); 490248843Sadrian SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS); 491248843Sadrian SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD); 492248843Sadrian SIGCHG(msr & MSR_RI, sig, SER_RI, SER_DRI); 493248843Sadrian new = sig & ~SER_MASK_DELTA; 494248843Sadrian } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 495248843Sadrian return (sig); 496248843Sadrian#endif 497248843Sadrian return (0); 498248843Sadrian} 499248843Sadrian 500248843Sadrianstatic int 501248843Sadrianar933x_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 502248843Sadrian{ 503248843Sadrian#if 0 504248843Sadrian struct uart_bas *bas; 505248843Sadrian int baudrate, divisor, error; 506248843Sadrian uint8_t efr, lcr; 507248843Sadrian 508248843Sadrian bas = &sc->sc_bas; 509248843Sadrian error = 0; 510248843Sadrian uart_lock(sc->sc_hwmtx); 511248843Sadrian switch (request) { 512248843Sadrian case UART_IOCTL_BREAK: 513248843Sadrian lcr = uart_getreg(bas, REG_LCR); 514248843Sadrian if (data) 515248843Sadrian lcr |= LCR_SBREAK; 516248843Sadrian else 517248843Sadrian lcr &= ~LCR_SBREAK; 518248843Sadrian uart_setreg(bas, REG_LCR, lcr); 519248843Sadrian uart_barrier(bas); 520248843Sadrian break; 521248843Sadrian case UART_IOCTL_IFLOW: 522248843Sadrian lcr = uart_getreg(bas, REG_LCR); 523248843Sadrian uart_barrier(bas); 524248843Sadrian uart_setreg(bas, REG_LCR, 0xbf); 525248843Sadrian uart_barrier(bas); 526248843Sadrian efr = uart_getreg(bas, REG_EFR); 527248843Sadrian if (data) 528248843Sadrian efr |= EFR_RTS; 529248843Sadrian else 530248843Sadrian efr &= ~EFR_RTS; 531248843Sadrian uart_setreg(bas, REG_EFR, efr); 532248843Sadrian uart_barrier(bas); 533248843Sadrian uart_setreg(bas, REG_LCR, lcr); 534248843Sadrian uart_barrier(bas); 535248843Sadrian break; 536248843Sadrian case UART_IOCTL_OFLOW: 537248843Sadrian lcr = uart_getreg(bas, REG_LCR); 538248843Sadrian uart_barrier(bas); 539248843Sadrian uart_setreg(bas, REG_LCR, 0xbf); 540248843Sadrian uart_barrier(bas); 541248843Sadrian efr = uart_getreg(bas, REG_EFR); 542248843Sadrian if (data) 543248843Sadrian efr |= EFR_CTS; 544248843Sadrian else 545248843Sadrian efr &= ~EFR_CTS; 546248843Sadrian uart_setreg(bas, REG_EFR, efr); 547248843Sadrian uart_barrier(bas); 548248843Sadrian uart_setreg(bas, REG_LCR, lcr); 549248843Sadrian uart_barrier(bas); 550248843Sadrian break; 551248843Sadrian case UART_IOCTL_BAUD: 552248843Sadrian lcr = uart_getreg(bas, REG_LCR); 553248843Sadrian uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); 554248843Sadrian uart_barrier(bas); 555248843Sadrian divisor = uart_getreg(bas, REG_DLL) | 556248843Sadrian (uart_getreg(bas, REG_DLH) << 8); 557248843Sadrian uart_barrier(bas); 558248843Sadrian uart_setreg(bas, REG_LCR, lcr); 559248843Sadrian uart_barrier(bas); 560248843Sadrian baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0; 561248843Sadrian if (baudrate > 0) 562248843Sadrian *(int*)data = baudrate; 563248843Sadrian else 564248843Sadrian error = ENXIO; 565248843Sadrian break; 566248843Sadrian default: 567248843Sadrian error = EINVAL; 568248843Sadrian break; 569248843Sadrian } 570248843Sadrian uart_unlock(sc->sc_hwmtx); 571248843Sadrian return (error); 572248843Sadrian#endif 573248843Sadrian return (ENXIO); 574248843Sadrian} 575248843Sadrian 576248843Sadrianstatic int 577248843Sadrianar933x_bus_ipend(struct uart_softc *sc) 578248843Sadrian{ 579248843Sadrian#if 0 580248843Sadrian struct uart_bas *bas; 581248843Sadrian struct ar933x_softc *ns8250; 582248843Sadrian int ipend; 583248843Sadrian uint8_t iir, lsr; 584248843Sadrian 585248843Sadrian ns8250 = (struct ar933x_softc *)sc; 586248843Sadrian bas = &sc->sc_bas; 587248843Sadrian uart_lock(sc->sc_hwmtx); 588248843Sadrian iir = uart_getreg(bas, REG_IIR); 589248843Sadrian if (iir & IIR_NOPEND) { 590248843Sadrian uart_unlock(sc->sc_hwmtx); 591248843Sadrian return (0); 592248843Sadrian } 593248843Sadrian ipend = 0; 594248843Sadrian if (iir & IIR_RXRDY) { 595248843Sadrian lsr = uart_getreg(bas, REG_LSR); 596248843Sadrian if (lsr & LSR_OE) 597248843Sadrian ipend |= SER_INT_OVERRUN; 598248843Sadrian if (lsr & LSR_BI) 599248843Sadrian ipend |= SER_INT_BREAK; 600248843Sadrian if (lsr & LSR_RXRDY) 601248843Sadrian ipend |= SER_INT_RXREADY; 602248843Sadrian } else { 603248843Sadrian if (iir & IIR_TXRDY) { 604248843Sadrian ipend |= SER_INT_TXIDLE; 605248843Sadrian uart_setreg(bas, REG_IER, ns8250->ier); 606248843Sadrian } else 607248843Sadrian ipend |= SER_INT_SIGCHG; 608248843Sadrian } 609248843Sadrian if (ipend == 0) 610248843Sadrian ar933x_clrint(bas); 611248843Sadrian uart_unlock(sc->sc_hwmtx); 612248843Sadrian return (ipend); 613248843Sadrian#endif 614248843Sadrian return (0); 615248843Sadrian} 616248843Sadrian 617248843Sadrianstatic int 618248843Sadrianar933x_bus_param(struct uart_softc *sc, int baudrate, int databits, 619248843Sadrian int stopbits, int parity) 620248843Sadrian{ 621248843Sadrian#if 0 622248843Sadrian struct uart_bas *bas; 623248843Sadrian int error; 624248843Sadrian 625248843Sadrian bas = &sc->sc_bas; 626248843Sadrian uart_lock(sc->sc_hwmtx); 627248843Sadrian error = ar933x_param(bas, baudrate, databits, stopbits, parity); 628248843Sadrian uart_unlock(sc->sc_hwmtx); 629248843Sadrian return (error); 630248843Sadrian#endif 631248843Sadrian return (ENXIO); 632248843Sadrian} 633248843Sadrian 634248843Sadrianstatic int 635248843Sadrianar933x_bus_probe(struct uart_softc *sc) 636248843Sadrian{ 637248843Sadrian#if 0 638248843Sadrian struct ar933x_softc *ns8250; 639248843Sadrian struct uart_bas *bas; 640248843Sadrian int count, delay, error, limit; 641248843Sadrian uint8_t lsr, mcr, ier; 642248843Sadrian 643248843Sadrian ns8250 = (struct ar933x_softc *)sc; 644248843Sadrian bas = &sc->sc_bas; 645248843Sadrian 646248843Sadrian error = ar933x_probe(bas); 647248843Sadrian if (error) 648248843Sadrian return (error); 649248843Sadrian 650248843Sadrian mcr = MCR_IE; 651248843Sadrian if (sc->sc_sysdev == NULL) { 652248843Sadrian /* By using ar933x_init() we also set DTR and RTS. */ 653248843Sadrian ar933x_init(bas, 115200, 8, 1, UART_PARITY_NONE); 654248843Sadrian } else 655248843Sadrian mcr |= MCR_DTR | MCR_RTS; 656248843Sadrian 657248843Sadrian error = ar933x_drain(bas, UART_DRAIN_TRANSMITTER); 658248843Sadrian if (error) 659248843Sadrian return (error); 660248843Sadrian 661248843Sadrian /* 662248843Sadrian * Set loopback mode. This avoids having garbage on the wire and 663248843Sadrian * also allows us send and receive data. We set DTR and RTS to 664248843Sadrian * avoid the possibility that automatic flow-control prevents 665248843Sadrian * any data from being sent. 666248843Sadrian */ 667248843Sadrian uart_setreg(bas, REG_MCR, MCR_LOOPBACK | MCR_IE | MCR_DTR | MCR_RTS); 668248843Sadrian uart_barrier(bas); 669248843Sadrian 670248843Sadrian /* 671248843Sadrian * Enable FIFOs. And check that the UART has them. If not, we're 672248843Sadrian * done. Since this is the first time we enable the FIFOs, we reset 673248843Sadrian * them. 674248843Sadrian */ 675248843Sadrian uart_setreg(bas, REG_FCR, FCR_ENABLE); 676248843Sadrian uart_barrier(bas); 677248843Sadrian if (!(uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK)) { 678248843Sadrian /* 679248843Sadrian * NS16450 or INS8250. We don't bother to differentiate 680248843Sadrian * between them. They're too old to be interesting. 681248843Sadrian */ 682248843Sadrian uart_setreg(bas, REG_MCR, mcr); 683248843Sadrian uart_barrier(bas); 684248843Sadrian sc->sc_rxfifosz = sc->sc_txfifosz = 1; 685248843Sadrian device_set_desc(sc->sc_dev, "8250 or 16450 or compatible"); 686248843Sadrian return (0); 687248843Sadrian } 688248843Sadrian 689248843Sadrian uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST); 690248843Sadrian uart_barrier(bas); 691248843Sadrian 692248843Sadrian count = 0; 693248843Sadrian delay = ar933x_delay(bas); 694248843Sadrian 695248843Sadrian /* We have FIFOs. Drain the transmitter and receiver. */ 696248843Sadrian error = ar933x_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER); 697248843Sadrian if (error) { 698248843Sadrian uart_setreg(bas, REG_MCR, mcr); 699248843Sadrian uart_setreg(bas, REG_FCR, 0); 700248843Sadrian uart_barrier(bas); 701248843Sadrian goto describe; 702248843Sadrian } 703248843Sadrian 704248843Sadrian /* 705248843Sadrian * We should have a sufficiently clean "pipe" to determine the 706248843Sadrian * size of the FIFOs. We send as much characters as is reasonable 707248843Sadrian * and wait for the overflow bit in the LSR register to be 708248843Sadrian * asserted, counting the characters as we send them. Based on 709248843Sadrian * that count we know the FIFO size. 710248843Sadrian */ 711248843Sadrian do { 712248843Sadrian uart_setreg(bas, REG_DATA, 0); 713248843Sadrian uart_barrier(bas); 714248843Sadrian count++; 715248843Sadrian 716248843Sadrian limit = 30; 717248843Sadrian lsr = 0; 718248843Sadrian /* 719248843Sadrian * LSR bits are cleared upon read, so we must accumulate 720248843Sadrian * them to be able to test LSR_OE below. 721248843Sadrian */ 722248843Sadrian while (((lsr |= uart_getreg(bas, REG_LSR)) & LSR_TEMT) == 0 && 723248843Sadrian --limit) 724248843Sadrian DELAY(delay); 725248843Sadrian if (limit == 0) { 726248843Sadrian ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; 727248843Sadrian uart_setreg(bas, REG_IER, ier); 728248843Sadrian uart_setreg(bas, REG_MCR, mcr); 729248843Sadrian uart_setreg(bas, REG_FCR, 0); 730248843Sadrian uart_barrier(bas); 731248843Sadrian count = 0; 732248843Sadrian goto describe; 733248843Sadrian } 734248843Sadrian } while ((lsr & LSR_OE) == 0 && count < 130); 735248843Sadrian count--; 736248843Sadrian 737248843Sadrian uart_setreg(bas, REG_MCR, mcr); 738248843Sadrian 739248843Sadrian /* Reset FIFOs. */ 740248843Sadrian ar933x_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); 741248843Sadrian 742248843Sadrian describe: 743248843Sadrian if (count >= 14 && count <= 16) { 744248843Sadrian sc->sc_rxfifosz = 16; 745248843Sadrian device_set_desc(sc->sc_dev, "16550 or compatible"); 746248843Sadrian } else if (count >= 28 && count <= 32) { 747248843Sadrian sc->sc_rxfifosz = 32; 748248843Sadrian device_set_desc(sc->sc_dev, "16650 or compatible"); 749248843Sadrian } else if (count >= 56 && count <= 64) { 750248843Sadrian sc->sc_rxfifosz = 64; 751248843Sadrian device_set_desc(sc->sc_dev, "16750 or compatible"); 752248843Sadrian } else if (count >= 112 && count <= 128) { 753248843Sadrian sc->sc_rxfifosz = 128; 754248843Sadrian device_set_desc(sc->sc_dev, "16950 or compatible"); 755248843Sadrian } else { 756248843Sadrian sc->sc_rxfifosz = 16; 757248843Sadrian device_set_desc(sc->sc_dev, 758248843Sadrian "Non-standard ns8250 class UART with FIFOs"); 759248843Sadrian } 760248843Sadrian 761248843Sadrian /* 762248843Sadrian * Force the Tx FIFO size to 16 bytes for now. We don't program the 763248843Sadrian * Tx trigger. Also, we assume that all data has been sent when the 764248843Sadrian * interrupt happens. 765248843Sadrian */ 766248843Sadrian sc->sc_txfifosz = 16; 767248843Sadrian 768248843Sadrian#if 0 769248843Sadrian /* 770248843Sadrian * XXX there are some issues related to hardware flow control and 771248843Sadrian * it's likely that uart(4) is the cause. This basicly needs more 772248843Sadrian * investigation, but we avoid using for hardware flow control 773248843Sadrian * until then. 774248843Sadrian */ 775248843Sadrian /* 16650s or higher have automatic flow control. */ 776248843Sadrian if (sc->sc_rxfifosz > 16) { 777248843Sadrian sc->sc_hwiflow = 1; 778248843Sadrian sc->sc_hwoflow = 1; 779248843Sadrian } 780248843Sadrian#endif 781248843Sadrian#endif 782248843Sadrian return (0); 783248843Sadrian} 784248843Sadrian 785248843Sadrianstatic int 786248843Sadrianar933x_bus_receive(struct uart_softc *sc) 787248843Sadrian{ 788248843Sadrian#if 0 789248843Sadrian struct uart_bas *bas; 790248843Sadrian int xc; 791248843Sadrian uint8_t lsr; 792248843Sadrian 793248843Sadrian bas = &sc->sc_bas; 794248843Sadrian uart_lock(sc->sc_hwmtx); 795248843Sadrian lsr = uart_getreg(bas, REG_LSR); 796248843Sadrian while (lsr & LSR_RXRDY) { 797248843Sadrian if (uart_rx_full(sc)) { 798248843Sadrian sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 799248843Sadrian break; 800248843Sadrian } 801248843Sadrian xc = uart_getreg(bas, REG_DATA); 802248843Sadrian if (lsr & LSR_FE) 803248843Sadrian xc |= UART_STAT_FRAMERR; 804248843Sadrian if (lsr & LSR_PE) 805248843Sadrian xc |= UART_STAT_PARERR; 806248843Sadrian uart_rx_put(sc, xc); 807248843Sadrian lsr = uart_getreg(bas, REG_LSR); 808248843Sadrian } 809248843Sadrian /* Discard everything left in the Rx FIFO. */ 810248843Sadrian while (lsr & LSR_RXRDY) { 811248843Sadrian (void)uart_getreg(bas, REG_DATA); 812248843Sadrian uart_barrier(bas); 813248843Sadrian lsr = uart_getreg(bas, REG_LSR); 814248843Sadrian } 815248843Sadrian uart_unlock(sc->sc_hwmtx); 816248843Sadrian#endif 817248843Sadrian return (0); 818248843Sadrian} 819248843Sadrian 820248843Sadrianstatic int 821248843Sadrianar933x_bus_setsig(struct uart_softc *sc, int sig) 822248843Sadrian{ 823248843Sadrian#if 0 824248843Sadrian struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc; 825248843Sadrian struct uart_bas *bas; 826248843Sadrian uint32_t new, old; 827248843Sadrian 828248843Sadrian bas = &sc->sc_bas; 829248843Sadrian do { 830248843Sadrian old = sc->sc_hwsig; 831248843Sadrian new = old; 832248843Sadrian if (sig & SER_DDTR) { 833248843Sadrian SIGCHG(sig & SER_DTR, new, SER_DTR, 834248843Sadrian SER_DDTR); 835248843Sadrian } 836248843Sadrian if (sig & SER_DRTS) { 837248843Sadrian SIGCHG(sig & SER_RTS, new, SER_RTS, 838248843Sadrian SER_DRTS); 839248843Sadrian } 840248843Sadrian } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 841248843Sadrian uart_lock(sc->sc_hwmtx); 842248843Sadrian ns8250->mcr &= ~(MCR_DTR|MCR_RTS); 843248843Sadrian if (new & SER_DTR) 844248843Sadrian ns8250->mcr |= MCR_DTR; 845248843Sadrian if (new & SER_RTS) 846248843Sadrian ns8250->mcr |= MCR_RTS; 847248843Sadrian uart_setreg(bas, REG_MCR, ns8250->mcr); 848248843Sadrian uart_barrier(bas); 849248843Sadrian uart_unlock(sc->sc_hwmtx); 850248843Sadrian#endif 851248843Sadrian return (0); 852248843Sadrian} 853248843Sadrian 854248843Sadrianstatic int 855248843Sadrianar933x_bus_transmit(struct uart_softc *sc) 856248843Sadrian{ 857248843Sadrian#if 0 858248843Sadrian struct ar933x_softc *ns8250 = (struct ar933x_softc*)sc; 859248843Sadrian struct uart_bas *bas; 860248843Sadrian int i; 861248843Sadrian 862248843Sadrian bas = &sc->sc_bas; 863248843Sadrian uart_lock(sc->sc_hwmtx); 864248843Sadrian while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0) 865248843Sadrian ; 866248843Sadrian uart_setreg(bas, REG_IER, ns8250->ier | IER_ETXRDY); 867248843Sadrian uart_barrier(bas); 868248843Sadrian for (i = 0; i < sc->sc_txdatasz; i++) { 869248843Sadrian uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]); 870248843Sadrian uart_barrier(bas); 871248843Sadrian } 872248843Sadrian sc->sc_txbusy = 1; 873248843Sadrian uart_unlock(sc->sc_hwmtx); 874248843Sadrian#endif 875248843Sadrian return (0); 876248843Sadrian} 877