Skip to content

Commit

Permalink
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…davej/cpufreq

Pull cpufreq updates for 3.4 from Dave Jones: new drivers and some fixes.

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq:
  provide disable_cpufreq() function to disable the API.
  EXYNOS5250: Add support cpufreq for EXYNOS5250
  EXYNOS4X12: Add support cpufreq for EXYNOS4X12
  [CPUFREQ] CPUfreq ondemand: update sampling rate without waiting for next sampling
  [CPUFREQ] Add S3C2416/S3C2450 cpufreq driver
  [CPUFREQ] Fix exposure of ARM_EXYNOS4210_CPUFREQ
  [CPUFREQ] EXYNOS4210: update the name of EXYNOS clock register
  [CPUFREQ] EXYNOS: Initialize locking_frequency with initial frequency
  [CPUFREQ] s3c64xx: Fix mis-cherry pick of VDDINT

Fix up trivial conflicts in Kconfig and Makefile due to just changes
next to each other (OMAP2PLUS changes vs some new EXYNOS cpufreq
drivers).
  • Loading branch information
torvalds committed Mar 24, 2012
2 parents 4416b0e + a7b422c commit cf82192
Show file tree
Hide file tree
Showing 12 changed files with 1,591 additions and 43 deletions.
2 changes: 2 additions & 0 deletions arch/arm/mach-exynos/include/mach/cpufreq.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ struct exynos_dvfs_info {
};

extern int exynos4210_cpufreq_init(struct exynos_dvfs_info *);
extern int exynos4x12_cpufreq_init(struct exynos_dvfs_info *);
extern int exynos5250_cpufreq_init(struct exynos_dvfs_info *);
37 changes: 37 additions & 0 deletions drivers/cpufreq/Kconfig.arm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ config ARM_OMAP2PLUS_CPUFREQ
default ARCH_OMAP2PLUS
select CPU_FREQ_TABLE

config ARM_S3C2416_CPUFREQ
bool "S3C2416 CPU Frequency scaling support"
depends on CPU_S3C2416
help
This adds the CPUFreq driver for the Samsung S3C2416 and
S3C2450 SoC. The S3C2416 supports changing the rate of the
armdiv clock source and also entering a so called dynamic
voltage scaling mode in which it is possible to reduce the
core voltage of the cpu.

If in doubt, say N.

config ARM_S3C2416_CPUFREQ_VCORESCALE
bool "Allow voltage scaling for S3C2416 arm core (EXPERIMENTAL)"
depends on ARM_S3C2416_CPUFREQ && REGULATOR && EXPERIMENTAL
help
Enable CPU voltage scaling when entering the dvs mode.
It uses information gathered through existing hardware and
tests but not documented in any datasheet.

If in doubt, say N.

config ARM_S3C64XX_CPUFREQ
bool "Samsung S3C64XX"
depends on CPU_S3C6410
Expand All @@ -30,6 +52,8 @@ config ARM_EXYNOS_CPUFREQ
bool "SAMSUNG EXYNOS SoCs"
depends on ARCH_EXYNOS
select ARM_EXYNOS4210_CPUFREQ if CPU_EXYNOS4210
select ARM_EXYNOS4X12_CPUFREQ if (SOC_EXYNOS4212 || SOC_EXYNOS4412)
select ARM_EXYNOS5250_CPUFREQ if SOC_EXYNOS5250
default y
help
This adds the CPUFreq driver common part for Samsung
Expand All @@ -39,6 +63,19 @@ config ARM_EXYNOS_CPUFREQ

config ARM_EXYNOS4210_CPUFREQ
bool "Samsung EXYNOS4210"
depends on ARCH_EXYNOS
help
This adds the CPUFreq driver for Samsung EXYNOS4210
SoC (S5PV310 or S5PC210).

config ARM_EXYNOS4X12_CPUFREQ
bool "Samsung EXYNOS4X12"
help
This adds the CPUFreq driver for Samsung EXYNOS4X12
SoC (EXYNOS4212 or EXYNOS4412).

config ARM_EXYNOS5250_CPUFREQ
bool "Samsung EXYNOS5250"
help
This adds the CPUFreq driver for Samsung EXYNOS5250
SoC.
3 changes: 3 additions & 0 deletions drivers/cpufreq/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,13 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
##################################################################################
# ARM SoC drivers
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o

##################################################################################
Expand Down
24 changes: 24 additions & 0 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,15 @@ static int __init init_cpufreq_transition_notifier_list(void)
}
pure_initcall(init_cpufreq_transition_notifier_list);

static int off __read_mostly;
int cpufreq_disabled(void)
{
return off;
}
void disable_cpufreq(void)
{
off = 1;
}
static LIST_HEAD(cpufreq_governor_list);
static DEFINE_MUTEX(cpufreq_governor_mutex);

Expand Down Expand Up @@ -1441,6 +1450,9 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
{
int retval = -EINVAL;

if (cpufreq_disabled())
return -ENODEV;

pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
target_freq, relation);
if (cpu_online(policy->cpu) && cpufreq_driver->target)
Expand Down Expand Up @@ -1549,6 +1561,9 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
if (!governor)
return -EINVAL;

if (cpufreq_disabled())
return -ENODEV;

mutex_lock(&cpufreq_governor_mutex);

err = -EBUSY;
Expand All @@ -1572,6 +1587,9 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor)
if (!governor)
return;

if (cpufreq_disabled())
return;

#ifdef CONFIG_HOTPLUG_CPU
for_each_present_cpu(cpu) {
if (cpu_online(cpu))
Expand Down Expand Up @@ -1814,6 +1832,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
unsigned long flags;
int ret;

if (cpufreq_disabled())
return -ENODEV;

if (!driver_data || !driver_data->verify || !driver_data->init ||
((!driver_data->setpolicy) && (!driver_data->target)))
return -EINVAL;
Expand Down Expand Up @@ -1901,6 +1922,9 @@ static int __init cpufreq_core_init(void)
{
int cpu;

if (cpufreq_disabled())
return -ENODEV;

for_each_possible_cpu(cpu) {
per_cpu(cpufreq_policy_cpu, cpu) = -1;
init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
Expand Down
58 changes: 57 additions & 1 deletion drivers/cpufreq/cpufreq_ondemand.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,62 @@ show_one(sampling_down_factor, sampling_down_factor);
show_one(ignore_nice_load, ignore_nice);
show_one(powersave_bias, powersave_bias);

/**
* update_sampling_rate - update sampling rate effective immediately if needed.
* @new_rate: new sampling rate
*
* If new rate is smaller than the old, simply updaing
* dbs_tuners_int.sampling_rate might not be appropriate. For example,
* if the original sampling_rate was 1 second and the requested new sampling
* rate is 10 ms because the user needs immediate reaction from ondemand
* governor, but not sure if higher frequency will be required or not,
* then, the governor may change the sampling rate too late; up to 1 second
* later. Thus, if we are reducing the sampling rate, we need to make the
* new value effective immediately.
*/
static void update_sampling_rate(unsigned int new_rate)
{
int cpu;

dbs_tuners_ins.sampling_rate = new_rate
= max(new_rate, min_sampling_rate);

for_each_online_cpu(cpu) {
struct cpufreq_policy *policy;
struct cpu_dbs_info_s *dbs_info;
unsigned long next_sampling, appointed_at;

policy = cpufreq_cpu_get(cpu);
if (!policy)
continue;
dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu);
cpufreq_cpu_put(policy);

mutex_lock(&dbs_info->timer_mutex);

if (!delayed_work_pending(&dbs_info->work)) {
mutex_unlock(&dbs_info->timer_mutex);
continue;
}

next_sampling = jiffies + usecs_to_jiffies(new_rate);
appointed_at = dbs_info->work.timer.expires;


if (time_before(next_sampling, appointed_at)) {

mutex_unlock(&dbs_info->timer_mutex);
cancel_delayed_work_sync(&dbs_info->work);
mutex_lock(&dbs_info->timer_mutex);

schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work,
usecs_to_jiffies(new_rate));

}
mutex_unlock(&dbs_info->timer_mutex);
}
}

static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
{
Expand All @@ -265,7 +321,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
update_sampling_rate(input);
return count;
}

Expand Down
6 changes: 6 additions & 0 deletions drivers/cpufreq/exynos-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)

cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);

locking_frequency = exynos_getspeed(0);

/* set the transition latency value */
policy->cpuinfo.transition_latency = 100000;

Expand Down Expand Up @@ -252,6 +254,10 @@ static int __init exynos_cpufreq_init(void)

if (soc_is_exynos4210())
ret = exynos4210_cpufreq_init(exynos_info);
else if (soc_is_exynos4212() || soc_is_exynos4412())
ret = exynos4x12_cpufreq_init(exynos_info);
else if (soc_is_exynos5250())
ret = exynos5250_cpufreq_init(exynos_info);
else
pr_err("%s: CPU type not found\n", __func__);

Expand Down
70 changes: 35 additions & 35 deletions drivers/cpufreq/exynos4210-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,25 +121,25 @@ static void exynos4210_set_clkdiv(unsigned int div_index)

tmp = exynos4210_clkdiv_table[div_index].clkdiv;

__raw_writel(tmp, S5P_CLKDIV_CPU);
__raw_writel(tmp, EXYNOS4_CLKDIV_CPU);

do {
tmp = __raw_readl(S5P_CLKDIV_STATCPU);
tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU);
} while (tmp & 0x1111111);

/* Change Divider - CPU1 */

tmp = __raw_readl(S5P_CLKDIV_CPU1);
tmp = __raw_readl(EXYNOS4_CLKDIV_CPU1);

tmp &= ~((0x7 << 4) | 0x7);

tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
(clkdiv_cpu1[div_index][1] << 0));

__raw_writel(tmp, S5P_CLKDIV_CPU1);
__raw_writel(tmp, EXYNOS4_CLKDIV_CPU1);

do {
tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU1);
} while (tmp & 0x11);
}

Expand All @@ -151,32 +151,32 @@ static void exynos4210_set_apll(unsigned int index)
clk_set_parent(moutcore, mout_mpll);

