aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTang Yuantian <Yuantian.Tang@freescale.com>2015-06-04 02:25:42 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-06-15 09:47:28 -0400
commit8a95c1441c799bb0f0d31cdb11523d91923d51a7 (patch)
treed6358c3e046df318e397dbfd1779c1b22f23f12e
parent431920edfd675ba74949415aace0a4eae07073e3 (diff)
cpufreq: qoriq: optimize the CPU frequency switching time
Each time the CPU switches its frequency, the clock nodes in DTS are walked through to find proper clock source. This is very time-consuming, for example, it is up to 500+ us on T4240. Besides, switching time varies from clock to clock. To optimize this, each input clock of CPU is buffered, so that it can be picked up instantly when needed. Since for each CPU each input clock is stored in a pointer which takes 4 or 8 bytes memory and normally there are several input clocks per CPU, that will not take much memory as well. Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/qoriq-cpufreq.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 88b21ae0d6b0..358f0752c31e 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -27,11 +27,11 @@
27 27
28/** 28/**
29 * struct cpu_data 29 * struct cpu_data
30 * @parent: the parent node of cpu clock 30 * @pclk: the parent clock of cpu
31 * @table: frequency table 31 * @table: frequency table
32 */ 32 */
33struct cpu_data { 33struct cpu_data {
34 struct device_node *parent; 34 struct clk **pclk;
35 struct cpufreq_frequency_table *table; 35 struct cpufreq_frequency_table *table;
36}; 36};
37 37
@@ -196,7 +196,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
196 196
197static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) 197static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
198{ 198{
199 struct device_node *np; 199 struct device_node *np, *pnode;
200 int i, count, ret; 200 int i, count, ret;
201 u32 freq, mask; 201 u32 freq, mask;
202 struct clk *clk; 202 struct clk *clk;
@@ -219,17 +219,23 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
219 goto err_nomem2; 219 goto err_nomem2;
220 } 220 }
221 221
222 data->parent = of_parse_phandle(np, "clocks", 0); 222 pnode = of_parse_phandle(np, "clocks", 0);
223 if (!data->parent) { 223 if (!pnode) {
224 pr_err("%s: could not get clock information\n", __func__); 224 pr_err("%s: could not get clock information\n", __func__);
225 goto err_nomem2; 225 goto err_nomem2;
226 } 226 }
227 227
228 count = of_property_count_strings(data->parent, "clock-names"); 228 count = of_property_count_strings(pnode, "clock-names");
229 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
230 if (!data->pclk) {
231 pr_err("%s: no memory\n", __func__);
232 goto err_node;
233 }
234
229 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); 235 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
230 if (!table) { 236 if (!table) {
231 pr_err("%s: no memory\n", __func__); 237 pr_err("%s: no memory\n", __func__);
232 goto err_node; 238 goto err_pclk;
233 } 239 }
234 240
235 if (fmask) 241 if (fmask)
@@ -238,7 +244,8 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
238 mask = 0x0; 244 mask = 0x0;
239 245
240 for (i = 0; i < count; i++) { 246 for (i = 0; i < count; i++) {
241 clk = of_clk_get(data->parent, i); 247 clk = of_clk_get(pnode, i);
248 data->pclk[i] = clk;
242 freq = clk_get_rate(clk); 249 freq = clk_get_rate(clk);
243 /* 250 /*
244 * the clock is valid if its frequency is not masked 251 * the clock is valid if its frequency is not masked
@@ -273,13 +280,16 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
273 policy->cpuinfo.transition_latency = u64temp + 1; 280 policy->cpuinfo.transition_latency = u64temp + 1;
274 281
275 of_node_put(np); 282 of_node_put(np);
283 of_node_put(pnode);
276 284
277 return 0; 285 return 0;
278 286
279err_nomem1: 287err_nomem1:
280 kfree(table); 288 kfree(table);
289err_pclk:
290 kfree(data->pclk);
281err_node: 291err_node:
282 of_node_put(data->parent); 292 of_node_put(pnode);
283err_nomem2: 293err_nomem2:
284 policy->driver_data = NULL; 294 policy->driver_data = NULL;
285 kfree(data); 295 kfree(data);
@@ -293,7 +303,7 @@ static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy)
293{ 303{
294 struct cpu_data *data = policy->driver_data; 304 struct cpu_data *data = policy->driver_data;
295 305
296 of_node_put(data->parent); 306 kfree(data->pclk);
297 kfree(data->table); 307 kfree(data->table);
298 kfree(data); 308 kfree(data);
299 policy->driver_data = NULL; 309 policy->driver_data = NULL;
@@ -307,7 +317,7 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy,
307 struct clk *parent; 317 struct clk *parent;
308 struct cpu_data *data = policy->driver_data; 318 struct cpu_data *data = policy->driver_data;
309 319
310 parent = of_clk_get(data->parent, data->table[index].driver_data); 320 parent = data->pclk[data->table[index].driver_data];
311 return clk_set_parent(policy->clk, parent); 321 return clk_set_parent(policy->clk, parent);
312} 322}
313 323