aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukasz Majewski <l.majewski@samsung.com>2013-10-09 08:08:43 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-10-17 07:52:49 -0400
commit7ad65d592b0a7f70fe21af2e3d4d02c76333d5a0 (patch)
tree93e967897f077ed4d377c3d06d53fdaf4dbb72a9
parentcf4671559fdc0550de38fc8f6cd0ea6369736f1f (diff)
cpufreq: exynos4210: Use the common clock framework to set APLL clock rate
In the exynos4210_set_apll() function, the APLL frequency is set with direct register manipulation. Such approach is not allowed in the common clock framework. The frequency is changed, but the corresponding clock value is not updated. This causes wrong frequency read from cpufreq's cpuinfo_cur_freq sysfs attribute. Also direct manipulation with PLL's S parameter has been removed. It is already done at PLL35xx code. Tested at: - Exynos4210 - Trats board (linux 3.12-rc4) Signed-off-by: Lukasz Majewski <l.majewski@samsung.com> Reviewed-by: Yadwinder Singh Brar <yadi.brar@samsung.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/exynos4210-cpufreq.c67
1 files changed, 8 insertions, 59 deletions
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index add7fbec4fc9..f2c75065ce19 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -81,9 +81,9 @@ static void exynos4210_set_clkdiv(unsigned int div_index)
81 81
82static void exynos4210_set_apll(unsigned int index) 82static void exynos4210_set_apll(unsigned int index)
83{ 83{
84 unsigned int tmp; 84 unsigned int tmp, freq = apll_freq_4210[index].freq;
85 85
86 /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */ 86 /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
87 clk_set_parent(moutcore, mout_mpll); 87 clk_set_parent(moutcore, mout_mpll);
88 88
89 do { 89 do {
@@ -92,21 +92,9 @@ static void exynos4210_set_apll(unsigned int index)
92 tmp &= 0x7; 92 tmp &= 0x7;
93 } while (tmp != 0x2); 93 } while (tmp != 0x2);
94 94
95 /* 2. Set APLL Lock time */ 95 clk_set_rate(mout_apll, freq * 1000);
96 __raw_writel(EXYNOS4_APLL_LOCKTIME, EXYNOS4_APLL_LOCK);
97
98 /* 3. Change PLL PMS values */
99 tmp = __raw_readl(EXYNOS4_APLL_CON0);
100 tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
101 tmp |= apll_freq_4210[index].mps;
102 __raw_writel(tmp, EXYNOS4_APLL_CON0);
103 96
104 /* 4. wait_lock_time */ 97 /* MUX_CORE_SEL = APLL */
105 do {
106 tmp = __raw_readl(EXYNOS4_APLL_CON0);
107 } while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT)));
108
109 /* 5. MUX_CORE_SEL = APLL */
110 clk_set_parent(moutcore, mout_apll); 98 clk_set_parent(moutcore, mout_apll);
111 99
112 do { 100 do {
@@ -115,53 +103,15 @@ static void exynos4210_set_apll(unsigned int index)
115 } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); 103 } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
116} 104}
117 105
118static bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index)
119{
120 unsigned int old_pm = apll_freq_4210[old_index].mps >> 8;
121 unsigned int new_pm = apll_freq_4210[new_index].mps >> 8;
122
123 return (old_pm == new_pm) ? 0 : 1;
124}
125
126static void exynos4210_set_frequency(unsigned int old_index, 106static void exynos4210_set_frequency(unsigned int old_index,
127 unsigned int new_index) 107 unsigned int new_index)
128{ 108{
129 unsigned int tmp;
130
131 if (old_index > new_index) { 109 if (old_index > new_index) {
132 if (!exynos4210_pms_change(old_index, new_index)) { 110 exynos4210_set_clkdiv(new_index);
133 /* 1. Change the system clock divider values */ 111 exynos4210_set_apll(new_index);
134 exynos4210_set_clkdiv(new_index);
135
136 /* 2. Change just s value in apll m,p,s value */
137 tmp = __raw_readl(EXYNOS4_APLL_CON0);
138 tmp &= ~(0x7 << 0);
139 tmp |= apll_freq_4210[new_index].mps & 0x7;
140 __raw_writel(tmp, EXYNOS4_APLL_CON0);
141 } else {
142 /* Clock Configuration Procedure */
143 /* 1. Change the system clock divider values */
144 exynos4210_set_clkdiv(new_index);
145 /* 2. Change the apll m,p,s value */
146 exynos4210_set_apll(new_index);
147 }
148 } else if (old_index < new_index) { 112 } else if (old_index < new_index) {
149 if (!exynos4210_pms_change(old_index, new_index)) { 113 exynos4210_set_apll(new_index);
150 /* 1. Change just s value in apll m,p,s value */ 114 exynos4210_set_clkdiv(new_index);
151 tmp = __raw_readl(EXYNOS4_APLL_CON0);
152 tmp &= ~(0x7 << 0);
153 tmp |= apll_freq_4210[new_index].mps & 0x7;
154 __raw_writel(tmp, EXYNOS4_APLL_CON0);
155
156 /* 2. Change the system clock divider values */
157 exynos4210_set_clkdiv(new_index);
158 } else {
159 /* Clock Configuration Procedure */
160 /* 1. Change the apll m,p,s value */
161 exynos4210_set_apll(new_index);
162 /* 2. Change the system clock divider values */
163 exynos4210_set_clkdiv(new_index);
164 }
165 } 115 }
166} 116}
167 117
@@ -194,7 +144,6 @@ int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
194 info->volt_table = exynos4210_volt_table; 144 info->volt_table = exynos4210_volt_table;
195 info->freq_table = exynos4210_freq_table; 145 info->freq_table = exynos4210_freq_table;
196 info->set_freq = exynos4210_set_frequency; 146 info->set_freq = exynos4210_set_frequency;
197 info->need_apll_change = exynos4210_pms_change;
198 147
199 return 0; 148 return 0;
200 149