Sorry, I just now got around spending some more time on this issue and now fully understand what is going on. The big difference between the Tegra high-speed serial driver and the 8250 one is that while the former enables/disables clocks all the time the later does not do so but rather just enables the clocks during probe and leaves them enabled. Now, the problem is that the 2nd UART shares its clock with VFIR and while the kernel boots it initially probes UARTB and enables its clock. Later the kernel decides to disable the VFIR clock as it is unused. Any further accesses to UARTB now freeze. you may easily instrument this e.g. as follows:
- Stop in U-Boot.
- Make sure U-Boot console won’t overflow due to slow frame buffer console:
setenv stdout serial
.
- Enable tracing of clock related calls:
setenv defargs 'trace_event=clk_enable,clk_disable,clk_set_parent tp_printk'
.
- Now proceed with booting:
boot
.
- You will now notice UART and VFIR clocks being enabled resp. disabled:
.
[ 2.229213] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[ 2.231946] clk_enable: uarta
[ 2.232458] printk: console [ttyS0] disabled
[ 2.232548] 70006000.serial: ttyS0 at MMIO 0x70006000 (irq = 78, base_baud = 25500000) is a Tegra
[ 3.969906] printk: console [ttyS0] enabled
[ 3.974678] clk_enable: uartb
[ 3.978110] 70006040.serial: ttyS1 at MMIO 0x70006040 (irq = 79, base_baud = 25500000) is a Tegra
[ 3.987577] clk_enable: uartc
[ 3.991024] 70006200.serial: ttyS2 at MMIO 0x70006200 (irq = 80, base_baud = 25500000) is a Tegra
[ 4.000485] clk_enable: uartd
[ 4.003906] 70006300.serial: ttyS3 at MMIO 0x70006300 (irq = 81, base_baud = 25500000) is a Tegra
...
[ 7.246243] clk_disable: vfir
This disabling of the VFIR clock may easily be prevented with the following simple patch:
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index 38c4eb28c8bf..e3da3147468a 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -671,7 +671,7 @@ static struct tegra_periph_init_data periph_clks[] = {
MUX("hda", mux_pllp_pllc_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda_8),
MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x),
MUX8("hda2codec_2x", mux_pllp_pllc_plla_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x_8),
- MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir),
+ MUX_FLAGS("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir, CLK_IGNORE_UNUSED),
MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1),
MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2),
MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3),
Let me check with the Tegra maintainers whether that is indeed an acceptable solution.
Thanks again for reporting this issue and sorry it took so long for us to figure it out.