aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpufreq.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-01-27 03:49:16 -0500
committerPaul Mundt <lethal@linux-sh.org>2012-01-27 03:49:16 -0500
commit3bccf467727c82421e5f7b630c9bb864ebe8d2e6 (patch)
tree66e692cc557dbbf87fbd11de651a5ee21e5016e0 /arch/sh/kernel/cpufreq.c
parent74ea15d909b31158f9b63190a95b52bc05586d4b (diff)
sh: cpufreq: percpu struct clk accounting.
At the moment there is simply a global struct clk pointer for the CPU frequency, which is fundamentally broken in the SMP case. This moves to fix it up by switching to a percpu case. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/cpufreq.c')
-rw-r--r--arch/sh/kernel/cpufreq.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c
index 0fffacea6ed9..8203865e16b7 100644
--- a/arch/sh/kernel/cpufreq.c
+++ b/arch/sh/kernel/cpufreq.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * cpufreq driver for the SuperH processors. 4 * cpufreq driver for the SuperH processors.
5 * 5 *
6 * Copyright (C) 2002 - 2007 Paul Mundt 6 * Copyright (C) 2002 - 2012 Paul Mundt
7 * Copyright (C) 2002 M. R. Brown 7 * Copyright (C) 2002 M. R. Brown
8 * 8 *
9 * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c 9 * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c
@@ -24,12 +24,14 @@
24#include <linux/smp.h> 24#include <linux/smp.h>
25#include <linux/sched.h> /* set_cpus_allowed() */ 25#include <linux/sched.h> /* set_cpus_allowed() */
26#include <linux/clk.h> 26#include <linux/clk.h>
27#include <linux/percpu.h>
28#include <linux/sh_clk.h>
27 29
28static struct clk *cpuclk; 30static DEFINE_PER_CPU(struct clk, sh_cpuclk);
29 31
30static unsigned int sh_cpufreq_get(unsigned int cpu) 32static unsigned int sh_cpufreq_get(unsigned int cpu)
31{ 33{
32 return (clk_get_rate(cpuclk) + 500) / 1000; 34 return (clk_get_rate(&per_cpu(sh_cpuclk, cpu)) + 500) / 1000;
33} 35}
34 36
35/* 37/*
@@ -40,6 +42,7 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy,
40 unsigned int relation) 42 unsigned int relation)
41{ 43{
42 unsigned int cpu = policy->cpu; 44 unsigned int cpu = policy->cpu;
45 struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu);
43 cpumask_t cpus_allowed; 46 cpumask_t cpus_allowed;
44 struct cpufreq_freqs freqs; 47 struct cpufreq_freqs freqs;
45 long freq; 48 long freq;
@@ -77,13 +80,15 @@ static int sh_cpufreq_target(struct cpufreq_policy *policy,
77 80
78static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) 81static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
79{ 82{
80 if (!cpu_online(policy->cpu)) 83 unsigned int cpu = policy->cpu;
84 struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu);
85
86 if (!cpu_online(cpu))
81 return -ENODEV; 87 return -ENODEV;
82 88
83 cpuclk = clk_get(NULL, "cpu_clk"); 89 cpuclk = clk_get(NULL, "cpu_clk");
84 if (IS_ERR(cpuclk)) { 90 if (IS_ERR(cpuclk)) {
85 printk(KERN_ERR "cpufreq: couldn't get CPU#%d clk\n", 91 printk(KERN_ERR "cpufreq: couldn't get CPU#%d clk\n", cpu);
86 policy->cpu);
87 return PTR_ERR(cpuclk); 92 return PTR_ERR(cpuclk);
88 } 93 }
89 94
@@ -92,7 +97,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
92 policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; 97 policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
93 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 98 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
94 99
95 policy->cur = sh_cpufreq_get(policy->cpu); 100 policy->cur = sh_cpufreq_get(cpu);
96 policy->min = policy->cpuinfo.min_freq; 101 policy->min = policy->cpuinfo.min_freq;
97 policy->max = policy->cpuinfo.max_freq; 102 policy->max = policy->cpuinfo.max_freq;
98 103
@@ -102,7 +107,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
102 */ 107 */
103 if (unlikely(policy->min == policy->max)) { 108 if (unlikely(policy->min == policy->max)) {
104 printk(KERN_ERR "cpufreq: clock framework rate rounding " 109 printk(KERN_ERR "cpufreq: clock framework rate rounding "
105 "not supported on CPU#%d.\n", policy->cpu); 110 "not supported on CPU#%d.\n", cpu);
106 111
107 clk_put(cpuclk); 112 clk_put(cpuclk);
108 return -EINVAL; 113 return -EINVAL;
@@ -110,7 +115,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
110 115
111 printk(KERN_INFO "cpufreq: CPU#%d Frequencies - Minimum %u.%03u MHz, " 116 printk(KERN_INFO "cpufreq: CPU#%d Frequencies - Minimum %u.%03u MHz, "
112 "Maximum %u.%03u MHz.\n", 117 "Maximum %u.%03u MHz.\n",
113 policy->cpu, policy->min / 1000, policy->min % 1000, 118 cpu, policy->min / 1000, policy->min % 1000,
114 policy->max / 1000, policy->max % 1000); 119 policy->max / 1000, policy->max % 1000);
115 120
116 return 0; 121 return 0;
@@ -125,6 +130,7 @@ static int sh_cpufreq_verify(struct cpufreq_policy *policy)
125 130
126static int sh_cpufreq_exit(struct cpufreq_policy *policy) 131static int sh_cpufreq_exit(struct cpufreq_policy *policy)
127{ 132{
133 struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu);
128 clk_put(cpuclk); 134 clk_put(cpuclk);
129 return 0; 135 return 0;
130} 136}