diff options
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/Kconfig | 3 | ||||
-rw-r--r-- | drivers/cpufreq/Kconfig.arm | 6 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq-cpu0.c | 2 | ||||
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 69 | ||||
-rw-r--r-- | drivers/cpufreq/spear-cpufreq.c | 2 |
5 files changed, 62 insertions, 20 deletions
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 38093e272377..386dbc9ccdfd 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig | |||
@@ -181,7 +181,8 @@ config CPU_FREQ_GOV_CONSERVATIVE | |||
181 | 181 | ||
182 | config GENERIC_CPUFREQ_CPU0 | 182 | config GENERIC_CPUFREQ_CPU0 |
183 | tristate "Generic CPU0 cpufreq driver" | 183 | tristate "Generic CPU0 cpufreq driver" |
184 | depends on HAVE_CLK && REGULATOR && PM_OPP && OF | 184 | depends on HAVE_CLK && REGULATOR && OF |
185 | select PM_OPP | ||
185 | help | 186 | help |
186 | This adds a generic cpufreq driver for CPU0 frequency management. | 187 | This adds a generic cpufreq driver for CPU0 frequency management. |
187 | It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) | 188 | It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) |
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index ce52ed949249..456ba5e1781c 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
@@ -4,7 +4,8 @@ | |||
4 | 4 | ||
5 | config ARM_BIG_LITTLE_CPUFREQ | 5 | config ARM_BIG_LITTLE_CPUFREQ |
6 | tristate "Generic ARM big LITTLE CPUfreq driver" | 6 | tristate "Generic ARM big LITTLE CPUfreq driver" |
7 | depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK | 7 | depends on ARM && ARM_CPU_TOPOLOGY && HAVE_CLK |
8 | select PM_OPP | ||
8 | help | 9 | help |
9 | This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. | 10 | This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. |
10 | 11 | ||
@@ -54,7 +55,8 @@ config ARM_EXYNOS5250_CPUFREQ | |||
54 | config ARM_EXYNOS5440_CPUFREQ | 55 | config ARM_EXYNOS5440_CPUFREQ |
55 | bool "SAMSUNG EXYNOS5440" | 56 | bool "SAMSUNG EXYNOS5440" |
56 | depends on SOC_EXYNOS5440 | 57 | depends on SOC_EXYNOS5440 |
57 | depends on HAVE_CLK && PM_OPP && OF | 58 | depends on HAVE_CLK && OF |
59 | select PM_OPP | ||
58 | default y | 60 | default y |
59 | help | 61 | help |
60 | This adds the CPUFreq driver for Samsung EXYNOS5440 | 62 | This adds the CPUFreq driver for Samsung EXYNOS5440 |
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index d4585ce2346c..0faf756f6197 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c | |||
@@ -44,7 +44,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) | |||
44 | int ret; | 44 | int ret; |
45 | 45 | ||
46 | freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); | 46 | freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); |
47 | if (freq_Hz < 0) | 47 | if (freq_Hz <= 0) |
48 | freq_Hz = freq_table[index].frequency * 1000; | 48 | freq_Hz = freq_table[index].frequency * 1000; |
49 | 49 | ||
50 | freq_exact = freq_Hz; | 50 | freq_exact = freq_Hz; |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index f9d561e198ab..0f63f5d598f7 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #define SAMPLE_COUNT 3 | 35 | #define SAMPLE_COUNT 3 |
36 | 36 | ||
37 | #define BYT_RATIOS 0x66a | 37 | #define BYT_RATIOS 0x66a |
38 | #define BYT_VIDS 0x66b | ||
38 | 39 | ||
39 | #define FRAC_BITS 8 | 40 | #define FRAC_BITS 8 |
40 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) | 41 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) |
@@ -64,6 +65,12 @@ struct pstate_data { | |||
64 | int turbo_pstate; | 65 | int turbo_pstate; |
65 | }; | 66 | }; |
66 | 67 | ||
68 | struct vid_data { | ||
69 | int32_t min; | ||
70 | int32_t max; | ||
71 | int32_t ratio; | ||
72 | }; | ||
73 | |||
67 | struct _pid { | 74 | struct _pid { |
68 | int setpoint; | 75 | int setpoint; |
69 | int32_t integral; | 76 | int32_t integral; |
@@ -82,10 +89,9 @@ struct cpudata { | |||
82 | struct timer_list timer; | 89 | struct timer_list timer; |
83 | 90 | ||
84 | struct pstate_data pstate; | 91 | struct pstate_data pstate; |
92 | struct vid_data vid; | ||
85 | struct _pid pid; | 93 | struct _pid pid; |
86 | 94 | ||
87 | int min_pstate_count; | ||
88 | |||
89 | u64 prev_aperf; | 95 | u64 prev_aperf; |
90 | u64 prev_mperf; | 96 | u64 prev_mperf; |
91 | int sample_ptr; | 97 | int sample_ptr; |
@@ -106,7 +112,8 @@ struct pstate_funcs { | |||
106 | int (*get_max)(void); | 112 | int (*get_max)(void); |
107 | int (*get_min)(void); | 113 | int (*get_min)(void); |
108 | int (*get_turbo)(void); | 114 | int (*get_turbo)(void); |
109 | void (*set)(int pstate); | 115 | void (*set)(struct cpudata*, int pstate); |
116 | void (*get_vid)(struct cpudata *); | ||
110 | }; | 117 | }; |
111 | 118 | ||
112 | struct cpu_defaults { | 119 | struct cpu_defaults { |
@@ -358,6 +365,42 @@ static int byt_get_max_pstate(void) | |||
358 | return (value >> 16) & 0xFF; | 365 | return (value >> 16) & 0xFF; |
359 | } | 366 | } |
360 | 367 | ||
368 | static void byt_set_pstate(struct cpudata *cpudata, int pstate) | ||
369 | { | ||
370 | u64 val; | ||
371 | int32_t vid_fp; | ||
372 | u32 vid; | ||
373 | |||
374 | val = pstate << 8; | ||
375 | if (limits.no_turbo) | ||
376 | val |= (u64)1 << 32; | ||
377 | |||
378 | vid_fp = cpudata->vid.min + mul_fp( | ||
379 | int_tofp(pstate - cpudata->pstate.min_pstate), | ||
380 | cpudata->vid.ratio); | ||
381 | |||
382 | vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max); | ||
383 | vid = fp_toint(vid_fp); | ||
384 | |||
385 | val |= vid; | ||
386 | |||
387 | wrmsrl(MSR_IA32_PERF_CTL, val); | ||
388 | } | ||
389 | |||
390 | static void byt_get_vid(struct cpudata *cpudata) | ||
391 | { | ||
392 | u64 value; | ||
393 | |||
394 | rdmsrl(BYT_VIDS, value); | ||
395 | cpudata->vid.min = int_tofp((value >> 8) & 0x7f); | ||
396 | cpudata->vid.max = int_tofp((value >> 16) & 0x7f); | ||
397 | cpudata->vid.ratio = div_fp( | ||
398 | cpudata->vid.max - cpudata->vid.min, | ||
399 | int_tofp(cpudata->pstate.max_pstate - | ||
400 | cpudata->pstate.min_pstate)); | ||
401 | } | ||
402 | |||
403 | |||
361 | static int core_get_min_pstate(void) | 404 | static int core_get_min_pstate(void) |
362 | { | 405 | { |
363 | u64 value; | 406 | u64 value; |
@@ -384,7 +427,7 @@ static int core_get_turbo_pstate(void) | |||
384 | return ret; | 427 | return ret; |
385 | } | 428 | } |
386 | 429 | ||
387 | static void core_set_pstate(int pstate) | 430 | static void core_set_pstate(struct cpudata *cpudata, int pstate) |
388 | { | 431 | { |
389 | u64 val; | 432 | u64 val; |
390 | 433 | ||
@@ -425,7 +468,8 @@ static struct cpu_defaults byt_params = { | |||
425 | .get_max = byt_get_max_pstate, | 468 | .get_max = byt_get_max_pstate, |
426 | .get_min = byt_get_min_pstate, | 469 | .get_min = byt_get_min_pstate, |
427 | .get_turbo = byt_get_max_pstate, | 470 | .get_turbo = byt_get_max_pstate, |
428 | .set = core_set_pstate, | 471 | .set = byt_set_pstate, |
472 | .get_vid = byt_get_vid, | ||
429 | }, | 473 | }, |
430 | }; | 474 | }; |
431 | 475 | ||
@@ -462,7 +506,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) | |||
462 | 506 | ||
463 | cpu->pstate.current_pstate = pstate; | 507 | cpu->pstate.current_pstate = pstate; |
464 | 508 | ||
465 | pstate_funcs.set(pstate); | 509 | pstate_funcs.set(cpu, pstate); |
466 | } | 510 | } |
467 | 511 | ||
468 | static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) | 512 | static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) |
@@ -488,6 +532,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) | |||
488 | cpu->pstate.max_pstate = pstate_funcs.get_max(); | 532 | cpu->pstate.max_pstate = pstate_funcs.get_max(); |
489 | cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); | 533 | cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); |
490 | 534 | ||
535 | if (pstate_funcs.get_vid) | ||
536 | pstate_funcs.get_vid(cpu); | ||
537 | |||
491 | /* | 538 | /* |
492 | * goto max pstate so we don't slow up boot if we are built-in if we are | 539 | * goto max pstate so we don't slow up boot if we are built-in if we are |
493 | * a module we will take care of it during normal operation | 540 | * a module we will take care of it during normal operation |
@@ -568,15 +615,6 @@ static void intel_pstate_timer_func(unsigned long __data) | |||
568 | 615 | ||
569 | intel_pstate_sample(cpu); | 616 | intel_pstate_sample(cpu); |
570 | intel_pstate_adjust_busy_pstate(cpu); | 617 | intel_pstate_adjust_busy_pstate(cpu); |
571 | |||
572 | if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) { | ||
573 | cpu->min_pstate_count++; | ||
574 | if (!(cpu->min_pstate_count % 5)) { | ||
575 | intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); | ||
576 | } | ||
577 | } else | ||
578 | cpu->min_pstate_count = 0; | ||
579 | |||
580 | intel_pstate_set_sample_time(cpu); | 618 | intel_pstate_set_sample_time(cpu); |
581 | } | 619 | } |
582 | 620 | ||
@@ -781,6 +819,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) | |||
781 | pstate_funcs.get_min = funcs->get_min; | 819 | pstate_funcs.get_min = funcs->get_min; |
782 | pstate_funcs.get_turbo = funcs->get_turbo; | 820 | pstate_funcs.get_turbo = funcs->get_turbo; |
783 | pstate_funcs.set = funcs->set; | 821 | pstate_funcs.set = funcs->set; |
822 | pstate_funcs.get_vid = funcs->get_vid; | ||
784 | } | 823 | } |
785 | 824 | ||
786 | #if IS_ENABLED(CONFIG_ACPI) | 825 | #if IS_ENABLED(CONFIG_ACPI) |
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index d02ccd19c9c4..45ea4c094542 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c | |||
@@ -138,7 +138,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy, | |||
138 | } | 138 | } |
139 | 139 | ||
140 | newfreq = clk_round_rate(srcclk, newfreq * mult); | 140 | newfreq = clk_round_rate(srcclk, newfreq * mult); |
141 | if (newfreq < 0) { | 141 | if (newfreq <= 0) { |
142 | pr_err("clk_round_rate failed for cpu src clock\n"); | 142 | pr_err("clk_round_rate failed for cpu src clock\n"); |
143 | return newfreq; | 143 | return newfreq; |
144 | } | 144 | } |