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 #include <dev/uart/uart_dev_imx.h> 47 #include "uart_if.h" 48 49 #include <arm/freescale/imx/imx_ccmvar.h> 50 51 /* 52 * Low-level UART interface. 53 */ 54 static int imx_uart_probe(struct uart_bas *bas); 55 static void imx_uart_init(struct uart_bas *bas, int, int, int, int); 56 static void imx_uart_term(struct uart_bas *bas); 57 static void imx_uart_putc(struct uart_bas *bas, int); 58 static int imx_uart_rxready(struct uart_bas *bas); 59 static int imx_uart_getc(struct uart_bas *bas, struct mtx *); 60 61 static struct uart_ops uart_imx_uart_ops = { 62 .probe = imx_uart_probe, 63 .init = imx_uart_init, 64 .term = imx_uart_term, 65 .putc = imx_uart_putc, 66 .rxready = imx_uart_rxready, 67 .getc = imx_uart_getc, 68 }; 69 70 #if 0 /* Handy when debugging. */ 71 static void 72 dumpregs(struct uart_bas *bas, const char * msg) 73 { 74 75 if (!bootverbose) 76 return; 77 printf("%s bsh 0x%08lx UCR1 0x%08x UCR2 0x%08x " 78 "UCR3 0x%08x UCR4 0x%08x USR1 0x%08x USR2 0x%08x\n", 79 msg, bas->bsh, 80 GETREG(bas, REG(UCR1)), GETREG(bas, REG(UCR2)), 81 GETREG(bas, REG(UCR3)), GETREG(bas, REG(UCR4)), 82 GETREG(bas, REG(USR1)), GETREG(bas, REG(USR2))); 83 } 84 #endif 85 86 static int 87 imx_uart_probe(struct uart_bas *bas) 88 { 89 90 return (0); 91 } 92 93 static void 94 imx_uart_init(struct uart_bas *bas, int baudrate, int databits, 95 int stopbits, int parity) 96 { 97 uint32_t baseclk, reg; 98 99 /* Enable the device and the RX/TX channels. */ 100 SET(bas, REG(UCR1), FLD(UCR1, UARTEN)); 101 SET(bas, REG(UCR2), FLD(UCR2, RXEN) | FLD(UCR2, TXEN)); 102 103 if (databits == 7) 104 DIS(bas, UCR2, WS); 105 else 106 ENA(bas, UCR2, WS); 107 108 if (stopbits == 2) 109 ENA(bas, UCR2, STPB); 110 else 111 DIS(bas, UCR2, STPB); 112 113 switch (parity) { 114 case UART_PARITY_ODD: 115 DIS(bas, UCR2, PROE); 116 ENA(bas, UCR2, PREN); 117 break; 118 case UART_PARITY_EVEN: 119 ENA(bas, UCR2, PROE); 120 ENA(bas, UCR2, PREN); 121 break; 122 case UART_PARITY_MARK: 123 case UART_PARITY_SPACE: 124 /* FALLTHROUGH: Hardware doesn't support mark/space. */ 125 case UART_PARITY_NONE: 126 default: 127 DIS(bas, UCR2, PREN); 128 break; 129 } 130 131 /* 132 * The hardware has an extremely flexible baud clock: it allows setting 133 * both the numerator and denominator of the divider, as well as a 134 * separate pre-divider. We simplify the problem of coming up with a 135 * workable pair of numbers by assuming a pre-divider and numerator of 136 * one because our base clock is so fast we can reach virtually any 137 * reasonable speed with a simple divisor. The numerator value actually 138 * includes the 16x over-sampling (so a value of 16 means divide by 1); 139 * the register value is the numerator-1, so we have a hard-coded 15. 140 * Note that a quirk of the hardware requires that both UBIR and UBMR be 141 * set back to back in order for the change to take effect. 142 */ 143 if (baudrate > 0) { 144 baseclk = imx_ccm_uart_hz(); 145 reg = GETREG(bas, REG(UFCR)); 146 reg = (reg & ~IMXUART_UFCR_RFDIV_MASK) | IMXUART_UFCR_RFDIV_DIV1; 147 SETREG(bas, REG(UFCR), reg); 148 SETREG(bas, REG(UBIR), 15); 149 SETREG(bas, REG(UBMR), (baseclk / baudrate) - 1); 150 } 151 } 152 153 static void 154 imx_uart_term(struct uart_bas *bas) 155 { 156 157 } 158 159 static void 160 imx_uart_putc(struct uart_bas *bas, int c) 161 { 162 163 while (!(IS(bas, USR2, TXFE))) 164 ; 165 SETREG(bas, REG(UTXD), c); 166 } 167 168 static int 169 imx_uart_rxready(struct uart_bas *bas) 170 { 171 172 return ((IS(bas, USR2, RDR)) ? 1 : 0); 173 } 174 175 static int 176 imx_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) 177 { 178 int c; 179 180 uart_lock(hwmtx); 181 while (!(IS(bas, USR2, RDR))) 182 ; 183 184 c = GETREG(bas, REG(URXD)); 185 uart_unlock(hwmtx); 186 #if defined(KDB) 187 if (c & FLD(URXD, BRK)) { 188 if (kdb_break()) 189 return (0); 190 } 191 #endif 192 return (c & 0xff); 193 } 194 195 /* 196 * High-level UART interface. 197 */ 198 struct imx_uart_softc { 199 struct uart_softc base; 200 }; 201 202 static int imx_uart_bus_attach(struct uart_softc *); 203 static int imx_uart_bus_detach(struct uart_softc *); 204 static int imx_uart_bus_flush(struct uart_softc *, int); 205 static int imx_uart_bus_getsig(struct uart_softc *); 206 static int imx_uart_bus_ioctl(struct uart_softc *, int, intptr_t); 207 static int imx_uart_bus_ipend(struct uart_softc *); 208 static int imx_uart_bus_param(struct uart_softc *, int, int, int, int); 209 static int imx_uart_bus_probe(struct uart_softc *); 210 static int imx_uart_bus_receive(struct uart_softc *); 211 static int imx_uart_bus_setsig(struct uart_softc *, int); 212 static int imx_uart_bus_transmit(struct uart_softc *); 213 static void imx_uart_bus_grab(struct uart_softc *); 214 static void imx_uart_bus_ungrab(struct uart_softc *); 215 216 static kobj_method_t imx_uart_methods[] = { 217 KOBJMETHOD(uart_attach, imx_uart_bus_attach), 218 KOBJMETHOD(uart_detach, imx_uart_bus_detach), 219 KOBJMETHOD(uart_flush, imx_uart_bus_flush), 220 KOBJMETHOD(uart_getsig, imx_uart_bus_getsig), 221 KOBJMETHOD(uart_ioctl, imx_uart_bus_ioctl), 222 KOBJMETHOD(uart_ipend, imx_uart_bus_ipend), 223 KOBJMETHOD(uart_param, imx_uart_bus_param), 224 KOBJMETHOD(uart_probe, imx_uart_bus_probe), 225 KOBJMETHOD(uart_receive, imx_uart_bus_receive), 226 KOBJMETHOD(uart_setsig, imx_uart_bus_setsig), 227 KOBJMETHOD(uart_transmit, imx_uart_bus_transmit), 228 KOBJMETHOD(uart_grab, imx_uart_bus_grab), 229 KOBJMETHOD(uart_ungrab, imx_uart_bus_ungrab), 230 { 0, 0 } 231 }; 232 233 struct uart_class uart_imx_class = { 234 "imx", 235 imx_uart_methods, 236 sizeof(struct imx_uart_softc), 237 .uc_ops = &uart_imx_uart_ops, 238 .uc_range = 0x100, 239 .uc_rclk = 24000000 /* TODO: get value from CCM */ 240 }; 241 242 #define SIGCHG(c, i, s, d) \ 243 if (c) { \ 244 i |= (i & s) ? s : s | d; \ 245 } else { \ 246 i = (i & s) ? (i & ~s) | d : i; \ 247 } 248 249 static int 250 imx_uart_bus_attach(struct uart_softc *sc) 251 { 252 struct uart_bas *bas; 253 struct uart_devinfo *di; 254 255 bas = &sc->sc_bas; 256 if (sc->sc_sysdev != NULL) { 257 di = sc->sc_sysdev; 258 imx_uart_init(bas, di->baudrate, di->databits, di->stopbits, 259 di->parity); 260 } else { 261 imx_uart_init(bas, 115200, 8, 1, 0); 262 } 263 264 (void)imx_uart_bus_getsig(sc); 265 266 ENA(bas, UCR4, DREN); 267 DIS(bas, UCR1, RRDYEN); 268 DIS(bas, UCR1, IDEN); 269 DIS(bas, UCR3, RXDSEN); 270 DIS(bas, UCR2, ATEN); 271 DIS(bas, UCR1, TXMPTYEN); 272 DIS(bas, UCR1, TRDYEN); 273 DIS(bas, UCR4, TCEN); 274 DIS(bas, UCR4, OREN); 275 ENA(bas, UCR4, BKEN); 276 DIS(bas, UCR4, WKEN); 277 DIS(bas, UCR1, ADEN); 278 DIS(bas, UCR3, ACIEN); 279 DIS(bas, UCR2, ESCI); 280 DIS(bas, UCR4, ENIRI); 281 DIS(bas, UCR3, AIRINTEN); 282 DIS(bas, UCR3, AWAKEN); 283 DIS(bas, UCR3, FRAERREN); 284 DIS(bas, UCR3, PARERREN); 285 DIS(bas, UCR1, RTSDEN); 286 DIS(bas, UCR2, RTSEN); 287 DIS(bas, UCR3, DTREN); 288 DIS(bas, UCR3, RI); 289 DIS(bas, UCR3, DCD); 290 DIS(bas, UCR3, DTRDEN); 291 ENA(bas, UCR2, IRTS); 292 ENA(bas, UCR3, RXDMUXSEL); 293 294 /* ACK all interrupts */ 295 SETREG(bas, REG(USR1), 0xffff); 296 SETREG(bas, REG(USR2), 0xffff); 297 return (0); 298 } 299 300 static int 301 imx_uart_bus_detach(struct uart_softc *sc) 302 { 303 304 SETREG(&sc->sc_bas, REG(UCR4), 0); 305 306 return (0); 307 } 308 309 static int 310 imx_uart_bus_flush(struct uart_softc *sc, int what) 311 { 312 313 /* TODO */ 314 return (0); 315 } 316 317 static int 318 imx_uart_bus_getsig(struct uart_softc *sc) 319 { 320 uint32_t new, old, sig; 321 uint8_t bes; 322 323 do { 324 old = sc->sc_hwsig; 325 sig = old; 326 uart_lock(sc->sc_hwmtx); 327 bes = GETREG(&sc->sc_bas, REG(USR2)); 328 uart_unlock(sc->sc_hwmtx); 329 /* XXX: chip can show delta */ 330 SIGCHG(bes & FLD(USR2, DCDIN), sig, SER_DCD, SER_DDCD); 331 new = sig & ~SER_MASK_DELTA; 332 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 333 334 return (sig); 335 } 336 337 static int 338 imx_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 339 { 340 struct uart_bas *bas; 341 int error; 342 343 bas = &sc->sc_bas; 344 error = 0; 345 uart_lock(sc->sc_hwmtx); 346 switch (request) { 347 case UART_IOCTL_BREAK: 348 /* TODO */ 349 break; 350 case UART_IOCTL_BAUD: 351 /* TODO */ 352 *(int*)data = 115200; 353 break; 354 default: 355 error = EINVAL; 356 break; 357 } 358 uart_unlock(sc->sc_hwmtx); 359 360 return (error); 361 } 362 363 static int 364 imx_uart_bus_ipend(struct uart_softc *sc) 365 { 366 struct uart_bas *bas; 367 int ipend; 368 uint32_t usr1, usr2; 369 uint32_t ucr1, ucr4; 370 371 bas = &sc->sc_bas; 372 ipend = 0; 373 374 uart_lock(sc->sc_hwmtx); 375 376 /* Read pending interrupts */ 377 usr1 = GETREG(bas, REG(USR1)); 378 usr2 = GETREG(bas, REG(USR2)); 379 /* ACK interrupts */ 380 SETREG(bas, REG(USR1), usr1); 381 SETREG(bas, REG(USR2), usr2); 382 383 ucr1 = GETREG(bas, REG(UCR1)); 384 ucr4 = GETREG(bas, REG(UCR4)); 385 386 if ((usr2 & FLD(USR2, TXFE)) && (ucr1 & FLD(UCR1, TXMPTYEN))) { 387 DIS(bas, UCR1, TXMPTYEN); 388 /* Continue TXing */ 389 ipend |= SER_INT_TXIDLE; 390 } 391 if ((usr2 & FLD(USR2, RDR)) && (ucr4 & FLD(UCR4, DREN))) { 392 DIS(bas, UCR4, DREN); 393 /* Wow, new char on input */ 394 ipend |= SER_INT_RXREADY; 395 } 396 if ((usr2 & FLD(USR2, BRCD)) && (ucr4 & FLD(UCR4, BKEN))) 397 ipend |= SER_INT_BREAK; 398 399 uart_unlock(sc->sc_hwmtx); 400 401 return (ipend); 402 } 403 404 static int 405 imx_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, 406 int stopbits, int parity) 407 { 408 409 uart_lock(sc->sc_hwmtx); 410 imx_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity); 411 uart_unlock(sc->sc_hwmtx); 412 return (0); 413 } 414 415 static int 416 imx_uart_bus_probe(struct uart_softc *sc) 417 { 418 int error; 419 420 error = imx_uart_probe(&sc->sc_bas); 421 if (error) 422 return (error); 423 424 sc->sc_rxfifosz = 1; 425 sc->sc_txfifosz = 1; 426 427 device_set_desc(sc->sc_dev, "Freescale i.MX UART"); 428 return (0); 429 } 430 431 static int 432 imx_uart_bus_receive(struct uart_softc *sc) 433 { 434 struct uart_bas *bas; 435 int xc, out; 436 437 bas = &sc->sc_bas; 438 uart_lock(sc->sc_hwmtx); 439 440 /* Read while we have anything in FIFO */ 441 while (IS(bas, USR2, RDR)) { 442 if (uart_rx_full(sc)) { 443 /* No space left in input buffer */ 444 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 445 break; 446 } 447 out = 0; 448 xc = GETREG(bas, REG(URXD)); 449 450 /* We have valid char */ 451 if (xc & FLD(URXD, CHARRDY)) 452 out = xc & 0x000000ff; 453 454 if (xc & FLD(URXD, FRMERR)) 455 out |= UART_STAT_FRAMERR; 456 if (xc & FLD(URXD, PRERR)) 457 out |= UART_STAT_PARERR; 458 if (xc & FLD(URXD, OVRRUN)) 459 out |= UART_STAT_OVERRUN; 460 if (xc & FLD(URXD, BRK)) 461 out |= UART_STAT_BREAK; 462 463 uart_rx_put(sc, out); 464 } 465 /* Reenable Data Ready interrupt */ 466 ENA(bas, UCR4, DREN); 467 468 uart_unlock(sc->sc_hwmtx); 469 return (0); 470 } 471 472 static int 473 imx_uart_bus_setsig(struct uart_softc *sc, int sig) 474 { 475 476 return (0); 477 } 478 479 static int 480 imx_uart_bus_transmit(struct uart_softc *sc) 481 { 482 struct uart_bas *bas = &sc->sc_bas; 483 int i; 484 485 bas = &sc->sc_bas; 486 uart_lock(sc->sc_hwmtx); 487 488 /* Fill TX FIFO */ 489 for (i = 0; i < sc->sc_txdatasz; i++) { 490 SETREG(bas, REG(UTXD), sc->sc_txbuf[i] & 0xff); 491 } 492 493 sc->sc_txbusy = 1; 494 /* Call me when ready */ 495 ENA(bas, UCR1, TXMPTYEN); 496 497 uart_unlock(sc->sc_hwmtx); 498 499 return (0); 500 } 501 502 static void 503 imx_uart_bus_grab(struct uart_softc *sc) 504 { 505 struct uart_bas *bas = &sc->sc_bas; 506 507 bas = &sc->sc_bas; 508 uart_lock(sc->sc_hwmtx); 509 DIS(bas, UCR4, DREN); 510 uart_unlock(sc->sc_hwmtx); 511 } 512 513 static void 514 imx_uart_bus_ungrab(struct uart_softc *sc) 515 { 516 struct uart_bas *bas = &sc->sc_bas; 517 518 bas = &sc->sc_bas; 519 uart_lock(sc->sc_hwmtx); 520 ENA(bas, UCR4, DREN); 521 uart_unlock(sc->sc_hwmtx); 522 } 523