2 * arch/sh/kernel/cpufreq.c
4 * cpufreq driver for the SuperH processors.
6 * Copyright (C) 2002 - 2012 Paul Mundt
7 * Copyright (C) 2002 M. R. Brown
9 * Clock framework bits from arch/avr32/mach-at32ap/cpufreq.c
11 * Copyright (C) 2004-2007 Atmel Corporation
13 * This file is subject to the terms and conditions of the GNU General Public
14 * License. See the file "COPYING" in the main directory of this archive
17 #define pr_fmt(fmt) "cpufreq: " fmt
19 #include <linux/types.h>
20 #include <linux/cpufreq.h>
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/err.h>
25 #include <linux/cpumask.h>
26 #include <linux/cpu.h>
27 #include <linux/smp.h>
28 #include <linux/sched.h> /* set_cpus_allowed() */
29 #include <linux/clk.h>
30 #include <linux/percpu.h>
31 #include <linux/sh_clk.h>
33 static DEFINE_PER_CPU(struct clk
, sh_cpuclk
);
35 static unsigned int sh_cpufreq_get(unsigned int cpu
)
37 return (clk_get_rate(&per_cpu(sh_cpuclk
, cpu
)) + 500) / 1000;
41 * Here we notify other drivers of the proposed change and the final change.
43 static int sh_cpufreq_target(struct cpufreq_policy
*policy
,
44 unsigned int target_freq
,
45 unsigned int relation
)
47 unsigned int cpu
= policy
->cpu
;
48 struct clk
*cpuclk
= &per_cpu(sh_cpuclk
, cpu
);
49 cpumask_t cpus_allowed
;
50 struct cpufreq_freqs freqs
;
57 cpus_allowed
= current
->cpus_allowed
;
58 set_cpus_allowed_ptr(current
, cpumask_of(cpu
));
60 BUG_ON(smp_processor_id() != cpu
);
62 dev
= get_cpu_device(cpu
);
64 /* Convert target_freq from kHz to Hz */
65 freq
= clk_round_rate(cpuclk
, target_freq
* 1000);
67 if (freq
< (policy
->min
* 1000) || freq
> (policy
->max
* 1000))
70 dev_dbg(dev
, "requested frequency %u Hz\n", target_freq
* 1000);
73 freqs
.old
= sh_cpufreq_get(cpu
);
74 freqs
.new = (freq
+ 500) / 1000;
77 cpufreq_notify_transition(&freqs
, CPUFREQ_PRECHANGE
);
78 set_cpus_allowed_ptr(current
, &cpus_allowed
);
79 clk_set_rate(cpuclk
, freq
);
80 cpufreq_notify_transition(&freqs
, CPUFREQ_POSTCHANGE
);
82 dev_dbg(dev
, "set frequency %lu Hz\n", freq
);
87 static int sh_cpufreq_verify(struct cpufreq_policy
*policy
)
89 struct clk
*cpuclk
= &per_cpu(sh_cpuclk
, policy
->cpu
);
90 struct cpufreq_frequency_table
*freq_table
;
92 freq_table
= cpuclk
->nr_freqs
? cpuclk
->freq_table
: NULL
;
94 return cpufreq_frequency_table_verify(policy
, freq_table
);
96 cpufreq_verify_within_limits(policy
, policy
->cpuinfo
.min_freq
,
97 policy
->cpuinfo
.max_freq
);
99 policy
->min
= (clk_round_rate(cpuclk
, 1) + 500) / 1000;
100 policy
->max
= (clk_round_rate(cpuclk
, ~0UL) + 500) / 1000;
102 cpufreq_verify_within_limits(policy
, policy
->cpuinfo
.min_freq
,
103 policy
->cpuinfo
.max_freq
);
108 static int sh_cpufreq_cpu_init(struct cpufreq_policy
*policy
)
110 unsigned int cpu
= policy
->cpu
;
111 struct clk
*cpuclk
= &per_cpu(sh_cpuclk
, cpu
);
112 struct cpufreq_frequency_table
*freq_table
;
115 if (!cpu_online(cpu
))
118 dev
= get_cpu_device(cpu
);
120 cpuclk
= clk_get(dev
, "cpu_clk");
121 if (IS_ERR(cpuclk
)) {
122 dev_err(dev
, "couldn't get CPU clk\n");
123 return PTR_ERR(cpuclk
);
126 policy
->cur
= policy
->min
= policy
->max
= sh_cpufreq_get(cpu
);
128 freq_table
= cpuclk
->nr_freqs
? cpuclk
->freq_table
: NULL
;
132 result
= cpufreq_frequency_table_cpuinfo(policy
, freq_table
);
134 cpufreq_frequency_table_get_attr(freq_table
, cpu
);
136 dev_notice(dev
, "no frequency table found, falling back "
137 "to rate rounding.\n");
139 policy
->cpuinfo
.min_freq
=
140 (clk_round_rate(cpuclk
, 1) + 500) / 1000;
141 policy
->cpuinfo
.max_freq
=
142 (clk_round_rate(cpuclk
, ~0UL) + 500) / 1000;
145 policy
->min
= policy
->cpuinfo
.min_freq
;
146 policy
->max
= policy
->cpuinfo
.max_freq
;
148 policy
->cpuinfo
.transition_latency
= CPUFREQ_ETERNAL
;
150 dev_info(dev
, "CPU Frequencies - Minimum %u.%03u MHz, "
151 "Maximum %u.%03u MHz.\n",
152 policy
->min
/ 1000, policy
->min
% 1000,
153 policy
->max
/ 1000, policy
->max
% 1000);
158 static int sh_cpufreq_cpu_exit(struct cpufreq_policy
*policy
)
160 unsigned int cpu
= policy
->cpu
;
161 struct clk
*cpuclk
= &per_cpu(sh_cpuclk
, cpu
);
163 cpufreq_frequency_table_put_attr(cpu
);
169 static struct freq_attr
*sh_freq_attr
[] = {
170 &cpufreq_freq_attr_scaling_available_freqs
,
174 static struct cpufreq_driver sh_cpufreq_driver
= {
175 .owner
= THIS_MODULE
,
177 .get
= sh_cpufreq_get
,
178 .target
= sh_cpufreq_target
,
179 .verify
= sh_cpufreq_verify
,
180 .init
= sh_cpufreq_cpu_init
,
181 .exit
= sh_cpufreq_cpu_exit
,
182 .attr
= sh_freq_attr
,
185 static int __init
sh_cpufreq_module_init(void)
187 pr_notice("SuperH CPU frequency driver.\n");
188 return cpufreq_register_driver(&sh_cpufreq_driver
);
191 static void __exit
sh_cpufreq_module_exit(void)
193 cpufreq_unregister_driver(&sh_cpufreq_driver
);
196 module_init(sh_cpufreq_module_init
);
197 module_exit(sh_cpufreq_module_exit
);
199 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
200 MODULE_DESCRIPTION("cpufreq driver for SuperH");
201 MODULE_LICENSE("GPL");