linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/4] reset: APIs to manage a list of resets
@ 2017-06-19 14:34 Philipp Zabel
  2017-06-19 14:34 ` [PATCH v6 1/4] reset: Add APIs to manage array " Philipp Zabel
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Philipp Zabel @ 2017-06-19 14:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Vivek Gautam, Jon Hunter, Felipe Balbi, Greg Kroah-Hartman,
	Thierry Reding, linux-tegra, linux-usb, linux-arm-msm,
	Philipp Zabel

A set of patches to allow consumers to get and de/assert or trigger
a number of resets at the same time. A patch on top of Vivek's original
API extension is added to hide the reset_control_array behind a struct
reset_control so that the consumer doesn't have to care about the difference
between a singular reset control and a reset control controlling an array
of resets, except when requesting it.

This series also contains reset controls patches for dwc3-of-simple
and tegra pmc drivers.
A small patch is added in this series to correctly re-order the
resource handling in dwc3_of_simple_remove().

The series is tested on torvald's master branch the device tree
patches to enable usb on db820c.

Changes since v5:
 - Fixed devm/of_reset_control_array_get stub return values in the
   "reset: hide reset control arrays behind struct reset_control" patch.
 - Merged "reset: hide reset control arrays behind struct reset_control" patch
   into "reset: Add APIs to manage array of resets" patch, to avoid adding
   new API functions in one patch that are removed in the other.
 - Updated commit message of "soc/tegra: pmc: Use the new reset APIs to manage
   reset controllers" patch.
 - Dropped already merged "reset: use kref for reference counting" patch.

Changes since v4:
 - Added a patch to hide reset control arrays behind struct reset_control
   and adapted the consumer patches. This could be merged with the reset
   array API patch if we think this is a good idea.

Changes since v3:
 - Squashed of_reset_control_get_count() patch in the second patch that
   adds the reset control array APIs.
 - The error path after getting count through of_reset_control_get_count()
   now returns NULL pointer in case when 'optional' flag is true.
 - Added code in reset_control_array_assert() to deassert the
   already asserted resets in the error case.
 - Using of_reset_control_array_get_optional_exclusive() in dwc3 patch
   to request the reset control array.
 - Added a patch to fix the order in which resources are handled in
   dwc3_of_simple_remove() path.
 - Added tegra_powergate->reset to take care of single reset control
   passed from the client drivers.

Changes since v2:
 - Addressed comments to make APIs inline with gpiod API.
 - Moved number of reset controls in 'struct reset_control_array'
   so that the footprint is reduced.
 - of_reset_control_array_get() and devm_reset_control_array_get()
   now return pointer to the newly created reset control array.
 - Added comments to mention that the reset control array APIs don't
   guarantee any particular order when handling the reset controls.
 - Dropped 'name' from reset_control_array' since the interface is meant
   for a bunch of anonymous resets that can all be asserted or deasserted
   in arbitrary order.
 - Fixed returns for APIs reported by kbuild.
 - Fixed 'for' clause guards reported by kbuild.

Changes since v1:
 - Addressed comment for error handling in of_reset_control_get_count()
 - Added patch to manage reset controller array.
 - Rebased dwc3-of-simple changes based on the new set of APIs
   for reset control array.
 - Added a patch for soc/tegra/pmc driver to use the new set of
   reset control array APIs.

Vivek Gautam (4):
  reset: Add APIs to manage array of resets
  usb: dwc3: of-simple: Re-order resource handling in remove
  usb: dwc3: of-simple: Add support to get resets for the device
  soc/tegra: pmc: Use the new reset APIs to manage reset controllers

 drivers/reset/core.c              | 211 +++++++++++++++++++++++++++++++++++++-
 drivers/soc/tegra/pmc.c           |  82 ++++-----------
 drivers/usb/dwc3/dwc3-of-simple.c |  29 +++++-
 include/linux/reset.h             |  73 +++++++++++++
 4 files changed, 329 insertions(+), 66 deletions(-)

-- 
2.11.0

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

* [PATCH v6 1/4] reset: Add APIs to manage array of resets
  2017-06-19 14:34 [PATCH v6 0/4] reset: APIs to manage a list of resets Philipp Zabel
@ 2017-06-19 14:34 ` Philipp Zabel
  2017-06-19 19:42   ` kbuild test robot
  2017-06-19 20:21   ` kbuild test robot
  2017-06-19 14:34 ` [PATCH v6 2/4] usb: dwc3: of-simple: Re-order resource handling in remove Philipp Zabel
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 9+ messages in thread
From: Philipp Zabel @ 2017-06-19 14:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Vivek Gautam, Jon Hunter, Felipe Balbi, Greg Kroah-Hartman,
	Thierry Reding, linux-tegra, linux-usb, linux-arm-msm,
	Philipp Zabel

From: Vivek Gautam <vivek.gautam@codeaurora.org>

Many devices may want to request a bunch of resets and control them. So
it's better to manage them as an array. Add APIs to _get() an array of
reset_control, reusing the _assert(), _deassert(), and _reset() APIs for
single reset controls. Since reset controls already may control multiple
reset lines with a single hardware bit, from the user perspective, reset
control arrays are not at all different from single reset controls.
Note that these APIs don't guarantee that the reset lines managed in the
array are handled in any particular order.

Cc: Felipe Balbi <balbi@kernel.org>
Cc: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
[p.zabel@pengutronix.de: changed API to hide reset control arrays behind
 struct reset_control]
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
Changes since v5:
 - Merged "reset: hide reset control arrays behind struct reset_control" patch
   into this one, fixed devm/of_reset_control_array_get stub return values in
   the new patch.
---
 drivers/reset/core.c  | 211 +++++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/reset.h |  73 +++++++++++++++++
 2 files changed, 283 insertions(+), 1 deletion(-)

diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 0090784ff4105..c8fb4426b218a 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -43,11 +43,24 @@ struct reset_control {
 	unsigned int id;
 	struct kref refcnt;
 	bool shared;
+	bool array;
 	atomic_t deassert_count;
 	atomic_t triggered_count;
 };
 
 /**
+ * struct reset_control_array - an array of reset controls
+ * @base: reset control for compatibility with reset control API functions
+ * @num_rstcs: number of reset controls
+ * @rstc: array of reset controls
+ */
+struct reset_control_array {
+	struct reset_control base;
+	unsigned int num_rstcs;
+	struct reset_control *rstc[];
+};
+
+/**
  * of_reset_simple_xlate - translate reset_spec to the reset line number
  * @rcdev: a pointer to the reset controller device
  * @reset_spec: reset line specifier as found in the device tree
@@ -135,6 +148,65 @@ int devm_reset_controller_register(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_reset_controller_register);
 
+static inline struct reset_control_array *
+rstc_to_array(struct reset_control *rstc) {
+	return container_of(rstc, struct reset_control_array, base);
+}
+
+static int reset_control_array_reset(struct reset_control_array *resets)
+{
+	int ret, i;
+
+	for (i = 0; i < resets->num_rstcs; i++) {
+		ret = reset_control_reset(resets->rstc[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int reset_control_array_assert(struct reset_control_array *resets)
+{
+	int ret, i;
+
+	for (i = 0; i < resets->num_rstcs; i++) {
+		ret = reset_control_assert(resets->rstc[i]);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	while (i--)
+		reset_control_deassert(resets->rstc[i]);
+	return ret;
+}
+
+static int reset_control_array_deassert(struct reset_control_array *resets)
+{
+	int ret, i;
+
+	for (i = 0; i < resets->num_rstcs; i++) {
+		ret = reset_control_deassert(resets->rstc[i]);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	while (i--)
+		reset_control_assert(resets->rstc[i]);
+	return ret;
+}
+
+static inline bool reset_control_is_array(struct reset_control *rstc)
+{
+	return rstc->array;
+}
+
 /**
  * reset_control_reset - reset the controlled device
  * @rstc: reset controller
@@ -158,6 +230,9 @@ int reset_control_reset(struct reset_control *rstc)
 	if (WARN_ON(IS_ERR(rstc)))
 		return -EINVAL;
 
+	if (reset_control_is_array(rstc))
+		return reset_control_array_reset(rstc_to_array(rstc));
+
 	if (!rstc->rcdev->ops->reset)
 		return -ENOTSUPP;
 
@@ -202,6 +277,9 @@ int reset_control_assert(struct reset_control *rstc)
 	if (WARN_ON(IS_ERR(rstc)))
 		return -EINVAL;
 
+	if (reset_control_is_array(rstc))
+		return reset_control_array_assert(rstc_to_array(rstc));
+
 	if (!rstc->rcdev->ops->assert)
 		return -ENOTSUPP;
 
@@ -240,6 +318,9 @@ int reset_control_deassert(struct reset_control *rstc)
 	if (WARN_ON(IS_ERR(rstc)))
 		return -EINVAL;
 
+	if (reset_control_is_array(rstc))
+		return reset_control_array_deassert(rstc_to_array(rstc));
+
 	if (!rstc->rcdev->ops->deassert)
 		return -ENOTSUPP;
 
@@ -266,7 +347,7 @@ int reset_control_status(struct reset_control *rstc)
 	if (!rstc)
 		return 0;
 
-	if (WARN_ON(IS_ERR(rstc)))
+	if (WARN_ON(IS_ERR(rstc)) || reset_control_is_array(rstc))
 		return -EINVAL;
 
 	if (rstc->rcdev->ops->status)
@@ -404,6 +485,16 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id,
 }
 EXPORT_SYMBOL_GPL(__reset_control_get);
 
+static void reset_control_array_put(struct reset_control_array *resets)
+{
+	int i;
+
+	mutex_lock(&reset_list_mutex);
+	for (i = 0; i < resets->num_rstcs; i++)
+		__reset_control_put_internal(resets->rstc[i]);
+	mutex_unlock(&reset_list_mutex);
+}
+
 /**
  * reset_control_put - free the reset controller
  * @rstc: reset controller
@@ -413,6 +504,11 @@ void reset_control_put(struct reset_control *rstc)
 	if (IS_ERR_OR_NULL(rstc))
 		return;
 
+	if (reset_control_is_array(rstc)) {
+		reset_control_array_put(rstc_to_array(rstc));
+		return;
+	}
+
 	mutex_lock(&reset_list_mutex);
 	__reset_control_put_internal(rstc);
 	mutex_unlock(&reset_list_mutex);
@@ -472,3 +568,116 @@ int device_reset(struct device *dev)
 	return ret;
 }
 EXPORT_SYMBOL_GPL(device_reset);
+
+/**
+ * APIs to manage an array of reset controls.
+ */
+/**
+ * of_reset_control_get_count - Count number of resets available with a device
+ *
+ * @node: device node that contains 'resets'.
+ *
+ * Returns positive reset count on success, or error number on failure and
+ * on count being zero.
+ */
+static int of_reset_control_get_count(struct device_node *node)
+{
+	int count;
+
+	if (!node)
+		return -EINVAL;
+
+	count = of_count_phandle_with_args(node, "resets", "#reset-cells");
+	if (count == 0)
+		count = -ENOENT;
+
+	return count;
+}
+
+/**
+ * of_reset_control_array_get - Get a list of reset controls using
+ *				device node.
+ *
+ * @np: device node for the device that requests the reset controls array
+ * @shared: whether reset controls are shared or not
+ * @optional: whether it is optional to get the reset controls
+ *
+ * Returns pointer to allocated reset_control_array on success or
+ * error on failure
+ */
+struct reset_control *
+of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
+{
+	struct reset_control_array *resets;
+	struct reset_control *rstc;
+	int num, i;
+
+	num = of_reset_control_get_count(np);
+	if (num < 0)
+		return optional ? NULL : ERR_PTR(num);
+
+	resets = kzalloc(sizeof(*resets) + sizeof(resets->rstc[0]) * num,
+			 GFP_KERNEL);
+	if (!resets)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < num; i++) {
+		rstc = __of_reset_control_get(np, NULL, i, shared, optional);
+		if (IS_ERR(rstc))
+			goto err_rst;
+		resets->rstc[i] = rstc;
+	}
+	resets->num_rstcs = num;
+	resets->base.array = true;
+
+	return &resets->base;
+
+err_rst:
+	mutex_lock(&reset_list_mutex);
+	while (--i >= 0)
+		__reset_control_put_internal(resets->rstc[i]);
+	mutex_unlock(&reset_list_mutex);
+
+	kfree(resets);
+
+	return rstc;
+}
+EXPORT_SYMBOL_GPL(of_reset_control_array_get);
+
+/**
+ * devm_reset_control_array_get - Resource managed reset control array get
+ *
+ * @dev: device that requests the list of reset controls
+ * @shared: whether reset controls are shared or not
+ * @optional: whether it is optional to get the reset controls
+ *
+ * The reset control array APIs are intended for a list of resets
+ * that just have to be asserted or deasserted, without any
+ * requirements on the order.
+ *
+ * Returns pointer to allocated reset_control_array on success or
+ * error on failure
+ */
+struct reset_control *
+devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
+{
+	struct reset_control **devres;
+	struct reset_control *rstc;
+
+	devres = devres_alloc(devm_reset_control_release, sizeof(*devres),
+			      GFP_KERNEL);
+	if (!devres)
+		return ERR_PTR(-ENOMEM);
+
+	rstc = of_reset_control_array_get(dev->of_node, shared, optional);
+	if (IS_ERR(rstc)) {
+		devres_free(devres);
+		return rstc;
+	}
+
+	*devres = rstc;
+	devres_add(dev, devres);
+
+	return rstc;
+}
+EXPORT_SYMBOL_GPL(devm_reset_control_array_get);
diff --git a/include/linux/reset.h b/include/linux/reset.h
index 13d8681210d54..6368029aa54fe 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -25,6 +25,11 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
 
 int __must_check device_reset(struct device *dev);
 
+struct reset_control *devm_reset_control_array_get(struct device *dev,
+						   bool shared, bool optional);
+struct reset_control *of_reset_control_array_get(struct device_node *np,
+						 bool shared, bool optional);
+
 static inline int device_reset_optional(struct device *dev)
 {
 	return device_reset(dev);
@@ -89,6 +94,23 @@ static inline struct reset_control *__devm_reset_control_get(
 	return optional ? NULL : ERR_PTR(-ENOTSUPP);
 }
 
+static inline struct reset_control *
+devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
+{
+	return optional ? NULL : ERR_PTR(-ENOTSUPP);
+}
+
+static inline struct reset_control *
+of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
+{
+	return optional ? NULL : ERR_PTR(-ENOTSUPP);
+}
+
+static inline
+void reset_control_array_put(struct reset_control_array *resets)
+{
+}
+
 #endif /* CONFIG_RESET_CONTROLLER */
 
 /**
@@ -374,4 +396,55 @@ static inline struct reset_control *devm_reset_control_get_by_index(
 {
 	return devm_reset_control_get_exclusive_by_index(dev, index);
 }
+
+/*
+ * APIs to manage a list of reset controllers
+ */
+static inline struct reset_control *
+devm_reset_control_array_get_exclusive(struct device *dev)
+{
+	return devm_reset_control_array_get(dev, false, false);
+}
+
+static inline struct reset_control *
+devm_reset_control_array_get_shared(struct device *dev)
+{
+	return devm_reset_control_array_get(dev, true, false);
+}
+
+static inline struct reset_control *
+devm_reset_control_array_get_optional_exclusive(struct device *dev)
+{
+	return devm_reset_control_array_get(dev, false, true);
+}
+
+static inline struct reset_control *
+devm_reset_control_array_get_optional_shared(struct device *dev)
+{
+	return devm_reset_control_array_get(dev, true, true);
+}
+
+static inline struct reset_control *
+of_reset_control_array_get_exclusive(struct device_node *node)
+{
+	return of_reset_control_array_get(node, false, false);
+}
+
+static inline struct reset_control *
+of_reset_control_array_get_shared(struct device_node *node)
+{
+	return of_reset_control_array_get(node, true, false);
+}
+
+static inline struct reset_control *
+of_reset_control_array_get_optional_exclusive(struct device_node *node)
+{
+	return of_reset_control_array_get(node, false, true);
+}
+
+static inline struct reset_control *
+of_reset_control_array_get_optional_shared(struct device_node *node)
+{
+	return of_reset_control_array_get(node, true, true);
+}
 #endif
-- 
2.11.0

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

* [PATCH v6 2/4] usb: dwc3: of-simple: Re-order resource handling in remove
  2017-06-19 14:34 [PATCH v6 0/4] reset: APIs to manage a list of resets Philipp Zabel
  2017-06-19 14:34 ` [PATCH v6 1/4] reset: Add APIs to manage array " Philipp Zabel
