
Hi Kishon,
On Mon, 12 Jul 2021 at 00:20, Kishon Vijay Abraham I kishon@ti.com wrote:
Add devm_to_reset() to return dummy "struct reset_ctl", useful for invoking reset APIs which doesn't have a valid "struct reset_ctl".
Suggested-by: Simon Glass sjg@chromium.org Signed-off-by: Kishon Vijay Abraham I kishon@ti.com
drivers/reset/reset-uclass.c | 16 ++++++++++++++++ drivers/reset/sandbox-reset-test.c | 4 +++- include/reset.h | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index 8caa616ed9..9f2eeb4fe4 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -15,6 +15,8 @@ #include <dm/devres.h> #include <dm/lists.h>
+static struct reset_ctl devm_no_reset;
static inline struct reset_ops *reset_dev_ops(struct udevice *dev) { return (struct reset_ops *)dev->driver->ops; @@ -256,6 +258,20 @@ int reset_release_all(struct reset_ctl *reset_ctl, int count) return 0; }
+int devm_to_reset(struct reset_ctl *in, struct reset_ctl **outp) +{
if (IS_ERR_OR_NULL(in)) {
*outp = &devm_no_reset;
This var ends up in BSS so won't work in early SPL / pre-relocation in U-Boot. Please add a priv_auto struct in the UCLASS_DRIVER() and put this value in there.
if (!in)
return -ENOENT;
else
return PTR_ERR(in);
}
*outp = in;
return 0;
+}
static void devm_reset_release(struct udevice *dev, void *res) { reset_free(res); diff --git a/drivers/reset/sandbox-reset-test.c b/drivers/reset/sandbox-reset-test.c index 51b79810c8..4389bde5e7 100644 --- a/drivers/reset/sandbox-reset-test.c +++ b/drivers/reset/sandbox-reset-test.c @@ -32,13 +32,15 @@ int sandbox_reset_test_get_devm(struct udevice *dev)
Can this function move into the test itself? It seems strange for it to be here.
{ struct sandbox_reset_test *sbrt = dev_get_priv(dev); struct reset_ctl *r;
int ret; r = devm_reset_control_get(dev, "not-a-valid-reset-ctl"); if (!IS_ERR(r)) return -EINVAL; r = devm_reset_control_get_optional(dev, "not-a-valid-reset-ctl");
if (r)
ret = devm_to_reset(r, &r);
if (reset_valid(r)) return -EINVAL;
Can you not do:
if (ret) return ret;
?
sbrt->ctlp = devm_reset_control_get(dev, "test");
diff --git a/include/reset.h b/include/reset.h index cde2c4b4a8..21affc1455 100644 --- a/include/reset.h +++ b/include/reset.h @@ -341,6 +341,18 @@ int reset_status(struct reset_ctl *reset_ctl); */ int reset_release_all(struct reset_ctl *reset_ctl, int count);
+/**
- devm_to_reset - Provide a dummy reset_ctl for invalid reset_ctl
Returns the reset_ctl to use for a devm reset?
- Provide a dummy reset_ctl for invalid reset_ctl or give the same
- input reset_ctl
- @in: Input reset_ctl returned by devm_reset_control_get()
- @outp: Dummy reset_ctl for invalid reset_ctl or Input reset_ctl
Put the positive case first.
Returns @in if valid. If not valid, returns a dummy reset_ctl for which reset_valid() will always return false.
- @return 0 if OK, or a negative error code.
Please document what specific errors this returns as this is important.
- */
+int devm_to_reset(struct reset_ctl *in, struct reset_ctl **outp);
/**
- reset_release_bulk - Assert/Free an array of previously requested reset
- signals in a reset control bulk struct.
@@ -456,6 +468,11 @@ static inline int reset_release_bulk(struct reset_ctl_bulk *bulk) { return 0; }
+static inline int devm_to_reset(struct reset_ctl *in, struct reset_ctl **outp) +{
return 0;
That indicates success but *outp is not set. Is that OK? Should you return -ENOSYS, or maybe set *outp to something?
+} #endif
/**
2.17.1
Regards, Simon