[PATCH v3 11/11] usb: phy-mxs: Add system suspend/resume API

Shawn Guo shawn.guo at linaro.org
Mon Nov 4 22:05:15 EST 2013


On Tue, Nov 05, 2013 at 09:49:43AM +0800, Peter Chen wrote:
> We need this to keep PHY's power on or off during the system
> suspend mode. If we need to enable USB wakeup, then we
> must keep PHY's power being on during the system suspend mode.
> Otherwise, we need to keep PHY's power being off to save power.
> 
> Signed-off-by: Peter Chen <peter.chen at freescale.com>
> ---
>  drivers/usb/phy/phy-mxs-usb.c |   66 +++++++++++++++++++++++++++++++++++++++--
>  1 files changed, 63 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
> index ff8b98c..4588c72 100644
> --- a/drivers/usb/phy/phy-mxs-usb.c
> +++ b/drivers/usb/phy/phy-mxs-usb.c
> @@ -55,11 +55,18 @@
>  #define BM_USBPHY_DEBUG_CLKGATE			BIT(30)
>  
>  /* Anatop Registers */
> +#define ANADIG_ANA_MISC0			0x150
> +#define ANADIG_ANA_MISC0_SET			0x154
> +#define ANADIG_ANA_MISC0_CLR			0x158
> +
>  #define ANADIG_USB1_VBUS_DET_STAT		0x1c0
>  
>  #define ANADIG_USB1_LOOPBACK_SET		0x1e4
>  #define ANADIG_USB1_LOOPBACK_CLR		0x1e8
>  
> +#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG	BIT(12)
> +#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL BIT(11)
> +
>  #define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID	BIT(3)
>  
>  #define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1	BIT(2)
> @@ -83,6 +90,15 @@
>   */
>  #define MXS_PHY_SENDING_SOF_TOO_FAST		BIT(2)
>  
> +/* imx23 style PHY */
> +#define MXS_PHY_IMX23				BIT(3)
> +
> +/* imx6q style PHY */
> +#define MXS_PHY_IMX6Q				BIT(4)
> +
> +/* imx6sl style PHY */
> +#define MXS_PHY_IMX6SL				BIT(5)
> +

We will not need these, if we do what I suggested to carry a pointer
to mxs_phy_data in mxs_phy.

struct mxs_phy {
	...
	struct mxs_phy_data *data;
};

The check then can be done like below.

static inline int is_imx6q_phy(struct mxs_phy *mxs_phy)
{
        return mxs_phy->data == &imx6q_phy_data;
}

Shawn

>  /*
>   * IC fix for MXS_PHY_ABNORAML_IN_SUSPEND, bit 17 is the effective bit
>   * in HW_USBPHY_IP.
> @@ -100,19 +116,23 @@ struct mxs_phy_platform_flag {
>  };
>  
>  static const struct mxs_phy_platform_flag imx23_phy_data = {
> -	.flags = MXS_PHY_ABNORAML_IN_SUSPEND | MXS_PHY_SENDING_SOF_TOO_FAST,
> +	.flags = MXS_PHY_ABNORAML_IN_SUSPEND |
> +		MXS_PHY_SENDING_SOF_TOO_FAST |
> +		MXS_PHY_IMX23,
>  };
>  
>  static const struct mxs_phy_platform_flag imx6q_phy_data = {
>  	.flags = MXS_PHY_SENDING_SOF_TOO_FAST |
>  		MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
> -		MXS_PHY_FIX_ABNORAML_IN_SUSPEND,
> +		MXS_PHY_FIX_ABNORAML_IN_SUSPEND |
> +		MXS_PHY_IMX6Q,
>  };
>  
>  static const struct mxs_phy_platform_flag imx6sl_phy_data = {
>  	.flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
>  		MXS_PHY_FIX_ABNORAML_IN_SUSPEND |
> -		MXS_PHY_FIX_SENDING_SOF_TOO_FAST,
> +		MXS_PHY_FIX_SENDING_SOF_TOO_FAST |
> +		MXS_PHY_IMX6SL,
>  };
>  
>  static const struct of_device_id mxs_phy_dt_ids[] = {
> @@ -210,6 +230,22 @@ static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
>  			? "disconnected" : "connected");
>  }
>  
> +static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
> +{
> +	unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
> +
> +	/* If the SoCs don't have anatop, quit */
> +	if (!mxs_phy->regmap_anatop)
> +		return;
> +
> +	if (mxs_phy->flags & MXS_PHY_IMX6Q)
> +		regmap_write(mxs_phy->regmap_anatop, reg,
> +			BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
> +	else if (mxs_phy->flags & MXS_PHY_IMX6SL)
> +		regmap_write(mxs_phy->regmap_anatop,
> +			reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
> +}
> +
>  static int mxs_phy_init(struct usb_phy *phy)
>  {
>  	struct mxs_phy *mxs_phy = to_mxs_phy(phy);
> @@ -395,6 +431,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, &mxs_phy->phy);
>  
> +	device_set_wakeup_capable(&pdev->dev, true);
>  	ret = usb_add_phy_dev(&mxs_phy->phy);
>  	if (ret)
>  		return ret;
> @@ -411,6 +448,28 @@ static int mxs_phy_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int mxs_phy_system_suspend(struct device *dev)
> +{
> +	struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
> +
> +	if (device_may_wakeup(dev))
> +		mxs_phy_enable_ldo_in_suspend(mxs_phy, true);
> +
> +	return 0;
> +}
> +
> +static int mxs_phy_system_resume(struct device *dev)
> +{
> +	struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
> +
> +	if (device_may_wakeup(dev))
> +		mxs_phy_enable_ldo_in_suspend(mxs_phy, false);
> +
> +	return 0;
> +}
> +
> +SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend, mxs_phy_system_resume);
> +
>  static struct platform_driver mxs_phy_driver = {
>  	.probe = mxs_phy_probe,
>  	.remove = mxs_phy_remove,
> @@ -418,6 +477,7 @@ static struct platform_driver mxs_phy_driver = {
>  		.name = DRIVER_NAME,
>  		.owner	= THIS_MODULE,
>  		.of_match_table = mxs_phy_dt_ids,
> +		.pm = &mxs_phy_pm,
>  	 },
>  };
>  
> -- 
> 1.7.1
> 
> 




More information about the linux-arm-kernel mailing list