aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-03 12:59:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-03 12:59:39 -0400
commit70c9f18ca8f3652c7dcf715e9f0d41c399fe130d (patch)
tree5824f0937025688aab07582838d1a0aea5a24a3f /drivers/cpufreq
parenta0a4194c943bc64dd7b6e26cccb036cb26b81363 (diff)
parent6283e328fb8148a8a5753e95c04c16aaef2287c0 (diff)
Merge branch 'next' of git://github.com/kernelslacker/cpufreq
* 'next' of git://github.com/kernelslacker/cpufreq: [CPUFREQ] db8500: support all frequencies [CPUFREQ] db8500: remove unneeded for loop iteration over freq_table [CPUFREQ] ARM Exynos4210 PM/Suspend compatibility with different bootloaders [CPUFREQ] ARM: ux500: send cpufreq notification for all cpus [CPUFREQ] e_powersaver: Allow user to lower maximum voltage [CPUFREQ] e_powersaver: Check BIOS limit for CPU frequency [CPUFREQ] e_powersaver: Additional checks [CPUFREQ] exynos4210: Show list of available frequencies
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/db8500-cpufreq.c36
-rw-r--r--drivers/cpufreq/e_powersaver.c135
-rw-r--r--drivers/cpufreq/exynos4210-cpufreq.c129
3 files changed, 268 insertions, 32 deletions
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index 8e89dcf9d94d..edaa987621ea 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -18,24 +18,29 @@
18static struct cpufreq_frequency_table freq_table[] = { 18static struct cpufreq_frequency_table freq_table[] = {
19 [0] = { 19 [0] = {
20 .index = 0, 20 .index = 0,
21 .frequency = 300000, 21 .frequency = 200000,
22 }, 22 },
23 [1] = { 23 [1] = {
24 .index = 1, 24 .index = 1,
25 .frequency = 600000, 25 .frequency = 300000,
26 }, 26 },
27 [2] = { 27 [2] = {
28 /* Used for MAX_OPP, if available */
29 .index = 2, 28 .index = 2,
30 .frequency = CPUFREQ_TABLE_END, 29 .frequency = 600000,
31 }, 30 },
32 [3] = { 31 [3] = {
32 /* Used for MAX_OPP, if available */
33 .index = 3, 33 .index = 3,
34 .frequency = CPUFREQ_TABLE_END, 34 .frequency = CPUFREQ_TABLE_END,
35 }, 35 },
36 [4] = {
37 .index = 4,
38 .frequency = CPUFREQ_TABLE_END,
39 },
36}; 40};
37 41
38static enum arm_opp idx2opp[] = { 42static enum arm_opp idx2opp[] = {
43 ARM_EXTCLK,
39 ARM_50_OPP, 44 ARM_50_OPP,
40 ARM_100_OPP, 45 ARM_100_OPP,
41 ARM_MAX_OPP 46 ARM_MAX_OPP
@@ -72,13 +77,13 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
72 77
73 freqs.old = policy->cur; 78 freqs.old = policy->cur;
74 freqs.new = freq_table[idx].frequency; 79 freqs.new = freq_table[idx].frequency;
75 freqs.cpu = policy->cpu;
76 80
77 if (freqs.old == freqs.new) 81 if (freqs.old == freqs.new)
78 return 0; 82 return 0;
79 83
80 /* pre-change notification */ 84 /* pre-change notification */
81 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 85 for_each_cpu(freqs.cpu, policy->cpus)
86 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
82 87
83 /* request the PRCM unit for opp change */ 88 /* request the PRCM unit for opp change */
84 if (prcmu_set_arm_opp(idx2opp[idx])) { 89 if (prcmu_set_arm_opp(idx2opp[idx])) {
@@ -87,7 +92,8 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
87 } 92 }
88 93
89 /* post change notification */ 94 /* post change notification */
90 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 95 for_each_cpu(freqs.cpu, policy->cpus)
96 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
91 97
92 return 0; 98 return 0;
93} 99}
@@ -104,16 +110,18 @@ static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
104static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) 110static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
105{ 111{
106 int res; 112 int res;
107 int i;
108 113
109 BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); 114 BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
110 115
111 if (cpu_is_u8500v2() && !prcmu_is_u8400()) { 116 if (!prcmu_is_u8400()) {
112 freq_table[0].frequency = 400000; 117 freq_table[1].frequency = 400000;
113 freq_table[1].frequency = 800000; 118 freq_table[2].frequency = 800000;
114 if (prcmu_has_arm_maxopp()) 119 if (prcmu_has_arm_maxopp())
115 freq_table[2].frequency = 1000000; 120 freq_table[3].frequency = 1000000;
116 } 121 }
122 pr_info("db8500-cpufreq : Available frequencies:\n");
123 while (freq_table[i].frequency != CPUFREQ_TABLE_END)
124 pr_info(" %d Mhz\n", freq_table[i++].frequency/1000);
117 125
118 /* get policy fields based on the table */ 126 /* get policy fields based on the table */
119 res = cpufreq_frequency_table_cpuinfo(policy, freq_table); 127 res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
@@ -127,10 +135,6 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
127 policy->min = policy->cpuinfo.min_freq; 135 policy->min = policy->cpuinfo.min_freq;
128 policy->max = policy->cpuinfo.max_freq; 136 policy->max = policy->cpuinfo.max_freq;
129 policy->cur = db8500_cpufreq_getspeed(policy->cpu); 137 policy->cur = db8500_cpufreq_getspeed(policy->cpu);
130
131 for (i = 0; freq_table[i].frequency != policy->cur; i++)
132 ;
133
134 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 138 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
135 139
136 /* 140 /*
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index 35a257dd4bb7..4bd6815d317b 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -19,6 +19,11 @@
19#include <asm/msr.h> 19#include <asm/msr.h>
20#include <asm/tsc.h> 20#include <asm/tsc.h>
21 21
22#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
23#include <linux/acpi.h>
24#include <acpi/processor.h>
25#endif
26
22#define EPS_BRAND_C7M 0 27#define EPS_BRAND_C7M 0
23#define EPS_BRAND_C7 1 28#define EPS_BRAND_C7 1
24#define EPS_BRAND_EDEN 2 29#define EPS_BRAND_EDEN 2
@@ -27,11 +32,59 @@
27 32
28struct eps_cpu_data { 33struct eps_cpu_data {
29 u32 fsb; 34 u32 fsb;
35#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
36 u32 bios_limit;
37#endif
30 struct cpufreq_frequency_table freq_table[]; 38 struct cpufreq_frequency_table freq_table[];
31}; 39};
32 40
33static struct eps_cpu_data *eps_cpu[NR_CPUS]; 41static struct eps_cpu_data *eps_cpu[NR_CPUS];
34 42
43/* Module parameters */
44static int freq_failsafe_off;
45static int voltage_failsafe_off;
46static int set_max_voltage;
47
48#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
49static int ignore_acpi_limit;
50
51static struct acpi_processor_performance *eps_acpi_cpu_perf;
52
53/* Minimum necessary to get acpi_processor_get_bios_limit() working */
54static int eps_acpi_init(void)
55{
56 eps_acpi_cpu_perf = kzalloc(sizeof(struct acpi_processor_performance),
57 GFP_KERNEL);
58 if (!eps_acpi_cpu_perf)
59 return -ENOMEM;
60
61 if (!zalloc_cpumask_var(&eps_acpi_cpu_perf->shared_cpu_map,
62 GFP_KERNEL)) {
63 kfree(eps_acpi_cpu_perf);
64 eps_acpi_cpu_perf = NULL;
65 return -ENOMEM;
66 }
67
68 if (acpi_processor_register_performance(eps_acpi_cpu_perf, 0)) {
69 free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
70 kfree(eps_acpi_cpu_perf);
71 eps_acpi_cpu_perf = NULL;
72 return -EIO;
73 }
74 return 0;
75}
76
77static int eps_acpi_exit(struct cpufreq_policy *policy)
78{
79 if (eps_acpi_cpu_perf) {
80 acpi_processor_unregister_performance(eps_acpi_cpu_perf, 0);
81 free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
82 kfree(eps_acpi_cpu_perf);
83 eps_acpi_cpu_perf = NULL;
84 }
85 return 0;
86}
87#endif
35 88
36static unsigned int eps_get(unsigned int cpu) 89static unsigned int eps_get(unsigned int cpu)
37{ 90{
@@ -164,6 +217,9 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
164 int k, step, voltage; 217 int k, step, voltage;
165 int ret; 218 int ret;
166 int states; 219 int states;
220#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
221 unsigned int limit;
222#endif
167 223
168 if (policy->cpu != 0) 224 if (policy->cpu != 0)
169 return -ENODEV; 225 return -ENODEV;
@@ -244,11 +300,62 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
244 return -EINVAL; 300 return -EINVAL;
245 if (current_voltage > 0x1f || max_voltage > 0x1f) 301 if (current_voltage > 0x1f || max_voltage > 0x1f)
246 return -EINVAL; 302 return -EINVAL;
247 if (max_voltage < min_voltage) 303 if (max_voltage < min_voltage
304 || current_voltage < min_voltage
305 || current_voltage > max_voltage)
248 return -EINVAL; 306 return -EINVAL;
249 307
308 /* Check for systems using underclocked CPU */
309 if (!freq_failsafe_off && max_multiplier != current_multiplier) {
310 printk(KERN_INFO "eps: Your processor is running at different "
311 "frequency then its maximum. Aborting.\n");
312 printk(KERN_INFO "eps: You can use freq_failsafe_off option "
313 "to disable this check.\n");
314 return -EINVAL;
315 }
316 if (!voltage_failsafe_off && max_voltage != current_voltage) {
317 printk(KERN_INFO "eps: Your processor is running at different "
318 "voltage then its maximum. Aborting.\n");
319 printk(KERN_INFO "eps: You can use voltage_failsafe_off "
320 "option to disable this check.\n");
321 return -EINVAL;
322 }
323
250 /* Calc FSB speed */ 324 /* Calc FSB speed */
251 fsb = cpu_khz / current_multiplier; 325 fsb = cpu_khz / current_multiplier;
326
327#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
328 /* Check for ACPI processor speed limit */
329 if (!ignore_acpi_limit && !eps_acpi_init()) {
330 if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) {
331 printk(KERN_INFO "eps: ACPI limit %u.%uGHz\n",
332 limit/1000000,
333 (limit%1000000)/10000);
334 eps_acpi_exit(policy);
335 /* Check if max_multiplier is in BIOS limits */
336 if (limit && max_multiplier * fsb > limit) {
337 printk(KERN_INFO "eps: Aborting.\n");
338 return -EINVAL;
339 }
340 }
341 }
342#endif
343
344 /* Allow user to set lower maximum voltage then that reported
345 * by processor */
346 if (brand == EPS_BRAND_C7M && set_max_voltage) {
347 u32 v;
348
349 /* Change mV to something hardware can use */
350 v = (set_max_voltage - 700) / 16;
351 /* Check if voltage is within limits */
352 if (v >= min_voltage && v <= max_voltage) {
353 printk(KERN_INFO "eps: Setting %dmV as maximum.\n",
354 v * 16 + 700);
355 max_voltage = v;
356 }
357 }
358
252 /* Calc number of p-states supported */ 359 /* Calc number of p-states supported */
253 if (brand == EPS_BRAND_C7M) 360 if (brand == EPS_BRAND_C7M)
254 states = max_multiplier - min_multiplier + 1; 361 states = max_multiplier - min_multiplier + 1;
@@ -265,6 +372,9 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
265 372
266 /* Copy basic values */ 373 /* Copy basic values */
267 centaur->fsb = fsb; 374 centaur->fsb = fsb;
375#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
376 centaur->bios_limit = limit;
377#endif
268 378
269 /* Fill frequency and MSR value table */ 379 /* Fill frequency and MSR value table */
270 f_table = &centaur->freq_table[0]; 380 f_table = &centaur->freq_table[0];
@@ -303,17 +413,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
303static int eps_cpu_exit(struct cpufreq_policy *policy) 413static int eps_cpu_exit(struct cpufreq_policy *policy)
304{ 414{
305 unsigned int cpu = policy->cpu; 415 unsigned int cpu = policy->cpu;
306 struct eps_cpu_data *centaur;
307 u32 lo, hi;
308 416
309 if (eps_cpu[cpu] == NULL)
310 return -ENODEV;
311 centaur = eps_cpu[cpu];
312
313 /* Get max frequency */
314 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
315 /* Set max frequency */
316 eps_set_state(centaur, cpu, hi & 0xffff);
317 /* Bye */ 417 /* Bye */
318 cpufreq_frequency_table_put_attr(policy->cpu); 418 cpufreq_frequency_table_put_attr(policy->cpu);
319 kfree(eps_cpu[cpu]); 419 kfree(eps_cpu[cpu]);
@@ -359,6 +459,19 @@ static void __exit eps_exit(void)
359 cpufreq_unregister_driver(&eps_driver); 459 cpufreq_unregister_driver(&eps_driver);
360} 460}
361 461
462/* Allow user to overclock his machine or to change frequency to higher after
463 * unloading module */
464module_param(freq_failsafe_off, int, 0644);
465MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check");
466module_param(voltage_failsafe_off, int, 0644);
467MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check");
468#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
469module_param(ignore_acpi_limit, int, 0644);
470MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit");
471#endif
472module_param(set_max_voltage, int, 0644);
473MODULE_PARM_DESC(set_max_voltage, "Set maximum CPU voltage (mV) C7-M only");
474
362MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>"); 475MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>");
363MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's."); 476MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");
364MODULE_LICENSE("GPL"); 477MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index b7c3a84c4cfa..ab9741fab92e 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -17,6 +17,8 @@
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/regulator/consumer.h> 18#include <linux/regulator/consumer.h>
19#include <linux/cpufreq.h> 19#include <linux/cpufreq.h>
20#include <linux/notifier.h>
21#include <linux/suspend.h>
20 22
21#include <mach/map.h> 23#include <mach/map.h>
22#include <mach/regs-clock.h> 24#include <mach/regs-clock.h>
@@ -36,6 +38,10 @@ static struct regulator *int_regulator;
36static struct cpufreq_freqs freqs; 38static struct cpufreq_freqs freqs;
37static unsigned int memtype; 39static unsigned int memtype;
38 40
41static unsigned int locking_frequency;
42static bool frequency_locked;
43static DEFINE_MUTEX(cpufreq_lock);
44
39enum exynos4_memory_type { 45enum exynos4_memory_type {
40 DDR2 = 4, 46 DDR2 = 4,
41 LPDDR2, 47 LPDDR2,
@@ -405,22 +411,32 @@ static int exynos4_target(struct cpufreq_policy *policy,
405{ 411{
406 unsigned int index, old_index; 412 unsigned int index, old_index;
407 unsigned int arm_volt, int_volt; 413 unsigned int arm_volt, int_volt;
414 int err = -EINVAL;
408 415
409 freqs.old = exynos4_getspeed(policy->cpu); 416 freqs.old = exynos4_getspeed(policy->cpu);
410 417
418 mutex_lock(&cpufreq_lock);
419
420 if (frequency_locked && target_freq != locking_frequency) {
421 err = -EAGAIN;
422 goto out;
423 }
424
411 if (cpufreq_frequency_table_target(policy, exynos4_freq_table, 425 if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
412 freqs.old, relation, &old_index)) 426 freqs.old, relation, &old_index))
413 return -EINVAL; 427 goto out;
414 428
415 if (cpufreq_frequency_table_target(policy, exynos4_freq_table, 429 if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
416 target_freq, relation, &index)) 430 target_freq, relation, &index))
417 return -EINVAL; 431 goto out;
432
433 err = 0;
418 434
419 freqs.new = exynos4_freq_table[index].frequency; 435 freqs.new = exynos4_freq_table[index].frequency;
420 freqs.cpu = policy->cpu; 436 freqs.cpu = policy->cpu;
421 437
422 if (freqs.new == freqs.old) 438 if (freqs.new == freqs.old)
423 return 0; 439 goto out;
424 440
425 /* get the voltage value */ 441 /* get the voltage value */
426 arm_volt = exynos4_volt_table[index].arm_volt; 442 arm_volt = exynos4_volt_table[index].arm_volt;
@@ -447,10 +463,16 @@ static int exynos4_target(struct cpufreq_policy *policy,
447 463
448 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 464 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
449 465
450 return 0; 466out:
467 mutex_unlock(&cpufreq_lock);
468 return err;
451} 469}
452 470
453#ifdef CONFIG_PM 471#ifdef CONFIG_PM
472/*
473 * These suspend/resume are used as syscore_ops, it is already too
474 * late to set regulator voltages at this stage.
475 */
454static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy) 476static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
455{ 477{
456 return 0; 478 return 0;
@@ -462,8 +484,82 @@ static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
462} 484}
463#endif 485#endif
464 486
487/**
488 * exynos4_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
489 * context
490 * @notifier
491 * @pm_event
492 * @v
493 *
494 * While frequency_locked == true, target() ignores every frequency but
495 * locking_frequency. The locking_frequency value is the initial frequency,
496 * which is set by the bootloader. In order to eliminate possible
497 * inconsistency in clock values, we save and restore frequencies during
498 * suspend and resume and block CPUFREQ activities. Note that the standard
499 * suspend/resume cannot be used as they are too deep (syscore_ops) for
500 * regulator actions.
501 */
502static int exynos4_cpufreq_pm_notifier(struct notifier_block *notifier,
503 unsigned long pm_event, void *v)
504{
505 struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
506 static unsigned int saved_frequency;
507 unsigned int temp;
508
509 mutex_lock(&cpufreq_lock);
510 switch (pm_event) {
511 case PM_SUSPEND_PREPARE:
512 if (frequency_locked)
513 goto out;
514 frequency_locked = true;
515
516 if (locking_frequency) {
517 saved_frequency = exynos4_getspeed(0);
518
519 mutex_unlock(&cpufreq_lock);
520 exynos4_target(policy, locking_frequency,
521 CPUFREQ_RELATION_H);
522 mutex_lock(&cpufreq_lock);
523 }
524
525 break;
526 case PM_POST_SUSPEND:
527
528 if (saved_frequency) {
529 /*
530 * While frequency_locked, only locking_frequency
531 * is valid for target(). In order to use
532 * saved_frequency while keeping frequency_locked,
533 * we temporarly overwrite locking_frequency.
534 */
535 temp = locking_frequency;
536 locking_frequency = saved_frequency;
537
538 mutex_unlock(&cpufreq_lock);
539 exynos4_target(policy, locking_frequency,
540 CPUFREQ_RELATION_H);
541 mutex_lock(&cpufreq_lock);
542
543 locking_frequency = temp;
544 }
545
546 frequency_locked = false;
547 break;
548 }
549out:
550 mutex_unlock(&cpufreq_lock);
551
552 return NOTIFY_OK;
553}
554
555static struct notifier_block exynos4_cpufreq_nb = {
556 .notifier_call = exynos4_cpufreq_pm_notifier,
557};
558
465static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy) 559static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
466{ 560{
561 int ret;
562
467 policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu); 563 policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
468 564
469 cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu); 565 cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
@@ -479,16 +575,35 @@ static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
479 */ 575 */
480 cpumask_setall(policy->cpus); 576 cpumask_setall(policy->cpus);
481 577
482 return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table); 578 ret = cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
579 if (ret)
580 return ret;
581
582 cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
583
584 return 0;
585}
586
587static int exynos4_cpufreq_cpu_exit(struct cpufreq_policy *policy)
588{
589 cpufreq_frequency_table_put_attr(policy->cpu);
590 return 0;
483} 591}
484 592
593static struct freq_attr *exynos4_cpufreq_attr[] = {
594 &cpufreq_freq_attr_scaling_available_freqs,
595 NULL,
596};
597
485static struct cpufreq_driver exynos4_driver = { 598static struct cpufreq_driver exynos4_driver = {
486 .flags = CPUFREQ_STICKY, 599 .flags = CPUFREQ_STICKY,
487 .verify = exynos4_verify_speed, 600 .verify = exynos4_verify_speed,
488 .target = exynos4_target, 601 .target = exynos4_target,
489 .get = exynos4_getspeed, 602 .get = exynos4_getspeed,
490 .init = exynos4_cpufreq_cpu_init, 603 .init = exynos4_cpufreq_cpu_init,
604 .exit = exynos4_cpufreq_cpu_exit,
491 .name = "exynos4_cpufreq", 605 .name = "exynos4_cpufreq",
606 .attr = exynos4_cpufreq_attr,
492#ifdef CONFIG_PM 607#ifdef CONFIG_PM
493 .suspend = exynos4_cpufreq_suspend, 608 .suspend = exynos4_cpufreq_suspend,
494 .resume = exynos4_cpufreq_resume, 609 .resume = exynos4_cpufreq_resume,
@@ -501,6 +616,8 @@ static int __init exynos4_cpufreq_init(void)
501 if (IS_ERR(cpu_clk)) 616 if (IS_ERR(cpu_clk))
502 return PTR_ERR(cpu_clk); 617 return PTR_ERR(cpu_clk);
503 618
619 locking_frequency = exynos4_getspeed(0);
620
504 moutcore = clk_get(NULL, "moutcore"); 621 moutcore = clk_get(NULL, "moutcore");
505 if (IS_ERR(moutcore)) 622 if (IS_ERR(moutcore))
506 goto out; 623 goto out;
@@ -540,6 +657,8 @@ static int __init exynos4_cpufreq_init(void)
540 printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype); 657 printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
541 } 658 }
542 659
660 register_pm_notifier(&exynos4_cpufreq_nb);
661
543 return cpufreq_register_driver(&exynos4_driver); 662 return cpufreq_register_driver(&exynos4_driver);
544 663
545out: 664out: