diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/68360serial.c | 6 | ||||
-rw-r--r-- | drivers/serial/amba-pl010.c | 2 | ||||
-rw-r--r-- | drivers/serial/amba-pl011.c | 90 | ||||
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_core.c | 2 | ||||
-rw-r--r-- | drivers/serial/nwpserial.c | 2 | ||||
-rw-r--r-- | drivers/serial/sn_console.c | 6 |
6 files changed, 85 insertions, 23 deletions
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 24661cd5e4fb..768612f8e41e 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c | |||
@@ -2649,7 +2649,7 @@ static int __init rs_360_init(void) | |||
2649 | sup->tfcr = SMC_EB; | 2649 | sup->tfcr = SMC_EB; |
2650 | 2650 | ||
2651 | /* Set this to 1 for now, so we get single | 2651 | /* Set this to 1 for now, so we get single |
2652 | * character interrupts. Using idle charater | 2652 | * character interrupts. Using idle character |
2653 | * time requires some additional tuning. | 2653 | * time requires some additional tuning. |
2654 | */ | 2654 | */ |
2655 | sup->mrblr = 1; | 2655 | sup->mrblr = 1; |
@@ -2728,7 +2728,7 @@ static int __init rs_360_init(void) | |||
2728 | up->tfcr = SMC_EB; | 2728 | up->tfcr = SMC_EB; |
2729 | 2729 | ||
2730 | /* Set this to 1 for now, so we get single | 2730 | /* Set this to 1 for now, so we get single |
2731 | * character interrupts. Using idle charater | 2731 | * character interrupts. Using idle character |
2732 | * time requires some additional tuning. | 2732 | * time requires some additional tuning. |
2733 | */ | 2733 | */ |
2734 | up->mrblr = 1; | 2734 | up->mrblr = 1; |
@@ -2886,7 +2886,7 @@ int serial_console_setup( struct console *co, char *options) | |||
2886 | sup->tfcr = SMC_EB; | 2886 | sup->tfcr = SMC_EB; |
2887 | 2887 | ||
2888 | /* Set this to 1 for now, so we get single | 2888 | /* Set this to 1 for now, so we get single |
2889 | * character interrupts. Using idle charater | 2889 | * character interrupts. Using idle character |
2890 | * time requires some additional tuning. | 2890 | * time requires some additional tuning. |
2891 | */ | 2891 | */ |
2892 | sup->mrblr = 1; | 2892 | sup->mrblr = 1; |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index b09a638d051f..50441ffe8e38 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -782,7 +782,7 @@ static int pl010_resume(struct amba_device *dev) | |||
782 | return 0; | 782 | return 0; |
783 | } | 783 | } |
784 | 784 | ||
785 | static struct amba_id pl010_ids[] __initdata = { | 785 | static struct amba_id pl010_ids[] = { |
786 | { | 786 | { |
787 | .id = 0x00041010, | 787 | .id = 0x00041010, |
788 | .mask = 0x000fffff, | 788 | .mask = 0x000fffff, |
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index eb4cb480b93e..6ca7a44f29c2 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c | |||
@@ -69,9 +69,12 @@ | |||
69 | struct uart_amba_port { | 69 | struct uart_amba_port { |
70 | struct uart_port port; | 70 | struct uart_port port; |
71 | struct clk *clk; | 71 | struct clk *clk; |
72 | unsigned int im; /* interrupt mask */ | 72 | unsigned int im; /* interrupt mask */ |
73 | unsigned int old_status; | 73 | unsigned int old_status; |
74 | unsigned int ifls; /* vendor-specific */ | 74 | unsigned int ifls; /* vendor-specific */ |
75 | unsigned int lcrh_tx; /* vendor-specific */ | ||
76 | unsigned int lcrh_rx; /* vendor-specific */ | ||
77 | bool oversampling; /* vendor-specific */ | ||
75 | bool autorts; | 78 | bool autorts; |
76 | }; | 79 | }; |
77 | 80 | ||
@@ -79,16 +82,25 @@ struct uart_amba_port { | |||
79 | struct vendor_data { | 82 | struct vendor_data { |
80 | unsigned int ifls; | 83 | unsigned int ifls; |
81 | unsigned int fifosize; | 84 | unsigned int fifosize; |
85 | unsigned int lcrh_tx; | ||
86 | unsigned int lcrh_rx; | ||
87 | bool oversampling; | ||
82 | }; | 88 | }; |
83 | 89 | ||
84 | static struct vendor_data vendor_arm = { | 90 | static struct vendor_data vendor_arm = { |
85 | .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, | 91 | .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, |
86 | .fifosize = 16, | 92 | .fifosize = 16, |
93 | .lcrh_tx = UART011_LCRH, | ||
94 | .lcrh_rx = UART011_LCRH, | ||
95 | .oversampling = false, | ||
87 | }; | 96 | }; |
88 | 97 | ||
89 | static struct vendor_data vendor_st = { | 98 | static struct vendor_data vendor_st = { |
90 | .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, | 99 | .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, |
91 | .fifosize = 64, | 100 | .fifosize = 64, |
101 | .lcrh_tx = ST_UART011_LCRH_TX, | ||
102 | .lcrh_rx = ST_UART011_LCRH_RX, | ||
103 | .oversampling = true, | ||
92 | }; | 104 | }; |
93 | 105 | ||
94 | static void pl011_stop_tx(struct uart_port *port) | 106 | static void pl011_stop_tx(struct uart_port *port) |
@@ -327,12 +339,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) | |||
327 | unsigned int lcr_h; | 339 | unsigned int lcr_h; |
328 | 340 | ||
329 | spin_lock_irqsave(&uap->port.lock, flags); | 341 | spin_lock_irqsave(&uap->port.lock, flags); |
330 | lcr_h = readw(uap->port.membase + UART011_LCRH); | 342 | lcr_h = readw(uap->port.membase + uap->lcrh_tx); |
331 | if (break_state == -1) | 343 | if (break_state == -1) |
332 | lcr_h |= UART01x_LCRH_BRK; | 344 | lcr_h |= UART01x_LCRH_BRK; |
333 | else | 345 | else |
334 | lcr_h &= ~UART01x_LCRH_BRK; | 346 | lcr_h &= ~UART01x_LCRH_BRK; |
335 | writew(lcr_h, uap->port.membase + UART011_LCRH); | 347 | writew(lcr_h, uap->port.membase + uap->lcrh_tx); |
336 | spin_unlock_irqrestore(&uap->port.lock, flags); | 348 | spin_unlock_irqrestore(&uap->port.lock, flags); |
337 | } | 349 | } |
338 | 350 | ||
@@ -393,7 +405,17 @@ static int pl011_startup(struct uart_port *port) | |||
393 | writew(cr, uap->port.membase + UART011_CR); | 405 | writew(cr, uap->port.membase + UART011_CR); |
394 | writew(0, uap->port.membase + UART011_FBRD); | 406 | writew(0, uap->port.membase + UART011_FBRD); |
395 | writew(1, uap->port.membase + UART011_IBRD); | 407 | writew(1, uap->port.membase + UART011_IBRD); |
396 | writew(0, uap->port.membase + UART011_LCRH); | 408 | writew(0, uap->port.membase + uap->lcrh_rx); |
409 | if (uap->lcrh_tx != uap->lcrh_rx) { | ||
410 | int i; | ||
411 | /* | ||
412 | * Wait 10 PCLKs before writing LCRH_TX register, | ||
413 | * to get this delay write read only register 10 times | ||
414 | */ | ||
415 | for (i = 0; i < 10; ++i) | ||
416 | writew(0xff, uap->port.membase + UART011_MIS); | ||
417 | writew(0, uap->port.membase + uap->lcrh_tx); | ||
418 | } | ||
397 | writew(0, uap->port.membase + UART01x_DR); | 419 | writew(0, uap->port.membase + UART01x_DR); |
398 | while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) | 420 | while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) |
399 | barrier(); | 421 | barrier(); |
@@ -422,10 +444,19 @@ static int pl011_startup(struct uart_port *port) | |||
422 | return retval; | 444 | return retval; |
423 | } | 445 | } |
424 | 446 | ||
447 | static void pl011_shutdown_channel(struct uart_amba_port *uap, | ||
448 | unsigned int lcrh) | ||
449 | { | ||
450 | unsigned long val; | ||
451 | |||
452 | val = readw(uap->port.membase + lcrh); | ||
453 | val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); | ||
454 | writew(val, uap->port.membase + lcrh); | ||
455 | } | ||
456 | |||
425 | static void pl011_shutdown(struct uart_port *port) | 457 | static void pl011_shutdown(struct uart_port *port) |
426 | { | 458 | { |
427 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 459 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
428 | unsigned long val; | ||
429 | 460 | ||
430 | /* | 461 | /* |
431 | * disable all interrupts | 462 | * disable all interrupts |
@@ -450,9 +481,9 @@ static void pl011_shutdown(struct uart_port *port) | |||
450 | /* | 481 | /* |
451 | * disable break condition and fifos | 482 | * disable break condition and fifos |
452 | */ | 483 | */ |
453 | val = readw(uap->port.membase + UART011_LCRH); | 484 | pl011_shutdown_channel(uap, uap->lcrh_rx); |
454 | val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN); | 485 | if (uap->lcrh_rx != uap->lcrh_tx) |
455 | writew(val, uap->port.membase + UART011_LCRH); | 486 | pl011_shutdown_channel(uap, uap->lcrh_tx); |
456 | 487 | ||
457 | /* | 488 | /* |
458 | * Shut down the clock producer | 489 | * Shut down the clock producer |
@@ -472,8 +503,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, | |||
472 | /* | 503 | /* |
473 | * Ask the core to calculate the divisor for us. | 504 | * Ask the core to calculate the divisor for us. |
474 | */ | 505 | */ |
475 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | 506 | baud = uart_get_baud_rate(port, termios, old, 0, |
476 | quot = port->uartclk * 4 / baud; | 507 | port->uartclk/(uap->oversampling ? 8 : 16)); |
508 | |||
509 | if (baud > port->uartclk/16) | ||
510 | quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); | ||
511 | else | ||
512 | quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud); | ||
477 | 513 | ||
478 | switch (termios->c_cflag & CSIZE) { | 514 | switch (termios->c_cflag & CSIZE) { |
479 | case CS5: | 515 | case CS5: |
@@ -552,6 +588,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, | |||
552 | uap->autorts = false; | 588 | uap->autorts = false; |
553 | } | 589 | } |
554 | 590 | ||
591 | if (uap->oversampling) { | ||
592 | if (baud > port->uartclk/16) | ||
593 | old_cr |= ST_UART011_CR_OVSFACT; | ||
594 | else | ||
595 | old_cr &= ~ST_UART011_CR_OVSFACT; | ||
596 | } | ||
597 | |||
555 | /* Set baud rate */ | 598 | /* Set baud rate */ |
556 | writew(quot & 0x3f, port->membase + UART011_FBRD); | 599 | writew(quot & 0x3f, port->membase + UART011_FBRD); |
557 | writew(quot >> 6, port->membase + UART011_IBRD); | 600 | writew(quot >> 6, port->membase + UART011_IBRD); |
@@ -561,7 +604,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, | |||
561 | * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L | 604 | * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L |
562 | * ----------^----------^----------^----------^----- | 605 | * ----------^----------^----------^----------^----- |
563 | */ | 606 | */ |
564 | writew(lcr_h, port->membase + UART011_LCRH); | 607 | writew(lcr_h, port->membase + uap->lcrh_rx); |
608 | if (uap->lcrh_rx != uap->lcrh_tx) { | ||
609 | int i; | ||
610 | /* | ||
611 | * Wait 10 PCLKs before writing LCRH_TX register, | ||
612 | * to get this delay write read only register 10 times | ||
613 | */ | ||
614 | for (i = 0; i < 10; ++i) | ||
615 | writew(0xff, uap->port.membase + UART011_MIS); | ||
616 | writew(lcr_h, port->membase + uap->lcrh_tx); | ||
617 | } | ||
565 | writew(old_cr, port->membase + UART011_CR); | 618 | writew(old_cr, port->membase + UART011_CR); |
566 | 619 | ||
567 | spin_unlock_irqrestore(&port->lock, flags); | 620 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -688,7 +741,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, | |||
688 | if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) { | 741 | if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) { |
689 | unsigned int lcr_h, ibrd, fbrd; | 742 | unsigned int lcr_h, ibrd, fbrd; |
690 | 743 | ||
691 | lcr_h = readw(uap->port.membase + UART011_LCRH); | 744 | lcr_h = readw(uap->port.membase + uap->lcrh_tx); |
692 | 745 | ||
693 | *parity = 'n'; | 746 | *parity = 'n'; |
694 | if (lcr_h & UART01x_LCRH_PEN) { | 747 | if (lcr_h & UART01x_LCRH_PEN) { |
@@ -707,6 +760,12 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, | |||
707 | fbrd = readw(uap->port.membase + UART011_FBRD); | 760 | fbrd = readw(uap->port.membase + UART011_FBRD); |
708 | 761 | ||
709 | *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); | 762 | *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); |
763 | |||
764 | if (uap->oversampling) { | ||
765 | if (readw(uap->port.membase + UART011_CR) | ||
766 | & ST_UART011_CR_OVSFACT) | ||
767 | *baud *= 2; | ||
768 | } | ||
710 | } | 769 | } |
711 | } | 770 | } |
712 | 771 | ||
@@ -800,6 +859,9 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id) | |||
800 | } | 859 | } |
801 | 860 | ||
802 | uap->ifls = vendor->ifls; | 861 | uap->ifls = vendor->ifls; |
862 | uap->lcrh_rx = vendor->lcrh_rx; | ||
863 | uap->lcrh_tx = vendor->lcrh_tx; | ||
864 | uap->oversampling = vendor->oversampling; | ||
803 | uap->port.dev = &dev->dev; | 865 | uap->port.dev = &dev->dev; |
804 | uap->port.mapbase = dev->res.start; | 866 | uap->port.mapbase = dev->res.start; |
805 | uap->port.membase = base; | 867 | uap->port.membase = base; |
@@ -868,7 +930,7 @@ static int pl011_resume(struct amba_device *dev) | |||
868 | } | 930 | } |
869 | #endif | 931 | #endif |
870 | 932 | ||
871 | static struct amba_id pl011_ids[] __initdata = { | 933 | static struct amba_id pl011_ids[] = { |
872 | { | 934 | { |
873 | .id = 0x00041011, | 935 | .id = 0x00041011, |
874 | .mask = 0x000fffff, | 936 | .mask = 0x000fffff, |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index cd6cf575902e..6016179db533 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -852,7 +852,7 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) | |||
852 | */ | 852 | */ |
853 | cpm_set_smc_fcr(up); | 853 | cpm_set_smc_fcr(up); |
854 | 854 | ||
855 | /* Using idle charater time requires some additional tuning. */ | 855 | /* Using idle character time requires some additional tuning. */ |
856 | out_be16(&up->smc_mrblr, pinfo->rx_fifosize); | 856 | out_be16(&up->smc_mrblr, pinfo->rx_fifosize); |
857 | out_be16(&up->smc_maxidl, pinfo->rx_fifosize); | 857 | out_be16(&up->smc_maxidl, pinfo->rx_fifosize); |
858 | out_be16(&up->smc_brklen, 0); | 858 | out_be16(&up->smc_brklen, 0); |
diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c index 3c02fa96f282..e65b0d9202a5 100644 --- a/drivers/serial/nwpserial.c +++ b/drivers/serial/nwpserial.c | |||
@@ -81,7 +81,7 @@ nwpserial_console_write(struct console *co, const char *s, unsigned int count) | |||
81 | 81 | ||
82 | uart_console_write(&up->port, s, count, nwpserial_console_putchar); | 82 | uart_console_write(&up->port, s, count, nwpserial_console_putchar); |
83 | 83 | ||
84 | /* wait for transmitter to become emtpy */ | 84 | /* wait for transmitter to become empty */ |
85 | while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0) | 85 | while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0) |
86 | cpu_relax(); | 86 | cpu_relax(); |
87 | 87 | ||
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 9794e0cd3dcc..7e5e5efea4e2 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c | |||
@@ -470,7 +470,7 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags) | |||
470 | } | 470 | } |
471 | 471 | ||
472 | if (port->sc_port.state) { | 472 | if (port->sc_port.state) { |
473 | /* The serial_core stuffs are initilized, use them */ | 473 | /* The serial_core stuffs are initialized, use them */ |
474 | tty = port->sc_port.state->port.tty; | 474 | tty = port->sc_port.state->port.tty; |
475 | } | 475 | } |
476 | else { | 476 | else { |
@@ -551,11 +551,11 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw) | |||
551 | BUG_ON(!port->sc_is_asynch); | 551 | BUG_ON(!port->sc_is_asynch); |
552 | 552 | ||
553 | if (port->sc_port.state) { | 553 | if (port->sc_port.state) { |
554 | /* We're initilized, using serial core infrastructure */ | 554 | /* We're initialized, using serial core infrastructure */ |
555 | xmit = &port->sc_port.state->xmit; | 555 | xmit = &port->sc_port.state->xmit; |
556 | } else { | 556 | } else { |
557 | /* Probably sn_sal_switch_to_asynch has been run but serial core isn't | 557 | /* Probably sn_sal_switch_to_asynch has been run but serial core isn't |
558 | * initilized yet. Just return. Writes are going through | 558 | * initialized yet. Just return. Writes are going through |
559 | * sn_sal_console_write (due to register_console) at this time. | 559 | * sn_sal_console_write (due to register_console) at this time. |
560 | */ | 560 | */ |
561 | return; | 561 | return; |