diff mbox series

[v1,07/17] cpufreq: tegra20: Use generic cpufreq-dt driver (Tegra30 supported now)

Message ID 20191015211618.20758-8-digetx@gmail.com (mailing list archive)
State Not Applicable, archived
Headers show
Series NVIDIA Tegra20 CPUFreq driver major update | expand

Commit Message

Dmitry Osipenko Oct. 15, 2019, 9:16 p.m. UTC
Re-parenting to intermediate clock is supported now by the clock driver
and thus there is no need in a customized CPUFreq driver, all that code
is common for both Tegra20 and Tegra30. The available CPU freqs are now
specified in device-tree in a form of OPPs, all users should update their
device-trees.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/cpufreq/Kconfig.arm          |   4 +-
 drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
 drivers/cpufreq/tegra20-cpufreq.c    | 236 ++++++---------------------
 3 files changed, 55 insertions(+), 187 deletions(-)

Comments

Viresh Kumar Oct. 16, 2019, 5:18 a.m. UTC | #1
On 16-10-19, 00:16, Dmitry Osipenko wrote:
> Re-parenting to intermediate clock is supported now by the clock driver
> and thus there is no need in a customized CPUFreq driver, all that code
> is common for both Tegra20 and Tegra30. The available CPU freqs are now
> specified in device-tree in a form of OPPs, all users should update their
> device-trees.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/cpufreq/Kconfig.arm          |   4 +-
>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>  drivers/cpufreq/tegra20-cpufreq.c    | 236 ++++++---------------------
>  3 files changed, 55 insertions(+), 187 deletions(-)
> 
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index a905796f7f85..2118c45d0acd 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -301,8 +301,8 @@ config ARM_TANGO_CPUFREQ
>  	default y
>  
>  config ARM_TEGRA20_CPUFREQ
> -	tristate "Tegra20 CPUFreq support"
> -	depends on ARCH_TEGRA
> +	bool "Tegra20 CPUFreq support"

Google is currently working on the GKI (generic kernel image) project where they
want to use a single kernel image with modules for all kind of android devices.
And for that they need all such drivers to be built as module. Since this is
already an module, I would ask you to keep it as is instead of moving it to bool
here. Else some google guy will switch it back as module later on.

LGTM otherwise. Nice work. Thanks.
Dmitry Osipenko Oct. 16, 2019, 1:29 p.m. UTC | #2
16.10.2019 08:18, Viresh Kumar пишет:
> On 16-10-19, 00:16, Dmitry Osipenko wrote:
>> Re-parenting to intermediate clock is supported now by the clock driver
>> and thus there is no need in a customized CPUFreq driver, all that code
>> is common for both Tegra20 and Tegra30. The available CPU freqs are now
>> specified in device-tree in a form of OPPs, all users should update their
>> device-trees.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>>  drivers/cpufreq/Kconfig.arm          |   4 +-
>>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>  drivers/cpufreq/tegra20-cpufreq.c    | 236 ++++++---------------------
>>  3 files changed, 55 insertions(+), 187 deletions(-)
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index a905796f7f85..2118c45d0acd 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -301,8 +301,8 @@ config ARM_TANGO_CPUFREQ
>>  	default y
>>  
>>  config ARM_TEGRA20_CPUFREQ
>> -	tristate "Tegra20 CPUFreq support"
>> -	depends on ARCH_TEGRA
>> +	bool "Tegra20 CPUFreq support"
> 
> Google is currently working on the GKI (generic kernel image) project where they
> want to use a single kernel image with modules for all kind of android devices.
> And for that they need all such drivers to be built as module. Since this is
> already an module, I would ask you to keep it as is instead of moving it to bool
> here. Else some google guy will switch it back as module later on.
> 
> LGTM otherwise. Nice work. Thanks.
> 

Okay, I'll keep the modularity in v2.

Although, tegra20-cpufreq isn't a driver anymore because now it merely
prepares OPP table for the cpufreq-dt driver, which is really a one-shot
action that is enough to do during boot and thus modularity is a bit
redundant here.
Peter Geis Oct. 16, 2019, 2:58 p.m. UTC | #3
On Wed, Oct 16, 2019 at 9:29 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>
> 16.10.2019 08:18, Viresh Kumar пишет:
> > On 16-10-19, 00:16, Dmitry Osipenko wrote:
> >> Re-parenting to intermediate clock is supported now by the clock driver
> >> and thus there is no need in a customized CPUFreq driver, all that code
> >> is common for both Tegra20 and Tegra30. The available CPU freqs are now
> >> specified in device-tree in a form of OPPs, all users should update their
> >> device-trees.
> >>
> >> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> >> ---
> >>  drivers/cpufreq/Kconfig.arm          |   4 +-
> >>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
> >>  drivers/cpufreq/tegra20-cpufreq.c    | 236 ++++++---------------------
> >>  3 files changed, 55 insertions(+), 187 deletions(-)
> >>
> >> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> >> index a905796f7f85..2118c45d0acd 100644
> >> --- a/drivers/cpufreq/Kconfig.arm
> >> +++ b/drivers/cpufreq/Kconfig.arm
> >> @@ -301,8 +301,8 @@ config ARM_TANGO_CPUFREQ
> >>      default y
> >>
> >>  config ARM_TEGRA20_CPUFREQ
> >> -    tristate "Tegra20 CPUFreq support"
> >> -    depends on ARCH_TEGRA
> >> +    bool "Tegra20 CPUFreq support"
> >
> > Google is currently working on the GKI (generic kernel image) project where they
> > want to use a single kernel image with modules for all kind of android devices.
> > And for that they need all such drivers to be built as module. Since this is
> > already an module, I would ask you to keep it as is instead of moving it to bool
> > here. Else some google guy will switch it back as module later on.
> >
> > LGTM otherwise. Nice work. Thanks.
> >
>
> Okay, I'll keep the modularity in v2.
>
> Although, tegra20-cpufreq isn't a driver anymore because now it merely
> prepares OPP table for the cpufreq-dt driver, which is really a one-shot
> action that is enough to do during boot and thus modularity is a bit
> redundant here.

I doubt Google will care much, since Android has moved on to aarch64.
Do they even support arm32 any more?
Dmitry Osipenko Oct. 16, 2019, 6:19 p.m. UTC | #4
16.10.2019 17:58, Peter Geis пишет:
> On Wed, Oct 16, 2019 at 9:29 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>>
>> 16.10.2019 08:18, Viresh Kumar пишет:
>>> On 16-10-19, 00:16, Dmitry Osipenko wrote:
>>>> Re-parenting to intermediate clock is supported now by the clock driver
>>>> and thus there is no need in a customized CPUFreq driver, all that code
>>>> is common for both Tegra20 and Tegra30. The available CPU freqs are now
>>>> specified in device-tree in a form of OPPs, all users should update their
>>>> device-trees.
>>>>
>>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>>> ---
>>>>  drivers/cpufreq/Kconfig.arm          |   4 +-
>>>>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>>>  drivers/cpufreq/tegra20-cpufreq.c    | 236 ++++++---------------------
>>>>  3 files changed, 55 insertions(+), 187 deletions(-)
>>>>
>>>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>>>> index a905796f7f85..2118c45d0acd 100644
>>>> --- a/drivers/cpufreq/Kconfig.arm
>>>> +++ b/drivers/cpufreq/Kconfig.arm
>>>> @@ -301,8 +301,8 @@ config ARM_TANGO_CPUFREQ
>>>>      default y
>>>>
>>>>  config ARM_TEGRA20_CPUFREQ
>>>> -    tristate "Tegra20 CPUFreq support"
>>>> -    depends on ARCH_TEGRA
>>>> +    bool "Tegra20 CPUFreq support"
>>>
>>> Google is currently working on the GKI (generic kernel image) project where they
>>> want to use a single kernel image with modules for all kind of android devices.
>>> And for that they need all such drivers to be built as module. Since this is
>>> already an module, I would ask you to keep it as is instead of moving it to bool
>>> here. Else some google guy will switch it back as module later on.
>>>
>>> LGTM otherwise. Nice work. Thanks.
>>>
>>
>> Okay, I'll keep the modularity in v2.
>>
>> Although, tegra20-cpufreq isn't a driver anymore because now it merely
>> prepares OPP table for the cpufreq-dt driver, which is really a one-shot
>> action that is enough to do during boot and thus modularity is a bit
>> redundant here.
> 
> I doubt Google will care much, since Android has moved on to aarch64.
> Do they even support arm32 any more?

Yes, I don't think there is a real need to care about Google. They won't
use pure upstream and won't care about older hardware any ways.
Viresh Kumar Oct. 17, 2019, 2:32 a.m. UTC | #5
On 16-10-19, 21:19, Dmitry Osipenko wrote:
> 16.10.2019 17:58, Peter Geis пишет:
> > On Wed, Oct 16, 2019 at 9:29 AM Dmitry Osipenko <digetx@gmail.com> wrote:
> >>
> >> 16.10.2019 08:18, Viresh Kumar пишет:
> >>> On 16-10-19, 00:16, Dmitry Osipenko wrote:
> >>>> Re-parenting to intermediate clock is supported now by the clock driver
> >>>> and thus there is no need in a customized CPUFreq driver, all that code
> >>>> is common for both Tegra20 and Tegra30. The available CPU freqs are now
> >>>> specified in device-tree in a form of OPPs, all users should update their
> >>>> device-trees.
> >>>>
> >>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> >>>> ---
> >>>>  drivers/cpufreq/Kconfig.arm          |   4 +-
> >>>>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
> >>>>  drivers/cpufreq/tegra20-cpufreq.c    | 236 ++++++---------------------
> >>>>  3 files changed, 55 insertions(+), 187 deletions(-)
> >>>>
> >>>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> >>>> index a905796f7f85..2118c45d0acd 100644
> >>>> --- a/drivers/cpufreq/Kconfig.arm
> >>>> +++ b/drivers/cpufreq/Kconfig.arm
> >>>> @@ -301,8 +301,8 @@ config ARM_TANGO_CPUFREQ
> >>>>      default y
> >>>>
> >>>>  config ARM_TEGRA20_CPUFREQ
> >>>> -    tristate "Tegra20 CPUFreq support"
> >>>> -    depends on ARCH_TEGRA
> >>>> +    bool "Tegra20 CPUFreq support"
> >>>
> >>> Google is currently working on the GKI (generic kernel image) project where they
> >>> want to use a single kernel image with modules for all kind of android devices.
> >>> And for that they need all such drivers to be built as module. Since this is
> >>> already an module, I would ask you to keep it as is instead of moving it to bool
> >>> here. Else some google guy will switch it back as module later on.
> >>>
> >>> LGTM otherwise. Nice work. Thanks.
> >>>
> >>
> >> Okay, I'll keep the modularity in v2.
> >>
> >> Although, tegra20-cpufreq isn't a driver anymore because now it merely
> >> prepares OPP table for the cpufreq-dt driver, which is really a one-shot
> >> action that is enough to do during boot and thus modularity is a bit
> >> redundant here.
> > 
> > I doubt Google will care much, since Android has moved on to aarch64.
> > Do they even support arm32 any more?
> 
> Yes, I don't think there is a real need to care about Google. They won't
> use pure upstream and won't care about older hardware any ways.

Well, using (almost) pure upstream is the idea I believe. And the thing is they
want to use a single multi-platform image which should be as small as possible
in size. So it won't have any drivers or platform stuff (if possible) and
everything is module.

I am not sure about arm32/64 thing though. And it is okay if you don't want to
care about Google right now. That was just some side knowledge I had :)
Viresh Kumar Oct. 17, 2019, 2:33 a.m. UTC | #6
On 16-10-19, 00:16, Dmitry Osipenko wrote:
> Re-parenting to intermediate clock is supported now by the clock driver
> and thus there is no need in a customized CPUFreq driver, all that code
> is common for both Tegra20 and Tegra30. The available CPU freqs are now
> specified in device-tree in a form of OPPs, all users should update their
> device-trees.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/cpufreq/Kconfig.arm          |   4 +-
>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>  drivers/cpufreq/tegra20-cpufreq.c    | 236 ++++++---------------------
>  3 files changed, 55 insertions(+), 187 deletions(-)

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Dmitry Osipenko Oct. 17, 2019, 9:09 p.m. UTC | #7
17.10.2019 05:32, Viresh Kumar пишет:
> On 16-10-19, 21:19, Dmitry Osipenko wrote:
>> 16.10.2019 17:58, Peter Geis пишет:
>>> On Wed, Oct 16, 2019 at 9:29 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>>>>
>>>> 16.10.2019 08:18, Viresh Kumar пишет:
>>>>> On 16-10-19, 00:16, Dmitry Osipenko wrote:
>>>>>> Re-parenting to intermediate clock is supported now by the clock driver
>>>>>> and thus there is no need in a customized CPUFreq driver, all that code
>>>>>> is common for both Tegra20 and Tegra30. The available CPU freqs are now
>>>>>> specified in device-tree in a form of OPPs, all users should update their
>>>>>> device-trees.
>>>>>>
>>>>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>>>>> ---
>>>>>>  drivers/cpufreq/Kconfig.arm          |   4 +-
>>>>>>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>>>>>  drivers/cpufreq/tegra20-cpufreq.c    | 236 ++++++---------------------
>>>>>>  3 files changed, 55 insertions(+), 187 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>>>>>> index a905796f7f85..2118c45d0acd 100644
>>>>>> --- a/drivers/cpufreq/Kconfig.arm
>>>>>> +++ b/drivers/cpufreq/Kconfig.arm
>>>>>> @@ -301,8 +301,8 @@ config ARM_TANGO_CPUFREQ
>>>>>>      default y
>>>>>>
>>>>>>  config ARM_TEGRA20_CPUFREQ
>>>>>> -    tristate "Tegra20 CPUFreq support"
>>>>>> -    depends on ARCH_TEGRA
>>>>>> +    bool "Tegra20 CPUFreq support"
>>>>>
>>>>> Google is currently working on the GKI (generic kernel image) project where they
>>>>> want to use a single kernel image with modules for all kind of android devices.
>>>>> And for that they need all such drivers to be built as module. Since this is
>>>>> already an module, I would ask you to keep it as is instead of moving it to bool
>>>>> here. Else some google guy will switch it back as module later on.
>>>>>
>>>>> LGTM otherwise. Nice work. Thanks.
>>>>>
>>>>
>>>> Okay, I'll keep the modularity in v2.
>>>>
>>>> Although, tegra20-cpufreq isn't a driver anymore because now it merely
>>>> prepares OPP table for the cpufreq-dt driver, which is really a one-shot
>>>> action that is enough to do during boot and thus modularity is a bit
>>>> redundant here.
>>>
>>> I doubt Google will care much, since Android has moved on to aarch64.
>>> Do they even support arm32 any more?
>>
>> Yes, I don't think there is a real need to care about Google. They won't
>> use pure upstream and won't care about older hardware any ways.
> 
> Well, using (almost) pure upstream is the idea I believe. And the thing is they
> want to use a single multi-platform image which should be as small as possible
> in size. So it won't have any drivers or platform stuff (if possible) and
> everything is module.
> 
> I am not sure about arm32/64 thing though. And it is okay if you don't want to
> care about Google right now. That was just some side knowledge I had :)
> 

I'll leave the module part as-is for now.
diff mbox series

Patch

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index a905796f7f85..2118c45d0acd 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -301,8 +301,8 @@  config ARM_TANGO_CPUFREQ
 	default y
 
 config ARM_TEGRA20_CPUFREQ
-	tristate "Tegra20 CPUFreq support"
-	depends on ARCH_TEGRA
+	bool "Tegra20 CPUFreq support"
+	depends on ARCH_TEGRA && CPUFREQ_DT
 	default y
 	help
 	  This adds the CPUFreq driver support for Tegra20 SOCs.
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 54bc76743b1f..07e88dcd112d 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -121,6 +121,8 @@  static const struct of_device_id blacklist[] __initconst = {
 	{ .compatible = "mediatek,mt8176", },
 	{ .compatible = "mediatek,mt8183", },
 
+	{ .compatible = "nvidia,tegra20", },
+	{ .compatible = "nvidia,tegra30", },
 	{ .compatible = "nvidia,tegra124", },
 	{ .compatible = "nvidia,tegra210", },
 
diff --git a/drivers/cpufreq/tegra20-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c
index f84ecd22f488..042017c73afa 100644
--- a/drivers/cpufreq/tegra20-cpufreq.c
+++ b/drivers/cpufreq/tegra20-cpufreq.c
@@ -7,215 +7,81 @@ 
  *	Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia Corporation
  */
 
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
+#define pr_fmt(fmt) "tegra20-cpufreq: " fmt
+
+#include <linux/bits.h>
 #include <linux/err.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/pm_opp.h>
 #include <linux/types.h>
 
-static struct cpufreq_frequency_table freq_table[] = {
-	{ .frequency = 216000 },
-	{ .frequency = 312000 },
-	{ .frequency = 456000 },
-	{ .frequency = 608000 },
-	{ .frequency = 760000 },
-	{ .frequency = 816000 },
-	{ .frequency = 912000 },
-	{ .frequency = 1000000 },
-	{ .frequency = CPUFREQ_TABLE_END },
-};
-
-struct tegra20_cpufreq {
-	struct device *dev;
-	struct cpufreq_driver driver;
-	struct clk *cpu_clk;
-	struct clk *pll_x_clk;
-	struct clk *pll_p_clk;
-	bool pll_x_prepared;
-};
-
-static unsigned int tegra_get_intermediate(struct cpufreq_policy *policy,
-					   unsigned int index)
-{
-	struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
-	unsigned int ifreq = clk_get_rate(cpufreq->pll_p_clk) / 1000;
-
-	/*
-	 * Don't switch to intermediate freq if:
-	 * - we are already at it, i.e. policy->cur == ifreq
-	 * - index corresponds to ifreq
-	 */
-	if (freq_table[index].frequency == ifreq || policy->cur == ifreq)
-		return 0;
-
-	return ifreq;
-}
+#include <soc/tegra/common.h>
+#include <soc/tegra/fuse.h>
 
-static int tegra_target_intermediate(struct cpufreq_policy *policy,
-				     unsigned int index)
+static bool __init cpu0_node_has_opp_v2_prop(void)
 {
-	struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
-	int ret;
-
-	/*
-	 * Take an extra reference to the main pll so it doesn't turn
-	 * off when we move the cpu off of it as enabling it again while we
-	 * switch to it from tegra_target() would take additional time.
-	 *
-	 * When target-freq is equal to intermediate freq we don't need to
-	 * switch to an intermediate freq and so this routine isn't called.
-	 * Also, we wouldn't be using pll_x anymore and must not take extra
-	 * reference to it, as it can be disabled now to save some power.
-	 */
-	clk_prepare_enable(cpufreq->pll_x_clk);
-
-	ret = clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_p_clk);
-	if (ret)
-		clk_disable_unprepare(cpufreq->pll_x_clk);
-	else
-		cpufreq->pll_x_prepared = true;
+	struct device_node *np = of_cpu_device_node_get(0);
+	bool ret = false;
 
-	return ret;
-}
-
-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 int ifreq = clk_get_rate(cpufreq->pll_p_clk) / 1000;
-	int ret;
-
-	/*
-	 * target freq == pll_p, don't need to take extra reference to pll_x_clk
-	 * as it isn't used anymore.
-	 */
-	if (rate == ifreq)
-		return clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_p_clk);
-
-	ret = clk_set_rate(cpufreq->pll_x_clk, rate * 1000);
-	/* Restore to earlier frequency on error, i.e. pll_x */
-	if (ret)
-		dev_err(cpufreq->dev, "Failed to change pll_x to %lu\n", rate);
-
-	ret = clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_x_clk);
-	/* This shouldn't fail while changing or restoring */
-	WARN_ON(ret);
-
-	/*
-	 * Drop count to pll_x clock only if we switched to intermediate freq
-	 * earlier while transitioning to a target frequency.
-	 */
-	if (cpufreq->pll_x_prepared) {
-		clk_disable_unprepare(cpufreq->pll_x_clk);
-		cpufreq->pll_x_prepared = false;
-	}
+	if (of_get_property(np, "operating-points-v2", NULL))
+		ret = true;
 
+	of_node_put(np);
 	return ret;
 }
 
