Skip to content

Commit

Permalink
serial: 8250_omap: Implementation of Errata i2310
Browse files Browse the repository at this point in the history
commit 9d141c1 upstream.

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: b67e830 ("serial: 8250: 8250_omap: Fix possible interrupt storm on K3 SoCs")
Cc: stable@vger.kernel.org
Signed-off-by: Udit Kumar <u-kumar1@ti.com>
Link: https://lore.kernel.org/r/20240619105903.165434-1-u-kumar1@ti.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
uditkumarti authored and gregkh committed Jul 5, 2024
1 parent a47407a commit 98840e4
Showing 1 changed file with 20 additions and 5 deletions.
25 changes: 20 additions & 5 deletions drivers/tty/serial/8250/8250_omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ static u32 uart_read(struct omap8250_priv *priv, u32 reg)
return readl(priv->membase + (reg << OMAP_UART_REGSHIFT));
}

/* Timeout low and High */
#define UART_OMAP_TO_L 0x26
#define UART_OMAP_TO_H 0x27

/*
* Called on runtime PM resume path from omap8250_restore_regs(), and
* omap8250_set_mctrl().
Expand Down Expand Up @@ -628,13 +632,24 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)

/*
* 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
* is required to clear RX TIMEOUT condition.
* FIFO has been drained or erroneously.
* So apply solution of Errata i2310 as mentioned in
* https://www.ti.com/lit/pdf/sprz536
*/
if (priv->habit & UART_RX_TIMEOUT_QUIRK &&
(iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT &&
serial_port_in(port, UART_OMAP_RX_LVL) == 0) {
serial_port_in(port, UART_RX);
(iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT) {
unsigned char efr2, timeout_h, timeout_l;

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 */
Expand Down

0 comments on commit 98840e4

Please sign in to comment.