From 07929a3e5f2c1fbcd268ecd06ada515083baf9ec Mon Sep 17 00:00:00 2001 From: Dilip Kota Date: Fri, 24 Jan 2014 02:41:47 +0530 Subject: msm_serial_hs: Program RFR to synchronize clock-off sequence with HW Assert the RFR line during clock off and de-assert it after the clock off is successful. This is to avoid the data to be coming from the client during clock off. Change-Id: I6cad22a63ebd3cfaa20c52445584829b382b7e3a Signed-off-by: Dilip Kota Signed-off-by: Kiran Gunda --- drivers/tty/serial/msm_serial_hs.c | 42 +++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 3c72654aa02f..cd392126dac4 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -1139,6 +1139,8 @@ static void msm_hs_set_termios(struct uart_port *uport, data = msm_hs_read(uport, UART_DM_MR1); data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK; msm_hs_write(uport, UART_DM_MR1, data); + /* set RFR_N to high */ + msm_hs_write(uport, UART_DM_CR, RFR_HIGH); /* * Disable Rx channel of UARTDM @@ -1269,12 +1271,12 @@ static void msm_hs_set_termios(struct uart_port *uport, * UART Core would trigger RFR if it is not having any space with * RX FIFO. */ + /* Pulling RFR line high */ + msm_hs_write(uport, UART_DM_CR, RFR_LOW); data = msm_hs_read(uport, UART_DM_MR1); data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK); - if (c_cflag & CRTSCTS) { data |= UARTDM_MR1_CTS_CTL_BMSK; data |= UARTDM_MR1_RX_RDY_CTL_BMSK; - } msm_hs_write(uport, UART_DM_MR1, data); msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg); @@ -2085,6 +2087,7 @@ static int msm_hs_check_clock_off(struct uart_port *uport) { unsigned long sr_status; unsigned long flags; + unsigned int data; struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); struct circ_buf *tx_buf = &uport->state->xmit; @@ -2100,8 +2103,16 @@ static int msm_hs_check_clock_off(struct uart_port *uport) msm_uport->imr_reg & UARTDM_ISR_TXLEV_BMSK) { spin_unlock_irqrestore(&uport->lock, flags); mutex_unlock(&msm_uport->clk_mutex); - if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) + if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) { msm_uport->clk_state = MSM_HS_CLK_ON; + /* Pulling RFR line high */ + msm_hs_write(uport, UART_DM_CR, RFR_LOW); + /* Enable auto RFR */ + data = msm_hs_read(uport, UART_DM_MR1); + data |= UARTDM_MR1_RX_RDY_CTL_BMSK; + msm_hs_write(uport, UART_DM_MR1, data); + mb(); + } MSM_HS_DBG("%s(): clkstate %d", __func__, msm_uport->clk_state); return -1; } @@ -2133,6 +2144,14 @@ static int msm_hs_check_clock_off(struct uart_port *uport) spin_unlock_irqrestore(&uport->lock, flags); + /* Pulling RFR line high */ + msm_hs_write(uport, UART_DM_CR, RFR_LOW); + /* Enable auto RFR */ + data = msm_hs_read(uport, UART_DM_MR1); + data |= UARTDM_MR1_RX_RDY_CTL_BMSK; + msm_hs_write(uport, UART_DM_MR1, data); + mb(); + /* we really want to clock off */ msm_hs_clock_unvote(msm_uport); @@ -2309,6 +2328,14 @@ void msm_hs_request_clock_off(struct uart_port *uport) { spin_lock_irqsave(&uport->lock, flags); if (msm_uport->clk_state == MSM_HS_CLK_ON) { msm_uport->clk_state = MSM_HS_CLK_REQUEST_OFF; + data = msm_hs_read(uport, UART_DM_MR1); + /*disable auto ready-for-receiving */ + data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK; + msm_hs_write(uport, UART_DM_MR1, data); + mb(); + /* set RFR_N to high */ + msm_hs_write(uport, UART_DM_CR, RFR_HIGH); + data = msm_hs_read(uport, UART_DM_SR); MSM_HS_DBG("%s(): TXEMT, queuing clock off work\n", __func__); @@ -2330,6 +2357,15 @@ void msm_hs_request_clock_on(struct uart_port *uport) mutex_lock(&msm_uport->clk_mutex); spin_lock_irqsave(&uport->lock, flags); + if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) { + /* Pulling RFR line high */ + msm_hs_write(uport, UART_DM_CR, RFR_LOW); + /* Enable auto RFR */ + data = msm_hs_read(uport, UART_DM_MR1); + data |= UARTDM_MR1_RX_RDY_CTL_BMSK; + msm_hs_write(uport, UART_DM_MR1, data); + mb(); + } switch (msm_uport->clk_state) { case MSM_HS_CLK_OFF: wake_lock(&msm_uport->dma_wake_lock); -- cgit v1.2.3