diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/common.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-tegra/devices.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/uncompress.h | 8 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_clocks.c | 93 |
4 files changed, 86 insertions, 47 deletions
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 951a4cc3a061..fbbdb7ccd960 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -109,32 +109,36 @@ void tegra_assert_system_reset(char mode, const char *cmd) static __initdata struct tegra_clk_init_table common_clk_init_table[] = { /* name parent rate enabled */ { "clk_m", NULL, 0, true }, +#ifdef CONFIG_ARCH_TEGRA_2x_SOC { "pll_p", NULL, 216000000, true }, { "pll_p_out1", "pll_p", 28800000, true }, { "pll_p_out2", "pll_p", 48000000, true }, { "pll_p_out3", "pll_p", 72000000, true }, { "pll_p_out4", "pll_p", 108000000, true }, -#ifdef CONFIG_ARCH_TEGRA_2x_SOC { "pll_m", "clk_m", 600000000, true }, { "pll_m_out1", "pll_m", 120000000, true }, { "sclk", "pll_m_out1", 40000000, true }, { "hclk", "sclk", 40000000, true }, { "pclk", "hclk", 40000000, true }, #else + { "pll_p", NULL, 408000000, true }, + { "pll_p_out1", "pll_p", 9600000, true }, + { "pll_p_out2", "pll_p", 48000000, true }, + { "pll_p_out3", "pll_p", 102000000, true }, { "pll_m_out1", "pll_m", 275000000, true }, { "pll_c", NULL, ULONG_MAX, false }, { "pll_c_out1", "pll_c", 208000000, false }, - { "pll_p_out4", "pll_p", 108000000, true }, - { "sclk", "pll_p_out4", 108000000, true }, - { "hclk", "sclk", 108000000, true }, - { "pclk", "hclk", 54000000, true }, + { "pll_p_out4", "pll_p", 102000000, true }, + { "sclk", "pll_p_out4", 102000000, true }, + { "hclk", "sclk", 102000000, true }, + { "pclk", "hclk", 51000000, true }, #endif { "csite", NULL, 0, true }, { "emc", NULL, 0, true }, { "cpu", NULL, 0, true }, { "kfuse", NULL, 0, true }, { "pll_u", NULL, 480000000, false }, - { "sdmmc1", "pll_c", 48000000, false}, + { "sdmmc1", "pll_p", 48000000, false}, { "sdmmc3", "pll_p", 48000000, false}, { "sdmmc4", "pll_p", 48000000, false}, #ifndef CONFIG_ARCH_TEGRA_2x_SOC diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index 1142a402b60d..39523ae61206 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c @@ -33,6 +33,12 @@ #include <mach/usb_phy.h> #include "gpio-names.h" +#if !defined(CONFIG_ARCH_TEGRA_2x_SOC) +#define UART_SOURCE_RATE 408000000 +#else +#define UART_SOURCE_RATE 216000000 +#endif + static struct resource i2c_resource1[] = { [0] = { .start = INT_I2C, @@ -723,7 +729,7 @@ static struct plat_serial8250_port debug_uarta_platform_data[] = { .type = PORT_TEGRA, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = 216000000, + .uartclk = UART_SOURCE_RATE, }, { .flags = 0, @@ -739,7 +745,7 @@ static struct plat_serial8250_port debug_uartb_platform_data[] = { .type = PORT_TEGRA, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = 216000000, + .uartclk = UART_SOURCE_RATE, }, { .flags = 0, @@ -755,7 +761,7 @@ static struct plat_serial8250_port debug_uartc_platform_data[] = { .type = PORT_TEGRA, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = 216000000, + .uartclk = UART_SOURCE_RATE, }, { .flags = 0, @@ -771,7 +777,7 @@ static struct plat_serial8250_port debug_uartd_platform_data[] = { .type = PORT_TEGRA, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = 216000000, + .uartclk = UART_SOURCE_RATE, }, { .flags = 0, @@ -788,7 +794,7 @@ static struct plat_serial8250_port debug_uarte_platform_data[] = { .type = PORT_TEGRA, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = 216000000, + .uartclk = UART_SOURCE_RATE, }, { .flags = 0, diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 939dcd4d6b0a..9665858ab11d 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -66,6 +66,12 @@ #define DEBUG_UART_RST_CLR_BIT 0 #endif +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +#define DEBUG_UART_DLL 0x75 +#else +#define DEBUG_UART_DLL 0xdd +#endif + static void putc(int c) { volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; @@ -120,7 +126,7 @@ static inline void arch_decomp_setup(void) /* Set up debug UART. */ uart[UART_LCR << shift] |= UART_LCR_DLAB; - uart[UART_DLL << shift] = 0x75; + uart[UART_DLL << shift] = DEBUG_UART_DLL; uart[UART_DLM << shift] = 0x0; uart[UART_LCR << shift] = 3; } diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c index 68e400e01a91..99853ff4f76a 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -198,6 +198,8 @@ #define SUPER_CLK_DIVIDER 0x04 #define SUPER_CLOCK_DIV_U71_SHIFT 16 #define SUPER_CLOCK_DIV_U71_MASK (0xff << SUPER_CLOCK_DIV_U71_SHIFT) +/* guarantees safe cpu backup */ +#define SUPER_CLOCK_DIV_U71_MIN 0x2 #define BUS_CLK_DISABLE (1<<3) #define BUS_CLK_DIV_MASK 0x3 @@ -568,11 +570,13 @@ static void tegra3_super_clk_init(struct clk *c) c->parent = sel->input; if (c->flags & DIV_U71) { - val = clk_readl(c->reg + SUPER_CLK_DIVIDER); - val &= SUPER_CLOCK_DIV_U71_MASK; - clk_writel(val, c->reg + SUPER_CLK_DIVIDER); - c->div = (val >> SUPER_CLOCK_DIV_U71_SHIFT) + 2; + /* Init safe 7.1 divider value (does not affect PLLX path) */ + clk_writel(SUPER_CLOCK_DIV_U71_MIN << SUPER_CLOCK_DIV_U71_SHIFT, + c->reg + SUPER_CLK_DIVIDER); c->mul = 2; + c->div = 2; + if (!(c->parent->flags & PLLX)) + c->div += SUPER_CLOCK_DIV_U71_MIN; } else clk_writel(0, c->reg + SUPER_CLK_DIVIDER); @@ -616,6 +620,20 @@ static int tegra3_super_clk_set_parent(struct clk *c, struct clk *p) val &= ~(SUPER_SOURCE_MASK << shift); val |= (sel->value & SUPER_SOURCE_MASK) << shift; + /* 7.1 divider for CPU super-clock does not affect + PLLX path */ + if (c->flags & DIV_U71) { + u32 div = 0; + if (!(p->flags & PLLX)) { + div = clk_readl(c->reg + + SUPER_CLK_DIVIDER); + div &= SUPER_CLOCK_DIV_U71_MASK; + div >>= SUPER_CLOCK_DIV_U71_SHIFT; + } + c->div = div + 2; + c->mul = 2; + } + if (c->refcnt) clk_enable(p); @@ -645,6 +663,8 @@ static int tegra3_super_clk_set_rate(struct clk *c, unsigned long rate) if ((c->flags & DIV_U71) && (c->parent->flags & PLL_FIXED)) { int div = clk_div71_get_divider(c->parent->u.pll.fixed_rate, rate, c->flags, ROUND_DIVIDER_DOWN); + div = max(div, SUPER_CLOCK_DIV_U71_MIN); + clk_writel(div << SUPER_CLOCK_DIV_U71_SHIFT, c->reg + SUPER_CLK_DIVIDER); c->div = div + 2; @@ -689,7 +709,6 @@ static void tegra3_cpu_clk_disable(struct clk *c) static int tegra3_cpu_clk_set_rate(struct clk *c, unsigned long rate) { int ret; - unsigned long backup_rate; if (!c->dvfs || !c->dvfs->dvfs_rail) { #ifdef CONFIG_TEGRA_FPGA_PLATFORM @@ -720,12 +739,8 @@ static int tegra3_cpu_clk_set_rate(struct clk *c, unsigned long rate) goto out; } - backup_rate = clk_get_rate(c->u.cpu.backup); - if (c->u.cpu.backup->flags & PLL_FIXED) { - clk_set_rate(c->parent, rate); - if (rate <= backup_rate) - goto out; - } else if (rate == backup_rate) + ret = clk_set_rate(c->parent, rate); + if (!ret && (rate <= clk_get_rate(c->parent))) goto out; if (rate != clk_get_rate(c->u.cpu.main)) { @@ -1276,9 +1291,8 @@ static void tegra3_pll_clk_init(struct clk *c) return; } } - pr_warning("Clock %s has unknown fixed frequency\n", c->name); - c->mul = 1; - c->div = 1; + pr_err("Clock %s has unknown fixed frequency\n", c->name); + BUG(); } else if (val & PLL_BASE_BYPASS) { c->mul = 1; c->div = 1; @@ -1290,6 +1304,10 @@ static void tegra3_pll_clk_init(struct clk *c) else c->div *= (0x1 << ((val & PLL_BASE_DIVP_MASK) >> PLL_BASE_DIVP_SHIFT)); + if (c->flags & PLL_FIXED) { + unsigned long rate = clk_get_rate_locked(c); + BUG_ON(rate != c->u.pll.fixed_rate); + } } if (c->flags & PLLU) { @@ -1349,9 +1367,13 @@ static int tegra3_pll_clk_set_rate(struct clk *c, unsigned long rate) pr_debug("%s: %s %lu\n", __func__, c->name, rate); if (c->flags & PLL_FIXED) { - val = clk_readl(c->reg + PLL_BASE); - if (!(val & PLL_BASE_OVERRIDE) && (rate == c->u.pll.fixed_rate)) - return 0; + int ret = 0; + if (rate != c->u.pll.fixed_rate) { + pr_err("%s: Can not change %s fixed rate %lu to %lu\n", + __func__, c->name, c->u.pll.fixed_rate, rate); + ret = -EINVAL; + } + return ret; } p_div = 0; @@ -1421,10 +1443,6 @@ static int tegra3_pll_clk_set_rate(struct clk *c, unsigned long rate) c->div = sel->m * sel->p; old_base = val = clk_readl(c->reg + PLL_BASE); - if (c->flags & PLL_FIXED) { - BUG(); - val |= PLL_BASE_OVERRIDE; - } val &= ~(PLL_BASE_DIVM_MASK | PLL_BASE_DIVN_MASK | ((c->flags & PLLU) ? PLLU_BASE_POST_DIV : PLL_BASE_DIVP_MASK)); val |= (sel->m << PLL_BASE_DIVM_SHIFT) | @@ -2682,7 +2700,7 @@ static struct clk tegra_pll_p = { .vco_max = 1400000000, .freq_table = tegra_pll_p_freq_table, .lock_delay = 300, - .fixed_rate = 216000000, + .fixed_rate = 408000000, }, }; @@ -2727,6 +2745,10 @@ static struct clk tegra_pll_p_out4 = { }; static struct clk_pll_freq_table tegra_pll_a_freq_table[] = { + { 9600000, 564480000, 294, 5, 1, 4}, + { 9600000, 552960000, 288, 5, 1, 4}, + { 9600000, 24000000, 5, 2, 1, 1}, + { 28800000, 56448000, 49, 25, 1, 1}, { 28800000, 73728000, 64, 25, 1, 1}, { 28800000, 24000000, 5, 6, 1, 1}, @@ -2739,7 +2761,7 @@ static struct clk tegra_pll_a = { .ops = &tegra_pll_ops, .reg = 0xb0, .parent = &tegra_pll_p_out1, - .max_rate = 100000000, + .max_rate = 700000000, .u.pll = { .input_min = 2000000, .input_max = 31000000, @@ -3201,7 +3223,7 @@ static struct clk tegra_clk_sclk = { .reg = 0x28, .ops = &tegra_super_ops, .max_rate = 300000000, - .min_rate = 108000000, + .min_rate = 102000000, }; static struct clk tegra_clk_virtual_cpu_g = { @@ -3276,7 +3298,7 @@ static struct clk tegra_clk_pclk = { .reg_shift = 0, .ops = &tegra_bus_ops, .max_rate = 150000000, - .min_rate = 36000000, + .min_rate = 34000000, }; static struct clk tegra_clk_sbus_cmplx = { @@ -3288,7 +3310,7 @@ static struct clk tegra_clk_sbus_cmplx = { .hclk = &tegra_clk_hclk, .sclk_low = &tegra_pll_p_out4, .sclk_high = &tegra_pll_m_out1, - .threshold = 108000000, /* exact factor of low range pll_p */ + .threshold = 204000000, /* exact factor of low range pll_p */ }, }; @@ -3538,7 +3560,7 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ PERIPH_CLK("dsia", "tegradc.0", "dsia", 48, 0, 500000000, mux_plld_out0, 0), PERIPH_CLK_EX("dsib", "tegradc.1", "dsib", 82, 0xd0, 500000000, mux_plld_out0_plld2_out0, MUX | PLLD, &tegra_dsib_clk_ops), - PERIPH_CLK("csi", "tegra_camera", "csi", 52, 0, 72000000, mux_pllp_out3, 0), + PERIPH_CLK("csi", "tegra_camera", "csi", 52, 0, 102000000, mux_pllp_out3, 0), PERIPH_CLK("isp", "tegra_camera", "isp", 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */ PERIPH_CLK("csus", "tegra_camera", "csus", 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET), @@ -3722,14 +3744,14 @@ void __init tegra_soc_init_clocks(void) */ static struct cpufreq_frequency_table freq_table_300MHz[] = { - { 0, 216000 }, + { 0, 204000 }, { 1, 300000 }, { 2, CPUFREQ_TABLE_END }, }; static struct cpufreq_frequency_table freq_table_1p0GHz[] = { - { 0, 108000 }, - { 1, 216000 }, + { 0, 102000 }, + { 1, 204000 }, { 2, 312000 }, { 3, 456000 }, { 4, 608000 }, @@ -3741,8 +3763,8 @@ static struct cpufreq_frequency_table freq_table_1p0GHz[] = { }; static struct cpufreq_frequency_table freq_table_1p3GHz[] = { - { 0, 108000 }, - { 1, 216000 }, + { 0, 102000 }, + { 1, 204000 }, { 2, 340000 }, { 3, 480000 }, { 4, 640000 }, @@ -3756,8 +3778,8 @@ static struct cpufreq_frequency_table freq_table_1p3GHz[] = { }; static struct cpufreq_frequency_table freq_table_1p4GHz[] = { - { 0, 108000 }, - { 1, 216000 }, + { 0, 102000 }, + { 1, 204000 }, { 2, 370000 }, { 3, 480000 }, { 4, 620000 }, @@ -3982,6 +4004,7 @@ void tegra_clk_resume(void) tegra3_periph_clk_init(&tegra_clk_emc); tegra_emc_timing_invalidate(); - tegra3_pll_clk_init(&tegra_pll_u); + tegra3_pll_clk_init(&tegra_pll_u); /* Re-init utmi parameters */ + tegra3_pll_clk_init(&tegra_pll_p); /* Fire a bug if not restored */ } #endif |