|
@@ -328,3 +328,81 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
|
|
|
/* we keep the cpu pll table in Hz, to ensure we get an
|
|
|
* accurate value for the PLL output. */
|
|
|
|
|
|
+ tmp_policy.min = policy->min * 1000;
|
|
|
+ tmp_policy.max = policy->max * 1000;
|
|
|
+ tmp_policy.cpu = policy->cpu;
|
|
|
+
|
|
|
+ /* cpufreq_frequency_table_target uses a pointer to 'index'
|
|
|
+ * which is the number of the table entry, not the value of
|
|
|
+ * the table entry's index field. */
|
|
|
+
|
|
|
+ ret = cpufreq_frequency_table_target(&tmp_policy, pll_reg,
|
|
|
+ target_freq, relation,
|
|
|
+ &index);
|
|
|
+
|
|
|
+ if (ret < 0) {
|
|
|
+ printk(KERN_ERR "%s: no PLL available\n", __func__);
|
|
|
+ goto err_notpossible;
|
|
|
+ }
|
|
|
+
|
|
|
+ pll = pll_reg + index;
|
|
|
+
|
|
|
+ s3c_freq_dbg("%s: target %u => %u\n",
|
|
|
+ __func__, target_freq, pll->frequency);
|
|
|
+
|
|
|
+ target_freq = pll->frequency;
|
|
|
+ }
|
|
|
+
|
|
|
+ return s3c_cpufreq_settarget(policy, target_freq, pll);
|
|
|
+
|
|
|
+ err_notpossible:
|
|
|
+ printk(KERN_ERR "no compatible settings for %d\n", target_freq);
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned int s3c_cpufreq_get(unsigned int cpu)
|
|
|
+{
|
|
|
+ return clk_get_rate(clk_arm) / 1000;
|
|
|
+}
|
|
|
+
|
|
|
+struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
|
|
|
+{
|
|
|
+ struct clk *clk;
|
|
|
+
|
|
|
+ clk = clk_get(dev, name);
|
|
|
+ if (IS_ERR(clk))
|
|
|
+ printk(KERN_ERR "cpufreq: failed to get clock '%s'\n", name);
|
|
|
+
|
|
|
+ return clk;
|
|
|
+}
|
|
|
+
|
|
|
+static int s3c_cpufreq_init(struct cpufreq_policy *policy)
|
|
|
+{
|
|
|
+ printk(KERN_INFO "%s: initialising policy %p\n", __func__, policy);
|
|
|
+
|
|
|
+ if (policy->cpu != 0)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ policy->cur = s3c_cpufreq_get(0);
|
|
|
+ policy->min = policy->cpuinfo.min_freq = 0;
|
|
|
+ policy->max = policy->cpuinfo.max_freq = cpu_cur.info->max.fclk / 1000;
|
|
|
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
|
|
+
|
|
|
+ /* feed the latency information from the cpu driver */
|
|
|
+ policy->cpuinfo.transition_latency = cpu_cur.info->latency;
|
|
|
+
|
|
|
+ if (ftab)
|
|
|
+ cpufreq_frequency_table_cpuinfo(policy, ftab);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static __init int s3c_cpufreq_initclks(void)
|
|
|
+{
|
|
|
+ _clk_mpll = s3c_cpufreq_clk_get(NULL, "mpll");
|
|
|
+ _clk_xtal = s3c_cpufreq_clk_get(NULL, "xtal");
|
|
|
+ clk_fclk = s3c_cpufreq_clk_get(NULL, "fclk");
|
|
|
+ clk_hclk = s3c_cpufreq_clk_get(NULL, "hclk");
|
|
|
+ clk_pclk = s3c_cpufreq_clk_get(NULL, "pclk");
|
|
|
+ clk_arm = s3c_cpufreq_clk_get(NULL, "armclk");
|
|
|
+
|