diff options
Diffstat (limited to 'drivers/usb/phy/phy-am335x.c')
| -rw-r--r-- | drivers/usb/phy/phy-am335x.c | 74 | 
1 files changed, 64 insertions, 10 deletions
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index c4d614d1f17..585e50cb198 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -2,7 +2,7 @@  #include <linux/platform_device.h>  #include <linux/dma-mapping.h>  #include <linux/usb/otg.h> -#include <linux/usb/usb_phy_gen_xceiv.h> +#include <linux/usb/usb_phy_generic.h>  #include <linux/slab.h>  #include <linux/clk.h>  #include <linux/regulator/consumer.h> @@ -13,7 +13,7 @@  #include "phy-generic.h"  struct am335x_phy { -	struct usb_phy_gen_xceiv usb_phy_gen; +	struct usb_phy_generic usb_phy_gen;  	struct phy_control *phy_ctrl;  	int id;  }; @@ -52,23 +52,32 @@ static int am335x_phy_probe(struct platform_device *pdev)  		return am_phy->id;  	} -	ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, -			USB_PHY_TYPE_USB2, 0, false, false); +	ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL);  	if (ret)  		return ret;  	ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);  	if (ret) -		goto err_add; +		return ret;  	am_phy->usb_phy_gen.phy.init = am335x_init;  	am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;  	platform_set_drvdata(pdev, am_phy); -	return 0; +	device_init_wakeup(dev, true); + +	/* +	 * If we leave PHY wakeup enabled then AM33XX wakes up +	 * immediately from DS0. To avoid this we mark dev->power.can_wakeup +	 * to false. The same is checked in suspend routine to decide +	 * on whether to enable PHY wakeup or not. +	 * PHY wakeup works fine in standby mode, there by allowing us to +	 * handle remote wakeup, wakeup on disconnect and connect. +	 */ + +	device_set_wakeup_enable(dev, false); +	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false); -err_add: -	usb_phy_gen_cleanup_phy(&am_phy->usb_phy_gen); -	return ret; +	return 0;  }  static int am335x_phy_remove(struct platform_device *pdev) @@ -79,6 +88,50 @@ static int am335x_phy_remove(struct platform_device *pdev)  	return 0;  } +#ifdef CONFIG_PM_SLEEP +static int am335x_phy_suspend(struct device *dev) +{ +	struct platform_device	*pdev = to_platform_device(dev); +	struct am335x_phy *am_phy = platform_get_drvdata(pdev); + +	/* +	 * Enable phy wakeup only if dev->power.can_wakeup is true. +	 * Make sure to enable wakeup to support remote wakeup	in +	 * standby mode ( same is not supported in OFF(DS0) mode). +	 * Enable it by doing +	 * echo enabled > /sys/bus/platform/devices/<usb-phy-id>/power/wakeup +	 */ + +	if (device_may_wakeup(dev)) +		phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, true); + +	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false); + +	return 0; +} + +static int am335x_phy_resume(struct device *dev) +{ +	struct platform_device	*pdev = to_platform_device(dev); +	struct am335x_phy	*am_phy = platform_get_drvdata(pdev); + +	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true); + +	if (device_may_wakeup(dev)) +		phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, false); + +	return 0; +} + +static const struct dev_pm_ops am335x_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(am335x_phy_suspend, am335x_phy_resume) +}; + +#define DEV_PM_OPS     (&am335x_pm_ops) +#else +#define DEV_PM_OPS     NULL +#endif +  static const struct of_device_id am335x_phy_ids[] = {  	{ .compatible = "ti,am335x-usb-phy" },  	{ } @@ -91,7 +144,8 @@ static struct platform_driver am335x_phy_driver = {  	.driver         = {  		.name   = "am335x-phy-driver",  		.owner  = THIS_MODULE, -		.of_match_table = of_match_ptr(am335x_phy_ids), +		.pm = DEV_PM_OPS, +		.of_match_table = am335x_phy_ids,  	},  };  | 
