summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorTerry Lv <r65388@freescale.com>2010-11-17 15:37:49 +0800
committerTerry <r65388@freescale.com>2010-12-14 17:20:40 +0800
commitdca35697e3758ac81894ca305c3f206ff552b697 (patch)
tree02cd77b87c58ea0b0a97d9964a1f869b32e0987f /cpu
parentbb24c00fe03c58f9695b0f68e51f35c6c5982746 (diff)
downloadu-boot-imx-dca35697e3758ac81894ca305c3f206ff552b697.zip
u-boot-imx-dca35697e3758ac81894ca305c3f206ff552b697.tar.gz
u-boot-imx-dca35697e3758ac81894ca305c3f206ff552b697.tar.bz2
ENGR00133727: uart outputs messy code when kernel starts on mx51
uart outputs messy code when kernel starts on mx51. Change uart clock to use pll2 as source clock. Signed-off-by: Terry Lv <r65388@freescale.com>
Diffstat (limited to 'cpu')
-rw-r--r--cpu/arm_cortexa8/mx51/generic.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/cpu/arm_cortexa8/mx51/generic.c b/cpu/arm_cortexa8/mx51/generic.c
index d02bc5f..c26f8ea 100644
--- a/cpu/arm_cortexa8/mx51/generic.c
+++ b/cpu/arm_cortexa8/mx51/generic.c
@@ -562,6 +562,28 @@ int clk_info(u32 clk_type)
(tmp - 1); \
})
+#define calc_pred_n_podf(target_clk, src_clk, p_pred, p_podf, pred_limit, podf_limit) { \
+ u32 div = calc_div(target_clk, src_clk, \
+ pred_limit * podf_limit); \
+ u32 tmp = 0, tmp_i = 0, tmp_j = 0; \
+ if (div > (pred_limit * podf_limit)) {\
+ tmp_i = pred_limit; \
+ tmp_j = podf_limit; \
+ } \
+ for (tmp_i = 1; tmp_i <= pred_limit; ++tmp_i) { \
+ for (tmp_j = 1; tmp_j <= podf_limit; ++tmp_j) { \
+ if (div == (tmp_i * tmp_j)) { \
+ tmp = 1; \
+ break; \
+ } \
+ } \
+ if (1 == tmp) \
+ break; \
+ } \
+ *p_pred = tmp_j - 1; \
+ *p_podf = tmp_i - 1; \
+ }
+
static u32 calc_per_cbcdr_val(u32 per_clk, u32 cbcmr)
{
u32 cbcdr = __REG(MXC_CCM_CBCDR);
@@ -599,6 +621,29 @@ static u32 calc_per_cbcdr_val(u32 per_clk, u32 cbcmr)
return cbcdr;
}
+static u32 calc_per_cscdr1_val(u32 per_clk)
+{
+ u32 cscdr1 = __REG(MXC_CCM_CSCDR1);
+ u32 tmp_clk = 0, pred, podf;
+
+ /*
+ * Currently, most clocks in scsmr1 will use pll3 as clock source,
+ * except uart.
+ * So we will just adjust uart clock here.
+ */
+ tmp_clk = __get_uart_clk();
+ calc_pred_n_podf(tmp_clk, per_clk, &pred, &podf, 8, 8);
+
+ cscdr1 &=
+ !(MXC_CCM_CSCDR1_UART_CLK_PRED_MASK
+ | MXC_CCM_CSCDR1_UART_CLK_PODF_MASK);
+
+ cscdr1 |= (pred << MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET);
+ cscdr1 |= (podf << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET);
+
+ return cscdr1;
+}
+
#define CHANGE_PLL_SETTINGS(base, pd, mfi, mfn, mfd) \
{ \
writel(0x1232, base + PLL_DP_CTL); \
@@ -732,8 +777,21 @@ static int config_periph_clk(u32 ref, u32 freq)
return -1;
}
} else {
+ u32 pll3_freq = __decode_pll(PLL3_CLK, CONFIG_MX51_HCLK_FREQ);
+ u32 old_pll2_freq =
+ __decode_pll(PLL2_CLK, CONFIG_MX51_HCLK_FREQ);
u32 old_cbcmr = readl(CCM_BASE_ADDR + CLKCTL_CBCMR);
u32 new_cbcdr = calc_per_cbcdr_val(pll, old_cbcmr);
+ u32 new_cscdr1 = calc_per_cscdr1_val(pll);
+
+ /* Set PLL3 to PLL2 freq */
+ ret = calc_pll_params(ref, old_pll2_freq, &pll_param);
+ if (ret != 0) {
+ printf("Can't find pll parameters: %d\n",
+ ret);
+ return ret;
+ }
+ config_pll_clk(PLL3_CLK, &pll_param);
/* Switch peripheral to PLL3 */
/* Disable IPU and HSC dividers */
@@ -760,11 +818,22 @@ static int config_periph_clk(u32 ref, u32 freq)
writel(0x60000, CCM_BASE_ADDR + CLKCTL_CCDR);
writel(new_cbcdr, CCM_BASE_ADDR + CLKCTL_CBCDR);
writel(old_cbcmr, CCM_BASE_ADDR + CLKCTL_CBCMR);
+ writel(new_cscdr1, CCM_BASE_ADDR + CLKCTL_CSCDR1);
+
+ /* Switch PLL3's freq back */
+ ret = calc_pll_params(ref, pll3_freq, &pll_param);
+ if (ret != 0) {
+ printf("Can't find pll parameters: %d\n",
+ ret);
+ return ret;
+ }
+ config_pll_clk(PLL3_CLK, &pll_param);
/* Make sure change is effective */
while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0)
;
writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR);
+
puts("\n");
}