You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'pm-cpufreq'
* pm-cpufreq: (40 commits) thermal: exynos: boost: Automatic enable/disable of BOOST feature (at Exynos4412) cpufreq: exynos4x12: Change L0 driver data to CPUFREQ_BOOST_FREQ Documentation: cpufreq / boost: Update BOOST documentation cpufreq: exynos: Extend Exynos cpufreq driver to support boost cpufreq / boost: Kconfig: Support for software-managed BOOST acpi-cpufreq: Adjust the code to use the common boost attribute cpufreq: Add boost frequency support in core intel_pstate: Add trace point to report internal state. cpufreq: introduce cpufreq_generic_get() routine ARM: SA1100: Create dummy clk_get_rate() to avoid build failures cpufreq: stats: create sysfs entries when cpufreq_stats is a module cpufreq: stats: free table and remove sysfs entry in a single routine cpufreq: stats: remove hotplug notifiers cpufreq: stats: handle cpufreq_unregister_driver() and suspend/resume properly cpufreq: speedstep: remove unused speedstep_get_state powernow-k6: reorder frequencies powernow-k6: correctly initialize default parameters powernow-k6: disable cache when changing frequency Documentation: add ABI entry for intel_pstate cpufreq: exynos: Convert exynos-cpufreq to platform driver ...
This commit is contained in:
@@ -200,3 +200,27 @@ Description: address and size of the percpu note.
|
|||||||
note of cpu#.
|
note of cpu#.
|
||||||
|
|
||||||
crash_notes_size: size of the 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
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ Introduction
|
|||||||
Some CPUs support a functionality to raise the operating frequency of
|
Some CPUs support a functionality to raise the operating frequency of
|
||||||
some cores in a multi-core package if certain conditions apply, mostly
|
some cores in a multi-core package if certain conditions apply, mostly
|
||||||
if the whole chip is not fully utilized and below it's intended thermal
|
if the whole chip is not fully utilized and below it's intended thermal
|
||||||
budget. This is done without operating system control by a combination
|
budget. The decision about boost disable/enable is made either at hardware
|
||||||
of hardware and firmware.
|
(e.g. x86) or software (e.g ARM).
|
||||||
On Intel CPUs this is called "Turbo Boost", AMD calls it "Turbo-Core",
|
On Intel CPUs this is called "Turbo Boost", AMD calls it "Turbo-Core",
|
||||||
in technical documentation "Core performance boost". In Linux we use
|
in technical documentation "Core performance boost". In Linux we use
|
||||||
the term "boost" for convenience.
|
the term "boost" for convenience.
|
||||||
@@ -48,24 +48,24 @@ be desirable:
|
|||||||
User controlled switch
|
User controlled switch
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
To allow the user to toggle the boosting functionality, the acpi-cpufreq
|
To allow the user to toggle the boosting functionality, the cpufreq core
|
||||||
driver exports a sysfs knob to disable it. There is a file:
|
driver exports a sysfs knob to enable or disable it. There is a file:
|
||||||
/sys/devices/system/cpu/cpufreq/boost
|
/sys/devices/system/cpu/cpufreq/boost
|
||||||
which can either read "0" (boosting disabled) or "1" (boosting enabled).
|
which can either read "0" (boosting disabled) or "1" (boosting enabled).
|
||||||
Reading the file is always supported, even if the processor does not
|
The file is exported only when cpufreq driver supports boosting.
|
||||||
support boosting. In this case the file will be read-only and always
|
Explicitly changing the permissions and writing to that file anyway will
|
||||||
reads as "0". Explicitly changing the permissions and writing to that
|
return EINVAL.
|
||||||
file anyway will return EINVAL.
|
|
||||||
|
|
||||||
On supported CPUs one can write either a "0" or a "1" into this file.
|
On supported CPUs one can write either a "0" or a "1" into this file.
|
||||||
This will either disable the boost functionality on all cores in the
|
This will either disable the boost functionality on all cores in the
|
||||||
whole system (0) or will allow the hardware to boost at will (1).
|
whole system (0) or will allow the software or hardware to boost at will
|
||||||
|
(1).
|
||||||
|
|
||||||
Writing a "1" does not explicitly boost the system, but just allows the
|
Writing a "1" does not explicitly boost the system, but just allows the
|
||||||
CPU (and the firmware) to boost at their discretion. Some implementations
|
CPU to boost at their discretion. Some implementations take external
|
||||||
take external factors like the chip's temperature into account, so
|
factors like the chip's temperature into account, so boosting once does
|
||||||
boosting once does not necessarily mean that it will occur every time
|
not necessarily mean that it will occur every time even using the exact
|
||||||
even using the exact same software setup.
|
same software setup.
|
||||||
|
|
||||||
|
|
||||||
AMD legacy cpb switch
|
AMD legacy cpb switch
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
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
|
||||||
@@ -303,6 +303,11 @@ void __init exynos_cpuidle_init(void)
|
|||||||
platform_device_register(&exynos_cpuidle);
|
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)
|
void __init exynos_init_late(void)
|
||||||
{
|
{
|
||||||
if (of_machine_is_compatible("samsung,exynos5440"))
|
if (of_machine_is_compatible("samsung,exynos5440"))
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ void exynos_init_io(void);
|
|||||||
void exynos4_restart(enum reboot_mode mode, const char *cmd);
|
void exynos4_restart(enum reboot_mode mode, const char *cmd);
|
||||||
void exynos5_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_cpuidle_init(void);
|
||||||
|
void exynos_cpufreq_init(void);
|
||||||
void exynos_init_late(void);
|
void exynos_init_late(void);
|
||||||
|
|
||||||
void exynos_firmware_init(void);
|
void exynos_firmware_init(void);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
static void __init exynos4_dt_machine_init(void)
|
static void __init exynos4_dt_machine_init(void)
|
||||||
{
|
{
|
||||||
exynos_cpuidle_init();
|
exynos_cpuidle_init();
|
||||||
|
exynos_cpufreq_init();
|
||||||
|
|
||||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ static void __init exynos5_dt_machine_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
exynos_cpuidle_init();
|
exynos_cpuidle_init();
|
||||||
|
exynos_cpufreq_init();
|
||||||
|
|
||||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,13 @@ struct clk clk_##_name = { \
|
|||||||
|
|
||||||
static DEFINE_SPINLOCK(clocks_lock);
|
static DEFINE_SPINLOCK(clocks_lock);
|
||||||
|
|
||||||
|
/* Dummy clk routine to build generic kernel parts that may be using them */
|
||||||
|
unsigned long clk_get_rate(struct clk *clk)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(clk_get_rate);
|
||||||
|
|
||||||
static void clk_gpio27_enable(struct clk *clk)
|
static void clk_gpio27_enable(struct clk *clk)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ if CPU_FREQ
|
|||||||
config CPU_FREQ_GOV_COMMON
|
config CPU_FREQ_GOV_COMMON
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config CPU_FREQ_BOOST_SW
|
||||||
|
bool
|
||||||
|
depends on THERMAL
|
||||||
|
|
||||||
config CPU_FREQ_STAT
|
config CPU_FREQ_STAT
|
||||||
tristate "CPU frequency translation statistics"
|
tristate "CPU frequency translation statistics"
|
||||||
default y
|
default y
|
||||||
@@ -181,7 +185,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 @@
|
|||||||
|
|
||||||
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 && BIG_LITTLE && 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
|
|||||||
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
|
||||||
@@ -64,6 +66,21 @@ config ARM_EXYNOS5440_CPUFREQ
|
|||||||
|
|
||||||
If in doubt, say N.
|
If in doubt, say N.
|
||||||
|
|
||||||
|
config ARM_EXYNOS_CPU_FREQ_BOOST_SW
|
||||||
|
bool "EXYNOS Frequency Overclocking - Software"
|
||||||
|
depends on ARM_EXYNOS_CPUFREQ
|
||||||
|
select CPU_FREQ_BOOST_SW
|
||||||
|
select EXYNOS_THERMAL
|
||||||
|
help
|
||||||
|
This driver supports software managed overclocking (BOOST).
|
||||||
|
It allows usage of special frequencies for Samsung Exynos
|
||||||
|
processors if thermal conditions are appropriate.
|
||||||
|
|
||||||
|
It reguires, for safe operation, thermal framework with properly
|
||||||
|
defined trip points.
|
||||||
|
|
||||||
|
If in doubt, say N.
|
||||||
|
|
||||||
config ARM_HIGHBANK_CPUFREQ
|
config ARM_HIGHBANK_CPUFREQ
|
||||||
tristate "Calxeda Highbank-based"
|
tristate "Calxeda Highbank-based"
|
||||||
depends on ARCH_HIGHBANK
|
depends on ARCH_HIGHBANK
|
||||||
@@ -79,11 +96,11 @@ config ARM_HIGHBANK_CPUFREQ
|
|||||||
If in doubt, say N.
|
If in doubt, say N.
|
||||||
|
|
||||||
config ARM_IMX6Q_CPUFREQ
|
config ARM_IMX6Q_CPUFREQ
|
||||||
tristate "Freescale i.MX6Q cpufreq support"
|
tristate "Freescale i.MX6 cpufreq support"
|
||||||
depends on SOC_IMX6Q
|
depends on ARCH_MXC
|
||||||
depends on REGULATOR_ANATOP
|
depends on REGULATOR_ANATOP
|
||||||
help
|
help
|
||||||
This adds cpufreq driver support for Freescale i.MX6Q SOC.
|
This adds cpufreq driver support for Freescale i.MX6 series SoCs.
|
||||||
|
|
||||||
If in doubt, say N.
|
If in doubt, say N.
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ static struct acpi_processor_performance __percpu *acpi_perf_data;
|
|||||||
static struct cpufreq_driver acpi_cpufreq_driver;
|
static struct cpufreq_driver acpi_cpufreq_driver;
|
||||||
|
|
||||||
static unsigned int acpi_pstate_strict;
|
static unsigned int acpi_pstate_strict;
|
||||||
static bool boost_enabled, boost_supported;
|
|
||||||
static struct msr __percpu *msrs;
|
static struct msr __percpu *msrs;
|
||||||
|
|
||||||
static bool boost_state(unsigned int cpu)
|
static bool boost_state(unsigned int cpu)
|
||||||
@@ -133,49 +132,16 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
|
|||||||
wrmsr_on_cpus(cpumask, msr_addr, msrs);
|
wrmsr_on_cpus(cpumask, msr_addr, msrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t _store_boost(const char *buf, size_t count)
|
static int _store_boost(int val)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
unsigned long val = 0;
|
|
||||||
|
|
||||||
if (!boost_supported)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 10, &val);
|
|
||||||
if (ret || (val > 1))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if ((val && boost_enabled) || (!val && !boost_enabled))
|
|
||||||
return count;
|
|
||||||
|
|
||||||
get_online_cpus();
|
get_online_cpus();
|
||||||
|
|
||||||
boost_set_msrs(val, cpu_online_mask);
|
boost_set_msrs(val, cpu_online_mask);
|
||||||
|
|
||||||
put_online_cpus();
|
put_online_cpus();
|
||||||
|
|
||||||
boost_enabled = val;
|
|
||||||
pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");
|
pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");
|
||||||
|
|
||||||
return count;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_global_boost(struct kobject *kobj, struct attribute *attr,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
return _store_boost(buf, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_global_boost(struct kobject *kobj,
|
|
||||||
struct attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
return sprintf(buf, "%u\n", boost_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct global_attr global_boost = __ATTR(boost, 0644,
|
|
||||||
show_global_boost,
|
|
||||||
store_global_boost);
|
|
||||||
|
|
||||||
static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
|
static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
|
||||||
{
|
{
|
||||||
struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
|
struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
|
||||||
@@ -186,15 +152,32 @@ static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
|
|||||||
cpufreq_freq_attr_ro(freqdomain_cpus);
|
cpufreq_freq_attr_ro(freqdomain_cpus);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
|
#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
|
||||||
|
static ssize_t store_boost(const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned long val = 0;
|
||||||
|
|
||||||
|
if (!acpi_cpufreq_driver.boost_supported)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = kstrtoul(buf, 10, &val);
|
||||||
|
if (ret || (val > 1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
_store_boost((int) val);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
|
static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
return _store_boost(buf, count);
|
return store_boost(buf, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
|
static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
|
||||||
{
|
{
|
||||||
return sprintf(buf, "%u\n", boost_enabled);
|
return sprintf(buf, "%u\n", acpi_cpufreq_driver.boost_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpufreq_freq_attr_rw(cpb);
|
cpufreq_freq_attr_rw(cpb);
|
||||||
@@ -554,7 +537,7 @@ static int boost_notify(struct notifier_block *nb, unsigned long action,
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case CPU_UP_PREPARE:
|
case CPU_UP_PREPARE:
|
||||||
case CPU_UP_PREPARE_FROZEN:
|
case CPU_UP_PREPARE_FROZEN:
|
||||||
boost_set_msrs(boost_enabled, cpumask);
|
boost_set_msrs(acpi_cpufreq_driver.boost_enabled, cpumask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPU_DOWN_PREPARE:
|
case CPU_DOWN_PREPARE:
|
||||||
@@ -911,6 +894,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
|
|||||||
.resume = acpi_cpufreq_resume,
|
.resume = acpi_cpufreq_resume,
|
||||||
.name = "acpi-cpufreq",
|
.name = "acpi-cpufreq",
|
||||||
.attr = acpi_cpufreq_attr,
|
.attr = acpi_cpufreq_attr,
|
||||||
|
.set_boost = _store_boost,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init acpi_cpufreq_boost_init(void)
|
static void __init acpi_cpufreq_boost_init(void)
|
||||||
@@ -921,33 +905,22 @@ static void __init acpi_cpufreq_boost_init(void)
|
|||||||
if (!msrs)
|
if (!msrs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
boost_supported = true;
|
acpi_cpufreq_driver.boost_supported = true;
|
||||||
boost_enabled = boost_state(0);
|
acpi_cpufreq_driver.boost_enabled = boost_state(0);
|
||||||
|
|
||||||
get_online_cpus();
|
get_online_cpus();
|
||||||
|
|
||||||
/* Force all MSRs to the same value */
|
/* Force all MSRs to the same value */
|
||||||
boost_set_msrs(boost_enabled, cpu_online_mask);
|
boost_set_msrs(acpi_cpufreq_driver.boost_enabled,
|
||||||
|
cpu_online_mask);
|
||||||
|
|
||||||
register_cpu_notifier(&boost_nb);
|
register_cpu_notifier(&boost_nb);
|
||||||
|
|
||||||
put_online_cpus();
|
put_online_cpus();
|
||||||
} else
|
}
|
||||||
global_boost.attr.mode = 0444;
|
|
||||||
|
|
||||||
/* We create the boost file in any case, though for systems without
|
|
||||||
* hardware support it will be read-only and hardwired to return 0.
|
|
||||||
*/
|
|
||||||
if (cpufreq_sysfs_create_file(&(global_boost.attr)))
|
|
||||||
pr_warn(PFX "could not register global boost sysfs file\n");
|
|
||||||
else
|
|
||||||
pr_debug("registered global boost sysfs file\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit acpi_cpufreq_boost_exit(void)
|
static void __exit acpi_cpufreq_boost_exit(void)
|
||||||
{
|
{
|
||||||
cpufreq_sysfs_remove_file(&(global_boost.attr));
|
|
||||||
|
|
||||||
if (msrs) {
|
if (msrs) {
|
||||||
unregister_cpu_notifier(&boost_nb);
|
unregister_cpu_notifier(&boost_nb);
|
||||||
|
|
||||||
@@ -993,12 +966,11 @@ static int __init acpi_cpufreq_init(void)
|
|||||||
*iter = &cpb;
|
*iter = &cpb;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
acpi_cpufreq_boost_init();
|
||||||
|
|
||||||
ret = cpufreq_register_driver(&acpi_cpufreq_driver);
|
ret = cpufreq_register_driver(&acpi_cpufreq_driver);
|
||||||
if (ret)
|
if (ret)
|
||||||
free_acpi_perf_data();
|
free_acpi_perf_data();
|
||||||
else
|
|
||||||
acpi_cpufreq_boost_init();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -488,7 +488,8 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
|
|||||||
static struct cpufreq_driver bL_cpufreq_driver = {
|
static struct cpufreq_driver bL_cpufreq_driver = {
|
||||||
.name = "arm-big-little",
|
.name = "arm-big-little",
|
||||||
.flags = CPUFREQ_STICKY |
|
.flags = CPUFREQ_STICKY |
|
||||||
CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
|
CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
|
||||||
|
CPUFREQ_NEED_INITIAL_FREQ_CHECK,
|
||||||
.verify = cpufreq_generic_frequency_table_verify,
|
.verify = cpufreq_generic_frequency_table_verify,
|
||||||
.target_index = bL_cpufreq_set_target,
|
.target_index = bL_cpufreq_set_target,
|
||||||
.get = bL_cpufreq_get_rate,
|
.get = bL_cpufreq_get_rate,
|
||||||
|
|||||||
@@ -21,17 +21,8 @@
|
|||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
static struct clk *cpuclk;
|
|
||||||
static struct cpufreq_frequency_table *freq_table;
|
static struct cpufreq_frequency_table *freq_table;
|
||||||
|
|
||||||
static unsigned int at32_get_speed(unsigned int cpu)
|
|
||||||
{
|
|
||||||
/* No SMP support */
|
|
||||||
if (cpu)
|
|
||||||
return 0;
|
|
||||||
return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int ref_freq;
|
static unsigned int ref_freq;
|
||||||
static unsigned long loops_per_jiffy_ref;
|
static unsigned long loops_per_jiffy_ref;
|
||||||
|
|
||||||
@@ -39,7 +30,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
|
|||||||
{
|
{
|
||||||
unsigned int old_freq, new_freq;
|
unsigned int old_freq, new_freq;
|
||||||
|
|
||||||
old_freq = at32_get_speed(0);
|
old_freq = policy->cur;
|
||||||
new_freq = freq_table[index].frequency;
|
new_freq = freq_table[index].frequency;
|
||||||
|
|
||||||
if (!ref_freq) {
|
if (!ref_freq) {
|
||||||
@@ -50,7 +41,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
|
|||||||
if (old_freq < new_freq)
|
if (old_freq < new_freq)
|
||||||
boot_cpu_data.loops_per_jiffy = cpufreq_scale(
|
boot_cpu_data.loops_per_jiffy = cpufreq_scale(
|
||||||
loops_per_jiffy_ref, ref_freq, new_freq);
|
loops_per_jiffy_ref, ref_freq, new_freq);
|
||||||
clk_set_rate(cpuclk, new_freq * 1000);
|
clk_set_rate(policy->clk, new_freq * 1000);
|
||||||
if (new_freq < old_freq)
|
if (new_freq < old_freq)
|
||||||
boot_cpu_data.loops_per_jiffy = cpufreq_scale(
|
boot_cpu_data.loops_per_jiffy = cpufreq_scale(
|
||||||
loops_per_jiffy_ref, ref_freq, new_freq);
|
loops_per_jiffy_ref, ref_freq, new_freq);
|
||||||
@@ -61,6 +52,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
|
|||||||
static int at32_cpufreq_driver_init(struct cpufreq_policy *policy)
|
static int at32_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
unsigned int frequency, rate, min_freq;
|
unsigned int frequency, rate, min_freq;
|
||||||
|
static struct clk *cpuclk;
|
||||||
int retval, steps, i;
|
int retval, steps, i;
|
||||||
|
|
||||||
if (policy->cpu != 0)
|
if (policy->cpu != 0)
|
||||||
@@ -103,6 +95,7 @@ static int at32_cpufreq_driver_init(struct cpufreq_policy *policy)
|
|||||||
frequency /= 2;
|
frequency /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
policy->clk = cpuclk;
|
||||||
freq_table[steps - 1].frequency = CPUFREQ_TABLE_END;
|
freq_table[steps - 1].frequency = CPUFREQ_TABLE_END;
|
||||||
|
|
||||||
retval = cpufreq_table_validate_and_show(policy, freq_table);
|
retval = cpufreq_table_validate_and_show(policy, freq_table);
|
||||||
@@ -123,7 +116,7 @@ static struct cpufreq_driver at32_driver = {
|
|||||||
.init = at32_cpufreq_driver_init,
|
.init = at32_cpufreq_driver_init,
|
||||||
.verify = cpufreq_generic_frequency_table_verify,
|
.verify = cpufreq_generic_frequency_table_verify,
|
||||||
.target_index = at32_set_target,
|
.target_index = at32_set_target,
|
||||||
.get = at32_get_speed,
|
.get = cpufreq_generic_get,
|
||||||
.flags = CPUFREQ_STICKY,
|
.flags = CPUFREQ_STICKY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -30,11 +30,6 @@ static struct clk *cpu_clk;
|
|||||||
static struct regulator *cpu_reg;
|
static struct regulator *cpu_reg;
|
||||||
static struct cpufreq_frequency_table *freq_table;
|
static struct cpufreq_frequency_table *freq_table;
|
||||||
|
|
||||||
static unsigned int cpu0_get_speed(unsigned int cpu)
|
|
||||||
{
|
|
||||||
return clk_get_rate(cpu_clk) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
|
static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||||
{
|
{
|
||||||
struct dev_pm_opp *opp;
|
struct dev_pm_opp *opp;
|
||||||
@@ -44,7 +39,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;
|
||||||
@@ -100,6 +95,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
|
|||||||
|
|
||||||
static int cpu0_cpufreq_init(struct cpufreq_policy *policy)
|
static int cpu0_cpufreq_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
|
policy->clk = cpu_clk;
|
||||||
return cpufreq_generic_init(policy, freq_table, transition_latency);
|
return cpufreq_generic_init(policy, freq_table, transition_latency);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +103,7 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
|
|||||||
.flags = CPUFREQ_STICKY,
|
.flags = CPUFREQ_STICKY,
|
||||||
.verify = cpufreq_generic_frequency_table_verify,
|
.verify = cpufreq_generic_frequency_table_verify,
|
||||||
.target_index = cpu0_set_target,
|
.target_index = cpu0_set_target,
|
||||||
.get = cpu0_get_speed,
|
.get = cpufreq_generic_get,
|
||||||
.init = cpu0_cpufreq_init,
|
.init = cpu0_cpufreq_init,
|
||||||
.exit = cpufreq_generic_exit,
|
.exit = cpufreq_generic_exit,
|
||||||
.name = "generic_cpu0",
|
.name = "generic_cpu0",
|
||||||
|
|||||||
+199
-19
@@ -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);
|
||||||
static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback);
|
static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback);
|
||||||
static DEFINE_RWLOCK(cpufreq_driver_lock);
|
static DEFINE_RWLOCK(cpufreq_driver_lock);
|
||||||
static DEFINE_MUTEX(cpufreq_governor_lock);
|
DEFINE_MUTEX(cpufreq_governor_lock);
|
||||||
static LIST_HEAD(cpufreq_policy_list);
|
static LIST_HEAD(cpufreq_policy_list);
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
@@ -176,6 +176,20 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cpufreq_generic_init);
|
EXPORT_SYMBOL_GPL(cpufreq_generic_init);
|
||||||
|
|
||||||
|
unsigned int cpufreq_generic_get(unsigned int cpu)
|
||||||
|
{
|
||||||
|
struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
|
||||||
|
|
||||||
|
if (!policy || IS_ERR(policy->clk)) {
|
||||||
|
pr_err("%s: No %s associated to cpu: %d\n", __func__,
|
||||||
|
policy ? "clk" : "policy", cpu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clk_get_rate(policy->clk) / 1000;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cpufreq_generic_get);
|
||||||
|
|
||||||
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
|
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct cpufreq_policy *policy = NULL;
|
struct cpufreq_policy *policy = NULL;
|
||||||
@@ -320,10 +334,51 @@ void cpufreq_notify_transition(struct cpufreq_policy *policy,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
|
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 *
|
* SYSFS INTERFACE *
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
ssize_t show_boost(struct kobject *kobj,
|
||||||
|
struct attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t store_boost(struct kobject *kobj, struct attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
int ret, enable;
|
||||||
|
|
||||||
|
ret = sscanf(buf, "%d", &enable);
|
||||||
|
if (ret != 1 || enable < 0 || enable > 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (cpufreq_boost_trigger_state(enable)) {
|
||||||
|
pr_err("%s: Cannot %s BOOST!\n", __func__,
|
||||||
|
enable ? "enable" : "disable");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("%s: cpufreq BOOST %s\n", __func__,
|
||||||
|
enable ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
define_one_global_rw(boost);
|
||||||
|
|
||||||
static struct cpufreq_governor *__find_governor(const char *str_governor)
|
static struct cpufreq_governor *__find_governor(const char *str_governor)
|
||||||
{
|
{
|
||||||
@@ -929,6 +984,9 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
|
|||||||
struct kobject *kobj;
|
struct kobject *kobj;
|
||||||
struct completion *cmp;
|
struct completion *cmp;
|
||||||
|
|
||||||
|
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
|
||||||
|
CPUFREQ_REMOVE_POLICY, policy);
|
||||||
|
|
||||||
down_read(&policy->rwsem);
|
down_read(&policy->rwsem);
|
||||||
kobj = &policy->kobj;
|
kobj = &policy->kobj;
|
||||||
cmp = &policy->kobj_unregister;
|
cmp = &policy->kobj_unregister;
|
||||||
@@ -1051,6 +1109,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
|
|||||||
goto err_set_policy_cpu;
|
goto err_set_policy_cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
||||||
|
for_each_cpu(j, policy->cpus)
|
||||||
|
per_cpu(cpufreq_cpu_data, j) = policy;
|
||||||
|
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||||
|
|
||||||
if (cpufreq_driver->get) {
|
if (cpufreq_driver->get) {
|
||||||
policy->cur = cpufreq_driver->get(policy->cpu);
|
policy->cur = cpufreq_driver->get(policy->cpu);
|
||||||
if (!policy->cur) {
|
if (!policy->cur) {
|
||||||
@@ -1059,6 +1122,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 */
|
/* related cpus should atleast have policy->cpus */
|
||||||
cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
|
cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
|
||||||
|
|
||||||
@@ -1085,15 +1188,12 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
|
||||||
for_each_cpu(j, policy->cpus)
|
|
||||||
per_cpu(cpufreq_cpu_data, j) = policy;
|
|
||||||
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
|
||||||
|
|
||||||
if (!frozen) {
|
if (!frozen) {
|
||||||
ret = cpufreq_add_dev_interface(policy, dev);
|
ret = cpufreq_add_dev_interface(policy, dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_out_unregister;
|
goto err_out_unregister;
|
||||||
|
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
|
||||||
|
CPUFREQ_CREATE_POLICY, policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
||||||
@@ -1115,12 +1215,12 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out_unregister:
|
err_out_unregister:
|
||||||
|
err_get_freq:
|
||||||
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
||||||
for_each_cpu(j, policy->cpus)
|
for_each_cpu(j, policy->cpus)
|
||||||
per_cpu(cpufreq_cpu_data, j) = NULL;
|
per_cpu(cpufreq_cpu_data, j) = NULL;
|
||||||
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||||
|
|
||||||
err_get_freq:
|
|
||||||
if (cpufreq_driver->exit)
|
if (cpufreq_driver->exit)
|
||||||
cpufreq_driver->exit(policy);
|
cpufreq_driver->exit(policy);
|
||||||
err_set_policy_cpu:
|
err_set_policy_cpu:
|
||||||
@@ -1725,17 +1825,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
|
|||||||
pr_err("%s: Failed to change cpu frequency: %d\n",
|
pr_err("%s: Failed to change cpu frequency: %d\n",
|
||||||
__func__, retval);
|
__func__, retval);
|
||||||
|
|
||||||
if (notify) {
|
if (notify)
|
||||||
/*
|
cpufreq_notify_post_transition(policy, &freqs, retval);
|
||||||
* Notify with old freq in case we failed to change
|
|
||||||
* frequency
|
|
||||||
*/
|
|
||||||
if (retval)
|
|
||||||
freqs.new = freqs.old;
|
|
||||||
|
|
||||||
cpufreq_notify_transition(policy, &freqs,
|
|
||||||
CPUFREQ_POSTCHANGE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -2119,6 +2210,73 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
|
|||||||
.notifier_call = cpufreq_cpu_callback,
|
.notifier_call = cpufreq_cpu_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* BOOST *
|
||||||
|
*********************************************************************/
|
||||||
|
static int cpufreq_boost_set_sw(int state)
|
||||||
|
{
|
||||||
|
struct cpufreq_frequency_table *freq_table;
|
||||||
|
struct cpufreq_policy *policy;
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
|
list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
|
||||||
|
freq_table = cpufreq_frequency_get_table(policy->cpu);
|
||||||
|
if (freq_table) {
|
||||||
|
ret = cpufreq_frequency_table_cpuinfo(policy,
|
||||||
|
freq_table);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Policy frequency update failed\n",
|
||||||
|
__func__);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
policy->user_policy.max = policy->max;
|
||||||
|
__cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpufreq_boost_trigger_state(int state)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (cpufreq_driver->boost_enabled == state)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
||||||
|
cpufreq_driver->boost_enabled = state;
|
||||||
|
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||||
|
|
||||||
|
ret = cpufreq_driver->set_boost(state);
|
||||||
|
if (ret) {
|
||||||
|
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
||||||
|
cpufreq_driver->boost_enabled = !state;
|
||||||
|
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||||
|
|
||||||
|
pr_err("%s: Cannot %s BOOST\n", __func__,
|
||||||
|
state ? "enable" : "disable");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpufreq_boost_supported(void)
|
||||||
|
{
|
||||||
|
if (likely(cpufreq_driver))
|
||||||
|
return cpufreq_driver->boost_supported;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
|
||||||
|
|
||||||
|
int cpufreq_boost_enabled(void)
|
||||||
|
{
|
||||||
|
return cpufreq_driver->boost_enabled;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cpufreq_boost_enabled);
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* REGISTER / UNREGISTER CPUFREQ DRIVER *
|
* REGISTER / UNREGISTER CPUFREQ DRIVER *
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
@@ -2159,9 +2317,25 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
|
|||||||
cpufreq_driver = driver_data;
|
cpufreq_driver = driver_data;
|
||||||
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||||
|
|
||||||
|
if (cpufreq_boost_supported()) {
|
||||||
|
/*
|
||||||
|
* Check if driver provides function to enable boost -
|
||||||
|
* if not, use cpufreq_boost_set_sw as default
|
||||||
|
*/
|
||||||
|
if (!cpufreq_driver->set_boost)
|
||||||
|
cpufreq_driver->set_boost = cpufreq_boost_set_sw;
|
||||||
|
|
||||||
|
ret = cpufreq_sysfs_create_file(&boost.attr);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: cannot register global BOOST sysfs file\n",
|
||||||
|
__func__);
|
||||||
|
goto err_null_driver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = subsys_interface_register(&cpufreq_interface);
|
ret = subsys_interface_register(&cpufreq_interface);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_null_driver;
|
goto err_boost_unreg;
|
||||||
|
|
||||||
if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) {
|
if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) {
|
||||||
int i;
|
int i;
|
||||||
@@ -2188,6 +2362,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
|
|||||||
return 0;
|
return 0;
|
||||||
err_if_unreg:
|
err_if_unreg:
|
||||||
subsys_interface_unregister(&cpufreq_interface);
|
subsys_interface_unregister(&cpufreq_interface);
|
||||||
|
err_boost_unreg:
|
||||||
|
if (cpufreq_boost_supported())
|
||||||
|
cpufreq_sysfs_remove_file(&boost.attr);
|
||||||
err_null_driver:
|
err_null_driver:
|
||||||
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
write_lock_irqsave(&cpufreq_driver_lock, flags);
|
||||||
cpufreq_driver = NULL;
|
cpufreq_driver = NULL;
|
||||||
@@ -2214,6 +2391,9 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
|
|||||||
pr_debug("unregistering driver %s\n", driver->name);
|
pr_debug("unregistering driver %s\n", driver->name);
|
||||||
|
|
||||||
subsys_interface_unregister(&cpufreq_interface);
|
subsys_interface_unregister(&cpufreq_interface);
|
||||||
|
if (cpufreq_boost_supported())
|
||||||
|
cpufreq_sysfs_remove_file(&boost.attr);
|
||||||
|
|
||||||
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
|
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
|
||||||
|
|
||||||
down_write(&cpufreq_rwsem);
|
down_write(&cpufreq_rwsem);
|
||||||
|
|||||||
@@ -119,8 +119,9 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
mutex_lock(&cpufreq_governor_lock);
|
||||||
if (!policy->governor_enabled)
|
if (!policy->governor_enabled)
|
||||||
return;
|
goto out_unlock;
|
||||||
|
|
||||||
if (!all_cpus) {
|
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)
|
for_each_cpu(i, policy->cpus)
|
||||||
__gov_queue_work(i, dbs_data, delay);
|
__gov_queue_work(i, dbs_data, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&cpufreq_governor_lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(gov_queue_work);
|
EXPORT_SYMBOL_GPL(gov_queue_work);
|
||||||
|
|
||||||
|
|||||||
@@ -257,6 +257,8 @@ static ssize_t show_sampling_rate_min_gov_pol \
|
|||||||
return sprintf(buf, "%u\n", dbs_data->min_sampling_rate); \
|
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);
|
void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
|
||||||
bool need_load_eval(struct cpu_dbs_common_info *cdbs,
|
bool need_load_eval(struct cpu_dbs_common_info *cdbs,
|
||||||
unsigned int sampling_rate);
|
unsigned int sampling_rate);
|
||||||
|
|||||||
@@ -151,44 +151,36 @@ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* should be called late in the CPU removal sequence so that the stats
|
static void __cpufreq_stats_free_table(struct cpufreq_policy *policy)
|
||||||
* memory is still available in case someone tries to use it.
|
|
||||||
*/
|
|
||||||
static void cpufreq_stats_free_table(unsigned int cpu)
|
|
||||||
{
|
{
|
||||||
struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
|
struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
|
||||||
|
|
||||||
|
if (!stat)
|
||||||
|
return;
|
||||||
|
|
||||||
if (stat) {
|
|
||||||
pr_debug("%s: Free stat table\n", __func__);
|
pr_debug("%s: Free stat table\n", __func__);
|
||||||
|
|
||||||
|
sysfs_remove_group(&policy->kobj, &stats_attr_group);
|
||||||
kfree(stat->time_in_state);
|
kfree(stat->time_in_state);
|
||||||
kfree(stat);
|
kfree(stat);
|
||||||
per_cpu(cpufreq_stats_table, cpu) = NULL;
|
per_cpu(cpufreq_stats_table, policy->cpu) = NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must be called early in the CPU removal sequence (before
|
static void cpufreq_stats_free_table(unsigned int cpu)
|
||||||
* cpufreq_remove_dev) so that policy is still valid.
|
|
||||||
*/
|
|
||||||
static void cpufreq_stats_free_sysfs(unsigned int cpu)
|
|
||||||
{
|
{
|
||||||
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
|
struct cpufreq_policy *policy;
|
||||||
|
|
||||||
|
policy = cpufreq_cpu_get(cpu);
|
||||||
if (!policy)
|
if (!policy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!cpufreq_frequency_get_table(cpu))
|
if (cpufreq_frequency_get_table(policy->cpu))
|
||||||
goto put_ref;
|
__cpufreq_stats_free_table(policy);
|
||||||
|
|
||||||
if (!policy_is_shared(policy)) {
|
|
||||||
pr_debug("%s: Free sysfs stat\n", __func__);
|
|
||||||
sysfs_remove_group(&policy->kobj, &stats_attr_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
put_ref:
|
|
||||||
cpufreq_cpu_put(policy);
|
cpufreq_cpu_put(policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
|
static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
|
||||||
struct cpufreq_frequency_table *table)
|
struct cpufreq_frequency_table *table)
|
||||||
{
|
{
|
||||||
unsigned int i, j, count = 0, ret = 0;
|
unsigned int i, j, count = 0, ret = 0;
|
||||||
@@ -261,6 +253,26 @@ error_get_fail:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cpufreq_stats_create_table(unsigned int cpu)
|
||||||
|
{
|
||||||
|
struct cpufreq_policy *policy;
|
||||||
|
struct cpufreq_frequency_table *table;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "likely(!policy)" because normally cpufreq_stats will be registered
|
||||||
|
* before cpufreq driver
|
||||||
|
*/
|
||||||
|
policy = cpufreq_cpu_get(cpu);
|
||||||
|
if (likely(!policy))
|
||||||
|
return;
|
||||||
|
|
||||||
|
table = cpufreq_frequency_get_table(policy->cpu);
|
||||||
|
if (likely(table))
|
||||||
|
__cpufreq_stats_create_table(policy, table);
|
||||||
|
|
||||||
|
cpufreq_cpu_put(policy);
|
||||||
|
}
|
||||||
|
|
||||||
static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy)
|
static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table,
|
struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table,
|
||||||
@@ -277,7 +289,7 @@ static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy)
|
|||||||
static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
|
static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
|
||||||
unsigned long val, void *data)
|
unsigned long val, void *data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = 0;
|
||||||
struct cpufreq_policy *policy = data;
|
struct cpufreq_policy *policy = data;
|
||||||
struct cpufreq_frequency_table *table;
|
struct cpufreq_frequency_table *table;
|
||||||
unsigned int cpu = policy->cpu;
|
unsigned int cpu = policy->cpu;
|
||||||
@@ -287,15 +299,16 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val != CPUFREQ_NOTIFY)
|
|
||||||
return 0;
|
|
||||||
table = cpufreq_frequency_get_table(cpu);
|
table = cpufreq_frequency_get_table(cpu);
|
||||||
if (!table)
|
if (!table)
|
||||||
return 0;
|
return 0;
|
||||||
ret = cpufreq_stats_create_table(policy, table);
|
|
||||||
if (ret)
|
if (val == CPUFREQ_CREATE_POLICY)
|
||||||
|
ret = __cpufreq_stats_create_table(policy, table);
|
||||||
|
else if (val == CPUFREQ_REMOVE_POLICY)
|
||||||
|
__cpufreq_stats_free_table(policy);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
|
static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
|
||||||
@@ -334,29 +347,6 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cpufreq_stat_cpu_callback(struct notifier_block *nfb,
|
|
||||||
unsigned long action,
|
|
||||||
void *hcpu)
|
|
||||||
{
|
|
||||||
unsigned int cpu = (unsigned long)hcpu;
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case CPU_DOWN_PREPARE:
|
|
||||||
cpufreq_stats_free_sysfs(cpu);
|
|
||||||
break;
|
|
||||||
case CPU_DEAD:
|
|
||||||
cpufreq_stats_free_table(cpu);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NOTIFY_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* priority=1 so this will get called before cpufreq_remove_dev */
|
|
||||||
static struct notifier_block cpufreq_stat_cpu_notifier __refdata = {
|
|
||||||
.notifier_call = cpufreq_stat_cpu_callback,
|
|
||||||
.priority = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct notifier_block notifier_policy_block = {
|
static struct notifier_block notifier_policy_block = {
|
||||||
.notifier_call = cpufreq_stat_notifier_policy
|
.notifier_call = cpufreq_stat_notifier_policy
|
||||||
};
|
};
|
||||||
@@ -376,14 +366,14 @@ static int __init cpufreq_stats_init(void)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
|
for_each_online_cpu(cpu)
|
||||||
|
cpufreq_stats_create_table(cpu);
|
||||||
|
|
||||||
ret = cpufreq_register_notifier(¬ifier_trans_block,
|
ret = cpufreq_register_notifier(¬ifier_trans_block,
|
||||||
CPUFREQ_TRANSITION_NOTIFIER);
|
CPUFREQ_TRANSITION_NOTIFIER);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
cpufreq_unregister_notifier(¬ifier_policy_block,
|
cpufreq_unregister_notifier(¬ifier_policy_block,
|
||||||
CPUFREQ_POLICY_NOTIFIER);
|
CPUFREQ_POLICY_NOTIFIER);
|
||||||
unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
|
|
||||||
for_each_online_cpu(cpu)
|
for_each_online_cpu(cpu)
|
||||||
cpufreq_stats_free_table(cpu);
|
cpufreq_stats_free_table(cpu);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -399,11 +389,8 @@ static void __exit cpufreq_stats_exit(void)
|
|||||||
CPUFREQ_POLICY_NOTIFIER);
|
CPUFREQ_POLICY_NOTIFIER);
|
||||||
cpufreq_unregister_notifier(¬ifier_trans_block,
|
cpufreq_unregister_notifier(¬ifier_trans_block,
|
||||||
CPUFREQ_TRANSITION_NOTIFIER);
|
CPUFREQ_TRANSITION_NOTIFIER);
|
||||||
unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
|
for_each_online_cpu(cpu)
|
||||||
for_each_online_cpu(cpu) {
|
|
||||||
cpufreq_stats_free_table(cpu);
|
cpufreq_stats_free_table(cpu);
|
||||||
cpufreq_stats_free_sysfs(cpu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
|
MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
|
||||||
|
|||||||
@@ -58,14 +58,6 @@ static int davinci_verify_speed(struct cpufreq_policy *policy)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int davinci_getspeed(unsigned int cpu)
|
|
||||||
{
|
|
||||||
if (cpu)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return clk_get_rate(cpufreq.armclk) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
|
static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
|
||||||
{
|
{
|
||||||
struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
|
struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
|
||||||
@@ -73,7 +65,7 @@ static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
|
|||||||
unsigned int old_freq, new_freq;
|
unsigned int old_freq, new_freq;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
old_freq = davinci_getspeed(0);
|
old_freq = policy->cur;
|
||||||
new_freq = pdata->freq_table[idx].frequency;
|
new_freq = pdata->freq_table[idx].frequency;
|
||||||
|
|
||||||
/* if moving to higher frequency, up the voltage beforehand */
|
/* if moving to higher frequency, up the voltage beforehand */
|
||||||
@@ -116,6 +108,8 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
policy->clk = cpufreq.armclk;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Time measurement across the target() function yields ~1500-1800us
|
* Time measurement across the target() function yields ~1500-1800us
|
||||||
* time taken with no drivers on notification list.
|
* time taken with no drivers on notification list.
|
||||||
@@ -126,10 +120,10 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver davinci_driver = {
|
static struct cpufreq_driver davinci_driver = {
|
||||||
.flags = CPUFREQ_STICKY,
|
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
|
||||||
.verify = davinci_verify_speed,
|
.verify = davinci_verify_speed,
|
||||||
.target_index = davinci_target,
|
.target_index = davinci_target,
|
||||||
.get = davinci_getspeed,
|
.get = cpufreq_generic_get,
|
||||||
.init = davinci_cpu_init,
|
.init = davinci_cpu_init,
|
||||||
.exit = cpufreq_generic_exit,
|
.exit = cpufreq_generic_exit,
|
||||||
.name = "davinci",
|
.name = "davinci",
|
||||||
|
|||||||
@@ -26,32 +26,18 @@ static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
|
|||||||
return clk_set_rate(armss_clk, freq_table[index].frequency * 1000);
|
return clk_set_rate(armss_clk, freq_table[index].frequency * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
unsigned long freq = clk_get_rate(armss_clk) / 1000;
|
|
||||||
|
|
||||||
/* The value is rounded to closest frequency in the defined table. */
|
|
||||||
while (freq_table[i + 1].frequency != CPUFREQ_TABLE_END) {
|
|
||||||
if (freq < freq_table[i].frequency +
|
|
||||||
(freq_table[i + 1].frequency - freq_table[i].frequency) / 2)
|
|
||||||
return freq_table[i].frequency;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return freq_table[i].frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dbx500_cpufreq_init(struct cpufreq_policy *policy)
|
static int dbx500_cpufreq_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
|
policy->clk = armss_clk;
|
||||||
return cpufreq_generic_init(policy, freq_table, 20 * 1000);
|
return cpufreq_generic_init(policy, freq_table, 20 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver dbx500_cpufreq_driver = {
|
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,
|
.verify = cpufreq_generic_frequency_table_verify,
|
||||||
.target_index = dbx500_cpufreq_target,
|
.target_index = dbx500_cpufreq_target,
|
||||||
.get = dbx500_cpufreq_getspeed,
|
.get = cpufreq_generic_get,
|
||||||
.init = dbx500_cpufreq_init,
|
.init = dbx500_cpufreq_init,
|
||||||
.name = "DBX500",
|
.name = "DBX500",
|
||||||
.attr = cpufreq_generic_attr,
|
.attr = cpufreq_generic_attr,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user