[02/14] clk: Create of_clk_shared_by_cpus()

Message ID 5f7164d789e87c62d722b575980c92dfd0504334.1404231535.git.viresh.kumar@linaro.org
State New
Headers show

Commit Message

Viresh Kumar July 1, 2014, 4:32 p.m.
Create a new routine of_clk_shared_by_cpus() that finds if clock lines are
shared between two CPUs. This is verified by comparing "clocks" property from
CPU's DT node.

Returns 1 if clock line is shared between them, 0 if clock isn't shared and
return appropriate errors in case nodes/properties are missing.

Cc: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/clk/clk.c   | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h |  6 ++++++
 2 files changed, 62 insertions(+)

Comments

Stephen Boyd July 1, 2014, 6 p.m. | #1
On 07/01/14 09:32, Viresh Kumar wrote:
> Create a new routine of_clk_shared_by_cpus() that finds if clock lines are
> shared between two CPUs. This is verified by comparing "clocks" property from
> CPU's DT node.
>
> Returns 1 if clock line is shared between them, 0 if clock isn't shared and
> return appropriate errors in case nodes/properties are missing.
>
> Cc: Mike Turquette <mturquette@linaro.org>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  drivers/clk/clk.c   | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h |  6 ++++++

This doesn't make much sense to me. This function doesn't deal with
struct clk pointers or any of the internals of the common clock
framework so why put it in clk.c? It looks more like an internal
function that the cpufreq-generic driver should have.
Viresh Kumar July 2, 2014, 1:57 a.m. | #2
On 1 July 2014 23:30, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 07/01/14 09:32, Viresh Kumar wrote:
>> Create a new routine of_clk_shared_by_cpus() that finds if clock lines are
>> shared between two CPUs. This is verified by comparing "clocks" property from
>> CPU's DT node.
>>
>> Returns 1 if clock line is shared between them, 0 if clock isn't shared and
>> return appropriate errors in case nodes/properties are missing.
>>
>> Cc: Mike Turquette <mturquette@linaro.org>
>> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
>> ---
>>  drivers/clk/clk.c   | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/clk.h |  6 ++++++
>
> This doesn't make much sense to me. This function doesn't deal with
> struct clk pointers or any of the internals of the common clock
> framework so why put it in clk.c? It looks more like an internal
> function that the cpufreq-generic driver should have.

I thought this is what Rob suggested when he said:
"I think a clock api function would be better."

I had it in cpufreq-cpu0 driver earlier and moved it to a separate API
yesterday only.

Sorry if I misunderstood his comment.
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Santosh Shilimkar July 9, 2014, 2:38 p.m. | #3
+ Lorenzo

On Tuesday 01 July 2014 12:32 PM, Viresh Kumar wrote:
> Create a new routine of_clk_shared_by_cpus() that finds if clock lines are
> shared between two CPUs. This is verified by comparing "clocks" property from
> CPU's DT node.
> 
> Returns 1 if clock line is shared between them, 0 if clock isn't shared and
> return appropriate errors in case nodes/properties are missing.
> 
> Cc: Mike Turquette <mturquette@linaro.org>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  drivers/clk/clk.c   | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h |  6 ++++++
>  2 files changed, 62 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 8b73ede..497735c 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -10,6 +10,7 @@
>   */
>  
>  #include <linux/clk-private.h>
> +#include <linux/cpu.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/spinlock.h>
> @@ -2528,6 +2529,61 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
>  }
>  EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
>  
> +/**
> + * of_clk_shared_by_cpus - Finds if clock line is shared between CPUs
> + * @cpu1, cpu2: CPU numbers
> + *
> + * Finds if clock lines are shared by two CPUs. This is verified by comparing
> + * "clocks" property from CPU's DT node.
> + *
> + * Returns 1 if clock line is shared between them, 0 if clock isn't shared.
> + * Return appropriate errors in case some requirements aren't met.
> + */
> +int of_clk_shared_by_cpus(int cpu1, int cpu2)

I might be wrong but this API seems to bit short cited. We should probably
handle it bit better since there are more cases instead of just checking CPU
tuple. More than two CPUs may share the clock so discovering that in one iteration
is better. I also think this is closely related to CPU topology.

- CPUs part of 'a cluster' shares same clock.
- Multiple clusters may share same clock
- Every CPU might be clocked from separate PLL.

What you say ?

Regards,
Santosh




--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Viresh Kumar July 9, 2014, 3:20 p.m. | #4
On 9 July 2014 20:08, Santosh Shilimkar <santosh.shilimkar@ti.com> wrote:
> I might be wrong but this API seems to bit short cited. We should probably
> handle it bit better since there are more cases instead of just checking CPU
> tuple. More than two CPUs may share the clock so discovering that in one iteration
> is better. I also think this is closely related to CPU topology.
>
> - CPUs part of 'a cluster' shares same clock.
> - Multiple clusters may share same clock
> - Every CPU might be clocked from separate PLL.

All these configurations are currently supported by this series.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Grant Likely July 28, 2014, 2:01 p.m. | #5
On Tue,  1 Jul 2014 22:02:31 +0530, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> Create a new routine of_clk_shared_by_cpus() that finds if clock lines are
> shared between two CPUs. This is verified by comparing "clocks" property from
> CPU's DT node.
> 
> Returns 1 if clock line is shared between them, 0 if clock isn't shared and
> return appropriate errors in case nodes/properties are missing.
> 
> Cc: Mike Turquette <mturquette@linaro.org>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  drivers/clk/clk.c   | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h |  6 ++++++
>  2 files changed, 62 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 8b73ede..497735c 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -10,6 +10,7 @@
>   */
>  
>  #include <linux/clk-private.h>
> +#include <linux/cpu.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/spinlock.h>
> @@ -2528,6 +2529,61 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
>  }
>  EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
>  
> +/**
> + * of_clk_shared_by_cpus - Finds if clock line is shared between CPUs
> + * @cpu1, cpu2: CPU numbers
> + *
> + * Finds if clock lines are shared by two CPUs. This is verified by comparing
> + * "clocks" property from CPU's DT node.
> + *
> + * Returns 1 if clock line is shared between them, 0 if clock isn't shared.
> + * Return appropriate errors in case some requirements aren't met.
> + */
> +int of_clk_shared_by_cpus(int cpu1, int cpu2)
> +{
> +	struct device *cpu1_dev, *cpu2_dev;
> +	struct device_node *np1, *np2;
> +	int ret;
> +
> +	cpu1_dev = get_cpu_device(cpu1);
> +	if (!cpu1_dev) {
> +		pr_err("%s: failed to get cpu_dev for cpu%d\n", __func__, cpu1);
> +		return -ENODEV;
> +	}
> +
> +	cpu2_dev = get_cpu_device(cpu2);
> +	if (!cpu2_dev) {
> +		pr_err("%s: failed to get cpu_dev for cpu%d\n", __func__, cpu2);
> +		return -ENODEV;
> +	}
> +
> +	np1 = of_node_get(cpu1_dev->of_node);
> +	if (!np1) {
> +		pr_err("%s: failed to find of_node for cpu%d\n", __func__,
> +		       cpu1);
> +		return -ENODEV;
> +	}
> +
> +	np2 = of_node_get(cpu2_dev->of_node);
> +	if (!np2) {
> +		pr_err("%s: failed to find of_node for cpu%d\n", __func__,
> +		       cpu2);
> +		ret = -ENODEV;
> +		goto put_np1;
> +	}
> +
> +	/* Match "clocks" property */
> +	ret = of_property_match(np1, np2, "clocks");

This looks na誰ve. It is entirely possible for different clock specifiers
to resolve to the same clock line, or for there to be multple clocks in
the clocks property. This looks like a buggy way to do it. The only
reliable way to determine if two clocks resolve to the same thing is to
resolve the references with the clock controller.

g.
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8b73ede..497735c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -10,6 +10,7 @@ 
  */
 
 #include <linux/clk-private.h>
+#include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
@@ -2528,6 +2529,61 @@  const char *of_clk_get_parent_name(struct device_node *np, int index)
 }
 EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
 
+/**
+ * of_clk_shared_by_cpus - Finds if clock line is shared between CPUs
+ * @cpu1, cpu2: CPU numbers
+ *
+ * Finds if clock lines are shared by two CPUs. This is verified by comparing
+ * "clocks" property from CPU's DT node.
+ *
+ * Returns 1 if clock line is shared between them, 0 if clock isn't shared.
+ * Return appropriate errors in case some requirements aren't met.
+ */
+int of_clk_shared_by_cpus(int cpu1, int cpu2)
+{
+	struct device *cpu1_dev, *cpu2_dev;
+	struct device_node *np1, *np2;
+	int ret;
+
+	cpu1_dev = get_cpu_device(cpu1);
+	if (!cpu1_dev) {
+		pr_err("%s: failed to get cpu_dev for cpu%d\n", __func__, cpu1);
+		return -ENODEV;
+	}
+
+	cpu2_dev = get_cpu_device(cpu2);
+	if (!cpu2_dev) {
+		pr_err("%s: failed to get cpu_dev for cpu%d\n", __func__, cpu2);
+		return -ENODEV;
+	}
+
+	np1 = of_node_get(cpu1_dev->of_node);
+	if (!np1) {
+		pr_err("%s: failed to find of_node for cpu%d\n", __func__,
+		       cpu1);
+		return -ENODEV;
+	}
+
+	np2 = of_node_get(cpu2_dev->of_node);
+	if (!np2) {
+		pr_err("%s: failed to find of_node for cpu%d\n", __func__,
+		       cpu2);
+		ret = -ENODEV;
+		goto put_np1;
+	}
+
+	/* Match "clocks" property */
+	ret = of_property_match(np1, np2, "clocks");
+
+	of_node_put(np2);
+
+put_np1:
+	of_node_put(np1);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_clk_shared_by_cpus);
+
 struct clock_provider {
 	of_clk_init_cb_t clk_init_cb;
 	struct device_node *np;
diff --git a/include/linux/clk.h b/include/linux/clk.h
index fb5e097..58e281a 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -399,6 +399,7 @@  struct of_phandle_args;
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
 struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
+int of_clk_shared_by_cpus(int cpu1, int cpu2);
 #else
 static inline struct clk *of_clk_get(struct device_node *np, int index)
 {
@@ -409,6 +410,11 @@  static inline struct clk *of_clk_get_by_name(struct device_node *np,
 {
 	return ERR_PTR(-ENOENT);
 }
+
+static inline int of_clk_shared_by_cpus(int cpu1, int cpu2)
+{
+	return -ENOSYS;
+}
 #endif
 
 #endif