summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@freescale.com>2014-07-10 17:05:49 +0800
committerShawn Guo <shawn.guo@freescale.com>2014-07-11 16:14:45 +0800
commitf9a708175789b138e559f6afcea75cd4b2acd25e (patch)
tree59004074ef83f621a3b8a54c92c42faa41a78e66
parentdc49a7739f46c92cc52e43e538d98f45e8cd5920 (diff)
ENGR00322272-1: ARM: imx6sx: hide the buggy ldb_di_sel mux from clk API
This is a smilar change for imx6sx clock tree as what we did for imx6q with commit 0bec46131d88 (ENGR00318063-8: ARM: imx6q: hide buggy ldb_di_sel from clk API). As the valid procedure of switching ldb_di_sel on imx6sx is not available yet, we hide this buggy mux by looking at the parent selection done by bootloader and register it statically to clock framework, so that switching this buggy mux becomes impossible. Also, since the bit width of ldb_di_sels is 3, we add two "dummy" entries for ldb_di_sels to avoid out-of-bounds error. Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
-rw-r--r--arch/arm/mach-imx/clk-imx6sx.c29
-rw-r--r--include/dt-bindings/clock/imx6sx-clock.h2
2 files changed, 21 insertions, 10 deletions
diff --git a/arch/arm/mach-imx/clk-imx6sx.c b/arch/arm/mach-imx/clk-imx6sx.c
index f742857a2cdf..b3ddb75be7d8 100644
--- a/arch/arm/mach-imx/clk-imx6sx.c
+++ b/arch/arm/mach-imx/clk-imx6sx.c
@@ -43,8 +43,8 @@ static const char *gpu_axi_sels[] = { "pll2_pfd2_396m", "pll3_pfd0_720m", "pll3_
static const char *gpu_core_sels[] = { "pll3_pfd1_540m", "pll3_pfd0_720m", "pll2_bus", "pll2_pfd2_396m", };
static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
-static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", };
-static const char *ldb_di1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", };
+static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", "dummy", "dummy"};
+static const char *ldb_di1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", "dummy", "dummy"};
static const char *pcie_axi_sels[] = { "axi", "ahb", };
static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll5_video_div", "pll4_audio_div", };
static const char *qspi1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", };
@@ -127,6 +127,21 @@ static u32 share_count_asrc;
static u32 share_count_audio;
static u32 share_count_esai;
+/*
+ * The ldb_di_sel is buggy and could generate a glitch during clock switch.
+ * Find out the parent set up by bootloader and register it statically to
+ * clock framework, so that we hide this buggy mux clock completely from the
+ * clock tree.
+ */
+static inline const char *ldb_di_parent(void __iomem *base, int ldb_di_idx)
+{
+ u32 val = readl_relaxed(base + 0x2c);
+ unsigned int shift = (ldb_di_idx == 0) ? 9 : 12;
+ unsigned int index = (val >> shift) & 0x7;
+
+ return (ldb_di_idx == 0) ? ldb_di0_sels[index] : ldb_di1_sels[index];
+}
+
static void __init imx6sx_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
@@ -266,8 +281,6 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT);
clks[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT);
- clks[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels), CLK_SET_RATE_PARENT);
- clks[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels), CLK_SET_RATE_PARENT);
clks[IMX6SX_CLK_LCDIF1_PRE_SEL] = imx_clk_mux_flags("lcdif1_pre_sel", base + 0x38, 15, 3, lcdif1_pre_sels, ARRAY_SIZE(lcdif1_pre_sels), CLK_SET_RATE_PARENT);
clks[IMX6SX_CLK_LCDIF1_SEL] = imx_clk_mux_flags("lcdif1_sel", base + 0x38, 9, 3, lcdif1_sels, ARRAY_SIZE(lcdif1_sels), CLK_SET_RATE_PARENT);
@@ -313,10 +326,10 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3);
clks[IMX6SX_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3);
- clks[IMX6SX_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
- clks[IMX6SX_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7);
- clks[IMX6SX_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
- clks[IMX6SX_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7);
+ clks[IMX6SX_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", ldb_di_parent(base, 0), 2, 7);
+ clks[IMX6SX_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", ldb_di_parent(base, 0), 1, 7);
+ clks[IMX6SX_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", ldb_di_parent(base, 1), 2, 7);
+ clks[IMX6SX_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", ldb_di_parent(base, 1), 1, 7);
/* name reg shift width busy: reg, shift parent_names num_parents */
clks[IMX6SX_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
diff --git a/include/dt-bindings/clock/imx6sx-clock.h b/include/dt-bindings/clock/imx6sx-clock.h
index 0e3710cdd5f6..0206616014dc 100644
--- a/include/dt-bindings/clock/imx6sx-clock.h
+++ b/include/dt-bindings/clock/imx6sx-clock.h
@@ -72,8 +72,6 @@
#define IMX6SX_CLK_CAN_SEL 59
#define IMX6SX_CLK_UART_SEL 60
#define IMX6SX_CLK_QSPI2_SEL 61
-#define IMX6SX_CLK_LDB_DI1_SEL 62
-#define IMX6SX_CLK_LDB_DI0_SEL 63
#define IMX6SX_CLK_SPDIF_SEL 64
#define IMX6SX_CLK_AUDIO_SEL 65
#define IMX6SX_CLK_ENET_PRE_SEL 66