[PATCH 3/6] usb: cdns3-ti: add suspend/resume procedures for J7200

Théo Lebrun theo.lebrun at bootlin.com
Mon Nov 13 06:26:58 PST 2023


Hardware initialisation is only done at probe. The J7200 USB controller
is reset at resume because of power-domains toggling off & on. We
therefore (1) toggle PM runtime at suspend/resume & (2) reconfigure the
hardware at resume.

Reuse the newly extracted cdns_ti_init_hw() function that contains the
register write sequence.

We guard this behavior based on compatible to avoid modifying the
current behavior on other platforms. If the controller does not reset
we do not want to touch PM runtime & do not want to redo reg writes.

Signed-off-by: Théo Lebrun <theo.lebrun at bootlin.com>
---
 drivers/usb/cdns3/cdns3-ti.c | 48 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c
index c331bcd2faeb..50b38c4b9c87 100644
--- a/drivers/usb/cdns3/cdns3-ti.c
+++ b/drivers/usb/cdns3/cdns3-ti.c
@@ -197,6 +197,50 @@ static int cdns_ti_probe(struct platform_device *pdev)
 	return error;
 }
 
+#ifdef CONFIG_PM
+
+static int cdns_ti_suspend(struct device *dev)
+{
+	struct cdns_ti *data = dev_get_drvdata(dev);
+
+	if (!of_device_is_compatible(dev_of_node(dev), "ti,j7200-usb"))
+		return 0;
+
+	pm_runtime_put_sync(data->dev);
+
+	return 0;
+}
+
+static int cdns_ti_resume(struct device *dev)
+{
+	struct cdns_ti *data = dev_get_drvdata(dev);
+	int ret;
+
+	if (!of_device_is_compatible(dev_of_node(dev), "ti,j7200-usb"))
+		return 0;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		dev_err(dev, "pm_runtime_get_sync failed: %d\n", ret);
+		goto err;
+	}
+
+	cdns_ti_init_hw(data);
+
+	return 0;
+
+err:
+	pm_runtime_put_sync(data->dev);
+	pm_runtime_disable(data->dev);
+	return ret;
+}
+
+static const struct dev_pm_ops cdns_ti_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(cdns_ti_suspend, cdns_ti_resume)
+};
+
+#endif /* CONFIG_PM */
+
 static int cdns_ti_remove_core(struct device *dev, void *c)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -218,6 +262,7 @@ static void cdns_ti_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id cdns_ti_of_match[] = {
+	{ .compatible = "ti,j7200-usb", },
 	{ .compatible = "ti,j721e-usb", },
 	{ .compatible = "ti,am64-usb", },
 	{},
@@ -228,8 +273,9 @@ static struct platform_driver cdns_ti_driver = {
 	.probe		= cdns_ti_probe,
 	.remove_new	= cdns_ti_remove,
 	.driver		= {
-		.name	= "cdns3-ti",
+		.name		= "cdns3-ti",
 		.of_match_table	= cdns_ti_of_match,
+		.pm		= pm_ptr(&cdns_ti_pm_ops),
 	},
 };
 

-- 
2.41.0




More information about the linux-arm-kernel mailing list