diff options
| author | Wolfram Sang <w.sang@pengutronix.de> | 2008-12-21 04:54:32 -0500 |
|---|---|---|
| committer | Grant Likely <grant.likely@secretlab.ca> | 2008-12-21 04:54:32 -0500 |
| commit | aec739e010f8163eac225f4e331ac7fbd59ac5c8 (patch) | |
| tree | 85b01751d95c1635d0825c02d43654444543fb21 | |
| parent | b65149880d0467287fa4c7b4f19953392323f4ac (diff) | |
powerpc/mpc5200: add rts/cts handling in PSC UART driver
Add RTS/CTS-support for the PSC of the MPC5200B. Tested with a Phytec
MPC5200B-IO.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
| -rw-r--r-- | arch/powerpc/include/asm/mpc52xx_psc.h | 11 | ||||
| -rw-r--r-- | drivers/serial/mpc52xx_uart.c | 41 |
2 files changed, 47 insertions, 5 deletions
diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h index 8917ed630565..a218da6bec7c 100644 --- a/arch/powerpc/include/asm/mpc52xx_psc.h +++ b/arch/powerpc/include/asm/mpc52xx_psc.h | |||
| @@ -68,12 +68,20 @@ | |||
| 68 | #define MPC52xx_PSC_IMR_ORERR 0x1000 | 68 | #define MPC52xx_PSC_IMR_ORERR 0x1000 |
| 69 | #define MPC52xx_PSC_IMR_IPC 0x8000 | 69 | #define MPC52xx_PSC_IMR_IPC 0x8000 |
| 70 | 70 | ||
| 71 | /* PSC input port change bit */ | 71 | /* PSC input port change bits */ |
| 72 | #define MPC52xx_PSC_CTS 0x01 | 72 | #define MPC52xx_PSC_CTS 0x01 |
| 73 | #define MPC52xx_PSC_DCD 0x02 | 73 | #define MPC52xx_PSC_DCD 0x02 |
| 74 | #define MPC52xx_PSC_D_CTS 0x10 | 74 | #define MPC52xx_PSC_D_CTS 0x10 |
| 75 | #define MPC52xx_PSC_D_DCD 0x20 | 75 | #define MPC52xx_PSC_D_DCD 0x20 |
| 76 | 76 | ||
| 77 | /* PSC acr bits */ | ||
| 78 | #define MPC52xx_PSC_IEC_CTS 0x01 | ||
| 79 | #define MPC52xx_PSC_IEC_DCD 0x02 | ||
| 80 | |||
| 81 | /* PSC output port bits */ | ||
| 82 | #define MPC52xx_PSC_OP_RTS 0x01 | ||
| 83 | #define MPC52xx_PSC_OP_RES 0x02 | ||
| 84 | |||
| 77 | /* PSC mode fields */ | 85 | /* PSC mode fields */ |
| 78 | #define MPC52xx_PSC_MODE_5_BITS 0x00 | 86 | #define MPC52xx_PSC_MODE_5_BITS 0x00 |
| 79 | #define MPC52xx_PSC_MODE_6_BITS 0x01 | 87 | #define MPC52xx_PSC_MODE_6_BITS 0x01 |
| @@ -91,6 +99,7 @@ | |||
| 91 | #define MPC52xx_PSC_MODE_ONE_STOP_5_BITS 0x00 | 99 | #define MPC52xx_PSC_MODE_ONE_STOP_5_BITS 0x00 |
| 92 | #define MPC52xx_PSC_MODE_ONE_STOP 0x07 | 100 | #define MPC52xx_PSC_MODE_ONE_STOP 0x07 |
| 93 | #define MPC52xx_PSC_MODE_TWO_STOP 0x0f | 101 | #define MPC52xx_PSC_MODE_TWO_STOP 0x0f |
| 102 | #define MPC52xx_PSC_MODE_TXCTS 0x10 | ||
| 94 | 103 | ||
| 95 | #define MPC52xx_PSC_RFNUM_MASK 0x01ff | 104 | #define MPC52xx_PSC_RFNUM_MASK 0x01ff |
| 96 | 105 | ||
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index d82650d54391..d2a1fc29834e 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); |
| @@ -832,6 +857,7 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
| 832 | struct uart_port *port = dev_id; | 857 | struct uart_port *port = dev_id; |
| 833 | unsigned long pass = ISR_PASS_LIMIT; | 858 | unsigned long pass = ISR_PASS_LIMIT; |
| 834 | unsigned int keepgoing; | 859 | unsigned int keepgoing; |
| 860 | u8 status; | ||
| 835 | 861 | ||
| 836 | spin_lock(&port->lock); | 862 | spin_lock(&port->lock); |
| 837 | 863 | ||
| @@ -848,6 +874,13 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
| 848 | if (psc_ops->tx_rdy(port)) | 874 | if (psc_ops->tx_rdy(port)) |
| 849 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 875 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
| 850 | 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 | |||
| 851 | /* Limit number of iteration */ | 884 | /* Limit number of iteration */ |
| 852 | if (!(--pass)) | 885 | if (!(--pass)) |
| 853 | keepgoing = 0; | 886 | keepgoing = 0; |
