summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2019-06-12 03:37:00 -0700
committerYe Li <ye.li@nxp.com>2019-06-17 19:53:47 -0700
commitb9310b6ef2cf8c536126dd3867e9aa2b13bab81b (patch)
tree001f5df983c14ea72d1e4067a7527278c5f21ce7 /arch
parentcb91ff49c461974f1b2e1aa2e41e802cbbe4a087 (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.c37
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);
+ }
}
/*