summaryrefslogtreecommitdiff
path: root/drivers/serial
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2010-02-23 13:53:40 +0530
committerLaxman Dewangan <ldewangan@nvidia.com>2010-02-23 14:39:46 +0530
commit364ea74fdd968c0370d64908891e22961e771788 (patch)
tree4db49c20b46f58c217da2c16554d78fabb152b2a /drivers/serial
parentbdbfc7a9b82eb6c26524f46523b7728dd645a3ef (diff)
tegra uart: Removing the modification of the mctrl
The serial_core have the modem state variable mctrl which was getting modified by the tegra uart driver. The low level driver should not modify this variable as serial core uses this for the modem control statesi and uses in future for controling the modem states. Removing the modification of this variable from low level driver. Tested with suspend/resume with BT on whistler by monitoring the modem signals. Change-Id: Ib6244c5160e40623a40e4764f5f156dc4f386ec9
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/tegra_hsuart.c116
1 files changed, 70 insertions, 46 deletions
diff --git a/drivers/serial/tegra_hsuart.c b/drivers/serial/tegra_hsuart.c
index feccfcf91ffc..d28778eb6018 100644
--- a/drivers/serial/tegra_hsuart.c
+++ b/drivers/serial/tegra_hsuart.c
@@ -74,6 +74,8 @@ struct tegra_uart_port {
unsigned char mcr_shadow;
unsigned char lcr_shadow;
unsigned char ier_shadow;
+ bool use_cts_control;
+ bool rts_active;
/* FIFO watermarks which decides when the interrupts are triggered(PIO
* mode). In the case of receive it is high watermark and in the case
@@ -112,6 +114,8 @@ struct tegra_uart_port {
static void tegra_set_baudrate(struct tegra_uart_port *t, unsigned int baud);
static void tegra_set_mctrl(struct uart_port *u, unsigned int mctrl);
static void do_handle_rx_pio(struct uart_port *u);
+static void set_rts(struct tegra_uart_port *t, bool active);
+static void set_dtr(struct tegra_uart_port *t, bool active);
static inline int tegra_uart_isbreak(struct uart_port *u)
{
@@ -143,15 +147,11 @@ void tegra_rx_dma_threshold_callback(struct tegra_dma_req *req, int err)
spin_lock_irqsave(&u->lock, flags);
- u->mctrl &= ~TIOCM_RTS;
- u->mctrl &= ~TIOCM_DTR;
- tegra_set_mctrl(u, u->mctrl);
-
+ if (t->rts_active)
+ set_rts(t, false);
tegra_dma_dequeue(t->rx_dma);
-
- u->mctrl |= TIOCM_RTS;
- u->mctrl |= TIOCM_DTR;
- tegra_set_mctrl(u, u->mctrl);
+ if (t->rts_active)
+ set_rts(t, true);
spin_unlock_irqrestore(&u->lock, flags);
}
@@ -202,17 +202,11 @@ static void do_handle_rx_dma(struct uart_port *u)
struct tegra_uart_port *t;
t = container_of(u, struct tegra_uart_port, uport);
-
- u->mctrl &= ~TIOCM_RTS;
- u->mctrl &= ~TIOCM_DTR;
- tegra_set_mctrl(u, u->mctrl);
-
+ if (t->rts_active)
+ set_rts(t, false);
tegra_dma_dequeue(t->rx_dma);
-
- u->mctrl |= TIOCM_RTS;
- u->mctrl |= TIOCM_DTR;
- tegra_set_mctrl(u, u->mctrl);
-
+ if (t->rts_active)
+ set_rts(t, true);
}
static char do_decode_rx_error(struct uart_port *u)
@@ -504,10 +498,8 @@ static void tegra_stop_rx(struct uart_port *u)
t = container_of(u, struct tegra_uart_port, uport);
- u->mctrl &= ~TIOCM_RTS;
- u->mctrl &= ~TIOCM_DTR;
- tegra_set_mctrl(u, u->mctrl);
-
+ if (t->rts_active)
+ set_rts(t, false);
tegra_dma_dequeue(t->rx_dma);
return;
@@ -534,7 +526,6 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *t)
static int tegra_uart_hw_init(struct tegra_uart_port *t)
{
unsigned char fcr;
- unsigned char mcr;
unsigned char ier;
NvError err;
@@ -613,16 +604,6 @@ static int tegra_uart_hw_init(struct tegra_uart_port *t)
NO_CHANGE, t->fcr_shadow);
writeb(t->fcr_shadow, t->regs + UART_IIR_FCR_0);
- /* Let hw control the RTS/CTS signals.
- */
- mcr = t->mcr_shadow;
- mcr = NV_FLD_SET_DRF_DEF(UART, MCR, CTS_EN, ENABLE, mcr);
- mcr = NV_FLD_SET_DRF_DEF(UART, MCR, RTS_EN, DISABLE, mcr);
- mcr = NV_FLD_SET_DRF_DEF(UART, MCR, RTS, FORCE_RTS_HI, mcr);
- mcr = NV_FLD_SET_DRF_DEF(UART, MCR, DTR, FORCE_DTR_HI, mcr);
- t->mcr_shadow = mcr;
- writeb(mcr, t->regs + UART_MCR_0);
-
/*
* Enable IE_RXS for the receive status interrupts like line errros.
* Enable IE_RX_TIMEOUT to get the bytes which cannot be DMA'd.
@@ -820,6 +801,36 @@ static unsigned int tegra_get_mctrl(struct uart_port *u)
return TIOCM_RI | TIOCM_CD | TIOCM_DSR | TIOCM_CTS;
}
+static void set_rts(struct tegra_uart_port *t, bool active)
+{
+ unsigned char mcr;
+ mcr = t->mcr_shadow;
+ if (active)
+ mcr = NV_FLD_SET_DRF_DEF(UART, MCR, RTS, FORCE_RTS_LOW, mcr);
+ else
+ mcr = NV_FLD_SET_DRF_DEF(UART, MCR, RTS, FORCE_RTS_HI, mcr);
+ if (mcr != t->mcr_shadow) {
+ writeb(mcr, t->regs + UART_MCR_0);
+ t->mcr_shadow = mcr;
+ }
+ return;
+}
+
+static void set_dtr(struct tegra_uart_port *t, bool active)
+{
+ unsigned char mcr;
+ mcr = t->mcr_shadow;
+ if (active)
+ mcr = NV_FLD_SET_DRF_DEF(UART, MCR, DTR, FORCE_DTR_LOW, mcr);
+ else
+ mcr = NV_FLD_SET_DRF_DEF(UART, MCR, DTR, FORCE_DTR_HI, mcr);
+ if (mcr != t->mcr_shadow) {
+ writeb(mcr, t->regs + UART_MCR_0);
+ t->mcr_shadow = mcr;
+ }
+ return;
+}
+
static void tegra_set_mctrl(struct uart_port *u, unsigned int mctrl)
{
unsigned char mcr;
@@ -829,20 +840,18 @@ static void tegra_set_mctrl(struct uart_port *u, unsigned int mctrl)
t = container_of(u, struct tegra_uart_port, uport);
mcr = t->mcr_shadow;
- if (mctrl & TIOCM_RTS)
- mcr = NV_FLD_SET_DRF_DEF(UART, MCR, RTS, FORCE_RTS_LOW, mcr);
- else
- mcr = NV_FLD_SET_DRF_DEF(UART, MCR, RTS, FORCE_RTS_HI, mcr);
+ if (mctrl & TIOCM_RTS) {
+ t->rts_active = true;
+ set_rts(t, true);
+ } else {
+ t->rts_active = false;
+ set_rts(t, false);
+ }
if (mctrl & TIOCM_DTR)
- mcr = NV_FLD_SET_DRF_DEF(UART, MCR, DTR, FORCE_DTR_LOW, mcr);
+ set_dtr(t, true);
else
- mcr = NV_FLD_SET_DRF_DEF(UART, MCR, DTR, FORCE_DTR_HI, mcr);
-
- if (mcr != t->mcr_shadow) {
- writeb(mcr, t->regs + UART_MCR_0);
- t->mcr_shadow = mcr;
- }
+ set_dtr(t, false);
return;
}
@@ -961,7 +970,7 @@ static void tegra_set_baudrate(struct tegra_uart_port *t, unsigned int baud)
&clock, 1, &actual_clock, 0);
if (err != NvSuccess) {
dev_err(t->uport.dev, "Setting the UART clock failed min "
- "%ld ideal %d max %ld\n", minclock, clock, maxclock);
+ "%lld ideal %d max %lld\n", minclock, clock, maxclock);
return;
}
@@ -994,6 +1003,7 @@ void tegra_set_termios(struct uart_port *u, struct ktermios *termios,
unsigned int lcr;
unsigned int c_cflag = termios->c_cflag;
char debug_string[50];
+ unsigned char mcr;
t = container_of(u, struct tegra_uart_port, uport);
dev_vdbg(t->uport.dev, "+tegra_set_termios\n");
@@ -1061,7 +1071,21 @@ void tegra_set_termios(struct uart_port *u, struct ktermios *termios,
t->lcr_shadow = lcr;
/* Flow control */
- termios->c_cflag |= CRTSCTS;
+ if (termios->c_cflag & CRTSCTS) {
+ mcr = t->mcr_shadow;
+ mcr = NV_FLD_SET_DRF_DEF(UART, MCR, CTS_EN, ENABLE, mcr);
+ mcr = NV_FLD_SET_DRF_DEF(UART, MCR, RTS_EN, DISABLE, mcr);
+ t->mcr_shadow = mcr;
+ writeb(mcr, t->regs + UART_MCR_0);
+ t->use_cts_control = true;
+ } else {
+ mcr = t->mcr_shadow;
+ mcr = NV_FLD_SET_DRF_DEF(UART, MCR, CTS_EN, DISABLE, mcr);
+ mcr = NV_FLD_SET_DRF_DEF(UART, MCR, RTS_EN, DISABLE, mcr);
+ t->mcr_shadow = mcr;
+ writeb(mcr, t->regs + UART_MCR_0);
+ t->use_cts_control = false;
+ }
spin_unlock_irqrestore(&u->lock, flags);
dev_info(u->dev, "%s\n", debug_string);