Commit aec739e0 authored by Wolfram Sang's avatar Wolfram Sang Committed by Grant Likely

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: default avatarWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent b6514988
...@@ -68,12 +68,20 @@ ...@@ -68,12 +68,20 @@
#define MPC52xx_PSC_IMR_ORERR 0x1000 #define MPC52xx_PSC_IMR_ORERR 0x1000
#define MPC52xx_PSC_IMR_IPC 0x8000 #define MPC52xx_PSC_IMR_IPC 0x8000
/* PSC input port change bit */ /* PSC input port change bits */
#define MPC52xx_PSC_CTS 0x01 #define MPC52xx_PSC_CTS 0x01
#define MPC52xx_PSC_DCD 0x02 #define MPC52xx_PSC_DCD 0x02
#define MPC52xx_PSC_D_CTS 0x10 #define MPC52xx_PSC_D_CTS 0x10
#define MPC52xx_PSC_D_DCD 0x20 #define MPC52xx_PSC_D_DCD 0x20
/* PSC acr bits */
#define MPC52xx_PSC_IEC_CTS 0x01
#define MPC52xx_PSC_IEC_DCD 0x02
/* PSC output port bits */
#define MPC52xx_PSC_OP_RTS 0x01
#define MPC52xx_PSC_OP_RES 0x02
/* PSC mode fields */ /* PSC mode fields */
#define MPC52xx_PSC_MODE_5_BITS 0x00 #define MPC52xx_PSC_MODE_5_BITS 0x00
#define MPC52xx_PSC_MODE_6_BITS 0x01 #define MPC52xx_PSC_MODE_6_BITS 0x01
...@@ -91,6 +99,7 @@ ...@@ -91,6 +99,7 @@
#define MPC52xx_PSC_MODE_ONE_STOP_5_BITS 0x00 #define MPC52xx_PSC_MODE_ONE_STOP_5_BITS 0x00
#define MPC52xx_PSC_MODE_ONE_STOP 0x07 #define MPC52xx_PSC_MODE_ONE_STOP 0x07
#define MPC52xx_PSC_MODE_TWO_STOP 0x0f #define MPC52xx_PSC_MODE_TWO_STOP 0x0f
#define MPC52xx_PSC_MODE_TXCTS 0x10
#define MPC52xx_PSC_RFNUM_MASK 0x01ff #define MPC52xx_PSC_RFNUM_MASK 0x01ff
......
...@@ -429,14 +429,24 @@ mpc52xx_uart_tx_empty(struct uart_port *port) ...@@ -429,14 +429,24 @@ mpc52xx_uart_tx_empty(struct uart_port *port)
static void static void
mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{ {
/* Not implemented */ if (mctrl & TIOCM_RTS)
out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS);
else
out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS);
} }
static unsigned int static unsigned int
mpc52xx_uart_get_mctrl(struct uart_port *port) mpc52xx_uart_get_mctrl(struct uart_port *port)
{ {
/* Not implemented */ unsigned int ret = TIOCM_DSR;
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr);
if (!(status & MPC52xx_PSC_CTS))
ret |= TIOCM_CTS;
if (!(status & MPC52xx_PSC_DCD))
ret |= TIOCM_CAR;
return ret;
} }
static void static void
...@@ -479,7 +489,15 @@ mpc52xx_uart_stop_rx(struct uart_port *port) ...@@ -479,7 +489,15 @@ mpc52xx_uart_stop_rx(struct uart_port *port)
static void static void
mpc52xx_uart_enable_ms(struct uart_port *port) mpc52xx_uart_enable_ms(struct uart_port *port)
{ {
/* Not implemented */ struct mpc52xx_psc __iomem *psc = PSC(port);
/* clear D_*-bits by reading them */
in_8(&psc->mpc52xx_psc_ipcr);
/* enable CTS and DCD as IPC interrupts */
out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD);
port->read_status_mask |= MPC52xx_PSC_IMR_IPC;
out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
} }
static void static void
...@@ -580,6 +598,10 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, ...@@ -580,6 +598,10 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
MPC52xx_PSC_MODE_ONE_STOP_5_BITS : MPC52xx_PSC_MODE_ONE_STOP_5_BITS :
MPC52xx_PSC_MODE_ONE_STOP; MPC52xx_PSC_MODE_ONE_STOP;
if (new->c_cflag & CRTSCTS) {
mr1 |= MPC52xx_PSC_MODE_RXRTS;
mr2 |= MPC52xx_PSC_MODE_TXCTS;
}
baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
quot = uart_get_divisor(port, baud); quot = uart_get_divisor(port, baud);
...@@ -617,6 +639,9 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, ...@@ -617,6 +639,9 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
out_8(&psc->ctur, ctr >> 8); out_8(&psc->ctur, ctr >> 8);
out_8(&psc->ctlr, ctr & 0xff); out_8(&psc->ctlr, ctr & 0xff);
if (UART_ENABLE_MS(port, new->c_cflag))
mpc52xx_uart_enable_ms(port);
/* Reenable TX & RX */ /* Reenable TX & RX */
out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); out_8(&psc->command, MPC52xx_PSC_TX_ENABLE);
out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); out_8(&psc->command, MPC52xx_PSC_RX_ENABLE);
...@@ -832,6 +857,7 @@ mpc52xx_uart_int(int irq, void *dev_id) ...@@ -832,6 +857,7 @@ mpc52xx_uart_int(int irq, void *dev_id)
struct uart_port *port = dev_id; struct uart_port *port = dev_id;
unsigned long pass = ISR_PASS_LIMIT; unsigned long pass = ISR_PASS_LIMIT;
unsigned int keepgoing; unsigned int keepgoing;
u8 status;
spin_lock(&port->lock); spin_lock(&port->lock);
...@@ -848,6 +874,13 @@ mpc52xx_uart_int(int irq, void *dev_id) ...@@ -848,6 +874,13 @@ mpc52xx_uart_int(int irq, void *dev_id)
if (psc_ops->tx_rdy(port)) if (psc_ops->tx_rdy(port))
keepgoing |= mpc52xx_uart_int_tx_chars(port); keepgoing |= mpc52xx_uart_int_tx_chars(port);
status = in_8(&PSC(port)->mpc52xx_psc_ipcr);
if (status & MPC52xx_PSC_D_DCD)
uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD));
if (status & MPC52xx_PSC_D_CTS)
uart_handle_cts_change(port, !(status & MPC52xx_PSC_CTS));
/* Limit number of iteration */ /* Limit number of iteration */
if (!(--pass)) if (!(--pass))
keepgoing = 0; keepgoing = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment