Commit b332d6d5 authored by Li Jun's avatar Li Jun Committed by Greg Kroah-Hartman
Browse files

usb: chipidea: usbmisc: group usbmisc operations for PM



As there maybe more APIs of usbmisc for suspend and resume, group
them into imx_usbmisc_suspend/resume. Besides, introduced .power_lost_check
API, so that proper resume operations can be performed in power lost case.

Signed-off-by: default avatarLi Jun <jun.li@nxp.com>
Link: https://lore.kernel.org/r/20221013151442.3262951-6-xu.yang_2@nxp.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 235ffc17
Loading
Loading
Loading
Loading
+15 −34
Original line number Diff line number Diff line
@@ -527,16 +527,19 @@ static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
	ci_hdrc_imx_remove(pdev);
}

static int __maybe_unused imx_controller_suspend(struct device *dev)
static int __maybe_unused imx_controller_suspend(struct device *dev,
						 pm_message_t msg)
{
	struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
	int ret = 0;

	dev_dbg(dev, "at %s\n", __func__);

	ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false);
	ret = imx_usbmisc_suspend(data->usbmisc_data,
				  PMSG_IS_AUTO(msg) || device_may_wakeup(dev));
	if (ret) {
		dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret);
		dev_err(dev,
			"usbmisc suspend failed, ret=%d\n", ret);
		return ret;
	}

@@ -549,7 +552,8 @@ static int __maybe_unused imx_controller_suspend(struct device *dev)
	return 0;
}

static int __maybe_unused imx_controller_resume(struct device *dev)
static int __maybe_unused imx_controller_resume(struct device *dev,
						pm_message_t msg)
{
	struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
	int ret = 0;
@@ -570,22 +574,15 @@ static int __maybe_unused imx_controller_resume(struct device *dev)

	data->in_lpm = false;

	ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
	ret = imx_usbmisc_resume(data->usbmisc_data,
				 PMSG_IS_AUTO(msg) || device_may_wakeup(dev));
	if (ret) {
		dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
		dev_err(dev, "usbmisc resume failed, ret=%d\n", ret);
		goto clk_disable;
	}

	ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true);
	if (ret) {
		dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret);
		goto hsic_set_clk_fail;
	}

	return 0;

hsic_set_clk_fail:
	imx_usbmisc_set_wakeup(data->usbmisc_data, true);
clk_disable:
	imx_disable_unprepare_clks(dev);
	return ret;
@@ -601,16 +598,7 @@ static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev)
		/* The core's suspend doesn't run */
		return 0;

	if (device_may_wakeup(dev)) {
		ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
		if (ret) {
			dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n",
					ret);
			return ret;
		}
	}

	ret = imx_controller_suspend(dev);
	ret = imx_controller_suspend(dev, PMSG_SUSPEND);
	if (ret)
		return ret;

@@ -624,7 +612,7 @@ static int __maybe_unused ci_hdrc_imx_resume(struct device *dev)
	int ret;

	pinctrl_pm_select_default_state(dev);
	ret = imx_controller_resume(dev);
	ret = imx_controller_resume(dev, PMSG_RESUME);
	if (!ret && data->supports_runtime_pm) {
		pm_runtime_disable(dev);
		pm_runtime_set_active(dev);
@@ -637,25 +625,18 @@ static int __maybe_unused ci_hdrc_imx_resume(struct device *dev)
static int __maybe_unused ci_hdrc_imx_runtime_suspend(struct device *dev)
{
	struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
	int ret;

	if (data->in_lpm) {
		WARN_ON(1);
		return 0;
	}

	ret = imx_usbmisc_set_wakeup(data->usbmisc_data, true);
	if (ret) {
		dev_err(dev, "usbmisc set_wakeup failed, ret=%d\n", ret);
		return ret;
	}

	return imx_controller_suspend(dev);
	return imx_controller_suspend(dev, PMSG_AUTO_SUSPEND);
}

static int __maybe_unused ci_hdrc_imx_runtime_resume(struct device *dev)
{
	return imx_controller_resume(dev);
	return imx_controller_resume(dev, PMSG_AUTO_RESUME);
}

static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
+2 −2
Original line number Diff line number Diff line
@@ -32,9 +32,9 @@ struct imx_usbmisc_data {

int imx_usbmisc_init(struct imx_usbmisc_data *data);
int imx_usbmisc_init_post(struct imx_usbmisc_data *data);
int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled);
int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data);
int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on);
int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect);
int imx_usbmisc_suspend(struct imx_usbmisc_data *data, bool wakeup);
int imx_usbmisc_resume(struct imx_usbmisc_data *data, bool wakeup);

#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
+89 −30
Original line number Diff line number Diff line
@@ -150,6 +150,8 @@ struct usbmisc_ops {
	int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
	/* usb charger detection */
	int (*charger_detection)(struct imx_usbmisc_data *data);
	/* It's called when system resume from usb power lost */
	int (*power_lost_check)(struct imx_usbmisc_data *data);
};

struct imx_usbmisc {
@@ -1009,30 +1011,29 @@ EXPORT_SYMBOL_GPL(imx_usbmisc_init);
int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
{
	struct imx_usbmisc *usbmisc;
	int ret = 0;

	if (!data)
		return 0;

	usbmisc = dev_get_drvdata(data->dev);
	if (!usbmisc->ops->post)
		return 0;
	return usbmisc->ops->post(data);
	if (usbmisc->ops->post)
		ret = usbmisc->ops->post(data);
	if (ret) {
		dev_err(data->dev, "post init failed, ret=%d\n", ret);
		return ret;
	}
EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);

int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
{
	struct imx_usbmisc *usbmisc;

	if (!data)
		return 0;
	if (usbmisc->ops->set_wakeup)
		ret = usbmisc->ops->set_wakeup(data, false);
	if (ret) {
		dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret);
		return ret;
	}

	usbmisc = dev_get_drvdata(data->dev);
	if (!usbmisc->ops->set_wakeup)
	return 0;
	return usbmisc->ops->set_wakeup(data, enabled);
}
EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);

int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
{
@@ -1048,20 +1049,6 @@ int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
}
EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);

int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
{
	struct imx_usbmisc *usbmisc;

	if (!data)
		return 0;

	usbmisc = dev_get_drvdata(data->dev);
	if (!usbmisc->ops->hsic_set_clk || !data->hsic)
		return 0;
	return usbmisc->ops->hsic_set_clk(data, on);
}
EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);

int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect)
{
	struct imx_usbmisc *usbmisc;
@@ -1094,6 +1081,78 @@ int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect)
}
EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection);

int imx_usbmisc_suspend(struct imx_usbmisc_data *data, bool wakeup)
{
	struct imx_usbmisc *usbmisc;
	int ret = 0;

	if (!data)
		return 0;

	usbmisc = dev_get_drvdata(data->dev);

	if (wakeup && usbmisc->ops->set_wakeup)
		ret = usbmisc->ops->set_wakeup(data, true);
	if (ret) {
		dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret);
		return ret;
	}

	if (usbmisc->ops->hsic_set_clk && data->hsic)
		ret = usbmisc->ops->hsic_set_clk(data, false);
	if (ret) {
		dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret);
		return ret;
	}

	return ret;
}
EXPORT_SYMBOL_GPL(imx_usbmisc_suspend);

int imx_usbmisc_resume(struct imx_usbmisc_data *data, bool wakeup)
{
	struct imx_usbmisc *usbmisc;
	int ret = 0;

	if (!data)
		return 0;

	usbmisc = dev_get_drvdata(data->dev);

	if (usbmisc->ops->power_lost_check)
		ret = usbmisc->ops->power_lost_check(data);
	if (ret > 0) {
		/* re-init if resume from power lost */
		ret = imx_usbmisc_init(data);
		if (ret) {
			dev_err(data->dev, "re-init failed, ret=%d\n", ret);
			return ret;
		}
	}

	if (wakeup && usbmisc->ops->set_wakeup)
		ret = usbmisc->ops->set_wakeup(data, false);
	if (ret) {
		dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret);
		return ret;
	}

	if (usbmisc->ops->hsic_set_clk && data->hsic)
		ret = usbmisc->ops->hsic_set_clk(data, true);
	if (ret) {
		dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret);
		goto hsic_set_clk_fail;
	}

	return 0;

hsic_set_clk_fail:
	if (wakeup && usbmisc->ops->set_wakeup)
		usbmisc->ops->set_wakeup(data, true);
	return ret;
}
EXPORT_SYMBOL_GPL(imx_usbmisc_resume);

static const struct of_device_id usbmisc_imx_dt_ids[] = {
	{
		.compatible = "fsl,imx25-usbmisc",