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

From: Gregory CLEMENT
Date: Mon Nov 13 2023 - 10:39:25 EST


Hello Théo,

> 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@xxxxxxxxxxx>
> ---
> 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;

Just a small remark:

What about adding a boolean in the cdns_ti struct for taking care of
it ? Then you will go through the device tree only during probe. Moreover
if this behaviour is needed for more compatible we can just add them in
the probe too.

Besides this you still can add my

Reviewed-by: Gregory CLEMENT <gregory.clement@xxxxxxxxxxx>

Thanks,

Gregory

> +
> + 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
>
>

--
Gregory Clement, Bootlin
Embedded Linux and Kernel engineering
http://bootlin.com