All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers
@ 2017-06-20  9:59 patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 01/10] reset: add reset_request() patrice.chotard at st.com
                   ` (9 more replies)
  0 siblings, 10 replies; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

This series improves generic ehci and ohci drivers by addition of :
	_ error path during probe (clocks, resets and phy release)
	_ .remove callback
	_ add generic PHY framework for both generic ehci and ohci drivers
	_ add RESET and CLOCK framework for generic ohci driver

To implement these features, some new methods are needed in reset, clock and
in dm/core framework:
	_ add reset_request() and reset_assert_all() methods in RESET framework
	_ add clk_count() and clk_disable_all() methods in CLOCK framework
	_ add ofnode_count_phandle_with_args() in dm/core

v7:	_ replace clk_count() and reset_count() methods by
	  ofnode_count_phandle_with_args() in patches 3, 4 and 5	

v6:	_ replace clk_get_by_index() by dev_read_phandle_with_args() in
	  clk_count() in patch 4
	_  add Reviewed-by Simon Glass for patch 2 and 5

v5:	_ rebase on top of dm/master requested by Simon Glass in order to use
	  livetree update
	_ replace fdtdec_parse_phandle_with_args() by dev_read_phandle_with_args() in patch 2

v4:	_ add clk_disable_all() and reset_assert_all() methods into CLOCK and
	  RESET framework as suggested by Simon Glass and Marek Vasut
	_ add reset_count() and clk_count() methods which returns respectively the 
	  number of resets and clocks declared into "resets" and "clocks" DT properties.
	  This allows to allocate the right amount of memory to keep resets and clocks
	  reference
	_ update the memory allocation for deasserted resets and enabled
	  clocks reference list. Replace lists by arrays.
	
v3:     _ keep enabled clocks and deasserted resets reference in list in order to 
	  disable clock or assert resets in error path or in .remove callback
	_ add missing commit message
	_ use struct generic_ehci * instead of struct udevice * as parameter for
	  ehci_release_resets() and ehci_release_clocks()
	_ test return value on generic_phy_get_by_index() and
	  generic_phy_init()
	_ split previous patch 5 in 3 independant patch for CLOCK, RESET and PHY support

v2:     _ add needed reset_request() in RESET framework
	_ add error path in ehci/ohci-generic to disable clocks and to assert
	resets
	_ add .remove callback with clocks, resets and phy release
	_ split the replacement of printf() by error() in an independant patch

Patrice Chotard (10):
  reset: add reset_request()
  reset: add reset_assert_all()
  clk: add clk_disable_all()
  dm: core: add ofnode_count_phandle_with_args()
  usb: host: ehci-generic: replace printf() by error()
  usb: host: ehci-generic: add error path and .remove callback
  usb: host: ehci-generic: add generic PHY support
  usb: host: ohci-generic: add CLOCK support
  usb: host: ohci-generic: add RESET support
  usb: host: ohci-generic: add generic PHY support

 drivers/clk/clk-uclass.c        |  22 ++++++
 drivers/core/of_access.c        |   7 ++
 drivers/core/ofnode.c           |  12 ++++
 drivers/reset/reset-uclass.c    |  31 ++++++++
 drivers/usb/host/ehci-generic.c | 153 ++++++++++++++++++++++++++++++++++------
 drivers/usb/host/ohci-generic.c | 132 +++++++++++++++++++++++++++++++++-
 include/clk.h                   |  10 +++
 include/dm/of_access.h          |  18 +++++
 include/dm/ofnode.h             |  17 +++++
 include/reset.h                 |  26 +++++++
 10 files changed, 403 insertions(+), 25 deletions(-)

-- 
1.9.1

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

* [U-Boot] [PATCH v7 01/10] reset: add reset_request()
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 02/10] reset: add reset_assert_all() patrice.chotard at st.com
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

This is needed in error path to assert previously deasserted
reset by using a saved reset_ctl reference.

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
v7:	_ none
v6:	_ none
v5:	_ none
v4:	_ none
v3:	_ none
v2:	_ none


 drivers/reset/reset-uclass.c | 9 +++++++++
 include/reset.h              | 9 +++++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index de3695f..4fd82b9 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -97,6 +97,15 @@ int reset_get_by_name(struct udevice *dev, const char *name,
 	return reset_get_by_index(dev, index, reset_ctl);
 }
 
+int reset_request(struct reset_ctl *reset_ctl)
+{
+	struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
+
+	debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
+
+	return ops->request(reset_ctl);
+}
+
 int reset_free(struct reset_ctl *reset_ctl)
 {
 	struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
diff --git a/include/reset.h b/include/reset.h
index f45fcf8..4f2e35f 100644
--- a/include/reset.h
+++ b/include/reset.h
@@ -100,6 +100,15 @@ int reset_get_by_name(struct udevice *dev, const char *name,
 		      struct reset_ctl *reset_ctl);
 
 /**
+ * reset_request - Request a reset signal.
+ *
+ * @reset_ctl:	A reset control struct.
+ *
+ * @return 0 if OK, or a negative error code.
+ */
+int reset_request(struct reset_ctl *reset_ctl);
+
+/**
  * reset_free - Free a previously requested reset signal.
  *
  * @reset_ctl:	A reset control struct that was previously successfully
-- 
1.9.1

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

* [U-Boot] [PATCH v7 02/10] reset: add reset_assert_all()
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 01/10] reset: add reset_request() patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 03/10] clk: add clk_disable_all() patrice.chotard at st.com
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

Add reset_assert_all() method which Request/Assert/Free an
array of resets signal that has been previously successfully
requested by reset_get_by_*()

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
v7:	_ none
v6:	_ none
v5:	_ none
v4:	_ add reset_assert_all() method as suggested by Marek Vasut
	  and Simon Glass

 drivers/reset/reset-uclass.c | 22 ++++++++++++++++++++++
 include/reset.h              | 17 +++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index 4fd82b9..c39ce14 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -133,6 +133,28 @@ int reset_deassert(struct reset_ctl *reset_ctl)
 	return ops->rst_deassert(reset_ctl);
 }
 
+int reset_assert_all(struct reset_ctl *reset_ctl, int count)
+{
+	int i, ret;
+
+	for (i = 0; i < count; i++) {
+		debug("%s(reset_ctl[%d]=%p)\n", __func__, i, &reset_ctl[i]);
+
+		ret = reset_request(&reset_ctl[i]);
+		if (ret)
+			return ret;
+
+		ret = reset_assert(&reset_ctl[i]);
+		if (ret)
+			return ret;
+
+		ret = reset_free(&reset_ctl[i]);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
 UCLASS_DRIVER(reset) = {
 	.id		= UCLASS_RESET,
 	.name		= "reset",
diff --git a/include/reset.h b/include/reset.h
index 4f2e35f..2678257 100644
--- a/include/reset.h
+++ b/include/reset.h
@@ -144,6 +144,17 @@ int reset_assert(struct reset_ctl *reset_ctl);
  */
 int reset_deassert(struct reset_ctl *reset_ctl);
 
+/**
+ * reset_assert_all - Request/Assert/Free resets.
+ *
+ * This function will request, assert and free array of clocks,
+ *
+ * @reset_ctl:	A reset struct array that was previously successfully
+ *		requested by reset_get_by_*().
+ * @count	Number of reset contained in the array
+ * @return 0 if OK, or a negative error code.
+ */
+int reset_assert_all(struct reset_ctl *reset_ctl, int count);
 #else
 static inline int reset_get_by_index(struct udevice *dev, int index,
 				     struct reset_ctl *reset_ctl)
@@ -171,6 +182,12 @@ static inline int reset_deassert(struct reset_ctl *reset_ctl)
 {
 	return 0;
 }
+
+static inline int reset_assert_all(struct reset_ctl *reset_ctl, int count)
+{
+	return 0;
+}
+
 #endif
 
 #endif
-- 
1.9.1

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

* [U-Boot] [PATCH v7 03/10] clk: add clk_disable_all()
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 01/10] reset: add reset_request() patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 02/10] reset: add reset_assert_all() patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20 12:11   ` Lothar Waßmann
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 04/10] dm: core: add ofnode_count_phandle_with_args() patrice.chotard at st.com
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

Add clk_disable_all() method which Request/Disable/Free an
array of clocks that has been previously requested by
clk_request/get_by_*()

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

v7:	_ none
v6:	_ none
v5:	_ none
v4:	_ none
v3:	_ add commit message
v2:	_ create this independant path for printf() replacement

 drivers/clk/clk-uclass.c | 22 ++++++++++++++++++++++
 include/clk.h            | 10 ++++++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 83b6328..e732514 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -187,6 +187,28 @@ int clk_disable(struct clk *clk)
 	return ops->disable(clk);
 }
 
+int clk_disable_all(struct clk *clk, int count)
+{
+	int i, ret;
+
+	debug("%s(clk=%p count=%d)\n", __func__, clk, count);
+
+	for (i = 0; i < count; i++) {
+		ret = clk_request(clk->dev, &clk[i]);
+		if (ret && ret != -ENOSYS)
+			return ret;
+
+		ret = clk_disable(&clk[i]);
+		if (ret && ret != -ENOSYS)
+			return ret;
+
+		ret = clk_free(&clk[i]);
+		if (ret && ret != -ENOSYS)
+			return ret;
+	}
+	return 0;
+}
+
 UCLASS_DRIVER(clk) = {
 	.id		= UCLASS_CLK,
 	.name		= "clk",
diff --git a/include/clk.h b/include/clk.h
index 5a5c2ff..e04c274 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -174,6 +174,16 @@ int clk_enable(struct clk *clk);
  */
 int clk_disable(struct clk *clk);
 
+/**
+ * clk_disable_all() - Request/Disable (turn off)/Free clocks.
+ *
+ * @clk:	A clock struct array that was previously successfully
+ *		requested by clk_request/get_by_*().
+ * @count	Number of clock contained in the array
+ * @return zero on success, or -ve error code.
+ */
+int clk_disable_all(struct clk *clk, int count);
+
 int soc_clk_dump(void);
 
 #endif
-- 
1.9.1

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

* [U-Boot] [PATCH v7 04/10] dm: core: add ofnode_count_phandle_with_args()
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
                   ` (2 preceding siblings ...)
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 03/10] clk: add clk_disable_all() patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20 18:26   ` Simon Glass
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 05/10] usb: host: ehci-generic: replace printf() by error() patrice.chotard at st.com
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

This function is usefull to get phandle number contained
in a property list.
For example,  this allows to allocate the right amount
of memory to keep clock's reference contained into the
"clocks" property.

To implement it, either of_count_phandle_with_args() or
fdtdec_parse_phandle_with_args() are used respectively
for live tree and flat tree.
By passing index = -1, these 2 functions returns the
number of phandle contained into the property list.

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
---

v7:	_ add ofnode_count_phandle_with_args() which returns
	  the phandle number contained into a property list.
	

 drivers/core/of_access.c |  7 +++++++
 drivers/core/ofnode.c    | 12 ++++++++++++
 include/dm/of_access.h   | 18 ++++++++++++++++++
 include/dm/ofnode.h      | 17 +++++++++++++++++
 4 files changed, 54 insertions(+)

diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index 93a6560..76d5996 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -641,6 +641,13 @@ int of_parse_phandle_with_args(const struct device_node *np,
 					    index, out_args);
 }
 
+int of_count_phandle_with_args(const struct device_node *np,
+			       const char *list_name, const char *cells_name)
+{
+	return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
+					    -1, NULL);
+}
+
 static void of_alias_add(struct alias_prop *ap, struct device_node *np,
 			 int id, const char *stem, int stem_len)
 {
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index ac312d6..02bc5d2 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -307,6 +307,18 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
 	return 0;
 }
 
+int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
+				   const char *cells_name)
+{
+	if (ofnode_is_np(node))
+		return of_count_phandle_with_args(ofnode_to_np(node),
+				list_name, cells_name);
+	else
+		return fdtdec_parse_phandle_with_args(gd->fdt_blob,
+				ofnode_to_offset(node), list_name, cells_name,
+				0, -1, NULL);
+}
+
 ofnode ofnode_path(const char *path)
 {
 	if (of_live_active())
diff --git a/include/dm/of_access.h b/include/dm/of_access.h
index 142f0f4..5be29b1 100644
--- a/include/dm/of_access.h
+++ b/include/dm/of_access.h
@@ -315,6 +315,24 @@ int of_parse_phandle_with_args(const struct device_node *np,
 			       int index, struct of_phandle_args *out_args);
 
 /**
+ * of_count_phandle_with_args() - Count the number of phandle in a list
+ *
+ * @np:		pointer to a device tree node containing a list
+ * @list_name:	property name that contains a list
+ * @cells_name:	property name that specifies phandles' arguments count
+ * @return number of phandle found, -ENOENT if
+ *	@list_name does not exist, -EINVAL if a phandle was not found,
+ *	@cells_name could not be found, the arguments were truncated or there
+ *	were too many arguments.
+ *
+ * Returns number of phandle found on success, on error returns appropriate
+ * errno value.
+ *
+ */
+int of_count_phandle_with_args(const struct device_node *np,
+			       const char *list_name, const char *cells_name);
+
+/**
  * of_alias_scan() - Scan all properties of the 'aliases' node
  *
  * The function scans all the properties of the 'aliases' node and populates
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 149622a..3f2cfbb 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -423,6 +423,23 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
 				   struct ofnode_phandle_args *out_args);
 
 /**
+ * ofnode_count_phandle_with_args() - Count number of phandle in a list
+ *
+ * This function is useful to count phandles into a list.
+ * Returns number of phandle on success, on error returns appropriate
+ * errno value.
+ *
+ * @node:	device tree node containing a list
+ * @list_name:	property name that contains a list
+ * @cells_name:	property name that specifies phandles' arguments count
+ * @return number of phandle on success, -ENOENT if @list_name does not
+ *      exist, -EINVAL if a phandle was not found, @cells_name could not
+ *      be found.
+ */
+int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
+				   const char *cells_name);
+
+/**
  * ofnode_path() - find a node by full path
  *
  * @path: Full path to node, e.g. "/bus/spi at 1"
-- 
1.9.1

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

* [U-Boot] [PATCH v7 05/10] usb: host: ehci-generic: replace printf() by error()
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
                   ` (3 preceding siblings ...)
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 04/10] dm: core: add ofnode_count_phandle_with_args() patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback patrice.chotard at st.com
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

this allows to get file, line and function location
of the current error message.

Signed-off-by: patrice chotard <patrice.chotard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
v7:	_ none
v6:	_ none
v5:	_ none
v4:	_ none
v3:	_ add commit message
v2:	_ create this independant path for printf() replacement

 drivers/usb/host/ehci-generic.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index fb78462..2116ae1 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -34,7 +34,7 @@ static int ehci_usb_probe(struct udevice *dev)
 		if (ret < 0)
 			break;
 		if (clk_enable(&clk))
-			printf("failed to enable clock %d\n", i);
+			error("failed to enable clock %d\n", i);
 		clk_free(&clk);
 	}
 
@@ -46,7 +46,7 @@ static int ehci_usb_probe(struct udevice *dev)
 		if (ret < 0)
 			break;
 		if (reset_deassert(&reset))
-			printf("failed to deassert reset %d\n", i);
+			error("failed to deassert reset %d\n", i);
 		reset_free(&reset);
 	}
 
-- 
1.9.1

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

* [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
                   ` (4 preceding siblings ...)
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 05/10] usb: host: ehci-generic: replace printf() by error() patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20 10:09   ` Marek Vasut
  2017-06-20 11:32   ` Lothar Waßmann
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 07/10] usb: host: ehci-generic: add generic PHY support patrice.chotard at st.com
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

Use an array to save enabled clocks reference and deasserted resets
in order to respectively disabled and asserted them in case of error
during probe() or during driver removal.

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
---

v7:	_ replace clk_count() and reset_count() by ofnode_count_phandle_with_args()

v6:	_ none

v5: 	_ none

v4:	_ update the memory allocation for deasserted resets and enabled
	  clocks reference list. Replace lists by arrays.
	_ usage of new RESET and CLOCK methods clk_count(), reset_count(),
	  reset_assert_all() and clk_disable_all().

v3:	_ keep enabled clocks and deasserted resets reference in list in order to
	  disable clock or assert resets in error path or in .remove callback
	_ use struct generic_ehci * instead of struct udevice * as parameter for
	  ehci_release_resets() and ehci_release_clocks()

 drivers/usb/host/ehci-generic.c | 125 ++++++++++++++++++++++++++++++++--------
 1 file changed, 101 insertions(+), 24 deletions(-)

diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 2116ae1..388b242 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -11,6 +11,8 @@
 #include <dm.h>
 #include "ehci.h"
 
+#include <dm/ofnode.h>
+
 /*
  * Even though here we don't explicitly use "struct ehci_ctrl"
  * ehci_register() expects it to be the first thing that resides in
@@ -18,43 +20,119 @@
  */
 struct generic_ehci {
 	struct ehci_ctrl ctrl;
+	struct clk *clocks;
+	struct reset_ctl *resets;
+	int clock_count;
+	int reset_count;
 };
 
 static int ehci_usb_probe(struct udevice *dev)
 {
+	struct generic_ehci *priv = dev_get_priv(dev);
 	struct ehci_hccr *hccr;
 	struct ehci_hcor *hcor;
-	int i;
-
-	for (i = 0; ; i++) {
-		struct clk clk;
-		int ret;
-
-		ret = clk_get_by_index(dev, i, &clk);
-		if (ret < 0)
-			break;
-		if (clk_enable(&clk))
-			error("failed to enable clock %d\n", i);
-		clk_free(&clk);
-	}
+	int i, err, ret, clock_nb, reset_nb;
+
+	err = 0;
+	priv->clock_count = 0;
+	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
+						  "#clock-cells");
+	if (clock_nb > 0) {
+		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
+					    GFP_KERNEL);
+		if (!priv->clocks) {
+			error("Can't allocate resource\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < clock_nb; i++) {
+			err = clk_get_by_index(dev, i, &priv->clocks[i]);
+
+			if (err < 0)
+				break;
 
-	for (i = 0; ; i++) {
-		struct reset_ctl reset;
-		int ret;
+			priv->clock_count++;
 
-		ret = reset_get_by_index(dev, i, &reset);
-		if (ret < 0)
-			break;
-		if (reset_deassert(&reset))
-			error("failed to deassert reset %d\n", i);
-		reset_free(&reset);
+			if (clk_enable(&priv->clocks[i])) {
+				error("failed to enable clock %d\n", i);
+				clk_free(&priv->clocks[i]);
+				goto clk_err;
+			}
+			clk_free(&priv->clocks[i]);
+		}
+	} else {
+		if (clock_nb != -ENOENT) {
+			error("failed to get clock phandle(%d)\n", clock_nb);
+			return clock_nb;
+		}
 	}
 
+	priv->reset_count = 0;
+	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
+						  "#reset-cells");
+	if (reset_nb > 0) {
+		priv->resets = devm_kmalloc(dev,
+					    sizeof(struct reset_ctl) * reset_nb,
+					    GFP_KERNEL);
+		if (!priv->resets) {
+			error("Can't allocate resource\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < reset_nb; i++) {
+			err = reset_get_by_index(dev, i, &priv->resets[i]);
+			if (err < 0)
+				break;
+
+			priv->reset_count++;
+
+			if (reset_deassert(&priv->resets[i])) {
+				error("failed to deassert reset %d\n", i);
+				reset_free(&priv->resets[i]);
+				goto reset_err;
+			}
+			reset_free(&priv->resets[i]);
+		}
+	} else {
+		if (reset_nb != -ENOENT) {
+			error("failed to get reset phandle(%d)\n", reset_nb);
+			goto clk_err;
+		}
+	}
 	hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
 	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
 				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
-	return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+	err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+	if (!err)
+		return err;
+
+reset_err:
+	ret = reset_assert_all(priv->resets, priv->reset_count);
+	if (ret)
+		return ret;
+clk_err:
+	ret = clk_disable_all(priv->clocks, priv->clock_count);
+	if (ret)
+		return ret;
+
+	return err;
+}
+
+static int ehci_usb_remove(struct udevice *dev)
+{
+	struct generic_ehci *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ehci_deregister(dev);
+	if (ret)
+		return ret;
+
+	ret =  reset_assert_all(priv->resets, priv->reset_count);
+	if (ret)
+		return ret;
+
+	return clk_disable_all(priv->clocks, priv->clock_count);
 }
 
 static const struct udevice_id ehci_usb_ids[] = {
@@ -67,7 +145,7 @@ U_BOOT_DRIVER(ehci_generic) = {
 	.id	= UCLASS_USB,
 	.of_match = ehci_usb_ids,
 	.probe = ehci_usb_probe,
-	.remove = ehci_deregister,
+	.remove = ehci_usb_remove,
 	.ops	= &ehci_usb_ops,
 	.priv_auto_alloc_size = sizeof(struct generic_ehci),
 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
-- 
1.9.1

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

* [U-Boot] [PATCH v7 07/10] usb: host: ehci-generic: add generic PHY support
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
                   ` (5 preceding siblings ...)
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support patrice.chotard at st.com
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

Extend ehci-generic driver with generic PHY framework

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

v7:	_ none

v6:	_ none

v5:	_ none

v4:	_ update the memory allocation for deasserted resets and enabled
	  clocks reference list. Replace lists by arrays.
	_ usage of new RESET and CLOCK methods clk_count(), reset_count(),
	  reset_assert_all() and clk_disable_all().

v3:	_ keep enabled clocks and deasserted resets reference in list in order to
	  disable clock or assert resets in error path or in .remove callback
	_ use struct generic_ehci * instead of struct udevice * as parameter for
	  ehci_release_resets() and ehci_release_clocks()

 drivers/usb/host/ehci-generic.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 388b242..00a7772 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <clk.h>
+#include <generic-phy.h>
 #include <reset.h>
 #include <asm/io.h>
 #include <dm.h>
@@ -22,6 +23,7 @@ struct generic_ehci {
 	struct ehci_ctrl ctrl;
 	struct clk *clocks;
 	struct reset_ctl *resets;
+	struct phy phy;
 	int clock_count;
 	int reset_count;
 };
@@ -99,6 +101,21 @@ static int ehci_usb_probe(struct udevice *dev)
 			goto clk_err;
 		}
 	}
+
+	err = generic_phy_get_by_index(dev, 0, &priv->phy);
+	if (err) {
+		if (err != -ENOENT) {
+			error("failed to get usb phy\n");
+			goto reset_err;
+		}
+	} else {
+		err = generic_phy_init(&priv->phy);
+		if (err) {
+			error("failed to init usb phy\n");
+			goto reset_err;
+		}
+	}
+
 	hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
 	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
 				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
@@ -107,6 +124,12 @@ static int ehci_usb_probe(struct udevice *dev)
 	if (!err)
 		return err;
 
+	if (generic_phy_valid(&priv->phy)) {
+		ret = generic_phy_exit(&priv->phy);
+		if (ret)
+			return ret;
+	}
+
 reset_err:
 	ret = reset_assert_all(priv->resets, priv->reset_count);
 	if (ret)
@@ -128,6 +151,12 @@ static int ehci_usb_remove(struct udevice *dev)
 	if (ret)
 		return ret;
 
+	if (generic_phy_valid(&priv->phy)) {
+		ret = generic_phy_exit(&priv->phy);
+		if (ret)
+			return ret;
+	}
+
 	ret =  reset_assert_all(priv->resets, priv->reset_count);
 	if (ret)
 		return ret;
-- 
1.9.1

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

* [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
                   ` (6 preceding siblings ...)
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 07/10] usb: host: ehci-generic: add generic PHY support patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20 12:06   ` Lothar Waßmann
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 09/10] usb: host: ohci-generic: add RESET support patrice.chotard at st.com
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 10/10] usb: host: ohci-generic: add generic PHY support patrice.chotard at st.com
  9 siblings, 1 reply; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

use array to save enabled clocks reference in order to
disabled them in case of error during probe() or during
driver removal.

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
---
v7:	_ replace clk_count() by ofnode_count_phandle_with_args()

v6:	_ none

v5:	_ none

v4:	_ use generic_phy_valid() before generic_phy_exit() call

v3:	_ extract in this patch the CLOCK support add-on from previous patch 5
	_ keep enabled clocks reference in list in order to
	  disable clocks in error path or in .remove callback

v2:	_ add error path management
	_ add .remove callback

 drivers/usb/host/ohci-generic.c | 59 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index f85738f..f76a1c2 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -5,27 +5,83 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include "ohci.h"
 
+#include <dm/ofnode.h>
+
 #if !defined(CONFIG_USB_OHCI_NEW)
 # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
 #endif
 
 struct generic_ohci {
 	ohci_t ohci;
+	struct clk *clocks;
+	int clock_count;
 };
 
 static int ohci_usb_probe(struct udevice *dev)
 {
 	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
+	struct generic_ohci *priv = dev_get_priv(dev);
+	int i, err, ret, clock_nb;
+
+	err = 0;
+	priv->clock_count = 0;
+	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
+						  "#clock-cells");
+	if (clock_nb > 0) {
+		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
+					    GFP_KERNEL);
+		if (!priv->clocks) {
+			error("Can't allocate resource\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < clock_nb; i++) {
+			err = clk_get_by_index(dev, i, &priv->clocks[i]);
+			if (err < 0)
+				break;
+
+			priv->clock_count++;
+
+			if (clk_enable(&priv->clocks[i])) {
+				error("failed to enable clock %d\n", i);
+				clk_free(&priv->clocks[i]);
+				goto clk_err;
+			}
+			clk_free(&priv->clocks[i]);
+		}
+	} else {
+		if (clock_nb != -ENOENT) {
+			error("failed to get clock phandle(%d)\n", clock_nb);
+			return clock_nb;
+		}
+	}
 
-	return ohci_register(dev, regs);
+	err = ohci_register(dev, regs);
+	if (!err)
+		return err;
+
+clk_err:
+	ret = clk_disable_all(priv->clocks, priv->clock_count);
+	if (ret)
+		return ret;
+
+	return err;
 }
 
 static int ohci_usb_remove(struct udevice *dev)
 {
-	return ohci_deregister(dev);
+	struct generic_ohci *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ohci_deregister(dev);
+	if (ret)
+		return ret;
+
+	return clk_disable_all(priv->clocks, priv->clock_count);
 }
 
 static const struct udevice_id ohci_usb_ids[] = {
-- 
1.9.1

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

* [U-Boot] [PATCH v7 09/10] usb: host: ohci-generic: add RESET support
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
                   ` (7 preceding siblings ...)
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  2017-06-20 18:26   ` Simon Glass
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 10/10] usb: host: ohci-generic: add generic PHY support patrice.chotard at st.com
  9 siblings, 1 reply; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

use array to save deasserted resets reference in order to
assert them in case of error during probe() or during driver
removal.

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
---
v7:	_ replace reset_count() by ofnode_count_phandle_with_args()

v6:	_ none

v5:	_ none

v4:	_ update the memory allocation for deasserted resets. Replace lists by arrays.
	_ usage of new RESET methods reset_assert_all() and clk_disable_all().

v3:	_ extract in this patch the RESET support add-on from previous patch 5
	_ keep deasserted resets reference in list in order to
	  assert resets in error path or in .remove callback

v2:	_ add error path management
	_ add .remove callback

 drivers/usb/host/ohci-generic.c | 46 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index f76a1c2..5bd52ff 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
+#include <reset.h>
 #include "ohci.h"
 
 #include <dm/ofnode.h>
@@ -18,14 +19,16 @@
 struct generic_ohci {
 	ohci_t ohci;
 	struct clk *clocks;
+	struct reset_ctl *resets;
 	int clock_count;
+	int reset_count;
 };
 
 static int ohci_usb_probe(struct udevice *dev)
 {
 	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
 	struct generic_ohci *priv = dev_get_priv(dev);
-	int i, err, ret, clock_nb;
+	int i, err, ret, clock_nb, reset_nb;
 
 	err = 0;
 	priv->clock_count = 0;
@@ -60,10 +63,47 @@ static int ohci_usb_probe(struct udevice *dev)
 		}
 	}
 
+	priv->reset_count = 0;
+	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
+						  "#reset-cells");
+	if (reset_nb > 0) {
+		priv->resets = devm_kmalloc(dev,
+					    sizeof(struct reset_ctl) * reset_nb,
+					    GFP_KERNEL);
+		if (!priv->resets) {
+			error("Can't allocate resource\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < reset_nb; i++) {
+			err = reset_get_by_index(dev, i, &priv->resets[i]);
+			if (err < 0)
+				break;
+
+			priv->reset_count++;
+
+			if (reset_deassert(&priv->resets[i])) {
+				error("failed to deassert reset %d\n", i);
+				reset_free(&priv->resets[i]);
+				goto reset_err;
+			}
+			reset_free(&priv->resets[i]);
+		}
+	} else {
+		if (reset_nb != -ENOENT) {
+			error("failed to get reset phandle(%d)\n", reset_nb);
+			goto clk_err;
+		}
+	}
+
 	err = ohci_register(dev, regs);
 	if (!err)
 		return err;
 
+reset_err:
+	ret = reset_assert_all(priv->resets, priv->reset_count);
+	if (ret)
+		return ret;
 clk_err:
 	ret = clk_disable_all(priv->clocks, priv->clock_count);
 	if (ret)
@@ -81,6 +121,10 @@ static int ohci_usb_remove(struct udevice *dev)
 	if (ret)
 		return ret;
 
+	ret = reset_assert_all(priv->resets, priv->reset_count);
+	if (ret)
+		return ret;
+
 	return clk_disable_all(priv->clocks, priv->clock_count);
 }
 
-- 
1.9.1

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

* [U-Boot] [PATCH v7 10/10] usb: host: ohci-generic: add generic PHY support
  2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
                   ` (8 preceding siblings ...)
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 09/10] usb: host: ohci-generic: add RESET support patrice.chotard at st.com
@ 2017-06-20  9:59 ` patrice.chotard at st.com
  9 siblings, 0 replies; 24+ messages in thread
From: patrice.chotard at st.com @ 2017-06-20  9:59 UTC (permalink / raw)
  To: u-boot

From: Patrice Chotard <patrice.chotard@st.com>

Extend ohci-generic driver with generic PHY framework

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
v7:	_ none

v6:	_ none

v5:	_ none

v4:	_ use generic_phy_valid() before generic_phy_exit() call

v3:	_ extract in this patch the PHY support add-on from previous patch 5

 drivers/usb/host/ohci-generic.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index 5bd52ff..63cc25e 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
+#include <generic-phy.h>
 #include <reset.h>
 #include "ohci.h"
 
@@ -20,6 +21,7 @@ struct generic_ohci {
 	ohci_t ohci;
 	struct clk *clocks;
 	struct reset_ctl *resets;
+	struct phy phy;
 	int clock_count;
 	int reset_count;
 };
@@ -96,10 +98,30 @@ static int ohci_usb_probe(struct udevice *dev)
 		}
 	}
 
+	err = generic_phy_get_by_index(dev, 0, &priv->phy);
+	if (err) {
+		if (err != -ENOENT) {
+			error("failed to get usb phy\n");
+			goto reset_err;
+		}
+	} else {
+		err = generic_phy_init(&priv->phy);
+		if (err) {
+			error("failed to init usb phy\n");
+			goto reset_err;
+		}
+	}
+
 	err = ohci_register(dev, regs);
 	if (!err)
 		return err;
 
+	if (generic_phy_valid(&priv->phy)) {
+		ret = generic_phy_exit(&priv->phy);
+		if (ret)
+			return ret;
+	}
+
 reset_err:
 	ret = reset_assert_all(priv->resets, priv->reset_count);
 	if (ret)
@@ -121,6 +143,12 @@ static int ohci_usb_remove(struct udevice *dev)
 	if (ret)
 		return ret;
 
+	if (generic_phy_valid(&priv->phy)) {
+		ret = generic_phy_exit(&priv->phy);
+		if (ret)
+			return ret;
+	}
+
 	ret = reset_assert_all(priv->resets, priv->reset_count);
 	if (ret)
 		return ret;
-- 
1.9.1

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

* [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback patrice.chotard at st.com
@ 2017-06-20 10:09   ` Marek Vasut
  2017-06-20 11:26     ` Lothar Waßmann
  2017-06-20 12:22     ` Patrice CHOTARD
  2017-06-20 11:32   ` Lothar Waßmann
  1 sibling, 2 replies; 24+ messages in thread
From: Marek Vasut @ 2017-06-20 10:09 UTC (permalink / raw)
  To: u-boot

On 06/20/2017 11:59 AM, patrice.chotard at st.com wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
> 
> Use an array to save enabled clocks reference and deasserted resets
> in order to respectively disabled and asserted them in case of error
> during probe() or during driver removal.
> 
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>

Nitpicks below

> ---
> 
> v7:	_ replace clk_count() and reset_count() by ofnode_count_phandle_with_args()
> 
> v6:	_ none
> 
> v5: 	_ none
> 
> v4:	_ update the memory allocation for deasserted resets and enabled
> 	  clocks reference list. Replace lists by arrays.
> 	_ usage of new RESET and CLOCK methods clk_count(), reset_count(),
> 	  reset_assert_all() and clk_disable_all().
> 
> v3:	_ keep enabled clocks and deasserted resets reference in list in order to
> 	  disable clock or assert resets in error path or in .remove callback
> 	_ use struct generic_ehci * instead of struct udevice * as parameter for
> 	  ehci_release_resets() and ehci_release_clocks()
> 
>  drivers/usb/host/ehci-generic.c | 125 ++++++++++++++++++++++++++++++++--------
>  1 file changed, 101 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
> index 2116ae1..388b242 100644
> --- a/drivers/usb/host/ehci-generic.c
> +++ b/drivers/usb/host/ehci-generic.c
> @@ -11,6 +11,8 @@
>  #include <dm.h>
>  #include "ehci.h"
>  
> +#include <dm/ofnode.h>
> +
>  /*
>   * Even though here we don't explicitly use "struct ehci_ctrl"
>   * ehci_register() expects it to be the first thing that resides in
> @@ -18,43 +20,119 @@
>   */
>  struct generic_ehci {
>  	struct ehci_ctrl ctrl;
> +	struct clk *clocks;
> +	struct reset_ctl *resets;
> +	int clock_count;
> +	int reset_count;
>  };
>  
>  static int ehci_usb_probe(struct udevice *dev)
>  {
> +	struct generic_ehci *priv = dev_get_priv(dev);
>  	struct ehci_hccr *hccr;
>  	struct ehci_hcor *hcor;
> -	int i;
> -
> -	for (i = 0; ; i++) {
> -		struct clk clk;
> -		int ret;
> -
> -		ret = clk_get_by_index(dev, i, &clk);
> -		if (ret < 0)
> -			break;
> -		if (clk_enable(&clk))
> -			error("failed to enable clock %d\n", i);
> -		clk_free(&clk);
> -	}
> +	int i, err, ret, clock_nb, reset_nb;
> +
> +	err = 0;
> +	priv->clock_count = 0;
> +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
> +						  "#clock-cells");
> +	if (clock_nb > 0) {
> +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
> +					    GFP_KERNEL);

devm_kzalloc()

> +		if (!priv->clocks) {
> +			error("Can't allocate resource\n");

If you run out of memory, you're screwed anyway, drop this print.

> +			return -ENOMEM;
> +		}
> +
> +		for (i = 0; i < clock_nb; i++) {
> +			err = clk_get_by_index(dev, i, &priv->clocks[i]);
> +
> +			if (err < 0)
> +				break;
>  
> -	for (i = 0; ; i++) {
> -		struct reset_ctl reset;
> -		int ret;
> +			priv->clock_count++;
>  
> -		ret = reset_get_by_index(dev, i, &reset);
> -		if (ret < 0)
> -			break;
> -		if (reset_deassert(&reset))
> -			error("failed to deassert reset %d\n", i);
> -		reset_free(&reset);
> +			if (clk_enable(&priv->clocks[i])) {
> +				error("failed to enable clock %d\n", i);
> +				clk_free(&priv->clocks[i]);
> +				goto clk_err;
> +			}
> +			clk_free(&priv->clocks[i]);
> +		}
> +	} else {
> +		if (clock_nb != -ENOENT) {
> +			error("failed to get clock phandle(%d)\n", clock_nb);
> +			return clock_nb;
> +		}
>  	}
>  
> +	priv->reset_count = 0;
> +	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
> +						  "#reset-cells");
> +	if (reset_nb > 0) {
> +		priv->resets = devm_kmalloc(dev,
> +					    sizeof(struct reset_ctl) * reset_nb,
> +					    GFP_KERNEL);
> +		if (!priv->resets) {
> +			error("Can't allocate resource\n");
> +			return -ENOMEM;
> +		}
> +
> +		for (i = 0; i < reset_nb; i++) {
> +			err = reset_get_by_index(dev, i, &priv->resets[i]);
> +			if (err < 0)
> +				break;
> +
> +			priv->reset_count++;
> +
> +			if (reset_deassert(&priv->resets[i])) {
> +				error("failed to deassert reset %d\n", i);
> +				reset_free(&priv->resets[i]);
> +				goto reset_err;
> +			}
> +			reset_free(&priv->resets[i]);
> +		}
> +	} else {
> +		if (reset_nb != -ENOENT) {
> +			error("failed to get reset phandle(%d)\n", reset_nb);
> +			goto clk_err;
> +		}
> +	}

Newline

>  	hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
>  	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
>  				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
>  
> -	return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
> +	err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
> +	if (!err)
> +		return err;
> +
> +reset_err:
> +	ret = reset_assert_all(priv->resets, priv->reset_count);
> +	if (ret)
> +		return ret;
> +clk_err:
> +	ret = clk_disable_all(priv->clocks, priv->clock_count);
> +	if (ret)
> +		return ret;
> +
> +	return err;
> +}
> +
> +static int ehci_usb_remove(struct udevice *dev)
> +{
> +	struct generic_ehci *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	ret = ehci_deregister(dev);
> +	if (ret)
> +		return ret;
> +
> +	ret =  reset_assert_all(priv->resets, priv->reset_count);
> +	if (ret)
> +		return ret;
> +
> +	return clk_disable_all(priv->clocks, priv->clock_count);
>  }
>  
>  static const struct udevice_id ehci_usb_ids[] = {
> @@ -67,7 +145,7 @@ U_BOOT_DRIVER(ehci_generic) = {
>  	.id	= UCLASS_USB,
>  	.of_match = ehci_usb_ids,
>  	.probe = ehci_usb_probe,
> -	.remove = ehci_deregister,
> +	.remove = ehci_usb_remove,
>  	.ops	= &ehci_usb_ops,
>  	.priv_auto_alloc_size = sizeof(struct generic_ehci),
>  	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
> 


-- 
Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback
  2017-06-20 10:09   ` Marek Vasut
@ 2017-06-20 11:26     ` Lothar Waßmann
  2017-06-20 12:22     ` Patrice CHOTARD
  1 sibling, 0 replies; 24+ messages in thread
From: Lothar Waßmann @ 2017-06-20 11:26 UTC (permalink / raw)
  To: u-boot

Hi,

On Tue, 20 Jun 2017 12:09:22 +0200 Marek Vasut wrote:
> On 06/20/2017 11:59 AM, patrice.chotard at st.com wrote:
> > From: Patrice Chotard <patrice.chotard@st.com>
> > 
> > Use an array to save enabled clocks reference and deasserted resets
> > in order to respectively disabled and asserted them in case of error
> > during probe() or during driver removal.
> > 
> > Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> 
> Nitpicks below
> 
> > ---
> > 
> > v7:	_ replace clk_count() and reset_count() by ofnode_count_phandle_with_args()
> > 
> > v6:	_ none
> > 
> > v5: 	_ none
> > 
> > v4:	_ update the memory allocation for deasserted resets and enabled
> > 	  clocks reference list. Replace lists by arrays.
> > 	_ usage of new RESET and CLOCK methods clk_count(), reset_count(),
> > 	  reset_assert_all() and clk_disable_all().
> > 
> > v3:	_ keep enabled clocks and deasserted resets reference in list in order to
> > 	  disable clock or assert resets in error path or in .remove callback
> > 	_ use struct generic_ehci * instead of struct udevice * as parameter for
> > 	  ehci_release_resets() and ehci_release_clocks()
> > 
> >  drivers/usb/host/ehci-generic.c | 125 ++++++++++++++++++++++++++++++++--------
> >  1 file changed, 101 insertions(+), 24 deletions(-)
> > 
> > diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
> > index 2116ae1..388b242 100644
> > --- a/drivers/usb/host/ehci-generic.c
> > +++ b/drivers/usb/host/ehci-generic.c
> > @@ -11,6 +11,8 @@
> >  #include <dm.h>
> >  #include "ehci.h"
> >  
> > +#include <dm/ofnode.h>
> > +
> >  /*
> >   * Even though here we don't explicitly use "struct ehci_ctrl"
> >   * ehci_register() expects it to be the first thing that resides in
> > @@ -18,43 +20,119 @@
> >   */
> >  struct generic_ehci {
> >  	struct ehci_ctrl ctrl;
> > +	struct clk *clocks;
> > +	struct reset_ctl *resets;
> > +	int clock_count;
> > +	int reset_count;
> >  };
> >  
> >  static int ehci_usb_probe(struct udevice *dev)
> >  {
> > +	struct generic_ehci *priv = dev_get_priv(dev);
> >  	struct ehci_hccr *hccr;
> >  	struct ehci_hcor *hcor;
> > -	int i;
> > -
> > -	for (i = 0; ; i++) {
> > -		struct clk clk;
> > -		int ret;
> > -
> > -		ret = clk_get_by_index(dev, i, &clk);
> > -		if (ret < 0)
> > -			break;
> > -		if (clk_enable(&clk))
> > -			error("failed to enable clock %d\n", i);
> > -		clk_free(&clk);
> > -	}
> > +	int i, err, ret, clock_nb, reset_nb;
> > +
> > +	err = 0;
> > +	priv->clock_count = 0;
> > +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
> > +						  "#clock-cells");
> > +	if (clock_nb > 0) {
> > +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
> > +					    GFP_KERNEL);
> 
> devm_kzalloc()
>
devm_kcalloc(dev, clock_nb, sizeof()...)


Lothar Waßmann

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

* [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback patrice.chotard at st.com
  2017-06-20 10:09   ` Marek Vasut
@ 2017-06-20 11:32   ` Lothar Waßmann
  2017-06-20 12:28     ` Patrice CHOTARD
  1 sibling, 1 reply; 24+ messages in thread
From: Lothar Waßmann @ 2017-06-20 11:32 UTC (permalink / raw)
  To: u-boot

Hi,

On Tue, 20 Jun 2017 11:59:07 +0200 patrice.chotard at st.com wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
> 
> Use an array to save enabled clocks reference and deasserted resets
> in order to respectively disabled and asserted them in case of error
> during probe() or during driver removal.
> 
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> ---
> 
> v7:	_ replace clk_count() and reset_count() by ofnode_count_phandle_with_args()
> 
> v6:	_ none
> 
> v5: 	_ none
> 
> v4:	_ update the memory allocation for deasserted resets and enabled
> 	  clocks reference list. Replace lists by arrays.
> 	_ usage of new RESET and CLOCK methods clk_count(), reset_count(),
> 	  reset_assert_all() and clk_disable_all().
> 
> v3:	_ keep enabled clocks and deasserted resets reference in list in order to
> 	  disable clock or assert resets in error path or in .remove callback
> 	_ use struct generic_ehci * instead of struct udevice * as parameter for
> 	  ehci_release_resets() and ehci_release_clocks()
> 
>  drivers/usb/host/ehci-generic.c | 125 ++++++++++++++++++++++++++++++++--------
>  1 file changed, 101 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
> index 2116ae1..388b242 100644
> --- a/drivers/usb/host/ehci-generic.c
> +++ b/drivers/usb/host/ehci-generic.c
> @@ -11,6 +11,8 @@
>  #include <dm.h>
>  #include "ehci.h"
>  
> +#include <dm/ofnode.h>
> +
>  /*
>   * Even though here we don't explicitly use "struct ehci_ctrl"
>   * ehci_register() expects it to be the first thing that resides in
> @@ -18,43 +20,119 @@
>   */
>  struct generic_ehci {
>  	struct ehci_ctrl ctrl;
> +	struct clk *clocks;
> +	struct reset_ctl *resets;
> +	int clock_count;
> +	int reset_count;
>  };
>  
>  static int ehci_usb_probe(struct udevice *dev)
>  {
> +	struct generic_ehci *priv = dev_get_priv(dev);
>  	struct ehci_hccr *hccr;
>  	struct ehci_hcor *hcor;
> -	int i;
> -
> -	for (i = 0; ; i++) {
> -		struct clk clk;
> -		int ret;
> -
> -		ret = clk_get_by_index(dev, i, &clk);
> -		if (ret < 0)
> -			break;
> -		if (clk_enable(&clk))
> -			error("failed to enable clock %d\n", i);
> -		clk_free(&clk);
> -	}
> +	int i, err, ret, clock_nb, reset_nb;
> +
> +	err = 0;
> +	priv->clock_count = 0;
> +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
> +						  "#clock-cells");
> +	if (clock_nb > 0) {
> +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
> +					    GFP_KERNEL);
> +		if (!priv->clocks) {
> +			error("Can't allocate resource\n");
> +			return -ENOMEM;
> +		}
> +
> +		for (i = 0; i < clock_nb; i++) {
> +			err = clk_get_by_index(dev, i, &priv->clocks[i]);
> +
> +			if (err < 0)
> +				break;
>  
> -	for (i = 0; ; i++) {
> -		struct reset_ctl reset;
> -		int ret;
> +			priv->clock_count++;
>  
> -		ret = reset_get_by_index(dev, i, &reset);
> -		if (ret < 0)
> -			break;
> -		if (reset_deassert(&reset))
> -			error("failed to deassert reset %d\n", i);
> -		reset_free(&reset);
> +			if (clk_enable(&priv->clocks[i])) {
> +				error("failed to enable clock %d\n", i);
> +				clk_free(&priv->clocks[i]);
>
You free the clock here and again with clk_disable_all() in the error
path. Also you do not have a valid error code in 'err' which is
returned at the end of the function!

> +				goto clk_err;
> +			}
> +			clk_free(&priv->clocks[i]);
> +		}
> +	} else {
> +		if (clock_nb != -ENOENT) {
> +			error("failed to get clock phandle(%d)\n", clock_nb);
> +			return clock_nb;
> +		}
>  	}
>  
> +	priv->reset_count = 0;
> +	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
> +						  "#reset-cells");
> +	if (reset_nb > 0) {
> +		priv->resets = devm_kmalloc(dev,
> +					    sizeof(struct reset_ctl) * reset_nb,
> +					    GFP_KERNEL);
> +		if (!priv->resets) {
> +			error("Can't allocate resource\n");
> +			return -ENOMEM;
> +		}
> +
> +		for (i = 0; i < reset_nb; i++) {
> +			err = reset_get_by_index(dev, i, &priv->resets[i]);
> +			if (err < 0)
> +				break;
> +
> +			priv->reset_count++;
> +
> +			if (reset_deassert(&priv->resets[i])) {
> +				error("failed to deassert reset %d\n", i);
> +				reset_free(&priv->resets[i]);
> +				goto reset_err;
> +			}
> +			reset_free(&priv->resets[i]);
> +		}
> +	} else {
> +		if (reset_nb != -ENOENT) {
> +			error("failed to get reset phandle(%d)\n", reset_nb);
> +			goto clk_err;
> +		}
> +	}
>  	hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
>  	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
>  				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
>  
> -	return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
> +	err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
> +	if (!err)
> +		return err;
> +
> +reset_err:
> +	ret = reset_assert_all(priv->resets, priv->reset_count);
> +	if (ret)
> +		return ret;
>
You should do the clock cleanup even though the reset cleanup failed.

> +clk_err:
> +	ret = clk_disable_all(priv->clocks, priv->clock_count);
> +	if (ret)
> +		return ret;
>
You should return the error code of the operation that failed
initially (err), not some error code that has occured during cleanup.

> +	return err;
> +}
> +
> +static int ehci_usb_remove(struct udevice *dev)
> +{
> +	struct generic_ehci *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	ret = ehci_deregister(dev);
> +	if (ret)
> +		return ret;
> +
> +	ret =  reset_assert_all(priv->resets, priv->reset_count);
> +	if (ret)
> +		return ret;
> +
> +	return clk_disable_all(priv->clocks, priv->clock_count);
>  }
>  
>  static const struct udevice_id ehci_usb_ids[] = {
> @@ -67,7 +145,7 @@ U_BOOT_DRIVER(ehci_generic) = {
>  	.id	= UCLASS_USB,
>  	.of_match = ehci_usb_ids,
>  	.probe = ehci_usb_probe,
> -	.remove = ehci_deregister,
> +	.remove = ehci_usb_remove,
>  	.ops	= &ehci_usb_ops,
>  	.priv_auto_alloc_size = sizeof(struct generic_ehci),
>  	.flags	= DM_FLAG_ALLOC_PRIV_DMA,


Lothar Waßmann

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

* [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support patrice.chotard at st.com
@ 2017-06-20 12:06   ` Lothar Waßmann
  2017-06-20 12:56     ` Patrice CHOTARD
  0 siblings, 1 reply; 24+ messages in thread
From: Lothar Waßmann @ 2017-06-20 12:06 UTC (permalink / raw)
  To: u-boot

Hi,

On Tue, 20 Jun 2017 11:59:09 +0200 patrice.chotard at st.com wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
> 
> use array to save enabled clocks reference in order to
> disabled them in case of error during probe() or during
> driver removal.
> 
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> ---
> v7:	_ replace clk_count() by ofnode_count_phandle_with_args()
> 
> v6:	_ none
> 
> v5:	_ none
> 
> v4:	_ use generic_phy_valid() before generic_phy_exit() call
> 
> v3:	_ extract in this patch the CLOCK support add-on from previous patch 5
> 	_ keep enabled clocks reference in list in order to
> 	  disable clocks in error path or in .remove callback
> 
> v2:	_ add error path management
> 	_ add .remove callback
> 
>  drivers/usb/host/ohci-generic.c | 59 +++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 57 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
> index f85738f..f76a1c2 100644
> --- a/drivers/usb/host/ohci-generic.c
> +++ b/drivers/usb/host/ohci-generic.c
> @@ -5,27 +5,83 @@
>   */
>  
>  #include <common.h>
> +#include <clk.h>
>  #include <dm.h>
>  #include "ohci.h"
>  
> +#include <dm/ofnode.h>
> +
>  #if !defined(CONFIG_USB_OHCI_NEW)
>  # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
>  #endif
>  
>  struct generic_ohci {
>  	ohci_t ohci;
> +	struct clk *clocks;
> +	int clock_count;
>  };
>  
>  static int ohci_usb_probe(struct udevice *dev)
>  {
>  	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
> +	struct generic_ohci *priv = dev_get_priv(dev);
> +	int i, err, ret, clock_nb;
> +
> +	err = 0;
> +	priv->clock_count = 0;
> +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
> +						  "#clock-cells");
> +	if (clock_nb > 0) {
> +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
> +					    GFP_KERNEL);
> +		if (!priv->clocks) {
> +			error("Can't allocate resource\n");
> +			return -ENOMEM;
> +		}
> +
> +		for (i = 0; i < clock_nb; i++) {
> +			err = clk_get_by_index(dev, i, &priv->clocks[i]);
> +			if (err < 0)
> +				break;
> +
> +			priv->clock_count++;
> +
> +			if (clk_enable(&priv->clocks[i])) {
> +				error("failed to enable clock %d\n", i);
> +				clk_free(&priv->clocks[i]);
> +				goto clk_err;
> +			}
> +			clk_free(&priv->clocks[i]);
>
You free the freshly allocated clock right away and use it lateron?

> +	} else {
> +		if (clock_nb != -ENOENT) {
> +			error("failed to get clock phandle(%d)\n", clock_nb);
> +			return clock_nb;
> +		}
> +	}
>  
> -	return ohci_register(dev, regs);
> +	err = ohci_register(dev, regs);
> +	if (!err)
> +		return err;
> +
	if (err)
		goto clk_err;
	return 0;
would be more easy to follow.

> +clk_err:
> +	ret = clk_disable_all(priv->clocks, priv->clock_count);
> +	if (ret)
> +		return ret;
> +
> +	return err;
>  }
>  
>  static int ohci_usb_remove(struct udevice *dev)
>  {
> -	return ohci_deregister(dev);
> +	struct generic_ohci *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	ret = ohci_deregister(dev);
> +	if (ret)
> +		return ret;
> +
> +	return clk_disable_all(priv->clocks, priv->clock_count);
>  }
>  
>  static const struct udevice_id ohci_usb_ids[] = {


Lothar Waßmann

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

* [U-Boot] [PATCH v7 03/10] clk: add clk_disable_all()
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 03/10] clk: add clk_disable_all() patrice.chotard at st.com
@ 2017-06-20 12:11   ` Lothar Waßmann
  2017-06-20 12:40     ` Patrice CHOTARD
  0 siblings, 1 reply; 24+ messages in thread
From: Lothar Waßmann @ 2017-06-20 12:11 UTC (permalink / raw)
  To: u-boot

Hi,

On Tue, 20 Jun 2017 11:59:04 +0200 patrice.chotard at st.com wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
> 
> Add clk_disable_all() method which Request/Disable/Free an
> array of clocks that has been previously requested by
> clk_request/get_by_*()
> 
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
> 
> v7:	_ none
> v6:	_ none
> v5:	_ none
> v4:	_ none
> v3:	_ add commit message
> v2:	_ create this independant path for printf() replacement
> 
>  drivers/clk/clk-uclass.c | 22 ++++++++++++++++++++++
>  include/clk.h            | 10 ++++++++++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
> index 83b6328..e732514 100644
> --- a/drivers/clk/clk-uclass.c
> +++ b/drivers/clk/clk-uclass.c
> @@ -187,6 +187,28 @@ int clk_disable(struct clk *clk)
>  	return ops->disable(clk);
>  }
>  
> +int clk_disable_all(struct clk *clk, int count)
> +{
> +	int i, ret;
> +
> +	debug("%s(clk=%p count=%d)\n", __func__, clk, count);
> +
> +	for (i = 0; i < count; i++) {
> +		ret = clk_request(clk->dev, &clk[i]);
>
Shouldn't this be:
		ret = clk_request(clk[i].dev, &clk[i]);



Lothar Waßmann

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

* [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback
  2017-06-20 10:09   ` Marek Vasut
  2017-06-20 11:26     ` Lothar Waßmann
@ 2017-06-20 12:22     ` Patrice CHOTARD
  1 sibling, 0 replies; 24+ messages in thread
From: Patrice CHOTARD @ 2017-06-20 12:22 UTC (permalink / raw)
  To: u-boot

Hi Marek

On 06/20/2017 12:09 PM, Marek Vasut wrote:
> On 06/20/2017 11:59 AM, patrice.chotard at st.com wrote:
>> From: Patrice Chotard <patrice.chotard@st.com>
>>
>> Use an array to save enabled clocks reference and deasserted resets
>> in order to respectively disabled and asserted them in case of error
>> during probe() or during driver removal.
>>
>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> 
> Nitpicks below
> 
>> ---
>>
>> v7:	_ replace clk_count() and reset_count() by ofnode_count_phandle_with_args()
>>
>> v6:	_ none
>>
>> v5: 	_ none
>>
>> v4:	_ update the memory allocation for deasserted resets and enabled
>> 	  clocks reference list. Replace lists by arrays.
>> 	_ usage of new RESET and CLOCK methods clk_count(), reset_count(),
>> 	  reset_assert_all() and clk_disable_all().
>>
>> v3:	_ keep enabled clocks and deasserted resets reference in list in order to
>> 	  disable clock or assert resets in error path or in .remove callback
>> 	_ use struct generic_ehci * instead of struct udevice * as parameter for
>> 	  ehci_release_resets() and ehci_release_clocks()
>>
>>   drivers/usb/host/ehci-generic.c | 125 ++++++++++++++++++++++++++++++++--------
>>   1 file changed, 101 insertions(+), 24 deletions(-)
>>
>> diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
>> index 2116ae1..388b242 100644
>> --- a/drivers/usb/host/ehci-generic.c
>> +++ b/drivers/usb/host/ehci-generic.c
>> @@ -11,6 +11,8 @@
>>   #include <dm.h>
>>   #include "ehci.h"
>>   
>> +#include <dm/ofnode.h>
>> +
>>   /*
>>    * Even though here we don't explicitly use "struct ehci_ctrl"
>>    * ehci_register() expects it to be the first thing that resides in
>> @@ -18,43 +20,119 @@
>>    */
>>   struct generic_ehci {
>>   	struct ehci_ctrl ctrl;
>> +	struct clk *clocks;
>> +	struct reset_ctl *resets;
>> +	int clock_count;
>> +	int reset_count;
>>   };
>>   
>>   static int ehci_usb_probe(struct udevice *dev)
>>   {
>> +	struct generic_ehci *priv = dev_get_priv(dev);
>>   	struct ehci_hccr *hccr;
>>   	struct ehci_hcor *hcor;
>> -	int i;
>> -
>> -	for (i = 0; ; i++) {
>> -		struct clk clk;
>> -		int ret;
>> -
>> -		ret = clk_get_by_index(dev, i, &clk);
>> -		if (ret < 0)
>> -			break;
>> -		if (clk_enable(&clk))
>> -			error("failed to enable clock %d\n", i);
>> -		clk_free(&clk);
>> -	}
>> +	int i, err, ret, clock_nb, reset_nb;
>> +
>> +	err = 0;
>> +	priv->clock_count = 0;
>> +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
>> +						  "#clock-cells");
>> +	if (clock_nb > 0) {
>> +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
>> +					    GFP_KERNEL);
> 
> devm_kzalloc()

Ok

> 
>> +		if (!priv->clocks) {
>> +			error("Can't allocate resource\n");
> 
> If you run out of memory, you're screwed anyway, drop this print.

Ok, i will remove it

> 
>> +			return -ENOMEM;
>> +		}
>> +
>> +		for (i = 0; i < clock_nb; i++) {
>> +			err = clk_get_by_index(dev, i, &priv->clocks[i]);
>> +
>> +			if (err < 0)
>> +				break;
>>   
>> -	for (i = 0; ; i++) {
>> -		struct reset_ctl reset;
>> -		int ret;
>> +			priv->clock_count++;
>>   
>> -		ret = reset_get_by_index(dev, i, &reset);
>> -		if (ret < 0)
>> -			break;
>> -		if (reset_deassert(&reset))
>> -			error("failed to deassert reset %d\n", i);
>> -		reset_free(&reset);
>> +			if (clk_enable(&priv->clocks[i])) {
>> +				error("failed to enable clock %d\n", i);
>> +				clk_free(&priv->clocks[i]);
>> +				goto clk_err;
>> +			}
>> +			clk_free(&priv->clocks[i]);
>> +		}
>> +	} else {
>> +		if (clock_nb != -ENOENT) {
>> +			error("failed to get clock phandle(%d)\n", clock_nb);
>> +			return clock_nb;
>> +		}
>>   	}
>>   
>> +	priv->reset_count = 0;
>> +	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
>> +						  "#reset-cells");
>> +	if (reset_nb > 0) {
>> +		priv->resets = devm_kmalloc(dev,
>> +					    sizeof(struct reset_ctl) * reset_nb,
>> +					    GFP_KERNEL);
>> +		if (!priv->resets) {
>> +			error("Can't allocate resource\n");
>> +			return -ENOMEM;
>> +		}
>> +
>> +		for (i = 0; i < reset_nb; i++) {
>> +			err = reset_get_by_index(dev, i, &priv->resets[i]);
>> +			if (err < 0)
>> +				break;
>> +
>> +			priv->reset_count++;
>> +
>> +			if (reset_deassert(&priv->resets[i])) {
>> +				error("failed to deassert reset %d\n", i);
>> +				reset_free(&priv->resets[i]);
>> +				goto reset_err;
>> +			}
>> +			reset_free(&priv->resets[i]);
>> +		}
>> +	} else {
>> +		if (reset_nb != -ENOENT) {
>> +			error("failed to get reset phandle(%d)\n", reset_nb);
>> +			goto clk_err;
>> +		}
>> +	}
> 
> Newline

ok

> 
>>   	hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
>>   	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
>>   				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
>>   
>> -	return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
>> +	err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
>> +	if (!err)
>> +		return err;
>> +
>> +reset_err:
>> +	ret = reset_assert_all(priv->resets, priv->reset_count);
>> +	if (ret)
>> +		return ret;
>> +clk_err:
>> +	ret = clk_disable_all(priv->clocks, priv->clock_count);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return err;
>> +}
>> +
>> +static int ehci_usb_remove(struct udevice *dev)
>> +{
>> +	struct generic_ehci *priv = dev_get_priv(dev);
>> +	int ret;
>> +
>> +	ret = ehci_deregister(dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret =  reset_assert_all(priv->resets, priv->reset_count);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return clk_disable_all(priv->clocks, priv->clock_count);
>>   }
>>   
>>   static const struct udevice_id ehci_usb_ids[] = {
>> @@ -67,7 +145,7 @@ U_BOOT_DRIVER(ehci_generic) = {
>>   	.id	= UCLASS_USB,
>>   	.of_match = ehci_usb_ids,
>>   	.probe = ehci_usb_probe,
>> -	.remove = ehci_deregister,
>> +	.remove = ehci_usb_remove,
>>   	.ops	= &ehci_usb_ops,
>>   	.priv_auto_alloc_size = sizeof(struct generic_ehci),
>>   	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
>>
> 
> 

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

* [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback
  2017-06-20 11:32   ` Lothar Waßmann
@ 2017-06-20 12:28     ` Patrice CHOTARD
  0 siblings, 0 replies; 24+ messages in thread
From: Patrice CHOTARD @ 2017-06-20 12:28 UTC (permalink / raw)
  To: u-boot

Hi Lothar

On 06/20/2017 01:32 PM, Lothar Waßmann wrote:
> Hi,
> 
> On Tue, 20 Jun 2017 11:59:07 +0200 patrice.chotard at st.com wrote:
>> From: Patrice Chotard <patrice.chotard@st.com>
>>
>> Use an array to save enabled clocks reference and deasserted resets
>> in order to respectively disabled and asserted them in case of error
>> during probe() or during driver removal.
>>
>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
>> ---
>>
>> v7:	_ replace clk_count() and reset_count() by ofnode_count_phandle_with_args()
>>
>> v6:	_ none
>>
>> v5: 	_ none
>>
>> v4:	_ update the memory allocation for deasserted resets and enabled
>> 	  clocks reference list. Replace lists by arrays.
>> 	_ usage of new RESET and CLOCK methods clk_count(), reset_count(),
>> 	  reset_assert_all() and clk_disable_all().
>>
>> v3:	_ keep enabled clocks and deasserted resets reference in list in order to
>> 	  disable clock or assert resets in error path or in .remove callback
>> 	_ use struct generic_ehci * instead of struct udevice * as parameter for
>> 	  ehci_release_resets() and ehci_release_clocks()
>>
>>   drivers/usb/host/ehci-generic.c | 125 ++++++++++++++++++++++++++++++++--------
>>   1 file changed, 101 insertions(+), 24 deletions(-)
>>
>> diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
>> index 2116ae1..388b242 100644
>> --- a/drivers/usb/host/ehci-generic.c
>> +++ b/drivers/usb/host/ehci-generic.c
>> @@ -11,6 +11,8 @@
>>   #include <dm.h>
>>   #include "ehci.h"
>>   
>> +#include <dm/ofnode.h>
>> +
>>   /*
>>    * Even though here we don't explicitly use "struct ehci_ctrl"
>>    * ehci_register() expects it to be the first thing that resides in
>> @@ -18,43 +20,119 @@
>>    */
>>   struct generic_ehci {
>>   	struct ehci_ctrl ctrl;
>> +	struct clk *clocks;
>> +	struct reset_ctl *resets;
>> +	int clock_count;
>> +	int reset_count;
>>   };
>>   
>>   static int ehci_usb_probe(struct udevice *dev)
>>   {
>> +	struct generic_ehci *priv = dev_get_priv(dev);
>>   	struct ehci_hccr *hccr;
>>   	struct ehci_hcor *hcor;
>> -	int i;
>> -
>> -	for (i = 0; ; i++) {
>> -		struct clk clk;
>> -		int ret;
>> -
>> -		ret = clk_get_by_index(dev, i, &clk);
>> -		if (ret < 0)
>> -			break;
>> -		if (clk_enable(&clk))
>> -			error("failed to enable clock %d\n", i);
>> -		clk_free(&clk);
>> -	}
>> +	int i, err, ret, clock_nb, reset_nb;
>> +
>> +	err = 0;
>> +	priv->clock_count = 0;
>> +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
>> +						  "#clock-cells");
>> +	if (clock_nb > 0) {
>> +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
>> +					    GFP_KERNEL);
>> +		if (!priv->clocks) {
>> +			error("Can't allocate resource\n");
>> +			return -ENOMEM;
>> +		}
>> +
>> +		for (i = 0; i < clock_nb; i++) {
>> +			err = clk_get_by_index(dev, i, &priv->clocks[i]);
>> +
>> +			if (err < 0)
>> +				break;
>>   
>> -	for (i = 0; ; i++) {
>> -		struct reset_ctl reset;
>> -		int ret;
>> +			priv->clock_count++;
>>   
>> -		ret = reset_get_by_index(dev, i, &reset);
>> -		if (ret < 0)
>> -			break;
>> -		if (reset_deassert(&reset))
>> -			error("failed to deassert reset %d\n", i);
>> -		reset_free(&reset);
>> +			if (clk_enable(&priv->clocks[i])) {
>> +				error("failed to enable clock %d\n", i);
>> +				clk_free(&priv->clocks[i]);
>>
> You free the clock here and again with clk_disable_all() in the error
> path. Also you do not have a valid error code in 'err' which is
> returned at the end of the function!

Good catch, to fix it, i will move the priv->clock_count++ after the 
clk_enable statement. In this case, in the error path, only clocks which 
have been previously correctly enabled will be requested/disabled/freed

Ok i will catch the error code in err and use it as return value.


> 
>> +				goto clk_err;
>> +			}
>> +			clk_free(&priv->clocks[i]);
>> +		}
>> +	} else {
>> +		if (clock_nb != -ENOENT) {
>> +			error("failed to get clock phandle(%d)\n", clock_nb);
>> +			return clock_nb;
>> +		}
>>   	}
>>   
>> +	priv->reset_count = 0;
>> +	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
>> +						  "#reset-cells");
>> +	if (reset_nb > 0) {
>> +		priv->resets = devm_kmalloc(dev,
>> +					    sizeof(struct reset_ctl) * reset_nb,
>> +					    GFP_KERNEL);
>> +		if (!priv->resets) {
>> +			error("Can't allocate resource\n");
>> +			return -ENOMEM;
>> +		}
>> +
>> +		for (i = 0; i < reset_nb; i++) {
>> +			err = reset_get_by_index(dev, i, &priv->resets[i]);
>> +			if (err < 0)
>> +				break;
>> +
>> +			priv->reset_count++;
>> +
>> +			if (reset_deassert(&priv->resets[i])) {
>> +				error("failed to deassert reset %d\n", i);
>> +				reset_free(&priv->resets[i]);
>> +				goto reset_err;
>> +			}
>> +			reset_free(&priv->resets[i]);
>> +		}
>> +	} else {
>> +		if (reset_nb != -ENOENT) {
>> +			error("failed to get reset phandle(%d)\n", reset_nb);
>> +			goto clk_err;
>> +		}
>> +	}
>>   	hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
>>   	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
>>   				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
>>   
>> -	return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
>> +	err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
>> +	if (!err)
>> +		return err;
>> +
>> +reset_err:
>> +	ret = reset_assert_all(priv->resets, priv->reset_count);
>> +	if (ret)
>> +		return ret;
>>
> You should do the clock cleanup even though the reset cleanup failed.

Agree, i will fix it

> 
>> +clk_err:
>> +	ret = clk_disable_all(priv->clocks, priv->clock_count);
>> +	if (ret)
>> +		return ret;
>>
> You should return the error code of the operation that failed
> initially (err), not some error code that has occured during cleanup.

Agree again

Thanks

Patrice

> 
>> +	return err;
>> +}
>> +
>> +static int ehci_usb_remove(struct udevice *dev)
>> +{
>> +	struct generic_ehci *priv = dev_get_priv(dev);
>> +	int ret;
>> +
>> +	ret = ehci_deregister(dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret =  reset_assert_all(priv->resets, priv->reset_count);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return clk_disable_all(priv->clocks, priv->clock_count);
>>   }
>>   
>>   static const struct udevice_id ehci_usb_ids[] = {
>> @@ -67,7 +145,7 @@ U_BOOT_DRIVER(ehci_generic) = {
>>   	.id	= UCLASS_USB,
>>   	.of_match = ehci_usb_ids,
>>   	.probe = ehci_usb_probe,
>> -	.remove = ehci_deregister,
>> +	.remove = ehci_usb_remove,
>>   	.ops	= &ehci_usb_ops,
>>   	.priv_auto_alloc_size = sizeof(struct generic_ehci),
>>   	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
> 
> 
> Lothar Waßmann
> 

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

* [U-Boot] [PATCH v7 03/10] clk: add clk_disable_all()
  2017-06-20 12:11   ` Lothar Waßmann
@ 2017-06-20 12:40     ` Patrice CHOTARD
  0 siblings, 0 replies; 24+ messages in thread
From: Patrice CHOTARD @ 2017-06-20 12:40 UTC (permalink / raw)
  To: u-boot

Hi Lothar

On 06/20/2017 02:11 PM, Lothar Waßmann wrote:
> Hi,
> 
> On Tue, 20 Jun 2017 11:59:04 +0200 patrice.chotard at st.com wrote:
>> From: Patrice Chotard <patrice.chotard@st.com>
>>
>> Add clk_disable_all() method which Request/Disable/Free an
>> array of clocks that has been previously requested by
>> clk_request/get_by_*()
>>
>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> v7:	_ none
>> v6:	_ none
>> v5:	_ none
>> v4:	_ none
>> v3:	_ add commit message
>> v2:	_ create this independant path for printf() replacement
>>
>>   drivers/clk/clk-uclass.c | 22 ++++++++++++++++++++++
>>   include/clk.h            | 10 ++++++++++
>>   2 files changed, 32 insertions(+)
>>
>> diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
>> index 83b6328..e732514 100644
>> --- a/drivers/clk/clk-uclass.c
>> +++ b/drivers/clk/clk-uclass.c
>> @@ -187,6 +187,28 @@ int clk_disable(struct clk *clk)
>>   	return ops->disable(clk);
>>   }
>>   
>> +int clk_disable_all(struct clk *clk, int count)
>> +{
>> +	int i, ret;
>> +
>> +	debug("%s(clk=%p count=%d)\n", __func__, clk, count);
>> +
>> +	for (i = 0; i < count; i++) {
>> +		ret = clk_request(clk->dev, &clk[i]);
>>
> Shouldn't this be:
> 		ret = clk_request(clk[i].dev, &clk[i]);

Yes, i will fix it

Thanks

Patrice
> 
> 
> 
> Lothar Waßmann
> 

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

* [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support
  2017-06-20 12:06   ` Lothar Waßmann
@ 2017-06-20 12:56     ` Patrice CHOTARD
  2017-06-21  7:56       ` Lothar Waßmann
  0 siblings, 1 reply; 24+ messages in thread
From: Patrice CHOTARD @ 2017-06-20 12:56 UTC (permalink / raw)
  To: u-boot

Hi Lothar

On 06/20/2017 02:06 PM, Lothar Waßmann wrote:
> Hi,
> 
> On Tue, 20 Jun 2017 11:59:09 +0200 patrice.chotard at st.com wrote:
>> From: Patrice Chotard <patrice.chotard@st.com>
>>
>> use array to save enabled clocks reference in order to
>> disabled them in case of error during probe() or during
>> driver removal.
>>
>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
>> ---
>> v7:	_ replace clk_count() by ofnode_count_phandle_with_args()
>>
>> v6:	_ none
>>
>> v5:	_ none
>>
>> v4:	_ use generic_phy_valid() before generic_phy_exit() call
>>
>> v3:	_ extract in this patch the CLOCK support add-on from previous patch 5
>> 	_ keep enabled clocks reference in list in order to
>> 	  disable clocks in error path or in .remove callback
>>
>> v2:	_ add error path management
>> 	_ add .remove callback
>>
>>   drivers/usb/host/ohci-generic.c | 59 +++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 57 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
>> index f85738f..f76a1c2 100644
>> --- a/drivers/usb/host/ohci-generic.c
>> +++ b/drivers/usb/host/ohci-generic.c
>> @@ -5,27 +5,83 @@
>>    */
>>   
>>   #include <common.h>
>> +#include <clk.h>
>>   #include <dm.h>
>>   #include "ohci.h"
>>   
>> +#include <dm/ofnode.h>
>> +
>>   #if !defined(CONFIG_USB_OHCI_NEW)
>>   # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
>>   #endif
>>   
>>   struct generic_ohci {
>>   	ohci_t ohci;
>> +	struct clk *clocks;
>> +	int clock_count;
>>   };
>>   
>>   static int ohci_usb_probe(struct udevice *dev)
>>   {
>>   	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
>> +	struct generic_ohci *priv = dev_get_priv(dev);
>> +	int i, err, ret, clock_nb;
>> +
>> +	err = 0;
>> +	priv->clock_count = 0;
>> +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
>> +						  "#clock-cells");
>> +	if (clock_nb > 0) {
>> +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
>> +					    GFP_KERNEL);
>> +		if (!priv->clocks) {
>> +			error("Can't allocate resource\n");
>> +			return -ENOMEM;
>> +		}
>> +
>> +		for (i = 0; i < clock_nb; i++) {
>> +			err = clk_get_by_index(dev, i, &priv->clocks[i]);
>> +			if (err < 0)
>> +				break;
>> +
>> +			priv->clock_count++;
>> +
>> +			if (clk_enable(&priv->clocks[i])) {
>> +				error("failed to enable clock %d\n", i);
>> +				clk_free(&priv->clocks[i]);
>> +				goto clk_err;
>> +			}
>> +			clk_free(&priv->clocks[i]);
>>
> You free the freshly allocated clock right away and use it lateron?

clk_free() didn't free clock resources, it's the opposite of 
clk_request(), see comments in include.clk.h

> 
>> +	} else {
>> +		if (clock_nb != -ENOENT) {
>> +			error("failed to get clock phandle(%d)\n", clock_nb);
>> +			return clock_nb;
>> +		}
>> +	}
>>   
>> -	return ohci_register(dev, regs);
>> +	err = ohci_register(dev, regs);
>> +	if (!err)
>> +		return err;
>> +
> 	if (err)
> 		goto clk_err;
> 	return 0;
> would be more easy to follow.

ok, i will fix it

Thanks

Patrice

> 
>> +clk_err:
>> +	ret = clk_disable_all(priv->clocks, priv->clock_count);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return err;
>>   }
>>   
>>   static int ohci_usb_remove(struct udevice *dev)
>>   {
>> -	return ohci_deregister(dev);
>> +	struct generic_ohci *priv = dev_get_priv(dev);
>> +	int ret;
>> +
>> +	ret = ohci_deregister(dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return clk_disable_all(priv->clocks, priv->clock_count);
>>   }
>>   
>>   static const struct udevice_id ohci_usb_ids[] = {
> 
> 
> Lothar Waßmann
> 

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

* [U-Boot] [PATCH v7 04/10] dm: core: add ofnode_count_phandle_with_args()
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 04/10] dm: core: add ofnode_count_phandle_with_args() patrice.chotard at st.com
@ 2017-06-20 18:26   ` Simon Glass
  0 siblings, 0 replies; 24+ messages in thread
From: Simon Glass @ 2017-06-20 18:26 UTC (permalink / raw)
  To: u-boot

On 20 June 2017 at 03:59,  <patrice.chotard@st.com> wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
>
> This function is usefull to get phandle number contained
> in a property list.
> For example,  this allows to allocate the right amount
> of memory to keep clock's reference contained into the
> "clocks" property.
>
> To implement it, either of_count_phandle_with_args() or
> fdtdec_parse_phandle_with_args() are used respectively
> for live tree and flat tree.
> By passing index = -1, these 2 functions returns the
> number of phandle contained into the property list.
>
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> ---
>
> v7:     _ add ofnode_count_phandle_with_args() which returns
>           the phandle number contained into a property list.
>
>
>  drivers/core/of_access.c |  7 +++++++
>  drivers/core/ofnode.c    | 12 ++++++++++++
>  include/dm/of_access.h   | 18 ++++++++++++++++++
>  include/dm/ofnode.h      | 17 +++++++++++++++++
>  4 files changed, 54 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v7 09/10] usb: host: ohci-generic: add RESET support
  2017-06-20  9:59 ` [U-Boot] [PATCH v7 09/10] usb: host: ohci-generic: add RESET support patrice.chotard at st.com
@ 2017-06-20 18:26   ` Simon Glass
  0 siblings, 0 replies; 24+ messages in thread
From: Simon Glass @ 2017-06-20 18:26 UTC (permalink / raw)
  To: u-boot

On 20 June 2017 at 03:59,  <patrice.chotard@st.com> wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
>
> use array to save deasserted resets reference in order to
> assert them in case of error during probe() or during driver
> removal.
>
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> ---
> v7:     _ replace reset_count() by ofnode_count_phandle_with_args()
>
> v6:     _ none
>
> v5:     _ none
>
> v4:     _ update the memory allocation for deasserted resets. Replace lists by arrays.
>         _ usage of new RESET methods reset_assert_all() and clk_disable_all().
>
> v3:     _ extract in this patch the RESET support add-on from previous patch 5
>         _ keep deasserted resets reference in list in order to
>           assert resets in error path or in .remove callback
>
> v2:     _ add error path management
>         _ add .remove callback
>
>  drivers/usb/host/ohci-generic.c | 46 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 45 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support
  2017-06-20 12:56     ` Patrice CHOTARD
@ 2017-06-21  7:56       ` Lothar Waßmann
  2017-06-21  8:36         ` Patrice CHOTARD
  0 siblings, 1 reply; 24+ messages in thread
From: Lothar Waßmann @ 2017-06-21  7:56 UTC (permalink / raw)
  To: u-boot

Hi,

On Tue, 20 Jun 2017 12:56:48 +0000 Patrice CHOTARD wrote:
> Hi Lothar
> 
> On 06/20/2017 02:06 PM, Lothar Waßmann wrote:
> > Hi,
> > 
> > On Tue, 20 Jun 2017 11:59:09 +0200 patrice.chotard at st.com wrote:
> >> From: Patrice Chotard <patrice.chotard@st.com>
> >>
> >> use array to save enabled clocks reference in order to
> >> disabled them in case of error during probe() or during
> >> driver removal.
> >>
> >> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> >> ---
> >> v7:	_ replace clk_count() by ofnode_count_phandle_with_args()
> >>
> >> v6:	_ none
> >>
> >> v5:	_ none
> >>
> >> v4:	_ use generic_phy_valid() before generic_phy_exit() call
> >>
> >> v3:	_ extract in this patch the CLOCK support add-on from previous patch 5
> >> 	_ keep enabled clocks reference in list in order to
> >> 	  disable clocks in error path or in .remove callback
> >>
> >> v2:	_ add error path management
> >> 	_ add .remove callback
> >>
> >>   drivers/usb/host/ohci-generic.c | 59 +++++++++++++++++++++++++++++++++++++++--
> >>   1 file changed, 57 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
> >> index f85738f..f76a1c2 100644
> >> --- a/drivers/usb/host/ohci-generic.c
> >> +++ b/drivers/usb/host/ohci-generic.c
> >> @@ -5,27 +5,83 @@
> >>    */
> >>   
> >>   #include <common.h>
> >> +#include <clk.h>
> >>   #include <dm.h>
> >>   #include "ohci.h"
> >>   
> >> +#include <dm/ofnode.h>
> >> +
> >>   #if !defined(CONFIG_USB_OHCI_NEW)
> >>   # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
> >>   #endif
> >>   
> >>   struct generic_ohci {
> >>   	ohci_t ohci;
> >> +	struct clk *clocks;
> >> +	int clock_count;
> >>   };
> >>   
> >>   static int ohci_usb_probe(struct udevice *dev)
> >>   {
> >>   	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
> >> +	struct generic_ohci *priv = dev_get_priv(dev);
> >> +	int i, err, ret, clock_nb;
> >> +
> >> +	err = 0;
> >> +	priv->clock_count = 0;
> >> +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
> >> +						  "#clock-cells");
> >> +	if (clock_nb > 0) {
> >> +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
> >> +					    GFP_KERNEL);
> >> +		if (!priv->clocks) {
> >> +			error("Can't allocate resource\n");
> >> +			return -ENOMEM;
> >> +		}
> >> +
> >> +		for (i = 0; i < clock_nb; i++) {
> >> +			err = clk_get_by_index(dev, i, &priv->clocks[i]);
> >> +			if (err < 0)
> >> +				break;
> >> +
> >> +			priv->clock_count++;
> >> +
> >> +			if (clk_enable(&priv->clocks[i])) {
> >> +				error("failed to enable clock %d\n", i);
> >> +				clk_free(&priv->clocks[i]);
> >> +				goto clk_err;
> >> +			}
> >> +			clk_free(&priv->clocks[i]);
> >>
> > You free the freshly allocated clock right away and use it lateron?
> 
> clk_free() didn't free clock resources, it's the opposite of 
> clk_request(), see comments in include.clk.h
> 
But as long as you are working with some resource (whether it's a
clock, a gpio, a 'reset' or whatever), you should keep it requested and
free it only after you relinquished using it.
Otherwise the object you are using may be destroyed underneath your
feet.


Lothar Waßmann

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

* [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support
  2017-06-21  7:56       ` Lothar Waßmann
@ 2017-06-21  8:36         ` Patrice CHOTARD
  0 siblings, 0 replies; 24+ messages in thread
From: Patrice CHOTARD @ 2017-06-21  8:36 UTC (permalink / raw)
  To: u-boot

Hi Lothar

On 06/21/2017 09:56 AM, Lothar Waßmann wrote:
> Hi,
> 
> On Tue, 20 Jun 2017 12:56:48 +0000 Patrice CHOTARD wrote:
>> Hi Lothar
>>
>> On 06/20/2017 02:06 PM, Lothar Waßmann wrote:
>>> Hi,
>>>
>>> On Tue, 20 Jun 2017 11:59:09 +0200 patrice.chotard at st.com wrote:
>>>> From: Patrice Chotard <patrice.chotard@st.com>
>>>>
>>>> use array to save enabled clocks reference in order to
>>>> disabled them in case of error during probe() or during
>>>> driver removal.
>>>>
>>>> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
>>>> ---
>>>> v7:	_ replace clk_count() by ofnode_count_phandle_with_args()
>>>>
>>>> v6:	_ none
>>>>
>>>> v5:	_ none
>>>>
>>>> v4:	_ use generic_phy_valid() before generic_phy_exit() call
>>>>
>>>> v3:	_ extract in this patch the CLOCK support add-on from previous patch 5
>>>> 	_ keep enabled clocks reference in list in order to
>>>> 	  disable clocks in error path or in .remove callback
>>>>
>>>> v2:	_ add error path management
>>>> 	_ add .remove callback
>>>>
>>>>    drivers/usb/host/ohci-generic.c | 59 +++++++++++++++++++++++++++++++++++++++--
>>>>    1 file changed, 57 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
>>>> index f85738f..f76a1c2 100644
>>>> --- a/drivers/usb/host/ohci-generic.c
>>>> +++ b/drivers/usb/host/ohci-generic.c
>>>> @@ -5,27 +5,83 @@
>>>>     */
>>>>    
>>>>    #include <common.h>
>>>> +#include <clk.h>
>>>>    #include <dm.h>
>>>>    #include "ohci.h"
>>>>    
>>>> +#include <dm/ofnode.h>
>>>> +
>>>>    #if !defined(CONFIG_USB_OHCI_NEW)
>>>>    # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
>>>>    #endif
>>>>    
>>>>    struct generic_ohci {
>>>>    	ohci_t ohci;
>>>> +	struct clk *clocks;
>>>> +	int clock_count;
>>>>    };
>>>>    
>>>>    static int ohci_usb_probe(struct udevice *dev)
>>>>    {
>>>>    	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
>>>> +	struct generic_ohci *priv = dev_get_priv(dev);
>>>> +	int i, err, ret, clock_nb;
>>>> +
>>>> +	err = 0;
>>>> +	priv->clock_count = 0;
>>>> +	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
>>>> +						  "#clock-cells");
>>>> +	if (clock_nb > 0) {
>>>> +		priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
>>>> +					    GFP_KERNEL);
>>>> +		if (!priv->clocks) {
>>>> +			error("Can't allocate resource\n");
>>>> +			return -ENOMEM;
>>>> +		}
>>>> +
>>>> +		for (i = 0; i < clock_nb; i++) {
>>>> +			err = clk_get_by_index(dev, i, &priv->clocks[i]);
>>>> +			if (err < 0)
>>>> +				break;
>>>> +
>>>> +			priv->clock_count++;
>>>> +
>>>> +			if (clk_enable(&priv->clocks[i])) {
>>>> +				error("failed to enable clock %d\n", i);
>>>> +				clk_free(&priv->clocks[i]);
>>>> +				goto clk_err;
>>>> +			}
>>>> +			clk_free(&priv->clocks[i]);
>>>>
>>> You free the freshly allocated clock right away and use it lateron?
>>
>> clk_free() didn't free clock resources, it's the opposite of
>> clk_request(), see comments in include.clk.h
>>
> But as long as you are working with some resource (whether it's a
> clock, a gpio, a 'reset' or whatever), you should keep it requested and
> free it only after you relinquished using it.
> Otherwise the object you are using may be destroyed underneath your
> feet.

Ah yes, my bad, i focused on the clk_free() inside the previous statement.

I will fix it

Thanks
> 
> 
> Lothar Waßmann
> 

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

end of thread, other threads:[~2017-06-21  8:36 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-20  9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
2017-06-20  9:59 ` [U-Boot] [PATCH v7 01/10] reset: add reset_request() patrice.chotard at st.com
2017-06-20  9:59 ` [U-Boot] [PATCH v7 02/10] reset: add reset_assert_all() patrice.chotard at st.com
2017-06-20  9:59 ` [U-Boot] [PATCH v7 03/10] clk: add clk_disable_all() patrice.chotard at st.com
2017-06-20 12:11   ` Lothar Waßmann
2017-06-20 12:40     ` Patrice CHOTARD
2017-06-20  9:59 ` [U-Boot] [PATCH v7 04/10] dm: core: add ofnode_count_phandle_with_args() patrice.chotard at st.com
2017-06-20 18:26   ` Simon Glass
2017-06-20  9:59 ` [U-Boot] [PATCH v7 05/10] usb: host: ehci-generic: replace printf() by error() patrice.chotard at st.com
2017-06-20  9:59 ` [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback patrice.chotard at st.com
2017-06-20 10:09   ` Marek Vasut
2017-06-20 11:26     ` Lothar Waßmann
2017-06-20 12:22     ` Patrice CHOTARD
2017-06-20 11:32   ` Lothar Waßmann
2017-06-20 12:28     ` Patrice CHOTARD
2017-06-20  9:59 ` [U-Boot] [PATCH v7 07/10] usb: host: ehci-generic: add generic PHY support patrice.chotard at st.com
2017-06-20  9:59 ` [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support patrice.chotard at st.com
2017-06-20 12:06   ` Lothar Waßmann
2017-06-20 12:56     ` Patrice CHOTARD
2017-06-21  7:56       ` Lothar Waßmann
2017-06-21  8:36         ` Patrice CHOTARD
2017-06-20  9:59 ` [U-Boot] [PATCH v7 09/10] usb: host: ohci-generic: add RESET support patrice.chotard at st.com
2017-06-20 18:26   ` Simon Glass
2017-06-20  9:59 ` [U-Boot] [PATCH v7 10/10] usb: host: ohci-generic: add generic PHY support patrice.chotard at st.com

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.