1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2012 The FreeBSD Foundation 5 * All rights reserved. 6 * 7 * This software was developed by Oleksandr Rybalko under sponsorship 8 * from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD$"); 34 35#include "opt_ddb.h" 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/bus.h> 40#include <sys/conf.h> 41#include <sys/kdb.h> 42#include <machine/bus.h> 43 44#include <dev/uart/uart.h> 45#include <dev/uart/uart_cpu.h> 46#include <dev/uart/uart_cpu_fdt.h> 47#include <dev/uart/uart_bus.h> 48#include <dev/uart/uart_dev_imx.h> 49 50#if defined(EXT_RESOURCES) && defined(__aarch64__) 51#define IMX_ENABLE_CLOCKS 52#endif 53 54#ifdef IMX_ENABLE_CLOCKS 55#include <dev/extres/clk/clk.h> 56#endif 57 58#include "uart_if.h" 59 60#include <arm/freescale/imx/imx_ccmvar.h> 61 62/* 63 * The hardare FIFOs are 32 bytes. We want an interrupt when there are 24 bytes 64 * available to read or space for 24 more bytes to write. While 8 bytes of 65 * slack before over/underrun might seem excessive, the hardware can run at 66 * 5mbps, which means 2uS per char, so at full speed 8 bytes provides only 16uS 67 * to get into the interrupt handler and service the fifo. 68 */ 69#define IMX_FIFOSZ 32 70#define IMX_RXFIFO_LEVEL 24 71#define IMX_TXFIFO_LEVEL 24 72 73/* 74 * Low-level UART interface. 75 */ 76static int imx_uart_probe(struct uart_bas *bas); 77static void imx_uart_init(struct uart_bas *bas, int, int, int, int); 78static void imx_uart_term(struct uart_bas *bas); 79static void imx_uart_putc(struct uart_bas *bas, int); 80static int imx_uart_rxready(struct uart_bas *bas); 81static int imx_uart_getc(struct uart_bas *bas, struct mtx *); 82 83static struct uart_ops uart_imx_uart_ops = { 84 .probe = imx_uart_probe, 85 .init = imx_uart_init, 86 .term = imx_uart_term, 87 .putc = imx_uart_putc, 88 .rxready = imx_uart_rxready, 89 .getc = imx_uart_getc, 90}; 91 92#if 0 /* Handy when debugging. */ 93static void 94dumpregs(struct uart_bas *bas, const char * msg) 95{ 96 97 if (!bootverbose) 98 return; 99 printf("%s bsh 0x%08lx UCR1 0x%08x UCR2 0x%08x " 100 "UCR3 0x%08x UCR4 0x%08x USR1 0x%08x USR2 0x%08x\n", 101 msg, bas->bsh, 102 GETREG(bas, REG(UCR1)), GETREG(bas, REG(UCR2)), 103 GETREG(bas, REG(UCR3)), GETREG(bas, REG(UCR4)), 104 GETREG(bas, REG(USR1)), GETREG(bas, REG(USR2))); 105} 106#endif 107 108static int 109imx_uart_probe(struct uart_bas *bas) 110{ 111 112 return (0); 113} 114 115static u_int 116imx_uart_getbaud(struct uart_bas *bas) 117{ 118 uint32_t rate, ubir, ubmr; 119 u_int baud, blo, bhi, i; 120 static const u_int predivs[] = {6, 5, 4, 3, 2, 1, 7, 1}; 121 static const u_int std_rates[] = { 122 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600 123 }; 124 125 /* 126 * Get the baud rate the hardware is programmed for, then search the 127 * table of standard baud rates for a number that's within 3% of the 128 * actual rate the hardware is programmed for. It's more comforting to 129 * see that your console is running at 115200 than 114942. Note that 130 * here we cannot make a simplifying assumption that the predivider and 131 * numerator are 1 (like we do when setting the baud rate), because we 132 * don't know what u-boot might have set up. 133 */ 134 i = (GETREG(bas, REG(UFCR)) & IMXUART_UFCR_RFDIV_MASK) >> 135 IMXUART_UFCR_RFDIV_SHIFT; 136 rate = bas->rclk / predivs[i]; 137 ubir = GETREG(bas, REG(UBIR)) + 1; 138 ubmr = GETREG(bas, REG(UBMR)) + 1; 139 baud = ((rate / 16 ) * ubir) / ubmr; 140 141 blo = (baud * 100) / 103; 142 bhi = (baud * 100) / 97; 143 for (i = 0; i < nitems(std_rates); i++) { 144 rate = std_rates[i]; 145 if (rate >= blo && rate <= bhi) { 146 baud = rate; 147 break; 148 } 149 } 150 151 return (baud); 152} 153 154static void 155imx_uart_init(struct uart_bas *bas, int baudrate, int databits, 156 int stopbits, int parity) 157{ 158 uint32_t baseclk, reg; 159 160 /* Enable the device and the RX/TX channels. */ 161 SET(bas, REG(UCR1), FLD(UCR1, UARTEN)); 162 SET(bas, REG(UCR2), FLD(UCR2, RXEN) | FLD(UCR2, TXEN)); 163 164 if (databits == 7) 165 DIS(bas, UCR2, WS); 166 else 167 ENA(bas, UCR2, WS); 168 169 if (stopbits == 2) 170 ENA(bas, UCR2, STPB); 171 else 172 DIS(bas, UCR2, STPB); 173 174 switch (parity) { 175 case UART_PARITY_ODD: 176 DIS(bas, UCR2, PROE); 177 ENA(bas, UCR2, PREN); 178 break; 179 case UART_PARITY_EVEN: 180 ENA(bas, UCR2, PROE); 181 ENA(bas, UCR2, PREN); 182 break; 183 case UART_PARITY_MARK: 184 case UART_PARITY_SPACE: 185 /* FALLTHROUGH: Hardware doesn't support mark/space. */ 186 case UART_PARITY_NONE: 187 default: 188 DIS(bas, UCR2, PREN); 189 break; 190 } 191 192 /* 193 * The hardware has an extremely flexible baud clock: it allows setting 194 * both the numerator and denominator of the divider, as well as a 195 * separate pre-divider. We simplify the problem of coming up with a 196 * workable pair of numbers by assuming a pre-divider and numerator of 197 * one because our base clock is so fast we can reach virtually any 198 * reasonable speed with a simple divisor. The numerator value actually 199 * includes the 16x over-sampling (so a value of 16 means divide by 1); 200 * the register value is the numerator-1, so we have a hard-coded 15. 201 * Note that a quirk of the hardware requires that both UBIR and UBMR be 202 * set back to back in order for the change to take effect. 203 */ 204 if ((baudrate > 0) && (bas->rclk != 0)) { 205 baseclk = bas->rclk; 206 reg = GETREG(bas, REG(UFCR)); 207 reg = (reg & ~IMXUART_UFCR_RFDIV_MASK) | IMXUART_UFCR_RFDIV_DIV1; 208 SETREG(bas, REG(UFCR), reg); 209 SETREG(bas, REG(UBIR), 15); 210 SETREG(bas, REG(UBMR), (baseclk / baudrate) - 1); 211 } 212 213 /* 214 * Program the tx lowater and rx hiwater levels at which fifo-service 215 * interrupts are signaled. The tx value is interpetted as "when there 216 * are only this many bytes remaining" (not "this many free"). 217 */ 218 reg = GETREG(bas, REG(UFCR)); 219 reg &= ~(IMXUART_UFCR_TXTL_MASK | IMXUART_UFCR_RXTL_MASK); 220 reg |= (IMX_FIFOSZ - IMX_TXFIFO_LEVEL) << IMXUART_UFCR_TXTL_SHIFT; 221 reg |= IMX_RXFIFO_LEVEL << IMXUART_UFCR_RXTL_SHIFT; 222 SETREG(bas, REG(UFCR), reg); 223} 224 225static void 226imx_uart_term(struct uart_bas *bas) 227{ 228 229} 230 231static void 232imx_uart_putc(struct uart_bas *bas, int c) 233{ 234 235 while (!(IS(bas, USR1, TRDY))) 236 ; 237 SETREG(bas, REG(UTXD), c); 238} 239 240static int 241imx_uart_rxready(struct uart_bas *bas) 242{ 243 244 return ((IS(bas, USR2, RDR)) ? 1 : 0); 245} 246 247static int 248imx_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) 249{ 250 int c; 251 252 uart_lock(hwmtx); 253 while (!(IS(bas, USR2, RDR))) 254 ; 255 256 c = GETREG(bas, REG(URXD)); 257 uart_unlock(hwmtx); 258#if defined(KDB) 259 if (c & FLD(URXD, BRK)) { 260 if (kdb_break()) 261 return (0); 262 } 263#endif 264 return (c & 0xff); 265} 266 267/* 268 * High-level UART interface. 269 */ 270struct imx_uart_softc { 271 struct uart_softc base; 272}; 273 274static int imx_uart_bus_attach(struct uart_softc *); 275static int imx_uart_bus_detach(struct uart_softc *); 276static int imx_uart_bus_flush(struct uart_softc *, int); 277static int imx_uart_bus_getsig(struct uart_softc *); 278static int imx_uart_bus_ioctl(struct uart_softc *, int, intptr_t); 279static int imx_uart_bus_ipend(struct uart_softc *); 280static int imx_uart_bus_param(struct uart_softc *, int, int, int, int); 281static int imx_uart_bus_probe(struct uart_softc *); 282static int imx_uart_bus_receive(struct uart_softc *); 283static int imx_uart_bus_setsig(struct uart_softc *, int); 284static int imx_uart_bus_transmit(struct uart_softc *); 285static void imx_uart_bus_grab(struct uart_softc *); 286static void imx_uart_bus_ungrab(struct uart_softc *); 287 288static kobj_method_t imx_uart_methods[] = { 289 KOBJMETHOD(uart_attach, imx_uart_bus_attach), 290 KOBJMETHOD(uart_detach, imx_uart_bus_detach), 291 KOBJMETHOD(uart_flush, imx_uart_bus_flush), 292 KOBJMETHOD(uart_getsig, imx_uart_bus_getsig), 293 KOBJMETHOD(uart_ioctl, imx_uart_bus_ioctl), 294 KOBJMETHOD(uart_ipend, imx_uart_bus_ipend), 295 KOBJMETHOD(uart_param, imx_uart_bus_param), 296 KOBJMETHOD(uart_probe, imx_uart_bus_probe), 297 KOBJMETHOD(uart_receive, imx_uart_bus_receive), 298 KOBJMETHOD(uart_setsig, imx_uart_bus_setsig), 299 KOBJMETHOD(uart_transmit, imx_uart_bus_transmit), 300 KOBJMETHOD(uart_grab, imx_uart_bus_grab), 301 KOBJMETHOD(uart_ungrab, imx_uart_bus_ungrab), 302 { 0, 0 } 303}; 304 305static struct uart_class uart_imx_class = { 306 "imx", 307 imx_uart_methods, 308 sizeof(struct imx_uart_softc), 309 .uc_ops = &uart_imx_uart_ops, 310 .uc_range = 0x100, 311 .uc_rclk = 24000000, /* TODO: get value from CCM */ 312 .uc_rshift = 0 313}; 314 315static struct ofw_compat_data compat_data[] = { 316 {"fsl,imx6q-uart", (uintptr_t)&uart_imx_class}, 317 {"fsl,imx53-uart", (uintptr_t)&uart_imx_class}, 318 {"fsl,imx51-uart", (uintptr_t)&uart_imx_class}, 319 {"fsl,imx31-uart", (uintptr_t)&uart_imx_class}, 320 {"fsl,imx27-uart", (uintptr_t)&uart_imx_class}, 321 {"fsl,imx25-uart", (uintptr_t)&uart_imx_class}, 322 {"fsl,imx21-uart", (uintptr_t)&uart_imx_class}, 323 {NULL, (uintptr_t)NULL}, 324}; 325UART_FDT_CLASS_AND_DEVICE(compat_data); 326 327#define SIGCHG(c, i, s, d) \ 328 if (c) { \ 329 i |= (i & s) ? s : s | d; \ 330 } else { \ 331 i = (i & s) ? (i & ~s) | d : i; \ 332 } 333 334#ifdef IMX_ENABLE_CLOCKS 335static int 336imx_uart_setup_clocks(struct uart_softc *sc) 337{ 338 struct uart_bas *bas; 339 clk_t ipgclk, perclk; 340 uint64_t freq; 341 int error; 342 343 bas = &sc->sc_bas; 344 345 if (clk_get_by_ofw_name(sc->sc_dev, 0, "ipg", &ipgclk) != 0) 346 return (ENOENT); 347 348 if (clk_get_by_ofw_name(sc->sc_dev, 0, "per", &perclk) != 0) { 349 return (ENOENT); 350 } 351 352 error = clk_enable(ipgclk); 353 if (error != 0) { 354 device_printf(sc->sc_dev, "cannot enable ipg clock\n"); 355 return (error); 356 } 357 358 error = clk_get_freq(perclk, &freq); 359 if (error != 0) { 360 device_printf(sc->sc_dev, "cannot get frequency\n"); 361 return (error); 362 } 363 364 bas->rclk = (uint32_t)freq; 365 366 return (0); 367} 368#endif 369 370static int 371imx_uart_bus_attach(struct uart_softc *sc) 372{ 373 struct uart_bas *bas; 374 struct uart_devinfo *di; 375 376 bas = &sc->sc_bas; 377 378#ifdef IMX_ENABLE_CLOCKS 379 int error = imx_uart_setup_clocks(sc); 380 if (error) 381 return (error); 382#else 383 bas->rclk = imx_ccm_uart_hz(); 384#endif 385 386 if (sc->sc_sysdev != NULL) { 387 di = sc->sc_sysdev; 388 imx_uart_init(bas, di->baudrate, di->databits, di->stopbits, 389 di->parity); 390 } else { 391 imx_uart_init(bas, 115200, 8, 1, 0); 392 } 393 394 (void)imx_uart_bus_getsig(sc); 395 396 /* Clear all pending interrupts. */ 397 SETREG(bas, REG(USR1), 0xffff); 398 SETREG(bas, REG(USR2), 0xffff); 399 400 DIS(bas, UCR4, DREN); 401 ENA(bas, UCR1, RRDYEN); 402 DIS(bas, UCR1, IDEN); 403 DIS(bas, UCR3, RXDSEN); 404 ENA(bas, UCR2, ATEN); 405 DIS(bas, UCR1, TXMPTYEN); 406 DIS(bas, UCR1, TRDYEN); 407 DIS(bas, UCR4, TCEN); 408 DIS(bas, UCR4, OREN); 409 ENA(bas, UCR4, BKEN); 410 DIS(bas, UCR4, WKEN); 411 DIS(bas, UCR1, ADEN); 412 DIS(bas, UCR3, ACIEN); 413 DIS(bas, UCR2, ESCI); 414 DIS(bas, UCR4, ENIRI); 415 DIS(bas, UCR3, AIRINTEN); 416 DIS(bas, UCR3, AWAKEN); 417 DIS(bas, UCR3, FRAERREN); 418 DIS(bas, UCR3, PARERREN); 419 DIS(bas, UCR1, RTSDEN); 420 DIS(bas, UCR2, RTSEN); 421 DIS(bas, UCR3, DTREN); 422 DIS(bas, UCR3, RI); 423 DIS(bas, UCR3, DCD); 424 DIS(bas, UCR3, DTRDEN); 425 ENA(bas, UCR2, IRTS); 426 ENA(bas, UCR3, RXDMUXSEL); 427 428 return (0); 429} 430 431static int 432imx_uart_bus_detach(struct uart_softc *sc) 433{ 434 435 SETREG(&sc->sc_bas, REG(UCR4), 0); 436 437 return (0); 438} 439 440static int 441imx_uart_bus_flush(struct uart_softc *sc, int what) 442{ 443 444 /* TODO */ 445 return (0); 446} 447 448static int 449imx_uart_bus_getsig(struct uart_softc *sc) 450{ 451 uint32_t new, old, sig; 452 uint8_t bes; 453 454 do { 455 old = sc->sc_hwsig; 456 sig = old; 457 uart_lock(sc->sc_hwmtx); 458 bes = GETREG(&sc->sc_bas, REG(USR2)); 459 uart_unlock(sc->sc_hwmtx); 460 /* XXX: chip can show delta */ 461 SIGCHG(bes & FLD(USR2, DCDIN), sig, SER_DCD, SER_DDCD); 462 new = sig & ~SER_MASK_DELTA; 463 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 464 465 return (sig); 466} 467 468static int 469imx_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 470{ 471 struct uart_bas *bas; 472 int error; 473 474 bas = &sc->sc_bas; 475 error = 0; 476 uart_lock(sc->sc_hwmtx); 477 switch (request) { 478 case UART_IOCTL_BREAK: 479 /* TODO */ 480 break; 481 case UART_IOCTL_BAUD: 482 *(u_int*)data = imx_uart_getbaud(bas); 483 break; 484 default: 485 error = EINVAL; 486 break; 487 } 488 uart_unlock(sc->sc_hwmtx); 489 490 return (error); 491} 492 493static int 494imx_uart_bus_ipend(struct uart_softc *sc) 495{ 496 struct uart_bas *bas; 497 int ipend; 498 uint32_t usr1, usr2; 499 uint32_t ucr1, ucr2, ucr4; 500 501 bas = &sc->sc_bas; 502 ipend = 0; 503 504 uart_lock(sc->sc_hwmtx); 505 506 /* Read pending interrupts */ 507 usr1 = GETREG(bas, REG(USR1)); 508 usr2 = GETREG(bas, REG(USR2)); 509 /* ACK interrupts */ 510 SETREG(bas, REG(USR1), usr1); 511 SETREG(bas, REG(USR2), usr2); 512 513 ucr1 = GETREG(bas, REG(UCR1)); 514 ucr2 = GETREG(bas, REG(UCR2)); 515 ucr4 = GETREG(bas, REG(UCR4)); 516 517 /* If we have reached tx low-water, we can tx some more now. */ 518 if ((usr1 & FLD(USR1, TRDY)) && (ucr1 & FLD(UCR1, TRDYEN))) { 519 DIS(bas, UCR1, TRDYEN); 520 ipend |= SER_INT_TXIDLE; 521 } 522 523 /* 524 * If we have reached the rx high-water, or if there are bytes in the rx 525 * fifo and no new data has arrived for 8 character periods (aging 526 * timer), we have input data to process. 527 */ 528 if (((usr1 & FLD(USR1, RRDY)) && (ucr1 & FLD(UCR1, RRDYEN))) || 529 ((usr1 & FLD(USR1, AGTIM)) && (ucr2 & FLD(UCR2, ATEN)))) { 530 DIS(bas, UCR1, RRDYEN); 531 DIS(bas, UCR2, ATEN); 532 ipend |= SER_INT_RXREADY; 533 } 534 535 /* A break can come in at any time, it never gets disabled. */ 536 if ((usr2 & FLD(USR2, BRCD)) && (ucr4 & FLD(UCR4, BKEN))) 537 ipend |= SER_INT_BREAK; 538 539 uart_unlock(sc->sc_hwmtx); 540 541 return (ipend); 542} 543 544static int 545imx_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, 546 int stopbits, int parity) 547{ 548 549 uart_lock(sc->sc_hwmtx); 550 imx_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity); 551 uart_unlock(sc->sc_hwmtx); 552 return (0); 553} 554 555static int 556imx_uart_bus_probe(struct uart_softc *sc) 557{ 558 int error; 559 560 error = imx_uart_probe(&sc->sc_bas); 561 if (error) 562 return (error); 563 564 /* 565 * On input we can read up to the full fifo size at once. On output, we 566 * want to write only as much as the programmed tx low water level, 567 * because that's all we can be certain we have room for in the fifo 568 * when we get a tx-ready interrupt. 569 */ 570 sc->sc_rxfifosz = IMX_FIFOSZ; 571 sc->sc_txfifosz = IMX_TXFIFO_LEVEL; 572 573 device_set_desc(sc->sc_dev, "Freescale i.MX UART"); 574 return (0); 575} 576 577static int 578imx_uart_bus_receive(struct uart_softc *sc) 579{ 580 struct uart_bas *bas; 581 int xc, out; 582 583 bas = &sc->sc_bas; 584 uart_lock(sc->sc_hwmtx); 585 586 /* 587 * Empty the rx fifo. We get the RRDY interrupt when IMX_RXFIFO_LEVEL 588 * (the rx high-water level) is reached, but we set sc_rxfifosz to the 589 * full hardware fifo size, so we can safely process however much is 590 * there, not just the highwater size. 591 */ 592 while (IS(bas, USR2, RDR)) { 593 if (uart_rx_full(sc)) { 594 /* No space left in input buffer */ 595 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 596 break; 597 } 598 xc = GETREG(bas, REG(URXD)); 599 out = xc & 0x000000ff; 600 if (xc & FLD(URXD, FRMERR)) 601 out |= UART_STAT_FRAMERR; 602 if (xc & FLD(URXD, PRERR)) 603 out |= UART_STAT_PARERR; 604 if (xc & FLD(URXD, OVRRUN)) 605 out |= UART_STAT_OVERRUN; 606 if (xc & FLD(URXD, BRK)) 607 out |= UART_STAT_BREAK; 608 609 uart_rx_put(sc, out); 610 } 611 ENA(bas, UCR1, RRDYEN); 612 ENA(bas, UCR2, ATEN); 613 614 uart_unlock(sc->sc_hwmtx); 615 return (0); 616} 617 618static int 619imx_uart_bus_setsig(struct uart_softc *sc, int sig) 620{ 621 622 return (0); 623} 624 625static int 626imx_uart_bus_transmit(struct uart_softc *sc) 627{ 628 struct uart_bas *bas = &sc->sc_bas; 629 int i; 630 631 bas = &sc->sc_bas; 632 uart_lock(sc->sc_hwmtx); 633 634 /* 635 * Fill the tx fifo. The uart core puts at most IMX_TXFIFO_LEVEL bytes 636 * into the txbuf (because that's what sc_txfifosz is set to), and 637 * because we got the TRDY (low-water reached) interrupt we know at 638 * least that much space is available in the fifo. 639 */ 640 for (i = 0; i < sc->sc_txdatasz; i++) { 641 SETREG(bas, REG(UTXD), sc->sc_txbuf[i] & 0xff); 642 } 643 sc->sc_txbusy = 1; 644 ENA(bas, UCR1, TRDYEN); 645 646 uart_unlock(sc->sc_hwmtx); 647 648 return (0); 649} 650 651static void 652imx_uart_bus_grab(struct uart_softc *sc) 653{ 654 struct uart_bas *bas = &sc->sc_bas; 655 656 bas = &sc->sc_bas; 657 uart_lock(sc->sc_hwmtx); 658 DIS(bas, UCR1, RRDYEN); 659 DIS(bas, UCR2, ATEN); 660 uart_unlock(sc->sc_hwmtx); 661} 662 663static void 664imx_uart_bus_ungrab(struct uart_softc *sc) 665{ 666 struct uart_bas *bas = &sc->sc_bas; 667 668 bas = &sc->sc_bas; 669 uart_lock(sc->sc_hwmtx); 670 ENA(bas, UCR1, RRDYEN); 671 ENA(bas, UCR2, ATEN); 672 uart_unlock(sc->sc_hwmtx); 673} 674