summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx5/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx5/clock.c')
-rw-r--r--arch/arm/mach-mx5/clock.c548
1 files changed, 403 insertions, 145 deletions
diff --git a/arch/arm/mach-mx5/clock.c b/arch/arm/mach-mx5/clock.c
index 7c6f614bf97f..5ec89a6570cd 100644
--- a/arch/arm/mach-mx5/clock.c
+++ b/arch/arm/mach-mx5/clock.c
@@ -42,6 +42,7 @@ static struct clk emi_slow_clk;
static struct clk emi_intr_clk[];
static struct clk ddr_clk;
static struct clk ipu_clk[];
+static struct clk ldb_di_clk[];
static struct clk axi_a_clk;
static struct clk axi_b_clk;
static struct clk ddr_hf_clk;
@@ -52,16 +53,26 @@ static struct clk vpu_clk[];
static int cpu_curr_wp;
static struct cpu_wp *cpu_wp_tbl;
-void __iomem *pll1_base;
-void __iomem *pll2_base;
-void __iomem *pll3_base;
-void __iomem *pll4_base;
+static void __iomem *pll1_base;
+static void __iomem *pll2_base;
+static void __iomem *pll3_base;
+static void __iomem *pll4_base;
+
+extern int cpu_wp_nr;
+extern int lp_high_freq;
+extern int lp_med_freq;
+int max_axi_a_clk;
+int max_axi_b_clk;
-int cpu_wp_nr;
-int lp_high_freq;
-int lp_med_freq;
#define SPIN_DELAY 1000000 /* in nanoseconds */
+#define MAX_AXI_A_CLK_MX51 166250000
+#define MAX_AXI_A_CLK_MX53 400000000
+#define MAX_AXI_B_CLK_MX51 133000000
+#define MAX_AXI_B_CLK_MX53 200000000
+#define MAX_AHB_CLK 133000000
+#define MAX_EMI_SLOW_CLK 133000000
+#define MAX_DDR_HF_RATE 200000000
extern int mxc_jtag_enabled;
extern int uart_at_24;
@@ -70,8 +81,8 @@ extern int low_bus_freq_mode;
static int cpu_clk_set_wp(int wp);
extern void propagate_rate(struct clk *tclk);
-struct cpu_wp *(*get_cpu_wp)(int *wp);
-void (*set_num_cpu_wp)(int num);
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void (*set_num_cpu_wp)(int num);
static struct clk esdhc3_clk[];
@@ -394,7 +405,12 @@ static int _clk_pll_enable(struct clk *clk)
struct timespec curtime;
pllbase = _get_pll_base(clk);
- reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+
+ if (reg & MXC_PLL_DP_CTL_UPEN)
+ return 0;
+
+ reg |= MXC_PLL_DP_CTL_UPEN;
__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
/* Wait for lock */
@@ -738,10 +754,18 @@ static unsigned long _clk_axi_a_round_rate(struct clk *clk,
u32 div;
div = clk->parent->rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (clk->parent->rate / div > max_axi_a_clk)
+ div++;
+
if (div > 8)
div = 8;
- else if (div == 0)
- div++;
+
return clk->parent->rate / div;
}
@@ -771,10 +795,18 @@ static unsigned long _clk_ddr_hf_round_rate(struct clk *clk,
u32 div;
div = clk->parent->rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (clk->parent->rate / div > MAX_DDR_HF_RATE)
+ div++;
+
if (div > 8)
div = 8;
- else if (div == 0)
- div++;
+
return clk->parent->rate / div;
}
@@ -875,10 +907,18 @@ static unsigned long _clk_axi_b_round_rate(struct clk *clk,
u32 div;
div = clk->parent->rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (clk->parent->rate / div > max_axi_b_clk)
+ div++;
+
if (div > 8)
div = 8;
- else if (div == 0)
- div++;
+
return clk->parent->rate / div;
}
@@ -945,10 +985,18 @@ static unsigned long _clk_ahb_round_rate(struct clk *clk,
u32 div;
div = clk->parent->rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (clk->parent->rate / div > MAX_AHB_CLK)
+ div++;
+
if (div > 8)
div = 8;
- else if (div == 0)
- div++;
+
return clk->parent->rate / div;
}
@@ -973,7 +1021,7 @@ static int _clk_max_enable(struct clk *clk)
if (cpu_is_mx51())
reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS_MX51;
else
- reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS_MX53;
+ reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
__raw_writel(reg, MXC_CCM_CLPCR);
return 0;
@@ -991,7 +1039,7 @@ static void _clk_max_disable(struct clk *clk)
if (cpu_is_mx51())
reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS_MX51;
else
- reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS_MX53;
+ reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
__raw_writel(reg, MXC_CCM_CLPCR);
}
@@ -1078,10 +1126,18 @@ static unsigned long _clk_emi_slow_round_rate(struct clk *clk,
u32 div;
div = clk->parent->rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (clk->parent->rate / div > MAX_EMI_SLOW_CLK)
+ div++;
+
if (div > 8)
div = 8;
- else if (div == 0)
- div++;
+
return clk->parent->rate / div;
}
@@ -1143,6 +1199,9 @@ static struct clk emi_intr_clk[] = {
.disable = _clk_disable_inwait,
},
{
+ /* On MX51 - this clock is name emi_garb_clk, and controls the
+ * access of ARM to GARB.
+ */
.name = "emi_intr_clk",
.id = 1,
.parent = &ahb_clk,
@@ -1311,7 +1370,7 @@ static int _clk_sdma_enable(struct clk *clk)
if (cpu_is_mx51())
reg &= ~MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS_MX51;
else
- reg &= ~MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS_MX53;
+ reg &= ~MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS;
__raw_writel(reg, MXC_CCM_CLPCR);
return 0;
@@ -1327,7 +1386,7 @@ static void _clk_sdma_disable(struct clk *clk)
if (cpu_is_mx51())
reg |= MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS_MX51;
else
- reg |= MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS_MX53;
+ reg |= MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS;
__raw_writel(reg, MXC_CCM_CLPCR);
}
@@ -1357,7 +1416,10 @@ static int _clk_ipu_enable(struct clk *clk)
_clk_enable(clk);
/* Handshake with IPU when certain clock rates are changed. */
reg = __raw_readl(MXC_CCM_CCDR);
- reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
+ if (cpu_is_mx51())
+ reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
+ else
+ reg &= ~MXC_CCM_CCDR_IPU_HS_MX53_MASK;
__raw_writel(reg, MXC_CCM_CCDR);
/* Handshake with IPU when LPM is entered as its enabled. */
@@ -1445,6 +1507,8 @@ static int _clk_ipu_di_set_parent(struct clk *clk, struct clk *parent)
reg |= 3 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
} else if ((parent == &tve_clk) && (clk->id == 1))
reg |= 3 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
+ else if ((parent == &ldb_di_clk[clk->id]) && cpu_is_mx53())
+ reg |= 5 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
else /* Assume any other clock is external clock pin */
reg |= 4 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
__raw_writel(reg, MXC_CCM_CSCMR2);
@@ -1498,7 +1562,10 @@ static int _clk_ipu_di_set_rate(struct clk *clk, unsigned long rate)
__raw_writel(reg, MXC_CCM_CDCDR);
} else if ((clk->parent == &tve_clk) && (clk->id == 1))
clk->rate = rate; /*the rate decided by tve hw actually*/
- else
+ else if ((clk->parent == &ldb_di_clk[clk->id]) && cpu_is_mx53()) {
+ clk->rate = clk->parent->rate;
+ return 0;
+ } else
return -EINVAL;
clk->rate = rate;
@@ -1511,12 +1578,16 @@ static unsigned long _clk_ipu_di_round_rate(struct clk *clk,
{
u32 div;
- div = clk->parent->rate / rate;
- if (div > 8)
- div = 8;
- else if (div == 0)
- div++;
- return clk->parent->rate / div;
+ if ((clk->parent == &ldb_di_clk[clk->id]) && cpu_is_mx53())
+ return clk->parent->rate;
+ else {
+ div = clk->parent->rate / rate;
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+ return clk->parent->rate / div;
+ }
}
static struct clk ipu_di_clk[] = {
@@ -1550,6 +1621,128 @@ static struct clk ipu_di_clk[] = {
},
};
+static int _clk_ldb_di_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+
+ if ((parent == &pll3_sw_clk)) {
+ if (clk->id == 0)
+ reg &= ~(MXC_CCM_CSCMR2_LDB_DI0_CLK_SEL);
+ else
+ reg &= ~(MXC_CCM_CSCMR2_LDB_DI1_CLK_SEL);
+ } else if ((parent == &pll4_sw_clk)) {
+ if (clk->id == 0)
+ reg |= MXC_CCM_CSCMR2_LDB_DI0_CLK_SEL;
+ else
+ reg |= MXC_CCM_CSCMR2_LDB_DI1_CLK_SEL;
+ } else {
+ BUG();
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+ return 0;
+}
+
+static void _clk_ldb_di_recalc(struct clk *clk)
+{
+ u32 div;
+
+ if (clk->id == 0)
+ div = __raw_readl(MXC_CCM_CSCMR2) &
+ MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
+ else
+ div = __raw_readl(MXC_CCM_CSCMR2) &
+ MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
+
+ if (div)
+ clk->rate = clk->parent->rate / 7;
+ else
+ clk->rate = 2 * clk->parent->rate / 7;
+}
+
+static unsigned long _clk_ldb_di_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ if (rate * 7 <= clk->parent->rate)
+ return clk->parent->rate / 7;
+ else
+ return 2 * clk->parent->rate / 7;
+}
+
+static int _clk_ldb_di_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div = 0;
+
+ if (rate * 7 <= clk->parent->rate) {
+ div = 7;
+ rate = clk->parent->rate / 7;
+ } else
+ rate = 2 * clk->parent->rate / 7;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ if (div == 7)
+ reg |= (clk->id ? MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV :
+ MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+ else
+ reg &= ~(clk->id ? MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV :
+ MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ clk->rate = rate;
+ return 0;
+}
+
+static int _clk_ldb_di_enable(struct clk *clk)
+{
+ _clk_enable(clk);
+ ipu_di_clk[clk->id].set_parent(&ipu_di_clk[clk->id], clk);
+ ipu_di_clk[clk->id].parent = clk;
+ ipu_di_clk[clk->id].rate = clk->rate;
+ ipu_di_clk[clk->id].enable(&ipu_di_clk[clk->id]);
+ ipu_di_clk[clk->id].usecount++;
+ return 0;
+}
+
+static void _clk_ldb_di_disable(struct clk *clk)
+{
+ _clk_disable(clk);
+ ipu_di_clk[clk->id].disable(&ipu_di_clk[clk->id]);
+ ipu_di_clk[clk->id].usecount--;
+}
+
+static struct clk ldb_di_clk[] = {
+ {
+ .name = "ldb_di0_clk",
+ .id = 0,
+ .parent = &pll4_sw_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGR6_CG14_OFFSET,
+ .recalc = _clk_ldb_di_recalc,
+ .set_parent = _clk_ldb_di_set_parent,
+ .round_rate = _clk_ldb_di_round_rate,
+ .set_rate = _clk_ldb_di_set_rate,
+ .enable = _clk_ldb_di_enable,
+ .disable = _clk_ldb_di_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT,
+ },
+ {
+ .name = "ldb_di1_clk",
+ .id = 1,
+ .parent = &pll4_sw_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGR6_CG15_OFFSET,
+ .recalc = _clk_ldb_di_recalc,
+ .set_parent = _clk_ldb_di_set_parent,
+ .round_rate = _clk_ldb_di_round_rate,
+ .set_rate = _clk_ldb_di_set_rate,
+ .enable = _clk_ldb_di_enable,
+ .disable = _clk_ldb_di_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT,
+ },
+};
+
static int _clk_csi0_set_parent(struct clk *clk, struct clk *parent)
{
u32 reg, mux;
@@ -2060,28 +2253,6 @@ static struct clk uart5_clk[] = {
},
};
-static struct clk esai_clk[] = {
- {
- .name = "esai_clk",
- .id = 2,
- .parent = &pll3_sw_clk,
- .secondary = &esai_clk[1],
- .enable_reg = MXC_CCM_CCGR6,
- .enable_shift = MXC_CCM_CCGR6_CG9_OFFSET,
- .enable = _clk_enable,
- .disable = _clk_disable,
- },
- {
- .name = "esai_ipg_clk",
- .id = 2,
- .parent = &pll3_sw_clk,
- .enable_reg = MXC_CCM_CCGR6,
- .enable_shift = MXC_CCM_CCGR6_CG8_OFFSET,
- .enable = _clk_enable,
- .disable = _clk_disable,
- },
-};
-
static struct clk gpt_clk[] = {
{
.name = "gpt_clk",
@@ -2311,23 +2482,15 @@ static struct clk cspi2_clk[] = {
},
};
-static struct clk cspi3_clk[] = {
- {
- .name = "cspi_clk",
- .id = 2,
- .parent = &cspi_main_clk,
- .enable_reg = MXC_CCM_CCGR4,
- .enable_shift = MXC_CCM_CCGR4_CG13_OFFSET,
- .enable = _clk_enable,
- .disable = _clk_disable,
- .secondary = &cspi3_clk[1],
- },
- {
- .name = "cspi_ipg_clk",
- .id = 2,
- .parent = &ipg_clk,
- .secondary = &aips_tz2_clk,
- },
+static struct clk cspi3_clk = {
+ .name = "cspi_ipg_clk",
+ .id = 2,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGR4_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &aips_tz2_clk,
};
static int _clk_ssi_lp_apm_set_parent(struct clk *clk, struct clk *parent)
@@ -2612,6 +2775,83 @@ static struct clk ssi_ext2_clk = {
.disable = _clk_disable,
};
+static int _clk_esai_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ if (parent == &pll1_sw_clk || parent == &pll2_sw_clk ||
+ parent == &pll3_sw_clk) {
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ NULL);
+ reg &= ~MXC_CCM_CSCMR2_ESAI_PRE_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR2_ESAI_PRE_SEL_OFFSET;
+ reg &= ~MXC_CCM_CSCMR2_ESAI_POST_SEL_MASK;
+ reg |= 0 << MXC_CCM_CSCMR2_ESAI_POST_SEL_OFFSET;
+ /* divider setting */
+ } else {
+ mux = _get_mux(parent, &ssi1_clk[0], &ssi2_clk[0], &ckih_clk,
+ &ckih2_clk);
+ reg &= ~MXC_CCM_CSCMR2_ESAI_POST_SEL_MASK;
+ reg |= (mux + 1) << MXC_CCM_CSCMR2_ESAI_POST_SEL_OFFSET;
+ /* divider setting */
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ /* set podf = 0 */
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK;
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+static void _clk_esai_recalc(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ if (clk->parent == &pll1_sw_clk || clk->parent == &pll2_sw_clk ||
+ clk->parent == &pll3_sw_clk) {
+ pred = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+ clk->rate = clk->parent->rate / (pred * podf);
+ } else {
+ podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+ clk->rate = clk->parent->rate / podf;
+ }
+}
+
+static struct clk esai_clk[] = {
+ {
+ .name = "esai_clk",
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_esai_set_parent,
+ .recalc = _clk_esai_recalc,
+ .secondary = &esai_clk[1],
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGR6_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .name = "esai_ipg_clk",
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGR6_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
static struct clk iim_clk = {
.name = "iim_clk",
.parent = &ipg_clk,
@@ -3135,51 +3375,63 @@ static struct clk ieee_1588_clk = {
.disable = _clk_disable,
};
-static struct clk mlb_clk = {
+static struct clk mlb_clk[] = {
+ {
.name = "mlb_clk",
.parent = &ipg_clk,
.enable = _clk_enable,
.enable_reg = MXC_CCM_CCGR7,
.enable_shift = MXC_CCM_CCGR7_CG2_OFFSET,
.disable = _clk_disable,
+ .secondary = &mlb_clk[1],
+ },
+ {
+ .name = "mlb_mem_clk",
+ .parent = &emi_fast_clk,
+ .secondary = &emi_intr_clk[1],
+ },
};
static struct clk can1_clk[] = {
{
- .name = "can1_clk",
- .parent = &pll3_sw_clk,
- .secondary = &can1_clk[1],
+ .name = "can_clk",
+ .id = 0,
+ .parent = &ipg_clk,
.enable = _clk_enable,
+ .secondary = &can1_clk[1],
.enable_reg = MXC_CCM_CCGR6,
- .enable_shift = MXC_CCM_CCGR6_CG11_OFFSET,
+ .enable_shift = MXC_CCM_CCGR6_CG10_OFFSET,
.disable = _clk_disable,
},
{
- .name = "can1_ipg_clk",
- .parent = &ipg_clk,
+ .name = "can_cpi_clk",
+ .id = 0,
+ .parent = &lp_apm_clk,
.enable = _clk_enable,
.enable_reg = MXC_CCM_CCGR6,
- .enable_shift = MXC_CCM_CCGR6_CG10_OFFSET,
+ .enable_shift = MXC_CCM_CCGR6_CG11_OFFSET,
.disable = _clk_disable,
},
};
static struct clk can2_clk[] = {
{
- .name = "can2_clk",
- .parent = &pll3_sw_clk,
- .secondary = &can2_clk[1],
+ .name = "can_clk",
+ .id = 1,
+ .parent = &ipg_clk,
.enable = _clk_enable,
+ .secondary = &can2_clk[1],
.enable_reg = MXC_CCM_CCGR4,
- .enable_shift = MXC_CCM_CCGR4_CG4_OFFSET,
+ .enable_shift = MXC_CCM_CCGR4_CG3_OFFSET,
.disable = _clk_disable,
},
{
- .name = "can2_ipg_clk",
- .parent = &ipg_clk,
+ .name = "can_cpi_clk",
+ .id = 1,
+ .parent = &lp_apm_clk,
.enable = _clk_enable,
.enable_reg = MXC_CCM_CCGR4,
- .enable_shift = MXC_CCM_CCGR4_CG3_OFFSET,
+ .enable_shift = MXC_CCM_CCGR4_CG4_OFFSET,
.disable = _clk_disable,
},
};
@@ -3680,7 +3932,6 @@ static struct clk pgc_clk = {
};
/*usb OTG clock */
-
static struct clk usb_clk = {
.name = "usb_clk",
.rate = 60000000,
@@ -3716,7 +3967,8 @@ static struct clk ata_clk = {
};
static struct clk owire_clk = {
- .name = "owire_clk",
+ /* 1w driver come from upstream and use owire as clock name*/
+ .name = "owire",
.parent = &ipg_perclk,
.enable = _clk_enable,
.enable_reg = MXC_CCM_CCGR2,
@@ -3796,16 +4048,6 @@ static int _clk_gpu3d_set_parent(struct clk *clk, struct clk *parent)
return 0;
}
-static struct clk gpu3d_clk = {
- .name = "gpu3d_clk",
- .parent = &axi_a_clk,
- .set_parent = _clk_gpu3d_set_parent,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CCGR5,
- .enable_shift = MXC_CCM_CCGR5_CG1_OFFSET,
- .disable = _clk_disable,
- .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
-};
static struct clk garb_clk = {
.name = "garb_clk",
@@ -3816,13 +4058,16 @@ static struct clk garb_clk = {
.disable = _clk_disable,
};
-static struct clk emi_garb_clk = {
- .name = "emi_garb_clk",
+static struct clk gpu3d_clk = {
+ .name = "gpu3d_clk",
.parent = &axi_a_clk,
+ .set_parent = _clk_gpu3d_set_parent,
.enable = _clk_enable,
- .enable_reg = MXC_CCM_CCGR6,
- .enable_shift = MXC_CCM_CCGR6_CG4_OFFSET,
- .disable = _clk_disable_inwait,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGR5_CG1_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ .secondary = &garb_clk,
};
static int _clk_gpu2d_set_parent(struct clk *clk, struct clk *parent)
@@ -4008,8 +4253,7 @@ static struct clk *mxc_clks[] = {
&cspi1_clk[1],
&cspi2_clk[0],
&cspi2_clk[1],
- &cspi3_clk[0],
- &cspi3_clk[1],
+ &cspi3_clk,
&ssi_lp_apm_clk,
&ssi1_clk[0],
&ssi1_clk[1],
@@ -4043,6 +4287,7 @@ static struct clk *mxc_clks[] = {
&emi_enfc_clk,
&emi_fast_clk,
&emi_intr_clk[0],
+ &emi_intr_clk[1],
&spdif_xtal_clk,
&spdif0_clk[0],
&spdif0_clk[1],
@@ -4111,9 +4356,6 @@ static void clk_tree_init(void)
pll4_sw_clk.parent = &osc_clk;
}
- if (cpu_is_mx53())
- tve_clk.parent = &pll4_sw_clk;
-
/* set emi_slow_clk parent */
emi_slow_clk.parent = &main_bus_clk;
reg = __raw_readl(MXC_CCM_CBCDR);
@@ -4191,6 +4433,7 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
esdhc2_clk[0].recalc = _clk_esdhc2_recalc;
esdhc2_clk[0].set_rate = _clk_esdhc2_set_rate;
+ emi_intr_clk[1].name = "emi_garb_clk";
clk_tree_init();
for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
@@ -4209,7 +4452,9 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
clk_register(&spdif1_clk[0]);
clk_register(&spdif1_clk[1]);
clk_register(&ddr_hf_clk);
- clk_register(&emi_garb_clk);
+
+ max_axi_a_clk = MAX_AXI_A_CLK_MX51;
+ max_axi_b_clk = MAX_AXI_B_CLK_MX51;
/* set DDR clock parent */
reg = 0;
@@ -4261,8 +4506,10 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
propagate_rate(&pll1_sw_clk);
propagate_rate(&pll2_sw_clk);
+#ifndef CONFIG_LATE_CPU_CLK_ENABLE
+ /* See comment below where cpu_clk is enabled for further information */
clk_enable(&cpu_clk);
-
+#endif
/* Set SDHC parents to be PLL2 */
clk_set_parent(&esdhc1_clk[0], &pll2_sw_clk);
clk_set_parent(&esdhc2_clk[0], &pll2_sw_clk);
@@ -4396,13 +4643,6 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
if (i > cpu_wp_nr)
BUG();
- /*Allow for automatic gating of the EMI internal clock.
- * If this is done, emi_intr CCGR bits should be set to 11.
- */
- reg = __raw_readl((IO_ADDRESS(M4IF_BASE_ADDR) + 0x8c));
- reg &= ~0x1;
- __raw_writel(reg, (IO_ADDRESS(M4IF_BASE_ADDR) + 0x8c));
-
clk_set_parent(&arm_axi_clk, &axi_a_clk);
clk_set_parent(&ipu_clk[0], &axi_b_clk);
@@ -4418,8 +4658,8 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
(0 << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET);
__raw_writel(reg, MXC_CCM_CSCDR1);
} else {
- /* Move UART to run from PLL1 */
- clk_set_parent(&uart_main_clk, &pll1_sw_clk);
+ /* Move UART to run from PLL2 */
+ clk_set_parent(&uart_main_clk, &pll2_sw_clk);
/* Set the UART dividers to divide,
* so the UART_CLK is 66.5MHz.
@@ -4427,7 +4667,7 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
reg = __raw_readl(MXC_CCM_CSCDR1);
reg &= ~MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
reg &= ~MXC_CCM_CSCDR1_UART_CLK_PRED_MASK;
- reg |= (5 << MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) |
+ reg |= (4 << MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) |
(1 << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET);
__raw_writel(reg, MXC_CCM_CSCDR1);
}
@@ -4446,6 +4686,15 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
base = ioremap(GPT1_BASE_ADDR, SZ_4K);
mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT);
+#ifdef CONFIG_LATE_CPU_CLK_ENABLE
+ /**
+ * Late enable of the cpu clock. This is causing a random crash at boot
+ * time on the ConnectCore Wi-i.MX51. Enabling the cpu clock here seems
+ * to work around the problem. Must be in order to better understand the
+ * reason of the problem and the real solution to the problem.
+ */
+ clk_enable(&cpu_clk);
+#endif
return 0;
}
@@ -4493,15 +4742,15 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
1 << MXC_CCM_CCGR5_CG6_OFFSET |
3 << MXC_CCM_CCGR5_CG7_OFFSET |
1 << MXC_CCM_CCGR5_CG8_OFFSET |
- 3 << MXC_CCM_CCGR5_CG9_OFFSET |
+ 1 << MXC_CCM_CCGR5_CG9_OFFSET |
1 << MXC_CCM_CCGR5_CG10_OFFSET |
3 << MXC_CCM_CCGR5_CG11_OFFSET, MXC_CCM_CCGR5);
- __raw_writel(3 << MXC_CCM_CCGR6_CG0_OFFSET |
+ __raw_writel(1 << MXC_CCM_CCGR6_CG0_OFFSET |
3 << MXC_CCM_CCGR6_CG1_OFFSET |
- 3 << MXC_CCM_CCGR6_CG4_OFFSET |
- 3 << MXC_CCM_CCGR6_CG8_OFFSET |
- 3 << MXC_CCM_CCGR6_CG9_OFFSET |
+ 1 << MXC_CCM_CCGR6_CG4_OFFSET |
+ 1 << MXC_CCM_CCGR6_CG8_OFFSET |
+ 1 << MXC_CCM_CCGR6_CG9_OFFSET |
3 << MXC_CCM_CCGR6_CG12_OFFSET |
3 << MXC_CCM_CCGR6_CG13_OFFSET , MXC_CCM_CCGR6);
@@ -4544,7 +4793,6 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
clk_register(*clkp);
clk_register(&pll4_sw_clk);
- clk_register(&emi_intr_clk[1]);
clk_register(&uart4_clk[0]);
clk_register(&uart4_clk[1]);
clk_register(&uart5_clk[0]);
@@ -4554,7 +4802,21 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
clk_register(&ocram_clk);
clk_register(&sata_clk);
clk_register(&ieee_1588_clk);
- clk_register(&mlb_clk);
+ clk_register(&mlb_clk[0]);
+ clk_register(&can1_clk[0]);
+ clk_register(&can2_clk[0]);
+ clk_register(&ldb_di_clk[0]);
+ clk_register(&ldb_di_clk[1]);
+ /* OSC of 22.5792M or 24.576M for ESAI */
+ clk_register(&esai_clk[0]);
+ clk_set_parent(&esai_clk[0], &ckih_clk);
+ clk_register(&esai_clk[1]);
+
+ ldb_di_clk[0].parent = ldb_di_clk[1].parent =
+ tve_clk.parent = &pll4_sw_clk;
+
+ max_axi_a_clk = MAX_AXI_A_CLK_MX53;
+ max_axi_b_clk = MAX_AXI_B_CLK_MX53;
/* set DDR clock parent */
reg = __raw_readl(MXC_CCM_CBCMR) &
@@ -4575,6 +4837,8 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
clk_set_parent(&esdhc2_clk[0], &esdhc1_clk[0]);
clk_set_parent(&esdhc3_clk[0], &pll2_sw_clk);
+ clk_set_parent(&ipu_di_clk[0], &pll4_sw_clk);
+
#if 0
/*Setup the LPM bypass bits */
reg = __raw_readl(MXC_CCM_CLPCR);
@@ -4585,13 +4849,6 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
__raw_writel(reg, MXC_CCM_CLPCR);
#endif
- /* Disable the handshake with HSC block as its not
- * initialised right now.
- */
- reg = __raw_readl(MXC_CCM_CCDR);
- reg |= MXC_CCM_CCDR_EMI_HS_MASK;
- __raw_writel(reg, MXC_CCM_CCDR);
-
/* This will propagate to all children and init all the clock rates */
propagate_rate(&osc_clk);
propagate_rate(&ckih_clk);
@@ -4605,14 +4862,15 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long
clk_enable(&main_bus_clk);
+ /* Set AXI_B_CLK to be 200MHz */
+ clk_set_rate(&axi_b_clk, 200000000);
+
/* Initialise the parents to be axi_b, parents are set to
* axi_a when the clocks are enabled.
*/
clk_set_parent(&vpu_clk[0], &axi_b_clk);
clk_set_parent(&vpu_clk[1], &axi_b_clk);
- clk_set_parent(&gpu3d_clk, &axi_a_clk);
- clk_set_parent(&gpu2d_clk, &axi_a_clk);
/* move cspi to 24MHz */
clk_set_parent(&cspi_main_clk, &lp_apm_clk);
@@ -4797,27 +5055,27 @@ static int cpu_clk_set_wp(int wp)
__raw_writel(reg, MXC_CCM_CCSR);
/* Stop the PLL */
- reg = __raw_readl(MXC_DPLL1_BASE + MXC_PLL_DP_CTL);
+ reg = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
reg &= ~MXC_PLL_DP_CTL_UPEN;
- __raw_writel(reg, MXC_DPLL1_BASE + MXC_PLL_DP_CTL);
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
/* PDF and MFI */
reg = p->pdf | p->mfi << MXC_PLL_DP_OP_MFI_OFFSET;
- __raw_writel(reg, MXC_DPLL1_BASE + MXC_PLL_DP_OP);
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_OP);
/* MFD */
- __raw_writel(p->mfd, MXC_DPLL1_BASE + MXC_PLL_DP_MFD);
+ __raw_writel(p->mfd, pll1_base + MXC_PLL_DP_MFD);
/* MFI */
- __raw_writel(p->mfn, MXC_DPLL1_BASE + MXC_PLL_DP_MFN);
+ __raw_writel(p->mfn, pll1_base + MXC_PLL_DP_MFN);
- reg = __raw_readl(MXC_DPLL1_BASE + MXC_PLL_DP_CTL);
+ reg = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
reg |= MXC_PLL_DP_CTL_UPEN;
/* Set the UPEN bits */
- __raw_writel(reg, MXC_DPLL1_BASE + MXC_PLL_DP_CTL);
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
/* Forcefully restart the PLL */
reg |= MXC_PLL_DP_CTL_RST;
- __raw_writel(reg, MXC_DPLL1_BASE + MXC_PLL_DP_CTL);
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
/* Wait for the PLL to lock */
getnstimeofday(&nstimeofday);
@@ -4825,7 +5083,7 @@ static int cpu_clk_set_wp(int wp)
getnstimeofday(&curtime);
if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY)
panic("pll1 relock failed\n");
- stat = __raw_readl(MXC_DPLL1_BASE + MXC_PLL_DP_CTL) &
+ stat = __raw_readl(pll1_base + MXC_PLL_DP_CTL) &
MXC_PLL_DP_CTL_LRF;
} while (!stat);