Commit 8405b044 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq:
  [CPUFREQ] s5pv210: make needlessly global symbols static
  [CPUFREQ] exynos4210: make needlessly global symbols static
  [CPUFREQ] S3C6410: Add some lower frequencies for 800MHz base clock operation
  [CPUFREQ] S5PV210: Add reboot notifier to prevent system hang
  [CPUFREQ] S5PV210: Adjust udelay prior to voltage scaling down
  [CPUFREQ] S5PV210: Lock a mutex while changing the cpu frequency
  [CPUFREQ] S5PV210: Add pm_notifier to prevent system unstable
  [CPUFREQ] S5PV210: Add arm/int voltage control support
  [CPUFREQ] S5PV210: Add additional symantics for "relation" in cpufreq with pm
  [CPUFREQ] S3C64xx: Notify transition complete as soon as frequency changed
  [CPUFREQ] S3C6410: Support 800MHz operation in cpufreq
  [CPUFREQ] s5pv210-cpufreq.c: Add missing clk_put
  [CPUFREQ] Move compile for S3C64XX cpufreq to /drivers/cpufreq
  [CPUFREQ] Remove some vi noise that escaped into the Makefile.
  [CPUFREQ] Move ARM Samsung cpufreq drivers to drivers/cpufreq/
  [CPUFREQ/S3C64xx] Move S3C64xx CPUfreq driver into drivers/cpufreq
  [CPUFREQ] Handle CPUs with different capabilities in acpi-cpufreq
