1220297Sadrian/* $NetBSD: uart.c,v 1.2 2007/03/23 20:05:47 dogcow Exp $ */ 2220297Sadrian 3220297Sadrian/*- 4220297Sadrian * Copyright (c) 2010 Aleksandr Rybalko. 5220297Sadrian * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko. 6220297Sadrian * Copyright (c) 2007 Oleksandr Tymoshenko. 7220297Sadrian * All rights reserved. 8220297Sadrian * 9220297Sadrian * Redistribution and use in source and binary forms, with or 10220297Sadrian * without modification, are permitted provided that the following 11220297Sadrian * conditions are met: 12220297Sadrian * 1. Redistributions of source code must retain the above copyright 13220297Sadrian * notice, this list of conditions and the following disclaimer. 14220297Sadrian * 2. Redistributions in binary form must reproduce the above 15220297Sadrian * copyright notice, this list of conditions and the following 16220297Sadrian * disclaimer in the documentation and/or other materials provided 17220297Sadrian * with the distribution. 18220297Sadrian * 19220297Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY 20220297Sadrian * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21220297Sadrian * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 22220297Sadrian * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 23220297Sadrian * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 24220297Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25220297Sadrian * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 26220297Sadrian * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27220297Sadrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 28220297Sadrian * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29220297Sadrian * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30220297Sadrian * OF SUCH DAMAGE. 31220297Sadrian */ 32220297Sadrian 33220297Sadrian#include <sys/cdefs.h> 34220297Sadrian__FBSDID("$FreeBSD: releng/10.2/sys/mips/rt305x/uart_dev_rt305x.c 262649 2014-03-01 04:16:54Z imp $"); 35220297Sadrian 36220297Sadrian#include "opt_ddb.h" 37220297Sadrian 38220297Sadrian#include <sys/param.h> 39220297Sadrian#include <sys/systm.h> 40220297Sadrian#include <sys/bus.h> 41220297Sadrian#include <sys/conf.h> 42220297Sadrian#include <sys/kdb.h> 43220297Sadrian#include <sys/reboot.h> 44220297Sadrian#include <sys/sysctl.h> 45220297Sadrian#include <sys/kernel.h> 46220297Sadrian#include <machine/bus.h> 47220297Sadrian 48220297Sadrian#include <dev/uart/uart.h> 49220297Sadrian#include <dev/uart/uart_cpu.h> 50220297Sadrian#include <dev/uart/uart_bus.h> 51220297Sadrian 52220297Sadrian#include <mips/rt305x/uart_dev_rt305x.h> 53220297Sadrian#include <mips/rt305x/rt305xreg.h> 54220297Sadrian 55220297Sadrian#include "uart_if.h" 56220297Sadrian/* 57220297Sadrian * Low-level UART interface. 58220297Sadrian */ 59220297Sadrianstatic int rt305x_uart_probe(struct uart_bas *bas); 60220297Sadrianstatic void rt305x_uart_init(struct uart_bas *bas, int, int, int, int); 61220297Sadrianstatic void rt305x_uart_term(struct uart_bas *bas); 62220297Sadrianstatic void rt305x_uart_putc(struct uart_bas *bas, int); 63220297Sadrianstatic int rt305x_uart_rxready(struct uart_bas *bas); 64220297Sadrianstatic int rt305x_uart_getc(struct uart_bas *bas, struct mtx *); 65220297Sadrian 66220297Sadrianstatic struct uart_ops uart_rt305x_uart_ops = { 67220297Sadrian .probe = rt305x_uart_probe, 68220297Sadrian .init = rt305x_uart_init, 69220297Sadrian .term = rt305x_uart_term, 70220297Sadrian .putc = rt305x_uart_putc, 71220297Sadrian .rxready = rt305x_uart_rxready, 72220297Sadrian .getc = rt305x_uart_getc, 73220297Sadrian}; 74220297Sadrian 75220297Sadrianstatic int uart_output = 1; 76220297SadrianTUNABLE_INT("kern.uart_output", &uart_output); 77220297SadrianSYSCTL_INT(_kern, OID_AUTO, uart_output, CTLFLAG_RW, 78220297Sadrian &uart_output, 0, "UART output enabled."); 79220297Sadrian 80220297Sadrian 81220297Sadrian 82220297Sadrian 83220297Sadrianstatic int 84220297Sadrianrt305x_uart_probe(struct uart_bas *bas) 85220297Sadrian{ 86220297Sadrian 87220297Sadrian return (0); 88220297Sadrian} 89220297Sadrian 90220297Sadrianstatic void 91220297Sadrianrt305x_uart_init(struct uart_bas *bas, int baudrate, int databits, 92220297Sadrian int stopbits, int parity) 93220297Sadrian{ 94220297Sadrian#ifdef notyet 95220297Sadrian /* CLKDIV = 384000000/ 3/ 16/ br */ 96220297Sadrian /* for 384MHz CLKDIV = 8000000 / baudrate; */ 97220297Sadrian switch (databits) { 98220297Sadrian case 5: 99220297Sadrian databits = UART_LCR_5B; 100220297Sadrian break; 101220297Sadrian case 6: 102220297Sadrian databits = UART_LCR_6B; 103220297Sadrian break; 104220297Sadrian case 7: 105220297Sadrian databits = UART_LCR_7B; 106220297Sadrian break; 107220297Sadrian case 8: 108220297Sadrian databits = UART_LCR_8B; 109220297Sadrian break; 110220297Sadrian default: 111220297Sadrian /* Unsupported */ 112220297Sadrian return; 113220297Sadrian } 114220297Sadrian switch (parity) { 115220297Sadrian case UART_PARITY_EVEN: parity = (UART_LCR_PEN|UART_LCR_EVEN); break; 116220297Sadrian case UART_PARITY_NONE: parity = (UART_LCR_PEN); break; 117220297Sadrian case UART_PARITY_ODD: parity = 0; break; 118220297Sadrian /* Unsupported */ 119220297Sadrian default: return; 120220297Sadrian } 121220297Sadrian uart_setreg(bas, UART_CDDL_REG, 8000000/baudrate); 122220297Sadrian uart_barrier(bas); 123220297Sadrian uart_setreg(bas, UART_LCR_REG, databits | (stopbits==1?0:4) | parity); 124220297Sadrian uart_barrier(bas); 125220297Sadrian#endif 126220297Sadrian} 127220297Sadrian 128220297Sadrianstatic void 129220297Sadrianrt305x_uart_term(struct uart_bas *bas) 130220297Sadrian{ 131220297Sadrian uart_setreg(bas, UART_MCR_REG, 0); 132220297Sadrian uart_barrier(bas); 133220297Sadrian} 134220297Sadrian 135220297Sadrianstatic void 136220297Sadrianrt305x_uart_putc(struct uart_bas *bas, int c) 137220297Sadrian{ 138220297Sadrian char chr; 139220297Sadrian if (!uart_output) return; 140220297Sadrian chr = c; 141220297Sadrian while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE)); 142220297Sadrian uart_setreg(bas, UART_TX_REG, c); 143220297Sadrian uart_barrier(bas); 144220297Sadrian while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE)); 145220297Sadrian} 146220297Sadrian 147220297Sadrianstatic int 148220297Sadrianrt305x_uart_rxready(struct uart_bas *bas) 149220297Sadrian{ 150220297Sadrian#ifdef notyet 151220297Sadrian if (uart_getreg(bas, UART_LSR_REG) & UART_LSR_DR) 152220297Sadrian return (1); 153220297Sadrian 154220297Sadrian return (0); 155220297Sadrian#else 156220297Sadrian return (1); 157220297Sadrian#endif 158220297Sadrian} 159220297Sadrian 160220297Sadrianstatic int 161220297Sadrianrt305x_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) 162220297Sadrian{ 163220297Sadrian int c; 164220297Sadrian 165220297Sadrian uart_lock(hwmtx); 166220297Sadrian 167220297Sadrian while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_DR)) { 168220297Sadrian uart_unlock(hwmtx); 169220297Sadrian DELAY(10); 170220297Sadrian uart_lock(hwmtx); 171220297Sadrian } 172220297Sadrian 173220297Sadrian c = uart_getreg(bas, UART_RX_REG); 174220297Sadrian 175220297Sadrian uart_unlock(hwmtx); 176220297Sadrian 177220297Sadrian return (c); 178220297Sadrian} 179220297Sadrian 180220297Sadrian/* 181220297Sadrian * High-level UART interface. 182220297Sadrian */ 183220297Sadrianstruct rt305x_uart_softc { 184220297Sadrian struct uart_softc base; 185220297Sadrian}; 186220297Sadrian 187220297Sadrianstatic int rt305x_uart_bus_attach(struct uart_softc *); 188220297Sadrianstatic int rt305x_uart_bus_detach(struct uart_softc *); 189220297Sadrianstatic int rt305x_uart_bus_flush(struct uart_softc *, int); 190220297Sadrianstatic int rt305x_uart_bus_getsig(struct uart_softc *); 191220297Sadrianstatic int rt305x_uart_bus_ioctl(struct uart_softc *, int, intptr_t); 192220297Sadrianstatic int rt305x_uart_bus_ipend(struct uart_softc *); 193220297Sadrianstatic int rt305x_uart_bus_param(struct uart_softc *, int, int, int, int); 194220297Sadrianstatic int rt305x_uart_bus_probe(struct uart_softc *); 195220297Sadrianstatic int rt305x_uart_bus_receive(struct uart_softc *); 196220297Sadrianstatic int rt305x_uart_bus_setsig(struct uart_softc *, int); 197220297Sadrianstatic int rt305x_uart_bus_transmit(struct uart_softc *); 198262649Simpstatic void rt305x_uart_bus_grab(struct uart_softc *); 199262649Simpstatic void rt305x_uart_bus_ungrab(struct uart_softc *); 200220297Sadrian 201220297Sadrianstatic kobj_method_t rt305x_uart_methods[] = { 202220297Sadrian KOBJMETHOD(uart_attach, rt305x_uart_bus_attach), 203220297Sadrian KOBJMETHOD(uart_detach, rt305x_uart_bus_detach), 204220297Sadrian KOBJMETHOD(uart_flush, rt305x_uart_bus_flush), 205220297Sadrian KOBJMETHOD(uart_getsig, rt305x_uart_bus_getsig), 206220297Sadrian KOBJMETHOD(uart_ioctl, rt305x_uart_bus_ioctl), 207220297Sadrian KOBJMETHOD(uart_ipend, rt305x_uart_bus_ipend), 208220297Sadrian KOBJMETHOD(uart_param, rt305x_uart_bus_param), 209220297Sadrian KOBJMETHOD(uart_probe, rt305x_uart_bus_probe), 210220297Sadrian KOBJMETHOD(uart_receive, rt305x_uart_bus_receive), 211220297Sadrian KOBJMETHOD(uart_setsig, rt305x_uart_bus_setsig), 212220297Sadrian KOBJMETHOD(uart_transmit, rt305x_uart_bus_transmit), 213262649Simp KOBJMETHOD(uart_grab, rt305x_uart_bus_grab), 214262649Simp KOBJMETHOD(uart_ungrab, rt305x_uart_bus_ungrab), 215220297Sadrian { 0, 0 } 216220297Sadrian}; 217220297Sadrian 218220297Sadrianstruct uart_class uart_rt305x_uart_class = { 219220297Sadrian "rt305x", 220220297Sadrian rt305x_uart_methods, 221220297Sadrian sizeof(struct rt305x_uart_softc), 222220297Sadrian .uc_ops = &uart_rt305x_uart_ops, 223220297Sadrian .uc_range = 1, /* use hinted range */ 224220297Sadrian .uc_rclk = SYSTEM_CLOCK 225220297Sadrian}; 226220297Sadrian 227220297Sadrian#define SIGCHG(c, i, s, d) \ 228220297Sadrian if (c) { \ 229220297Sadrian i |= (i & s) ? s : s | d; \ 230220297Sadrian } else { \ 231220297Sadrian i = (i & s) ? (i & ~s) | d : i; \ 232220297Sadrian } 233220297Sadrian 234220297Sadrian/* 235220297Sadrian * Disable TX interrupt. uart should be locked 236220297Sadrian */ 237220297Sadrianstatic __inline void 238220297Sadrianrt305x_uart_disable_txintr(struct uart_softc *sc) 239220297Sadrian{ 240220297Sadrian struct uart_bas *bas = &sc->sc_bas; 241220297Sadrian uint8_t cr; 242220297Sadrian 243220297Sadrian cr = uart_getreg(bas, UART_IER_REG); 244220297Sadrian cr &= ~UART_IER_ETBEI; 245220297Sadrian uart_setreg(bas, UART_IER_REG, cr); 246220297Sadrian uart_barrier(bas); 247220297Sadrian} 248220297Sadrian 249220297Sadrian/* 250220297Sadrian * Enable TX interrupt. uart should be locked 251220297Sadrian */ 252220297Sadrianstatic __inline void 253220297Sadrianrt305x_uart_enable_txintr(struct uart_softc *sc) 254220297Sadrian{ 255220297Sadrian struct uart_bas *bas = &sc->sc_bas; 256220297Sadrian uint8_t cr; 257220297Sadrian 258220297Sadrian cr = uart_getreg(bas, UART_IER_REG); 259220297Sadrian cr |= UART_IER_ETBEI; 260220297Sadrian uart_setreg(bas, UART_IER_REG, cr); 261220297Sadrian uart_barrier(bas); 262220297Sadrian} 263220297Sadrian 264220297Sadrianstatic int 265220297Sadrianrt305x_uart_bus_attach(struct uart_softc *sc) 266220297Sadrian{ 267220297Sadrian struct uart_bas *bas; 268220297Sadrian struct uart_devinfo *di; 269220297Sadrian 270220297Sadrian bas = &sc->sc_bas; 271220297Sadrian if (sc->sc_sysdev != NULL) { 272220297Sadrian di = sc->sc_sysdev; 273220297Sadrian rt305x_uart_init(bas, di->baudrate, di->databits, di->stopbits, 274220297Sadrian di->parity); 275220297Sadrian } else { 276220297Sadrian rt305x_uart_init(bas, 115200, 8, 1, 0); 277220297Sadrian } 278220297Sadrian 279220297Sadrian (void)rt305x_uart_bus_getsig(sc); 280220297Sadrian 281220297Sadrian /* Enable FIFO */ 282220297Sadrian uart_setreg(bas, UART_FCR_REG, 283220297Sadrian uart_getreg(bas, UART_FCR_REG) | 284220297Sadrian UART_FCR_FIFOEN | UART_FCR_TXTGR_1 | UART_FCR_RXTGR_1); 285262649Simp uart_barrier(bas); 286220297Sadrian /* Enable interrupts */ 287220297Sadrian uart_setreg(bas, UART_IER_REG, 288220297Sadrian UART_IER_EDSSI | UART_IER_ELSI | UART_IER_ERBFI); 289220297Sadrian uart_barrier(bas); 290220297Sadrian 291220297Sadrian return (0); 292220297Sadrian} 293220297Sadrian 294220297Sadrianstatic int 295220297Sadrianrt305x_uart_bus_detach(struct uart_softc *sc) 296220297Sadrian{ 297220297Sadrian 298220297Sadrian return (0); 299220297Sadrian} 300220297Sadrian 301220297Sadrianstatic int 302220297Sadrianrt305x_uart_bus_flush(struct uart_softc *sc, int what) 303220297Sadrian{ 304220297Sadrian struct uart_bas *bas = &sc->sc_bas; 305220297Sadrian uint32_t fcr = uart_getreg(bas, UART_FCR_REG); 306220297Sadrian if (what & UART_FLUSH_TRANSMITTER) { 307220297Sadrian uart_setreg(bas, UART_FCR_REG, fcr|UART_FCR_TXRST); 308220297Sadrian uart_barrier(bas); 309220297Sadrian } 310220297Sadrian if (what & UART_FLUSH_RECEIVER) { 311220297Sadrian uart_setreg(bas, UART_FCR_REG, fcr|UART_FCR_RXRST); 312220297Sadrian uart_barrier(bas); 313220297Sadrian } 314220297Sadrian uart_setreg(bas, UART_FCR_REG, fcr); 315220297Sadrian uart_barrier(bas); 316220297Sadrian return (0); 317220297Sadrian} 318220297Sadrian 319220297Sadrianstatic int 320220297Sadrianrt305x_uart_bus_getsig(struct uart_softc *sc) 321220297Sadrian{ 322220297Sadrian uint32_t new, old, sig; 323220297Sadrian uint8_t bes; 324220297Sadrian 325220297Sadrian do { 326220297Sadrian old = sc->sc_hwsig; 327220297Sadrian sig = old; 328220297Sadrian uart_lock(sc->sc_hwmtx); 329220297Sadrian bes = uart_getreg(&sc->sc_bas, UART_MSR_REG); 330220297Sadrian uart_unlock(sc->sc_hwmtx); 331220297Sadrian /* XXX: chip can show delta */ 332220297Sadrian SIGCHG(bes & UART_MSR_CTS, sig, SER_CTS, SER_DCTS); 333220297Sadrian SIGCHG(bes & UART_MSR_DCD, sig, SER_DCD, SER_DDCD); 334220297Sadrian SIGCHG(bes & UART_MSR_DSR, sig, SER_DSR, SER_DDSR); 335220297Sadrian new = sig & ~SER_MASK_DELTA; 336220297Sadrian } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 337220297Sadrian 338220297Sadrian return (sig); 339220297Sadrian} 340220297Sadrian 341220297Sadrianstatic int 342220297Sadrianrt305x_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 343220297Sadrian{ 344220297Sadrian struct uart_bas *bas; 345220297Sadrian int baudrate, divisor, error; 346220297Sadrian 347220297Sadrian bas = &sc->sc_bas; 348220297Sadrian error = 0; 349220297Sadrian uart_lock(sc->sc_hwmtx); 350220297Sadrian switch (request) { 351220297Sadrian case UART_IOCTL_BREAK: 352220297Sadrian /* TODO: Send BREAK */ 353220297Sadrian break; 354220297Sadrian case UART_IOCTL_BAUD: 355220297Sadrian divisor = uart_getreg(bas, UART_CDDL_REG); 356220297Sadrian baudrate = bas->rclk / (divisor * 16); 357220297Sadrian *(int*)data = baudrate; 358220297Sadrian break; 359220297Sadrian default: 360220297Sadrian error = EINVAL; 361220297Sadrian break; 362220297Sadrian } 363220297Sadrian uart_unlock(sc->sc_hwmtx); 364220297Sadrian return (error); 365220297Sadrian} 366220297Sadrian 367220297Sadrianstatic int 368220297Sadrianrt305x_uart_bus_ipend(struct uart_softc *sc) 369220297Sadrian{ 370220297Sadrian struct uart_bas *bas; 371220297Sadrian int ipend; 372220297Sadrian uint8_t iir, lsr, msr; 373220297Sadrian 374220297Sadrian bas = &sc->sc_bas; 375220297Sadrian ipend = 0; 376220297Sadrian 377220297Sadrian uart_lock(sc->sc_hwmtx); 378220297Sadrian iir = uart_getreg(&sc->sc_bas, UART_IIR_REG); 379220297Sadrian lsr = uart_getreg(&sc->sc_bas, UART_LSR_REG); 380220297Sadrian uart_setreg(&sc->sc_bas, UART_LSR_REG, lsr); 381220297Sadrian msr = uart_getreg(&sc->sc_bas, UART_MSR_REG); 382220297Sadrian uart_setreg(&sc->sc_bas, UART_MSR_REG, msr); 383220297Sadrian if (iir & UART_IIR_INTP) { 384220297Sadrian uart_unlock(sc->sc_hwmtx); 385220297Sadrian return (0); 386220297Sadrian } 387220297Sadrian 388220297Sadrian 389220297Sadrian switch ((iir >> 1) & 0x07) { 390220297Sadrian case UART_IIR_ID_THRE: 391220297Sadrian ipend |= SER_INT_TXIDLE; 392220297Sadrian break; 393220297Sadrian case UART_IIR_ID_DR2: 394220297Sadrian rt305x_uart_bus_flush(sc, UART_FLUSH_RECEIVER); 395220297Sadrian /* passthrough */ 396220297Sadrian case UART_IIR_ID_DR: 397220297Sadrian ipend |= SER_INT_RXREADY; 398220297Sadrian break; 399220297Sadrian case UART_IIR_ID_MST: 400220297Sadrian case UART_IIR_ID_LINESTATUS: 401220297Sadrian ipend |= SER_INT_SIGCHG; 402220297Sadrian if (lsr & UART_LSR_BI) 403220297Sadrian { 404220297Sadrian ipend |= SER_INT_BREAK; 405220297Sadrian#ifdef KDB 406220297Sadrian breakpoint(); 407220297Sadrian#endif 408220297Sadrian } 409220297Sadrian if (lsr & UART_LSR_OE) 410220297Sadrian ipend |= SER_INT_OVERRUN; 411220297Sadrian break; 412220297Sadrian default: 413220297Sadrian /* XXX: maybe return error here */ 414220297Sadrian break; 415220297Sadrian } 416220297Sadrian 417220297Sadrian uart_unlock(sc->sc_hwmtx); 418220297Sadrian 419220297Sadrian return (ipend); 420220297Sadrian} 421220297Sadrian 422220297Sadrianstatic int 423220297Sadrianrt305x_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, 424220297Sadrian int stopbits, int parity) 425220297Sadrian{ 426220297Sadrian uart_lock(sc->sc_hwmtx); 427220297Sadrian rt305x_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity); 428220297Sadrian uart_unlock(sc->sc_hwmtx); 429220297Sadrian return (0); 430220297Sadrian} 431220297Sadrian 432220297Sadrianstatic int 433220297Sadrianrt305x_uart_bus_probe(struct uart_softc *sc) 434220297Sadrian{ 435220297Sadrian char buf[80]; 436220297Sadrian int error; 437220297Sadrian 438220297Sadrian error = rt305x_uart_probe(&sc->sc_bas); 439220297Sadrian if (error) 440220297Sadrian return (error); 441220297Sadrian 442248965Sian sc->sc_rxfifosz = 16; 443248965Sian sc->sc_txfifosz = 16; 444248965Sian 445220297Sadrian snprintf(buf, sizeof(buf), "rt305x_uart"); 446220297Sadrian device_set_desc_copy(sc->sc_dev, buf); 447220297Sadrian 448220297Sadrian return (0); 449220297Sadrian} 450220297Sadrian 451220297Sadrianstatic int 452220297Sadrianrt305x_uart_bus_receive(struct uart_softc *sc) 453220297Sadrian{ 454220297Sadrian struct uart_bas *bas; 455220297Sadrian int xc; 456220297Sadrian uint8_t lsr; 457220297Sadrian 458220297Sadrian bas = &sc->sc_bas; 459220297Sadrian uart_lock(sc->sc_hwmtx); 460220297Sadrian lsr = uart_getreg(bas, UART_LSR_REG); 461220297Sadrian while ((lsr & UART_LSR_DR)) { 462220297Sadrian if (uart_rx_full(sc)) { 463220297Sadrian sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 464220297Sadrian break; 465220297Sadrian } 466220297Sadrian xc = 0; 467220297Sadrian xc = uart_getreg(bas, UART_RX_REG); 468220297Sadrian if (lsr & UART_LSR_FE) 469220297Sadrian xc |= UART_STAT_FRAMERR; 470220297Sadrian if (lsr & UART_LSR_PE) 471220297Sadrian xc |= UART_STAT_PARERR; 472220297Sadrian if (lsr & UART_LSR_OE) 473220297Sadrian xc |= UART_STAT_OVERRUN; 474220297Sadrian uart_barrier(bas); 475220297Sadrian uart_rx_put(sc, xc); 476220297Sadrian lsr = uart_getreg(bas, UART_LSR_REG); 477220297Sadrian } 478220297Sadrian 479220297Sadrian uart_unlock(sc->sc_hwmtx); 480220297Sadrian return (0); 481220297Sadrian} 482220297Sadrian 483220297Sadrianstatic int 484220297Sadrianrt305x_uart_bus_setsig(struct uart_softc *sc, int sig) 485220297Sadrian{ 486220297Sadrian 487220297Sadrian /* TODO: implement (?) */ 488220297Sadrian return (0); 489220297Sadrian} 490220297Sadrian 491220297Sadrianstatic int 492220297Sadrianrt305x_uart_bus_transmit(struct uart_softc *sc) 493220297Sadrian{ 494220297Sadrian struct uart_bas *bas = &sc->sc_bas; 495220297Sadrian int i; 496220297Sadrian 497220297Sadrian if (!uart_output) return (0); 498220297Sadrian 499220297Sadrian bas = &sc->sc_bas; 500220297Sadrian uart_lock(sc->sc_hwmtx); 501220297Sadrian while ((uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE) == 0) 502220297Sadrian ; 503220297Sadrian rt305x_uart_enable_txintr(sc); 504220297Sadrian for (i = 0; i < sc->sc_txdatasz; i++) { 505220297Sadrian uart_setreg(bas, UART_TX_REG, sc->sc_txbuf[i]); 506220297Sadrian uart_barrier(bas); 507220297Sadrian } 508220297Sadrian sc->sc_txbusy = 1; 509220297Sadrian uart_unlock(sc->sc_hwmtx); 510220297Sadrian return (0); 511220297Sadrian} 512262649Simp 513262649Simpstatic void 514262649Simprt305x_uart_bus_grab(struct uart_softc *sc) 515262649Simp{ 516262649Simp struct uart_bas *bas = &sc->sc_bas; 517262649Simp 518262649Simp /* disable interrupts -- XXX not sure which one is RX, so kill them all */ 519262649Simp uart_lock(sc->sc_hwmtx); 520262649Simp uart_setreg(bas, UART_IER_REG, 0); 521262649Simp uart_barrier(bas); 522262649Simp uart_unlock(sc->sc_hwmtx); 523262649Simp} 524262649Simp 525262649Simpstatic void 526262649Simprt305x_uart_bus_ungrab(struct uart_softc *sc) 527262649Simp{ 528262649Simp struct uart_bas *bas = &sc->sc_bas; 529262649Simp 530262649Simp /* Enable interrupts */ 531262649Simp uart_lock(sc->sc_hwmtx); 532262649Simp uart_setreg(bas, UART_IER_REG, 533262649Simp UART_IER_EDSSI | UART_IER_ELSI | UART_IER_ERBFI); 534262649Simp uart_barrier(bas); 535262649Simp uart_unlock(sc->sc_hwmtx); 536262649Simp} 537