-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Currently, only two operating points: 160Mhz and 800Mhz. the operating points are tested on babbage 3.0 Signed-off-by: Yong Shen <yong.shen@linaro.org> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
- Loading branch information
Yong Shen
authored and
Sascha Hauer
committed
Oct 22, 2010
1 parent
71e2889
commit 64f102b
Showing
10 changed files
with
295 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
*/ | ||
|
||
/* | ||
* The code contained herein is licensed under the GNU General Public | ||
* License. You may obtain a copy of the GNU General Public License | ||
* Version 2 or later at the following locations: | ||
* | ||
* http://www.opensource.org/licenses/gpl-license.html | ||
* http://www.gnu.org/copyleft/gpl.html | ||
*/ | ||
|
||
#include <linux/types.h> | ||
#include <mach/hardware.h> | ||
#include <linux/kernel.h> | ||
|
||
static struct cpu_op mx51_cpu_op[] = { | ||
{ | ||
.cpu_rate = 160000000,}, | ||
{ | ||
.cpu_rate = 800000000,}, | ||
}; | ||
|
||
struct cpu_op *mx51_get_cpu_op(int *op) | ||
{ | ||
*op = ARRAY_SIZE(mx51_cpu_op); | ||
return mx51_cpu_op; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
*/ | ||
|
||
/* | ||
* The code contained herein is licensed under the GNU General Public | ||
* License. You may obtain a copy of the GNU General Public License | ||
* Version 2 or later at the following locations: | ||
* | ||
* http://www.opensource.org/licenses/gpl-license.html | ||
* http://www.gnu.org/copyleft/gpl.html | ||
*/ | ||
|
||
extern struct cpu_op *mx51_get_cpu_op(int *op); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
/* | ||
* Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
*/ | ||
|
||
/* | ||
* The code contained herein is licensed under the GNU General Public | ||
* License. You may obtain a copy of the GNU General Public License | ||
* Version 2 or later at the following locations: | ||
* | ||
* http://www.opensource.org/licenses/gpl-license.html | ||
* http://www.gnu.org/copyleft/gpl.html | ||
*/ | ||
|
||
/* | ||
* A driver for the Freescale Semiconductor i.MXC CPUfreq module. | ||
* The CPUFREQ driver is for controling CPU frequency. It allows you to change | ||
* the CPU clock speed on the fly. | ||
*/ | ||
|
||
#include <linux/cpufreq.h> | ||
#include <linux/clk.h> | ||
#include <linux/err.h> | ||
#include <linux/slab.h> | ||
#include <mach/hardware.h> | ||
#include <mach/clock.h> | ||
|
||
#define CLK32_FREQ 32768 | ||
#define NANOSECOND (1000 * 1000 * 1000) | ||
|
||
struct cpu_op *(*get_cpu_op)(int *op); | ||
|
||
static int cpu_freq_khz_min; | ||
static int cpu_freq_khz_max; | ||
|
||
static struct clk *cpu_clk; | ||
static struct cpufreq_frequency_table *imx_freq_table; | ||
|
||
static int cpu_op_nr; | ||
static struct cpu_op *cpu_op_tbl; | ||
|
||
static int set_cpu_freq(int freq) | ||
{ | ||
int ret = 0; | ||
int org_cpu_rate; | ||
|
||
org_cpu_rate = clk_get_rate(cpu_clk); | ||
if (org_cpu_rate == freq) | ||
return ret; | ||
|
||
ret = clk_set_rate(cpu_clk, freq); | ||
if (ret != 0) { | ||
printk(KERN_DEBUG "cannot set CPU clock rate\n"); | ||
return ret; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
static int mxc_verify_speed(struct cpufreq_policy *policy) | ||
{ | ||
if (policy->cpu != 0) | ||
return -EINVAL; | ||
|
||
return cpufreq_frequency_table_verify(policy, imx_freq_table); | ||
} | ||
|
||
static unsigned int mxc_get_speed(unsigned int cpu) | ||
{ | ||
if (cpu) | ||
return 0; | ||
|
||
return clk_get_rate(cpu_clk) / 1000; | ||
} | ||
|
||
static int mxc_set_target(struct cpufreq_policy *policy, | ||
unsigned int target_freq, unsigned int relation) | ||
{ | ||
struct cpufreq_freqs freqs; | ||
int freq_Hz; | ||
int ret = 0; | ||
unsigned int index; | ||
|
||
cpufreq_frequency_table_target(policy, imx_freq_table, | ||
target_freq, relation, &index); | ||
freq_Hz = imx_freq_table[index].frequency * 1000; | ||
|
||
freqs.old = clk_get_rate(cpu_clk) / 1000; | ||
freqs.new = freq_Hz / 1000; | ||
freqs.cpu = 0; | ||
freqs.flags = 0; | ||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
|
||
ret = set_cpu_freq(freq_Hz); | ||
|
||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
|
||
return ret; | ||
} | ||
|
||
static int __init mxc_cpufreq_init(struct cpufreq_policy *policy) | ||
{ | ||
int ret; | ||
int i; | ||
|
||
printk(KERN_INFO "i.MXC CPU frequency driver\n"); | ||
|
||
if (policy->cpu != 0) | ||
return -EINVAL; | ||
|
||
if (!get_cpu_op) | ||
return -EINVAL; | ||
|
||
cpu_clk = clk_get(NULL, "cpu_clk"); | ||
if (IS_ERR(cpu_clk)) { | ||
printk(KERN_ERR "%s: failed to get cpu clock\n", __func__); | ||
return PTR_ERR(cpu_clk); | ||
} | ||
|
||
cpu_op_tbl = get_cpu_op(&cpu_op_nr); | ||
|
||
cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000; | ||
cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000; | ||
|
||
imx_freq_table = kmalloc( | ||
sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1), | ||
GFP_KERNEL); | ||
if (!imx_freq_table) { | ||
ret = -ENOMEM; | ||
goto err1; | ||
} | ||
|
||
for (i = 0; i < cpu_op_nr; i++) { | ||
imx_freq_table[i].index = i; | ||
imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000; | ||
|
||
if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min) | ||
cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000; | ||
|
||
if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max) | ||
cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000; | ||
} | ||
|
||
imx_freq_table[i].index = i; | ||
imx_freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
|
||
policy->cur = clk_get_rate(cpu_clk) / 1000; | ||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min; | ||
policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max; | ||
|
||
/* Manual states, that PLL stabilizes in two CLK32 periods */ | ||
policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ; | ||
|
||
ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table); | ||
|
||
if (ret < 0) { | ||
printk(KERN_ERR "%s: failed to register i.MXC CPUfreq \ | ||
with error code %d\n", __func__, ret); | ||
goto err; | ||
} | ||
|
||
cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu); | ||
return 0; | ||
err: | ||
kfree(imx_freq_table); | ||
err1: | ||
clk_put(cpu_clk); | ||
return ret; | ||
} | ||
|
||
static int mxc_cpufreq_exit(struct cpufreq_policy *policy) | ||
{ | ||
cpufreq_frequency_table_put_attr(policy->cpu); | ||
|
||
set_cpu_freq(cpu_freq_khz_max * 1000); | ||
clk_put(cpu_clk); | ||
kfree(imx_freq_table); | ||
return 0; | ||
} | ||
|
||
static struct cpufreq_driver mxc_driver = { | ||
.flags = CPUFREQ_STICKY, | ||
.verify = mxc_verify_speed, | ||
.target = mxc_set_target, | ||
.get = mxc_get_speed, | ||
.init = mxc_cpufreq_init, | ||
.exit = mxc_cpufreq_exit, | ||
.name = "imx", | ||
}; | ||
|
||
static int __devinit mxc_cpufreq_driver_init(void) | ||
{ | ||
return cpufreq_register_driver(&mxc_driver); | ||
} | ||
|
||
static void mxc_cpufreq_driver_exit(void) | ||
{ | ||
cpufreq_unregister_driver(&mxc_driver); | ||
} | ||
|
||
module_init(mxc_cpufreq_driver_init); | ||
module_exit(mxc_cpufreq_driver_exit); | ||
|
||
MODULE_AUTHOR("Freescale Semiconductor Inc. Yong Shen <yong.shen@linaro.org>"); | ||
MODULE_DESCRIPTION("CPUfreq driver for i.MX"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters