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