From 30d913556b25db11f2537f4412487c6e81dc0374 Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Thu, 17 Feb 2011 16:42:51 +0100 Subject: arm: tcc8k: Add missing include If NAND is enabled we better have the include around. Signed-off-by: Oskar Schirmer Signed-off-by: Thomas Gleixner --- arch/arm/mach-tcc8k/board-tcc8000-sdk.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/mach-tcc8k') diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c index 7991415e666b..a3b66d405eb3 100644 --- a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c +++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c @@ -17,6 +17,7 @@ #include #include +#include #include "common.h" -- cgit v1.2.3 From 85922e54a3a14a6aee6c0b1fc67d81ef0c60fc9c Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Thu, 17 Feb 2011 16:42:58 +0100 Subject: arm: tcc8k: Choose PLL settings conforming to board layout The evaluation board is driven with 1.2V core voltage, so system clock must not exceed 192 MHz, bus clock must not exceed 110 MHz. Choose appropriate values and set DTCMWAIT accordingly. Adapt UART setting to avoid console log interruption and wait for the specified locking time of 300us to pass. Signed-off-by: Oskar Schirmer Cc: bigeasy@linutronix.de Signed-off-by: Thomas Gleixner --- arch/arm/mach-tcc8k/board-tcc8000-sdk.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch/arm/mach-tcc8k') diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c index a3b66d405eb3..c25cf3f84566 100644 --- a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c +++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c @@ -6,6 +6,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -18,6 +19,7 @@ #include #include +#include #include "common.h" @@ -52,6 +54,22 @@ static struct sys_timer tcc8k_timer = { static void __init tcc8k_map_io(void) { tcc8k_map_common_io(); + + /* set PLL0 clock to 96MHz, adapt UART0 divisor */ + __raw_writel(0x00026003, CKC_BASE + PLL0CFG_OFFS); + __raw_writel(0x10000001, CKC_BASE + ACLKUART0_OFFS); + + /* set PLL1 clock to 192MHz */ + __raw_writel(0x00016003, CKC_BASE + PLL1CFG_OFFS); + + /* set PLL2 clock to 48MHz */ + __raw_writel(0x00036003, CKC_BASE + PLL2CFG_OFFS); + + /* with CPU freq higher than 150 MHz, need extra DTCM wait */ + __raw_writel(0x00000001, SCFG_BASE + DTCMWAIT_OFFS); + + /* PLL locking time as specified */ + udelay(300); } MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board") -- cgit v1.2.3 From fe03a9f7bb89e920e60fd1bb074adab2eed2bf48 Mon Sep 17 00:00:00 2001 From: Hans J. Koch Date: Thu, 17 Feb 2011 16:42:59 +0100 Subject: arm: tcc8k: Fix clock rate calculation The calculation of the best divider value for a requested clock rate always returned a value that was slightly too large. It was also not protected against possible divisions by zero. Request for very low, but non zero rates would cause the ACLK divisor field to overflow. Catch this situation by using the maximum value. The internal function aclk_set_rate() calculates the correct divider value, but doesn't write it back to the register. Add the write back. Signed-off-by: Hans J. Koch Signed-off-by: Oskar Schirmer Cc: bigeasy@linutronix.de Signed-off-by: Thomas Gleixner --- arch/arm/mach-tcc8k/clock.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-tcc8k') diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c index 3970a9cdce26..7ebcbff4652a 100644 --- a/arch/arm/mach-tcc8k/clock.c +++ b/arch/arm/mach-tcc8k/clock.c @@ -50,6 +50,8 @@ #define ACLKTCX (CKC_BASE + ACLKTCX_OFFS) #define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS) +#define ACLK_MAX_DIV (0xfff + 1) + /* Crystal frequencies */ static unsigned long xi_rate, xti_rate; @@ -258,14 +260,19 @@ static unsigned long aclk_best_div(struct clk *clk, unsigned long rate) { unsigned long div, src, freq, r1, r2; + if (!rate) + return ACLK_MAX_DIV; + src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT; src &= CLK_SRC_MASK; freq = root_clk_get_rate(src); - div = freq / rate + 1; + div = freq / rate; + if (!div) + return 1; + if (div >= ACLK_MAX_DIV) + return ACLK_MAX_DIV; r1 = freq / div; r2 = freq / (div + 1); - if (r2 >= rate) - return div + 1; if ((rate - r2) < (r1 - rate)) return div + 1; @@ -287,7 +294,8 @@ static int aclk_set_rate(struct clk *clk, unsigned long rate) u32 reg; reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK; - reg |= aclk_best_div(clk, rate); + reg |= aclk_best_div(clk, rate) - 1; + __raw_writel(reg, clk->aclkreg); return 0; } -- cgit v1.2.3 From 25d7a6003b5c76b735fdfc3dc5030d9d9c93844e Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Thu, 17 Feb 2011 16:43:00 +0100 Subject: arm: tcc8k: Avoid reading clock register twice There is no reason why in case of PLL2 the configuration register should be read twice, while for PLL0/1 using the value previously read is used. Do the same for PLL2. Signed-off-by: Oskar Schirmer Cc: bigeasy@linutronix.de Signed-off-by: Thomas Gleixner --- arch/arm/mach-tcc8k/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-tcc8k') diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c index 7ebcbff4652a..a25e3fcb716f 100644 --- a/arch/arm/mach-tcc8k/clock.c +++ b/arch/arm/mach-tcc8k/clock.c @@ -199,7 +199,7 @@ static unsigned long get_rate_pll_div(int pll) addr = CKC_BASE + CLKDIVC1_OFFS; reg = __raw_readl(addr); if (reg & CLKDIVC1_P2E) - div = __raw_readl(addr) & 0x3f; + div = reg & 0x3f; break; } return get_rate_pll(pll) / (div + 1); -- cgit v1.2.3 From cfeeb2f99867c075f3a1a6ac59c0a42e1cd741b0 Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Thu, 17 Feb 2011 16:43:01 +0100 Subject: arm: tcc8k: Fix indent, coding syle Remove double definition of ACLKUSBH, change parameter name in root_clk_disable, as there is no reason to have a different name than in root_clk_enable. No functional change. Signed-off-by: Oskar Schirmer Cc: bigeasy@linutronix.de Signed-off-by: Thomas Gleixner --- arch/arm/mach-tcc8k/clock.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-tcc8k') diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c index a25e3fcb716f..8d8c99f89558 100644 --- a/arch/arm/mach-tcc8k/clock.c +++ b/arch/arm/mach-tcc8k/clock.c @@ -45,7 +45,6 @@ #define ACLKGSB1 (CKC_BASE + ACLKGSB1_OFFS) #define ACLKGSB2 (CKC_BASE + ACLKGSB2_OFFS) #define ACLKGSB3 (CKC_BASE + ACLKGSB3_OFFS) -#define ACLKUSBH (CKC_BASE + ACLKUSBH_OFFS) #define ACLKTCT (CKC_BASE + ACLKTCT_OFFS) #define ACLKTCX (CKC_BASE + ACLKTCX_OFFS) #define ACLKTCZ (CKC_BASE + ACLKTCZ_OFFS) @@ -108,9 +107,9 @@ static int root_clk_enable(enum root_clks src) return 0; } -static int root_clk_disable(enum root_clks root_src) +static int root_clk_disable(enum root_clks src) { - switch (root_src) { + switch (src) { case CLK_SRC_PLL0: return pll_enable(0, 0); case CLK_SRC_PLL1: return pll_enable(1, 0); case CLK_SRC_PLL2: return pll_enable(2, 0); @@ -304,7 +303,7 @@ static unsigned long get_rate_sys(struct clk *clk) unsigned int src; src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK; - return root_clk_get_rate(src); + return root_clk_get_rate(src); } static unsigned long get_rate_bus(struct clk *clk) -- cgit v1.2.3 From f91f9cd505f92e4227ffda7e5799a33d4f34bf36 Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Thu, 17 Feb 2011 16:43:02 +0100 Subject: arm: tcc8k: Fix bus clock calculation There are two dividers used to derive bus clock from system clock: system clock is divided by SCKDIV+1, then by BCKDIV+1. SCKDIV divider has been ignored up to now, which is no problem as long as it is 0. Take SCKDIV into account for bus clock calculation. Signed-off-by: Oskar Schirmer Cc: bigeasy@linutronix.de Signed-off-by: Thomas Gleixner --- arch/arm/mach-tcc8k/clock.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-tcc8k') diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c index 8d8c99f89558..e7cdae5c77a4 100644 --- a/arch/arm/mach-tcc8k/clock.c +++ b/arch/arm/mach-tcc8k/clock.c @@ -308,10 +308,17 @@ static unsigned long get_rate_sys(struct clk *clk) static unsigned long get_rate_bus(struct clk *clk) { - unsigned int div; + unsigned int reg, sdiv, bdiv, rate; - div = (__raw_readl(CKC_BASE + CLKCTRL_OFFS) >> 4) & 0xff; - return get_rate_sys(clk) / (div + 1); + reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS); + rate = get_rate_sys(clk); + sdiv = (reg >> 20) & 3; + if (sdiv) + rate /= sdiv + 1; + bdiv = (reg >> 4) & 0xff; + if (bdiv) + rate /= bdiv + 1; + return rate; } static unsigned long get_rate_cpu(struct clk *clk) -- cgit v1.2.3