From 3d6e614952e3e4cf9e70e58893a740ffec220b24 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 12 Aug 2010 15:10:53 +0200 Subject: mx35: Fix boot ROM hang in internal boot mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a watchdog reset occurs after booting in internal boot mode, the i.MX35 won't boot anymore. The boot ROM code seems to assume that some clocks are turned on (they are after a power-on reset). This patch turns on the necessary clocks. Signed-off-by: Hans J. Koch Acked-by: Uwe Kleine-König Reported-by: John Ogness Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-mx3/clock-imx35.c') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index d3af0fdf847..32adf8d5b1f 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -485,10 +485,10 @@ static struct clk_lookup lookups[] = { int __init mx35_clocks_init() { - unsigned int ll = 0; + unsigned int cgr2 = 3 << 26, cgr3 = 0; #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) - ll = (3 << 16); + cgr2 |= 3 << 16; #endif clkdev_add_table(lookups, ARRAY_SIZE(lookups)); @@ -499,8 +499,20 @@ int __init mx35_clocks_init() __raw_writel((3 << 18), CCM_BASE + CCM_CGR0); __raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16), CCM_BASE + CCM_CGR1); - __raw_writel((3 << 26) | ll, CCM_BASE + CCM_CGR2); - __raw_writel(0, CCM_BASE + CCM_CGR3); + + /* + * Check if we came up in internal boot mode. If yes, we need some + * extra clocks turned on, otherwise the MX35 boot ROM code will + * hang after a watchdog reset. + */ + if (!(__raw_readl(CCM_BASE + CCM_RCSR) & (3 << 10))) { + /* Additionally turn on UART1, SCC, and IIM clocks */ + cgr2 |= 3 << 16 | 3 << 4; + cgr3 |= 3 << 2; + } + + __raw_writel(cgr2, CCM_BASE + CCM_CGR2); + __raw_writel(cgr3, CCM_BASE + CCM_CGR3); mxc_timer_init(&gpt_clk, MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT); -- cgit v1.2.3-70-g09d2 From 9a6f17fd1cd84811962735ff47111f84a8f05073 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 22 Apr 2010 12:37:13 +0200 Subject: i.MX35: remove get_3_3_div helper function In the v2 reference manual there are no dividers combined of two dividers. Instead, all dividers are simple 6bit dividers. I assume the combined dividers only exist in preliminary hardware. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'arch/arm/mach-mx3/clock-imx35.c') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 32adf8d5b1f..d3a8d3f3216 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -176,16 +176,11 @@ static unsigned long get_rate_ipg(struct clk *clk) return get_rate_ahb(NULL) >> 1; } -static unsigned long get_3_3_div(unsigned long in) -{ - return (((in >> 3) & 0x7) + 1) * ((in & 0x7) + 1); -} - static unsigned long get_rate_uart(struct clk *clk) { unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3); unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4); - unsigned long div = get_3_3_div(pdr4 >> 10); + unsigned long div = ((pdr4 >> 10) & 0x3f) + 1; if (pdr3 & (1 << 14)) return get_rate_arm() / div; @@ -216,7 +211,7 @@ static unsigned long get_rate_sdhc(struct clk *clk) break; } - return rate / get_3_3_div(div); + return rate / (div + 1); } static unsigned long get_rate_mshc(struct clk *clk) @@ -270,7 +265,7 @@ static unsigned long get_rate_csi(struct clk *clk) else rate = get_rate_ppll(); - return rate / get_3_3_div((pdr2 >> 16) & 0x3f); + return rate / (((pdr2 >> 16) & 0x3f) + 1); } static unsigned long get_rate_otg(struct clk *clk) @@ -283,22 +278,21 @@ static unsigned long get_rate_otg(struct clk *clk) else rate = get_rate_ppll(); - return rate / get_3_3_div((pdr4 >> 22) & 0x3f); + return rate / (((pdr4 >> 22) & 0x3f) + 1); } static unsigned long get_rate_ipg_per(struct clk *clk) { unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0); unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4); - unsigned long div1, div2; + unsigned long div; if (pdr0 & (1 << 26)) { - div1 = (pdr4 >> 19) & 0x7; - div2 = (pdr4 >> 16) & 0x7; - return get_rate_arm() / ((div1 + 1) * (div2 + 1)); + div = (pdr4 >> 16) & 0x3f; + return get_rate_arm() / (div + 1); } else { - div1 = (pdr0 >> 12) & 0x7; - return get_rate_ahb(NULL) / div1; + div = (pdr0 >> 12) & 0x7; + return get_rate_ahb(NULL) / div; } } -- cgit v1.2.3-70-g09d2 From c96c1e394fa72bd995154af7143873945a3fa89d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 16 Aug 2010 15:54:05 +0200 Subject: clock-imx35: fix divider if ahb is source for ipg_per According to the Datasheet: "i.MX35 (MCIMX35) Multimedia Applications Processor Reference Manual, Rev. 2" "Table 14-6. PDR0 Field Descriptions" the divider is CCM_PER_AHB[3:0] + 1. This patch adds the missing + 1. Signed-off-by: Marc Kleine-Budde Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-mx3/clock-imx35.c') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index d3a8d3f3216..e582ceb6e0c 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -292,7 +292,7 @@ static unsigned long get_rate_ipg_per(struct clk *clk) return get_rate_arm() / (div + 1); } else { div = (pdr0 >> 12) & 0x7; - return get_rate_ahb(NULL) / div; + return get_rate_ahb(NULL) / (div + 1); } } -- cgit v1.2.3-70-g09d2 From c56702de106b4fde301282f7ea60412276481442 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 16 Aug 2010 15:54:06 +0200 Subject: clock-imx35: correct arm and ahb clock calculation According to the Datasheet: "i.MX35 (MCIMX35) Multimedia Applications Processor Reference Manual, Rev. 2" "Figure 14-24. Clock Control And Gating" change the result of get_rate_ahb based on the frequency returned by get_rate_arm to calculate the proper rate. Signed-off-by: Marc Kleine-Budde Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-mx3/clock-imx35.c') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index e582ceb6e0c..1d311b77b40 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -155,7 +155,7 @@ static unsigned long get_rate_arm(void) aad = &clk_consumer[(pdr0 >> 16) & 0xf]; if (aad->sel) - fref = fref * 2 / 3; + fref = fref * 3 / 4; return fref / aad->arm; } @@ -164,7 +164,7 @@ static unsigned long get_rate_ahb(struct clk *clk) { unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0); struct arm_ahb_div *aad; - unsigned long fref = get_rate_mpll(); + unsigned long fref = get_rate_arm(); aad = &clk_consumer[(pdr0 >> 16) & 0xf]; -- cgit v1.2.3-70-g09d2 From c735c40587cea45f9d2f83339f374595073c1923 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 16 Aug 2010 15:54:07 +0200 Subject: clock-imx35: Calculate the base clock rate for the IPU unit The mx3fb driver needs the clock the IPU runs in order to calculate the divider for the LCD clock. This patch adds the clock rate calculation routine for the i.MX35 CPU. Signed-off-by: Juergen Beisert Signed-off-by: Michael Grzeschik Signed-off-by: Sascha Hauer --- arch/arm/mach-mx3/clock-imx35.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-mx3/clock-imx35.c') diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 1d311b77b40..7a62e744a8b 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -296,6 +296,33 @@ static unsigned long get_rate_ipg_per(struct clk *clk) } } +static unsigned long get_rate_hsp(struct clk *clk) +{ + unsigned long hsp_podf = (__raw_readl(CCM_BASE + CCM_PDR0) >> 20) & 0x03; + unsigned long fref = get_rate_mpll(); + + if (fref > 400 * 1000 * 1000) { + switch (hsp_podf) { + case 0: + return fref >> 2; + case 1: + return fref >> 3; + case 2: + return fref / 3; + } + } else { + switch (hsp_podf) { + case 0: + case 2: + return fref / 3; + case 1: + return fref / 6; + } + } + + return 0; +} + static int clk_cgr_enable(struct clk *clk) { u32 reg; @@ -353,7 +380,7 @@ DEFINE_CLOCK(i2c1_clk, 0, CCM_CGR1, 10, get_rate_ipg_per, NULL); DEFINE_CLOCK(i2c2_clk, 1, CCM_CGR1, 12, get_rate_ipg_per, NULL); DEFINE_CLOCK(i2c3_clk, 2, CCM_CGR1, 14, get_rate_ipg_per, NULL); DEFINE_CLOCK(iomuxc_clk, 0, CCM_CGR1, 16, NULL, NULL); -DEFINE_CLOCK(ipu_clk, 0, CCM_CGR1, 18, get_rate_ahb, NULL); +DEFINE_CLOCK(ipu_clk, 0, CCM_CGR1, 18, get_rate_hsp, NULL); DEFINE_CLOCK(kpp_clk, 0, CCM_CGR1, 20, get_rate_ipg, NULL); DEFINE_CLOCK(mlb_clk, 0, CCM_CGR1, 22, get_rate_ahb, NULL); DEFINE_CLOCK(mshc_clk, 0, CCM_CGR1, 24, get_rate_mshc, NULL); -- cgit v1.2.3-70-g09d2