1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12#include <stdlib.h> 13#include <platsupport/serial.h> 14#include <platsupport/plat/serial.h> 15#include <string.h> 16#include <utils/fence.h> 17 18#include "../../chardev.h" 19 20#define UART_BYTE_MASK 0xff 21 22#define NV_UART_INPUT_CLOCK_FREQ_HZ (408000000) 23 24#define LCR_DLAB BIT(7) 25#define LCR_SET_BREAK BIT(6) 26#define LCR_SET_PARITY BIT(5) /* Force parity to value of BIT(4) */ 27#define LCR_EVEN BIT(4) /* even parity? */ 28#define LCR_PAR BIT(3) /* send parity? */ 29#define LCR_STOP BIT(2) /* transmit 1 (0) or 2 (1) stop bits */ 30#define LCR_WD_SIZE_5 0 31#define LCR_WD_SIZE_6 1 32#define LCR_WD_SIZE_7 2 33#define LCR_WD_SIZE_8 3 34 35#define LSR_THRE_EMPTY (BIT(5)) 36#define LSR_RDR_READY BIT(0) 37 38#define IER_RHR_ENABLE BIT(0) 39#define IER_THR_EMPTY_ENABLE BIT(1) 40#define IER_RX_FIFO_TIMEDOUT BIT(4) 41#define IER_EO_RECEIVE_DATA BIT(5) 42 43/* IIR is read-only, FCR is write-only. Both share the same address mapping. 44 * IIR is automatically selected when you do a read-access. 45 * FCR is automatically selected when you do a write-access 46 */ 47#define FCR_FIFO_ENABLE BIT(0) 48#define FCR_DMA_MODE0 (0) 49#define FCR_DMA_MODE1 BIT(3) 50#define FCR_RX_TRIG_SHIFT (6) 51#define FCR_RX_TRIG_MASK (0x3) 52#define FCR_RX_TRIG_FIFO_GT_1 (0) 53#define FCR_RX_TRIG_FIFO_GT_4 (1) 54#define FCR_RX_TRIG_FIFO_GT_8 (2) 55#define FCR_RX_TRIG_FIFO_GT_16 (3) 56 57#define FCR_TX_TRIG_SHIFT (4) 58#define FCR_TX_TRIG_MASK (0x3) 59#define FCR_TX_TRIG_FIFO_GT_1 (3) 60#define FCR_TX_TRIG_FIFO_GT_4 (2) 61#define FCR_TX_TRIG_FIFO_GT_8 (1) 62#define FCR_TX_TRIG_FIFO_GT_16 (0) 63 64#define FCR_TX_FIFO_CLEAR_SHIFT (2) 65#define FCR_RX_FIFO_CLEAR_SHIFT (1) 66 67#define IIR_FIFO_MODE_STATUS_SHIFT (6) 68#define IIR_FIFO_MODE_STATUS_MASK (0x3) 69 70#define IIR_INT_PENDING BIT(0) 71#define IIR_INT_SOURCE_SHIFT (0) 72#define IIR_INT_SOURCE_MASK (0xF) 73 74enum iir_int_source { 75 IIR_INT_SOURCE_NO_INTERRUPT = 0x1, 76 IIR_INT_SOURCE_DATA_ERROR = 0x6, 77 IIR_INT_SOURCE_RECEIVED_DATA_AVAILABLE = 0x4, 78 IIR_INT_SOURCE_RECEIVED_DATA_TIMEOUT = 0xC, 79 IIR_INT_SOURCE_EO_RECEIVED_DATA = 0x8, 80 IIR_INT_SOURCE_THR_TXRDY = 0x2, 81 IIR_INT_SOURCE_MODEM_STATUS = 0x0 82}; 83 84#define EXTRACT_BITS(bf,shift,mask) (((bf) >> (shift)) & (mask)) 85#define ENCODE_BITS(bf,shift,mask,v) (((bf) & ~(((mask) << (shift)))) \ 86 | (((v) & (mask)) << (shift))) 87struct tk1_uart_regs { 88 uint32_t thr_dlab; /* 0x0: tx holding register */ 89 uint32_t ier_dlab; /* 0x4: IER and DLH registers */ 90 uint32_t iir_fcr; /* 0x8: FIFO control; interrupt identification */ 91 uint32_t lcr; /* 0xc: line control */ 92 uint32_t mcr; /* 0x10: modem control */ 93 uint32_t lsr; /* 0x14: line status */ 94 uint32_t msr; /* 0x18: modem status */ 95 uint32_t spr; /* 0x1c: scratchpad */ 96 uint32_t csr; /* 0x20: IrDA pulse coding */ 97 uint32_t rx_fifo_cfg;/* 0x24: */ 98 uint32_t mie; /* 0x28: modem interrupt enable */ 99 uint32_t asr; /* 0x3c: auto sense baud */ 100}; 101typedef volatile struct tk1_uart_regs tk1_uart_regs_t; 102 103static inline tk1_uart_regs_t* 104tk1_uart_get_priv(ps_chardevice_t *d) 105{ 106 return (tk1_uart_regs_t*)d->vaddr; 107} 108 109static inline bool 110tk1_uart_is_async(ps_chardevice_t *d) 111{ 112 /* NV_UART[ABCD] are polling, while NV_UART[ABCD]_ASYNC are asynchronous 113 * versions of the first 4 devices. 114 */ 115 return (d->id >= NV_UARTA_ASYNC); 116} 117 118static inline void 119tk1_uart_set_thr_irq(tk1_uart_regs_t *regs, bool enable) 120{ 121 uint32_t ier; 122 123 ier = regs->ier_dlab; 124 if (enable) { 125 ier |= IER_THR_EMPTY_ENABLE; 126 } else { 127 ier &= ~IER_THR_EMPTY_ENABLE; 128 } 129 regs->ier_dlab = ier; 130} 131 132static inline void 133tk1_uart_set_rbr_irq(tk1_uart_regs_t *regs, bool enable) 134{ 135 uint32_t ier; 136 137 ier = regs->ier_dlab; 138 if (enable) { 139 ier |= IER_RHR_ENABLE; 140 ier |= IER_RX_FIFO_TIMEDOUT; 141 } else { 142 ier &= ~IER_RHR_ENABLE; 143 ier &= ~IER_RX_FIFO_TIMEDOUT; 144 } 145 regs->ier_dlab = ier; 146} 147 148int uart_getchar(ps_chardevice_t *d) 149{ 150 tk1_uart_regs_t* regs = tk1_uart_get_priv(d); 151 uint32_t reg = 0; 152 int c = -1; 153 154 if (regs->lsr & LSR_RDR_READY) { 155 reg = regs->thr_dlab; 156 c = reg & UART_BYTE_MASK; 157 } 158 return c; 159} 160 161int uart_putchar(ps_chardevice_t* d, int c) 162{ 163 tk1_uart_regs_t* regs = tk1_uart_get_priv(d); 164 uint32_t lsr = regs->lsr; 165 166 if (((lsr & LSR_THRE_EMPTY) == LSR_THRE_EMPTY)) { 167 if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) { 168 uart_putchar(d, '\r'); 169 } 170 171 regs->thr_dlab = (uint8_t) c; 172 173 return c; 174 } else { 175 return -1; 176 } 177} 178 179static void 180tk1_uart_invoke_callback(ps_chardevice_t *d, enum chardev_status stat, 181 size_t n_bytes_xferred, 182 bool invoke_read, bool invoke_write) 183{ 184 tk1_uart_regs_t *regs = tk1_uart_get_priv(d); 185 186 if (!invoke_read && !invoke_write) { 187 ZF_LOGW("invoke_cb called with no indication of what should be done."); 188 return; 189 } 190 191 if (invoke_read) { 192 if (d->read_descriptor.callback != NULL 193 && d->read_descriptor.bytes_requested > 0) { 194 d->read_descriptor.callback(d, stat, 195 n_bytes_xferred, 196 d->read_descriptor.token); 197 198 /* If the client set bytes_requested to 0 inside of the callback, 199 * that is a signal to us that we should close any asynchronous 200 * reading from the line. 201 */ 202 if (d->read_descriptor.bytes_requested == 0) { 203 tk1_uart_set_rbr_irq(regs, false); 204 } 205 } 206 } 207 if (invoke_write) { 208 if (d->write_descriptor.callback != NULL 209 && d->write_descriptor.bytes_requested > 0) { 210 d->write_descriptor.callback(d, stat, 211 n_bytes_xferred, 212 d->write_descriptor.token); 213 214 /* If the client set bytes_requested to 0 inside of the callback, 215 * that is a signal to us that we should consider the async write 216 * to be closed. 217 */ 218 if (d->write_descriptor.bytes_requested == 0) { 219 tk1_uart_set_thr_irq(regs, false); 220 } 221 } 222 } 223} 224 225static void 226uart_handle_irq(ps_chardevice_t* d) 227{ 228 tk1_uart_regs_t *regs = tk1_uart_get_priv(d); 229 uintptr_t irq_ident_val; 230 231 /* Determine the cause of the IRQ. */ 232 irq_ident_val = regs->iir_fcr; 233 irq_ident_val &= IIR_INT_SOURCE_MASK; 234 235 switch (irq_ident_val) { 236 case IIR_INT_SOURCE_NO_INTERRUPT: 237 break; 238 case IIR_INT_SOURCE_DATA_ERROR: 239 240 ZF_LOGE("Parity, overrun, or framing error."); 241 if (d->read_descriptor.data != NULL) { 242 tk1_uart_invoke_callback(d, CHARDEV_STAT_ERROR, 0, true, false); 243 } 244 break; 245 246 case IIR_INT_SOURCE_RECEIVED_DATA_TIMEOUT: 247 case IIR_INT_SOURCE_EO_RECEIVED_DATA: 248 case IIR_INT_SOURCE_RECEIVED_DATA_AVAILABLE: { 249 uint8_t *client_buff; 250 int c; 251 252 struct chardev_xmit_descriptor *rd = &d->read_descriptor; 253 254 if (irq_ident_val == IIR_INT_SOURCE_EO_RECEIVED_DATA) { 255 256 /* Tegra K1 Mobile Processor TRM, section 23.4.2: 257 * 258 * "EORD (End of Receive Data) Interrupt occurs when the receiver 259 * detects that data stops coming in for more than 4 character 260 * times. This interrupt is useful for determining that the sending 261 * device has completed sending all its data. EORD timeout will not 262 * occur if the receiving data stream is stopped because of hardware 263 * handshaking." 264 * 265 * "To clear the EORD timeout interrupt you must DISABLE the EORD 266 * interrupt enable (IE_EORD)." 267 * 268 * But I assume I have to re-enable it too, because otherwise I 269 * won't get them anymore. 270 */ 271 ZF_LOGV("Int reason EO received data."); 272 regs->ier_dlab &= ~IER_EO_RECEIVE_DATA; 273 regs->ier_dlab |= IER_EO_RECEIVE_DATA; 274 } 275 276 if (rd->data == NULL || rd->bytes_requested == 0) { 277 /* Even if there is no rx buffer, or no bytes have been requested, 278 * or some other unusual case has been triggered, we should read the 279 * RBR register and consume the bytes in it. 280 */ 281 ZF_LOGW("Draining."); 282 while (uart_getchar(d) != -1) { 283 /* Just read the bytes out to clear the FIFO */ 284 } 285 break; 286 } 287 288 /* So everytime a new RX data IRQ comes in, the buffer cursor gets 289 * reset to the beginning of the client-supplied buffer. 290 * 291 * Therefore the client should try to service IRQs as quickly as possible. 292 */ 293 294 client_buff = rd->data; 295 296 c = uart_getchar(d); 297 while (c != -1) { 298 /* Don't overrun the client-supplied buffer */ 299 if (rd->bytes_transfered >= rd->bytes_requested) { 300 ZF_LOGV("Buffer of %dB will be overrun.", rd->bytes_requested); 301 302 tk1_uart_invoke_callback(d, CHARDEV_STAT_INCOMPLETE, 303 rd->bytes_transfered, 304 true, false); 305 306 /* We use bytes_requested as a flag to indicate to the this IRQ 307 * handler that it shouldn't call the callback again. 308 * If bytes_requested is 0, we won't get here, so this callback 309 * won't be called repeatedly if there's more data than the 310 * caller's buffer can hold. 311 */ 312 rd->bytes_requested = 0; 313 break; 314 } 315 316 client_buff[rd->bytes_transfered] = (char)c; 317 rd->bytes_transfered++; 318 c = uart_getchar(d); 319 } 320 321 /* If the loop exits early because the buffer was overrun, "c" will 322 * not be -1, because the UART would have returned a character. We 323 * just didn't have any buffer memory remaining. 324 * 325 * I.e, c will be -1 if the loop exited normally. 326 */ 327 if (c == -1 && rd->bytes_transfered > 0) { 328 tk1_uart_invoke_callback(d, CHARDEV_STAT_COMPLETE, 329 rd->bytes_transfered, 330 true, false); 331 } 332 333 break; 334 } 335 336 case IIR_INT_SOURCE_THR_TXRDY: 337 ZF_LOGV("Int reason THR ready: %d of %d bytes transferred.", 338 d->write_descriptor.bytes_transfered, 339 d->write_descriptor.bytes_requested); 340 341 if (d->write_descriptor.data != NULL) { 342 struct chardev_xmit_descriptor *wd = &d->write_descriptor; 343 uint8_t *client_data; 344 int status; 345 346 client_data = wd->data; 347 while (wd->bytes_transfered < wd->bytes_requested) { 348 status = uart_putchar(d, client_data[wd->bytes_transfered]); 349 if (status == -1) { 350 ZF_LOGV("One DMA pass finished: written %d of %dB!", 351 wd->bytes_transfered, wd->bytes_requested); 352 break; 353 } 354 355 wd->bytes_transfered++; 356 } 357 358 if (wd->bytes_transfered >= wd->bytes_requested) { 359 /* Disable the THR_EMPTY IRQ until a new write request is made. */ 360 tk1_uart_set_thr_irq(regs, false); 361 362 tk1_uart_invoke_callback(d, CHARDEV_STAT_COMPLETE, 363 wd->bytes_transfered, 364 false, true); 365 } 366 } else { 367 /* If there's no input data buffer to read from, disable the 368 * THR_EMPTY IRQ, because it was triggered, for one reason or 369 * another. 370 */ 371 tk1_uart_set_thr_irq(regs, false); 372 } 373 break; 374 375 case IIR_INT_SOURCE_MODEM_STATUS: 376 ZF_LOGV("Modem status changed."); 377 break; 378 default: 379 ZF_LOGW("Unknown interrupt reason %d.", irq_ident_val); 380 }; 381} 382 383static ssize_t 384tk1_uart_write(ps_chardevice_t* d, const void* vdata, 385 size_t count, chardev_callback_t rcb, 386 void* token) 387{ 388 struct chardev_xmit_descriptor wd = { 389 .callback = rcb, 390 .token = token, 391 .bytes_transfered = 0, 392 .bytes_requested = count, 393 .data = (void *)vdata 394 }; 395 396 d->write_descriptor = wd; 397 398 if (count == 0) { 399 /* Call the callback immediately */ 400 if (rcb != NULL) { 401 rcb(d, CHARDEV_STAT_COMPLETE, count, token); 402 } 403 return 0; 404 } 405 406 if (!tk1_uart_is_async(d)) { 407 /* Write the data out over the line synchronously. */ 408 for (int i = 0; i < count; i++) { 409 while (uart_putchar(d, ((uint8_t *)vdata)[i]) == -1) { 410 } 411 412 d->write_descriptor.bytes_transfered++; 413 } 414 415 if (rcb != NULL) { 416 rcb(d, CHARDEV_STAT_COMPLETE, d->write_descriptor.bytes_transfered, 417 token); 418 } 419 } else { 420 /* Else enable the THRE IRQ and return. */ 421 tk1_uart_set_thr_irq(tk1_uart_get_priv(d), true); 422 THREAD_MEMORY_RELEASE(); 423 } 424 425 return d->write_descriptor.bytes_transfered; 426} 427 428static ssize_t 429tk1_uart_read(ps_chardevice_t* d, void* vdata, 430 size_t count, chardev_callback_t rcb, 431 void* token) 432{ 433 if (count < 1) { 434 count = 0; 435 } 436 437 struct chardev_xmit_descriptor rd = { 438 .callback = rcb, 439 .token = token, 440 .bytes_transfered = 0, 441 .bytes_requested = count, 442 .data = vdata 443 }; 444 445 d->read_descriptor = rd; 446 447 if (count == 0 && rcb != NULL) { 448 ZF_LOGV("read call with 0 count."); 449 rcb(d, CHARDEV_STAT_COMPLETE, count, token); 450 } 451 452 if (!tk1_uart_is_async(d)) { 453 int n_chars_read = 0; 454 int c; 455 456 while ((c = uart_getchar(d)) == -1) { 457 /* Ideally we should use a cpu_relax() type of opcode here. */ 458 } 459 460 /* Read the data synchronously. */ 461 while (c != -1) { 462 ((uint8_t *)vdata)[n_chars_read] = c; 463 464 c = uart_getchar(d); 465 n_chars_read++; 466 } 467 468 d->read_descriptor.bytes_transfered = n_chars_read; 469 470 if (rcb != NULL) { 471 rcb(d, CHARDEV_STAT_COMPLETE, d->read_descriptor.bytes_transfered, 472 token); 473 } 474 } 475 476 return d->read_descriptor.bytes_transfered; 477} 478 479/** Used for debugging. Concats the dlab hi and lo bytes into a 16-bit int. 480 * @param d Pointer to the device whose divisor you want to get. 481 * @return 16-bit divisor. 482 */ 483UNUSED static uint16_t 484tk1_uart_get_dlab_divisor(ps_chardevice_t *d) 485{ 486 uint16_t ret=0; 487 tk1_uart_regs_t* regs = tk1_uart_get_priv(d); 488 489 regs->lcr |= LCR_DLAB; 490 THREAD_MEMORY_RELEASE(); 491 ret = regs->thr_dlab & 0xFF; 492 ret |= (regs->ier_dlab & 0xFF) << 8; 493 THREAD_MEMORY_RELEASE(); 494 regs->lcr &= ~LCR_DLAB; 495 496 return ret; 497} 498 499static void 500tk1_uart_set_dlab_divisor(ps_chardevice_t *d, uint16_t divisor) 501{ 502 tk1_uart_regs_t* regs = tk1_uart_get_priv(d); 503 504 regs->lcr |= LCR_DLAB; 505 THREAD_MEMORY_RELEASE(); 506 regs->thr_dlab = divisor & 0xFF; 507 regs->ier_dlab = (divisor >> 8) & 0xFF; 508 THREAD_MEMORY_RELEASE(); 509 regs->lcr &= ~LCR_DLAB; 510} 511 512static int 513tk1_uart_get_divisor_for(int baud) 514{ 515 int ret; 516 517 switch (baud) { 518 case 115200: 519 case 57600: 520 case 38400: 521 case 19200: 522 case 9600: 523 case 4800: 524 case 2400: 525 case 1200: 526 case 300: 527 /* Do nothing; This switch is for input validation. */ 528 break; 529 default: 530 ZF_LOGE("TK1-uart: Unsupported baud rate %d.", 531 baud); 532 return -1; 533 } 534 535 /* Both we an u-boot program the UARTs to use PllP_out as their input clock, 536 * which is fixed at 408MHz: 537 * 538 * TegraK1 TRM, Section 5.22, Table 14: 539 * "pllP_out: This is the PLLP���s output clock which is set to 408 MHz." 540 * 541 * This 408MHz output, is then channeled into the UART-controllers after 542 * being passed through a divider. The divider's default divisor is 17 543 * on hardware #RESET, but u-boot sets the divider's divisor to 0, and so 544 * the UART controller gets the full 408 MHz as its input. 545 * 546 * From there, we just calculate a divisor to put into the UART controller's 547 * DLAB (divisor latch) registers, based on the caller's requested baud 548 * rate, according to the formula: 549 * Divisor = input_clock_freq / (16 * desired_baud) 550 * 551 * The number "16" comes from the fact that the UART controller takes 16 552 * clock phases to generate one bit of output on the line (TK1 TRM, section 553 * 34.1.1.) 554 */ 555 ret = (NV_UART_INPUT_CLOCK_FREQ_HZ / 16) / baud; 556 return ret; 557} 558 559int 560serial_configure(ps_chardevice_t* d, long bps, int char_size, enum serial_parity parity, int stop_bits) 561{ 562 tk1_uart_regs_t* regs = tk1_uart_get_priv(d); 563 int divisor; 564 /* line control register */ 565 uint32_t lcr = 0; 566 567 /* Disable the receive IRQ while changing line configuration. */ 568 tk1_uart_set_rbr_irq(regs, false); 569 THREAD_MEMORY_RELEASE(); 570 571 switch (char_size) { 572 case 5: 573 lcr |= LCR_WD_SIZE_5; 574 break; 575 case 6: 576 lcr |= LCR_WD_SIZE_6; 577 break; 578 case 7: 579 lcr |= LCR_WD_SIZE_7; 580 break; 581 case 8: 582 lcr |= LCR_WD_SIZE_8; 583 break; 584 default: 585 return -1; 586 } 587 588 switch (parity) { 589 case PARITY_NONE: 590 break; 591 case PARITY_EVEN: 592 lcr |= LCR_EVEN | LCR_PAR; 593 break; 594 case PARITY_ODD: 595 lcr |= LCR_PAR; 596 break; 597/* 598 * Uncomment if we ever need fixed values for parity bits 599 * 600 case PARITY_ONE: 601 lcr |= LCR_SET_PARITY | LCR_EVEN; 602 break; 603 case PARITY_ZERO: 604 lcr |= LCR_SET_PARITY; 605 break 606*/ 607 default: 608 return -1; 609 } 610 611 /* one stop bit */ 612 regs->lcr = lcr; 613 614 divisor = tk1_uart_get_divisor_for(bps); 615 if (divisor < 1) { 616 /* Unsupported baud rate. */ 617 return -1; 618 } 619 620 tk1_uart_set_dlab_divisor(d, divisor); 621 622 /* Disable hardware flow control for all UARTs other than UARTD, 623 * because UARTD actually has an RS232 pinout port. 624 */ 625 if (d->id != NV_UARTD && d->id != NV_UARTD_ASYNC) { 626 uint32_t mcr = regs->mcr; 627 628 /* Clear RTS_EN and CTS_EN. */ 629 mcr &= ~(BIT(6) | BIT(5)); 630 /* Force RTS and DTR to low (active) */ 631 mcr |= (BIT(1) | BIT(0)); 632 regs->mcr = mcr; 633 } 634 635 /* Drain the RX buffer when configuring a new set of line options. 636 * By implication, the caller should wait for previous transmissions to be 637 * completed before reconfiguring. 638 */ 639 while (uart_getchar(d) != -1) { 640 } 641 642 if (tk1_uart_is_async(d)) { 643 /* Re-enable receive IRQ. */ 644 tk1_uart_set_rbr_irq(regs, true); 645 } 646 647 return 0; 648} 649 650/** Initialize a ps_chardevice_t instance. 651 * 652 * Expects an already valid mapping to the TK1 UART MMIO vaddr range. 653 */ 654int 655tk1_uart_init_common(const struct dev_defn *defn, void *const uart_mmio_vaddr, 656 ps_chardevice_t *dev) 657{ 658 volatile void *uart_vaddr = 0; 659 tk1_uart_regs_t* regs; 660 uint32_t iir_fcr; 661 struct chardev_xmit_descriptor cxd_zero = {0}; 662 ps_io_ops_t ioops_zero = {{0}}; 663 664 /* add offsets properly */ 665 switch (defn->id) { 666 case NV_UARTA: 667 case NV_UARTA_ASYNC: 668 uart_vaddr = uart_mmio_vaddr; 669 break; 670 case NV_UARTB: 671 case NV_UARTB_ASYNC: 672 uart_vaddr = uart_mmio_vaddr + UARTB_OFFSET; 673 break; 674 case NV_UARTC: 675 case NV_UARTC_ASYNC: 676 uart_vaddr = uart_mmio_vaddr + UARTC_OFFSET; 677 break; 678 case NV_UARTD: 679 case NV_UARTD_ASYNC: 680 uart_vaddr = uart_mmio_vaddr + UARTD_OFFSET; 681 /* The kernel uses UART-D. Recommend not conflicting with it. */ 682 break; 683 default: 684 return -1; 685 } 686 687 memset(dev, 0, sizeof(*dev)); 688 689 /* Set up all the device properties. */ 690 dev->id = defn->id; 691 dev->vaddr = (void*)uart_vaddr; 692 dev->read = &tk1_uart_read; 693 dev->write = &tk1_uart_write; 694 dev->handle_irq = &uart_handle_irq; 695 dev->irqs = defn->irqs; 696 dev->ioops = ioops_zero; 697 dev->flags = SERIAL_AUTO_CR; 698 699 /* Zero out the client state. */ 700 dev->write_descriptor = cxd_zero; 701 dev->read_descriptor = cxd_zero; 702 703 regs = tk1_uart_get_priv(dev); 704 705 /* Disable IRQs. */ 706 tk1_uart_set_rbr_irq(regs, false); 707 tk1_uart_set_thr_irq(regs, false); 708 709 /* Line configuration */ 710 serial_configure(dev, 115200, 8, PARITY_NONE, 1); 711 712 /* Set FCR[0] to 1 to enable FIFO mode, and enable DMA mode 1 which will 713 * generate an interrupt only when the buffer has. 714 * 715 * There's no point in doing an R-M-W sequence because reading the FCR 716 * actually returns the values from the IIR, so you can't actually read FCR. 717 */ 718 iir_fcr = 0 719 | FCR_FIFO_ENABLE | FCR_DMA_MODE0 720 | ENCODE_BITS(0, FCR_RX_TRIG_SHIFT, FCR_RX_TRIG_MASK, FCR_RX_TRIG_FIFO_GT_16) 721 | ENCODE_BITS(0, FCR_TX_TRIG_SHIFT, FCR_TX_TRIG_MASK, FCR_TX_TRIG_FIFO_GT_16) 722 | BIT(FCR_TX_FIFO_CLEAR_SHIFT) 723 | BIT(FCR_RX_FIFO_CLEAR_SHIFT); 724 725 regs->iir_fcr = iir_fcr; 726 727 /* Read the status bit to ensure the FIFO was enabled. */ 728 iir_fcr = regs->iir_fcr; 729 if (EXTRACT_BITS(iir_fcr, 730 IIR_FIFO_MODE_STATUS_SHIFT, 731 IIR_FIFO_MODE_STATUS_MASK) != 3) { 732 ZF_LOGE("FIFO mode wasn't enabled.\n"); 733 return -1; 734 } 735 736 return 0; 737} 738 739/** Initializes a ps_chardevice_t. 740 * 741 * Expects a viable ps_io_ops_t for mapping the registers. 742 */ 743int 744uart_init(const struct dev_defn* defn, 745 const ps_io_ops_t* ops, 746 ps_chardevice_t* dev) 747{ 748 static void *vaddr = 0; 749 int ret; 750 751 /* Attempt to map the virtual address, assure this works */ 752 if (vaddr == 0) { 753 vaddr = chardev_map(defn, ops); 754 755 if (vaddr == NULL) { 756 return -1; 757 } 758 } 759 760 ret = tk1_uart_init_common(defn, vaddr, dev); 761 dev->ioops = *ops; 762 return ret; 763} 764