diff options
Diffstat (limited to 'drivers/serial/mpc52xx_uart.c')
-rw-r--r-- | drivers/serial/mpc52xx_uart.c | 74 |
1 files changed, 60 insertions, 14 deletions
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 28c00c3d58f5..0c3a2ab1612c 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -429,14 +429,24 @@ mpc52xx_uart_tx_empty(struct uart_port *port) | |||
429 | static void | 429 | static void |
430 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | 430 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
431 | { | 431 | { |
432 | /* Not implemented */ | 432 | if (mctrl & TIOCM_RTS) |
433 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
434 | else | ||
435 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
433 | } | 436 | } |
434 | 437 | ||
435 | static unsigned int | 438 | static unsigned int |
436 | mpc52xx_uart_get_mctrl(struct uart_port *port) | 439 | mpc52xx_uart_get_mctrl(struct uart_port *port) |
437 | { | 440 | { |
438 | /* Not implemented */ | 441 | unsigned int ret = TIOCM_DSR; |
439 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | 442 | u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr); |
443 | |||
444 | if (!(status & MPC52xx_PSC_CTS)) | ||
445 | ret |= TIOCM_CTS; | ||
446 | if (!(status & MPC52xx_PSC_DCD)) | ||
447 | ret |= TIOCM_CAR; | ||
448 | |||
449 | return ret; | ||
440 | } | 450 | } |
441 | 451 | ||
442 | static void | 452 | static void |
@@ -479,7 +489,15 @@ mpc52xx_uart_stop_rx(struct uart_port *port) | |||
479 | static void | 489 | static void |
480 | mpc52xx_uart_enable_ms(struct uart_port *port) | 490 | mpc52xx_uart_enable_ms(struct uart_port *port) |
481 | { | 491 | { |
482 | /* Not implemented */ | 492 | struct mpc52xx_psc __iomem *psc = PSC(port); |
493 | |||
494 | /* clear D_*-bits by reading them */ | ||
495 | in_8(&psc->mpc52xx_psc_ipcr); | ||
496 | /* enable CTS and DCD as IPC interrupts */ | ||
497 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
498 | |||
499 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
500 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
483 | } | 501 | } |
484 | 502 | ||
485 | static void | 503 | static void |
@@ -580,6 +598,10 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
580 | MPC52xx_PSC_MODE_ONE_STOP_5_BITS : | 598 | MPC52xx_PSC_MODE_ONE_STOP_5_BITS : |
581 | MPC52xx_PSC_MODE_ONE_STOP; | 599 | MPC52xx_PSC_MODE_ONE_STOP; |
582 | 600 | ||
601 | if (new->c_cflag & CRTSCTS) { | ||
602 | mr1 |= MPC52xx_PSC_MODE_RXRTS; | ||
603 | mr2 |= MPC52xx_PSC_MODE_TXCTS; | ||
604 | } | ||
583 | 605 | ||
584 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); | 606 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); |
585 | quot = uart_get_divisor(port, baud); | 607 | quot = uart_get_divisor(port, baud); |
@@ -617,6 +639,9 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
617 | out_8(&psc->ctur, ctr >> 8); | 639 | out_8(&psc->ctur, ctr >> 8); |
618 | out_8(&psc->ctlr, ctr & 0xff); | 640 | out_8(&psc->ctlr, ctr & 0xff); |
619 | 641 | ||
642 | if (UART_ENABLE_MS(port, new->c_cflag)) | ||
643 | mpc52xx_uart_enable_ms(port); | ||
644 | |||
620 | /* Reenable TX & RX */ | 645 | /* Reenable TX & RX */ |
621 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 646 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); |
622 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 647 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); |
@@ -752,10 +777,15 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
752 | if (status & MPC52xx_PSC_SR_RB) { | 777 | if (status & MPC52xx_PSC_SR_RB) { |
753 | flag = TTY_BREAK; | 778 | flag = TTY_BREAK; |
754 | uart_handle_break(port); | 779 | uart_handle_break(port); |
755 | } else if (status & MPC52xx_PSC_SR_PE) | 780 | port->icount.brk++; |
781 | } else if (status & MPC52xx_PSC_SR_PE) { | ||
756 | flag = TTY_PARITY; | 782 | flag = TTY_PARITY; |
757 | else if (status & MPC52xx_PSC_SR_FE) | 783 | port->icount.parity++; |
784 | } | ||
785 | else if (status & MPC52xx_PSC_SR_FE) { | ||
758 | flag = TTY_FRAME; | 786 | flag = TTY_FRAME; |
787 | port->icount.frame++; | ||
788 | } | ||
759 | 789 | ||
760 | /* Clear error condition */ | 790 | /* Clear error condition */ |
761 | out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT); | 791 | out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT); |
@@ -769,6 +799,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
769 | * affect the current character | 799 | * affect the current character |
770 | */ | 800 | */ |
771 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 801 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
802 | port->icount.overrun++; | ||
772 | } | 803 | } |
773 | } | 804 | } |
774 | 805 | ||
@@ -826,6 +857,7 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
826 | struct uart_port *port = dev_id; | 857 | struct uart_port *port = dev_id; |
827 | unsigned long pass = ISR_PASS_LIMIT; | 858 | unsigned long pass = ISR_PASS_LIMIT; |
828 | unsigned int keepgoing; | 859 | unsigned int keepgoing; |
860 | u8 status; | ||
829 | 861 | ||
830 | spin_lock(&port->lock); | 862 | spin_lock(&port->lock); |
831 | 863 | ||
@@ -842,6 +874,13 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
842 | if (psc_ops->tx_rdy(port)) | 874 | if (psc_ops->tx_rdy(port)) |
843 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 875 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
844 | 876 | ||
877 | status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | ||
878 | if (status & MPC52xx_PSC_D_DCD) | ||
879 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); | ||
880 | |||
881 | if (status & MPC52xx_PSC_D_CTS) | ||
882 | uart_handle_cts_change(port, !(status & MPC52xx_PSC_CTS)); | ||
883 | |||
845 | /* Limit number of iteration */ | 884 | /* Limit number of iteration */ |
846 | if (!(--pass)) | 885 | if (!(--pass)) |
847 | keepgoing = 0; | 886 | keepgoing = 0; |
@@ -1109,22 +1148,29 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
1109 | return ret; | 1148 | return ret; |
1110 | 1149 | ||
1111 | port->mapbase = res.start; | 1150 | port->mapbase = res.start; |
1151 | if (!port->mapbase) { | ||
1152 | dev_dbg(&op->dev, "Could not allocate resources for PSC\n"); | ||
1153 | return -EINVAL; | ||
1154 | } | ||
1155 | |||
1112 | port->irq = irq_of_parse_and_map(op->node, 0); | 1156 | port->irq = irq_of_parse_and_map(op->node, 0); |
1157 | if (port->irq == NO_IRQ) { | ||
1158 | dev_dbg(&op->dev, "Could not get irq\n"); | ||
1159 | return -EINVAL; | ||
1160 | } | ||
1113 | 1161 | ||
1114 | dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n", | 1162 | dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n", |
1115 | (void *)port->mapbase, port->irq, port->uartclk); | 1163 | (void *)port->mapbase, port->irq, port->uartclk); |
1116 | 1164 | ||
1117 | if ((port->irq == NO_IRQ) || !port->mapbase) { | ||
1118 | printk(KERN_ERR "Could not allocate resources for PSC\n"); | ||
1119 | return -EINVAL; | ||
1120 | } | ||
1121 | |||
1122 | /* Add the port to the uart sub-system */ | 1165 | /* Add the port to the uart sub-system */ |
1123 | ret = uart_add_one_port(&mpc52xx_uart_driver, port); | 1166 | ret = uart_add_one_port(&mpc52xx_uart_driver, port); |
1124 | if (!ret) | 1167 | if (ret) { |
1125 | dev_set_drvdata(&op->dev, (void *)port); | 1168 | irq_dispose_mapping(port->irq); |
1169 | return ret; | ||
1170 | } | ||
1126 | 1171 | ||
1127 | return ret; | 1172 | dev_set_drvdata(&op->dev, (void *)port); |
1173 | return 0; | ||
1128 | } | 1174 | } |
1129 | 1175 | ||
1130 | static int | 1176 | static int |