do {
tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU)
>> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT);
tmp &= 0x7;
} while (tmp != 0x2);

/* 2. Set APLL Lock time */
__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
__raw_writel(EXYNOS4_APLL_LOCKTIME, EXYNOS4_APLL_LOCK);

/* 3. Change PLL PMS values */
tmp = __raw_readl(S5P_APLL_CON0);
tmp = __raw_readl(EXYNOS4_APLL_CON0);
tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
tmp |= exynos4210_apll_pms_table[index];
__raw_writel(tmp, S5P_APLL_CON0);
__raw_writel(tmp, EXYNOS4_APLL_CON0);

/* 4. wait_lock_time */
do {
tmp = __raw_readl(S5P_APLL_CON0);
} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
tmp = __raw_readl(EXYNOS4_APLL_CON0);
} while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT)));

/* 5. MUX_CORE_SEL = APLL */
clk_set_parent(moutcore, mout_apll);

do {
tmp = __raw_readl(S5P_CLKMUX_STATCPU);
tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU);
tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK;
} while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
}

bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index)
Expand All @@ -198,10 +198,10 @@ static void exynos4210_set_frequency(unsigned int old_index,
exynos4210_set_clkdiv(new_index);

/* 2. Change just s value in apll m,p,s value */
tmp = __raw_readl(S5P_APLL_CON0);
tmp = __raw_readl(EXYNOS4_APLL_CON0);
tmp &= ~(0x7 << 0);
tmp |= (exynos4210_apll_pms_table[new_index] & 0x7);
__raw_writel(tmp, S5P_APLL_CON0);
__raw_writel(tmp, EXYNOS4_APLL_CON0);
} else {
/* Clock Configuration Procedure */
/* 1. Change the system clock divider values */
Expand All @@ -212,10 +212,10 @@ static void exynos4210_set_frequency(unsigned int old_index,
} else if (old_index < new_index) {
if (!exynos4210_pms_change(old_index, new_index)) {
/* 1. Change just s value in apll m,p,s value */
tmp = __raw_readl(S5P_APLL_CON0);
tmp = __raw_readl(EXYNOS4_APLL_CON0);
tmp &= ~(0x7 << 0);
tmp |= (exynos4210_apll_pms_table[new_index] & 0x7);
__raw_writel(tmp, S5P_APLL_CON0);
__raw_writel(tmp, EXYNOS4_APLL_CON0);

/* 2. Change the system clock divider values */
exynos4210_set_clkdiv(new_index);
Expand Down Expand Up @@ -253,24 +253,24 @@ int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
if (IS_ERR(mout_apll))
goto err_mout_apll;

tmp = __raw_readl(S5P_CLKDIV_CPU);
tmp = __raw_readl(EXYNOS4_CLKDIV_CPU);

for (i = L0; i < CPUFREQ_LEVEL_END; i++) {
tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK |
S5P_CLKDIV_CPU0_COREM0_MASK |
S5P_CLKDIV_CPU0_COREM1_MASK |
S5P_CLKDIV_CPU0_PERIPH_MASK |
S5P_CLKDIV_CPU0_ATB_MASK |
S5P_CLKDIV_CPU0_PCLKDBG_MASK |
S5P_CLKDIV_CPU0_APLL_MASK);

tmp |= ((clkdiv_cpu0[i][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
(clkdiv_cpu0[i][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
(clkdiv_cpu0[i][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
(clkdiv_cpu0[i][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
(clkdiv_cpu0[i][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
(clkdiv_cpu0[i][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
(clkdiv_cpu0[i][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
tmp &= ~(EXYNOS4_CLKDIV_CPU0_CORE_MASK |
EXYNOS4_CLKDIV_CPU0_COREM0_MASK |
EXYNOS4_CLKDIV_CPU0_COREM1_MASK |
EXYNOS4_CLKDIV_CPU0_PERIPH_MASK |
EXYNOS4_CLKDIV_CPU0_ATB_MASK |
EXYNOS4_CLKDIV_CPU0_PCLKDBG_MASK |
EXYNOS4_CLKDIV_CPU0_APLL_MASK);

tmp |= ((clkdiv_cpu0[i][0] << EXYNOS4_CLKDIV_CPU0_CORE_SHIFT) |
(clkdiv_cpu0[i][1] << EXYNOS4_CLKDIV_CPU0_COREM0_SHIFT) |
(clkdiv_cpu0[i][2] << EXYNOS4_CLKDIV_CPU0_COREM1_SHIFT) |
(clkdiv_cpu0[i][3] << EXYNOS4_CLKDIV_CPU0_PERIPH_SHIFT) |
(clkdiv_cpu0[i][4] << EXYNOS4_CLKDIV_CPU0_ATB_SHIFT) |
(clkdiv_cpu0[i][5] << EXYNOS4_CLKDIV_CPU0_PCLKDBG_SHIFT) |
(clkdiv_cpu0[i][6] << EXYNOS4_CLKDIV_CPU0_APLL_SHIFT));

exynos4210_clkdiv_table[i].clkdiv = tmp;
}
Expand Down
Loading

0 comments on commit cf82192

Please sign in to comment.