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