uart_dev_at91usart.c revision 256281
1/*- 2 * Copyright (c) 2005 M. Warner Losh 3 * Copyright (c) 2005 Olivier Houchard 4 * Copyright (c) 2012 Ian Lepore 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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 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 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: stable/10/sys/arm/at91/uart_dev_at91usart.c 248964 2013-04-01 00:00:10Z ian $"); 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/bus.h> 36#include <sys/conf.h> 37#include <sys/cons.h> 38#include <sys/tty.h> 39#include <machine/bus.h> 40 41#include <dev/uart/uart.h> 42#include <dev/uart/uart_cpu.h> 43#include <dev/uart/uart_bus.h> 44#include <arm/at91/at91_usartreg.h> 45#include <arm/at91/at91_pdcreg.h> 46#include <arm/at91/at91_piovar.h> 47#include <arm/at91/at91_pioreg.h> 48#include <arm/at91/at91rm92reg.h> 49#include <arm/at91/at91var.h> 50 51#include "uart_if.h" 52 53#define DEFAULT_RCLK at91_master_clock 54#define USART_DEFAULT_FIFO_BYTES 128 55 56#define USART_DCE_CHANGE_BITS (USART_CSR_CTSIC | USART_CSR_DCDIC | \ 57 USART_CSR_DSRIC | USART_CSR_RIIC) 58 59/* 60 * High-level UART interface. 61 */ 62struct at91_usart_rx { 63 bus_addr_t pa; 64 uint8_t *buffer; 65 bus_dmamap_t map; 66}; 67 68struct at91_usart_softc { 69 struct uart_softc base; 70 bus_dma_tag_t tx_tag; 71 bus_dmamap_t tx_map; 72 uint32_t flags; 73#define HAS_TIMEOUT 0x1 74#define USE_RTS0_WORKAROUND 0x2 75 bus_dma_tag_t rx_tag; 76 struct at91_usart_rx ping_pong[2]; 77 struct at91_usart_rx *ping; 78 struct at91_usart_rx *pong; 79}; 80 81#define RD4(bas, reg) \ 82 bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg)) 83#define WR4(bas, reg, value) \ 84 bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value) 85 86#define SIGCHG(c, i, s, d) \ 87 do { \ 88 if (c) { \ 89 i |= (i & s) ? s : s | d; \ 90 } else { \ 91 i = (i & s) ? (i & ~s) | d : i; \ 92 } \ 93 } while (0); 94 95#define BAUD2DIVISOR(b) \ 96 ((((DEFAULT_RCLK * 10) / ((b) * 16)) + 5) / 10) 97 98/* 99 * Low-level UART interface. 100 */ 101static int at91_usart_probe(struct uart_bas *bas); 102static void at91_usart_init(struct uart_bas *bas, int, int, int, int); 103static void at91_usart_term(struct uart_bas *bas); 104static void at91_usart_putc(struct uart_bas *bas, int); 105static int at91_usart_rxready(struct uart_bas *bas); 106static int at91_usart_getc(struct uart_bas *bas, struct mtx *hwmtx); 107 108extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; 109 110static int 111at91_usart_param(struct uart_bas *bas, int baudrate, int databits, 112 int stopbits, int parity) 113{ 114 uint32_t mr; 115 116 /* 117 * Assume 3-wire RS-232 configuration. 118 * XXX Not sure how uart will present the other modes to us, so 119 * XXX they are unimplemented. maybe ioctl? 120 */ 121 mr = USART_MR_MODE_NORMAL; 122 mr |= USART_MR_USCLKS_MCK; /* Assume MCK */ 123 124 /* 125 * Or in the databits requested 126 */ 127 if (databits < 9) 128 mr &= ~USART_MR_MODE9; 129 switch (databits) { 130 case 5: 131 mr |= USART_MR_CHRL_5BITS; 132 break; 133 case 6: 134 mr |= USART_MR_CHRL_6BITS; 135 break; 136 case 7: 137 mr |= USART_MR_CHRL_7BITS; 138 break; 139 case 8: 140 mr |= USART_MR_CHRL_8BITS; 141 break; 142 case 9: 143 mr |= USART_MR_CHRL_8BITS | USART_MR_MODE9; 144 break; 145 default: 146 return (EINVAL); 147 } 148 149 /* 150 * Or in the parity 151 */ 152 switch (parity) { 153 case UART_PARITY_NONE: 154 mr |= USART_MR_PAR_NONE; 155 break; 156 case UART_PARITY_ODD: 157 mr |= USART_MR_PAR_ODD; 158 break; 159 case UART_PARITY_EVEN: 160 mr |= USART_MR_PAR_EVEN; 161 break; 162 case UART_PARITY_MARK: 163 mr |= USART_MR_PAR_MARK; 164 break; 165 case UART_PARITY_SPACE: 166 mr |= USART_MR_PAR_SPACE; 167 break; 168 default: 169 return (EINVAL); 170 } 171 172 /* 173 * Or in the stop bits. Note: The hardware supports 1.5 stop 174 * bits in async mode, but there's no way to specify that 175 * AFAICT. Instead, rely on the convention documented at 176 * http://www.lammertbies.nl/comm/info/RS-232_specs.html which 177 * states that 1.5 stop bits are used for 5 bit bytes and 178 * 2 stop bits only for longer bytes. 179 */ 180 if (stopbits == 1) 181 mr |= USART_MR_NBSTOP_1; 182 else if (databits > 5) 183 mr |= USART_MR_NBSTOP_2; 184 else 185 mr |= USART_MR_NBSTOP_1_5; 186 187 /* 188 * We want normal plumbing mode too, none of this fancy 189 * loopback or echo mode. 190 */ 191 mr |= USART_MR_CHMODE_NORMAL; 192 193 mr &= ~USART_MR_MSBF; /* lsb first */ 194 mr &= ~USART_MR_CKLO_SCK; /* Don't drive SCK */ 195 196 WR4(bas, USART_MR, mr); 197 198 /* 199 * Set the baud rate (only if we know our master clock rate) 200 */ 201 if (DEFAULT_RCLK != 0) 202 WR4(bas, USART_BRGR, BAUD2DIVISOR(baudrate)); 203 204 /* 205 * Set the receive timeout based on the baud rate. The idea is to 206 * compromise between being responsive on an interactive connection and 207 * giving a bulk data sender a bit of time to queue up a new buffer 208 * without mistaking it for a stopping point in the transmission. For 209 * 19.2kbps and below, use 20 * bit time (2 characters). For faster 210 * connections use 500 microseconds worth of bits. 211 */ 212 if (baudrate <= 19200) 213 WR4(bas, USART_RTOR, 20); 214 else 215 WR4(bas, USART_RTOR, baudrate / 2000); 216 WR4(bas, USART_CR, USART_CR_STTTO); 217 218 /* XXX Need to take possible synchronous mode into account */ 219 return (0); 220} 221 222static struct uart_ops at91_usart_ops = { 223 .probe = at91_usart_probe, 224 .init = at91_usart_init, 225 .term = at91_usart_term, 226 .putc = at91_usart_putc, 227 .rxready = at91_usart_rxready, 228 .getc = at91_usart_getc, 229}; 230 231static int 232at91_usart_probe(struct uart_bas *bas) 233{ 234 235 /* We know that this is always here */ 236 return (0); 237} 238 239/* 240 * Initialize this device for use as a console. 241 */ 242static void 243at91_usart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, 244 int parity) 245{ 246 247 at91_usart_param(bas, baudrate, databits, stopbits, parity); 248 249 /* Reset the rx and tx buffers and turn on rx and tx */ 250 WR4(bas, USART_CR, USART_CR_RSTSTA | USART_CR_RSTRX | USART_CR_RSTTX); 251 WR4(bas, USART_CR, USART_CR_RXEN | USART_CR_TXEN); 252 WR4(bas, USART_IDR, 0xffffffff); 253} 254 255/* 256 * Free resources now that we're no longer the console. This appears to 257 * be never called, and I'm unsure quite what to do if I am called. 258 */ 259static void 260at91_usart_term(struct uart_bas *bas) 261{ 262 263 /* XXX */ 264} 265 266/* 267 * Put a character of console output (so we do it here polling rather than 268 * interrupt driven). 269 */ 270static void 271at91_usart_putc(struct uart_bas *bas, int c) 272{ 273 274 while (!(RD4(bas, USART_CSR) & USART_CSR_TXRDY)) 275 continue; 276 WR4(bas, USART_THR, c); 277} 278 279/* 280 * Check for a character available. 281 */ 282static int 283at91_usart_rxready(struct uart_bas *bas) 284{ 285 286 return ((RD4(bas, USART_CSR) & USART_CSR_RXRDY) != 0 ? 1 : 0); 287} 288 289/* 290 * Block waiting for a character. 291 */ 292static int 293at91_usart_getc(struct uart_bas *bas, struct mtx *hwmtx) 294{ 295 int c; 296 297 uart_lock(hwmtx); 298 while (!(RD4(bas, USART_CSR) & USART_CSR_RXRDY)) { 299 uart_unlock(hwmtx); 300 DELAY(4); 301 uart_lock(hwmtx); 302 } 303 c = RD4(bas, USART_RHR) & 0xff; 304 uart_unlock(hwmtx); 305 return (c); 306} 307 308static int at91_usart_bus_probe(struct uart_softc *sc); 309static int at91_usart_bus_attach(struct uart_softc *sc); 310static int at91_usart_bus_flush(struct uart_softc *, int); 311static int at91_usart_bus_getsig(struct uart_softc *); 312static int at91_usart_bus_ioctl(struct uart_softc *, int, intptr_t); 313static int at91_usart_bus_ipend(struct uart_softc *); 314static int at91_usart_bus_param(struct uart_softc *, int, int, int, int); 315static int at91_usart_bus_receive(struct uart_softc *); 316static int at91_usart_bus_setsig(struct uart_softc *, int); 317static int at91_usart_bus_transmit(struct uart_softc *); 318 319static kobj_method_t at91_usart_methods[] = { 320 KOBJMETHOD(uart_probe, at91_usart_bus_probe), 321 KOBJMETHOD(uart_attach, at91_usart_bus_attach), 322 KOBJMETHOD(uart_flush, at91_usart_bus_flush), 323 KOBJMETHOD(uart_getsig, at91_usart_bus_getsig), 324 KOBJMETHOD(uart_ioctl, at91_usart_bus_ioctl), 325 KOBJMETHOD(uart_ipend, at91_usart_bus_ipend), 326 KOBJMETHOD(uart_param, at91_usart_bus_param), 327 KOBJMETHOD(uart_receive, at91_usart_bus_receive), 328 KOBJMETHOD(uart_setsig, at91_usart_bus_setsig), 329 KOBJMETHOD(uart_transmit, at91_usart_bus_transmit), 330 331 KOBJMETHOD_END 332}; 333 334int 335at91_usart_bus_probe(struct uart_softc *sc) 336{ 337 int value; 338 339 value = USART_DEFAULT_FIFO_BYTES; 340 resource_int_value(device_get_name(sc->sc_dev), 341 device_get_unit(sc->sc_dev), "fifo_bytes", &value); 342 value = roundup2(value, arm_dcache_align); 343 sc->sc_txfifosz = value; 344 sc->sc_rxfifosz = value; 345 sc->sc_hwiflow = 0; 346 return (0); 347} 348 349static void 350at91_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 351{ 352 353 if (error != 0) 354 return; 355 *(bus_addr_t *)arg = segs[0].ds_addr; 356} 357 358static int 359at91_usart_requires_rts0_workaround(struct uart_softc *sc) 360{ 361 int value; 362 int unit; 363 364 unit = device_get_unit(sc->sc_dev); 365 366 /* 367 * On the rm9200 chips, the PA21/RTS0 pin is not correctly wired to the 368 * usart device interally (so-called 'erratum 39', but it's 41.14 in rev 369 * I of the manual). This prevents use of the hardware flow control 370 * feature in the usart itself. It also means that if we are to 371 * implement RTS/CTS flow via the tty layer logic, we must use pin PA21 372 * as a gpio and manually manipulate it in at91_usart_bus_setsig(). We 373 * can only safely do so if we've been given permission via a hint, 374 * otherwise we might manipulate a pin that's attached to who-knows-what 375 * and Bad Things could happen. 376 */ 377 if (at91_is_rm92() && unit == 1) { 378 value = 0; 379 resource_int_value(device_get_name(sc->sc_dev), unit, 380 "use_rts0_workaround", &value); 381 if (value != 0) { 382 at91_pio_use_gpio(AT91RM92_PIOA_BASE, AT91C_PIO_PA21); 383 at91_pio_gpio_output(AT91RM92_PIOA_BASE, 384 AT91C_PIO_PA21, 1); 385 at91_pio_use_periph_a(AT91RM92_PIOA_BASE, 386 AT91C_PIO_PA20, 0); 387 return (1); 388 } 389 } 390 return (0); 391} 392 393static int 394at91_usart_bus_attach(struct uart_softc *sc) 395{ 396 int err; 397 int i; 398 uint32_t cr; 399 struct at91_usart_softc *atsc; 400 401 atsc = (struct at91_usart_softc *)sc; 402 403 if (at91_usart_requires_rts0_workaround(sc)) 404 atsc->flags |= USE_RTS0_WORKAROUND; 405 406 /* 407 * See if we have a TIMEOUT bit. We disable all interrupts as 408 * a side effect. Boot loaders may have enabled them. Since 409 * a TIMEOUT interrupt can't happen without other setup, the 410 * apparent race here can't actually happen. 411 */ 412 WR4(&sc->sc_bas, USART_IDR, 0xffffffff); 413 WR4(&sc->sc_bas, USART_IER, USART_CSR_TIMEOUT); 414 if (RD4(&sc->sc_bas, USART_IMR) & USART_CSR_TIMEOUT) 415 atsc->flags |= HAS_TIMEOUT; 416 WR4(&sc->sc_bas, USART_IDR, 0xffffffff); 417 418 /* 419 * Allocate transmit DMA tag and map. We allow a transmit buffer 420 * to be any size, but it must map to a single contiguous physical 421 * extent. 422 */ 423 err = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 424 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 425 BUS_SPACE_MAXSIZE_32BIT, 1, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, 426 NULL, &atsc->tx_tag); 427 if (err != 0) 428 goto errout; 429 err = bus_dmamap_create(atsc->tx_tag, 0, &atsc->tx_map); 430 if (err != 0) 431 goto errout; 432 433 if (atsc->flags & HAS_TIMEOUT) { 434 /* 435 * Allocate receive DMA tags, maps, and buffers. 436 * The receive buffers should be aligned to arm_dcache_align, 437 * otherwise partial cache line flushes on every receive 438 * interrupt are pretty much guaranteed. 439 */ 440 err = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 441 arm_dcache_align, 0, BUS_SPACE_MAXADDR_32BIT, 442 BUS_SPACE_MAXADDR, NULL, NULL, sc->sc_rxfifosz, 1, 443 sc->sc_rxfifosz, BUS_DMA_ALLOCNOW, NULL, NULL, 444 &atsc->rx_tag); 445 if (err != 0) 446 goto errout; 447 for (i = 0; i < 2; i++) { 448 err = bus_dmamem_alloc(atsc->rx_tag, 449 (void **)&atsc->ping_pong[i].buffer, 450 BUS_DMA_NOWAIT, &atsc->ping_pong[i].map); 451 if (err != 0) 452 goto errout; 453 err = bus_dmamap_load(atsc->rx_tag, 454 atsc->ping_pong[i].map, 455 atsc->ping_pong[i].buffer, sc->sc_rxfifosz, 456 at91_getaddr, &atsc->ping_pong[i].pa, 0); 457 if (err != 0) 458 goto errout; 459 bus_dmamap_sync(atsc->rx_tag, atsc->ping_pong[i].map, 460 BUS_DMASYNC_PREREAD); 461 } 462 atsc->ping = &atsc->ping_pong[0]; 463 atsc->pong = &atsc->ping_pong[1]; 464 } 465 466 /* Turn on rx and tx */ 467 cr = USART_CR_RSTSTA | USART_CR_RSTRX | USART_CR_RSTTX; 468 WR4(&sc->sc_bas, USART_CR, cr); 469 WR4(&sc->sc_bas, USART_CR, USART_CR_RXEN | USART_CR_TXEN); 470 471 /* 472 * Setup the PDC to receive data. We use the ping-pong buffers 473 * so that we can more easily bounce between the two and so that 474 * we get an interrupt 1/2 way through the software 'fifo' we have 475 * to avoid overruns. 476 */ 477 if (atsc->flags & HAS_TIMEOUT) { 478 WR4(&sc->sc_bas, PDC_RPR, atsc->ping->pa); 479 WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz); 480 WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa); 481 WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz); 482 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN); 483 484 /* 485 * Set the receive timeout to be 1.5 character times 486 * assuming 8N1. 487 */ 488 WR4(&sc->sc_bas, USART_RTOR, 15); 489 WR4(&sc->sc_bas, USART_CR, USART_CR_STTTO); 490 WR4(&sc->sc_bas, USART_IER, USART_CSR_TIMEOUT | 491 USART_CSR_RXBUFF | USART_CSR_ENDRX); 492 } else { 493 WR4(&sc->sc_bas, USART_IER, USART_CSR_RXRDY); 494 } 495 WR4(&sc->sc_bas, USART_IER, USART_CSR_RXBRK | USART_DCE_CHANGE_BITS); 496 497 /* Prime sc->hwsig with the initial hw line states. */ 498 at91_usart_bus_getsig(sc); 499 500errout: 501 return (err); 502} 503 504static int 505at91_usart_bus_transmit(struct uart_softc *sc) 506{ 507 bus_addr_t addr; 508 struct at91_usart_softc *atsc; 509 int err; 510 511 err = 0; 512 atsc = (struct at91_usart_softc *)sc; 513 uart_lock(sc->sc_hwmtx); 514 if (bus_dmamap_load(atsc->tx_tag, atsc->tx_map, sc->sc_txbuf, 515 sc->sc_txdatasz, at91_getaddr, &addr, 0) != 0) { 516 err = EAGAIN; 517 goto errout; 518 } 519 bus_dmamap_sync(atsc->tx_tag, atsc->tx_map, BUS_DMASYNC_PREWRITE); 520 sc->sc_txbusy = 1; 521 /* 522 * Setup the PDC to transfer the data and interrupt us when it 523 * is done. We've already requested the interrupt. 524 */ 525 WR4(&sc->sc_bas, PDC_TPR, addr); 526 WR4(&sc->sc_bas, PDC_TCR, sc->sc_txdatasz); 527 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_TXTEN); 528 WR4(&sc->sc_bas, USART_IER, USART_CSR_ENDTX); 529errout: 530 uart_unlock(sc->sc_hwmtx); 531 return (err); 532} 533 534static int 535at91_usart_bus_setsig(struct uart_softc *sc, int sig) 536{ 537 uint32_t new, old, cr; 538 struct at91_usart_softc *atsc; 539 540 atsc = (struct at91_usart_softc *)sc; 541 542 do { 543 old = sc->sc_hwsig; 544 new = old; 545 if (sig & SER_DDTR) 546 SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); 547 if (sig & SER_DRTS) 548 SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); 549 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 550 551 cr = 0; 552 if (new & SER_DTR) 553 cr |= USART_CR_DTREN; 554 else 555 cr |= USART_CR_DTRDIS; 556 if (new & SER_RTS) 557 cr |= USART_CR_RTSEN; 558 else 559 cr |= USART_CR_RTSDIS; 560 561 uart_lock(sc->sc_hwmtx); 562 WR4(&sc->sc_bas, USART_CR, cr); 563 if (atsc->flags & USE_RTS0_WORKAROUND) { 564 /* Signal is active-low. */ 565 if (new & SER_RTS) 566 at91_pio_gpio_clear(AT91RM92_PIOA_BASE, AT91C_PIO_PA21); 567 else 568 at91_pio_gpio_set(AT91RM92_PIOA_BASE,AT91C_PIO_PA21); 569 } 570 uart_unlock(sc->sc_hwmtx); 571 572 return (0); 573} 574 575static int 576at91_usart_bus_receive(struct uart_softc *sc) 577{ 578 579 return (0); 580} 581 582static int 583at91_usart_bus_param(struct uart_softc *sc, int baudrate, int databits, 584 int stopbits, int parity) 585{ 586 587 return (at91_usart_param(&sc->sc_bas, baudrate, databits, stopbits, 588 parity)); 589} 590 591static __inline void 592at91_rx_put(struct uart_softc *sc, int key) 593{ 594 595#if defined(KDB) 596 if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) 597 kdb_alt_break(key, &sc->sc_altbrk); 598#endif 599 uart_rx_put(sc, key); 600} 601 602static int 603at91_usart_bus_ipend(struct uart_softc *sc) 604{ 605 struct at91_usart_softc *atsc; 606 struct at91_usart_rx *p; 607 int i, ipend, len; 608 uint32_t csr; 609 610 ipend = 0; 611 atsc = (struct at91_usart_softc *)sc; 612 uart_lock(sc->sc_hwmtx); 613 csr = RD4(&sc->sc_bas, USART_CSR); 614 615 if (csr & USART_CSR_OVRE) { 616 WR4(&sc->sc_bas, USART_CR, USART_CR_RSTSTA); 617 ipend |= SER_INT_OVERRUN; 618 } 619 620 if (csr & USART_DCE_CHANGE_BITS) 621 ipend |= SER_INT_SIGCHG; 622 623 if (csr & USART_CSR_ENDTX) { 624 bus_dmamap_sync(atsc->tx_tag, atsc->tx_map, 625 BUS_DMASYNC_POSTWRITE); 626 bus_dmamap_unload(atsc->tx_tag, atsc->tx_map); 627 } 628 if (csr & (USART_CSR_TXRDY | USART_CSR_ENDTX)) { 629 if (sc->sc_txbusy) 630 ipend |= SER_INT_TXIDLE; 631 WR4(&sc->sc_bas, USART_IDR, csr & (USART_CSR_TXRDY | 632 USART_CSR_ENDTX)); 633 } 634 635 /* 636 * Due to the contraints of the DMA engine present in the 637 * atmel chip, I can't just say I have a rx interrupt pending 638 * and do all the work elsewhere. I need to look at the CSR 639 * bits right now and do things based on them to avoid races. 640 */ 641 if (atsc->flags & HAS_TIMEOUT) { 642 if (csr & USART_CSR_RXBUFF) { 643 /* 644 * We have a buffer overflow. Consume data from ping 645 * and give it back to the hardware before worrying 646 * about pong, to minimze data loss. Insert an overrun 647 * marker after the contents of the pong buffer. 648 */ 649 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTDIS); 650 bus_dmamap_sync(atsc->rx_tag, atsc->ping->map, 651 BUS_DMASYNC_POSTREAD); 652 for (i = 0; i < sc->sc_rxfifosz; i++) 653 at91_rx_put(sc, atsc->ping->buffer[i]); 654 bus_dmamap_sync(atsc->rx_tag, atsc->ping->map, 655 BUS_DMASYNC_PREREAD); 656 WR4(&sc->sc_bas, PDC_RPR, atsc->ping->pa); 657 WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz); 658 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN); 659 bus_dmamap_sync(atsc->rx_tag, atsc->pong->map, 660 BUS_DMASYNC_POSTREAD); 661 for (i = 0; i < sc->sc_rxfifosz; i++) 662 at91_rx_put(sc, atsc->pong->buffer[i]); 663 uart_rx_put(sc, UART_STAT_OVERRUN); 664 bus_dmamap_sync(atsc->rx_tag, atsc->pong->map, 665 BUS_DMASYNC_PREREAD); 666 WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa); 667 WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz); 668 ipend |= SER_INT_RXREADY; 669 } else if (csr & USART_CSR_ENDRX) { 670 /* 671 * Consume data from ping of ping pong buffer, but leave 672 * current pong in place, as it has become the new ping. 673 * We need to copy data and setup the old ping as the 674 * new pong when we're done. 675 */ 676 bus_dmamap_sync(atsc->rx_tag, atsc->ping->map, 677 BUS_DMASYNC_POSTREAD); 678 for (i = 0; i < sc->sc_rxfifosz; i++) 679 at91_rx_put(sc, atsc->ping->buffer[i]); 680 p = atsc->ping; 681 atsc->ping = atsc->pong; 682 atsc->pong = p; 683 bus_dmamap_sync(atsc->rx_tag, atsc->pong->map, 684 BUS_DMASYNC_PREREAD); 685 WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa); 686 WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz); 687 ipend |= SER_INT_RXREADY; 688 } else if (csr & USART_CSR_TIMEOUT) { 689 /* 690 * On a timeout, one of the following applies: 691 * 1. Two empty buffers. The last received byte exactly 692 * filled a buffer, causing an ENDTX that got 693 * processed earlier; no new bytes have arrived. 694 * 2. Ping buffer contains some data and pong is empty. 695 * This should be the most common timeout condition. 696 * 3. Ping buffer is full and pong is now being filled. 697 * This is exceedingly rare; it can happen only if 698 * the ping buffer is almost full when a timeout is 699 * signaled, and then dataflow resumes and the ping 700 * buffer filled up between the time we read the 701 * status register above and the point where the 702 * RXTDIS takes effect here. Yes, it can happen. 703 * Because dataflow can resume at any time following a 704 * timeout (it may have already resumed before we get 705 * here), it's important to minimize the time the PDC is 706 * disabled -- just long enough to take the ping buffer 707 * out of service (so we can consume it) and install the 708 * pong buffer as the active one. Note that in case 3 709 * the hardware has already done the ping-pong swap. 710 */ 711 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTDIS); 712 if (RD4(&sc->sc_bas, PDC_RNCR) == 0) { 713 len = sc->sc_rxfifosz; 714 } else { 715 len = sc->sc_rxfifosz - RD4(&sc->sc_bas, PDC_RCR); 716 WR4(&sc->sc_bas, PDC_RPR, atsc->pong->pa); 717 WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz); 718 WR4(&sc->sc_bas, PDC_RNCR, 0); 719 } 720 WR4(&sc->sc_bas, USART_CR, USART_CR_STTTO); 721 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN); 722 bus_dmamap_sync(atsc->rx_tag, atsc->ping->map, 723 BUS_DMASYNC_POSTREAD); 724 for (i = 0; i < len; i++) 725 at91_rx_put(sc, atsc->ping->buffer[i]); 726 bus_dmamap_sync(atsc->rx_tag, atsc->ping->map, 727 BUS_DMASYNC_PREREAD); 728 p = atsc->ping; 729 atsc->ping = atsc->pong; 730 atsc->pong = p; 731 WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa); 732 WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz); 733 ipend |= SER_INT_RXREADY; 734 } 735 } else if (csr & USART_CSR_RXRDY) { 736 /* 737 * We have another charater in a device that doesn't support 738 * timeouts, so we do it one character at a time. 739 */ 740 at91_rx_put(sc, RD4(&sc->sc_bas, USART_RHR) & 0xff); 741 ipend |= SER_INT_RXREADY; 742 } 743 744 if (csr & USART_CSR_RXBRK) { 745 ipend |= SER_INT_BREAK; 746 WR4(&sc->sc_bas, USART_CR, USART_CR_RSTSTA); 747 } 748 uart_unlock(sc->sc_hwmtx); 749 return (ipend); 750} 751 752static int 753at91_usart_bus_flush(struct uart_softc *sc, int what) 754{ 755 756 return (0); 757} 758 759static int 760at91_usart_bus_getsig(struct uart_softc *sc) 761{ 762 uint32_t csr, new, old, sig; 763 764 /* 765 * Note that the atmel channel status register DCE status bits reflect 766 * the electrical state of the lines, not the logical state. Since they 767 * are logically active-low signals, we invert the tests here. 768 */ 769 do { 770 old = sc->sc_hwsig; 771 sig = old; 772 csr = RD4(&sc->sc_bas, USART_CSR); 773 SIGCHG(!(csr & USART_CSR_DSR), sig, SER_DSR, SER_DDSR); 774 SIGCHG(!(csr & USART_CSR_CTS), sig, SER_CTS, SER_DCTS); 775 SIGCHG(!(csr & USART_CSR_DCD), sig, SER_DCD, SER_DDCD); 776 SIGCHG(!(csr & USART_CSR_RI), sig, SER_RI, SER_DRI); 777 new = sig & ~SER_MASK_DELTA; 778 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 779 780 return (sig); 781} 782 783static int 784at91_usart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 785{ 786 787 switch (request) { 788 case UART_IOCTL_BREAK: 789 case UART_IOCTL_IFLOW: 790 case UART_IOCTL_OFLOW: 791 break; 792 case UART_IOCTL_BAUD: 793 /* only if we know our master clock rate */ 794 if (DEFAULT_RCLK != 0) 795 WR4(&sc->sc_bas, USART_BRGR, 796 BAUD2DIVISOR(*(int *)data)); 797 return (0); 798 } 799 return (EINVAL); 800} 801 802struct uart_class at91_usart_class = { 803 "at91_usart", 804 at91_usart_methods, 805 sizeof(struct at91_usart_softc), 806 .uc_ops = &at91_usart_ops, 807 .uc_range = 8 808}; 809