tty: serial: qcom_geni_serial: Fix RX cancel command failure
[ Upstream commit 679aac5ead2f18d223554a52b543e1195e181811 ] RX cancel command fails when BT is switched on and off multiple times. To handle this, poll for the cancel bit in SE_GENI_S_IRQ_STATUS register instead of SE_GENI_S_CMD_CTRL_REG. As per the HPG update, handle the RX last bit after cancel command and flush out the RX FIFO buffer. Signed-off-by: satya priya <skakit@codeaurora.org> Cc: stable <stable@vger.kernel.org> Link: https://lore.kernel.org/r/1581415982-8793-1-git-send-email-skakit@codeaurora.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
e6ebad8588
commit
56ad5b4b74
1 changed files with 14 additions and 4 deletions
|
@ -121,6 +121,7 @@ static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop);
|
|||
static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop);
|
||||
static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port);
|
||||
static void qcom_geni_serial_stop_rx(struct uart_port *uport);
|
||||
static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
|
||||
|
||||
static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
|
||||
32000000, 48000000, 64000000, 80000000,
|
||||
|
@ -614,7 +615,7 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport)
|
|||
u32 irq_en;
|
||||
u32 status;
|
||||
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
|
||||
u32 irq_clear = S_CMD_DONE_EN;
|
||||
u32 s_irq_status;
|
||||
|
||||
irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN);
|
||||
irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
|
||||
|
@ -630,10 +631,19 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport)
|
|||
return;
|
||||
|
||||
geni_se_cancel_s_cmd(&port->se);
|
||||
qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG,
|
||||
S_GENI_CMD_CANCEL, false);
|
||||
qcom_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
|
||||
S_CMD_CANCEL_EN, true);
|
||||
/*
|
||||
* If timeout occurs secondary engine remains active
|
||||
* and Abort sequence is executed.
|
||||
*/
|
||||
s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
|
||||
/* Flush the Rx buffer */
|
||||
if (s_irq_status & S_RX_FIFO_LAST_EN)
|
||||
qcom_geni_serial_handle_rx(uport, true);
|
||||
writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR);
|
||||
|
||||
status = readl(uport->membase + SE_GENI_STATUS);
|
||||
writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR);
|
||||
if (status & S_GENI_CMD_ACTIVE)
|
||||
qcom_geni_serial_abort_rx(uport);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue