uart_dev_aml8726.c revision 280905
1/*- 2 * Copyright 2013-2015 John Wehle <john@feith.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Amlogic aml8726 UART driver. 29 * 30 * The current implementation only targets features common to all 31 * uarts. For example ... though UART A as a 128 byte FIFO, the 32 * others only have a 64 byte FIFO. 33 * 34 * Also, it's assumed that register 5 (the new baud rate register 35 * present on the aml8726-m6) has not been activated. 36 */ 37 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: head/sys/arm/amlogic/aml8726/uart_dev_aml8726.c 280905 2015-03-31 11:50:46Z ganbold $"); 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/bus.h> 44#include <sys/conf.h> 45#include <sys/kernel.h> 46#include <sys/sysctl.h> 47 48#include <machine/bus.h> 49#include <machine/cpu.h> 50 51#include <dev/uart/uart.h> 52#include <dev/uart/uart_cpu.h> 53#include <dev/uart/uart_cpu_fdt.h> 54#include <dev/uart/uart_bus.h> 55 56#include <arm/amlogic/aml8726/aml8726_uart.h> 57 58#include "uart_if.h" 59 60#undef uart_getreg 61#undef uart_setreg 62 63#define uart_getreg(bas, reg) \ 64 bus_space_read_4((bas)->bst, (bas)->bsh, reg) 65#define uart_setreg(bas, reg, value) \ 66 bus_space_write_4((bas)->bst, (bas)->bsh, reg, value) 67 68#define SIGCHG(c, i, s, d) \ 69 do { \ 70 if (c) { \ 71 i |= (i & s) ? s : s | d; \ 72 } else { \ 73 i = (i & s) ? (i & ~s) | d : i; \ 74 } \ 75 } while (0) 76 77static int 78aml8726_uart_divisor(int rclk, int baudrate) 79{ 80 int actual_baud, divisor; 81 int error; 82 83 if (baudrate == 0) 84 return (0); 85 86 /* integer version of (rclk / baudrate + .5) */ 87 divisor = ((rclk << 1) + baudrate) / (baudrate << 1); 88 if (divisor == 0 || divisor >= 65536) 89 return (0); 90 actual_baud = rclk / divisor; 91 92 /* 10 times error in percent: */ 93 error = (((actual_baud - baudrate) * 2000) / baudrate + 1) >> 1; 94 95 /* 3.0% maximum error tolerance: */ 96 if (error < -30 || error > 30) 97 return (0); 98 99 return (divisor); 100} 101 102static int 103aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, 104 int parity) 105{ 106 uint32_t cr; 107 uint32_t mr; 108 int divisor; 109 110 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 111 112 cr &= ~(AML_UART_CONTROL_DB_MASK | AML_UART_CONTROL_SB_MASK | 113 AML_UART_CONTROL_P_MASK); 114 115 switch (databits) { 116 case 5: cr |= AML_UART_CONTROL_5_DB; break; 117 case 6: cr |= AML_UART_CONTROL_6_DB; break; 118 case 7: cr |= AML_UART_CONTROL_7_DB; break; 119 case 8: cr |= AML_UART_CONTROL_8_DB; break; 120 default: return (EINVAL); 121 } 122 123 switch (stopbits) { 124 case 1: cr |= AML_UART_CONTROL_1_SB; break; 125 case 2: cr |= AML_UART_CONTROL_2_SB; break; 126 default: return (EINVAL); 127 } 128 129 switch (parity) { 130 case UART_PARITY_EVEN: cr |= AML_UART_CONTROL_P_EVEN; 131 cr |= AML_UART_CONTROL_P_EN; 132 break; 133 134 case UART_PARITY_ODD: cr |= AML_UART_CONTROL_P_ODD; 135 cr |= AML_UART_CONTROL_P_EN; 136 break; 137 138 case UART_PARITY_NONE: break; 139 140 default: return (EINVAL); 141 } 142 143 /* Set baudrate. */ 144 if (baudrate > 0 && bas->rclk != 0) { 145 divisor = aml8726_uart_divisor(bas->rclk / 4, baudrate) - 1; 146 if (divisor > 0xffff) 147 return (EINVAL); 148 149 cr &= ~AML_UART_CONTROL_BAUD_MASK; 150 cr |= (divisor & AML_UART_CONTROL_BAUD_MASK); 151 152 divisor >>= AML_UART_CONTROL_BAUD_WIDTH; 153 154 mr = uart_getreg(bas, AML_UART_MISC_REG); 155 mr &= ~(AML_UART_MISC_OLD_RX_BAUD | 156 AML_UART_MISC_BAUD_EXT_MASK); 157 mr |= ((divisor << AML_UART_MISC_BAUD_EXT_SHIFT) & 158 AML_UART_MISC_BAUD_EXT_MASK); 159 uart_setreg(bas, AML_UART_MISC_REG, mr); 160 } 161 162 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 163 uart_barrier(bas); 164 165 return (0); 166} 167 168/* 169 * Low-level UART interface. 170 */ 171 172static int 173aml8726_uart_probe(struct uart_bas *bas) 174{ 175 176 return (0); 177} 178 179static void 180aml8726_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, 181 int parity) 182{ 183 uint32_t cr; 184 uint32_t mr; 185 186 aml8726_uart_param(bas, baudrate, databits, stopbits, parity); 187 188 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 189 /* Disable all interrupt sources. */ 190 cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); 191 /* Reset the transmitter and receiver. */ 192 cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); 193 /* Enable the transmitter and receiver. */ 194 cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN); 195 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 196 uart_barrier(bas); 197 198 /* Clear RX FIFO level for generating interrupts. */ 199 mr = uart_getreg(bas, AML_UART_MISC_REG); 200 mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; 201 uart_setreg(bas, AML_UART_MISC_REG, mr); 202 uart_barrier(bas); 203 204 /* Ensure the reset bits are clear. */ 205 cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); 206 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 207 uart_barrier(bas); 208} 209 210static void 211aml8726_uart_term(struct uart_bas *bas) 212{ 213} 214 215static void 216aml8726_uart_putc(struct uart_bas *bas, int c) 217{ 218 219 while ((uart_getreg(bas, AML_UART_STATUS_REG) & 220 AML_UART_STATUS_TX_FIFO_FULL) != 0) 221 cpu_spinwait(); 222 223 uart_setreg(bas, AML_UART_WFIFO_REG, c); 224 uart_barrier(bas); 225} 226 227static int 228aml8726_uart_rxready(struct uart_bas *bas) 229{ 230 231 return ((uart_getreg(bas, AML_UART_STATUS_REG) & 232 AML_UART_STATUS_RX_FIFO_EMPTY) == 0 ? 1 : 0); 233} 234 235static int 236aml8726_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) 237{ 238 int c; 239 240 uart_lock(hwmtx); 241 242 while ((uart_getreg(bas, AML_UART_STATUS_REG) & 243 AML_UART_STATUS_RX_FIFO_EMPTY) != 0) { 244 uart_unlock(hwmtx); 245 DELAY(4); 246 uart_lock(hwmtx); 247 } 248 249 c = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff; 250 251 uart_unlock(hwmtx); 252 253 return (c); 254} 255 256struct uart_ops aml8726_uart_ops = { 257 .probe = aml8726_uart_probe, 258 .init = aml8726_uart_init, 259 .term = aml8726_uart_term, 260 .putc = aml8726_uart_putc, 261 .rxready = aml8726_uart_rxready, 262 .getc = aml8726_uart_getc, 263}; 264 265static int 266aml8726_uart_bus_probe(struct uart_softc *sc) 267{ 268 int error; 269 270 error = aml8726_uart_probe(&sc->sc_bas); 271 if (error) 272 return (error); 273 274 sc->sc_rxfifosz = 64; 275 sc->sc_txfifosz = 64; 276 sc->sc_hwiflow = 1; 277 sc->sc_hwoflow = 1; 278 279 device_set_desc(sc->sc_dev, "Amlogic aml8726 UART"); 280 281 return (0); 282} 283 284static int 285aml8726_uart_bus_getsig(struct uart_softc *sc) 286{ 287 uint32_t new, old, sig; 288 289 /* 290 * Treat DSR, DCD, and CTS as always on. 291 */ 292 293 do { 294 old = sc->sc_hwsig; 295 sig = old; 296 SIGCHG(1, sig, SER_DSR, SER_DDSR); 297 SIGCHG(1, sig, SER_DCD, SER_DDCD); 298 SIGCHG(1, sig, SER_CTS, SER_DCTS); 299 new = sig & ~SER_MASK_DELTA; 300 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 301 302 return (sig); 303} 304 305static int 306aml8726_uart_bus_setsig(struct uart_softc *sc, int sig) 307{ 308 uint32_t new, old; 309 310 do { 311 old = sc->sc_hwsig; 312 new = old; 313 if (sig & SER_DDTR) { 314 SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); 315 } 316 if (sig & SER_DRTS) { 317 SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); 318 } 319 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 320 321 return (0); 322} 323 324static int 325aml8726_uart_bus_attach(struct uart_softc *sc) 326{ 327 struct uart_bas *bas; 328 uint32_t cr; 329 uint32_t mr; 330 331 bas = &sc->sc_bas; 332 333 if (bas->rclk == 0) { 334 device_printf(sc->sc_dev, "missing clock attribute in FDT\n"); 335 return (ENXIO); 336 } 337 338 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 339 /* Disable all interrupt sources. */ 340 cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); 341 /* Ensure the reset bits are clear. */ 342 cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); 343 344 /* 345 * Reset the transmitter and receiver only if not acting as a 346 * console, otherwise it means that: 347 * 348 * 1) aml8726_uart_init was already called which did the reset 349 * 350 * 2) there may be console bytes sitting in the transmit fifo 351 */ 352 if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) 353 ; 354 else 355 cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); 356 357 /* Default to two wire mode. */ 358 cr |= AML_UART_CONTROL_TWO_WIRE_EN; 359 /* Enable the transmitter and receiver. */ 360 cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN); 361 /* Reset error bits. */ 362 cr |= AML_UART_CONTROL_CLR_ERR; 363 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 364 uart_barrier(bas); 365 366 /* Set FIFO levels for generating interrupts. */ 367 mr = uart_getreg(bas, AML_UART_MISC_REG); 368 mr &= ~AML_UART_MISC_XMIT_IRQ_CNT_MASK; 369 mr |= (0 << AML_UART_MISC_XMIT_IRQ_CNT_SHIFT); 370 mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; 371 mr |= (1 << AML_UART_MISC_RECV_IRQ_CNT_SHIFT); 372 uart_setreg(bas, AML_UART_MISC_REG, mr); 373 uart_barrier(bas); 374 375 aml8726_uart_bus_getsig(sc); 376 377 /* Ensure the reset bits are clear. */ 378 cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); 379 cr &= ~AML_UART_CONTROL_CLR_ERR; 380 /* Enable the receive interrupt. */ 381 cr |= AML_UART_CONTROL_RX_INT_EN; 382 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 383 uart_barrier(bas); 384 385 return (0); 386} 387 388static int 389aml8726_uart_bus_detach(struct uart_softc *sc) 390{ 391 struct uart_bas *bas; 392 uint32_t cr; 393 uint32_t mr; 394 395 bas = &sc->sc_bas; 396 397 /* Disable all interrupt sources. */ 398 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 399 cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN); 400 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 401 uart_barrier(bas); 402 403 /* Clear RX FIFO level for generating interrupts. */ 404 mr = uart_getreg(bas, AML_UART_MISC_REG); 405 mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK; 406 uart_setreg(bas, AML_UART_MISC_REG, mr); 407 uart_barrier(bas); 408 409 return (0); 410} 411 412static int 413aml8726_uart_bus_flush(struct uart_softc *sc, int what) 414{ 415 struct uart_bas *bas; 416 uint32_t cr; 417 418 bas = &sc->sc_bas; 419 uart_lock(sc->sc_hwmtx); 420 421 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 422 if (what & UART_FLUSH_TRANSMITTER) 423 cr |= AML_UART_CONTROL_TX_RST; 424 if (what & UART_FLUSH_RECEIVER) 425 cr |= AML_UART_CONTROL_RX_RST; 426 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 427 uart_barrier(bas); 428 429 /* Ensure the reset bits are clear. */ 430 cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST); 431 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 432 uart_barrier(bas); 433 434 uart_unlock(sc->sc_hwmtx); 435 436 return (0); 437} 438 439static int 440aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 441{ 442 struct uart_bas *bas; 443 int baudrate, divisor, error; 444 uint32_t cr, mr; 445 446 bas = &sc->sc_bas; 447 uart_lock(sc->sc_hwmtx); 448 449 error = 0; 450 switch (request) { 451 case UART_IOCTL_BAUD: 452 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 453 cr &= AML_UART_CONTROL_BAUD_MASK; 454 455 mr = uart_getreg(bas, AML_UART_MISC_REG); 456 mr &= AML_UART_MISC_BAUD_EXT_MASK; 457 458 divisor = ((mr >> AML_UART_MISC_BAUD_EXT_SHIFT) << 459 AML_UART_CONTROL_BAUD_WIDTH) | cr; 460 461 baudrate = bas->rclk / 4 / (divisor + 1); 462 if (baudrate > 0) 463 *(int*)data = baudrate; 464 else 465 error = ENXIO; 466 break; 467 468 case UART_IOCTL_IFLOW: 469 case UART_IOCTL_OFLOW: 470 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 471 if (data) 472 cr &= ~AML_UART_CONTROL_TWO_WIRE_EN; 473 else 474 cr |= AML_UART_CONTROL_TWO_WIRE_EN; 475 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 476 break; 477 478 default: 479 error = EINVAL; 480 break; 481 } 482 483 uart_unlock(sc->sc_hwmtx); 484 485 return (error); 486} 487 488static int 489aml8726_uart_bus_ipend(struct uart_softc *sc) 490{ 491 struct uart_bas *bas; 492 int ipend; 493 uint32_t sr; 494 uint32_t cr; 495 496 bas = &sc->sc_bas; 497 uart_lock(sc->sc_hwmtx); 498 499 ipend = 0; 500 sr = uart_getreg(bas, AML_UART_STATUS_REG); 501 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 502 503 if ((sr & AML_UART_STATUS_RX_FIFO_OVERFLOW) != 0) 504 ipend |= SER_INT_OVERRUN; 505 506 if ((sr & AML_UART_STATUS_TX_FIFO_EMPTY) != 0 && 507 (cr & AML_UART_CONTROL_TX_INT_EN) != 0) { 508 ipend |= SER_INT_TXIDLE; 509 510 cr &= ~AML_UART_CONTROL_TX_INT_EN; 511 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 512 uart_barrier(bas); 513 } 514 515 if ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) 516 ipend |= SER_INT_RXREADY; 517 518 uart_unlock(sc->sc_hwmtx); 519 520 return (ipend); 521} 522 523static int 524aml8726_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, 525 int stopbits, int parity) 526{ 527 struct uart_bas *bas; 528 int error; 529 530 bas = &sc->sc_bas; 531 uart_lock(sc->sc_hwmtx); 532 533 error = aml8726_uart_param(bas, baudrate, databits, stopbits, parity); 534 535 uart_unlock(sc->sc_hwmtx); 536 537 return (error); 538} 539 540static int 541aml8726_uart_bus_receive(struct uart_softc *sc) 542{ 543 struct uart_bas *bas; 544 int xc; 545 uint32_t sr; 546 547 bas = &sc->sc_bas; 548 uart_lock(sc->sc_hwmtx); 549 550 sr = uart_getreg(bas, AML_UART_STATUS_REG); 551 while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) { 552 if (uart_rx_full(sc)) { 553 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 554 break; 555 } 556 xc = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff; 557 if (sr & AML_UART_STATUS_FRAME_ERR) 558 xc |= UART_STAT_FRAMERR; 559 if (sr & AML_UART_STATUS_PARITY_ERR) 560 xc |= UART_STAT_PARERR; 561 uart_rx_put(sc, xc); 562 sr = uart_getreg(bas, AML_UART_STATUS_REG); 563 } 564 /* Discard everything left in the RX FIFO. */ 565 while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) { 566 (void)uart_getreg(bas, AML_UART_RFIFO_REG); 567 sr = uart_getreg(bas, AML_UART_STATUS_REG); 568 } 569 /* Reset error bits */ 570 if ((sr & (AML_UART_STATUS_FRAME_ERR | AML_UART_STATUS_PARITY_ERR)) != 0) { 571 uart_setreg(bas, AML_UART_CONTROL_REG, 572 (uart_getreg(bas, AML_UART_CONTROL_REG) | 573 AML_UART_CONTROL_CLR_ERR)); 574 uart_barrier(bas); 575 uart_setreg(bas, AML_UART_CONTROL_REG, 576 (uart_getreg(bas, AML_UART_CONTROL_REG) & 577 ~AML_UART_CONTROL_CLR_ERR)); 578 uart_barrier(bas); 579 } 580 581 uart_unlock(sc->sc_hwmtx); 582 583 return (0); 584} 585 586static int 587aml8726_uart_bus_transmit(struct uart_softc *sc) 588{ 589 struct uart_bas *bas; 590 int i; 591 uint32_t cr; 592 593 bas = &sc->sc_bas; 594 uart_lock(sc->sc_hwmtx); 595 596 /* 597 * Wait for sufficient space since aml8726_uart_putc 598 * may have been called after SER_INT_TXIDLE occurred. 599 */ 600 while ((uart_getreg(bas, AML_UART_STATUS_REG) & 601 AML_UART_STATUS_TX_FIFO_EMPTY) == 0) 602 cpu_spinwait(); 603 604 for (i = 0; i < sc->sc_txdatasz; i++) { 605 uart_setreg(bas, AML_UART_WFIFO_REG, sc->sc_txbuf[i]); 606 uart_barrier(bas); 607 } 608 609 sc->sc_txbusy = 1; 610 611 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 612 cr |= AML_UART_CONTROL_TX_INT_EN; 613 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 614 uart_barrier(bas); 615 616 uart_unlock(sc->sc_hwmtx); 617 618 return (0); 619} 620 621static void 622aml8726_uart_bus_grab(struct uart_softc *sc) 623{ 624 struct uart_bas *bas; 625 uint32_t cr; 626 627 /* 628 * Disable the receive interrupt to avoid a race between 629 * aml8726_uart_getc and aml8726_uart_bus_receive which 630 * can trigger: 631 * 632 * panic: bad stray interrupt 633 * 634 * due to the RX FIFO receiving a character causing an 635 * interrupt which gets serviced after aml8726_uart_getc 636 * has been called (meaning the RX FIFO is now empty). 637 */ 638 639 bas = &sc->sc_bas; 640 uart_lock(sc->sc_hwmtx); 641 642 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 643 cr &= ~AML_UART_CONTROL_RX_INT_EN; 644 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 645 uart_barrier(bas); 646 647 uart_unlock(sc->sc_hwmtx); 648} 649 650static void 651aml8726_uart_bus_ungrab(struct uart_softc *sc) 652{ 653 struct uart_bas *bas; 654 uint32_t cr; 655 uint32_t mr; 656 657 /* 658 * The RX FIFO level being set indicates that the device 659 * is currently attached meaning the receive interrupt 660 * should be enabled. 661 */ 662 663 bas = &sc->sc_bas; 664 uart_lock(sc->sc_hwmtx); 665 666 mr = uart_getreg(bas, AML_UART_MISC_REG); 667 mr &= AML_UART_MISC_RECV_IRQ_CNT_MASK; 668 669 if (mr != 0) { 670 cr = uart_getreg(bas, AML_UART_CONTROL_REG); 671 cr |= AML_UART_CONTROL_RX_INT_EN; 672 uart_setreg(bas, AML_UART_CONTROL_REG, cr); 673 uart_barrier(bas); 674 } 675 676 uart_unlock(sc->sc_hwmtx); 677} 678 679static kobj_method_t aml8726_uart_methods[] = { 680 KOBJMETHOD(uart_probe, aml8726_uart_bus_probe), 681 KOBJMETHOD(uart_attach, aml8726_uart_bus_attach), 682 KOBJMETHOD(uart_detach, aml8726_uart_bus_detach), 683 KOBJMETHOD(uart_flush, aml8726_uart_bus_flush), 684 KOBJMETHOD(uart_getsig, aml8726_uart_bus_getsig), 685 KOBJMETHOD(uart_setsig, aml8726_uart_bus_setsig), 686 KOBJMETHOD(uart_ioctl, aml8726_uart_bus_ioctl), 687 KOBJMETHOD(uart_ipend, aml8726_uart_bus_ipend), 688 KOBJMETHOD(uart_param, aml8726_uart_bus_param), 689 KOBJMETHOD(uart_receive, aml8726_uart_bus_receive), 690 KOBJMETHOD(uart_transmit, aml8726_uart_bus_transmit), 691 KOBJMETHOD(uart_grab, aml8726_uart_bus_grab), 692 KOBJMETHOD(uart_ungrab, aml8726_uart_bus_ungrab), 693 { 0, 0 } 694}; 695 696struct uart_class uart_aml8726_class = { 697 "uart", 698 aml8726_uart_methods, 699 sizeof(struct uart_softc), 700 .uc_ops = &aml8726_uart_ops, 701 .uc_range = 24, 702 .uc_rclk = 0 703}; 704 705static struct ofw_compat_data compat_data[] = { 706 { "amlogic,aml8726-uart", (uintptr_t)&uart_aml8726_class }, 707 { NULL, (uintptr_t)NULL } 708}; 709UART_FDT_CLASS_AND_DEVICE(compat_data); 710