[PATCH 1/2] reset: rzv2h-usb2phy: Add suspend/resume support

From: Tommaso Merciai

Date: Thu Oct 08 2026 - 03:55:36 EST


The RZ/V2H(P) USB2PHY reset driver is also used on the RZ/G3E SoC,
where deep sleep turns off power to the USB2PHY block.
Part of the initialization sequence written at probe time is cleared,
leaving the PHY unprepared to receive assert and deassert requests.

Add suspend/resume support to assert the reset on suspend, and to
deassert it and rewrite the initialization sequence on resume.

Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@xxxxxxxxxxxxxx>
---
drivers/reset/reset-rzv2h-usb2phy.c | 61 +++++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 4 deletions(-)

diff --git a/drivers/reset/reset-rzv2h-usb2phy.c b/drivers/reset/reset-rzv2h-usb2phy.c
index d96042e28cd5..c14c3fcd7875 100644
--- a/drivers/reset/reset-rzv2h-usb2phy.c
+++ b/drivers/reset/reset-rzv2h-usb2phy.c
@@ -37,6 +37,7 @@ struct rzv2h_usb2phy_reset_priv {
const struct rzv2h_usb2phy_reset_of_data *data;
struct regmap *regmap;
struct device *dev;
+ struct reset_control *rstc;
struct reset_controller_dev rcdev;
};

@@ -132,7 +133,6 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
const struct rzv2h_usb2phy_reset_of_data *data;
struct rzv2h_usb2phy_reset_priv *priv;
struct device *dev = &pdev->dev;
- struct reset_control *rstc;
void __iomem *base;
int error;

@@ -151,9 +151,9 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);

- rstc = devm_reset_control_get_shared_deasserted(dev, NULL);
- if (IS_ERR(rstc))
- return dev_err_probe(dev, PTR_ERR(rstc),
+ priv->rstc = devm_reset_control_get_shared_deasserted(dev, NULL);
+ if (IS_ERR(priv->rstc))
+ return dev_err_probe(dev, PTR_ERR(priv->rstc),
"failed to get deasserted reset\n");

error = devm_pm_runtime_enable(dev);
@@ -188,6 +188,8 @@ static int rzv2h_usb2phy_reset_probe(struct platform_device *pdev)
if (error)
return dev_err_probe(dev, error, "could not register aux mux\n");

+ platform_set_drvdata(pdev, priv);
+
return 0;
}

@@ -229,10 +231,61 @@ static const struct of_device_id rzv2h_usb2phy_reset_of_match[] = {
};
MODULE_DEVICE_TABLE(of, rzv2h_usb2phy_reset_of_match);

+static int rzv2h_usb2phy_reset_suspend(struct device *dev)
+{
+ struct rzv2h_usb2phy_reset_priv *priv = dev_get_drvdata(dev);
+ int error;
+
+ error = reset_control_assert(priv->rstc);
+ if (error)
+ return error;
+
+ error = pm_runtime_put_sync(dev);
+ if (error < 0) {
+ pm_runtime_get_noresume(dev);
+ reset_control_deassert(priv->rstc);
+ return error;
+ }
+
+ return 0;
+}
+
+static int rzv2h_usb2phy_reset_resume(struct device *dev)
+{
+ struct rzv2h_usb2phy_reset_priv *priv = dev_get_drvdata(dev);
+ int error;
+
+ error = pm_runtime_resume_and_get(dev);
+ if (error)
+ return error;
+
+ error = reset_control_deassert(priv->rstc);
+ if (error)
+ goto rpm_put;
+
+ error = regmap_multi_reg_write(priv->regmap, priv->data->init_seq,
+ priv->data->init_nseq);
+ if (error)
+ goto reset_assert;
+
+ return 0;
+
+reset_assert:
+ reset_control_assert(priv->rstc);
+rpm_put:
+ pm_runtime_put_sync(dev);
+ return error;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(rzv2h_usb2phy_reset_pm_ops,
+ rzv2h_usb2phy_reset_suspend,
+ rzv2h_usb2phy_reset_resume);
+
static struct platform_driver rzv2h_usb2phy_reset_driver = {
.driver = {
.name = "rzv2h_usb2phy_reset",
.of_match_table = rzv2h_usb2phy_reset_of_match,
+ .pm = pm_sleep_ptr(&rzv2h_usb2phy_reset_pm_ops),
},
.probe = rzv2h_usb2phy_reset_probe,
};
--
2.54.0