parents ee05eff6 133de121
...@@ -1895,10 +1895,6 @@ config CPU_FREQ_PXA ...@@ -1895,10 +1895,6 @@ config CPU_FREQ_PXA
default y default y
select CPU_FREQ_DEFAULT_GOV_USERSPACE select CPU_FREQ_DEFAULT_GOV_USERSPACE
config CPU_FREQ_S3C64XX
bool "CPUfreq support for Samsung S3C64XX CPUs"
depends on CPU_FREQ && CPU_S3C6410
config CPU_FREQ_S3C config CPU_FREQ_S3C
bool bool
help help
......
...@@ -15,7 +15,6 @@ obj- := ...@@ -15,7 +15,6 @@ obj- :=
obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o obj-$(CONFIG_CPU_EXYNOS4210) += cpu.o init.o clock.o irq-combiner.o
obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o irq-eint.o dma.o obj-$(CONFIG_CPU_EXYNOS4210) += setup-i2c0.o irq-eint.o dma.o
obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o
......
...@@ -23,10 +23,6 @@ obj-$(CONFIG_CPU_S3C6410) += s3c6410.o ...@@ -23,10 +23,6 @@ obj-$(CONFIG_CPU_S3C6410) += s3c6410.o
obj-y += irq.o obj-y += irq.o
obj-y += irq-eint.o obj-y += irq-eint.o
# CPU frequency scaling
obj-$(CONFIG_CPU_FREQ_S3C64XX) += cpufreq.o
# DMA support # DMA support
obj-$(CONFIG_S3C64XX_DMA) += dma.o obj-$(CONFIG_S3C64XX_DMA) += dma.o
......
...@@ -15,7 +15,6 @@ obj- := ...@@ -15,7 +15,6 @@ obj- :=
obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o
obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o
obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
# machine support # machine support
......
...@@ -184,5 +184,10 @@ depends on X86 ...@@ -184,5 +184,10 @@ depends on X86
source "drivers/cpufreq/Kconfig.x86" source "drivers/cpufreq/Kconfig.x86"
endmenu endmenu
menu "ARM CPU frequency scaling drivers"
depends on ARM
source "drivers/cpufreq/Kconfig.arm"
endmenu
endif endif
endmenu endmenu
#
# ARM CPU Frequency scaling drivers
#
config ARM_S3C64XX_CPUFREQ
bool "Samsung S3C64XX"
depends on CPU_S3C6410
default y
help
This adds the CPUFreq driver for Samsung S3C6410 SoC.
If in doubt, say N.
config ARM_S5PV210_CPUFREQ
bool "Samsung S5PV210 and S5PC110"
depends on CPU_S5PV210
default y
help
This adds the CPUFreq driver for Samsung S5PV210 and
S5PC110 SoCs.
If in doubt, say N.
config ARM_EXYNOS4210_CPUFREQ
bool "Samsung EXYNOS4210"
depends on CPU_EXYNOS4210
default y
help
This adds the CPUFreq driver for Samsung EXYNOS4210
SoC (S5PV310 or S5PC210).
If in doubt, say N.
...@@ -13,7 +13,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o ...@@ -13,7 +13,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
# CPUfreq cross-arch helpers # CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
##################################################################################d ##################################################################################
# x86 drivers. # x86 drivers.
# Link order matters. K8 is preferred to ACPI because of firmware bugs in early # Link order matters. K8 is preferred to ACPI because of firmware bugs in early
# K8 systems. ACPI is preferred to all other hardware-specific drivers. # K8 systems. ACPI is preferred to all other hardware-specific drivers.
...@@ -37,7 +37,9 @@ obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o ...@@ -37,7 +37,9 @@ obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
##################################################################################d ##################################################################################
# ARM SoC drivers # ARM SoC drivers
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
...@@ -655,7 +655,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -655,7 +655,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
acpi_processor_notify_smm(THIS_MODULE); acpi_processor_notify_smm(THIS_MODULE);
/* Check for APERF/MPERF support in hardware */ /* Check for APERF/MPERF support in hardware */
if (cpu_has(c, X86_FEATURE_APERFMPERF)) if (boot_cpu_has(X86_FEATURE_APERFMPERF))
acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf; acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf;
pr_debug("CPU%u - ACPI performance management activated.\n", cpu); pr_debug("CPU%u - ACPI performance management activated.\n", cpu);
......
/* linux/arch/arm/mach-exynos4/cpufreq.c /*
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
...@@ -192,17 +191,17 @@ static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = { ...@@ -192,17 +191,17 @@ static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
((200 << 16) | (6 << 8) | 4), ((200 << 16) | (6 << 8) | 4),
}; };
int exynos4_verify_speed(struct cpufreq_policy *policy) static int exynos4_verify_speed(struct cpufreq_policy *policy)
{ {
return cpufreq_frequency_table_verify(policy, exynos4_freq_table); return cpufreq_frequency_table_verify(policy, exynos4_freq_table);
} }
unsigned int exynos4_getspeed(unsigned int cpu) static unsigned int exynos4_getspeed(unsigned int cpu)
{ {
return clk_get_rate(cpu_clk) / 1000; return clk_get_rate(cpu_clk) / 1000;
} }
void exynos4_set_clkdiv(unsigned int div_index) static void exynos4_set_clkdiv(unsigned int div_index)
{ {
unsigned int tmp; unsigned int tmp;
......
/* linux/arch/arm/plat-s3c64xx/cpufreq.c /*
*
* Copyright 2009 Wolfson Microelectronics plc * Copyright 2009 Wolfson Microelectronics plc
* *
* S3C64xx CPUfreq Support * S3C64xx CPUfreq Support
...@@ -32,11 +31,14 @@ static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = { ...@@ -32,11 +31,14 @@ static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = {
[1] = { 1050000, 1150000 }, [1] = { 1050000, 1150000 },
[2] = { 1100000, 1150000 }, [2] = { 1100000, 1150000 },
[3] = { 1200000, 1350000 }, [3] = { 1200000, 1350000 },
[4] = { 1300000, 1350000 },
}; };
static struct cpufreq_frequency_table s3c64xx_freq_table[] = { static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
{ 0, 66000 }, { 0, 66000 },
{ 0, 100000 },
{ 0, 133000 }, { 0, 133000 },
{ 1, 200000 },
{ 1, 222000 }, { 1, 222000 },
{ 1, 266000 }, { 1, 266000 },
{ 2, 333000 }, { 2, 333000 },
...@@ -44,6 +46,7 @@ static struct cpufreq_frequency_table s3c64xx_freq_table[] = { ...@@ -44,6 +46,7 @@ static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
{ 2, 532000 }, { 2, 532000 },
{ 2, 533000 }, { 2, 533000 },
{ 3, 667000 }, { 3, 667000 },
{ 4, 800000 },
{ 0, CPUFREQ_TABLE_END }, { 0, CPUFREQ_TABLE_END },
}; };
#endif #endif
...@@ -111,6 +114,8 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy, ...@@ -111,6 +114,8 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
goto err; goto err;
} }
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
#ifdef CONFIG_REGULATOR #ifdef CONFIG_REGULATOR
if (vddarm && freqs.new < freqs.old) { if (vddarm && freqs.new < freqs.old) {
ret = regulator_set_voltage(vddarm, ret = regulator_set_voltage(vddarm,
...@@ -124,8 +129,6 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy, ...@@ -124,8 +129,6 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
} }
#endif #endif
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
pr_debug("cpufreq: Set actual frequency %lukHz\n", pr_debug("cpufreq: Set actual frequency %lukHz\n",
clk_get_rate(armclk) / 1000); clk_get_rate(armclk) / 1000);
......
/* linux/arch/arm/mach-s5pv210/cpufreq.c /*
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd. * Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
...@@ -17,6 +16,9 @@ ...@@ -17,6 +16,9 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/reboot.h>
#include <linux/regulator/consumer.h>
#include <linux/suspend.h>
#include <mach/map.h> #include <mach/map.h>
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
...@@ -25,11 +27,27 @@ static struct clk *cpu_clk; ...@@ -25,11 +27,27 @@ static struct clk *cpu_clk;
static struct clk *dmc0_clk; static struct clk *dmc0_clk;
static struct clk *dmc1_clk; static struct clk *dmc1_clk;
static struct cpufreq_freqs freqs; static struct cpufreq_freqs freqs;
static DEFINE_MUTEX(set_freq_lock);
/* APLL M,P,S values for 1G/800Mhz */ /* APLL M,P,S values for 1G/800Mhz */
#define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1) #define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1)
#define APLL_VAL_800 ((1 << 31) | (100 << 16) | (3 << 8) | 1) #define APLL_VAL_800 ((1 << 31) | (100 << 16) | (3 << 8) | 1)
/* Use 800MHz when entering sleep mode */
#define SLEEP_FREQ (800 * 1000)
/*
* relation has an additional symantics other than the standard of cpufreq
* DISALBE_FURTHER_CPUFREQ: disable further access to target
* ENABLE_FURTUER_CPUFREQ: enable access to target
*/
enum cpufreq_access {
DISABLE_FURTHER_CPUFREQ = 0x10,
ENABLE_FURTHER_CPUFREQ = 0x20,
};
static bool no_cpufreq_access;
/* /*
* DRAM configurations to calculate refresh counter for changing * DRAM configurations to calculate refresh counter for changing
* frequency of memory. * frequency of memory.
...@@ -66,6 +84,40 @@ static struct cpufreq_frequency_table s5pv210_freq_table[] = { ...@@ -66,6 +84,40 @@ static struct cpufreq_frequency_table s5pv210_freq_table[] = {
{0, CPUFREQ_TABLE_END}, {0, CPUFREQ_TABLE_END},
}; };
static struct regulator *arm_regulator;
static struct regulator *int_regulator;
struct s5pv210_dvs_conf {
int arm_volt; /* uV */
int int_volt; /* uV */
};
static const int arm_volt_max = 1350000;
static const int int_volt_max = 1250000;
static struct s5pv210_dvs_conf dvs_conf[] = {
[L0] = {
.arm_volt = 1250000,
.int_volt = 1100000,
},
[L1] = {
.arm_volt = 1200000,
.int_volt = 1100000,
},
[L2] = {
.arm_volt = 1050000,
.int_volt = 1100000,
},
[L3] = {
.arm_volt = 950000,
.int_volt = 1100000,
},
[L4] = {
.arm_volt = 950000,
.int_volt = 1000000,
},
};
static u32 clkdiv_val[5][11] = { static u32 clkdiv_val[5][11] = {
/* /*
* Clock divider value for following * Clock divider value for following
...@@ -122,7 +174,7 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) ...@@ -122,7 +174,7 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
__raw_writel(tmp1, reg); __raw_writel(tmp1, reg);
} }
int s5pv210_verify_speed(struct cpufreq_policy *policy) static int s5pv210_verify_speed(struct cpufreq_policy *policy)
{ {
if (policy->cpu) if (policy->cpu)
return -EINVAL; return -EINVAL;
...@@ -130,7 +182,7 @@ int s5pv210_verify_speed(struct cpufreq_policy *policy) ...@@ -130,7 +182,7 @@ int s5pv210_verify_speed(struct cpufreq_policy *policy)
return cpufreq_frequency_table_verify(policy, s5pv210_freq_table); return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
} }
unsigned int s5pv210_getspeed(unsigned int cpu) static unsigned int s5pv210_getspeed(unsigned int cpu)
{ {
if (cpu) if (cpu)
return 0; return 0;
...@@ -146,30 +198,66 @@ static int s5pv210_target(struct cpufreq_policy *policy, ...@@ -146,30 +198,66 @@ static int s5pv210_target(struct cpufreq_policy *policy,
unsigned int index, priv_index; unsigned int index, priv_index;
unsigned int pll_changing = 0; unsigned int pll_changing = 0;
unsigned int bus_speed_changing = 0; unsigned int bus_speed_changing = 0;
int arm_volt, int_volt;
int ret = 0;
mutex_lock(&set_freq_lock);
if (relation & ENABLE_FURTHER_CPUFREQ)
no_cpufreq_access = false;
if (no_cpufreq_access) {
#ifdef CONFIG_PM_VERBOSE
pr_err("%s:%d denied access to %s as it is disabled"
"temporarily\n", __FILE__, __LINE__, __func__);
#endif
ret = -EINVAL;
goto exit;
}
if (relation & DISABLE_FURTHER_CPUFREQ)
no_cpufreq_access = true;
relation &= ~(ENABLE_FURTHER_CPUFREQ | DISABLE_FURTHER_CPUFREQ);
freqs.old = s5pv210_getspeed(0); freqs.old = s5pv210_getspeed(0);
if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
target_freq, relation, &index)) target_freq, relation, &index)) {
return -EINVAL; ret = -EINVAL;
goto exit;
}
freqs.new = s5pv210_freq_table[index].frequency; freqs.new = s5pv210_freq_table[index].frequency;
freqs.cpu = 0; freqs.cpu = 0;
if (freqs.new == freqs.old) if (freqs.new == freqs.old)
return 0; goto exit;
/* Finding current running level index */ /* Finding current running level index */
if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
freqs.old, relation, &priv_index)) freqs.old, relation, &priv_index)) {
return -EINVAL; ret = -EINVAL;
goto exit;
}
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); arm_volt = dvs_conf[index].arm_volt;
int_volt = dvs_conf[index].int_volt;
if (freqs.new > freqs.old) { if (freqs.new > freqs.old) {
/* Voltage up: will be implemented */ ret = regulator_set_voltage(arm_regulator,
arm_volt, arm_volt_max);
if (ret)
goto exit;
ret = regulator_set_voltage(int_regulator,
int_volt, int_volt_max);
if (ret)
goto exit;
} }
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
/* Check if there need to change PLL */ /* Check if there need to change PLL */
if ((index == L0) || (priv_index == L0)) if ((index == L0) || (priv_index == L0))
pll_changing = 1; pll_changing = 1;
...@@ -380,15 +468,21 @@ static int s5pv210_target(struct cpufreq_policy *policy, ...@@ -380,15 +468,21 @@ static int s5pv210_target(struct cpufreq_policy *policy,
} }
} }
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
if (freqs.new < freqs.old) { if (freqs.new < freqs.old) {
/* Voltage down: will be implemented */ regulator_set_voltage(int_regulator,
} int_volt, int_volt_max);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); regulator_set_voltage(arm_regulator,
arm_volt, arm_volt_max);
}
printk(KERN_DEBUG "Perf changed[L%d]\n", index); printk(KERN_DEBUG "Perf changed[L%d]\n", index);
return 0; exit:
mutex_unlock(&set_freq_lock);
return ret;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -416,6 +510,7 @@ static int check_mem_type(void __iomem *dmc_reg) ...@@ -416,6 +510,7 @@ static int check_mem_type(void __iomem *dmc_reg)
static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
{ {
unsigned long mem_type; unsigned long mem_type;
int ret;
cpu_clk = clk_get(NULL, "armclk"); cpu_clk = clk_get(NULL, "armclk");
if (IS_ERR(cpu_clk)) if (IS_ERR(cpu_clk))
...@@ -423,19 +518,20 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) ...@@ -423,19 +518,20 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
dmc0_clk = clk_get(NULL, "sclk_dmc0"); dmc0_clk = clk_get(NULL, "sclk_dmc0");
if (IS_ERR(dmc0_clk)) { if (IS_ERR(dmc0_clk)) {
clk_put(cpu_clk); ret = PTR_ERR(dmc0_clk);
return PTR_ERR(dmc0_clk); goto out_dmc0;
} }
dmc1_clk = clk_get(NULL, "hclk_msys"); dmc1_clk = clk_get(NULL, "hclk_msys");
if (IS_ERR(dmc1_clk)) { if (IS_ERR(dmc1_clk)) {
clk_put(dmc0_clk); ret = PTR_ERR(dmc1_clk);
clk_put(cpu_clk); goto out_dmc1;
return PTR_ERR(dmc1_clk);
} }
if (policy->cpu != 0) if (policy->cpu != 0) {
return -EINVAL; ret = -EINVAL;
goto out_dmc1;
}
/* /*
* check_mem_type : This driver only support LPDDR & LPDDR2. * check_mem_type : This driver only support LPDDR & LPDDR2.
...@@ -445,7 +541,8 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) ...@@ -445,7 +541,8 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
if ((mem_type != LPDDR) && (mem_type != LPDDR2)) { if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
printk(KERN_ERR "CPUFreq doesn't support this memory type\n"); printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
return -EINVAL; ret = -EINVAL;
goto out_dmc1;
} }
/* Find current refresh counter and frequency each DMC */ /* Find current refresh counter and frequency each DMC */
...@@ -462,6 +559,49 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) ...@@ -462,6 +559,49 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 40000; policy->cpuinfo.transition_latency = 40000;
return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table); return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
out_dmc1:
clk_put(dmc0_clk);
out_dmc0:
clk_put(cpu_clk);
return ret;
}
static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
int ret;
switch (event) {
case PM_SUSPEND_PREPARE:
ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
DISABLE_FURTHER_CPUFREQ);
if (ret < 0)
return NOTIFY_BAD;
return NOTIFY_OK;
case PM_POST_RESTORE:
case PM_POST_SUSPEND:
cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
ENABLE_FURTHER_CPUFREQ);
return NOTIFY_OK;
}
return NOTIFY_DONE;
}
static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
int ret;
ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
DISABLE_FURTHER_CPUFREQ);
if (ret < 0)
return NOTIFY_BAD;
return NOTIFY_DONE;
} }
static struct cpufreq_driver s5pv210_driver = { static struct cpufreq_driver s5pv210_driver = {
...@@ -477,8 +617,32 @@ static struct cpufreq_driver s5pv210_driver = { ...@@ -477,8 +617,32 @@ static struct cpufreq_driver s5pv210_driver = {
#endif #endif
}; };
static struct notifier_block s5pv210_cpufreq_notifier = {
.notifier_call = s5pv210_cpufreq_notifier_event,
};
static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
.notifier_call = s5pv210_cpufreq_reboot_notifier_event,
};
static int __init s5pv210_cpufreq_init(void) static int __init s5pv210_cpufreq_init(void)
{ {
arm_regulator = regulator_get(NULL, "vddarm");
if (IS_ERR(arm_regulator)) {
pr_err("failed to get regulator vddarm");
return PTR_ERR(arm_regulator);
}
int_regulator = regulator_get(NULL, "vddint");
if (IS_ERR(int_regulator)) {
pr_err("failed to get regulator vddint");
regulator_put(arm_regulator);
return PTR_ERR(int_regulator);
}
register_pm_notifier(&s5pv210_cpufreq_notifier);
register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
return cpufreq_register_driver(&s5pv210_driver); return cpufreq_register_driver(&s5pv210_driver);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment