<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>
&gt; +#include &lt;linux/kernel.h&gt;<br>
&gt; +<br>
&gt; +static struct cpu_op mx51_cpu_op[] = {<br>
&gt; +     {<br>
&gt; +     .cpu_rate = 160000000,},<br>
&gt; +     {<br>
&gt; +     .cpu_rate = 800000000,},<br>
&gt; +};<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&#39;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">
&gt; +<br>
&gt; +struct cpu_op *mx51_get_cpu_op(int *op)<br>
&gt; +{<br>
&gt; +     *op = ARRAY_SIZE(mx51_cpu_op);<br>
&gt; +     return mx51_cpu_op;<br>
&gt; +}<br>
&gt; diff --git a/arch/arm/mach-mx5/cpu_op-mx51.h b/arch/arm/mach-mx5/cpu_op-mx51.h<br>
&gt; new file mode 100644<br>
&gt; index 0000000..97477fe<br>
&gt; --- /dev/null<br>
&gt; +++ b/arch/arm/mach-mx5/cpu_op-mx51.h<br>
&gt; @@ -0,0 +1,14 @@<br>
&gt; +/*<br>
&gt; + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.<br>
&gt; + */<br>
&gt; +<br>
&gt; +/*<br>
&gt; + * The code contained herein is licensed under the GNU General Public<br>
&gt; + * License. You may obtain a copy of the GNU General Public License<br>
&gt; + * Version 2 or later at the following locations:<br>
&gt; + *<br>
&gt; + * <a href="http://www.opensource.org/licenses/gpl-license.html" target="_blank">http://www.opensource.org/licenses/gpl-license.html</a><br>
&gt; + * <a href="http://www.gnu.org/copyleft/gpl.html" target="_blank">http://www.gnu.org/copyleft/gpl.html</a><br>
&gt; + */<br>
&gt; +<br>
&gt; +extern struct cpu_op *mx51_get_cpu_op(int *op);<br>
&gt; diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile<br>
&gt; index 78d405e..a833d38 100644<br>
&gt; --- a/arch/arm/plat-mxc/Makefile<br>
&gt; +++ b/arch/arm/plat-mxc/Makefile<br>
&gt; @@ -16,6 +16,7 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o<br>
&gt;  obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o<br>
&gt;  obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o<br>
&gt;  obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o<br>
&gt; +obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o<br>
&gt;  ifdef CONFIG_SND_IMX_SOC<br>
&gt;  obj-y += ssi-fiq.o<br>
&gt;  obj-y += ssi-fiq-ksym.o<br>
&gt; diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c<br>
&gt; new file mode 100644<br>
&gt; index 0000000..9cabeb9<br>
&gt; --- /dev/null<br>
&gt; +++ b/arch/arm/plat-mxc/cpufreq.c<br>
&gt; @@ -0,0 +1,202 @@<br>
&gt; +/*<br>
&gt; + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.<br>
&gt; + */<br>
&gt; +<br>
&gt; +/*<br>
&gt; + * The code contained herein is licensed under the GNU General Public<br>
&gt; + * License. You may obtain a copy of the GNU General Public License<br>
&gt; + * Version 2 or later at the following locations:<br>
&gt; + *<br>
&gt; + * <a href="http://www.opensource.org/licenses/gpl-license.html" target="_blank">http://www.opensource.org/licenses/gpl-license.html</a><br>
&gt; + * <a href="http://www.gnu.org/copyleft/gpl.html" target="_blank">http://www.gnu.org/copyleft/gpl.html</a><br>
&gt; + */<br>
&gt; +<br>
&gt; +/*<br>
&gt; + * A driver for the Freescale Semiconductor i.MXC CPUfreq module.<br>
&gt; + * The CPUFREQ driver is for controling CPU frequency. It allows you to change<br>
&gt; + * the CPU clock speed on the fly.<br>
&gt; + */<br>
&gt; +<br>
&gt; +#include &lt;linux/cpufreq.h&gt;<br>
&gt; +#include &lt;linux/clk.h&gt;<br>
&gt; +#include &lt;linux/err.h&gt;<br>
&gt; +#include &lt;linux/slab.h&gt;<br>
&gt; +#include &lt;mach/hardware.h&gt;<br>
&gt; +#include &lt;mach/clock.h&gt;<br>
&gt; +<br>
&gt; +#define CLK32_FREQ   32768<br>
&gt; +#define NANOSECOND   (1000 * 1000 * 1000)<br>
&gt; +<br>
&gt; +static int cpu_freq_khz_min;<br>
&gt; +static int cpu_freq_khz_max;<br>
&gt; +static int arm_normal_clk;<br>
&gt; +<br>
&gt; +static struct clk *cpu_clk;<br>
&gt; +static struct cpufreq_frequency_table *imx_freq_table;<br>
&gt; +<br>
&gt; +static int cpu_op_nr;<br>
&gt; +static struct cpu_op *cpu_op_tbl;<br>
&gt; +<br>
&gt; +static int set_cpu_freq(int freq)<br>
&gt; +{<br>
&gt; +     int ret = 0;<br>
&gt; +     int org_cpu_rate;<br>
&gt; +<br>
&gt; +     org_cpu_rate = clk_get_rate(cpu_clk);<br>
&gt; +     if (org_cpu_rate == freq)<br>
&gt; +             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>
&gt; +<br>
&gt; +     ret = clk_set_rate(cpu_clk, freq);<br>
&gt; +     if (ret != 0) {<br>
&gt; +             printk(KERN_DEBUG &quot;cannot set CPU clock rate\n&quot;);<br>
&gt; +             return ret;<br>
&gt; +     }<br>
&gt; +<br>
&gt; +     return ret;<br>
&gt; +}<br>
&gt; +<br>
&gt; +static int mxc_verify_speed(struct cpufreq_policy *policy)<br>
&gt; +{<br>
&gt; +     if (policy-&gt;cpu != 0)<br>
&gt; +             return -EINVAL;<br>
&gt; +<br>
&gt; +     return cpufreq_frequency_table_verify(policy, imx_freq_table);<br>
&gt; +}<br>
&gt; +<br>
&gt; +static unsigned int mxc_get_speed(unsigned int cpu)<br>
&gt; +{<br>
&gt; +     if (cpu)<br>
&gt; +             return 0;<br>
&gt; +<br>
&gt; +     return clk_get_rate(cpu_clk) / 1000;<br>
&gt; +}<br>
&gt; +<br>
&gt; +static int mxc_set_target(struct cpufreq_policy *policy,<br>
&gt; +                       unsigned int target_freq, unsigned int relation)<br>
&gt; +{<br>
&gt; +     struct cpufreq_freqs freqs;<br>
&gt; +     int freq_Hz;<br>
&gt; +     int ret = 0;<br>
&gt; +     unsigned int index;<br>
&gt; +<br>
&gt; +     cpufreq_frequency_table_target(policy, imx_freq_table,<br>
&gt; +                     target_freq, relation, &amp;index);<br>
&gt; +     freq_Hz = imx_freq_table[index].frequency * 1000;<br>
&gt; +<br>
&gt; +     freqs.old = clk_get_rate(cpu_clk) / 1000;<br>
&gt; +     freqs.new = freq_Hz / 1000;<br>
&gt; +     freqs.cpu = 0;<br>
&gt; +     freqs.flags = 0;<br>
&gt; +     cpufreq_notify_transition(&amp;freqs, CPUFREQ_PRECHANGE);<br>
&gt; +<br>
&gt; +     if (freqs.old != freqs.new)<br>
&gt; +             ret = set_cpu_freq(freq_Hz);<br>
&gt; +<br>
&gt; +     cpufreq_notify_transition(&amp;freqs, CPUFREQ_POSTCHANGE);<br>
&gt; +<br>
&gt; +     return ret;<br>
&gt; +}<br>
&gt; +<br>
&gt; +static int __init mxc_cpufreq_init(struct cpufreq_policy *policy)<br>
&gt; +{<br>
&gt; +     int ret;<br>
&gt; +     int i;<br>
&gt; +<br>
&gt; +     printk(KERN_INFO &quot;i.MXC CPU frequency driver\n&quot;);<br>
&gt; +<br>
&gt; +     if (policy-&gt;cpu != 0)<br>
&gt; +             return -EINVAL;<br>
&gt; +<br>
&gt; +     cpu_clk = clk_get(NULL, &quot;cpu_clk&quot;);<br>
&gt; +     if (IS_ERR(cpu_clk)) {<br>
&gt; +             printk(KERN_ERR &quot;%s: failed to get cpu clock\n&quot;, __func__);<br>
&gt; +             return PTR_ERR(cpu_clk);<br>
&gt; +     }<br>
&gt; +<br>
&gt; +     cpu_op_tbl = get_cpu_op(&amp;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>