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; |