diff options
author | Ye Li <ye.li@nxp.com> | 2019-06-12 03:37:00 -0700 |
---|---|---|
committer | Ye Li <ye.li@nxp.com> | 2019-06-17 19:53:47 -0700 |
commit | b9310b6ef2cf8c536126dd3867e9aa2b13bab81b (patch) | |
tree | 001f5df983c14ea72d1e4067a7527278c5f21ce7 /arch | |
parent | cb91ff49c461974f1b2e1aa2e41e802cbbe4a087 (diff) |
MLK-22005 imx8: clock: Handle FEC with freq limited on 8UX
When FEC is fused to limit RMII 10/100, we should configure clocks for RMII.
It needs enable 50Mhz ref clock, set SC_C_TXCLK mux to dummy. And we don't need
to enable the LPCG for RGMII TX CLK for RMII.
The latest SCFW has fixed a issue that PERCLK slice was disabled before
on parts with freq fused. With that issue the LPCGs using PERCLK as sources
are always in STOP staus. So the u-boot will loops in checking STOP status.
"commit 59e7cf4e81dd265411e4f1dcd5186567d3fb51ef
Author: Ranjani Vaidyanathan <ranjani.vaidyanathan@nxp.com>
Date: Mon Jun 17 17:10:43 2019 -0500
SCF-420 Ensure IEEE1588 can work on fused QX parts
"
SO to work with both old and latest SCFW versions, this patch changes to enable
LPCG by LPCG_ClockOn which won't wait on the LPCG STOP status
Signed-off-by: Ye Li <ye.li@nxp.com>
Acked-by: Peng Fan <peng.fan@nxp.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-imx/imx8/clock.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/arch/arm/mach-imx/imx8/clock.c b/arch/arm/mach-imx/imx8/clock.c index 55c4aefd98..01ed28883a 100644 --- a/arch/arm/mach-imx/imx8/clock.c +++ b/arch/arm/mach-imx/imx8/clock.c @@ -385,6 +385,7 @@ void init_clk_fec(int index) sc_ipc_t ipc; sc_pm_clock_rate_t rate = 24000000; sc_rsrc_t enet[2] = {SC_R_ENET_0, SC_R_ENET_1}; + bool enet_freq_limited = false; if (index > 1) return; @@ -394,6 +395,17 @@ void init_clk_fec(int index) ipc = gd->arch.ipc_channel_handle; + /* FEC may limited to RMII 10/100 by fuse, check it */ + if (is_imx8qxp()) { + uint32_t fuse_val = 0; + + err = sc_misc_otp_fuse_read(ipc, 0xa, &fuse_val); + if (err != SC_ERR_NONE) + printf("%s fuse read error: %d\n", __func__, err); + else + enet_freq_limited = ((fuse_val >> (index + 1)) & 0x1); + } + /* Disable SC_R_ENET_0 clock root */ err = sc_pm_clock_enable(ipc, enet[index], 0, false, false); err |= sc_pm_clock_enable(ipc, enet[index], 2, false, false); @@ -425,21 +437,36 @@ void init_clk_fec(int index) } /* Configure GPR regisers */ - if (sc_misc_set_control(ipc, enet[index], SC_C_TXCLK, 0) != SC_ERR_NONE) - printf("\nConfigure GPR registers operation(%d) failed!\n", SC_C_TXCLK); + if (!enet_freq_limited) { + if (sc_misc_set_control(ipc, enet[index], SC_C_TXCLK, 0) != SC_ERR_NONE) + printf("\nConfigure GPR registers operation(%d) failed!\n", SC_C_TXCLK); + } else { + /* SCFW will force TXCLK not from PERCLK if ENET freq is fused, here we explictly set to 1 */ + if (sc_misc_set_control(ipc, enet[index], SC_C_TXCLK, 1) != SC_ERR_NONE) + printf("\nConfigure GPR registers operation(%d) failed!\n", SC_C_TXCLK); + } + /* Enable divclk */ if (sc_misc_set_control(ipc, enet[index], SC_C_CLKDIV, 1) != SC_ERR_NONE) printf("\nConfigure GPR registers operation(%d) failed!\n", SC_C_CLKDIV); - if (sc_misc_set_control(ipc, enet[index], SC_C_DISABLE_50, 1) != SC_ERR_NONE) + if (sc_misc_set_control(ipc, enet[index], SC_C_DISABLE_50, 0) != SC_ERR_NONE) printf("\nConfigure GPR registers operation(%d) failed!\n", SC_C_DISABLE_50); - if (sc_misc_set_control(ipc, enet[index], SC_C_DISABLE_125, 1) != SC_ERR_NONE) + if (sc_misc_set_control(ipc, enet[index], SC_C_DISABLE_125, 0) != SC_ERR_NONE) printf("\nConfigure GPR registers operation(%d) failed!\n", SC_C_DISABLE_125); if (sc_misc_set_control(ipc, enet[index], SC_C_SEL_125, 0) != SC_ERR_NONE) printf("\nConfigure GPR registers operation(%d) failed!\n", SC_C_SEL_125); if (sc_misc_set_control(ipc, enet[index], SC_C_IPG_STOP, 0) != SC_ERR_NONE) printf("\nConfigure GPR registers operation(%d) failed!\n", SC_C_IPG_STOP); - LPCG_AllClockOn(ENET_0_LPCG + index * 0x10000); + LPCG_ClockOn(ENET_0_LPCG + index * 0x10000, 0); + LPCG_ClockOn(ENET_0_LPCG + index * 0x10000, 1); + LPCG_ClockOn(ENET_0_LPCG + index * 0x10000, 2); + LPCG_ClockOn(ENET_0_LPCG + index * 0x10000, 4); + LPCG_ClockOn(ENET_0_LPCG + index * 0x10000, 5); + if (!enet_freq_limited) { + /* RGMII TX CLK */ + LPCG_ClockOn(ENET_0_LPCG + index * 0x10000, 3); + } } /* |