1*a2c472e7SAleksandr Rybalko /*- 2*a2c472e7SAleksandr Rybalko * Copyright (c) 2012 The FreeBSD Foundation 3*a2c472e7SAleksandr Rybalko * All rights reserved. 4*a2c472e7SAleksandr Rybalko * 5*a2c472e7SAleksandr Rybalko * This software was developed by Oleksandr Rybalko under sponsorship 6*a2c472e7SAleksandr Rybalko * from the FreeBSD Foundation. 7*a2c472e7SAleksandr Rybalko * 8*a2c472e7SAleksandr Rybalko * Redistribution and use in source and binary forms, with or without 9*a2c472e7SAleksandr Rybalko * modification, are permitted provided that the following conditions 10*a2c472e7SAleksandr Rybalko * are met: 11*a2c472e7SAleksandr Rybalko * 1. Redistributions of source code must retain the above copyright 12*a2c472e7SAleksandr Rybalko * notice, this list of conditions and the following disclaimer. 13*a2c472e7SAleksandr Rybalko * 2. Redistributions in binary form must reproduce the above copyright 14*a2c472e7SAleksandr Rybalko * notice, this list of conditions and the following disclaimer in the 15*a2c472e7SAleksandr Rybalko * documentation and/or other materials provided with the distribution. 16*a2c472e7SAleksandr Rybalko * 17*a2c472e7SAleksandr Rybalko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18*a2c472e7SAleksandr Rybalko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*a2c472e7SAleksandr Rybalko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*a2c472e7SAleksandr Rybalko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21*a2c472e7SAleksandr Rybalko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*a2c472e7SAleksandr Rybalko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*a2c472e7SAleksandr Rybalko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*a2c472e7SAleksandr Rybalko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*a2c472e7SAleksandr Rybalko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*a2c472e7SAleksandr Rybalko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*a2c472e7SAleksandr Rybalko * SUCH DAMAGE. 28*a2c472e7SAleksandr Rybalko */ 29*a2c472e7SAleksandr Rybalko 30*a2c472e7SAleksandr Rybalko #include <sys/cdefs.h> 31*a2c472e7SAleksandr Rybalko __FBSDID("$FreeBSD$"); 32*a2c472e7SAleksandr Rybalko 33*a2c472e7SAleksandr Rybalko #include "opt_ddb.h" 34*a2c472e7SAleksandr Rybalko 35*a2c472e7SAleksandr Rybalko #include <sys/param.h> 36*a2c472e7SAleksandr Rybalko #include <sys/systm.h> 37*a2c472e7SAleksandr Rybalko #include <sys/bus.h> 38*a2c472e7SAleksandr Rybalko #include <sys/conf.h> 39*a2c472e7SAleksandr Rybalko #include <sys/kdb.h> 40*a2c472e7SAleksandr Rybalko #include <machine/bus.h> 41*a2c472e7SAleksandr Rybalko #include <machine/fdt.h> 42*a2c472e7SAleksandr Rybalko 43*a2c472e7SAleksandr Rybalko #include <dev/uart/uart.h> 44*a2c472e7SAleksandr Rybalko #include <dev/uart/uart_cpu.h> 45*a2c472e7SAleksandr Rybalko #include <dev/uart/uart_bus.h> 46*a2c472e7SAleksandr Rybalko 47*a2c472e7SAleksandr Rybalko #include <dev/uart/uart_dev_imx5xx.h> 48*a2c472e7SAleksandr Rybalko 49*a2c472e7SAleksandr Rybalko #include "uart_if.h" 50*a2c472e7SAleksandr Rybalko /* 51*a2c472e7SAleksandr Rybalko * Low-level UART interface. 52*a2c472e7SAleksandr Rybalko */ 53*a2c472e7SAleksandr Rybalko static int imx_uart_probe(struct uart_bas *bas); 54*a2c472e7SAleksandr Rybalko static void imx_uart_init(struct uart_bas *bas, int, int, int, int); 55*a2c472e7SAleksandr Rybalko static void imx_uart_term(struct uart_bas *bas); 56*a2c472e7SAleksandr Rybalko static void imx_uart_putc(struct uart_bas *bas, int); 57*a2c472e7SAleksandr Rybalko static int imx_uart_rxready(struct uart_bas *bas); 58*a2c472e7SAleksandr Rybalko static int imx_uart_getc(struct uart_bas *bas, struct mtx *); 59*a2c472e7SAleksandr Rybalko 60*a2c472e7SAleksandr Rybalko static struct uart_ops uart_imx_uart_ops = { 61*a2c472e7SAleksandr Rybalko .probe = imx_uart_probe, 62*a2c472e7SAleksandr Rybalko .init = imx_uart_init, 63*a2c472e7SAleksandr Rybalko .term = imx_uart_term, 64*a2c472e7SAleksandr Rybalko .putc = imx_uart_putc, 65*a2c472e7SAleksandr Rybalko .rxready = imx_uart_rxready, 66*a2c472e7SAleksandr Rybalko .getc = imx_uart_getc, 67*a2c472e7SAleksandr Rybalko }; 68*a2c472e7SAleksandr Rybalko 69*a2c472e7SAleksandr Rybalko static int 70*a2c472e7SAleksandr Rybalko imx_uart_probe(struct uart_bas *bas) 71*a2c472e7SAleksandr Rybalko { 72*a2c472e7SAleksandr Rybalko 73*a2c472e7SAleksandr Rybalko return (0); 74*a2c472e7SAleksandr Rybalko } 75*a2c472e7SAleksandr Rybalko 76*a2c472e7SAleksandr Rybalko static void 77*a2c472e7SAleksandr Rybalko imx_uart_init(struct uart_bas *bas, int baudrate, int databits, 78*a2c472e7SAleksandr Rybalko int stopbits, int parity) 79*a2c472e7SAleksandr Rybalko { 80*a2c472e7SAleksandr Rybalko 81*a2c472e7SAleksandr Rybalko } 82*a2c472e7SAleksandr Rybalko 83*a2c472e7SAleksandr Rybalko static void 84*a2c472e7SAleksandr Rybalko imx_uart_term(struct uart_bas *bas) 85*a2c472e7SAleksandr Rybalko { 86*a2c472e7SAleksandr Rybalko 87*a2c472e7SAleksandr Rybalko } 88*a2c472e7SAleksandr Rybalko 89*a2c472e7SAleksandr Rybalko static void 90*a2c472e7SAleksandr Rybalko imx_uart_putc(struct uart_bas *bas, int c) 91*a2c472e7SAleksandr Rybalko { 92*a2c472e7SAleksandr Rybalko 93*a2c472e7SAleksandr Rybalko while (!(IS(bas, USR2, TXFE))) 94*a2c472e7SAleksandr Rybalko ; 95*a2c472e7SAleksandr Rybalko SETREG(bas, REG(UTXD), c); 96*a2c472e7SAleksandr Rybalko } 97*a2c472e7SAleksandr Rybalko 98*a2c472e7SAleksandr Rybalko static int 99*a2c472e7SAleksandr Rybalko imx_uart_rxready(struct uart_bas *bas) 100*a2c472e7SAleksandr Rybalko { 101*a2c472e7SAleksandr Rybalko 102*a2c472e7SAleksandr Rybalko return ((IS(bas, USR2, RDR)) ? 1 : 0); 103*a2c472e7SAleksandr Rybalko } 104*a2c472e7SAleksandr Rybalko 105*a2c472e7SAleksandr Rybalko static int 106*a2c472e7SAleksandr Rybalko imx_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) 107*a2c472e7SAleksandr Rybalko { 108*a2c472e7SAleksandr Rybalko int c; 109*a2c472e7SAleksandr Rybalko 110*a2c472e7SAleksandr Rybalko uart_lock(hwmtx); 111*a2c472e7SAleksandr Rybalko while (!(IS(bas, USR2, RDR))) 112*a2c472e7SAleksandr Rybalko ; 113*a2c472e7SAleksandr Rybalko 114*a2c472e7SAleksandr Rybalko c = GETREG(bas, REG(URXD)); 115*a2c472e7SAleksandr Rybalko uart_unlock(hwmtx); 116*a2c472e7SAleksandr Rybalko #if defined(KDB) 117*a2c472e7SAleksandr Rybalko if (c & FLD(URXD, BRK)) { 118*a2c472e7SAleksandr Rybalko if (kdb_break()) 119*a2c472e7SAleksandr Rybalko return (0); 120*a2c472e7SAleksandr Rybalko } 121*a2c472e7SAleksandr Rybalko #endif 122*a2c472e7SAleksandr Rybalko return (c & 0xff); 123*a2c472e7SAleksandr Rybalko } 124*a2c472e7SAleksandr Rybalko 125*a2c472e7SAleksandr Rybalko /* 126*a2c472e7SAleksandr Rybalko * High-level UART interface. 127*a2c472e7SAleksandr Rybalko */ 128*a2c472e7SAleksandr Rybalko struct imx_uart_softc { 129*a2c472e7SAleksandr Rybalko struct uart_softc base; 130*a2c472e7SAleksandr Rybalko }; 131*a2c472e7SAleksandr Rybalko 132*a2c472e7SAleksandr Rybalko static int imx_uart_bus_attach(struct uart_softc *); 133*a2c472e7SAleksandr Rybalko static int imx_uart_bus_detach(struct uart_softc *); 134*a2c472e7SAleksandr Rybalko static int imx_uart_bus_flush(struct uart_softc *, int); 135*a2c472e7SAleksandr Rybalko static int imx_uart_bus_getsig(struct uart_softc *); 136*a2c472e7SAleksandr Rybalko static int imx_uart_bus_ioctl(struct uart_softc *, int, intptr_t); 137*a2c472e7SAleksandr Rybalko static int imx_uart_bus_ipend(struct uart_softc *); 138*a2c472e7SAleksandr Rybalko static int imx_uart_bus_param(struct uart_softc *, int, int, int, int); 139*a2c472e7SAleksandr Rybalko static int imx_uart_bus_probe(struct uart_softc *); 140*a2c472e7SAleksandr Rybalko static int imx_uart_bus_receive(struct uart_softc *); 141*a2c472e7SAleksandr Rybalko static int imx_uart_bus_setsig(struct uart_softc *, int); 142*a2c472e7SAleksandr Rybalko static int imx_uart_bus_transmit(struct uart_softc *); 143*a2c472e7SAleksandr Rybalko 144*a2c472e7SAleksandr Rybalko static kobj_method_t imx_uart_methods[] = { 145*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_attach, imx_uart_bus_attach), 146*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_detach, imx_uart_bus_detach), 147*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_flush, imx_uart_bus_flush), 148*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_getsig, imx_uart_bus_getsig), 149*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_ioctl, imx_uart_bus_ioctl), 150*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_ipend, imx_uart_bus_ipend), 151*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_param, imx_uart_bus_param), 152*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_probe, imx_uart_bus_probe), 153*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_receive, imx_uart_bus_receive), 154*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_setsig, imx_uart_bus_setsig), 155*a2c472e7SAleksandr Rybalko KOBJMETHOD(uart_transmit, imx_uart_bus_transmit), 156*a2c472e7SAleksandr Rybalko { 0, 0 } 157*a2c472e7SAleksandr Rybalko }; 158*a2c472e7SAleksandr Rybalko 159*a2c472e7SAleksandr Rybalko struct uart_class uart_imx_class = { 160*a2c472e7SAleksandr Rybalko "imx", 161*a2c472e7SAleksandr Rybalko imx_uart_methods, 162*a2c472e7SAleksandr Rybalko sizeof(struct imx_uart_softc), 163*a2c472e7SAleksandr Rybalko .uc_ops = &uart_imx_uart_ops, 164*a2c472e7SAleksandr Rybalko .uc_range = 0x100, 165*a2c472e7SAleksandr Rybalko .uc_rclk = 24000000 /* TODO: get value from CCM */ 166*a2c472e7SAleksandr Rybalko }; 167*a2c472e7SAleksandr Rybalko 168*a2c472e7SAleksandr Rybalko #define SIGCHG(c, i, s, d) \ 169*a2c472e7SAleksandr Rybalko if (c) { \ 170*a2c472e7SAleksandr Rybalko i |= (i & s) ? s : s | d; \ 171*a2c472e7SAleksandr Rybalko } else { \ 172*a2c472e7SAleksandr Rybalko i = (i & s) ? (i & ~s) | d : i; \ 173*a2c472e7SAleksandr Rybalko } 174*a2c472e7SAleksandr Rybalko 175*a2c472e7SAleksandr Rybalko static int 176*a2c472e7SAleksandr Rybalko imx_uart_bus_attach(struct uart_softc *sc) 177*a2c472e7SAleksandr Rybalko { 178*a2c472e7SAleksandr Rybalko struct uart_bas *bas; 179*a2c472e7SAleksandr Rybalko struct uart_devinfo *di; 180*a2c472e7SAleksandr Rybalko 181*a2c472e7SAleksandr Rybalko bas = &sc->sc_bas; 182*a2c472e7SAleksandr Rybalko if (sc->sc_sysdev != NULL) { 183*a2c472e7SAleksandr Rybalko di = sc->sc_sysdev; 184*a2c472e7SAleksandr Rybalko imx_uart_init(bas, di->baudrate, di->databits, di->stopbits, 185*a2c472e7SAleksandr Rybalko di->parity); 186*a2c472e7SAleksandr Rybalko } else { 187*a2c472e7SAleksandr Rybalko imx_uart_init(bas, 115200, 8, 1, 0); 188*a2c472e7SAleksandr Rybalko } 189*a2c472e7SAleksandr Rybalko 190*a2c472e7SAleksandr Rybalko sc->sc_rxfifosz = 1; 191*a2c472e7SAleksandr Rybalko sc->sc_txfifosz = 1; 192*a2c472e7SAleksandr Rybalko 193*a2c472e7SAleksandr Rybalko (void)imx_uart_bus_getsig(sc); 194*a2c472e7SAleksandr Rybalko 195*a2c472e7SAleksandr Rybalko /* XXX workaround to have working console on manut prompt */ 196*a2c472e7SAleksandr Rybalko if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE){ 197*a2c472e7SAleksandr Rybalko DIS(bas, UCR4, DREN); 198*a2c472e7SAleksandr Rybalko } else { 199*a2c472e7SAleksandr Rybalko ENA(bas, UCR4, DREN); 200*a2c472e7SAleksandr Rybalko } 201*a2c472e7SAleksandr Rybalko DIS(bas, UCR1, RRDYEN); 202*a2c472e7SAleksandr Rybalko DIS(bas, UCR1, IDEN); 203*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, RXDSEN); 204*a2c472e7SAleksandr Rybalko DIS(bas, UCR2, ATEN); 205*a2c472e7SAleksandr Rybalko DIS(bas, UCR1, TXMPTYEN); 206*a2c472e7SAleksandr Rybalko DIS(bas, UCR1, TRDYEN); 207*a2c472e7SAleksandr Rybalko DIS(bas, UCR4, TCEN); 208*a2c472e7SAleksandr Rybalko DIS(bas, UCR4, OREN); 209*a2c472e7SAleksandr Rybalko ENA(bas, UCR4, BKEN); 210*a2c472e7SAleksandr Rybalko DIS(bas, UCR4, WKEN); 211*a2c472e7SAleksandr Rybalko DIS(bas, UCR1, ADEN); 212*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, ACIEN); 213*a2c472e7SAleksandr Rybalko DIS(bas, UCR2, ESCI); 214*a2c472e7SAleksandr Rybalko DIS(bas, UCR4, ENIRI); 215*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, AIRINTEN); 216*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, AWAKEN); 217*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, FRAERREN); 218*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, PARERREN); 219*a2c472e7SAleksandr Rybalko DIS(bas, UCR1, RTSDEN); 220*a2c472e7SAleksandr Rybalko DIS(bas, UCR2, RTSEN); 221*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, DTREN); 222*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, RI); 223*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, DCD); 224*a2c472e7SAleksandr Rybalko DIS(bas, UCR3, DTRDEN); 225*a2c472e7SAleksandr Rybalko 226*a2c472e7SAleksandr Rybalko /* ACK all interrupts */ 227*a2c472e7SAleksandr Rybalko SETREG(bas, REG(USR1), 0xffff); 228*a2c472e7SAleksandr Rybalko SETREG(bas, REG(USR2), 0xffff); 229*a2c472e7SAleksandr Rybalko return (0); 230*a2c472e7SAleksandr Rybalko } 231*a2c472e7SAleksandr Rybalko 232*a2c472e7SAleksandr Rybalko static int 233*a2c472e7SAleksandr Rybalko imx_uart_bus_detach(struct uart_softc *sc) 234*a2c472e7SAleksandr Rybalko { 235*a2c472e7SAleksandr Rybalko 236*a2c472e7SAleksandr Rybalko SETREG(&sc->sc_bas, REG(UCR4), 0); 237*a2c472e7SAleksandr Rybalko 238*a2c472e7SAleksandr Rybalko return (0); 239*a2c472e7SAleksandr Rybalko } 240*a2c472e7SAleksandr Rybalko 241*a2c472e7SAleksandr Rybalko static int 242*a2c472e7SAleksandr Rybalko imx_uart_bus_flush(struct uart_softc *sc, int what) 243*a2c472e7SAleksandr Rybalko { 244*a2c472e7SAleksandr Rybalko 245*a2c472e7SAleksandr Rybalko /* TODO */ 246*a2c472e7SAleksandr Rybalko return (0); 247*a2c472e7SAleksandr Rybalko } 248*a2c472e7SAleksandr Rybalko 249*a2c472e7SAleksandr Rybalko static int 250*a2c472e7SAleksandr Rybalko imx_uart_bus_getsig(struct uart_softc *sc) 251*a2c472e7SAleksandr Rybalko { 252*a2c472e7SAleksandr Rybalko uint32_t new, old, sig; 253*a2c472e7SAleksandr Rybalko uint8_t bes; 254*a2c472e7SAleksandr Rybalko 255*a2c472e7SAleksandr Rybalko do { 256*a2c472e7SAleksandr Rybalko old = sc->sc_hwsig; 257*a2c472e7SAleksandr Rybalko sig = old; 258*a2c472e7SAleksandr Rybalko uart_lock(sc->sc_hwmtx); 259*a2c472e7SAleksandr Rybalko bes = GETREG(&sc->sc_bas, REG(USR2)); 260*a2c472e7SAleksandr Rybalko uart_unlock(sc->sc_hwmtx); 261*a2c472e7SAleksandr Rybalko /* XXX: chip can show delta */ 262*a2c472e7SAleksandr Rybalko SIGCHG(bes & FLD(USR2, DCDIN), sig, SER_DCD, SER_DDCD); 263*a2c472e7SAleksandr Rybalko new = sig & ~SER_MASK_DELTA; 264*a2c472e7SAleksandr Rybalko } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 265*a2c472e7SAleksandr Rybalko 266*a2c472e7SAleksandr Rybalko return (sig); 267*a2c472e7SAleksandr Rybalko } 268*a2c472e7SAleksandr Rybalko 269*a2c472e7SAleksandr Rybalko static int 270*a2c472e7SAleksandr Rybalko imx_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 271*a2c472e7SAleksandr Rybalko { 272*a2c472e7SAleksandr Rybalko struct uart_bas *bas; 273*a2c472e7SAleksandr Rybalko int error; 274*a2c472e7SAleksandr Rybalko 275*a2c472e7SAleksandr Rybalko bas = &sc->sc_bas; 276*a2c472e7SAleksandr Rybalko error = 0; 277*a2c472e7SAleksandr Rybalko uart_lock(sc->sc_hwmtx); 278*a2c472e7SAleksandr Rybalko switch (request) { 279*a2c472e7SAleksandr Rybalko case UART_IOCTL_BREAK: 280*a2c472e7SAleksandr Rybalko /* TODO */ 281*a2c472e7SAleksandr Rybalko break; 282*a2c472e7SAleksandr Rybalko case UART_IOCTL_BAUD: 283*a2c472e7SAleksandr Rybalko /* TODO */ 284*a2c472e7SAleksandr Rybalko *(int*)data = 115200; 285*a2c472e7SAleksandr Rybalko break; 286*a2c472e7SAleksandr Rybalko default: 287*a2c472e7SAleksandr Rybalko error = EINVAL; 288*a2c472e7SAleksandr Rybalko break; 289*a2c472e7SAleksandr Rybalko } 290*a2c472e7SAleksandr Rybalko uart_unlock(sc->sc_hwmtx); 291*a2c472e7SAleksandr Rybalko 292*a2c472e7SAleksandr Rybalko return (error); 293*a2c472e7SAleksandr Rybalko } 294*a2c472e7SAleksandr Rybalko 295*a2c472e7SAleksandr Rybalko static int 296*a2c472e7SAleksandr Rybalko imx_uart_bus_ipend(struct uart_softc *sc) 297*a2c472e7SAleksandr Rybalko { 298*a2c472e7SAleksandr Rybalko struct uart_bas *bas; 299*a2c472e7SAleksandr Rybalko int ipend; 300*a2c472e7SAleksandr Rybalko uint32_t usr1, usr2; 301*a2c472e7SAleksandr Rybalko uint32_t ucr1, ucr4; 302*a2c472e7SAleksandr Rybalko 303*a2c472e7SAleksandr Rybalko bas = &sc->sc_bas; 304*a2c472e7SAleksandr Rybalko ipend = 0; 305*a2c472e7SAleksandr Rybalko 306*a2c472e7SAleksandr Rybalko uart_lock(sc->sc_hwmtx); 307*a2c472e7SAleksandr Rybalko 308*a2c472e7SAleksandr Rybalko /* Read pending interrupts */ 309*a2c472e7SAleksandr Rybalko usr1 = GETREG(bas, REG(USR1)); 310*a2c472e7SAleksandr Rybalko usr2 = GETREG(bas, REG(USR2)); 311*a2c472e7SAleksandr Rybalko /* ACK interrupts */ 312*a2c472e7SAleksandr Rybalko SETREG(bas, REG(USR1), usr1); 313*a2c472e7SAleksandr Rybalko SETREG(bas, REG(USR2), usr2); 314*a2c472e7SAleksandr Rybalko 315*a2c472e7SAleksandr Rybalko ucr1 = GETREG(bas, REG(UCR1)); 316*a2c472e7SAleksandr Rybalko ucr4 = GETREG(bas, REG(UCR4)); 317*a2c472e7SAleksandr Rybalko 318*a2c472e7SAleksandr Rybalko if ((usr2 & FLD(USR2, TXFE)) && (ucr1 & FLD(UCR1, TXMPTYEN))) { 319*a2c472e7SAleksandr Rybalko DIS(bas, UCR1, TXMPTYEN); 320*a2c472e7SAleksandr Rybalko /* Continue TXing */ 321*a2c472e7SAleksandr Rybalko ipend |= SER_INT_TXIDLE; 322*a2c472e7SAleksandr Rybalko } 323*a2c472e7SAleksandr Rybalko if ((usr2 & FLD(USR2, RDR)) && (ucr4 & FLD(UCR4, DREN))) { 324*a2c472e7SAleksandr Rybalko DIS(bas, UCR4, DREN); 325*a2c472e7SAleksandr Rybalko /* Wow, new char on input */ 326*a2c472e7SAleksandr Rybalko ipend |= SER_INT_RXREADY; 327*a2c472e7SAleksandr Rybalko } 328*a2c472e7SAleksandr Rybalko if ((usr2 & FLD(USR2, BRCD)) && (ucr4 & FLD(UCR4, BKEN))) 329*a2c472e7SAleksandr Rybalko ipend |= SER_INT_BREAK; 330*a2c472e7SAleksandr Rybalko 331*a2c472e7SAleksandr Rybalko uart_unlock(sc->sc_hwmtx); 332*a2c472e7SAleksandr Rybalko 333*a2c472e7SAleksandr Rybalko return (ipend); 334*a2c472e7SAleksandr Rybalko } 335*a2c472e7SAleksandr Rybalko 336*a2c472e7SAleksandr Rybalko static int 337*a2c472e7SAleksandr Rybalko imx_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, 338*a2c472e7SAleksandr Rybalko int stopbits, int parity) 339*a2c472e7SAleksandr Rybalko { 340*a2c472e7SAleksandr Rybalko 341*a2c472e7SAleksandr Rybalko uart_lock(sc->sc_hwmtx); 342*a2c472e7SAleksandr Rybalko imx_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity); 343*a2c472e7SAleksandr Rybalko uart_unlock(sc->sc_hwmtx); 344*a2c472e7SAleksandr Rybalko return (0); 345*a2c472e7SAleksandr Rybalko } 346*a2c472e7SAleksandr Rybalko 347*a2c472e7SAleksandr Rybalko static int 348*a2c472e7SAleksandr Rybalko imx_uart_bus_probe(struct uart_softc *sc) 349*a2c472e7SAleksandr Rybalko { 350*a2c472e7SAleksandr Rybalko int error; 351*a2c472e7SAleksandr Rybalko 352*a2c472e7SAleksandr Rybalko error = imx_uart_probe(&sc->sc_bas); 353*a2c472e7SAleksandr Rybalko if (error) 354*a2c472e7SAleksandr Rybalko return (error); 355*a2c472e7SAleksandr Rybalko 356*a2c472e7SAleksandr Rybalko device_set_desc(sc->sc_dev, "imx_uart"); 357*a2c472e7SAleksandr Rybalko return (0); 358*a2c472e7SAleksandr Rybalko } 359*a2c472e7SAleksandr Rybalko 360*a2c472e7SAleksandr Rybalko static int 361*a2c472e7SAleksandr Rybalko imx_uart_bus_receive(struct uart_softc *sc) 362*a2c472e7SAleksandr Rybalko { 363*a2c472e7SAleksandr Rybalko struct uart_bas *bas; 364*a2c472e7SAleksandr Rybalko int xc, out; 365*a2c472e7SAleksandr Rybalko 366*a2c472e7SAleksandr Rybalko bas = &sc->sc_bas; 367*a2c472e7SAleksandr Rybalko uart_lock(sc->sc_hwmtx); 368*a2c472e7SAleksandr Rybalko 369*a2c472e7SAleksandr Rybalko /* Read while we have anything in FIFO */ 370*a2c472e7SAleksandr Rybalko while (IS(bas, USR2, RDR)) { 371*a2c472e7SAleksandr Rybalko if (uart_rx_full(sc)) { 372*a2c472e7SAleksandr Rybalko /* No space left in input buffer */ 373*a2c472e7SAleksandr Rybalko sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 374*a2c472e7SAleksandr Rybalko break; 375*a2c472e7SAleksandr Rybalko } 376*a2c472e7SAleksandr Rybalko out = 0; 377*a2c472e7SAleksandr Rybalko xc = GETREG(bas, REG(URXD)); 378*a2c472e7SAleksandr Rybalko 379*a2c472e7SAleksandr Rybalko /* We have valid char */ 380*a2c472e7SAleksandr Rybalko if (xc & FLD(URXD, CHARRDY)) 381*a2c472e7SAleksandr Rybalko out = xc & 0x000000ff; 382*a2c472e7SAleksandr Rybalko 383*a2c472e7SAleksandr Rybalko if (xc & FLD(URXD, FRMERR)) 384*a2c472e7SAleksandr Rybalko out |= UART_STAT_FRAMERR; 385*a2c472e7SAleksandr Rybalko if (xc & FLD(URXD, PRERR)) 386*a2c472e7SAleksandr Rybalko out |= UART_STAT_PARERR; 387*a2c472e7SAleksandr Rybalko if (xc & FLD(URXD, OVRRUN)) 388*a2c472e7SAleksandr Rybalko out |= UART_STAT_OVERRUN; 389*a2c472e7SAleksandr Rybalko if (xc & FLD(URXD, BRK)) 390*a2c472e7SAleksandr Rybalko out |= UART_STAT_BREAK; 391*a2c472e7SAleksandr Rybalko 392*a2c472e7SAleksandr Rybalko uart_rx_put(sc, out); 393*a2c472e7SAleksandr Rybalko } 394*a2c472e7SAleksandr Rybalko /* Reenable Data Ready interrupt */ 395*a2c472e7SAleksandr Rybalko ENA(bas, UCR4, DREN); 396*a2c472e7SAleksandr Rybalko 397*a2c472e7SAleksandr Rybalko uart_unlock(sc->sc_hwmtx); 398*a2c472e7SAleksandr Rybalko return (0); 399*a2c472e7SAleksandr Rybalko } 400*a2c472e7SAleksandr Rybalko 401*a2c472e7SAleksandr Rybalko static int 402*a2c472e7SAleksandr Rybalko imx_uart_bus_setsig(struct uart_softc *sc, int sig) 403*a2c472e7SAleksandr Rybalko { 404*a2c472e7SAleksandr Rybalko 405*a2c472e7SAleksandr Rybalko /* TODO: implement (?) */ 406*a2c472e7SAleksandr Rybalko 407*a2c472e7SAleksandr Rybalko /* XXX workaround to have working console on mount prompt */ 408*a2c472e7SAleksandr Rybalko /* Enable RX interrupt */ 409*a2c472e7SAleksandr Rybalko if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) 410*a2c472e7SAleksandr Rybalko if (!IS(&sc->sc_bas, UCR4, DREN)) 411*a2c472e7SAleksandr Rybalko ENA(&sc->sc_bas, UCR4, DREN); 412*a2c472e7SAleksandr Rybalko return (0); 413*a2c472e7SAleksandr Rybalko } 414*a2c472e7SAleksandr Rybalko 415*a2c472e7SAleksandr Rybalko static int 416*a2c472e7SAleksandr Rybalko imx_uart_bus_transmit(struct uart_softc *sc) 417*a2c472e7SAleksandr Rybalko { 418*a2c472e7SAleksandr Rybalko struct uart_bas *bas = &sc->sc_bas; 419*a2c472e7SAleksandr Rybalko int i; 420*a2c472e7SAleksandr Rybalko 421*a2c472e7SAleksandr Rybalko bas = &sc->sc_bas; 422*a2c472e7SAleksandr Rybalko uart_lock(sc->sc_hwmtx); 423*a2c472e7SAleksandr Rybalko 424*a2c472e7SAleksandr Rybalko /* Fill TX FIFO */ 425*a2c472e7SAleksandr Rybalko for (i = 0; i < sc->sc_txdatasz; i++) { 426*a2c472e7SAleksandr Rybalko SETREG(bas, REG(UTXD), sc->sc_txbuf[i] & 0xff); 427*a2c472e7SAleksandr Rybalko } 428*a2c472e7SAleksandr Rybalko 429*a2c472e7SAleksandr Rybalko sc->sc_txbusy = 1; 430*a2c472e7SAleksandr Rybalko /* Call me when ready */ 431*a2c472e7SAleksandr Rybalko ENA(bas, UCR1, TXMPTYEN); 432*a2c472e7SAleksandr Rybalko 433*a2c472e7SAleksandr Rybalko uart_unlock(sc->sc_hwmtx); 434*a2c472e7SAleksandr Rybalko 435*a2c472e7SAleksandr Rybalko return (0); 436*a2c472e7SAleksandr Rybalko } 437