Commit 72e2adcd authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge back earlier 'pm-cpufreq' material.

parents 98a947ab 109df086
...@@ -181,7 +181,8 @@ config CPU_FREQ_GOV_CONSERVATIVE ...@@ -181,7 +181,8 @@ config CPU_FREQ_GOV_CONSERVATIVE
config GENERIC_CPUFREQ_CPU0 config GENERIC_CPUFREQ_CPU0
tristate "Generic CPU0 cpufreq driver" tristate "Generic CPU0 cpufreq driver"
depends on HAVE_CLK && REGULATOR && PM_OPP && OF depends on HAVE_CLK && REGULATOR && OF
select PM_OPP
help help
This adds a generic cpufreq driver for CPU0 frequency management. This adds a generic cpufreq driver for CPU0 frequency management.
It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
config ARM_BIG_LITTLE_CPUFREQ config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver" tristate "Generic ARM big LITTLE CPUfreq driver"
depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK depends on ARM && ARM_CPU_TOPOLOGY && HAVE_CLK
select PM_OPP
help help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
...@@ -54,7 +55,8 @@ config ARM_EXYNOS5250_CPUFREQ ...@@ -54,7 +55,8 @@ config ARM_EXYNOS5250_CPUFREQ
config ARM_EXYNOS5440_CPUFREQ config ARM_EXYNOS5440_CPUFREQ
bool "SAMSUNG EXYNOS5440" bool "SAMSUNG EXYNOS5440"
depends on SOC_EXYNOS5440 depends on SOC_EXYNOS5440
depends on HAVE_CLK && PM_OPP && OF depends on HAVE_CLK && OF
select PM_OPP
default y default y
help help
This adds the CPUFreq driver for Samsung EXYNOS5440 This adds the CPUFreq driver for Samsung EXYNOS5440
......
...@@ -44,7 +44,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index) ...@@ -44,7 +44,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
int ret; int ret;
freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
if (freq_Hz < 0) if (freq_Hz <= 0)
freq_Hz = freq_table[index].frequency * 1000; freq_Hz = freq_table[index].frequency * 1000;
freq_exact = freq_Hz; freq_exact = freq_Hz;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define SAMPLE_COUNT 3 #define SAMPLE_COUNT 3
#define BYT_RATIOS 0x66a #define BYT_RATIOS 0x66a
#define BYT_VIDS 0x66b
#define FRAC_BITS 8 #define FRAC_BITS 8
#define int_tofp(X) ((int64_t)(X) << FRAC_BITS) #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
...@@ -64,6 +65,12 @@ struct pstate_data { ...@@ -64,6 +65,12 @@ struct pstate_data {
int turbo_pstate; int turbo_pstate;
}; };
struct vid_data {
int32_t min;
int32_t max;
int32_t ratio;
};
struct _pid { struct _pid {
int setpoint; int setpoint;
int32_t integral; int32_t integral;
...@@ -82,10 +89,9 @@ struct cpudata { ...@@ -82,10 +89,9 @@ struct cpudata {
struct timer_list timer; struct timer_list timer;
struct pstate_data pstate; struct pstate_data pstate;
struct vid_data vid;
struct _pid pid; struct _pid pid;
int min_pstate_count;
u64 prev_aperf; u64 prev_aperf;
u64 prev_mperf; u64 prev_mperf;
int sample_ptr; int sample_ptr;
...@@ -106,7 +112,8 @@ struct pstate_funcs { ...@@ -106,7 +112,8 @@ struct pstate_funcs {
int (*get_max)(void); int (*get_max)(void);
int (*get_min)(void); int (*get_min)(void);
int (*get_turbo)(void); int (*get_turbo)(void);
void (*set)(int pstate); void (*set)(struct cpudata*, int pstate);
void (*get_vid)(struct cpudata *);
}; };
struct cpu_defaults { struct cpu_defaults {
...@@ -358,6 +365,42 @@ static int byt_get_max_pstate(void) ...@@ -358,6 +365,42 @@ static int byt_get_max_pstate(void)
return (value >> 16) & 0xFF; return (value >> 16) & 0xFF;
} }
static void byt_set_pstate(struct cpudata *cpudata, int pstate)
{
u64 val;
int32_t vid_fp;
u32 vid;
val = pstate << 8;
if (limits.no_turbo)
val |= (u64)1 << 32;
vid_fp = cpudata->vid.min + mul_fp(
int_tofp(pstate - cpudata->pstate.min_pstate),
cpudata->vid.ratio);
vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max);
vid = fp_toint(vid_fp);
val |= vid;
wrmsrl(MSR_IA32_PERF_CTL, val);
}
static void byt_get_vid(struct cpudata *cpudata)
{
u64 value;
rdmsrl(BYT_VIDS, value);
cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
cpudata->vid.ratio = div_fp(
cpudata->vid.max - cpudata->vid.min,
int_tofp(cpudata->pstate.max_pstate -
cpudata->pstate.min_pstate));
}
static int core_get_min_pstate(void) static int core_get_min_pstate(void)
{ {
u64 value; u64 value;
...@@ -384,7 +427,7 @@ static int core_get_turbo_pstate(void) ...@@ -384,7 +427,7 @@ static int core_get_turbo_pstate(void)
return ret; return ret;
} }
static void core_set_pstate(int pstate) static void core_set_pstate(struct cpudata *cpudata, int pstate)
{ {
u64 val; u64 val;
...@@ -425,7 +468,8 @@ static struct cpu_defaults byt_params = { ...@@ -425,7 +468,8 @@ static struct cpu_defaults byt_params = {
.get_max = byt_get_max_pstate, .get_max = byt_get_max_pstate,
.get_min = byt_get_min_pstate, .get_min = byt_get_min_pstate,
.get_turbo = byt_get_max_pstate, .get_turbo = byt_get_max_pstate,
.set = core_set_pstate, .set = byt_set_pstate,
.get_vid = byt_get_vid,
}, },
}; };
...@@ -462,7 +506,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) ...@@ -462,7 +506,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
cpu->pstate.current_pstate = pstate; cpu->pstate.current_pstate = pstate;
pstate_funcs.set(pstate); pstate_funcs.set(cpu, pstate);
} }
static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) 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,6 +532,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
cpu->pstate.max_pstate = pstate_funcs.get_max(); cpu->pstate.max_pstate = pstate_funcs.get_max();
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
if (pstate_funcs.get_vid)
pstate_funcs.get_vid(cpu);
/* /*
* goto max pstate so we don't slow up boot if we are built-in if we are * goto max pstate so we don't slow up boot if we are built-in if we are
* a module we will take care of it during normal operation * 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,15 +615,6 @@ static void intel_pstate_timer_func(unsigned long __data)
intel_pstate_sample(cpu); intel_pstate_sample(cpu);
intel_pstate_adjust_busy_pstate(cpu); intel_pstate_adjust_busy_pstate(cpu);
if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) {
cpu->min_pstate_count++;
if (!(cpu->min_pstate_count % 5)) {
intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
}
} else
cpu->min_pstate_count = 0;
intel_pstate_set_sample_time(cpu); intel_pstate_set_sample_time(cpu);
} }
...@@ -781,6 +819,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) ...@@ -781,6 +819,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs)
pstate_funcs.get_min = funcs->get_min; pstate_funcs.get_min = funcs->get_min;
pstate_funcs.get_turbo = funcs->get_turbo; pstate_funcs.get_turbo = funcs->get_turbo;
pstate_funcs.set = funcs->set; pstate_funcs.set = funcs->set;
pstate_funcs.get_vid = funcs->get_vid;
} }
#if IS_ENABLED(CONFIG_ACPI) #if IS_ENABLED(CONFIG_ACPI)
......
...@@ -138,7 +138,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy, ...@@ -138,7 +138,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
} }
newfreq = clk_round_rate(srcclk, newfreq * mult); newfreq = clk_round_rate(srcclk, newfreq * mult);
if (newfreq < 0) { if (newfreq <= 0) {
pr_err("clk_round_rate failed for cpu src clock\n"); pr_err("clk_round_rate failed for cpu src clock\n");
return newfreq; return newfreq;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment