Skip to content

Commit

Permalink
cpufreq: introduce cpufreq_generic_get() routine
Browse files Browse the repository at this point in the history
CPUFreq drivers that use clock frameworks interface,i.e. clk_get_rate(),
to get CPUs clk rate, have similar sort of code used in most of them.

This patch adds a generic ->get() which will do the same thing for them.
All those drivers are required to now is to set .get to cpufreq_generic_get()
and set their clk pointer in policy->clk during ->init().

Acked-by: Hans-Christian Egtvedt <[email protected]>
Acked-by: Shawn Guo <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Acked-by: Shawn Guo <[email protected]>
Acked-by: Stephen Warren <[email protected]>
Signed-off-by: Viresh Kumar <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
  • Loading branch information
vireshk authored and rafaeljw committed Jan 17, 2014
1 parent 0ad04fb commit 652ed95
Show file tree
Hide file tree
Showing 18 changed files with 112 additions and 229 deletions.
17 changes: 5 additions & 12 deletions drivers/cpufreq/at32ap-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,16 @@
#include <linux/export.h>
#include <linux/slab.h>

static struct clk *cpuclk;
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 long loops_per_jiffy_ref;

static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
{
unsigned int old_freq, new_freq;

old_freq = at32_get_speed(0);
old_freq = policy->cur;
new_freq = freq_table[index].frequency;

if (!ref_freq) {
Expand All @@ -50,7 +41,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
if (old_freq < new_freq)
boot_cpu_data.loops_per_jiffy = cpufreq_scale(
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)
boot_cpu_data.loops_per_jiffy = cpufreq_scale(
loops_per_jiffy_ref, ref_freq, new_freq);
Expand All @@ -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)
{
unsigned int frequency, rate, min_freq;
static struct clk *cpuclk;
int retval, steps, i;

if (policy->cpu != 0)
Expand Down Expand Up @@ -103,6 +95,7 @@ static int at32_cpufreq_driver_init(struct cpufreq_policy *policy)
frequency /= 2;
}

policy->clk = cpuclk;
freq_table[steps - 1].frequency = CPUFREQ_TABLE_END;

retval = cpufreq_table_validate_and_show(policy, freq_table);
Expand All @@ -123,7 +116,7 @@ static struct cpufreq_driver at32_driver = {
.init = at32_cpufreq_driver_init,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = at32_set_target,
.get = at32_get_speed,
.get = cpufreq_generic_get,
.flags = CPUFREQ_STICKY,
};

Expand Down
8 changes: 2 additions & 6 deletions drivers/cpufreq/cpufreq-cpu0.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ static struct clk *cpu_clk;
static struct regulator *cpu_reg;
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)
{
struct dev_pm_opp *opp;
Expand Down Expand Up @@ -100,14 +95,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)

static int cpu0_cpufreq_init(struct cpufreq_policy *policy)
{
policy->clk = cpu_clk;
return cpufreq_generic_init(policy, freq_table, transition_latency);
}

static struct cpufreq_driver cpu0_cpufreq_driver = {
.flags = CPUFREQ_STICKY,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = cpu0_set_target,
.get = cpu0_get_speed,
.get = cpufreq_generic_get,
.init = cpu0_cpufreq_init,
.exit = cpufreq_generic_exit,
.name = "generic_cpu0",
Expand Down
26 changes: 20 additions & 6 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
}
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 *policy = NULL;
Expand Down Expand Up @@ -1068,6 +1082,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
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) {
policy->cur = cpufreq_driver->get(policy->cpu);
if (!policy->cur) {
Expand Down Expand Up @@ -1142,11 +1161,6 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
}
#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) {
ret = cpufreq_add_dev_interface(policy, dev);
if (ret)
Expand Down Expand Up @@ -1174,12 +1188,12 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
return 0;

err_out_unregister:
err_get_freq:
write_lock_irqsave(&cpufreq_driver_lock, flags);
for_each_cpu(j, policy->cpus)
per_cpu(cpufreq_cpu_data, j) = NULL;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);

err_get_freq:
if (cpufreq_driver->exit)
cpufreq_driver->exit(policy);
err_set_policy_cpu:
Expand Down
14 changes: 4 additions & 10 deletions drivers/cpufreq/davinci-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,14 @@ static int davinci_verify_speed(struct cpufreq_policy *policy)
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)
{
struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
struct clk *armclk = cpufreq.armclk;
unsigned int old_freq, new_freq;
int ret = 0;

old_freq = davinci_getspeed(0);
old_freq = policy->cur;
new_freq = pdata->freq_table[idx].frequency;

/* if moving to higher frequency, up the voltage beforehand */
Expand Down Expand Up @@ -116,6 +108,8 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
return result;
}

policy->clk = cpufreq.armclk;

/*
* Time measurement across the target() function yields ~1500-1800us
* time taken with no drivers on notification list.
Expand All @@ -129,7 +123,7 @@ static struct cpufreq_driver davinci_driver = {
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
.verify = davinci_verify_speed,
.target_index = davinci_target,
.get = davinci_getspeed,
.get = cpufreq_generic_get,
.init = davinci_cpu_init,
.exit = cpufreq_generic_exit,
.name = "davinci",
Expand Down
19 changes: 2 additions & 17 deletions drivers/cpufreq/dbx500-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,9 @@ static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
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)
{
policy->clk = armss_clk;
return cpufreq_generic_init(policy, freq_table, 20 * 1000);
}

Expand All @@ -52,7 +37,7 @@ static struct cpufreq_driver dbx500_cpufreq_driver = {
CPUFREQ_NEED_INITIAL_FREQ_CHECK,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = dbx500_cpufreq_target,
.get = dbx500_cpufreq_getspeed,
.get = cpufreq_generic_get,
.init = dbx500_cpufreq_init,
.name = "DBX500",
.attr = cpufreq_generic_attr,
Expand Down
10 changes: 3 additions & 7 deletions drivers/cpufreq/exynos-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ static unsigned int locking_frequency;
static bool frequency_locked;
static DEFINE_MUTEX(cpufreq_lock);

static unsigned int exynos_getspeed(unsigned int cpu)
{
return clk_get_rate(exynos_info->cpu_clk) / 1000;
}

static int exynos_cpufreq_get_index(unsigned int freq)
{
struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
Expand Down Expand Up @@ -215,14 +210,15 @@ static struct notifier_block exynos_cpufreq_nb = {

static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
policy->clk = exynos_info->cpu_clk;
return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
}

static struct cpufreq_driver exynos_driver = {
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = exynos_target,
.get = exynos_getspeed,
.get = cpufreq_generic_get,
.init = exynos_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "exynos_cpufreq",
Expand Down Expand Up @@ -264,7 +260,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
goto err_vdd_arm;
}

locking_frequency = exynos_getspeed(0);
locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;

register_pm_notifier(&exynos_cpufreq_nb);

Expand Down
33 changes: 14 additions & 19 deletions drivers/cpufreq/exynos5440-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ struct exynos_dvfs_data {
struct resource *mem;
int irq;
struct clk *cpu_clk;
unsigned int cur_frequency;
unsigned int latency;
struct cpufreq_frequency_table *freq_table;
unsigned int freq_count;
Expand Down Expand Up @@ -165,7 +164,7 @@ static int init_div_table(void)
return 0;
}

static void exynos_enable_dvfs(void)
static void exynos_enable_dvfs(unsigned int cur_frequency)
{
unsigned int tmp, i, cpu;
struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
Expand All @@ -184,18 +183,18 @@ static void exynos_enable_dvfs(void)

/* Set initial performance index */
for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
if (freq_table[i].frequency == dvfs_info->cur_frequency)
if (freq_table[i].frequency == cur_frequency)
break;

if (freq_table[i].frequency == CPUFREQ_TABLE_END) {
dev_crit(dvfs_info->dev, "Boot up frequency not supported\n");
/* Assign the highest frequency */
i = 0;
dvfs_info->cur_frequency = freq_table[i].frequency;
cur_frequency = freq_table[i].frequency;
}

dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ",
dvfs_info->cur_frequency);
cur_frequency);

for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
Expand All @@ -209,11 +208,6 @@ static void exynos_enable_dvfs(void)
dvfs_info->base + XMU_DVFS_CTRL);
}

static unsigned int exynos_getspeed(unsigned int cpu)
{
return dvfs_info->cur_frequency;
}

static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
{
unsigned int tmp;
Expand All @@ -222,7 +216,7 @@ static int exynos_target(struct cpufreq_policy *policy, unsigned int index)

mutex_lock(&cpufreq_lock);

freqs.old = dvfs_info->cur_frequency;
freqs.old = policy->cur;
freqs.new = freq_table[index].frequency;

cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
Expand Down Expand Up @@ -250,7 +244,7 @@ static void exynos_cpufreq_work(struct work_struct *work)
goto skip_work;

mutex_lock(&cpufreq_lock);
freqs.old = dvfs_info->cur_frequency;
freqs.old = policy->cur;

cur_pstate = __raw_readl(dvfs_info->base + XMU_P_STATUS);
if (cur_pstate >> C0_3_PSTATE_VALID_SHIFT & 0x1)
Expand All @@ -260,10 +254,9 @@ static void exynos_cpufreq_work(struct work_struct *work)

if (likely(index < dvfs_info->freq_count)) {
freqs.new = freq_table[index].frequency;
dvfs_info->cur_frequency = freqs.new;
} else {
dev_crit(dvfs_info->dev, "New frequency out of range\n");
freqs.new = dvfs_info->cur_frequency;
freqs.new = freqs.old;
}
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);

Expand Down Expand Up @@ -307,6 +300,7 @@ static void exynos_sort_descend_freq_table(void)

static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
policy->clk = dvfs_info->cpu_clk;
return cpufreq_generic_init(policy, dvfs_info->freq_table,
dvfs_info->latency);
}
Expand All @@ -316,7 +310,7 @@ static struct cpufreq_driver exynos_driver = {
CPUFREQ_NEED_INITIAL_FREQ_CHECK,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = exynos_target,
.get = exynos_getspeed,
.get = cpufreq_generic_get,
.init = exynos_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = CPUFREQ_NAME,
Expand All @@ -336,6 +330,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
int ret = -EINVAL;
struct device_node *np;
struct resource res;
unsigned int cur_frequency;

np = pdev->dev.of_node;
if (!np)
Expand Down Expand Up @@ -392,13 +387,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
goto err_free_table;
}

dvfs_info->cur_frequency = clk_get_rate(dvfs_info->cpu_clk);
if (!dvfs_info->cur_frequency) {
cur_frequency = clk_get_rate(dvfs_info->cpu_clk);
if (!cur_frequency) {
dev_err(dvfs_info->dev, "Failed to get clock rate\n");
ret = -EINVAL;
goto err_free_table;
}
dvfs_info->cur_frequency /= 1000;
cur_frequency /= 1000;

INIT_WORK(&dvfs_info->irq_work, exynos_cpufreq_work);
ret = devm_request_irq(dvfs_info->dev, dvfs_info->irq,
Expand All @@ -415,7 +410,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
goto err_free_table;
}

exynos_enable_dvfs();
exynos_enable_dvfs(cur_frequency);
ret = cpufreq_register_driver(&exynos_driver);
if (ret) {
dev_err(dvfs_info->dev,
Expand Down
Loading

0 comments on commit 652ed95

Please sign in to comment.