From b8c18483f8826a020ca9e435f2f8f0ddcbf28aa8 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 14 Feb 2013 19:43:20 +0100 Subject: [PATCH] cpufreq: exynos4x12: Parse frequency table from device tree Proxima PQ (rev1.1) can run stable at frequencies not higher than 1100 MHz. In the current code (exynos4x12-cpufreq) frequency up to 1400 MHz can be set (which shall work for REDWOOD). For the Proxima PQ frequency table has been modified and passed via device tree. Tested-on: Proxima PQ rev1.1 Signed-off-by: Lukasz Majewski Signed-off-by: Tomasz Figa --- drivers/cpufreq/exynos-cpufreq.c | 66 ++++++++++++++++++++++++++++++++++++ drivers/cpufreq/exynos-cpufreq.h | 2 ++ drivers/cpufreq/exynos4x12-cpufreq.c | 6 +++- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index ee4b947..3197d88 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -284,6 +284,72 @@ static struct cpufreq_driver exynos_driver = { /* Device Tree Support for CPU freq */ +struct cpufreq_frequency_table *exynos_of_parse_freq_table( + struct exynos_dvfs_info *info, const char *property_name) +{ + struct device_node *node = info->dev->of_node; + struct cpufreq_frequency_table *ft, *ret = NULL; + struct property *pp; + int len, num, i = 0; + u32 *of_f_tab; + + if (!node) + return NULL; + + pp = of_find_property(node, property_name, &len); + if (!pp) { + pr_debug("%s: Property: %s not found\n", __func__, + property_name); + goto err; + } + + if (len == 0) { + pr_debug("%s: Length wrong value!\n", __func__); + goto err; + } + + of_f_tab = kzalloc(len, GFP_KERNEL); + if (!of_f_tab) { + pr_err("%s: Allocation failed\n", __func__); + goto err; + } + + num = len / sizeof(u32); + + if (of_property_read_u32_array(node, pp->name, of_f_tab, num)) { + pr_err("%s: Property: %s cannot be read!\n", __func__, + pp->name); + goto err_of_f_tab; + } + + /* Here + 2 is required for CPUFREQ_ENTRY_INVALID and + CPUFREQ_TABLE_END */ + ft = kzalloc(sizeof(struct cpufreq_frequency_table) * (num + 2), + GFP_KERNEL); + if (!ft) { + pr_err("%s: Allocation failed\n", __func__); + goto err_of_f_tab; + } + + ft[0].index = L0; + ft[0].frequency = CPUFREQ_ENTRY_INVALID; + + for (i = 1; i <= num; i++) { + ft[i].index = i; + ft[i].frequency = of_f_tab[i-1]; + } + + ft[i].index = 0; + ft[i].frequency = CPUFREQ_TABLE_END; + + ret = ft; + + err_of_f_tab: + kfree(of_f_tab); + err: + return ret; +} + #ifdef CONFIG_OF static struct of_device_id exynos_cpufreq_of_match[] __initconst = { { .compatible = "samsung,exynos-cpufreq", }, diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h index 1d45a61..4e08ba7 100644 --- a/drivers/cpufreq/exynos-cpufreq.h +++ b/drivers/cpufreq/exynos-cpufreq.h @@ -47,3 +47,5 @@ struct exynos_dvfs_info { extern int exynos4210_cpufreq_init(struct exynos_dvfs_info *); extern int exynos4x12_cpufreq_init(struct exynos_dvfs_info *); extern int exynos5250_cpufreq_init(struct exynos_dvfs_info *); +extern struct cpufreq_frequency_table *exynos_of_parse_freq_table( + struct exynos_dvfs_info *info, const char *property_name); diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c index 972e949..70999b2 100644 --- a/drivers/cpufreq/exynos4x12-cpufreq.c +++ b/drivers/cpufreq/exynos4x12-cpufreq.c @@ -247,7 +247,11 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) info->pll_safe_idx = L7; info->cpu_clk = cpu_clk; info->volt_table = exynos4x12_volt_table; - info->freq_table = exynos4x12_freq_table; + + info->freq_table = exynos_of_parse_freq_table(info, "freq_table"); + if (!info->freq_table) + info->freq_table = exynos4x12_freq_table; + info->set_freq = exynos4x12_set_frequency; info->need_apll_change = exynos4x12_pms_change; -- 2.7.4