Skip to content

Instantly share code, notes, and snippets.

@digetx
Created August 10, 2018 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save digetx/267e9d3055b2f28e30f61c0906b4635f to your computer and use it in GitHub Desktop.
Save digetx/267e9d3055b2f28e30f61c0906b4635f to your computer and use it in GitHub Desktop.
T30 cpufreq
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 590b1cf1a8c4..9fb2835e8977 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -116,6 +116,10 @@ static void __init tegra_dt_init_late(void)
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
of_machine_is_compatible("nvidia,tegra20"))
platform_device_register_simple("tegra20-cpufreq", -1, NULL, 0);
+
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) &&
+ of_machine_is_compatible("nvidia,tegra30"))
+ platform_device_register_simple("tegra20-cpufreq", -1, NULL, 0);
}
static const char * const tegra_dt_board_compat[] = {
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index a8a2e210c624..377ef78c57d1 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -264,11 +264,11 @@ config ARM_TANGO_CPUFREQ
default y
config ARM_TEGRA20_CPUFREQ
- tristate "Tegra20 CPUFreq support"
+ tristate "Tegra20/30 CPUFreq support"
depends on ARCH_TEGRA
default y
help
- This adds the CPUFreq driver support for Tegra20 SOCs.
+ This adds the CPUFreq driver support for Tegra20/30 SOCs.
config ARM_TEGRA124_CPUFREQ
tristate "Tegra124 CPUFreq support"
diff --git a/drivers/cpufreq/tegra20-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c
index 05f57dcd5215..dc006fa318e7 100644
--- a/drivers/cpufreq/tegra20-cpufreq.c
+++ b/drivers/cpufreq/tegra20-cpufreq.c
@@ -21,10 +21,11 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/types.h>
-static struct cpufreq_frequency_table freq_table[] = {
+static struct cpufreq_frequency_table tegra20_freq_table[] = {
{ .frequency = 216000 },
{ .frequency = 312000 },
{ .frequency = 456000 },
@@ -36,9 +37,28 @@ static struct cpufreq_frequency_table freq_table[] = {
{ .frequency = CPUFREQ_TABLE_END },
};
+static struct cpufreq_frequency_table tegra30_freq_table[] = {
+ { .frequency = 204000 },
+ { .frequency = 306000 },
+ { .frequency = 408000 },
+ { .frequency = 612000 },
+ { .frequency = 760000 },
+ { .frequency = 816000 },
+ { .frequency = 910000 },
+ { .frequency = 1000000 },
+ { .frequency = 1100000 },
+ { .frequency = 1200000 },
+ { .frequency = 1300000 },
+ { .frequency = 1400000 },
+ { .frequency = 1500000 },
+ { .frequency = 1600000 },
+ { .frequency = CPUFREQ_TABLE_END },
+};
+
struct tegra20_cpufreq {
struct device *dev;
struct cpufreq_driver driver;
+ struct cpufreq_frequency_table *freq_table;
struct clk *cpu_clk;
struct clk *pll_x_clk;
struct clk *pll_p_clk;
@@ -56,7 +76,8 @@ static unsigned int tegra_get_intermediate(struct cpufreq_policy *policy,
* - we are already at it, i.e. policy->cur == ifreq
* - index corresponds to ifreq
*/
- if (freq_table[index].frequency == ifreq || policy->cur == ifreq)
+ if (cpufreq->freq_table[index].frequency == ifreq ||
+ policy->cur == ifreq)
return 0;
return ifreq;
@@ -92,7 +113,7 @@ static int tegra_target_intermediate(struct cpufreq_policy *policy,
static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
{
struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
- unsigned long rate = freq_table[index].frequency;
+ unsigned long rate = cpufreq->freq_table[index].frequency;
unsigned int ifreq = clk_get_rate(cpufreq->pll_p_clk) / 1000;
int ret;
@@ -132,14 +153,14 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
clk_prepare_enable(cpufreq->cpu_clk);
/* FIXME: what's the actual transition time? */
- ret = cpufreq_generic_init(policy, freq_table, 300 * 1000);
+ ret = cpufreq_generic_init(policy, cpufreq->freq_table, 300 * 1000);
if (ret) {
clk_disable_unprepare(cpufreq->cpu_clk);
return ret;
}
policy->clk = cpufreq->cpu_clk;
- policy->suspend_freq = freq_table[0].frequency;
+ policy->suspend_freq = cpufreq->freq_table[0].frequency;
return 0;
}
@@ -154,13 +175,16 @@ static int tegra_cpu_exit(struct cpufreq_policy *policy)
static int tegra20_cpufreq_probe(struct platform_device *pdev)
{
struct tegra20_cpufreq *cpufreq;
+ bool t30;
int err;
+ t30 = !!of_machine_is_compatible("nvidia,tegra30");
+
cpufreq = devm_kzalloc(&pdev->dev, sizeof(*cpufreq), GFP_KERNEL);
if (!cpufreq)
return -ENOMEM;
- cpufreq->cpu_clk = clk_get_sys(NULL, "cclk");
+ cpufreq->cpu_clk = clk_get_sys(NULL, t30 ? "cclk_g" : "cclk");
if (IS_ERR(cpufreq->cpu_clk))
return PTR_ERR(cpufreq->cpu_clk);
@@ -170,7 +194,7 @@ static int tegra20_cpufreq_probe(struct platform_device *pdev)
goto put_cpu;
}
- cpufreq->pll_p_clk = clk_get_sys(NULL, "pll_p");
+ cpufreq->pll_p_clk = clk_get_sys(NULL, t30 ? "pll_p_cclkg" : "pll_p");
if (IS_ERR(cpufreq->pll_p_clk)) {
err = PTR_ERR(cpufreq->pll_p_clk);
goto put_pll_x;
@@ -188,6 +212,7 @@ static int tegra20_cpufreq_probe(struct platform_device *pdev)
cpufreq->driver.target_index = tegra_target;
cpufreq->driver.get_intermediate = tegra_get_intermediate;
cpufreq->driver.target_intermediate = tegra_target_intermediate;
+ cpufreq->freq_table = t30 ? tegra30_freq_table : tegra20_freq_table;
snprintf(cpufreq->driver.name, CPUFREQ_NAME_LEN, "tegra");
err = cpufreq_register_driver(&cpufreq->driver);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment