diff mbox

[v3,2/2] cpufreq: qoriq: Don't look at clock implementation details

Message ID 1466058085-19353-2-git-send-email-oss@buserror.net (mailing list archive)
State Rejected, archived
Delegated to: Stephen Boyd
Headers show

Commit Message

Crystal Wood June 16, 2016, 6:21 a.m. UTC
From: Scott Wood <scottwood@freescale.com>

Get the CPU clock's potential parent clocks from the clock interface
itself, rather than manually parsing the clocks property to find a
phandle, looking at the clock-names property of that, and assuming that
those are valid parent clocks for the cpu clock.

This is necessary now that the clocks are generated based on the clock
driver's knowledge of the chip rather than a fragile device-tree
description of the mux options.

We can now rely on the clock driver to ensure that the mux only exposes
options that are valid.  The cpufreq driver was currently being overly
conservative in some cases -- for example, the "min_cpufreq =
get_bus_freq()" restriction only applies to chips with erratum
A-004510, and whether the freq_mask used on p5020 is needed depends on
the actual frequencies of the PLLs (FWIW, p5040 has a similar
limitation but its .freq_mask was zero) -- and the frequency mask
mechanism made assumptions about particular parent clock indices that
are no longer valid.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
---
v2: no changes

v3: Remove the now-unused pnode and the call to of_node_put()

 drivers/cpufreq/qoriq-cpufreq.c | 141 ++++++++++++----------------------------
 1 file changed, 41 insertions(+), 100 deletions(-)

Comments

Michael Turquette July 7, 2016, 1:30 a.m. UTC | #1
Quoting Scott Wood (2016-06-15 23:21:25)
> -static struct device_node *cpu_to_clk_node(int cpu)
> +static struct clk *cpu_to_clk(int cpu)
>  {
> -       struct device_node *np, *clk_np;
> +       struct device_node *np;
> +       struct clk *clk;
>  
>         if (!cpu_present(cpu))
>                 return NULL;
> @@ -112,37 +80,28 @@ static struct device_node *cpu_to_clk_node(int cpu)
>         if (!np)
>                 return NULL;
>  
> -       clk_np = of_parse_phandle(np, "clocks", 0);
> -       if (!clk_np)
> -               return NULL;
> -
> +       clk = of_clk_get(np, 0);

Why not use devm_clk_get here?

> @@ -221,17 +180,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
>                 goto err_nomem2;
>         }
>  
> -       pnode = of_parse_phandle(np, "clocks", 0);
> -       if (!pnode) {
> -               pr_err("%s: could not get clock information\n", __func__);
> -               goto err_nomem2;
> -       }
> +       count = clk_get_num_parents(policy->clk);

We already have of_clk_get_parent_count. This is found in
clk-provider.h, which doesn't fit perfectly here since the cpufreq
driver is not a clock provider, but instead a consumer.

> @@ -240,23 +194,11 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
>                 goto err_pclk;
>         }
>  
> -       if (fmask)
> -               mask = fmask[get_cpu_physical_id(cpu)];
> -       else
> -               mask = 0x0;
> -
>         for (i = 0; i < count; i++) {
> -               clk = of_clk_get(pnode, i);
> +               clk = clk_get_parent_by_index(policy->clk, i);
>                 data->pclk[i] = clk;
>                 freq = clk_get_rate(clk);
> -               /*
> -                * the clock is valid if its frequency is not masked
> -                * and large than minimum allowed frequency.
> -                */
> -               if (freq < min_cpufreq || (mask & (1 << i)))
> -                       table[i].frequency = CPUFREQ_ENTRY_INVALID;
> -               else
> -                       table[i].frequency = freq / 1000;
> +               table[i].frequency = freq / 1000;

Hmm, so you change cpu clock rate by selecting different clock sources
from a cpu clock mux, right? I wonder if you can just have a child mux
clock that selects parents from .set_rate (via a .determine_rate
callback)? Then you could just call clk_set_rate() on your cpu mux clock
and maybe skip most of the stuff this driver does?

Regards,
Mike
--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Crystal Wood July 7, 2016, 4:13 a.m. UTC | #2
On Wed, 2016-07-06 at 18:30 -0700, Michael Turquette wrote:
> Quoting Scott Wood (2016-06-15 23:21:25)
> > 
> > -static struct device_node *cpu_to_clk_node(int cpu)
> > +static struct clk *cpu_to_clk(int cpu)
> >  {
> > -       struct device_node *np, *clk_np;
> > +       struct device_node *np;
> > +       struct clk *clk;
> >  
> >         if (!cpu_present(cpu))
> >                 return NULL;
> > @@ -112,37 +80,28 @@ static struct device_node *cpu_to_clk_node(int cpu)
> >         if (!np)
> >                 return NULL;
> >  
> > -       clk_np = of_parse_phandle(np, "clocks", 0);
> > -       if (!clk_np)
> > -               return NULL;
> > -
> > +       clk = of_clk_get(np, 0);
> Why not use devm_clk_get here?

devm_clk_get() is a wrapper around clk_get() which is not the same as
of_clk_get().  What device would you pass to devm_clk_get(), and what name
would you pass?

> > 
> > @@ -221,17 +180,12 @@ static int qoriq_cpufreq_cpu_init(struct
> > cpufreq_policy *policy)
> >                 goto err_nomem2;
> >         }
> >  
> > -       pnode = of_parse_phandle(np, "clocks", 0);
> > -       if (!pnode) {
> > -               pr_err("%s: could not get clock information\n", __func__);
> > -               goto err_nomem2;
> > -       }
> > +       count = clk_get_num_parents(policy->clk);
> We already have of_clk_get_parent_count. This is found in
> clk-provider.h, which doesn't fit perfectly here since the cpufreq
> driver is not a clock provider, but instead a consumer.

It's also a device tree function, and the clock parents in question aren't in
the device tree.

> > @@ -240,23 +194,11 @@ static int qoriq_cpufreq_cpu_init(struct
> > cpufreq_policy *policy)
> >                 goto err_pclk;
> >         }
> >  
> > -       if (fmask)
> > -               mask = fmask[get_cpu_physical_id(cpu)];
> > -       else
> > -               mask = 0x0;
> > -
> >         for (i = 0; i < count; i++) {
> > -               clk = of_clk_get(pnode, i);
> > +               clk = clk_get_parent_by_index(policy->clk, i);
> >                 data->pclk[i] = clk;
> >                 freq = clk_get_rate(clk);
> > -               /*
> > -                * the clock is valid if its frequency is not masked
> > -                * and large than minimum allowed frequency.
> > -                */
> > -               if (freq < min_cpufreq || (mask & (1 << i)))
> > -                       table[i].frequency = CPUFREQ_ENTRY_INVALID;
> > -               else
> > -                       table[i].frequency = freq / 1000;
> > +               table[i].frequency = freq / 1000;
> Hmm, so you change cpu clock rate by selecting different clock sources
> from a cpu clock mux, right?

Yes.  You'd think such a simple thing would be more straightforward.

>  I wonder if you can just have a child mux
> clock that selects parents from .set_rate (via a .determine_rate
> callback)? Then you could just call clk_set_rate() on your cpu mux clock
> and maybe skip most of the stuff this driver does?

"Most of the stuff this driver does" is dealing with the cpufreq subsystem
(ask the cpufreq maintainers why it requires so much boilerplate), associating
clock muxes with cpus, etc.  It is also not obvious to me how to use
determine_rate() or that the end result would be any simpler or better.  It
seems like the implementation would just be reimplementing logic that already
exists in cpufreq, and the cpufreq driver would still need to be able to get a
list of possible frequencies, because cpufreq wants a table of them.

After nearly a year of non-response to these patches[1], a request to
completely rearchitect this driver[2] just to avoid exposing a couple
straightforward informational functions to clock consumers[3] was not quite
what I was hoping for.  What is wrong with clock consumers being able to query
the parent list, given that clock consumers have the ability to request a
particular parent?

-Scott

[1] Original versions:
http://www.spinics.net/lists/linux-clk/msg03069.html
http://www.spinics.net/lists/linux-clk/msg03070.html


[2] The only reason I'm touching this driver at all is because it currently
makes bad assumptions about clock provider internals (and clock provider
device tree structure) that are broken by the new bindings enabled by
commit 0dfc86b3173fee ("clk: qoriq: Move chip-specific knowledge into
driver").

[3] I initially discussed adding consumer APIs for this patchset in 
http://lkml.iu.edu/hypermail/linux/kernel/1509.2/02728.html

--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Michael Turquette July 8, 2016, 2:26 a.m. UTC | #3
Quoting Scott Wood (2016-07-06 21:13:23)
> On Wed, 2016-07-06 at 18:30 -0700, Michael Turquette wrote:
> > Quoting Scott Wood (2016-06-15 23:21:25)
> > > 
> > > -static struct device_node *cpu_to_clk_node(int cpu)
> > > +static struct clk *cpu_to_clk(int cpu)
> > >  {
> > > -       struct device_node *np, *clk_np;
> > > +       struct device_node *np;
> > > +       struct clk *clk;
> > >  
> > >         if (!cpu_present(cpu))
> > >                 return NULL;
> > > @@ -112,37 +80,28 @@ static struct device_node *cpu_to_clk_node(int cpu)
> > >         if (!np)
> > >                 return NULL;
> > >  
> > > -       clk_np = of_parse_phandle(np, "clocks", 0);
> > > -       if (!clk_np)
> > > -               return NULL;
> > > -
> > > +       clk = of_clk_get(np, 0);
> > Why not use devm_clk_get here?
> 
> devm_clk_get() is a wrapper around clk_get() which is not the same as
> of_clk_get().  What device would you pass to devm_clk_get(), and what name
> would you pass?

I'm fuzzy on whether or not you get a struct device from a cpufreq
driver. If so, then that would be the one to use. I would hope that
cpufreq drivers model cpus as devices, but I'm really not sure without
looking into the code.

Regards,
Mike

> 
> > > 
> > > @@ -221,17 +180,12 @@ static int qoriq_cpufreq_cpu_init(struct
> > > cpufreq_policy *policy)
> > >                 goto err_nomem2;
> > >         }
> > >  
> > > -       pnode = of_parse_phandle(np, "clocks", 0);
> > > -       if (!pnode) {
> > > -               pr_err("%s: could not get clock information\n", __func__);
> > > -               goto err_nomem2;
> > > -       }
> > > +       count = clk_get_num_parents(policy->clk);
> > We already have of_clk_get_parent_count. This is found in
> > clk-provider.h, which doesn't fit perfectly here since the cpufreq
> > driver is not a clock provider, but instead a consumer.
> 
> It's also a device tree function, and the clock parents in question aren't in
> the device tree.
> 
> > > @@ -240,23 +194,11 @@ static int qoriq_cpufreq_cpu_init(struct
> > > cpufreq_policy *policy)
> > >                 goto err_pclk;
> > >         }
> > >  
> > > -       if (fmask)
> > > -               mask = fmask[get_cpu_physical_id(cpu)];
> > > -       else
> > > -               mask = 0x0;
> > > -
> > >         for (i = 0; i < count; i++) {
> > > -               clk = of_clk_get(pnode, i);
> > > +               clk = clk_get_parent_by_index(policy->clk, i);
> > >                 data->pclk[i] = clk;
> > >                 freq = clk_get_rate(clk);
> > > -               /*
> > > -                * the clock is valid if its frequency is not masked
> > > -                * and large than minimum allowed frequency.
> > > -                */
> > > -               if (freq < min_cpufreq || (mask & (1 << i)))
> > > -                       table[i].frequency = CPUFREQ_ENTRY_INVALID;
> > > -               else
> > > -                       table[i].frequency = freq / 1000;
> > > +               table[i].frequency = freq / 1000;
> > Hmm, so you change cpu clock rate by selecting different clock sources
> > from a cpu clock mux, right?
> 
> Yes.  You'd think such a simple thing would be more straightforward.
> 
> >  I wonder if you can just have a child mux
> > clock that selects parents from .set_rate (via a .determine_rate
> > callback)? Then you could just call clk_set_rate() on your cpu mux clock
> > and maybe skip most of the stuff this driver does?
> 
> "Most of the stuff this driver does" is dealing with the cpufreq subsystem
> (ask the cpufreq maintainers why it requires so much boilerplate), associating
> clock muxes with cpus, etc.  It is also not obvious to me how to use
> determine_rate() or that the end result would be any simpler or better.  It
> seems like the implementation would just be reimplementing logic that already
> exists in cpufreq, and the cpufreq driver would still need to be able to get a
> list of possible frequencies, because cpufreq wants a table of them.
> 
> After nearly a year of non-response to these patches[1], a request to
> completely rearchitect this driver[2] just to avoid exposing a couple
> straightforward informational functions to clock consumers[3] was not quite
> what I was hoping for.  What is wrong with clock consumers being able to query
> the parent list, given that clock consumers have the ability to request a
> particular parent?
> 
> -Scott
> 
> [1] Original versions:
> http://www.spinics.net/lists/linux-clk/msg03069.html
> http://www.spinics.net/lists/linux-clk/msg03070.html
> 
> 
> [2] The only reason I'm touching this driver at all is because it currently
> makes bad assumptions about clock provider internals (and clock provider
> device tree structure) that are broken by the new bindings enabled by
> commit 0dfc86b3173fee ("clk: qoriq: Move chip-specific knowledge into
> driver").
> 
> [3] I initially discussed adding consumer APIs for this patchset in 
> http://lkml.iu.edu/hypermail/linux/kernel/1509.2/02728.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Crystal Wood July 8, 2016, 9:06 p.m. UTC | #4
On Thu, 2016-07-07 at 19:26 -0700, Michael Turquette wrote:
> Quoting Scott Wood (2016-07-06 21:13:23)
> > 
> > On Wed, 2016-07-06 at 18:30 -0700, Michael Turquette wrote:
> > > 
> > > Quoting Scott Wood (2016-06-15 23:21:25)
> > > > 
> > > > 
> > > > -static struct device_node *cpu_to_clk_node(int cpu)
> > > > +static struct clk *cpu_to_clk(int cpu)
> > > >  {
> > > > -       struct device_node *np, *clk_np;
> > > > +       struct device_node *np;
> > > > +       struct clk *clk;
> > > >  
> > > >         if (!cpu_present(cpu))
> > > >                 return NULL;
> > > > @@ -112,37 +80,28 @@ static struct device_node *cpu_to_clk_node(int
> > > > cpu)
> > > >         if (!np)
> > > >                 return NULL;
> > > >  
> > > > -       clk_np = of_parse_phandle(np, "clocks", 0);
> > > > -       if (!clk_np)
> > > > -               return NULL;
> > > > -
> > > > +       clk = of_clk_get(np, 0);
> > > Why not use devm_clk_get here?
> > devm_clk_get() is a wrapper around clk_get() which is not the same as
> > of_clk_get().  What device would you pass to devm_clk_get(), and what name
> > would you pass?
> I'm fuzzy on whether or not you get a struct device from a cpufreq
> driver. If so, then that would be the one to use. I would hope that
> cpufreq drivers model cpus as devices, but I'm really not sure without
> looking into the code.

It's not the cpufreq code that provides it, but get_cpu_device() could be
used.

Do you have any comments on the first patch of this set?

-Scott

--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
tang yuantian July 20, 2016, 3:02 a.m. UTC | #5
PING.

Regards,
Yuantian

> -----Original Message-----

> From: Scott Wood [mailto:oss@buserror.net]

> Sent: Saturday, July 09, 2016 5:07 AM

> To: Michael Turquette <mturquette@baylibre.com>; Russell King

> <linux@armlinux.org.uk>; Stephen Boyd <sboyd@codeaurora.org>; Viresh

> Kumar <viresh.kumar@linaro.org>; Rafael J. Wysocki <rjw@rjwysocki.net>

> Cc: linux-clk@vger.kernel.org; linux-pm@vger.kernel.org; linuxppc-

> dev@lists.ozlabs.org; Yuantian Tang <yuantian.tang@nxp.com>; Yang-Leo Li

> <leoyang.li@nxp.com>; Xiaofeng Ren <xiaofeng.ren@nxp.com>

> Subject: Re: [PATCH v3 2/2] cpufreq: qoriq: Don't look at clock

> implementation details

> 

> On Thu, 2016-07-07 at 19:26 -0700, Michael Turquette wrote:

> > Quoting Scott Wood (2016-07-06 21:13:23)

> > >

> > > On Wed, 2016-07-06 at 18:30 -0700, Michael Turquette wrote:

> > > >

> > > > Quoting Scott Wood (2016-06-15 23:21:25)

> > > > >

> > > > >

> > > > > -static struct device_node *cpu_to_clk_node(int cpu)

> > > > > +static struct clk *cpu_to_clk(int cpu)

> > > > >  {

> > > > > -       struct device_node *np, *clk_np;

> > > > > +       struct device_node *np;

> > > > > +       struct clk *clk;

> > > > >

> > > > >         if (!cpu_present(cpu))

> > > > >                 return NULL;

> > > > > @@ -112,37 +80,28 @@ static struct device_node

> > > > > *cpu_to_clk_node(int

> > > > > cpu)

> > > > >         if (!np)

> > > > >                 return NULL;

> > > > >

> > > > > -       clk_np = of_parse_phandle(np, "clocks", 0);

> > > > > -       if (!clk_np)

> > > > > -               return NULL;

> > > > > -

> > > > > +       clk = of_clk_get(np, 0);

> > > > Why not use devm_clk_get here?

> > > devm_clk_get() is a wrapper around clk_get() which is not the same

> > > as of_clk_get().  What device would you pass to devm_clk_get(), and

> > > what name would you pass?

> > I'm fuzzy on whether or not you get a struct device from a cpufreq

> > driver. If so, then that would be the one to use. I would hope that

> > cpufreq drivers model cpus as devices, but I'm really not sure without

> > looking into the code.

> 

> It's not the cpufreq code that provides it, but get_cpu_device() could be

> used.

> 

> Do you have any comments on the first patch of this set?

> 

> -Scott
Yang Li Feb. 2, 2017, 6:11 p.m. UTC | #6
On Tue, Jul 19, 2016 at 10:02 PM, Yuantian Tang <yuantian.tang@nxp.com> wrote:
>
> PING.
>
> Regards,
> Yuantian
>
> > -----Original Message-----
> > From: Scott Wood [mailto:oss@buserror.net]
> > Sent: Saturday, July 09, 2016 5:07 AM
> > To: Michael Turquette <mturquette@baylibre.com>; Russell King
> > <linux@armlinux.org.uk>; Stephen Boyd <sboyd@codeaurora.org>; Viresh
> > Kumar <viresh.kumar@linaro.org>; Rafael J. Wysocki <rjw@rjwysocki.net>
> > Cc: linux-clk@vger.kernel.org; linux-pm@vger.kernel.org; linuxppc-
> > dev@lists.ozlabs.org; Yuantian Tang <yuantian.tang@nxp.com>; Yang-Leo Li
> > <leoyang.li@nxp.com>; Xiaofeng Ren <xiaofeng.ren@nxp.com>
> > Subject: Re: [PATCH v3 2/2] cpufreq: qoriq: Don't look at clock
> > implementation details
> >
> > On Thu, 2016-07-07 at 19:26 -0700, Michael Turquette wrote:
> > > Quoting Scott Wood (2016-07-06 21:13:23)
> > > >
> > > > On Wed, 2016-07-06 at 18:30 -0700, Michael Turquette wrote:
> > > > >
> > > > > Quoting Scott Wood (2016-06-15 23:21:25)
> > > > > >
> > > > > >
> > > > > > -static struct device_node *cpu_to_clk_node(int cpu)
> > > > > > +static struct clk *cpu_to_clk(int cpu)
> > > > > >  {
> > > > > > -       struct device_node *np, *clk_np;
> > > > > > +       struct device_node *np;
> > > > > > +       struct clk *clk;
> > > > > >
> > > > > >         if (!cpu_present(cpu))
> > > > > >                 return NULL;
> > > > > > @@ -112,37 +80,28 @@ static struct device_node
> > > > > > *cpu_to_clk_node(int
> > > > > > cpu)
> > > > > >         if (!np)
> > > > > >                 return NULL;
> > > > > >
> > > > > > -       clk_np = of_parse_phandle(np, "clocks", 0);
> > > > > > -       if (!clk_np)
> > > > > > -               return NULL;
> > > > > > -
> > > > > > +       clk = of_clk_get(np, 0);
> > > > > Why not use devm_clk_get here?
> > > > devm_clk_get() is a wrapper around clk_get() which is not the same
> > > > as of_clk_get().  What device would you pass to devm_clk_get(), and
> > > > what name would you pass?
> > > I'm fuzzy on whether or not you get a struct device from a cpufreq
> > > driver. If so, then that would be the one to use. I would hope that
> > > cpufreq drivers model cpus as devices, but I'm really not sure without
> > > looking into the code.
> >
> > It's not the cpufreq code that provides it, but get_cpu_device() could be
> > used.
> >
> > Do you have any comments on the first patch of this set?


Any action on this patch?  This patch is still a dependency for
cpufreq to work on all QorIQ platforms.

Regards,
Leo
--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 53d8c3f..d66b3da 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -37,53 +37,20 @@  struct cpu_data {
 	struct thermal_cooling_device *cdev;
 };
 
+/*
+ * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
+ * matched a more generic compatible.
+ */
+#define SOC_BLACKLIST		1
+
 /**
  * struct soc_data - SoC specific data
- * @freq_mask: mask the disallowed frequencies
- * @flag: unique flags
+ * @flags: SOC_xxx
  */
 struct soc_data {
-	u32 freq_mask[4];
-	u32 flag;
-};
-
-#define FREQ_MASK	1
-/* see hardware specification for the allowed frqeuencies */
-static const struct soc_data sdata[] = {
-	{ /* used by p2041 and p3041 */
-		.freq_mask = {0x8, 0x8, 0x2, 0x2},
-		.flag = FREQ_MASK,
-	},
-	{ /* used by p5020 */
-		.freq_mask = {0x8, 0x2},
-		.flag = FREQ_MASK,
-	},
-	{ /* used by p4080, p5040 */
-		.freq_mask = {0},
-		.flag = 0,
-	},
+	u32 flags;
 };
 
-/*
- * the minimum allowed core frequency, in Hz
- * for chassis v1.0, >= platform frequency
- * for chassis v2.0, >= platform frequency / 2
- */
-static u32 min_cpufreq;
-static const u32 *fmask;
-
-#if defined(CONFIG_ARM)
-static int get_cpu_physical_id(int cpu)
-{
-	return topology_core_id(cpu);
-}
-#else
-static int get_cpu_physical_id(int cpu)
-{
-	return get_hard_smp_processor_id(cpu);
-}
-#endif
-
 static u32 get_bus_freq(void)
 {
 	struct device_node *soc;
@@ -101,9 +68,10 @@  static u32 get_bus_freq(void)
 	return sysfreq;
 }
 
-static struct device_node *cpu_to_clk_node(int cpu)
+static struct clk *cpu_to_clk(int cpu)
 {
-	struct device_node *np, *clk_np;
+	struct device_node *np;
+	struct clk *clk;
 
 	if (!cpu_present(cpu))
 		return NULL;
@@ -112,37 +80,28 @@  static struct device_node *cpu_to_clk_node(int cpu)
 	if (!np)
 		return NULL;
 
-	clk_np = of_parse_phandle(np, "clocks", 0);
-	if (!clk_np)
-		return NULL;
-
+	clk = of_clk_get(np, 0);
 	of_node_put(np);
-
-	return clk_np;
+	return clk;
 }
 
 /* traverse cpu nodes to get cpu mask of sharing clock wire */
 static void set_affected_cpus(struct cpufreq_policy *policy)
 {
-	struct device_node *np, *clk_np;
 	struct cpumask *dstp = policy->cpus;
+	struct clk *clk;
 	int i;
 
-	np = cpu_to_clk_node(policy->cpu);
-	if (!np)
-		return;
-
 	for_each_present_cpu(i) {
-		clk_np = cpu_to_clk_node(i);
-		if (!clk_np)
+		clk = cpu_to_clk(i);
+		if (IS_ERR(clk)) {
+			pr_err("%s: no clock for cpu %d\n", __func__, i);
 			continue;
+		}
 
-		if (clk_np == np)
+		if (clk_is_match(policy->clk, clk))
 			cpumask_set_cpu(i, dstp);
-
-		of_node_put(clk_np);
 	}
-	of_node_put(np);
 }
 
 /* reduce the duplicated frequencies in frequency table */
@@ -198,9 +157,9 @@  static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
 
 static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-	struct device_node *np, *pnode;
+	struct device_node *np;
 	int i, count, ret;
-	u32 freq, mask;
+	u32 freq;
 	struct clk *clk;
 	struct cpufreq_frequency_table *table;
 	struct cpu_data *data;
@@ -221,17 +180,12 @@  static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_nomem2;
 	}
 
-	pnode = of_parse_phandle(np, "clocks", 0);
-	if (!pnode) {
-		pr_err("%s: could not get clock information\n", __func__);
-		goto err_nomem2;
-	}
+	count = clk_get_num_parents(policy->clk);
 
-	count = of_property_count_strings(pnode, "clock-names");
 	data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
 	if (!data->pclk) {
 		pr_err("%s: no memory\n", __func__);
-		goto err_node;
+		goto err_nomem2;
 	}
 
 	table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
@@ -240,23 +194,11 @@  static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		goto err_pclk;
 	}
 
-	if (fmask)
-		mask = fmask[get_cpu_physical_id(cpu)];
-	else
-		mask = 0x0;
-
 	for (i = 0; i < count; i++) {
-		clk = of_clk_get(pnode, i);
+		clk = clk_get_parent_by_index(policy->clk, i);
 		data->pclk[i] = clk;
 		freq = clk_get_rate(clk);
-		/*
-		 * the clock is valid if its frequency is not masked
-		 * and large than minimum allowed frequency.
-		 */
-		if (freq < min_cpufreq || (mask & (1 << i)))
-			table[i].frequency = CPUFREQ_ENTRY_INVALID;
-		else
-			table[i].frequency = freq / 1000;
+		table[i].frequency = freq / 1000;
 		table[i].driver_data = i;
 	}
 	freq_table_redup(table, count);
@@ -282,18 +224,13 @@  static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	policy->cpuinfo.transition_latency = u64temp + 1;
 
 	of_node_put(np);
-	of_node_put(pnode);
-
 	return 0;
 
 err_nomem1:
 	kfree(table);
 err_pclk:
 	kfree(data->pclk);
-err_node:
-	of_node_put(pnode);
 err_nomem2:
-	policy->driver_data = NULL;
 	kfree(data);
 err_np:
 	of_node_put(np);
@@ -357,12 +294,20 @@  static struct cpufreq_driver qoriq_cpufreq_driver = {
 	.attr		= cpufreq_generic_attr,
 };
 
+static const struct soc_data blacklist = {
+	.flags = SOC_BLACKLIST,
+};
+
 static const struct of_device_id node_matches[] __initconst = {
-	{ .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
-	{ .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
-	{ .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
-	{ .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
-	{ .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
+	/* e6500 cannot use cpufreq due to erratum A-008083 */
+	{ .compatible = "fsl,b4420-clockgen", &blacklist },
+	{ .compatible = "fsl,b4860-clockgen", &blacklist },
+	{ .compatible = "fsl,t2080-clockgen", &blacklist },
+	{ .compatible = "fsl,t4240-clockgen", &blacklist },
+
+	{ .compatible = "fsl,ls1021a-clockgen", },
+	{ .compatible = "fsl,p4080-clockgen", },
+	{ .compatible = "fsl,qoriq-clockgen-1.0", },
 	{ .compatible = "fsl,qoriq-clockgen-2.0", },
 	{}
 };
@@ -380,16 +325,12 @@  static int __init qoriq_cpufreq_init(void)
 
 	match = of_match_node(node_matches, np);
 	data = match->data;
-	if (data) {
-		if (data->flag)
-			fmask = data->freq_mask;
-		min_cpufreq = get_bus_freq();
-	} else {
-		min_cpufreq = get_bus_freq() / 2;
-	}
 
 	of_node_put(np);
 
+	if (data && data->flags & SOC_BLACKLIST)
+		return -ENODEV;
+
 	ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
 	if (!ret)
 		pr_info("Freescale QorIQ CPU frequency scaling driver\n");