-static int tegra_cpu_init(struct cpufreq_policy *policy)
+static int __init tegra20_cpufreq_init(void)
 {
-	struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
-
-	clk_prepare_enable(cpufreq->cpu_clk);
-
-	/* FIXME: what's the actual transition time? */
-	cpufreq_generic_init(policy, freq_table, 300 * 1000);
-	policy->clk = cpufreq->cpu_clk;
-	policy->suspend_freq = freq_table[0].frequency;
-	return 0;
-}
-
-static int tegra_cpu_exit(struct cpufreq_policy *policy)
-{
-	struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
-
-	clk_disable_unprepare(cpufreq->cpu_clk);
-	return 0;
-}
-
-static int tegra20_cpufreq_probe(struct platform_device *pdev)
-{
-	struct tegra20_cpufreq *cpufreq;
+	struct platform_device *cpufreq_dt;
+	struct opp_table *opp_table;
+	u32 versions[2];
 	int err;
 
-	cpufreq = devm_kzalloc(&pdev->dev, sizeof(*cpufreq), GFP_KERNEL);
-	if (!cpufreq)
-		return -ENOMEM;
+	if (!soc_is_tegra())
+		return 0;
 
-	cpufreq->cpu_clk = clk_get_sys(NULL, "cclk");
-	if (IS_ERR(cpufreq->cpu_clk))
-		return PTR_ERR(cpufreq->cpu_clk);
+	switch (tegra_get_chip_id()) {
+	case TEGRA20:
+		versions[0] = BIT(tegra_sku_info.cpu_process_id);
+		versions[1] = BIT(tegra_sku_info.soc_speedo_id);
+		break;
+	case TEGRA30:
+		versions[0] = BIT(tegra_sku_info.cpu_process_id);
+		versions[1] = BIT(tegra_sku_info.cpu_speedo_id);
+		break;
+	default:
+		return 0;
+	}
 
-	cpufreq->pll_x_clk = clk_get_sys(NULL, "pll_x");
-	if (IS_ERR(cpufreq->pll_x_clk)) {
-		err = PTR_ERR(cpufreq->pll_x_clk);
-		goto put_cpu;
+	if (!cpu0_node_has_opp_v2_prop()) {
+		pr_err("operating points not found\n");
+		pr_err("can't continue, please update your device tree\n");
+		return 0;
 	}
 
-	cpufreq->pll_p_clk = clk_get_sys(NULL, "pll_p");
-	if (IS_ERR(cpufreq->pll_p_clk)) {
-		err = PTR_ERR(cpufreq->pll_p_clk);
-		goto put_pll_x;
+	pr_info("hardware version 0x%x 0x%x\n", versions[0], versions[1]);
+
+	opp_table = dev_pm_opp_set_supported_hw(get_cpu_device(0), versions, 2);
+	err = PTR_ERR_OR_ZERO(opp_table);
+	if (err) {
+		pr_err("failed to set supported hw: %d\n", err);
+		return err;
 	}
 
-	cpufreq->dev = &pdev->dev;
-	cpufreq->driver.get = cpufreq_generic_get;
-	cpufreq->driver.attr = cpufreq_generic_attr;
-	cpufreq->driver.init = tegra_cpu_init;
-	cpufreq->driver.exit = tegra_cpu_exit;
-	cpufreq->driver.flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK;
-	cpufreq->driver.verify = cpufreq_generic_frequency_table_verify;
-	cpufreq->driver.suspend = cpufreq_generic_suspend;
-	cpufreq->driver.driver_data = cpufreq;
-	cpufreq->driver.target_index = tegra_target;
-	cpufreq->driver.get_intermediate = tegra_get_intermediate;
-	cpufreq->driver.target_intermediate = tegra_target_intermediate;
-	snprintf(cpufreq->driver.name, CPUFREQ_NAME_LEN, "tegra");
-
-	err = cpufreq_register_driver(&cpufreq->driver);
-	if (err)
-		goto put_pll_p;
-
-	platform_set_drvdata(pdev, cpufreq);
+	cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+	err = PTR_ERR_OR_ZERO(cpufreq_dt);
+	if (err) {
+		pr_err("failed to create cpufreq-dt device: %d\n", err);
+		goto err_put_supported_hw;
+	}
 
 	return 0;
 
-put_pll_p:
-	clk_put(cpufreq->pll_p_clk);
-put_pll_x:
-	clk_put(cpufreq->pll_x_clk);
-put_cpu:
-	clk_put(cpufreq->cpu_clk);
+err_put_supported_hw:
+	dev_pm_opp_put_supported_hw(opp_table);
 
 	return err;
 }
-
-static int tegra20_cpufreq_remove(struct platform_device *pdev)
-{
-	struct tegra20_cpufreq *cpufreq = platform_get_drvdata(pdev);
-
-	cpufreq_unregister_driver(&cpufreq->driver);
-
-	clk_put(cpufreq->pll_p_clk);
-	clk_put(cpufreq->pll_x_clk);
-	clk_put(cpufreq->cpu_clk);
-
-	return 0;
-}
-
-static struct platform_driver tegra20_cpufreq_driver = {
-	.probe		= tegra20_cpufreq_probe,
-	.remove		= tegra20_cpufreq_remove,
-	.driver		= {
-		.name	= "tegra20-cpufreq",
-	},
-};
-module_platform_driver(tegra20_cpufreq_driver);
-
-MODULE_ALIAS("platform:tegra20-cpufreq");
-MODULE_AUTHOR("Colin Cross <ccross@android.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra20 cpufreq driver");
-MODULE_LICENSE("GPL");
+late_initcall(tegra20_cpufreq_init);