Commit 9d141c1e authored by Udit Kumar's avatar Udit Kumar Committed by Greg Kroah-Hartman

serial: 8250_omap: Implementation of Errata i2310

As per Errata i2310[0], Erroneous timeout can be triggered,
if this Erroneous interrupt is not cleared then it may leads
to storm of interrupts, therefore apply Errata i2310 solution.

[0] https://www.ti.com/lit/pdf/sprz536 page 23

Fixes: b67e830d ("serial: 8250: 8250_omap: Fix possible interrupt storm on K3 SoCs")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarUdit Kumar <u-kumar1@ti.com>
Link: https://lore.kernel.org/r/20240619105903.165434-1-u-kumar1@ti.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0ac18dac
...@@ -115,6 +115,10 @@ ...@@ -115,6 +115,10 @@
/* RX FIFO occupancy indicator */ /* RX FIFO occupancy indicator */
#define UART_OMAP_RX_LVL 0x19 #define UART_OMAP_RX_LVL 0x19
/* Timeout low and High */
#define UART_OMAP_TO_L 0x26
#define UART_OMAP_TO_H 0x27
/* /*
* Copy of the genpd flags for the console. * Copy of the genpd flags for the console.
* Only used if console suspend is disabled * Only used if console suspend is disabled
...@@ -663,13 +667,24 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) ...@@ -663,13 +667,24 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
/* /*
* On K3 SoCs, it is observed that RX TIMEOUT is signalled after * On K3 SoCs, it is observed that RX TIMEOUT is signalled after
* FIFO has been drained, in which case a dummy read of RX FIFO * FIFO has been drained or erroneously.
* is required to clear RX TIMEOUT condition. * So apply solution of Errata i2310 as mentioned in
* https://www.ti.com/lit/pdf/sprz536
*/ */
if (priv->habit & UART_RX_TIMEOUT_QUIRK && if (priv->habit & UART_RX_TIMEOUT_QUIRK &&
(iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT && (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT) {
serial_port_in(port, UART_OMAP_RX_LVL) == 0) { unsigned char efr2, timeout_h, timeout_l;
serial_port_in(port, UART_RX);
efr2 = serial_in(up, UART_OMAP_EFR2);
timeout_h = serial_in(up, UART_OMAP_TO_H);
timeout_l = serial_in(up, UART_OMAP_TO_L);
serial_out(up, UART_OMAP_TO_H, 0xFF);
serial_out(up, UART_OMAP_TO_L, 0xFF);
serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE);
serial_in(up, UART_IIR);
serial_out(up, UART_OMAP_EFR2, efr2);
serial_out(up, UART_OMAP_TO_H, timeout_h);
serial_out(up, UART_OMAP_TO_L, timeout_l);
} }
/* Stop processing interrupts on input overrun */ /* Stop processing interrupts on input overrun */
......
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