diff options
| -rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index ceb52db1e2f1..627bf0f4262e 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c | |||
| @@ -49,6 +49,8 @@ static struct cpufreq_frequency_table freq_table[] = { | |||
| 49 | #define NUM_CPUS 2 | 49 | #define NUM_CPUS 2 |
| 50 | 50 | ||
| 51 | static struct clk *cpu_clk; | 51 | static struct clk *cpu_clk; |
| 52 | static struct clk *pll_x_clk; | ||
| 53 | static struct clk *pll_p_clk; | ||
| 52 | static struct clk *emc_clk; | 54 | static struct clk *emc_clk; |
| 53 | 55 | ||
| 54 | static unsigned long target_cpu_speed[NUM_CPUS]; | 56 | static unsigned long target_cpu_speed[NUM_CPUS]; |
| @@ -71,6 +73,42 @@ static unsigned int tegra_getspeed(unsigned int cpu) | |||
| 71 | return rate; | 73 | return rate; |
| 72 | } | 74 | } |
| 73 | 75 | ||
| 76 | static int tegra_cpu_clk_set_rate(unsigned long rate) | ||
| 77 | { | ||
| 78 | int ret; | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Take an extra reference to the main pll so it doesn't turn | ||
| 82 | * off when we move the cpu off of it | ||
| 83 | */ | ||
| 84 | clk_prepare_enable(pll_x_clk); | ||
| 85 | |||
| 86 | ret = clk_set_parent(cpu_clk, pll_p_clk); | ||
| 87 | if (ret) { | ||
| 88 | pr_err("Failed to switch cpu to clock pll_p\n"); | ||
| 89 | goto out; | ||
| 90 | } | ||
| 91 | |||
| 92 | if (rate == clk_get_rate(pll_p_clk)) | ||
| 93 | goto out; | ||
| 94 | |||
| 95 | ret = clk_set_rate(pll_x_clk, rate); | ||
| 96 | if (ret) { | ||
| 97 | pr_err("Failed to change pll_x to %lu\n", rate); | ||
| 98 | goto out; | ||
| 99 | } | ||
| 100 | |||
| 101 | ret = clk_set_parent(cpu_clk, pll_x_clk); | ||
| 102 | if (ret) { | ||
| 103 | pr_err("Failed to switch cpu to clock pll_x\n"); | ||
| 104 | goto out; | ||
| 105 | } | ||
| 106 | |||
| 107 | out: | ||
| 108 | clk_disable_unprepare(pll_x_clk); | ||
| 109 | return ret; | ||
| 110 | } | ||
| 111 | |||
| 74 | static int tegra_update_cpu_speed(unsigned long rate) | 112 | static int tegra_update_cpu_speed(unsigned long rate) |
| 75 | { | 113 | { |
| 76 | int ret = 0; | 114 | int ret = 0; |
| @@ -101,7 +139,7 @@ static int tegra_update_cpu_speed(unsigned long rate) | |||
| 101 | freqs.old, freqs.new); | 139 | freqs.old, freqs.new); |
| 102 | #endif | 140 | #endif |
| 103 | 141 | ||
| 104 | ret = clk_set_rate(cpu_clk, freqs.new * 1000); | 142 | ret = tegra_cpu_clk_set_rate(freqs.new * 1000); |
| 105 | if (ret) { | 143 | if (ret) { |
| 106 | pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n", | 144 | pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n", |
| 107 | freqs.new); | 145 | freqs.new); |
| @@ -183,6 +221,14 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) | |||
| 183 | if (IS_ERR(cpu_clk)) | 221 | if (IS_ERR(cpu_clk)) |
| 184 | return PTR_ERR(cpu_clk); | 222 | return PTR_ERR(cpu_clk); |
| 185 | 223 | ||
| 224 | pll_x_clk = clk_get_sys(NULL, "pll_x"); | ||
| 225 | if (IS_ERR(pll_x_clk)) | ||
| 226 | return PTR_ERR(pll_x_clk); | ||
| 227 | |||
| 228 | pll_p_clk = clk_get_sys(NULL, "pll_p"); | ||
| 229 | if (IS_ERR(pll_p_clk)) | ||
| 230 | return PTR_ERR(pll_p_clk); | ||
| 231 | |||
| 186 | emc_clk = clk_get_sys("cpu", "emc"); | 232 | emc_clk = clk_get_sys("cpu", "emc"); |
| 187 | if (IS_ERR(emc_clk)) { | 233 | if (IS_ERR(emc_clk)) { |
| 188 | clk_put(cpu_clk); | 234 | clk_put(cpu_clk); |
