linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/2] clk: Add functions to get optional clocks
@ 2018-07-31 12:10 Phil Edworthy
  2018-07-31 12:10 ` [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function Phil Edworthy
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Phil Edworthy @ 2018-07-31 12:10 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Russell King
  Cc: Geert Uytterhoeven, Simon Horman, Andy Shevchenko, linux-clk,
	linux-kernel, linux-arm-kernel, Phil Edworthy

Quite a few drivers get an optional clock, e.g. a bus clock required to 
access peripheral's registers that is always enabled on some devices.

Phil Edworthy (2):
  clk: Add of_clk_get_by_name_optional() function
  clk: Add functions to get optional clocks

 drivers/clk/clk-devres.c | 18 +++++++++++++--
 drivers/clk/clkdev.c     | 58 +++++++++++++++++++++++++++++++++++++++++++-----
 include/linux/clk.h      | 35 +++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 7 deletions(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function
  2018-07-31 12:10 [PATCH v4 0/2] clk: Add functions to get optional clocks Phil Edworthy
@ 2018-07-31 12:10 ` Phil Edworthy
  2018-08-29 17:10   ` Andy Shevchenko
  2018-07-31 12:11 ` [PATCH v4 2/2] clk: Add functions to get optional clocks Phil Edworthy
  2018-08-29 17:11 ` [PATCH v4 0/2] " Andy Shevchenko
  2 siblings, 1 reply; 7+ messages in thread
From: Phil Edworthy @ 2018-07-31 12:10 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Russell King
  Cc: Geert Uytterhoeven, Simon Horman, Andy Shevchenko, linux-clk,
	linux-kernel, linux-arm-kernel, Phil Edworthy

Quite a few drivers get an optional clock, e.g. a clock required
to access peripheral's registers that is always enabled on some
devices.

This function behaves the same as of_clk_get_by_name() except that
it will return NULL instead of -ENOENT.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
v4:
 - For optional named clocks of_property_match_string() will return
   -EINVAL if the "clock-names" property is missing, or -ENODATA if
   the specified clock name in the "clock-names" property is missing.
   If we then call __of_clk_get() with these errors as the index, we
   get clk = -EINVAL. This is then filtered later on so users don't
   see it. However, if the clock is not named, __of_clk_get() will
   return -ENOENT is the clock provide is not there.
   So for optional named clocks, use index to determine if the clock
   provider is there or not, and for unnamed clocks, simply check if
   __of_clk_get() returns -ENOENT.

v3:
 - Fix check for clock not present. __of_clk_get() returns -EINVAL
   if it's not there. Cover case of when there is no clock name.
 - of_clk_get_by_name_optional() should return NULL if !np.
 - Add dummy version of of_clk_get_by_name_optional() for the
   !OF || !COMMON_CLK case.
---
 drivers/clk/clkdev.c | 43 +++++++++++++++++++++++++++++++++++++++----
 include/linux/clk.h  |  6 ++++++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 9ab3db8..f8f6ba9 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -54,7 +54,8 @@ EXPORT_SYMBOL(of_clk_get);
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
 					const char *dev_id,
-					const char *name)
+					const char *name,
+					bool optional)
 {
 	struct clk *clk = ERR_PTR(-ENOENT);
 
@@ -70,6 +71,12 @@ static struct clk *__of_clk_get_by_name(struct device_node *np,
 		if (name)
 			index = of_property_match_string(np, "clock-names", name);
 		clk = __of_clk_get(np, index, dev_id, name);
+		if (optional && (index == -EINVAL || index == -ENODATA ||
+		    PTR_ERR(clk) == -ENOENT)) {
+			clk = NULL;
+			pr_info("optional clock is not present %pOF:%s\n", np,
+				name ? name : "");
+		}
 		if (!IS_ERR(clk)) {
 			break;
 		} else if (name && index >= 0) {
@@ -89,6 +96,12 @@ static struct clk *__of_clk_get_by_name(struct device_node *np,
 			break;
 	}
 
+	if (optional && PTR_ERR(clk) == -ENOENT) {
+		clk = NULL;
+		pr_info("optional clock is not present %pOF:%s\n", np,
+			name ? name : "");
+	}
+
 	return clk;
 }
 
@@ -106,15 +119,37 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
 	if (!np)
 		return ERR_PTR(-ENOENT);
 
-	return __of_clk_get_by_name(np, np->full_name, name);
+	return __of_clk_get_by_name(np, np->full_name, name, false);
 }
 EXPORT_SYMBOL(of_clk_get_by_name);
 
+/**
+ * of_clk_get_by_name_optional() - Parse and lookup an optional clock referenced
+ * by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties, and uses them to
+ * look up the struct clk from the registered list of clock providers.
+ * It behaves the same as of_clk_get_by_name(), except when np is NULL or no
+ * clock provider is found, when it then returns NULL.
+ */
+struct clk *of_clk_get_by_name_optional(struct device_node *np,
+					const char *name)
+{
+	if (!np)
+		return NULL;
+
+	return __of_clk_get_by_name(np, np->full_name, name, true);
+}
+EXPORT_SYMBOL(of_clk_get_by_name_optional);
+
 #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
 
 static struct clk *__of_clk_get_by_name(struct device_node *np,
 					const char *dev_id,
-					const char *name)
+					const char *name,
+					bool optional)
 {
 	return ERR_PTR(-ENOENT);
 }
@@ -197,7 +232,7 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 	struct clk *clk;
 
 	if (dev && dev->of_node) {
-		clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
+		clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
 		if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
 			return clk;
 	}
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 4f750c4..de0e5e0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -777,6 +777,7 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 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_by_name_optional(struct device_node *np, const char *name);
 struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
 #else
 static inline struct clk *of_clk_get(struct device_node *np, int index)
@@ -788,6 +789,11 @@ static inline struct clk *of_clk_get_by_name(struct device_node *np,
 {
 	return ERR_PTR(-ENOENT);
 }
+static inline struct clk *of_clk_get_by_name_optional(struct device_node *np,
+						      const char *name)
+{
+	return NULL;
+}
 static inline struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
 {
 	return ERR_PTR(-ENOENT);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v4 2/2] clk: Add functions to get optional clocks
  2018-07-31 12:10 [PATCH v4 0/2] clk: Add functions to get optional clocks Phil Edworthy
  2018-07-31 12:10 ` [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function Phil Edworthy
@ 2018-07-31 12:11 ` Phil Edworthy
  2018-08-29 17:11 ` [PATCH v4 0/2] " Andy Shevchenko
  2 siblings, 0 replies; 7+ messages in thread
From: Phil Edworthy @ 2018-07-31 12:11 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Russell King
  Cc: Geert Uytterhoeven, Simon Horman, Andy Shevchenko, linux-clk,
	linux-kernel, linux-arm-kernel, Phil Edworthy

Behaves the same as (devm_)clk_get except where there is no clock
producer. In this case, instead of returning -ENOENT, the function
returns NULL. This makes error checking simpler and allows
clk_prepare_enable, etc to be called on the returned reference
without additional checks.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
v4:
 - No changes.
v3:
 - No changes.
---
 drivers/clk/clk-devres.c | 18 ++++++++++++++++--
 drivers/clk/clkdev.c     | 17 +++++++++++++++--
 include/linux/clk.h      | 29 +++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index d854e26..a2bb01a 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -14,7 +14,7 @@ static void devm_clk_release(struct device *dev, void *res)
 	clk_put(*(struct clk **)res);
 }
 
-struct clk *devm_clk_get(struct device *dev, const char *id)
+static struct clk *__devm_clk_get(struct device *dev, const char *id, bool optional)
 {
 	struct clk **ptr, *clk;
 
@@ -22,7 +22,10 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 	if (!ptr)
 		return ERR_PTR(-ENOMEM);
 
-	clk = clk_get(dev, id);
+	if (!optional)
+		clk = clk_get(dev, id);
+	else
+		clk = clk_get_optional(dev, id);
 	if (!IS_ERR(clk)) {
 		*ptr = clk;
 		devres_add(dev, ptr);
@@ -32,8 +35,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 
 	return clk;
 }
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+	return __devm_clk_get(dev, id, false);
+}
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+	return __devm_clk_get(dev, id, true);
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
 	struct clk_bulk_data *clks;
 	int num_clks;
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index f8f6ba9..0ad6c31 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -226,21 +226,34 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 }
 EXPORT_SYMBOL(clk_get_sys);
 
-struct clk *clk_get(struct device *dev, const char *con_id)
+static struct clk *internal_clk_get(struct device *dev, const char *con_id,
+				    bool optional)
 {
 	const char *dev_id = dev ? dev_name(dev) : NULL;
 	struct clk *clk;
 
 	if (dev && dev->of_node) {
-		clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id, false);
+		clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id,
+					   optional);
 		if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
 			return clk;
 	}
 
 	return clk_get_sys(dev_id, con_id);
 }
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+	return internal_clk_get(dev, con_id, false);
+}
 EXPORT_SYMBOL(clk_get);
 
+struct clk *clk_get_optional(struct device *dev, const char *con_id)
+{
+	return internal_clk_get(dev, con_id, true);
+}
+EXPORT_SYMBOL(clk_get_optional);
+
 void clk_put(struct clk *clk)
 {
 	__clk_put(clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index de0e5e0..58ec7bc 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -291,6 +291,16 @@ static inline void clk_bulk_unprepare(int num_clks, struct clk_bulk_data *clks)
 struct clk *clk_get(struct device *dev, const char *id);
 
 /**
+ * clk_get_optional - lookup and obtain a reference to optional clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as clk_get except where there is no clock producer. In this
+ * case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *clk_get_optional(struct device *dev, const char *id);
+
+/**
  * clk_bulk_get - lookup and obtain a number of references to clock producer.
  * @dev: device for clock "consumer"
  * @num_clks: the number of clk_bulk_data
@@ -349,6 +359,14 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
 /**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *			   clock producer.
+ * Behaves the same as devm_clk_get except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
+/**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *			     clock producer from child node.
  * @dev: device for clock "consumer"
@@ -636,6 +654,11 @@ static inline struct clk *clk_get(struct device *dev, const char *id)
 	return NULL;
 }
 
+static inline struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+	return NULL;
+}
+
 static inline int __must_check clk_bulk_get(struct device *dev, int num_clks,
 					    struct clk_bulk_data *clks)
 {
@@ -647,6 +670,12 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
 	return NULL;
 }
 
+static inline struct clk *devm_clk_get_optional(struct device *dev,
+						const char *id)
+{
+	return NULL;
+}
+
 static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
 						 struct clk_bulk_data *clks)
 {
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function
  2018-07-31 12:10 ` [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function Phil Edworthy
@ 2018-08-29 17:10   ` Andy Shevchenko
  2018-08-30  8:30     ` Phil Edworthy
  0 siblings, 1 reply; 7+ messages in thread
From: Andy Shevchenko @ 2018-08-29 17:10 UTC (permalink / raw)
  To: Phil Edworthy
  Cc: Michael Turquette, Stephen Boyd, Russell King,
	Geert Uytterhoeven, Simon Horman, linux-clk, linux-kernel,
	linux-arm-kernel

On Tue, Jul 31, 2018 at 01:10:59PM +0100, Phil Edworthy wrote:
> Quite a few drivers get an optional clock, e.g. a clock required
> to access peripheral's registers that is always enabled on some
> devices.
> 
> This function behaves the same as of_clk_get_by_name() except that
> it will return NULL instead of -ENOENT.

> +		if (optional && (index == -EINVAL || index == -ENODATA ||
> +		    PTR_ERR(clk) == -ENOENT)) {

A nit: I would rather rearrange this to be

if (optional &&
    (... || ... || ...)) {

(disregard 80 characters limit for second line)

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 0/2] clk: Add functions to get optional clocks
  2018-07-31 12:10 [PATCH v4 0/2] clk: Add functions to get optional clocks Phil Edworthy
  2018-07-31 12:10 ` [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function Phil Edworthy
  2018-07-31 12:11 ` [PATCH v4 2/2] clk: Add functions to get optional clocks Phil Edworthy
@ 2018-08-29 17:11 ` Andy Shevchenko
  2 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2018-08-29 17:11 UTC (permalink / raw)
  To: Phil Edworthy
  Cc: Michael Turquette, Stephen Boyd, Russell King,
	Geert Uytterhoeven, Simon Horman, linux-clk, linux-kernel,
	linux-arm-kernel

On Tue, Jul 31, 2018 at 01:10:58PM +0100, Phil Edworthy wrote:
> Quite a few drivers get an optional clock, e.g. a bus clock required to 
> access peripheral's registers that is always enabled on some devices.
> 

Didn't see any updates so far.
Anyway, this one LGTM,

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Phil Edworthy (2):
>   clk: Add of_clk_get_by_name_optional() function
>   clk: Add functions to get optional clocks
> 
>  drivers/clk/clk-devres.c | 18 +++++++++++++--
>  drivers/clk/clkdev.c     | 58 +++++++++++++++++++++++++++++++++++++++++++-----
>  include/linux/clk.h      | 35 +++++++++++++++++++++++++++++
>  3 files changed, 104 insertions(+), 7 deletions(-)
> 
> -- 
> 2.7.4
> 

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function
  2018-08-29 17:10   ` Andy Shevchenko
@ 2018-08-30  8:30     ` Phil Edworthy
  2018-08-30 10:39       ` Andy Shevchenko
  0 siblings, 1 reply; 7+ messages in thread
From: Phil Edworthy @ 2018-08-30  8:30 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Michael Turquette, Stephen Boyd, Russell King,
	Geert Uytterhoeven, Simon Horman, linux-clk, linux-kernel,
	linux-arm-kernel

Hi Andy,

On 29 August 2018 18:11 Andy Shevchenko wrote:
> On Tue, Jul 31, 2018 at 01:10:59PM +0100, Phil Edworthy wrote:
> > Quite a few drivers get an optional clock, e.g. a clock required
> > to access peripheral's registers that is always enabled on some
> > devices.
> >
> > This function behaves the same as of_clk_get_by_name() except that
> > it will return NULL instead of -ENOENT.
> 
> > +		if (optional && (index == -EINVAL || index == -ENODATA ||
> > +		    PTR_ERR(clk) == -ENOENT)) {
> 
> A nit: I would rather rearrange this to be
> 
> if (optional &&
>     (... || ... || ...)) {
> 
> (disregard 80 characters limit for second line)

Thanks for the review. I'm not particularly happy with the patch as is, it's
pretty messy. I was in rush trying to get things done before holidays - always
a mistake.
Would you mind if I sent a v5 that I feel is somewhat clearer?

Thanks
Phil

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function
  2018-08-30  8:30     ` Phil Edworthy
@ 2018-08-30 10:39       ` Andy Shevchenko
  0 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2018-08-30 10:39 UTC (permalink / raw)
  To: Phil Edworthy
  Cc: Michael Turquette, Stephen Boyd, Russell King,
	Geert Uytterhoeven, Simon Horman, linux-clk, linux-kernel,
	linux-arm-kernel

On Thu, Aug 30, 2018 at 08:30:59AM +0000, Phil Edworthy wrote:
> On 29 August 2018 18:11 Andy Shevchenko wrote:
> > On Tue, Jul 31, 2018 at 01:10:59PM +0100, Phil Edworthy wrote:

> Thanks for the review. I'm not particularly happy with the patch as is, it's
> pretty messy. I was in rush trying to get things done before holidays - always
> a mistake.
> Would you mind if I sent a v5 that I feel is somewhat clearer?

That's definitely preferable!

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-08-30 10:39 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-31 12:10 [PATCH v4 0/2] clk: Add functions to get optional clocks Phil Edworthy
2018-07-31 12:10 ` [PATCH v4 1/2] clk: Add of_clk_get_by_name_optional() function Phil Edworthy
2018-08-29 17:10   ` Andy Shevchenko
2018-08-30  8:30     ` Phil Edworthy
2018-08-30 10:39       ` Andy Shevchenko
2018-07-31 12:11 ` [PATCH v4 2/2] clk: Add functions to get optional clocks Phil Edworthy
2018-08-29 17:11 ` [PATCH v4 0/2] " Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).