This is a note to let you know that I've just added the patch titled
serial: 8250: omap: Fix idling of clocks for unused uarts
to my tty git tree which can be found at git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git in the tty-next branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will also be merged in the next major kernel release during the merge window.
If you have any questions about this process, please let me know.
From 13dc04d0e5fdc25c8f713ad23fdce51cf2bf96ba Mon Sep 17 00:00:00 2001
From: Tony Lindgren tony@atomide.com Date: Fri, 4 May 2018 10:44:09 -0700 Subject: serial: 8250: omap: Fix idling of clocks for unused uarts
I noticed that unused UARTs won't necessarily idle properly always unless at least one byte tx transfer is done first.
After some debugging I narrowed down the problem to the scr register dma configuration bits that need to be set before softreset for the clocks to idle. Unless we do this, the module clkctrl idlest bits may be set to 1 instead of 3 meaning the clock will never idle and is blocking deeper idle states for the whole domain.
This might be related to the configuration done by the bootloader or kexec booting where certain configurations cause the 8250 or the clkctrl clock to jam in a way where setting of the scr bits and reset is needed to clear it. I've tried diffing the 8250 registers for the various modes, but did not see anything specific. So far I've only seen this on omap4 but I'm suspecting this might also happen on the other clkctrl using SoCs considering they already have a quirk enabled for UART_ERRATA_CLOCK_DISABLE.
Let's fix the issue by configuring scr before reset for basic dma even if we don't use it. The scr register will be reset when we do softreset few lines after, and we restore scr on resume. We should do this for all the SoCs with UART_ERRATA_CLOCK_DISABLE quirk flag set since the ones with UART_ERRATA_CLOCK_DISABLE are all based using clkctrl similar to omap4.
Looks like both OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL bits are needed for the clkctrl to idle after a softreset.
And we need to add omap4 to also use the UART_ERRATA_CLOCK_DISABLE for the related workaround to be enabled. This same compatible value will also be used for omap5.
Fixes: cdb929e4452a ("serial: 8250_omap: workaround errata around idling UART after using DMA") Cc: Keerthy j-keerthy@ti.com Cc: Matthijs van Duin matthijsvanduin@gmail.com Cc: Sekhar Nori nsekhar@ti.com Cc: Tero Kristo t-kristo@ti.com Signed-off-by: Tony Lindgren tony@atomide.com Cc: stable stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/tty/serial/8250/8250_omap.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 6aaa84355fd1..1b337fee07ed 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1110,13 +1110,14 @@ static int omap8250_no_handle_irq(struct uart_port *port) return 0; }
+static const u8 omap4_habit = UART_ERRATA_CLOCK_DISABLE; static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE; static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE;
static const struct of_device_id omap8250_dt_ids[] = { { .compatible = "ti,omap2-uart" }, { .compatible = "ti,omap3-uart" }, - { .compatible = "ti,omap4-uart" }, + { .compatible = "ti,omap4-uart", .data = &omap4_habit, }, { .compatible = "ti,am3352-uart", .data = &am3352_habit, }, { .compatible = "ti,am4372-uart", .data = &am3352_habit, }, { .compatible = "ti,dra742-uart", .data = &dra742_habit, }, @@ -1362,6 +1363,19 @@ static int omap8250_soft_reset(struct device *dev) int sysc; int syss;
+ /* + * At least on omap4, unused uarts may not idle after reset without + * a basic scr dma configuration even with no dma in use. The + * module clkctrl status bits will be 1 instead of 3 blocking idle + * for the whole clockdomain. The softreset below will clear scr, + * and we restore it on resume so this is safe to do on all SoCs + * needing omap8250_soft_reset() quirk. Do it in two writes as + * recommended in the comment for omap8250_update_scr(). + */ + serial_out(up, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); + serial_out(up, UART_OMAP_SCR, + OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL); + sysc = serial_in(up, UART_OMAP_SYSC);
/* softreset the UART */