Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
51c4c4ce
Commit
51c4c4ce
authored
Jan 14, 2014
by
Rafael J. Wysocki
Browse files
Options
Browse Files
Download
Plain Diff
Merge back earlier 'pm-cpufreq' material.
parents
6cbd7ee1
22c73795
Changes
40
Show whitespace changes
Inline
Side-by-side
Showing
40 changed files
with
511 additions
and
206 deletions
+511
-206
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/ABI/testing/sysfs-devices-system-cpu
+24
-0
Documentation/cpu-freq/intel-pstate.txt
Documentation/cpu-freq/intel-pstate.txt
+40
-0
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/common.c
+5
-0
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/common.h
+1
-0
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos4-dt.c
+1
-0
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
+1
-0
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig
+2
-1
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Kconfig.arm
+7
-5
drivers/cpufreq/arm_big_little.c
drivers/cpufreq/arm_big_little.c
+2
-1
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq-cpu0.c
+1
-1
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq.c
+57
-12
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/cpufreq_governor.c
+5
-1
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_governor.h
+2
-0
drivers/cpufreq/davinci-cpufreq.c
drivers/cpufreq/davinci-cpufreq.c
+1
-1
drivers/cpufreq/dbx500-cpufreq.c
drivers/cpufreq/dbx500-cpufreq.c
+2
-1
drivers/cpufreq/exynos-cpufreq.c
drivers/cpufreq/exynos-cpufreq.c
+12
-3
drivers/cpufreq/exynos5250-cpufreq.c
drivers/cpufreq/exynos5250-cpufreq.c
+10
-64
drivers/cpufreq/exynos5440-cpufreq.c
drivers/cpufreq/exynos5440-cpufreq.c
+2
-1
drivers/cpufreq/freq_table.c
drivers/cpufreq/freq_table.c
+22
-0
drivers/cpufreq/imx6q-cpufreq.c
drivers/cpufreq/imx6q-cpufreq.c
+95
-33
drivers/cpufreq/integrator-cpufreq.c
drivers/cpufreq/integrator-cpufreq.c
+1
-0
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/intel_pstate.c
+54
-15
drivers/cpufreq/kirkwood-cpufreq.c
drivers/cpufreq/kirkwood-cpufreq.c
+1
-0
drivers/cpufreq/omap-cpufreq.c
drivers/cpufreq/omap-cpufreq.c
+1
-1
drivers/cpufreq/pcc-cpufreq.c
drivers/cpufreq/pcc-cpufreq.c
+7
-11
drivers/cpufreq/powernow-k6.c
drivers/cpufreq/powernow-k6.c
+120
-27
drivers/cpufreq/powernow-k8.c
drivers/cpufreq/powernow-k8.c
+1
-6
drivers/cpufreq/pxa2xx-cpufreq.c
drivers/cpufreq/pxa2xx-cpufreq.c
+1
-0
drivers/cpufreq/pxa3xx-cpufreq.c
drivers/cpufreq/pxa3xx-cpufreq.c
+1
-0
drivers/cpufreq/s3c2416-cpufreq.c
drivers/cpufreq/s3c2416-cpufreq.c
+1
-1
drivers/cpufreq/s3c2440-cpufreq.c
drivers/cpufreq/s3c2440-cpufreq.c
+2
-4
drivers/cpufreq/s3c24xx-cpufreq.c
drivers/cpufreq/s3c24xx-cpufreq.c
+2
-2
drivers/cpufreq/s3c64xx-cpufreq.c
drivers/cpufreq/s3c64xx-cpufreq.c
+1
-1
drivers/cpufreq/s5pv210-cpufreq.c
drivers/cpufreq/s5pv210-cpufreq.c
+1
-1
drivers/cpufreq/sa1100-cpufreq.c
drivers/cpufreq/sa1100-cpufreq.c
+1
-1
drivers/cpufreq/sa1110-cpufreq.c
drivers/cpufreq/sa1110-cpufreq.c
+1
-1
drivers/cpufreq/spear-cpufreq.c
drivers/cpufreq/spear-cpufreq.c
+2
-2
drivers/cpufreq/tegra-cpufreq.c
drivers/cpufreq/tegra-cpufreq.c
+1
-0
drivers/cpufreq/unicore2-cpufreq.c
drivers/cpufreq/unicore2-cpufreq.c
+7
-9
include/linux/cpufreq.h
include/linux/cpufreq.h
+13
-0
No files found.
Documentation/ABI/testing/sysfs-devices-system-cpu
View file @
51c4c4ce
...
...
@@ -200,3 +200,27 @@ Description: address and size of the percpu note.
note of cpu#.
crash_notes_size: size of the note of cpu#.
What: /sys/devices/system/cpu/intel_pstate/max_perf_pct
/sys/devices/system/cpu/intel_pstate/min_perf_pct
/sys/devices/system/cpu/intel_pstate/no_turbo
Date: February 2013
Contact: linux-pm@vger.kernel.org
Description: Parameters for the Intel P-state driver
Logic for selecting the current P-state in Intel
Sandybridge+ processors. The three knobs control
limits for the P-state that will be requested by the
driver.
max_perf_pct: limits the maximum P state that will be requested by
the driver stated as a percentage of the available performance.
min_perf_pct: limits the minimum P state that will be requested by
the driver stated as a percentage of the available performance.
no_turbo: limits the driver to selecting P states below the turbo
frequency range.
More details can be found in Documentation/cpu-freq/intel-pstate.txt
Documentation/cpu-freq/intel-pstate.txt
0 → 100644
View file @
51c4c4ce
Intel P-state driver
--------------------
This driver implements a scaling driver with an internal governor for
Intel Core processors. The driver follows the same model as the
Transmeta scaling driver (longrun.c) and implements the setpolicy()
instead of target(). Scaling drivers that implement setpolicy() are
assumed to implement internal governors by the cpufreq core. All the
logic for selecting the current P state is contained within the
driver; no external governor is used by the cpufreq core.
Intel SandyBridge+ processors are supported.
New sysfs files for controlling P state selection have been added to
/sys/devices/system/cpu/intel_pstate/
max_perf_pct: limits the maximum P state that will be requested by
the driver stated as a percentage of the available performance.
min_perf_pct: limits the minimum P state that will be requested by
the driver stated as a percentage of the available performance.
no_turbo: limits the driver to selecting P states below the turbo
frequency range.
For contemporary Intel processors, the frequency is controlled by the
processor itself and the P-states exposed to software are related to
performance levels. The idea that frequency can be set to a single
frequency is fiction for Intel Core processors. Even if the scaling
driver selects a single P state the actual frequency the processor
will run at is selected by the processor itself.
New debugfs files have also been added to /sys/kernel/debug/pstate_snb/
deadband
d_gain_pct
i_gain_pct
p_gain_pct
sample_rate_ms
setpoint
arch/arm/mach-exynos/common.c
View file @
51c4c4ce
...
...
@@ -303,6 +303,11 @@ void __init exynos_cpuidle_init(void)
platform_device_register
(
&
exynos_cpuidle
);
}
void
__init
exynos_cpufreq_init
(
void
)
{
platform_device_register_simple
(
"exynos-cpufreq"
,
-
1
,
NULL
,
0
);
}
void
__init
exynos_init_late
(
void
)
{
if
(
of_machine_is_compatible
(
"samsung,exynos5440"
))
...
...
arch/arm/mach-exynos/common.h
View file @
51c4c4ce
...
...
@@ -22,6 +22,7 @@ void exynos_init_io(void);
void
exynos4_restart
(
enum
reboot_mode
mode
,
const
char
*
cmd
);
void
exynos5_restart
(
enum
reboot_mode
mode
,
const
char
*
cmd
);
void
exynos_cpuidle_init
(
void
);
void
exynos_cpufreq_init
(
void
);
void
exynos_init_late
(
void
);
void
exynos_firmware_init
(
void
);
...
...
arch/arm/mach-exynos/mach-exynos4-dt.c
View file @
51c4c4ce
...
...
@@ -22,6 +22,7 @@
static
void
__init
exynos4_dt_machine_init
(
void
)
{
exynos_cpuidle_init
();
exynos_cpufreq_init
();
of_platform_populate
(
NULL
,
of_default_bus_match_table
,
NULL
,
NULL
);
}
...
...
arch/arm/mach-exynos/mach-exynos5-dt.c
View file @
51c4c4ce
...
...
@@ -44,6 +44,7 @@ static void __init exynos5_dt_machine_init(void)
}
exynos_cpuidle_init
();
exynos_cpufreq_init
();
of_platform_populate
(
NULL
,
of_default_bus_match_table
,
NULL
,
NULL
);
}
...
...
drivers/cpufreq/Kconfig
View file @
51c4c4ce
...
...
@@ -181,7 +181,8 @@ config CPU_FREQ_GOV_CONSERVATIVE
config GENERIC_CPUFREQ_CPU0
tristate "Generic CPU0 cpufreq driver"
depends on HAVE_CLK && REGULATOR && PM_OPP && OF
depends on HAVE_CLK && REGULATOR && OF
select PM_OPP
help
This adds a generic cpufreq driver for CPU0 frequency management.
It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
...
...
drivers/cpufreq/Kconfig.arm
View file @
51c4c4ce
...
...
@@ -4,7 +4,8 @@
config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver"
depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK
depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK
select PM_OPP
help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
...
...
@@ -54,7 +55,8 @@ config ARM_EXYNOS5250_CPUFREQ
config ARM_EXYNOS5440_CPUFREQ
bool "SAMSUNG EXYNOS5440"
depends on SOC_EXYNOS5440
depends on HAVE_CLK && PM_OPP && OF
depends on HAVE_CLK && OF
select PM_OPP
default y
help
This adds the CPUFreq driver for Samsung EXYNOS5440
...
...
@@ -79,11 +81,11 @@ config ARM_HIGHBANK_CPUFREQ
If in doubt, say N.
config ARM_IMX6Q_CPUFREQ
tristate "Freescale i.MX6
Q
cpufreq support"
depends on
SOC_IMX6Q
tristate "Freescale i.MX6 cpufreq support"
depends on
ARCH_MXC
depends on REGULATOR_ANATOP
help
This adds cpufreq driver support for Freescale i.MX6
Q SOC
.
This adds cpufreq driver support for Freescale i.MX6
series SoCs
.
If in doubt, say N.
...
...
drivers/cpufreq/arm_big_little.c
View file @
51c4c4ce
...
...
@@ -488,7 +488,8 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
static
struct
cpufreq_driver
bL_cpufreq_driver
=
{
.
name
=
"arm-big-little"
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_HAVE_GOVERNOR_PER_POLICY
,
CPUFREQ_HAVE_GOVERNOR_PER_POLICY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
bL_cpufreq_set_target
,
.
get
=
bL_cpufreq_get_rate
,
...
...
drivers/cpufreq/cpufreq-cpu0.c
View file @
51c4c4ce
...
...
@@ -44,7 +44,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
int
ret
;
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_exact
=
freq_Hz
;
...
...
drivers/cpufreq/cpufreq.c
View file @
51c4c4ce
...
...
@@ -39,7 +39,7 @@ static struct cpufreq_driver *cpufreq_driver;
static
DEFINE_PER_CPU
(
struct
cpufreq_policy
*
,
cpufreq_cpu_data
);
static
DEFINE_PER_CPU
(
struct
cpufreq_policy
*
,
cpufreq_cpu_data_fallback
);
static
DEFINE_RWLOCK
(
cpufreq_driver_lock
);
static
DEFINE_MUTEX
(
cpufreq_governor_lock
);
DEFINE_MUTEX
(
cpufreq_governor_lock
);
static
LIST_HEAD
(
cpufreq_policy_list
);
#ifdef CONFIG_HOTPLUG_CPU
...
...
@@ -320,6 +320,20 @@ void cpufreq_notify_transition(struct cpufreq_policy *policy,
}
EXPORT_SYMBOL_GPL
(
cpufreq_notify_transition
);
/* Do post notifications when there are chances that transition has failed */
void
cpufreq_notify_post_transition
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_freqs
*
freqs
,
int
transition_failed
)
{
cpufreq_notify_transition
(
policy
,
freqs
,
CPUFREQ_POSTCHANGE
);
if
(
!
transition_failed
)
return
;
swap
(
freqs
->
old
,
freqs
->
new
);
cpufreq_notify_transition
(
policy
,
freqs
,
CPUFREQ_PRECHANGE
);
cpufreq_notify_transition
(
policy
,
freqs
,
CPUFREQ_POSTCHANGE
);
}
EXPORT_SYMBOL_GPL
(
cpufreq_notify_post_transition
);
/*********************************************************************
* SYSFS INTERFACE *
...
...
@@ -1059,6 +1073,46 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
}
}
/*
* Sometimes boot loaders set CPU frequency to a value outside of
* frequency table present with cpufreq core. In such cases CPU might be
* unstable if it has to run on that frequency for long duration of time
* and so its better to set it to a frequency which is specified in
* freq-table. This also makes cpufreq stats inconsistent as
* cpufreq-stats would fail to register because current frequency of CPU
* isn't found in freq-table.
*
* Because we don't want this change to effect boot process badly, we go
* for the next freq which is >= policy->cur ('cur' must be set by now,
* otherwise we will end up setting freq to lowest of the table as 'cur'
* is initialized to zero).
*
* We are passing target-freq as "policy->cur - 1" otherwise
* __cpufreq_driver_target() would simply fail, as policy->cur will be
* equal to target-freq.
*/
if
((
cpufreq_driver
->
flags
&
CPUFREQ_NEED_INITIAL_FREQ_CHECK
)
&&
has_target
())
{
/* Are we running at unknown frequency ? */
ret
=
cpufreq_frequency_table_get_index
(
policy
,
policy
->
cur
);
if
(
ret
==
-
EINVAL
)
{
/* Warn user and fix it */
pr_warn
(
"%s: CPU%d: Running at unlisted freq: %u KHz
\n
"
,
__func__
,
policy
->
cpu
,
policy
->
cur
);
ret
=
__cpufreq_driver_target
(
policy
,
policy
->
cur
-
1
,
CPUFREQ_RELATION_L
);
/*
* Reaching here after boot in a few seconds may not
* mean that system will remain stable at "unknown"
* frequency for longer duration. Hence, a BUG_ON().
*/
BUG_ON
(
ret
);
pr_warn
(
"%s: CPU%d: Unlisted initial frequency changed to: %u KHz
\n
"
,
__func__
,
policy
->
cpu
,
policy
->
cur
);
}
}
/* related cpus should atleast have policy->cpus */
cpumask_or
(
policy
->
related_cpus
,
policy
->
related_cpus
,
policy
->
cpus
);
...
...
@@ -1725,17 +1779,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
pr_err
(
"%s: Failed to change cpu frequency: %d
\n
"
,
__func__
,
retval
);
if
(
notify
)
{
/*
* Notify with old freq in case we failed to change
* frequency
*/
if
(
retval
)
freqs
.
new
=
freqs
.
old
;
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_POSTCHANGE
);
}
if
(
notify
)
cpufreq_notify_post_transition
(
policy
,
&
freqs
,
retval
);
}
out:
...
...
drivers/cpufreq/cpufreq_governor.c
View file @
51c4c4ce
...
...
@@ -119,8 +119,9 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
{
int
i
;
mutex_lock
(
&
cpufreq_governor_lock
);
if
(
!
policy
->
governor_enabled
)
return
;
goto
out_unlock
;
if
(
!
all_cpus
)
{
/*
...
...
@@ -135,6 +136,9 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
for_each_cpu
(
i
,
policy
->
cpus
)
__gov_queue_work
(
i
,
dbs_data
,
delay
);
}
out_unlock:
mutex_unlock
(
&
cpufreq_governor_lock
);
}
EXPORT_SYMBOL_GPL
(
gov_queue_work
);
...
...
drivers/cpufreq/cpufreq_governor.h
View file @
51c4c4ce
...
...
@@ -257,6 +257,8 @@ static ssize_t show_sampling_rate_min_gov_pol \
return sprintf(buf, "%u\n", dbs_data->min_sampling_rate); \
}
extern
struct
mutex
cpufreq_governor_lock
;
void
dbs_check_cpu
(
struct
dbs_data
*
dbs_data
,
int
cpu
);
bool
need_load_eval
(
struct
cpu_dbs_common_info
*
cdbs
,
unsigned
int
sampling_rate
);
...
...
drivers/cpufreq/davinci-cpufreq.c
View file @
51c4c4ce
...
...
@@ -126,7 +126,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
davinci_driver
=
{
.
flags
=
CPUFREQ_STICKY
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
davinci_verify_speed
,
.
target_index
=
davinci_target
,
.
get
=
davinci_getspeed
,
...
...
drivers/cpufreq/dbx500-cpufreq.c
View file @
51c4c4ce
...
...
@@ -48,7 +48,8 @@ static int dbx500_cpufreq_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
dbx500_cpufreq_driver
=
{
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_CONST_LOOPS
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_CONST_LOOPS
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
dbx500_cpufreq_target
,
.
get
=
dbx500_cpufreq_getspeed
,
...
...
drivers/cpufreq/exynos-cpufreq.c
View file @
51c4c4ce
...
...
@@ -17,6 +17,7 @@
#include <linux/regulator/consumer.h>
#include <linux/cpufreq.h>
#include <linux/suspend.h>
#include <linux/platform_device.h>
#include <plat/cpu.h>
...
...
@@ -218,7 +219,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
exynos_driver
=
{
.
flags
=
CPUFREQ_STICKY
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
exynos_target
,
.
get
=
exynos_getspeed
,
...
...
@@ -232,7 +233,7 @@ static struct cpufreq_driver exynos_driver = {
#endif
};
static
int
__init
exynos_cpufreq_init
(
void
)
static
int
exynos_cpufreq_probe
(
struct
platform_device
*
pdev
)
{
int
ret
=
-
EINVAL
;
...
...
@@ -281,4 +282,12 @@ static int __init exynos_cpufreq_init(void)
kfree
(
exynos_info
);
return
-
EINVAL
;
}
late_initcall
(
exynos_cpufreq_init
);
static
struct
platform_driver
exynos_cpufreq_platdrv
=
{
.
driver
=
{
.
name
=
"exynos-cpufreq"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
exynos_cpufreq_probe
,
};
module_platform_driver
(
exynos_cpufreq_platdrv
);
drivers/cpufreq/exynos5250-cpufreq.c
View file @
51c4c4ce
...
...
@@ -102,12 +102,12 @@ static void set_clkdiv(unsigned int div_index)
cpu_relax
();
}
static
void
set_apll
(
unsigned
int
new_index
,
unsigned
int
old_index
)
static
void
set_apll
(
unsigned
int
index
)
{
unsigned
int
tmp
,
pdiv
;
unsigned
int
tmp
;
unsigned
int
freq
=
apll_freq_5250
[
index
].
freq
;
/*
1.
MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
/* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
clk_set_parent
(
moutcore
,
mout_mpll
);
do
{
...
...
@@ -116,24 +116,9 @@ static void set_apll(unsigned int new_index,
tmp
&=
0x7
;
}
while
(
tmp
!=
0x2
);
/* 2. Set APLL Lock time */
pdiv
=
((
apll_freq_5250
[
new_index
].
mps
>>
8
)
&
0x3f
);
__raw_writel
((
pdiv
*
250
),
EXYNOS5_APLL_LOCK
);
/* 3. Change PLL PMS values */
tmp
=
__raw_readl
(
EXYNOS5_APLL_CON0
);
tmp
&=
~
((
0x3ff
<<
16
)
|
(
0x3f
<<
8
)
|
(
0x7
<<
0
));
tmp
|=
apll_freq_5250
[
new_index
].
mps
;
__raw_writel
(
tmp
,
EXYNOS5_APLL_CON0
);
clk_set_rate
(
mout_apll
,
freq
*
1000
);
/* 4. wait_lock_time */
do
{
cpu_relax
();
tmp
=
__raw_readl
(
EXYNOS5_APLL_CON0
);
}
while
(
!
(
tmp
&
(
0x1
<<
29
)));
/* 5. MUX_CORE_SEL = APLL */
/* MUX_CORE_SEL = APLL */
clk_set_parent
(
moutcore
,
mout_apll
);
do
{
...
...
@@ -141,55 +126,17 @@ static void set_apll(unsigned int new_index,
tmp
=
__raw_readl
(
EXYNOS5_CLKMUX_STATCPU
);
tmp
&=
(
0x7
<<
16
);
}
while
(
tmp
!=
(
0x1
<<
16
));
}
static
bool
exynos5250_pms_change
(
unsigned
int
old_index
,
unsigned
int
new_index
)
{
unsigned
int
old_pm
=
apll_freq_5250
[
old_index
].
mps
>>
8
;
unsigned
int
new_pm
=
apll_freq_5250
[
new_index
].
mps
>>
8
;
return
(
old_pm
==
new_pm
)
?
0
:
1
;
}
static
void
exynos5250_set_frequency
(
unsigned
int
old_index
,
unsigned
int
new_index
)
{
unsigned
int
tmp
;
if
(
old_index
>
new_index
)
{
if
(
!
exynos5250_pms_change
(
old_index
,
new_index
))
{
/* 1. Change the system clock divider values */
set_clkdiv
(
new_index
);
/* 2. Change just s value in apll m,p,s value */
tmp
=
__raw_readl
(
EXYNOS5_APLL_CON0
);
tmp
&=
~
(
0x7
<<
0
);
tmp
|=
apll_freq_5250
[
new_index
].
mps
&
0x7
;
__raw_writel
(
tmp
,
EXYNOS5_APLL_CON0
);
}
else
{
/* Clock Configuration Procedure */
/* 1. Change the system clock divider values */
set_clkdiv
(
new_index
);
/* 2. Change the apll m,p,s value */
set_apll
(
new_index
,
old_index
);
}
set_apll
(
new_index
);
}
else
if
(
old_index
<
new_index
)
{
if
(
!
exynos5250_pms_change
(
old_index
,
new_index
))
{
/* 1. Change just s value in apll m,p,s value */
tmp
=
__raw_readl
(
EXYNOS5_APLL_CON0
);
tmp
&=
~
(
0x7
<<
0
);
tmp
|=
apll_freq_5250
[
new_index
].
mps
&
0x7
;
__raw_writel
(
tmp
,
EXYNOS5_APLL_CON0
);
/* 2. Change the system clock divider values */
set_apll
(
new_index
);
set_clkdiv
(
new_index
);
}
else
{
/* Clock Configuration Procedure */
/* 1. Change the apll m,p,s value */
set_apll
(
new_index
,
old_index
);
/* 2. Change the system clock divider values */
set_clkdiv
(
new_index
);
}
}
}
...
...
@@ -222,7 +169,6 @@ int exynos5250_cpufreq_init(struct exynos_dvfs_info *info)
info
->
volt_table
=
exynos5250_volt_table
;
info
->
freq_table
=
exynos5250_freq_table
;
info
->
set_freq
=
exynos5250_set_frequency
;
info
->
need_apll_change
=
exynos5250_pms_change
;
return
0
;
...
...
drivers/cpufreq/exynos5440-cpufreq.c
View file @
51c4c4ce
...
...
@@ -312,7 +312,8 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
exynos_driver
=
{
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_ASYNC_NOTIFICATION
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_ASYNC_NOTIFICATION
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
exynos_target
,
.
get
=
exynos_getspeed
,
...
...
drivers/cpufreq/freq_table.c
View file @
51c4c4ce
...
...
@@ -178,7 +178,29 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
}
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_target
);
int
cpufreq_frequency_table_get_index
(
struct
cpufreq_policy
*
policy
,
unsigned
int
freq
)
{
struct
cpufreq_frequency_table
*
table
;
int
i
;
table
=
cpufreq_frequency_get_table
(
policy
->
cpu
);
if
(
unlikely
(
!
table
))
{
pr_debug
(
"%s: Unable to find frequency table
\n
"
,
__func__
);
return
-
ENOENT
;
}
for
(
i
=
0
;
table
[
i
].
frequency
!=
CPUFREQ_TABLE_END
;
i
++
)
{
if
(
table
[
i
].
frequency
==
freq
)
return
i
;
}
return
-
EINVAL
;
}
EXPORT_SYMBOL_GPL
(
cpufreq_frequency_table_get_index
);
static
DEFINE_PER_CPU
(
struct
cpufreq_frequency_table
*
,
cpufreq_show_table
);
/**
* show_available_freqs - show available frequencies for the specified CPU
*/
...
...
drivers/cpufreq/imx6q-cpufreq.c
View file @
51c4c4ce
...
...
@@ -35,6 +35,9 @@ static struct device *cpu_dev;
static
struct
cpufreq_frequency_table
*
freq_table
;
static
unsigned
int
transition_latency
;
static
u32
*
imx6_soc_volt
;
static
u32
soc_opp_count
;
static
unsigned
int
imx6q_get_speed
(
unsigned
int
cpu
)
{
return
clk_get_rate
(
arm_clk
)
/
1000
;
...
...
@@ -69,23 +72,22 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
/* scaling up? scale voltage before frequency */
if
(
new_freq
>
old_freq
)
{
ret
=
regulator_set_voltage_tol
(
pu_reg
,
imx6_soc_volt
[
index
],
0
);
if
(
ret
)
{
dev_err
(
cpu_dev
,
"failed to scale vddpu up: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
regulator_set_voltage_tol
(
soc_reg
,
imx6_soc_volt
[
index
],
0
);
if
(
ret
)
{
dev_err
(
cpu_dev
,
"failed to scale vddsoc up: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
regulator_set_voltage_tol
(
arm_reg
,
volt
,
0
);
if
(
ret
)
{
dev_err
(
cpu_dev
,
"failed to scale vddarm up: %d
\n
"
,
ret
);
return
ret
;
}
/*
* Need to increase vddpu and vddsoc for safety
* if we are about to run at 1.2 GHz.
*/
if
(
new_freq
==
FREQ_1P2_GHZ
/
1000
)
{
regulator_set_voltage_tol
(
pu_reg
,
PU_SOC_VOLTAGE_HIGH
,
0
);
regulator_set_voltage_tol
(
soc_reg
,
PU_SOC_VOLTAGE_HIGH
,
0
);
}
}
/*
...
...
@@ -120,12 +122,15 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
"failed to scale vddarm down: %d
\n
"
,
ret
);
ret
=
0
;
}
if
(
old_freq
==
FREQ_1P2_GHZ
/
1000
)
{
regulator_set_voltage_tol
(
pu_reg
,
PU_SOC_VOLTAGE_NORMAL
,
0
);
regulator_set_voltage_tol
(
soc_reg
,
PU_SOC_VOLTAGE_NORMAL
,
0
);
ret
=
regulator_set_voltage_tol
(
soc_reg
,
imx6_soc_volt
[
index
],
0
);
if
(
ret
)
{
dev_warn
(
cpu_dev
,
"failed to scale vddsoc down: %d
\n
"
,
ret
);
ret
=
0
;
}
ret
=
regulator_set_voltage_tol
(
pu_reg
,
imx6_soc_volt
[
index
],
0
);
if
(
ret
)
{
dev_warn
(
cpu_dev
,
"failed to scale vddpu down: %d
\n
"
,
ret
);
ret
=
0
;
}
}
...
...
@@ -138,6 +143,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
imx6q_cpufreq_driver
=
{
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
imx6q_set_target
,
.
get
=
imx6q_get_speed
,
...
...
@@ -153,6 +159,9 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
struct
dev_pm_opp
*
opp
;
unsigned
long
min_volt
,
max_volt
;
int
num
,
ret
;
const
struct
property
*
prop
;
const
__be32
*
val
;
u32
nr
,
i
,
j
;
cpu_dev
=
get_cpu_device
(
0
);
if
(
!
cpu_dev
)
{
...
...
@@ -187,13 +196,26 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
goto
put_node
;
}
/* We expect an OPP table supplied by platform */
/*
* We expect an OPP table supplied by platform.
* Just, incase the platform did not supply the OPP
* table, it will try to get it.
*/
num
=
dev_pm_opp_get_opp_count
(
cpu_dev
);
if
(
num
<
0
)
{
ret
=
of_init_opp_table
(
cpu_dev
);
if
(
ret
<
0
)
{
dev_err
(
cpu_dev
,
"failed to init OPP table: %d
\n
"
,
ret
);
goto
put_node
;
}
num
=
dev_pm_opp_get_opp_count
(
cpu_dev
);
if
(
num
<
0
)
{
ret
=
num
;
dev_err
(
cpu_dev
,
"no OPP table is found: %d
\n
"
,
ret
);
goto
put_node
;
}
}
ret
=
dev_pm_opp_init_cpufreq_table
(
cpu_dev
,
&
freq_table
);
if
(
ret
)
{
...
...
@@ -201,9 +223,61 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
goto
put_node
;
}
/* Make imx6_soc_volt array's size same as arm opp number */
imx6_soc_volt
=
devm_kzalloc
(
cpu_dev
,
sizeof
(
*
imx6_soc_volt
)
*
num
,
GFP_KERNEL
);
if
(
imx6_soc_volt
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
free_freq_table
;
}
prop
=
of_find_property
(
np
,
"fsl,soc-operating-points"
,
NULL
);
if
(
!
prop
||
!
prop
->
value
)
goto
soc_opp_out
;
/*
* Each OPP is a set of tuples consisting of frequency and
* voltage like <freq-kHz vol-uV>.
*/
nr
=
prop
->
length
/
sizeof
(
u32
);
if
(
nr
%
2
||
(
nr
/
2
)
<
num
)
goto
soc_opp_out
;
for
(
j
=
0
;
j
<
num
;
j
++
)
{
val
=
prop
->
value
;
for
(
i
=
0
;
i
<
nr
/
2
;
i
++
)
{
unsigned
long
freq
=
be32_to_cpup
(
val
++
);
unsigned
long
volt
=
be32_to_cpup
(
val
++
);
if
(
freq_table
[
j
].
frequency
==
freq
)
{
imx6_soc_volt
[
soc_opp_count
++
]
=
volt
;
break
;
}
}
}
soc_opp_out:
/* use fixed soc opp volt if no valid soc opp info found in dtb */
if
(
soc_opp_count
!=
num
)
{
dev_warn
(
cpu_dev
,
"can NOT find valid fsl,soc-operating-points property in dtb, use default value!
\n
"
);
for
(
j
=
0
;
j
<
num
;
j
++
)
imx6_soc_volt
[
j
]
=
PU_SOC_VOLTAGE_NORMAL
;
if
(
freq_table
[
num
-
1
].
frequency
*
1000
==
FREQ_1P2_GHZ
)
imx6_soc_volt
[
num
-
1
]
=
PU_SOC_VOLTAGE_HIGH
;
}
if
(
of_property_read_u32
(
np
,
"clock-latency"
,
&
transition_latency
))
transition_latency
=
CPUFREQ_ETERNAL
;
/*
* Calculate the ramp time for max voltage change in the
* VDDSOC and VDDPU regulators.
*/
ret
=
regulator_set_voltage_time
(
soc_reg
,
imx6_soc_volt
[
0
],
imx6_soc_volt
[
num
-
1
]);
if
(
ret
>
0
)
transition_latency
+=
ret
*
1000
;
ret
=
regulator_set_voltage_time
(
pu_reg
,
imx6_soc_volt
[
0
],
imx6_soc_volt
[
num
-
1
]);
if
(
ret
>
0
)
transition_latency
+=
ret
*
1000
;
/*
* OPP is maintained in order of increasing frequency, and
* freq_table initialised from OPP is therefore sorted in the
...
...
@@ -221,18 +295,6 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
if
(
ret
>
0
)
transition_latency
+=
ret
*
1000
;
/* Count vddpu and vddsoc latency in for 1.2 GHz support */
if
(
freq_table
[
num
].
frequency
==
FREQ_1P2_GHZ
/
1000
)
{
ret
=
regulator_set_voltage_time
(
pu_reg
,
PU_SOC_VOLTAGE_NORMAL
,
PU_SOC_VOLTAGE_HIGH
);
if
(
ret
>
0
)
transition_latency
+=
ret
*
1000
;
ret
=
regulator_set_voltage_time
(
soc_reg
,
PU_SOC_VOLTAGE_NORMAL
,
PU_SOC_VOLTAGE_HIGH
);
if
(
ret
>
0
)
transition_latency
+=
ret
*
1000
;
}
ret
=
cpufreq_register_driver
(
&
imx6q_cpufreq_driver
);
if
(
ret
)
{
dev_err
(
cpu_dev
,
"failed register driver: %d
\n
"
,
ret
);
...
...
drivers/cpufreq/integrator-cpufreq.c
View file @
51c4c4ce
...
...
@@ -190,6 +190,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
integrator_driver
=
{
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
integrator_verify_policy
,
.
target
=
integrator_set_target
,
.
get
=
integrator_get
,
...
...
drivers/cpufreq/intel_pstate.c
View file @
51c4c4ce
...
...
@@ -35,6 +35,7 @@
#define SAMPLE_COUNT 3
#define BYT_RATIOS 0x66a
#define BYT_VIDS 0x66b
#define FRAC_BITS 8
#define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
...
...
@@ -64,6 +65,12 @@ struct pstate_data {
int
turbo_pstate
;
};
struct
vid_data
{
int32_t
min
;
int32_t
max
;
int32_t
ratio
;
};
struct
_pid
{
int
setpoint
;
int32_t
integral
;
...
...
@@ -82,10 +89,9 @@ struct cpudata {
struct
timer_list
timer
;
struct
pstate_data
pstate
;
struct
vid_data
vid
;
struct
_pid
pid
;
int
min_pstate_count
;
u64
prev_aperf
;
u64
prev_mperf
;
int
sample_ptr
;
...
...
@@ -106,7 +112,8 @@ struct pstate_funcs {
int
(
*
get_max
)(
void
);
int
(
*
get_min
)(
void
);
int
(
*
get_turbo
)(
void
);
void
(
*
set
)(
int
pstate
);
void
(
*
set
)(
struct
cpudata
*
,
int
pstate
);
void
(
*
get_vid
)(
struct
cpudata
*
);
};
struct
cpu_defaults
{
...
...
@@ -358,6 +365,42 @@ static int byt_get_max_pstate(void)
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
)
{
u64
value
;
...
...
@@ -384,7 +427,7 @@ static int core_get_turbo_pstate(void)
return
ret
;
}
static
void
core_set_pstate
(
int
pstate
)
static
void
core_set_pstate
(
struct
cpudata
*
cpudata
,
int
pstate
)
{
u64
val
;
...
...
@@ -425,7 +468,8 @@ static struct cpu_defaults byt_params = {
.
get_max
=
byt_get_max_pstate
,
.
get_min
=
byt_get_min_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)
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
)
...
...
@@ -488,6 +532,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
cpu
->
pstate
.
max_pstate
=
pstate_funcs
.
get_max
();
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
* a module we will take care of it during normal operation
...
...
@@ -568,15 +615,6 @@ static void intel_pstate_timer_func(unsigned long __data)
intel_pstate_sample
(
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
);
}
...
...
@@ -782,6 +820,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs)
pstate_funcs
.
get_min
=
funcs
->
get_min
;
pstate_funcs
.
get_turbo
=
funcs
->
get_turbo
;
pstate_funcs
.
set
=
funcs
->
set
;
pstate_funcs
.
get_vid
=
funcs
->
get_vid
;
}
#if IS_ENABLED(CONFIG_ACPI)
...
...
drivers/cpufreq/kirkwood-cpufreq.c
View file @
51c4c4ce
...
...
@@ -97,6 +97,7 @@ static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
kirkwood_cpufreq_driver
=
{
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
get
=
kirkwood_cpufreq_get_cpu_frequency
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
kirkwood_cpufreq_target
,
...
...
drivers/cpufreq/omap-cpufreq.c
View file @
51c4c4ce
...
...
@@ -162,7 +162,7 @@ static int omap_cpu_exit(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
omap_driver
=
{
.
flags
=
CPUFREQ_STICKY
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
omap_target
,
.
get
=
omap_getspeed
,
...
...
drivers/cpufreq/pcc-cpufreq.c
View file @
51c4c4ce
...
...
@@ -213,6 +213,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
cpu
,
target_freq
,
(
pcch_virt_addr
+
pcc_cpu_data
->
input_offset
));
freqs
.
old
=
policy
->
cur
;
freqs
.
new
=
target_freq
;
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_PRECHANGE
);
...
...
@@ -228,25 +229,20 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
memset_io
((
pcch_virt_addr
+
pcc_cpu_data
->
input_offset
),
0
,
BUF_SZ
);
status
=
ioread16
(
&
pcch_hdr
->
status
);
iowrite16
(
0
,
&
pcch_hdr
->
status
);
cpufreq_notify_post_transition
(
policy
,
&
freqs
,
status
!=
CMD_COMPLETE
);
spin_unlock
(
&
pcc_lock
);
if
(
status
!=
CMD_COMPLETE
)
{
pr_debug
(
"target: FAILED for cpu %d, with status: 0x%x
\n
"
,
cpu
,
status
);
goto
cmd_incomplete
;
return
-
EINVAL
;
}
iowrite16
(
0
,
&
pcch_hdr
->
status
);
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_POSTCHANGE
);
pr_debug
(
"target: was SUCCESSFUL for cpu %d
\n
"
,
cpu
);
spin_unlock
(
&
pcc_lock
);
return
0
;
cmd_incomplete:
freqs
.
new
=
freqs
.
old
;
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_POSTCHANGE
);
iowrite16
(
0
,
&
pcch_hdr
->
status
);
spin_unlock
(
&
pcc_lock
);
return
-
EINVAL
;
}
static
int
pcc_get_offset
(
int
cpu
)
...
...
drivers/cpufreq/powernow-k6.c
View file @
51c4c4ce
...
...
@@ -26,20 +26,52 @@
static
unsigned
int
busfreq
;
/* FSB, in 10 kHz */
static
unsigned
int
max_multiplier
;
static
unsigned
int
param_busfreq
=
0
;
static
unsigned
int
param_max_multiplier
=
0
;
module_param_named
(
max_multiplier
,
param_max_multiplier
,
uint
,
S_IRUGO
);
MODULE_PARM_DESC
(
max_multiplier
,
"Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)"
);
module_param_named
(
bus_frequency
,
param_busfreq
,
uint
,
S_IRUGO
);
MODULE_PARM_DESC
(
bus_frequency
,
"Bus frequency in kHz"
);
/* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
static
struct
cpufreq_frequency_table
clock_ratio
[]
=
{
{
45
,
/* 000 -> 4.5x */
0
},
{
60
,
/* 110 -> 6.0x */
0
},
{
55
,
/* 011 -> 5.5x */
0
},
{
50
,
/* 001 -> 5.0x */
0
},
{
45
,
/* 000 -> 4.5x */
0
},
{
40
,
/* 010 -> 4.0x */
0
},
{
55
,
/* 011 -> 5.5x */
0
},
{
20
,
/* 100 -> 2.0x */
0
},
{
30
,
/* 101 -> 3.0x */
0
},
{
60
,
/* 110 -> 6.0x */
0
},
{
35
,
/* 111 -> 3.5x */
0
},
{
30
,
/* 101 -> 3.0x */
0
},
{
20
,
/* 100 -> 2.0x */
0
},
{
0
,
CPUFREQ_TABLE_END
}
};
static
const
u8
index_to_register
[
8
]
=
{
6
,
3
,
1
,
0
,
2
,
7
,
5
,
4
};
static
const
u8
register_to_index
[
8
]
=
{
3
,
2
,
4
,
1
,
7
,
6
,
0
,
5
};
static
const
struct
{
unsigned
freq
;
unsigned
mult
;
}
usual_frequency_table
[]
=
{
{
400000
,
40
},
// 100 * 4
{
450000
,
45
},
// 100 * 4.5
{
475000
,
50
},
// 95 * 5
{
500000
,
50
},
// 100 * 5
{
506250
,
45
},
// 112.5 * 4.5
{
533500
,
55
},
// 97 * 5.5
{
550000
,
55
},
// 100 * 5.5
{
562500
,
50
},
// 112.5 * 5
{
570000
,
60
},
// 95 * 6
{
600000
,
60
},
// 100 * 6
{
618750
,
55
},
// 112.5 * 5.5
{
660000
,
55
},
// 120 * 5.5
{
675000
,
60
},
// 112.5 * 6
{
720000
,
60
},
// 120 * 6
};
#define FREQ_RANGE 3000
/**
* powernow_k6_get_cpu_multiplier - returns the current FSB multiplier
...
...
@@ -49,18 +81,53 @@ static struct cpufreq_frequency_table clock_ratio[] = {
*/
static
int
powernow_k6_get_cpu_multiplier
(
void
)
{
u
64
invalue
=
0
;
u
nsigned
long
invalue
=
0
;
u32
msrval
;
local_irq_disable
();
msrval
=
POWERNOW_IOPORT
+
0x1
;
wrmsr
(
MSR_K6_EPMR
,
msrval
,
0
);
/* enable the PowerNow port */
invalue
=
inl
(
POWERNOW_IOPORT
+
0x8
);
msrval
=
POWERNOW_IOPORT
+
0x0
;
wrmsr
(
MSR_K6_EPMR
,
msrval
,
0
);
/* disable it again */
return
clock_ratio
[(
invalue
>>
5
)
&
7
].
driver_data
;
local_irq_enable
();
return
clock_ratio
[
register_to_index
[(
invalue
>>
5
)
&
7
]].
driver_data
;
}
static
void
powernow_k6_set_cpu_multiplier
(
unsigned
int
best_i
)
{
unsigned
long
outvalue
,
invalue
;
unsigned
long
msrval
;
unsigned
long
cr0
;
/* we now need to transform best_i to the BVC format, see AMD#23446 */
/*
* The processor doesn't respond to inquiry cycles while changing the
* frequency, so we must disable cache.
*/
local_irq_disable
();
cr0
=
read_cr0
();
write_cr0
(
cr0
|
X86_CR0_CD
);
wbinvd
();
outvalue
=
(
1
<<
12
)
|
(
1
<<
10
)
|
(
1
<<
9
)
|
(
index_to_register
[
best_i
]
<<
5
);
msrval
=
POWERNOW_IOPORT
+
0x1
;
wrmsr
(
MSR_K6_EPMR
,
msrval
,
0
);
/* enable the PowerNow port */
invalue
=
inl
(
POWERNOW_IOPORT
+
0x8
);
invalue
=
invalue
&
0x1f
;
outvalue
=
outvalue
|
invalue
;
outl
(
outvalue
,
(
POWERNOW_IOPORT
+
0x8
));
msrval
=
POWERNOW_IOPORT
+
0x0
;
wrmsr
(
MSR_K6_EPMR
,
msrval
,
0
);
/* disable it again */
write_cr0
(
cr0
);
local_irq_enable
();
}
/**
* powernow_k6_target - set the PowerNow! multiplier
...
...
@@ -71,8 +138,6 @@ static int powernow_k6_get_cpu_multiplier(void)
static
int
powernow_k6_target
(
struct
cpufreq_policy
*
policy
,
unsigned
int
best_i
)
{
unsigned
long
outvalue
=
0
,
invalue
=
0
;
unsigned
long
msrval
;
struct
cpufreq_freqs
freqs
;
if
(
clock_ratio
[
best_i
].
driver_data
>
max_multiplier
)
{
...
...
@@ -85,35 +150,63 @@ static int powernow_k6_target(struct cpufreq_policy *policy,
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_PRECHANGE
);
/* we now need to transform best_i to the BVC format, see AMD#23446 */
outvalue
=
(
1
<<
12
)
|
(
1
<<
10
)
|
(
1
<<
9
)
|
(
best_i
<<
5
);
msrval
=
POWERNOW_IOPORT
+
0x1
;
wrmsr
(
MSR_K6_EPMR
,
msrval
,
0
);
/* enable the PowerNow port */
invalue
=
inl
(
POWERNOW_IOPORT
+
0x8
);
invalue
=
invalue
&
0xf
;
outvalue
=
outvalue
|
invalue
;
outl
(
outvalue
,
(
POWERNOW_IOPORT
+
0x8
));
msrval
=
POWERNOW_IOPORT
+
0x0
;
wrmsr
(
MSR_K6_EPMR
,
msrval
,
0
);
/* disable it again */
powernow_k6_set_cpu_multiplier
(
best_i
);
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_POSTCHANGE
);
return
0
;
}
static
int
powernow_k6_cpu_init
(
struct
cpufreq_policy
*
policy
)
{
unsigned
int
i
,
f
;
unsigned
khz
;
if
(
policy
->
cpu
!=
0
)
return
-
ENODEV
;
/* get frequencies */
max_multiplier
=
powernow_k6_get_cpu_multiplier
();
busfreq
=
cpu_khz
/
max_multiplier
;
max_multiplier
=
0
;
khz
=
cpu_khz
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
usual_frequency_table
);
i
++
)
{
if
(
khz
>=
usual_frequency_table
[
i
].
freq
-
FREQ_RANGE
&&
khz
<=
usual_frequency_table
[
i
].
freq
+
FREQ_RANGE
)
{
khz
=
usual_frequency_table
[
i
].
freq
;
max_multiplier
=
usual_frequency_table
[
i
].
mult
;
break
;
}
}
if
(
param_max_multiplier
)
{
for
(
i
=
0
;
(
clock_ratio
[
i
].
frequency
!=
CPUFREQ_TABLE_END
);
i
++
)
{
if
(
clock_ratio
[
i
].
driver_data
==
param_max_multiplier
)
{
max_multiplier
=
param_max_multiplier
;
goto
have_max_multiplier
;
}
}
printk
(
KERN_ERR
"powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60
\n
"
);
return
-
EINVAL
;
}
if
(
!
max_multiplier
)
{
printk
(
KERN_WARNING
"powernow-k6: unknown frequency %u, cannot determine current multiplier
\n
"
,
khz
);
printk
(
KERN_WARNING
"powernow-k6: use module parameters max_multiplier and bus_frequency
\n
"
);
return
-
EOPNOTSUPP
;
}
have_max_multiplier:
param_max_multiplier
=
max_multiplier
;
if
(
param_busfreq
)
{
if
(
param_busfreq
>=
50000
&&
param_busfreq
<=
150000
)
{
busfreq
=
param_busfreq
/
10
;
goto
have_busfreq
;
}
printk
(
KERN_ERR
"powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz
\n
"
);
return
-
EINVAL
;
}
busfreq
=
khz
/
max_multiplier
;
have_busfreq:
param_busfreq
=
busfreq
*
10
;
/* table init */
for
(
i
=
0
;
(
clock_ratio
[
i
].
frequency
!=
CPUFREQ_TABLE_END
);
i
++
)
{
...
...
@@ -125,7 +218,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
}
/* cpuinfo and default policy values */
policy
->
cpuinfo
.
transition_latency
=
2
00000
;
policy
->
cpuinfo
.
transition_latency
=
5
00000
;
return
cpufreq_table_validate_and_show
(
policy
,
clock_ratio
);
}
...
...
drivers/cpufreq/powernow-k8.c
View file @
51c4c4ce
...
...
@@ -964,14 +964,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
cpufreq_cpu_put
(
policy
);
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_PRECHANGE
);
res
=
transition_fid_vid
(
data
,
fid
,
vid
);
if
(
res
)
freqs
.
new
=
freqs
.
old
;
else
freqs
.
new
=
find_khz_freq_from_fid
(
data
->
currfid
);
cpufreq_notify_post_transition
(
policy
,
&
freqs
,
res
);
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_POSTCHANGE
);
return
res
;
}
...
...
drivers/cpufreq/pxa2xx-cpufreq.c
View file @
51c4c4ce
...
...
@@ -423,6 +423,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
pxa_cpufreq_driver
=
{
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
pxa_set_target
,
.
init
=
pxa_cpufreq_init
,
...
...
drivers/cpufreq/pxa3xx-cpufreq.c
View file @
51c4c4ce
...
...
@@ -201,6 +201,7 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
pxa3xx_cpufreq_driver
=
{
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
pxa3xx_cpufreq_set
,
.
init
=
pxa3xx_cpufreq_init
,
...
...
drivers/cpufreq/s3c2416-cpufreq.c
View file @
51c4c4ce
...
...
@@ -481,7 +481,7 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
s3c2416_cpufreq_driver
=
{
.
flags
=
0
,
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
s3c2416_cpufreq_set_target
,
.
get
=
s3c2416_cpufreq_get_speed
,
...
...
drivers/cpufreq/s3c2440-cpufreq.c
View file @
51c4c4ce
...
...
@@ -22,8 +22,6 @@
#include <linux/err.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
...
...
@@ -55,7 +53,7 @@ static inline int within_khz(unsigned long a, unsigned long b)
* specified in @cfg. The values are stored in @cfg for later use
* by the relevant set routine if the request settings can be reached.
*/
int
s3c2440_cpufreq_calcdivs
(
struct
s3c_cpufreq_config
*
cfg
)
static
int
s3c2440_cpufreq_calcdivs
(
struct
s3c_cpufreq_config
*
cfg
)
{
unsigned
int
hdiv
,
pdiv
;
unsigned
long
hclk
,
fclk
,
armclk
;
...
...
@@ -242,7 +240,7 @@ static int s3c2440_cpufreq_calctable(struct s3c_cpufreq_config *cfg,
return
ret
;
}
struct
s3c_cpufreq_info
s3c2440_cpufreq_info
=
{
st
atic
st
ruct
s3c_cpufreq_info
s3c2440_cpufreq_info
=
{
.
max
=
{
.
fclk
=
400000000
,
.
hclk
=
133333333
,
...
...
drivers/cpufreq/s3c24xx-cpufreq.c
View file @
51c4c4ce
...
...
@@ -448,7 +448,7 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy)
#endif
static
struct
cpufreq_driver
s3c24xx_driver
=
{
.
flags
=
CPUFREQ_STICKY
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
target
=
s3c_cpufreq_target
,
.
get
=
s3c_cpufreq_get
,
.
init
=
s3c_cpufreq_init
,
...
...
@@ -509,7 +509,7 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
return
0
;
}
int
__init
s3c_cpufreq_auto_io
(
void
)
static
int
__init
s3c_cpufreq_auto_io
(
void
)
{
int
ret
;
...
...
drivers/cpufreq/s3c64xx-cpufreq.c
View file @
51c4c4ce
...
...
@@ -226,7 +226,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
s3c64xx_cpufreq_driver
=
{
.
flags
=
0
,
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
s3c64xx_cpufreq_set_target
,
.
get
=
s3c64xx_cpufreq_get_speed
,
...
...
drivers/cpufreq/s5pv210-cpufreq.c
View file @
51c4c4ce
...
...
@@ -560,7 +560,7 @@ static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
}
static
struct
cpufreq_driver
s5pv210_driver
=
{
.
flags
=
CPUFREQ_STICKY
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
s5pv210_target
,
.
get
=
s5pv210_getspeed
,
...
...
drivers/cpufreq/sa1100-cpufreq.c
View file @
51c4c4ce
...
...
@@ -201,7 +201,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
sa1100_driver
__refdata
=
{
.
flags
=
CPUFREQ_STICKY
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
sa1100_target
,
.
get
=
sa11x0_getspeed
,
...
...
drivers/cpufreq/sa1110-cpufreq.c
View file @
51c4c4ce
...
...
@@ -312,7 +312,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
/* sa1110_driver needs __refdata because it must remain after init registers
* it with cpufreq_register_driver() */
static
struct
cpufreq_driver
sa1110_driver
__refdata
=
{
.
flags
=
CPUFREQ_STICKY
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
sa1110_target
,
.
get
=
sa11x0_getspeed
,
...
...
drivers/cpufreq/spear-cpufreq.c
View file @
51c4c4ce
...
...
@@ -138,7 +138,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
}
newfreq
=
clk_round_rate
(
srcclk
,
newfreq
*
mult
);
if
(
newfreq
<
0
)
{
if
(
newfreq
<
=
0
)
{
pr_err
(
"clk_round_rate failed for cpu src clock
\n
"
);
return
newfreq
;
}
...
...
@@ -162,7 +162,7 @@ static int spear_cpufreq_init(struct cpufreq_policy *policy)
static
struct
cpufreq_driver
spear_cpufreq_driver
=
{
.
name
=
"cpufreq-spear"
,
.
flags
=
CPUFREQ_STICKY
,
.
flags
=
CPUFREQ_STICKY
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
spear_cpufreq_target
,
.
get
=
spear_cpufreq_get
,
...
...
drivers/cpufreq/tegra-cpufreq.c
View file @
51c4c4ce
...
...
@@ -214,6 +214,7 @@ static int tegra_cpu_exit(struct cpufreq_policy *policy)
}
static
struct
cpufreq_driver
tegra_cpufreq_driver
=
{
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
tegra_target
,
.
get
=
tegra_getspeed
,
...
...
drivers/cpufreq/unicore2-cpufreq.c
View file @
51c4c4ce
...
...
@@ -46,20 +46,18 @@ static int ucv2_target(struct cpufreq_policy *policy,
unsigned
int
target_freq
,
unsigned
int
relation
)
{
unsigned
int
cur
=
ucv2_getspeed
(
0
);
struct
cpufreq_freqs
freqs
;
struct
clk
*
mclk
=
clk_get
(
NULL
,
"MAIN_CLK"
);
int
ret
;
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_PRECHANGE
);
if
(
!
clk_set_rate
(
mclk
,
target_freq
*
1000
))
{
freqs
.
old
=
cur
;
freqs
.
old
=
policy
->
cur
;
freqs
.
new
=
target_freq
;
}
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_POSTCHANGE
);
cpufreq_notify_transition
(
policy
,
&
freqs
,
CPUFREQ_PRECHANGE
);
ret
=
clk_set_rate
(
mclk
,
target_freq
*
1000
);
cpufreq_notify_post_transition
(
policy
,
&
freqs
,
ret
);
return
0
;
return
ret
;
}
static
int
__init
ucv2_cpu_init
(
struct
cpufreq_policy
*
policy
)
...
...
include/linux/cpufreq.h
View file @
51c4c4ce
...
...
@@ -252,6 +252,15 @@ struct cpufreq_driver {
*/
#define CPUFREQ_ASYNC_NOTIFICATION (1 << 4)
/*
* Set by drivers which want cpufreq core to check if CPU is running at a
* frequency present in freq-table exposed by the driver. For these drivers if
* CPU is found running at an out of table freq, we will try to set it to a freq
* from the table. And if that fails, we will stop further boot process by
* issuing a BUG_ON().
*/
#define CPUFREQ_NEED_INITIAL_FREQ_CHECK (1 << 5)
int
cpufreq_register_driver
(
struct
cpufreq_driver
*
driver_data
);
int
cpufreq_unregister_driver
(
struct
cpufreq_driver
*
driver_data
);
...
...
@@ -306,6 +315,8 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
void
cpufreq_notify_transition
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_freqs
*
freqs
,
unsigned
int
state
);
void
cpufreq_notify_post_transition
(
struct
cpufreq_policy
*
policy
,
struct
cpufreq_freqs
*
freqs
,
int
transition_failed
);
#else
/* CONFIG_CPU_FREQ */
static
inline
int
cpufreq_register_notifier
(
struct
notifier_block
*
nb
,
...
...
@@ -439,6 +450,8 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned
int
target_freq
,
unsigned
int
relation
,
unsigned
int
*
index
);
int
cpufreq_frequency_table_get_index
(
struct
cpufreq_policy
*
policy
,
unsigned
int
freq
);
void
cpufreq_frequency_table_update_policy_cpu
(
struct
cpufreq_policy
*
policy
);
ssize_t
cpufreq_show_cpus
(
const
struct
cpumask
*
mask
,
char
*
buf
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment