uart_dev_at91usart.c revision 213496
1324581Sbapt/*- 2241675Suqs * Copyright (c) 2005 M. Warner Losh 3241675Suqs * Copyright (c) 2005 Olivier Houchard 4316420Sbapt * All rights reserved. 5241675Suqs * 6241675Suqs * Redistribution and use in source and binary forms, with or without 7241675Suqs * modification, are permitted provided that the following conditions 8241675Suqs * are met: 9241675Suqs * 10241675Suqs * 1. Redistributions of source code must retain the above copyright 11241675Suqs * notice, this list of conditions and the following disclaimer. 12241675Suqs * 2. Redistributions in binary form must reproduce the above copyright 13241675Suqs * notice, this list of conditions and the following disclaimer in the 14241675Suqs * documentation and/or other materials provided with the distribution. 15241675Suqs * 16241675Suqs * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17241675Suqs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18241675Suqs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19241675Suqs * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 20275432Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21275432Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22241675Suqs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23241675Suqs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24241675Suqs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25241675Suqs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26241675Suqs * SUCH DAMAGE. 27241675Suqs */ 28241675Suqs 29241675Suqs#include <sys/cdefs.h> 30241675Suqs__FBSDID("$FreeBSD: head/sys/arm/at91/uart_dev_at91usart.c 213496 2010-10-06 22:25:21Z cognet $"); 31241675Suqs 32241675Suqs#include "opt_comconsole.h" 33241675Suqs 34322249Sbapt#include <sys/param.h> 35241675Suqs#include <sys/systm.h> 36274880Sbapt#include <sys/bus.h> 37241675Suqs#include <sys/conf.h> 38241675Suqs#include <sys/cons.h> 39241675Suqs#include <sys/tty.h> 40294113Sbapt#include <machine/bus.h> 41241675Suqs 42241675Suqs#include <dev/uart/uart.h> 43241675Suqs#include <dev/uart/uart_cpu.h> 44241675Suqs#include <dev/uart/uart_bus.h> 45241675Suqs#include <arm/at91/at91rm92reg.h> 46294113Sbapt#include <arm/at91/at91_usartreg.h> 47241675Suqs#include <arm/at91/at91_pdcreg.h> 48241675Suqs#include <arm/at91/at91var.h> 49322249Sbapt 50322249Sbapt#include "uart_if.h" 51322249Sbapt 52324581Sbapt#define DEFAULT_RCLK at91_master_clock 53324581Sbapt#define USART_BUFFER_SIZE 128 54324581Sbapt 55322249Sbapt/* 56322249Sbapt * High-level UART interface. 57322249Sbapt */ 58322249Sbaptstruct at91_usart_rx { 59322249Sbapt bus_addr_t pa; 60322249Sbapt uint8_t buffer[USART_BUFFER_SIZE]; 61322249Sbapt bus_dmamap_t map; 62322249Sbapt}; 63322249Sbapt 64322249Sbaptstruct at91_usart_softc { 65322249Sbapt struct uart_softc base; 66322249Sbapt bus_dma_tag_t dmatag; /* bus dma tag for mbufs */ 67322249Sbapt bus_dmamap_t tx_map; 68322249Sbapt uint32_t flags; 69322249Sbapt#define HAS_TIMEOUT 1 70322249Sbapt struct at91_usart_rx ping_pong[2]; 71322249Sbapt struct at91_usart_rx *ping; 72322249Sbapt struct at91_usart_rx *pong; 73322249Sbapt}; 74322249Sbapt 75322249Sbapt#define RD4(bas, reg) \ 76322249Sbapt bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg)) 77322249Sbapt#define WR4(bas, reg, value) \ 78322249Sbapt bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value) 79241675Suqs 80241675Suqs#define SIGCHG(c, i, s, d) \ 81241675Suqs do { \ 82322249Sbapt if (c) { \ 83279527Sbapt i |= (i & s) ? s : s | d; \ 84241675Suqs } else { \ 85279527Sbapt i = (i & s) ? (i & ~s) | d : i; \ 86241675Suqs } \ 87241675Suqs } while (0); 88322249Sbapt 89322249Sbapt#define BAUD2DIVISOR(b) \ 90241675Suqs ((((DEFAULT_RCLK * 10) / ((b) * 16)) + 5) / 10) 91241675Suqs 92241675Suqs/* 93316420Sbapt * Low-level UART interface. 94241675Suqs */ 95322249Sbaptstatic int at91_usart_probe(struct uart_bas *bas); 96316420Sbaptstatic void at91_usart_init(struct uart_bas *bas, int, int, int, int); 97316420Sbaptstatic void at91_usart_term(struct uart_bas *bas); 98322249Sbaptstatic void at91_usart_putc(struct uart_bas *bas, int); 99241675Suqsstatic int at91_usart_rxready(struct uart_bas *bas); 100241675Suqsstatic int at91_usart_getc(struct uart_bas *bas, struct mtx *mtx); 101241675Suqs 102241675Suqsextern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; 103241675Suqs 104241675Suqsstatic int 105241675Suqsat91_usart_param(struct uart_bas *bas, int baudrate, int databits, 106241675Suqs int stopbits, int parity) 107241675Suqs{ 108241675Suqs uint32_t mr; 109241675Suqs 110241675Suqs /* 111241675Suqs * Assume 3-write RS-232 configuration. 112241675Suqs * XXX Not sure how uart will present the other modes to us, so 113241675Suqs * XXX they are unimplemented. maybe ioctl? 114241675Suqs */ 115279527Sbapt mr = USART_MR_MODE_NORMAL; 116241675Suqs mr |= USART_MR_USCLKS_MCK; /* Assume MCK */ 117241675Suqs 118241675Suqs /* 119279527Sbapt * Or in the databits requested 120241675Suqs */ 121241675Suqs if (databits < 9) 122241675Suqs mr &= ~USART_MR_MODE9; 123241675Suqs switch (databits) { 124241675Suqs case 5: 125241675Suqs mr |= USART_MR_CHRL_5BITS; 126241675Suqs break; 127316420Sbapt case 6: 128241675Suqs mr |= USART_MR_CHRL_6BITS; 129241675Suqs break; 130274880Sbapt case 7: 131274880Sbapt mr |= USART_MR_CHRL_7BITS; 132316420Sbapt break; 133241675Suqs case 8: 134241675Suqs mr |= USART_MR_CHRL_8BITS; 135241675Suqs break; 136279527Sbapt case 9: 137241675Suqs mr |= USART_MR_CHRL_8BITS | USART_MR_MODE9; 138316420Sbapt break; 139241675Suqs default: 140279527Sbapt return (EINVAL); 141279527Sbapt } 142279527Sbapt 143279527Sbapt /* 144261344Suqs * Or in the parity 145261344Suqs */ 146241675Suqs switch (parity) { 147241675Suqs case UART_PARITY_NONE: 148241675Suqs mr |= USART_MR_PAR_NONE; 149241675Suqs break; 150241675Suqs case UART_PARITY_ODD: 151241675Suqs mr |= USART_MR_PAR_ODD; 152241675Suqs break; 153241675Suqs case UART_PARITY_EVEN: 154279527Sbapt mr |= USART_MR_PAR_EVEN; 155241675Suqs break; 156241675Suqs case UART_PARITY_MARK: 157241675Suqs mr |= USART_MR_PAR_MARK; 158241675Suqs break; 159241675Suqs case UART_PARITY_SPACE: 160241675Suqs mr |= USART_MR_PAR_SPACE; 161241675Suqs break; 162 default: 163 return (EINVAL); 164 } 165 166 /* 167 * Or in the stop bits. Note: The hardware supports 1.5 stop 168 * bits in async mode, but there's no way to specify that 169 * AFAICT. Instead, rely on the convention documented at 170 * http://www.lammertbies.nl/comm/info/RS-232_specs.html which 171 * states that 1.5 stop bits are used for 5 bit bytes and 172 * 2 stop bits only for longer bytes. 173 */ 174 if (stopbits == 1) 175 mr |= USART_MR_NBSTOP_1; 176 else if (databits > 5) 177 mr |= USART_MR_NBSTOP_2; 178 else 179 mr |= USART_MR_NBSTOP_1_5; 180 181 /* 182 * We want normal plumbing mode too, none of this fancy 183 * loopback or echo mode. 184 */ 185 mr |= USART_MR_CHMODE_NORMAL; 186 187 mr &= ~USART_MR_MSBF; /* lsb first */ 188 mr &= ~USART_MR_CKLO_SCK; /* Don't drive SCK */ 189 190 WR4(bas, USART_MR, mr); 191 192 /* 193 * Set the baud rate (only if we know our master clock rate) 194 */ 195 if (DEFAULT_RCLK != 0) 196 WR4(bas, USART_BRGR, BAUD2DIVISOR(baudrate)); 197 198 /* XXX Need to take possible synchronous mode into account */ 199 return (0); 200} 201 202static struct uart_ops at91_usart_ops = { 203 .probe = at91_usart_probe, 204 .init = at91_usart_init, 205 .term = at91_usart_term, 206 .putc = at91_usart_putc, 207 .rxready = at91_usart_rxready, 208 .getc = at91_usart_getc, 209}; 210 211static int 212at91_usart_probe(struct uart_bas *bas) 213{ 214 /* We know that this is always here */ 215 return (0); 216} 217 218/* 219 * Initialize this device for use as a console. 220 */ 221static void 222at91_usart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, 223 int parity) 224{ 225 226 at91_usart_param(bas, baudrate, databits, stopbits, parity); 227 228 /* Reset the rx and tx buffers and turn on rx and tx */ 229 WR4(bas, USART_CR, USART_CR_RSTSTA | USART_CR_RSTRX | USART_CR_RSTTX); 230 WR4(bas, USART_CR, USART_CR_RXEN | USART_CR_TXEN); 231 WR4(bas, USART_IDR, 0xffffffff); 232} 233 234/* 235 * Free resources now that we're no longer the console. This appears to 236 * be never called, and I'm unsure quite what to do if I am called. 237 */ 238static void 239at91_usart_term(struct uart_bas *bas) 240{ 241 /* XXX */ 242} 243 244/* 245 * Put a character of console output (so we do it here polling rather than 246 * interrutp driven). 247 */ 248static void 249at91_usart_putc(struct uart_bas *bas, int c) 250{ 251 252 while (!(RD4(bas, USART_CSR) & USART_CSR_TXRDY)) 253 continue; 254 WR4(bas, USART_THR, c); 255} 256 257/* 258 * Check for a character available. 259 */ 260static int 261at91_usart_rxready(struct uart_bas *bas) 262{ 263 264 return ((RD4(bas, USART_CSR) & USART_CSR_RXRDY) != 0 ? 1 : 0); 265} 266 267/* 268 * Block waiting for a character. 269 */ 270static int 271at91_usart_getc(struct uart_bas *bas, struct mtx *mtx) 272{ 273 int c; 274 275 while (!(RD4(bas, USART_CSR) & USART_CSR_RXRDY)) 276 continue; 277 c = RD4(bas, USART_RHR); 278 c &= 0xff; 279 return (c); 280} 281 282static int at91_usart_bus_probe(struct uart_softc *sc); 283static int at91_usart_bus_attach(struct uart_softc *sc); 284static int at91_usart_bus_flush(struct uart_softc *, int); 285static int at91_usart_bus_getsig(struct uart_softc *); 286static int at91_usart_bus_ioctl(struct uart_softc *, int, intptr_t); 287static int at91_usart_bus_ipend(struct uart_softc *); 288static int at91_usart_bus_param(struct uart_softc *, int, int, int, int); 289static int at91_usart_bus_receive(struct uart_softc *); 290static int at91_usart_bus_setsig(struct uart_softc *, int); 291static int at91_usart_bus_transmit(struct uart_softc *); 292 293static kobj_method_t at91_usart_methods[] = { 294 KOBJMETHOD(uart_probe, at91_usart_bus_probe), 295 KOBJMETHOD(uart_attach, at91_usart_bus_attach), 296 KOBJMETHOD(uart_flush, at91_usart_bus_flush), 297 KOBJMETHOD(uart_getsig, at91_usart_bus_getsig), 298 KOBJMETHOD(uart_ioctl, at91_usart_bus_ioctl), 299 KOBJMETHOD(uart_ipend, at91_usart_bus_ipend), 300 KOBJMETHOD(uart_param, at91_usart_bus_param), 301 KOBJMETHOD(uart_receive, at91_usart_bus_receive), 302 KOBJMETHOD(uart_setsig, at91_usart_bus_setsig), 303 KOBJMETHOD(uart_transmit, at91_usart_bus_transmit), 304 305 { 0, 0 } 306}; 307 308int 309at91_usart_bus_probe(struct uart_softc *sc) 310{ 311 312 sc->sc_txfifosz = USART_BUFFER_SIZE; 313 sc->sc_rxfifosz = USART_BUFFER_SIZE; 314 sc->sc_hwiflow = 0; 315 return (0); 316} 317 318#ifndef SKYEYE_WORKAROUNDS 319static void 320at91_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 321{ 322 if (error != 0) 323 return; 324 *(bus_addr_t *)arg = segs[0].ds_addr; 325} 326#endif 327 328static int 329at91_usart_bus_attach(struct uart_softc *sc) 330{ 331#ifndef SKYEYE_WORKAROUNDS 332 int err; 333 int i; 334#endif 335 uint32_t cr; 336 struct at91_usart_softc *atsc; 337 338 atsc = (struct at91_usart_softc *)sc; 339 340 /* 341 * See if we have a TIMEOUT bit. We disable all interrupts as 342 * a side effect. Boot loaders may have enabled them. Since 343 * a TIMEOUT interrupt can't happen without other setup, the 344 * apparent race here can't actually happen. 345 */ 346 WR4(&sc->sc_bas, USART_IDR, 0xffffffff); 347 WR4(&sc->sc_bas, USART_IER, USART_CSR_TIMEOUT); 348 if (RD4(&sc->sc_bas, USART_IMR) & USART_CSR_TIMEOUT) 349 atsc->flags |= HAS_TIMEOUT; 350 WR4(&sc->sc_bas, USART_IDR, 0xffffffff); 351 352#ifndef SKYEYE_WORKAROUNDS 353 /* 354 * Allocate DMA tags and maps 355 */ 356 err = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 357 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 358 USART_BUFFER_SIZE, 1, USART_BUFFER_SIZE, BUS_DMA_ALLOCNOW, NULL, 359 NULL, &atsc->dmatag); 360 if (err != 0) 361 goto errout; 362 err = bus_dmamap_create(atsc->dmatag, 0, &atsc->tx_map); 363 if (err != 0) 364 goto errout; 365 if (atsc->flags & HAS_TIMEOUT) { 366 for (i = 0; i < 2; i++) { 367 err = bus_dmamap_create(atsc->dmatag, 0, 368 &atsc->ping_pong[i].map); 369 if (err != 0) 370 goto errout; 371 err = bus_dmamap_load(atsc->dmatag, 372 atsc->ping_pong[i].map, 373 atsc->ping_pong[i].buffer, sc->sc_rxfifosz, 374 at91_getaddr, &atsc->ping_pong[i].pa, 0); 375 if (err != 0) 376 goto errout; 377 bus_dmamap_sync(atsc->dmatag, atsc->ping_pong[i].map, 378 BUS_DMASYNC_PREREAD); 379 } 380 atsc->ping = &atsc->ping_pong[0]; 381 atsc->pong = &atsc->ping_pong[1]; 382 } 383#endif 384 385 /* 386 * Prime the pump with the RX buffer. We use two 64 byte bounce 387 * buffers here to avoid data overflow. 388 */ 389 390 /* Turn on rx and tx */ 391 cr = USART_CR_RSTSTA | USART_CR_RSTRX | USART_CR_RSTTX; 392 WR4(&sc->sc_bas, USART_CR, cr); 393 WR4(&sc->sc_bas, USART_CR, USART_CR_RXEN | USART_CR_TXEN); 394 395 /* 396 * Setup the PDC to receive data. We use the ping-pong buffers 397 * so that we can more easily bounce between the two and so that 398 * we get an interrupt 1/2 way through the software 'fifo' we have 399 * to avoid overruns. 400 */ 401 if (atsc->flags & HAS_TIMEOUT) { 402 WR4(&sc->sc_bas, PDC_RPR, atsc->ping->pa); 403 WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz); 404 WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa); 405 WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz); 406 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN); 407 408 /* Set the receive timeout to be 1.5 character times. */ 409 WR4(&sc->sc_bas, USART_RTOR, 12); 410 WR4(&sc->sc_bas, USART_CR, USART_CR_STTTO); 411 WR4(&sc->sc_bas, USART_IER, USART_CSR_TIMEOUT | 412 USART_CSR_RXBUFF | USART_CSR_ENDRX); 413 } else { 414 WR4(&sc->sc_bas, USART_IER, USART_CSR_RXRDY); 415 } 416 WR4(&sc->sc_bas, USART_IER, USART_CSR_RXBRK); 417#ifndef SKYEYE_WORKAROUNDS 418errout:; 419 // XXX bad 420 return (err); 421#else 422 return (0); 423#endif 424} 425 426static int 427at91_usart_bus_transmit(struct uart_softc *sc) 428{ 429#ifndef SKYEYE_WORKAROUNDS 430 bus_addr_t addr; 431#endif 432 struct at91_usart_softc *atsc; 433 434 atsc = (struct at91_usart_softc *)sc; 435#ifndef SKYEYE_WORKAROUNDS 436 if (bus_dmamap_load(atsc->dmatag, atsc->tx_map, sc->sc_txbuf, 437 sc->sc_txdatasz, at91_getaddr, &addr, 0) != 0) 438 return (EAGAIN); 439 bus_dmamap_sync(atsc->dmatag, atsc->tx_map, BUS_DMASYNC_PREWRITE); 440#endif 441 442 uart_lock(sc->sc_hwmtx); 443 sc->sc_txbusy = 1; 444#ifndef SKYEYE_WORKAROUNDS 445 /* 446 * Setup the PDC to transfer the data and interrupt us when it 447 * is done. We've already requested the interrupt. 448 */ 449 WR4(&sc->sc_bas, PDC_TPR, addr); 450 WR4(&sc->sc_bas, PDC_TCR, sc->sc_txdatasz); 451 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_TXTEN); 452 WR4(&sc->sc_bas, USART_IER, USART_CSR_ENDTX); 453 uart_unlock(sc->sc_hwmtx); 454#else 455 for (int i = 0; i < sc->sc_txdatasz; i++) 456 at91_usart_putc(&sc->sc_bas, sc->sc_txbuf[i]); 457 /* 458 * XXX: Gross hack : Skyeye doesn't raise an interrupt once the 459 * transfer is done, so simulate it. 460 */ 461 WR4(&sc->sc_bas, USART_IER, USART_CSR_TXRDY); 462#endif 463 return (0); 464} 465static int 466at91_usart_bus_setsig(struct uart_softc *sc, int sig) 467{ 468 uint32_t new, old, cr; 469 struct uart_bas *bas; 470 471 do { 472 old = sc->sc_hwsig; 473 new = old; 474 if (sig & SER_DDTR) 475 SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); 476 if (sig & SER_DRTS) 477 SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); 478 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 479 bas = &sc->sc_bas; 480 uart_lock(sc->sc_hwmtx); 481 cr = 0; 482 if (new & SER_DTR) 483 cr |= USART_CR_DTREN; 484 else 485 cr |= USART_CR_DTRDIS; 486 if (new & SER_RTS) 487 cr |= USART_CR_RTSEN; 488 else 489 cr |= USART_CR_RTSDIS; 490 WR4(bas, USART_CR, cr); 491 uart_unlock(sc->sc_hwmtx); 492 return (0); 493} 494static int 495at91_usart_bus_receive(struct uart_softc *sc) 496{ 497 498 return (0); 499} 500static int 501at91_usart_bus_param(struct uart_softc *sc, int baudrate, int databits, 502 int stopbits, int parity) 503{ 504 505 return (at91_usart_param(&sc->sc_bas, baudrate, databits, stopbits, 506 parity)); 507} 508 509static __inline void 510at91_rx_put(struct uart_softc *sc, int key) 511{ 512#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER) 513 int kdb_brk; 514 515 if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { 516 if ((kdb_brk = kdb_alt_break(key, &sc->sc_altbrk)) != 0) { 517 switch (kdb_brk) { 518 case KDB_REQ_DEBUGGER: 519 kdb_enter(KDB_WHY_BREAK, 520 "Break sequence on console"); 521 break; 522 case KDB_REQ_PANIC: 523 kdb_panic("Panic sequence on console"); 524 break; 525 case KDB_REQ_REBOOT: 526 kdb_reboot(); 527 break; 528 } 529 } 530 } 531#endif 532 uart_rx_put(sc, key); 533} 534 535static int 536at91_usart_bus_ipend(struct uart_softc *sc) 537{ 538 int csr = RD4(&sc->sc_bas, USART_CSR); 539 int ipend = 0, i, len; 540 struct at91_usart_softc *atsc; 541 struct at91_usart_rx *p; 542 543 atsc = (struct at91_usart_softc *)sc; 544 if (csr & USART_CSR_ENDTX) { 545 bus_dmamap_sync(atsc->dmatag, atsc->tx_map, 546 BUS_DMASYNC_POSTWRITE); 547 bus_dmamap_unload(atsc->dmatag, atsc->tx_map); 548 } 549 uart_lock(sc->sc_hwmtx); 550 if (csr & USART_CSR_TXRDY) { 551 if (sc->sc_txbusy) 552 ipend |= SER_INT_TXIDLE; 553 WR4(&sc->sc_bas, USART_IDR, USART_CSR_TXRDY); 554 } 555 if (csr & USART_CSR_ENDTX) { 556 if (sc->sc_txbusy) 557 ipend |= SER_INT_TXIDLE; 558 WR4(&sc->sc_bas, USART_IDR, USART_CSR_ENDTX); 559 } 560 561 /* 562 * Due to the contraints of the DMA engine present in the 563 * atmel chip, I can't just say I have a rx interrupt pending 564 * and do all the work elsewhere. I need to look at the CSR 565 * bits right now and do things based on them to avoid races. 566 */ 567 if ((atsc->flags & HAS_TIMEOUT) && (csr & USART_CSR_RXBUFF)) { 568 // Have a buffer overflow. Copy all data from both 569 // ping and pong. Insert overflow character. Reset 570 // ping and pong and re-enable the PDC to receive 571 // characters again. 572 bus_dmamap_sync(atsc->dmatag, atsc->ping->map, 573 BUS_DMASYNC_POSTREAD); 574 bus_dmamap_sync(atsc->dmatag, atsc->pong->map, 575 BUS_DMASYNC_POSTREAD); 576 for (i = 0; i < sc->sc_rxfifosz; i++) 577 at91_rx_put(sc, atsc->ping->buffer[i]); 578 for (i = 0; i < sc->sc_rxfifosz; i++) 579 at91_rx_put(sc, atsc->pong->buffer[i]); 580 uart_rx_put(sc, UART_STAT_OVERRUN); 581 csr &= ~(USART_CSR_ENDRX | USART_CSR_TIMEOUT); 582 WR4(&sc->sc_bas, PDC_RPR, atsc->ping->pa); 583 WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz); 584 WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa); 585 WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz); 586 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN); 587 ipend |= SER_INT_RXREADY; 588 } 589 if ((atsc->flags & HAS_TIMEOUT) && (csr & USART_CSR_ENDRX)) { 590 // Shuffle data from 'ping' of ping pong buffer, but 591 // leave current 'pong' in place, as it has become the 592 // new 'ping'. We need to copy data and setup the old 593 // 'ping' as the new 'pong' when we're done. 594 bus_dmamap_sync(atsc->dmatag, atsc->ping->map, 595 BUS_DMASYNC_POSTREAD); 596 for (i = 0; i < sc->sc_rxfifosz; i++) 597 at91_rx_put(sc, atsc->ping->buffer[i]); 598 p = atsc->ping; 599 atsc->ping = atsc->pong; 600 atsc->pong = p; 601 WR4(&sc->sc_bas, PDC_RNPR, atsc->pong->pa); 602 WR4(&sc->sc_bas, PDC_RNCR, sc->sc_rxfifosz); 603 ipend |= SER_INT_RXREADY; 604 } 605 if ((atsc->flags & HAS_TIMEOUT) && (csr & USART_CSR_TIMEOUT)) { 606 // We have one partial buffer. We need to stop the 607 // PDC, get the number of characters left and from 608 // that compute number of valid characters. We then 609 // need to reset ping and pong and reenable the PDC. 610 // Not sure if there's a race here at fast baud rates 611 // we need to worry about. 612 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTDIS); 613 bus_dmamap_sync(atsc->dmatag, atsc->ping->map, 614 BUS_DMASYNC_POSTREAD); 615 len = sc->sc_rxfifosz - RD4(&sc->sc_bas, PDC_RCR); 616 for (i = 0; i < len; i++) 617 at91_rx_put(sc, atsc->ping->buffer[i]); 618 WR4(&sc->sc_bas, PDC_RPR, atsc->ping->pa); 619 WR4(&sc->sc_bas, PDC_RCR, sc->sc_rxfifosz); 620 WR4(&sc->sc_bas, USART_CR, USART_CR_STTTO); 621 WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_RXTEN); 622 ipend |= SER_INT_RXREADY; 623 } 624 if (!(atsc->flags & HAS_TIMEOUT) && (csr & USART_CSR_RXRDY)) { 625 // We have another charater in a device that doesn't support 626 // timeouts, so we do it one character at a time. 627 at91_rx_put(sc, RD4(&sc->sc_bas, USART_RHR) & 0xff); 628 ipend |= SER_INT_RXREADY; 629 } 630 631 if (csr & USART_CSR_RXBRK) { 632 unsigned int cr = USART_CR_RSTSTA; 633 634 ipend |= SER_INT_BREAK; 635 WR4(&sc->sc_bas, USART_CR, cr); 636 } 637 uart_unlock(sc->sc_hwmtx); 638 return (ipend); 639} 640static int 641at91_usart_bus_flush(struct uart_softc *sc, int what) 642{ 643 return (0); 644} 645 646static int 647at91_usart_bus_getsig(struct uart_softc *sc) 648{ 649 uint32_t new, sig; 650 uint8_t csr; 651 652 uart_lock(sc->sc_hwmtx); 653 csr = RD4(&sc->sc_bas, USART_CSR); 654 sig = 0; 655 if (csr & USART_CSR_CTS) 656 sig |= SER_CTS; 657 if (csr & USART_CSR_DCD) 658 sig |= SER_DCD; 659 if (csr & USART_CSR_DSR) 660 sig |= SER_DSR; 661 if (csr & USART_CSR_RI) 662 sig |= SER_RI; 663 new = sig & ~SER_MASK_DELTA; 664 sc->sc_hwsig = new; 665 uart_unlock(sc->sc_hwmtx); 666 return (sig); 667} 668 669static int 670at91_usart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 671{ 672 switch (request) { 673 case UART_IOCTL_BREAK: 674 case UART_IOCTL_IFLOW: 675 case UART_IOCTL_OFLOW: 676 break; 677 case UART_IOCTL_BAUD: 678 /* only if we know our master clock rate */ 679 if (DEFAULT_RCLK != 0) 680 WR4(&sc->sc_bas, USART_BRGR, 681 BAUD2DIVISOR(*(int *)data)); 682 return (0); 683 } 684 return (EINVAL); 685} 686 687struct uart_class at91_usart_class = { 688 "at91_usart", 689 at91_usart_methods, 690 sizeof(struct at91_usart_softc), 691 .uc_ops = &at91_usart_ops, 692 .uc_range = 8 693}; 694