<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div><div class="h5"><br><br>
> +#include <linux/kernel.h><br>
> +<br>
> +static struct cpu_op mx51_cpu_op[] = {<br>
> + {<br>
> + .cpu_rate = 160000000,},<br>
> + {<br>
> + .cpu_rate = 800000000,},<br>
> +};<br>
<br>
</div></div>Why did you remove the values between 800MHz and 160MHz? 400MHz and<br>
200Mhz should work also, no?<br>
<div><div></div><div class="h5"><br></div></div></blockquote><div>It proved that those operating points don't work well.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div class="h5">
> +<br>
> +struct cpu_op *mx51_get_cpu_op(int *op)<br>
> +{<br>
> + *op = ARRAY_SIZE(mx51_cpu_op);<br>
> + return mx51_cpu_op;<br>
> +}<br>
> diff --git a/arch/arm/mach-mx5/cpu_op-mx51.h b/arch/arm/mach-mx5/cpu_op-mx51.h<br>
> new file mode 100644<br>
> index 0000000..97477fe<br>
> --- /dev/null<br>
> +++ b/arch/arm/mach-mx5/cpu_op-mx51.h<br>
> @@ -0,0 +1,14 @@<br>
> +/*<br>
> + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.<br>
> + */<br>
> +<br>
> +/*<br>
> + * The code contained herein is licensed under the GNU General Public<br>
> + * License. You may obtain a copy of the GNU General Public License<br>
> + * Version 2 or later at the following locations:<br>
> + *<br>
> + * <a href="http://www.opensource.org/licenses/gpl-license.html" target="_blank">http://www.opensource.org/licenses/gpl-license.html</a><br>
> + * <a href="http://www.gnu.org/copyleft/gpl.html" target="_blank">http://www.gnu.org/copyleft/gpl.html</a><br>
> + */<br>
> +<br>
> +extern struct cpu_op *mx51_get_cpu_op(int *op);<br>
> diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile<br>
> index 78d405e..a833d38 100644<br>
> --- a/arch/arm/plat-mxc/Makefile<br>
> +++ b/arch/arm/plat-mxc/Makefile<br>
> @@ -16,6 +16,7 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o<br>
> obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o<br>
> obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o<br>
> obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o<br>
> +obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o<br>
> ifdef CONFIG_SND_IMX_SOC<br>
> obj-y += ssi-fiq.o<br>
> obj-y += ssi-fiq-ksym.o<br>
> diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c<br>
> new file mode 100644<br>
> index 0000000..9cabeb9<br>
> --- /dev/null<br>
> +++ b/arch/arm/plat-mxc/cpufreq.c<br>
> @@ -0,0 +1,202 @@<br>
> +/*<br>
> + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.<br>
> + */<br>
> +<br>
> +/*<br>
> + * The code contained herein is licensed under the GNU General Public<br>
> + * License. You may obtain a copy of the GNU General Public License<br>
> + * Version 2 or later at the following locations:<br>
> + *<br>
> + * <a href="http://www.opensource.org/licenses/gpl-license.html" target="_blank">http://www.opensource.org/licenses/gpl-license.html</a><br>
> + * <a href="http://www.gnu.org/copyleft/gpl.html" target="_blank">http://www.gnu.org/copyleft/gpl.html</a><br>
> + */<br>
> +<br>
> +/*<br>
> + * A driver for the Freescale Semiconductor i.MXC CPUfreq module.<br>
> + * The CPUFREQ driver is for controling CPU frequency. It allows you to change<br>
> + * the CPU clock speed on the fly.<br>
> + */<br>
> +<br>
> +#include <linux/cpufreq.h><br>
> +#include <linux/clk.h><br>
> +#include <linux/err.h><br>
> +#include <linux/slab.h><br>
> +#include <mach/hardware.h><br>
> +#include <mach/clock.h><br>
> +<br>
> +#define CLK32_FREQ 32768<br>
> +#define NANOSECOND (1000 * 1000 * 1000)<br>
> +<br>
> +static int cpu_freq_khz_min;<br>
> +static int cpu_freq_khz_max;<br>
> +static int arm_normal_clk;<br>
> +<br>
> +static struct clk *cpu_clk;<br>
> +static struct cpufreq_frequency_table *imx_freq_table;<br>
> +<br>
> +static int cpu_op_nr;<br>
> +static struct cpu_op *cpu_op_tbl;<br>
> +<br>
> +static int set_cpu_freq(int freq)<br>
> +{<br>
> + int ret = 0;<br>
> + int org_cpu_rate;<br>
> +<br>
> + org_cpu_rate = clk_get_rate(cpu_clk);<br>
> + if (org_cpu_rate == freq)<br>
> + return ret;<br>
<br>
</div></div>You already checked this in mxc_set_target. Once is enough.<br></blockquote><div><br></div><div>Well, this fucntion is not only used in mxc_set_target, so it is safer to still keep checking here. </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5"><br>
> +<br>
> + ret = clk_set_rate(cpu_clk, freq);<br>
> + if (ret != 0) {<br>
> + printk(KERN_DEBUG "cannot set CPU clock rate\n");<br>
> + return ret;<br>
> + }<br>
> +<br>
> + return ret;<br>
> +}<br>
> +<br>
> +static int mxc_verify_speed(struct cpufreq_policy *policy)<br>
> +{<br>
> + if (policy->cpu != 0)<br>
> + return -EINVAL;<br>
> +<br>
> + return cpufreq_frequency_table_verify(policy, imx_freq_table);<br>
> +}<br>
> +<br>
> +static unsigned int mxc_get_speed(unsigned int cpu)<br>
> +{<br>
> + if (cpu)<br>
> + return 0;<br>
> +<br>
> + return clk_get_rate(cpu_clk) / 1000;<br>
> +}<br>
> +<br>
> +static int mxc_set_target(struct cpufreq_policy *policy,<br>
> + unsigned int target_freq, unsigned int relation)<br>
> +{<br>
> + struct cpufreq_freqs freqs;<br>
> + int freq_Hz;<br>
> + int ret = 0;<br>
> + unsigned int index;<br>
> +<br>
> + cpufreq_frequency_table_target(policy, imx_freq_table,<br>
> + target_freq, relation, &index);<br>
> + freq_Hz = imx_freq_table[index].frequency * 1000;<br>
> +<br>
> + freqs.old = clk_get_rate(cpu_clk) / 1000;<br>
> + freqs.new = freq_Hz / 1000;<br>
> + freqs.cpu = 0;<br>
> + freqs.flags = 0;<br>
> + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);<br>
> +<br>
> + if (freqs.old != freqs.new)<br>
> + ret = set_cpu_freq(freq_Hz);<br>
> +<br>
> + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);<br>
> +<br>
> + return ret;<br>
> +}<br>
> +<br>
> +static int __init mxc_cpufreq_init(struct cpufreq_policy *policy)<br>
> +{<br>
> + int ret;<br>
> + int i;<br>
> +<br>
> + printk(KERN_INFO "i.MXC CPU frequency driver\n");<br>
> +<br>
> + if (policy->cpu != 0)<br>
> + return -EINVAL;<br>
> +<br>
> + cpu_clk = clk_get(NULL, "cpu_clk");<br>
> + if (IS_ERR(cpu_clk)) {<br>
> + printk(KERN_ERR "%s: failed to get cpu clock\n", __func__);<br>
> + return PTR_ERR(cpu_clk);<br>
> + }<br>
> +<br>
> + cpu_op_tbl = get_cpu_op(&cpu_op_nr);<br>
<br>
</div></div>This will crash every board except the babbage board which happens to<br>
set this function pointer.<br></blockquote><div>Add a checking here should avoid that. </div></div>