@ 2017-06-19 14:34 ` Philipp Zabel
  2017-06-19 14:34 ` [PATCH v6 3/4] usb: dwc3: of-simple: Add support to get resets for the device Philipp Zabel
  2017-06-19 14:34 ` [PATCH v6 4/4] soc/tegra: pmc: Use the new reset APIs to manage reset controllers Philipp Zabel
  3 siblings, 0 replies; 9+ messages in thread
From: Philipp Zabel @ 2017-06-19 14:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Vivek Gautam, Jon Hunter, Felipe Balbi, Greg Kroah-Hartman,
	Thierry Reding, linux-tegra, linux-usb, linux-arm-msm

From: Vivek Gautam <vivek.gautam@codeaurora.org>

Move clock handling after of_platform_depopulate to achieve
a sequence that is reverse of the probe sequence.

Cc: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
---
No changes since v5.
---
 drivers/usb/dwc3/dwc3-of-simple.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index fe414e7a9c78c..a9bac09d3750d 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -123,13 +123,13 @@ static int dwc3_of_simple_remove(struct platform_device *pdev)
 	struct device		*dev = &pdev->dev;
 	int			i;
 
+	of_platform_depopulate(dev);
+
 	for (i = 0; i < simple->num_clocks; i++) {
 		clk_disable_unprepare(simple->clks[i]);
 		clk_put(simple->clks[i]);
 	}
 
-	of_platform_depopulate(dev);
-
 	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
 
-- 
2.11.0

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

* [PATCH v6 3/4] usb: dwc3: of-simple: Add support to get resets for the device
  2017-06-19 14:34 [PATCH v6 0/4] reset: APIs to manage a list of resets Philipp Zabel
  2017-06-19 14:34 ` [PATCH v6 1/4] reset: Add APIs to manage array " Philipp Zabel
  2017-06-19 14:34 ` [PATCH v6 2/4] usb: dwc3: of-simple: Re-order resource handling in remove Philipp Zabel
@ 2017-06-19 14:34 ` Philipp Zabel
  2017-06-19 14:34 ` [PATCH v6 4/4] soc/tegra: pmc: Use the new reset APIs to manage reset controllers Philipp Zabel
  3 siblings, 0 replies; 9+ messages in thread
From: Philipp Zabel @ 2017-06-19 14:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Vivek Gautam, Jon Hunter, Felipe Balbi, Greg Kroah-Hartman,
	Thierry Reding, linux-tegra, linux-usb, linux-arm-msm,
	Philipp Zabel

From: Vivek Gautam <vivek.gautam@codeaurora.org>

Add support to get a list of resets available for the device.
These resets must be kept de-asserted until the device is
in use.

Cc: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
[p.zabel@pengutronix.de: switch to hidden reset control array]
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
No changes since v5.
---
 drivers/usb/dwc3/dwc3-of-simple.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index a9bac09d3750d..23d2221bde9df 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -29,11 +29,13 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
+#include <linux/reset.h>
 
 struct dwc3_of_simple {
 	struct device		*dev;
 	struct clk		**clks;
 	int			num_clocks;
+	struct reset_control	*resets;
 };
 
 static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
@@ -96,9 +98,20 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, simple);
 	simple->dev = dev;
 
+	simple->resets = of_reset_control_array_get_optional_exclusive(np);
+	if (IS_ERR(simple->resets)) {
+		ret = PTR_ERR(simple->resets);
+		dev_err(dev, "failed to get device resets, err=%d\n", ret);
+		return ret;
+	}
+
+	ret = reset_control_deassert(simple->resets);
+	if (ret)
+		goto err_resetc_put;
+
 	ret = dwc3_of_simple_clk_init(simple, of_clk_get_parent_count(np));
 	if (ret)
-		return ret;
+		goto err_resetc_assert;
 
 	ret = of_platform_populate(np, NULL, NULL, dev);
 	if (ret) {
@@ -107,7 +120,7 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
 			clk_put(simple->clks[i]);
 		}
 
-		return ret;
+		goto err_resetc_assert;
 	}
 
 	pm_runtime_set_active(dev);
@@ -115,6 +128,13 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
 	pm_runtime_get_sync(dev);
 
 	return 0;
+
+err_resetc_assert:
+	reset_control_assert(simple->resets);
+
+err_resetc_put:
+	reset_control_put(simple->resets);
+	return ret;
 }
 
 static int dwc3_of_simple_remove(struct platform_device *pdev)
@@ -130,6 +150,9 @@ static int dwc3_of_simple_remove(struct platform_device *pdev)
 		clk_put(simple->clks[i]);
 	}
 
+	reset_control_assert(simple->resets);
+	reset_control_put(simple->resets);
+
 	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
 
-- 
2.11.0

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

* [PATCH v6 4/4] soc/tegra: pmc: Use the new reset APIs to manage reset controllers
  2017-06-19 14:34 [PATCH v6 0/4] reset: APIs to manage a list of resets Philipp Zabel
                   ` (2 preceding siblings ...)
  2017-06-19 14:34 ` [PATCH v6 3/4] usb: dwc3: of-simple: Add support to get resets for the device Philipp Zabel
@ 2017-06-19 14:34 ` Philipp Zabel
  2018-02-13 13:54   ` Jon Hunter
  3 siblings, 1 reply; 9+ messages in thread
From: Philipp Zabel @ 2017-06-19 14:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Vivek Gautam, Jon Hunter, Felipe Balbi, Greg Kroah-Hartman,
	Thierry Reding, linux-tegra, linux-usb, linux-arm-msm,
	Philipp Zabel

From: Vivek Gautam <vivek.gautam@codeaurora.org>

Make use of of_reset_control_array_get_exclusive() to manage
an array of reset controllers available with the device.

Cc: Jon Hunter <jonathanh@nvidia.com>
Cc: Thierry Reding <treding@nvidia.com>
Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
[p.zabel@pengutronix.de: switch to hidden reset control array]
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
Changes since v5: updated commit message, added missing SoB
---
 drivers/soc/tegra/pmc.c | 82 ++++++++++++-------------------------------------
 1 file changed, 20 insertions(+), 62 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index e233dd5dcab3d..749b218147a19 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -124,8 +124,7 @@ struct tegra_powergate {
 	unsigned int id;
 	struct clk **clks;
 	unsigned int num_clks;
-	struct reset_control **resets;
-	unsigned int num_resets;
+	struct reset_control *reset;
 };
 
 struct tegra_io_pad_soc {
@@ -348,32 +347,14 @@ static int tegra_powergate_enable_clocks(struct tegra_powergate *pg)
 	return err;
 }
 
-static int tegra_powergate_reset_assert(struct tegra_powergate *pg)
+static inline int tegra_powergate_reset_assert(struct tegra_powergate *pg)
 {
-	unsigned int i;
-	int err;
-
-	for (i = 0; i < pg->num_resets; i++) {
-		err = reset_control_assert(pg->resets[i]);
-		if (err)
-			return err;
-	}
-
-	return 0;
+	return reset_control_assert(pg->reset);
 }
 
-static int tegra_powergate_reset_deassert(struct tegra_powergate *pg)
+static inline int tegra_powergate_reset_deassert(struct tegra_powergate *pg)
 {
-	unsigned int i;
-	int err;
-
-	for (i = 0; i < pg->num_resets; i++) {
-		err = reset_control_deassert(pg->resets[i]);
-		if (err)
-			return err;
-	}
-
-	return 0;
+	return reset_control_deassert(pg->reset);
 }
 
 static int tegra_powergate_power_up(struct tegra_powergate *pg,
@@ -566,8 +547,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
 	pg.id = id;
 	pg.clks = &clk;
 	pg.num_clks = 1;
-	pg.resets = &rst;
-	pg.num_resets = 1;
+	pg.reset = IS_ERR(rst) ? NULL : rst;
 
 	err = tegra_powergate_power_up(&pg, false);
 	if (err)
@@ -755,45 +735,26 @@ static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
 static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
 					 struct device_node *np, bool off)
 {
-	struct reset_control *rst;
-	unsigned int i, count;
 	int err;
 
-	count = of_count_phandle_with_args(np, "resets", "#reset-cells");
-	if (count == 0)
-		return -ENODEV;
-
-	pg->resets = kcalloc(count, sizeof(rst), GFP_KERNEL);
-	if (!pg->resets)
-		return -ENOMEM;
-
-	for (i = 0; i < count; i++) {
-		pg->resets[i] = of_reset_control_get_by_index(np, i);
-		if (IS_ERR(pg->resets[i])) {
-			err = PTR_ERR(pg->resets[i]);
-			goto error;
-		}
-
-		if (off)
-			err = reset_control_assert(pg->resets[i]);
-		else
-			err = reset_control_deassert(pg->resets[i]);
-
-		if (err) {
-			reset_control_put(pg->resets[i]);
-			goto error;
-		}
+	pg->reset = of_reset_control_array_get_exclusive(np);
+	if (IS_ERR(pg->reset)) {
+		pr_err("failed to get device resets\n");
+		return PTR_ERR(pg->reset);
 	}
 
-	pg->num_resets = count;
+	if (off)
+		err = reset_control_assert(pg->reset);
+	else
+		err = reset_control_deassert(pg->reset);
 
-	return 0;
+	if (err)
+		goto put_reset;
 
-error:
-	while (i--)
-		reset_control_put(pg->resets[i]);
+	return 0;
 
-	kfree(pg->resets);
+put_reset:
+	reset_control_put(pg->reset);
 
 	return err;
 }
@@ -885,10 +846,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
 	pm_genpd_remove(&pg->genpd);
 
 remove_resets:
-	while (pg->num_resets--)
-		reset_control_put(pg->resets[pg->num_resets]);
-
-	kfree(pg->resets);
+	reset_control_put(pg->reset);
 
 remove_clks:
 	while (pg->num_clks--)
-- 
2.11.0

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

* Re: [PATCH v6 1/4] reset: Add APIs to manage array of resets
  2017-06-19 14:34 ` [PATCH v6 1/4] reset: Add APIs to manage array " Philipp Zabel
@ 2017-06-19 19:42   ` kbuild test robot
  2017-06-19 20:21   ` kbuild test robot
  1 sibling, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2017-06-19 19:42 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: kbuild-all, linux-kernel, Vivek Gautam, Jon Hunter, Felipe Balbi,
	Greg Kroah-Hartman, Thierry Reding, linux-tegra, linux-usb,
	linux-arm-msm, Philipp Zabel

[-- Attachment #1: Type: text/plain, Size: 2636 bytes --]

Hi Vivek,

[auto build test WARNING on pza/reset/next]
[also build test WARNING on v4.12-rc6 next-20170619]
[cannot apply to balbi-usb/next]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Philipp-Zabel/reset-Add-APIs-to-manage-array-of-resets/20170620-021320
base:   git://git.pengutronix.de/git/pza/linux reset/next
config: x86_64-allyesdebian (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   In file included from drivers/gpu/drm/nouveau/include/nvif/os.h:28:0,
                    from drivers/gpu/drm/nouveau/include/nvkm/core/os.h:3,
                    from drivers/gpu/drm/nouveau/include/nvkm/core/event.h:3,
                    from drivers/gpu/drm/nouveau/include/nvkm/core/device.h:3,
                    from drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h:3,
                    from drivers/gpu/drm/nouveau/include/nvkm/core/engine.h:4,
                    from drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h:4,
                    from drivers/gpu/drm/nouveau/nvkm/falcon/priv.h:3,
                    from drivers/gpu/drm/nouveau/nvkm/falcon/v1.c:22:
>> include/linux/reset.h:110:37: warning: 'struct reset_control_array' declared inside parameter list will not be visible outside of this definition or declaration
    void reset_control_array_put(struct reset_control_array *resets)
                                        ^~~~~~~~~~~~~~~~~~~

vim +110 include/linux/reset.h

    94		return optional ? NULL : ERR_PTR(-ENOTSUPP);
    95	}
    96	
    97	static inline struct reset_control *
    98	devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
    99	{
   100		return optional ? NULL : ERR_PTR(-ENOTSUPP);
   101	}
   102	
   103	static inline struct reset_control *
   104	of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
   105	{
   106		return optional ? NULL : ERR_PTR(-ENOTSUPP);
   107	}
   108	
   109	static inline
 > 110	void reset_control_array_put(struct reset_control_array *resets)
   111	{
   112	}
   113	
   114	#endif /* CONFIG_RESET_CONTROLLER */
   115	
   116	/**
   117	 * reset_control_get_exclusive - Lookup and obtain an exclusive reference
   118	 *                               to a reset controller.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 38867 bytes --]

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

* Re: [PATCH v6 1/4] reset: Add APIs to manage array of resets
  2017-06-19 14:34 ` [PATCH v6 1/4] reset: Add APIs to manage array " Philipp Zabel
  2017-06-19 19:42   ` kbuild test robot
@ 2017-06-19 20:21   ` kbuild test robot
  2017-06-20  7:02     ` Philipp Zabel
  1 sibling, 1 reply; 9+ messages in thread
From: kbuild test robot @ 2017-06-19 20:21 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: kbuild-all, linux-kernel, Vivek Gautam, Jon Hunter, Felipe Balbi,
	Greg Kroah-Hartman, Thierry Reding, linux-tegra, linux-usb,
	linux-arm-msm, Philipp Zabel

[-- Attachment #1: Type: text/plain, Size: 2863 bytes --]

Hi Vivek,

[auto build test WARNING on pza/reset/next]
[also build test WARNING on v4.12-rc6 next-20170619]
[cannot apply to balbi-usb/next]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Philipp-Zabel/reset-Add-APIs-to-manage-array-of-resets/20170620-021320
base:   git://git.pengutronix.de/git/pza/linux reset/next
config: i386-randconfig-c0-06200218 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   In file included from drivers/gpu//drm/nouveau/include/nvif/os.h:28:0,
                    from drivers/gpu//drm/nouveau/include/nvkm/core/os.h:3,
                    from drivers/gpu//drm/nouveau/include/nvkm/core/event.h:3,
                    from drivers/gpu//drm/nouveau/include/nvkm/core/device.h:3,
                    from drivers/gpu//drm/nouveau/include/nvkm/core/subdev.h:3,
                    from drivers/gpu//drm/nouveau/include/nvkm/core/engine.h:4,
                    from drivers/gpu//drm/nouveau/include/nvkm/engine/fifo.h:3,
                    from drivers/gpu//drm/nouveau/nvkm/engine/fifo/priv.h:4,
                    from drivers/gpu//drm/nouveau/nvkm/engine/fifo/chan.h:4,
                    from drivers/gpu//drm/nouveau/nvkm/engine/fifo/channv50.h:4,
                    from drivers/gpu//drm/nouveau/nvkm/engine/fifo/chang84.c:24:
>> include/linux/reset.h:110:37: warning: 'struct reset_control_array' declared inside parameter list
    void reset_control_array_put(struct reset_control_array *resets)
                                        ^
>> include/linux/reset.h:110:37: warning: its scope is only this definition or declaration, which is probably not what you want

vim +110 include/linux/reset.h

    94		return optional ? NULL : ERR_PTR(-ENOTSUPP);
    95	}
    96	
    97	static inline struct reset_control *
    98	devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
    99	{
   100		return optional ? NULL : ERR_PTR(-ENOTSUPP);
   101	}
   102	
   103	static inline struct reset_control *
   104	of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
   105	{
   106		return optional ? NULL : ERR_PTR(-ENOTSUPP);
   107	}
   108	
   109	static inline
 > 110	void reset_control_array_put(struct reset_control_array *resets)
   111	{
   112	}
   113	
   114	#endif /* CONFIG_RESET_CONTROLLER */
   115	
   116	/**
   117	 * reset_control_get_exclusive - Lookup and obtain an exclusive reference
   118	 *                               to a reset controller.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 25302 bytes --]

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

* Re: [PATCH v6 1/4] reset: Add APIs to manage array of resets
  2017-06-19 20:21   ` kbuild test robot
@ 2017-06-20  7:02     ` Philipp Zabel
  0 siblings, 0 replies; 9+ messages in thread
From: Philipp Zabel @ 2017-06-20  7:02 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, linux-kernel, Vivek Gautam, Jon Hunter, Felipe Balbi,
	Greg Kroah-Hartman, Thierry Reding, linux-tegra, linux-usb,
	linux-arm-msm

On Tue, 2017-06-20 at 04:21 +0800, kbuild test robot wrote:
> Hi Vivek,
> 
> [auto build test WARNING on pza/reset/next]
> [also build test WARNING on v4.12-rc6 next-20170619]
> [cannot apply to balbi-usb/next]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Philipp-Zabel/reset-Add-APIs-to-manage-array-of-resets/20170620-021320
> base:   git://git.pengutronix.de/git/pza/linux reset/next
> config: i386-randconfig-c0-06200218 (attached as .config)
> compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386 
> 
> All warnings (new ones prefixed by >>):
> 
>    In file included from drivers/gpu//drm/nouveau/include/nvif/os.h:28:0,
>                     from drivers/gpu//drm/nouveau/include/nvkm/core/os.h:3,
>                     from drivers/gpu//drm/nouveau/include/nvkm/core/event.h:3,
>                     from drivers/gpu//drm/nouveau/include/nvkm/core/device.h:3,
>                     from drivers/gpu//drm/nouveau/include/nvkm/core/subdev.h:3,
>                     from drivers/gpu//drm/nouveau/include/nvkm/core/engine.h:4,
>                     from drivers/gpu//drm/nouveau/include/nvkm/engine/fifo.h:3,
>                     from drivers/gpu//drm/nouveau/nvkm/engine/fifo/priv.h:4,
>                     from drivers/gpu//drm/nouveau/nvkm/engine/fifo/chan.h:4,
>                     from drivers/gpu//drm/nouveau/nvkm/engine/fifo/channv50.h:4,
>                     from drivers/gpu//drm/nouveau/nvkm/engine/fifo/chang84.c:24:
> >> include/linux/reset.h:110:37: warning: 'struct reset_control_array' declared inside parameter list
>     void reset_control_array_put(struct reset_control_array *resets)
>                                         ^
> >> include/linux/reset.h:110:37: warning: its scope is only this definition or declaration, which is probably not what you want
> 
> vim +110 include/linux/reset.h
> 
>     94		return optional ? NULL : ERR_PTR(-ENOTSUPP);
>     95	}
>     96	
>     97	static inline struct reset_control *
>     98	devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
>     99	{
>    100		return optional ? NULL : ERR_PTR(-ENOTSUPP);
>    101	}
>    102	
>    103	static inline struct reset_control *
>    104	of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
>    105	{
>    106		return optional ? NULL : ERR_PTR(-ENOTSUPP);
>    107	}
>    108	
>    109	static inline
>  > 110	void reset_control_array_put(struct reset_control_array *resets)
>    111	{
>    112	}

reset_control_array_put is static now, I forgot to remove this stub.

regards
      * Philipp

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

* Re: [PATCH v6 4/4] soc/tegra: pmc: Use the new reset APIs to manage reset controllers
  2017-06-19 14:34 ` [PATCH v6 4/4] soc/tegra: pmc: Use the new reset APIs to manage reset controllers Philipp Zabel
@ 2018-02-13 13:54   ` Jon Hunter
  0 siblings, 0 replies; 9+ messages in thread
From: Jon Hunter @ 2018-02-13 13:54 UTC (permalink / raw)
  To: Philipp Zabel, linux-kernel
  Cc: Vivek Gautam, Felipe Balbi, Greg Kroah-Hartman, Thierry Reding,
	linux-tegra, linux-usb, linux-arm-msm



On 19/06/17 15:34, Philipp Zabel wrote:
> From: Vivek Gautam <vivek.gautam@codeaurora.org>
> 
> Make use of of_reset_control_array_get_exclusive() to manage
> an array of reset controllers available with the device.
> 
> Cc: Jon Hunter <jonathanh@nvidia.com>
> Cc: Thierry Reding <treding@nvidia.com>
> Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
> [p.zabel@pengutronix.de: switch to hidden reset control array]
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> ---
> Changes since v5: updated commit message, added missing SoB
> ---
>  drivers/soc/tegra/pmc.c | 82 ++++++++++++-------------------------------------
>  1 file changed, 20 insertions(+), 62 deletions(-)
> 
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index e233dd5dcab3d..749b218147a19 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -124,8 +124,7 @@ struct tegra_powergate {
>  	unsigned int id;
>  	struct clk **clks;
>  	unsigned int num_clks;
> -	struct reset_control **resets;
> -	unsigned int num_resets;
> +	struct reset_control *reset;
>  };
>  
>  struct tegra_io_pad_soc {
> @@ -348,32 +347,14 @@ static int tegra_powergate_enable_clocks(struct tegra_powergate *pg)
>  	return err;
>  }
>  
> -static int tegra_powergate_reset_assert(struct tegra_powergate *pg)
> +static inline int tegra_powergate_reset_assert(struct tegra_powergate *pg)
>  {
> -	unsigned int i;
> -	int err;
> -
> -	for (i = 0; i < pg->num_resets; i++) {
> -		err = reset_control_assert(pg->resets[i]);
> -		if (err)
> -			return err;
> -	}
> -
> -	return 0;
> +	return reset_control_assert(pg->reset);
>  }
>  
> -static int tegra_powergate_reset_deassert(struct tegra_powergate *pg)
> +static inline int tegra_powergate_reset_deassert(struct tegra_powergate *pg)
>  {
> -	unsigned int i;
> -	int err;
> -
> -	for (i = 0; i < pg->num_resets; i++) {
> -		err = reset_control_deassert(pg->resets[i]);
> -		if (err)
> -			return err;
> -	}
> -
> -	return 0;
> +	return reset_control_deassert(pg->reset);
>  }
>  
>  static int tegra_powergate_power_up(struct tegra_powergate *pg,
> @@ -566,8 +547,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
>  	pg.id = id;
>  	pg.clks = &clk;
>  	pg.num_clks = 1;
> -	pg.resets = &rst;
> -	pg.num_resets = 1;
> +	pg.reset = IS_ERR(rst) ? NULL : rst;
>  
>  	err = tegra_powergate_power_up(&pg, false);
>  	if (err)
> @@ -755,45 +735,26 @@ static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
>  static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
>  					 struct device_node *np, bool off)
>  {
> -	struct reset_control *rst;
> -	unsigned int i, count;
>  	int err;
>  
> -	count = of_count_phandle_with_args(np, "resets", "#reset-cells");
> -	if (count == 0)
> -		return -ENODEV;
> -
> -	pg->resets = kcalloc(count, sizeof(rst), GFP_KERNEL);
> -	if (!pg->resets)
> -		return -ENOMEM;
> -
> -	for (i = 0; i < count; i++) {
> -		pg->resets[i] = of_reset_control_get_by_index(np, i);
> -		if (IS_ERR(pg->resets[i])) {
> -			err = PTR_ERR(pg->resets[i]);
> -			goto error;
> -		}
> -
> -		if (off)
> -			err = reset_control_assert(pg->resets[i]);
> -		else
> -			err = reset_control_deassert(pg->resets[i]);
> -
> -		if (err) {
> -			reset_control_put(pg->resets[i]);
> -			goto error;
> -		}
> +	pg->reset = of_reset_control_array_get_exclusive(np);
> +	if (IS_ERR(pg->reset)) {
> +		pr_err("failed to get device resets\n");
> +		return PTR_ERR(pg->reset);
>  	}
>  
> -	pg->num_resets = count;
> +	if (off)
> +		err = reset_control_assert(pg->reset);
> +	else
> +		err = reset_control_deassert(pg->reset);
>  
> -	return 0;
> +	if (err)
> +		goto put_reset;
>  
> -error:
> -	while (i--)
> -		reset_control_put(pg->resets[i]);
> +	return 0;
>  
> -	kfree(pg->resets);
> +put_reset:
> +	reset_control_put(pg->reset);
>  
>  	return err;
>  }
> @@ -885,10 +846,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
>  	pm_genpd_remove(&pg->genpd);
>  
>  remove_resets:
> -	while (pg->num_resets--)
> -		reset_control_put(pg->resets[pg->num_resets]);
> -
> -	kfree(pg->resets);
> +	reset_control_put(pg->reset);
>  
>  remove_clks:
>  	while (pg->num_clks--)
> 

Acked-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>

Cheers
Jon

-- 
nvpublic

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

end of thread, other threads:[~2018-02-13 13:54 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-19 14:34 [PATCH v6 0/4] reset: APIs to manage a list of resets Philipp Zabel
2017-06-19 14:34 ` [PATCH v6 1/4] reset: Add APIs to manage array " Philipp Zabel
2017-06-19 19:42   ` kbuild test robot
2017-06-19 20:21   ` kbuild test robot
2017-06-20  7:02     ` Philipp Zabel
2017-06-19 14:34 ` [PATCH v6 2/4] usb: dwc3: of-simple: Re-order resource handling in remove Philipp Zabel
2017-06-19 14:34 ` [PATCH v6 3/4] usb: dwc3: of-simple: Add support to get resets for the device Philipp Zabel
2017-06-19 14:34 ` [PATCH v6 4/4] soc/tegra: pmc: Use the new reset APIs to manage reset controllers Philipp Zabel
2018-02-13 13:54   ` Jon Hunter

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).