aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index da2eb6c968ca..31ef59f88901 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -57,6 +57,10 @@
57#define BM_USBPHY_DEBUG_CLKGATE BIT(30) 57#define BM_USBPHY_DEBUG_CLKGATE BIT(30)
58 58
59/* Anatop Registers */ 59/* Anatop Registers */
60#define ANADIG_ANA_MISC0 0x150
61#define ANADIG_ANA_MISC0_SET 0x154
62#define ANADIG_ANA_MISC0_CLR 0x158
63
60#define ANADIG_USB1_VBUS_DET_STAT 0x1c0 64#define ANADIG_USB1_VBUS_DET_STAT 0x1c0
61#define ANADIG_USB2_VBUS_DET_STAT 0x220 65#define ANADIG_USB2_VBUS_DET_STAT 0x220
62 66
@@ -65,6 +69,9 @@
65#define ANADIG_USB2_LOOPBACK_SET 0x244 69#define ANADIG_USB2_LOOPBACK_SET 0x244
66#define ANADIG_USB2_LOOPBACK_CLR 0x248 70#define ANADIG_USB2_LOOPBACK_CLR 0x248
67 71
72#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG BIT(12)
73#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL BIT(11)
74
68#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3) 75#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3)
69#define BM_ANADIG_USB2_VBUS_DET_STAT_VBUS_VALID BIT(3) 76#define BM_ANADIG_USB2_VBUS_DET_STAT_VBUS_VALID BIT(3)
70 77
@@ -134,6 +141,16 @@ struct mxs_phy {
134 int port_id; 141 int port_id;
135}; 142};
136 143
144static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
145{
146 return mxs_phy->data == &imx6q_phy_data;
147}
148
149static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
150{
151 return mxs_phy->data == &imx6sl_phy_data;
152}
153
137static int mxs_phy_hw_init(struct mxs_phy *mxs_phy) 154static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
138{ 155{
139 int ret; 156 int ret;
@@ -387,6 +404,8 @@ static int mxs_phy_probe(struct platform_device *pdev)
387 404
388 platform_set_drvdata(pdev, mxs_phy); 405 platform_set_drvdata(pdev, mxs_phy);
389 406
407 device_set_wakeup_capable(&pdev->dev, true);
408
390 ret = usb_add_phy_dev(&mxs_phy->phy); 409 ret = usb_add_phy_dev(&mxs_phy->phy);
391 if (ret) 410 if (ret)
392 return ret; 411 return ret;
@@ -403,6 +422,47 @@ static int mxs_phy_remove(struct platform_device *pdev)
403 return 0; 422 return 0;
404} 423}
405 424
425#ifdef CONFIG_PM_SLEEP
426static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
427{
428 unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
429
430 /* If the SoCs don't have anatop, quit */
431 if (!mxs_phy->regmap_anatop)
432 return;
433
434 if (is_imx6q_phy(mxs_phy))
435 regmap_write(mxs_phy->regmap_anatop, reg,
436 BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
437 else if (is_imx6sl_phy(mxs_phy))
438 regmap_write(mxs_phy->regmap_anatop,
439 reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
440}
441
442static int mxs_phy_system_suspend(struct device *dev)
443{
444 struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
445
446 if (device_may_wakeup(dev))
447 mxs_phy_enable_ldo_in_suspend(mxs_phy, true);
448
449 return 0;
450}
451
452static int mxs_phy_system_resume(struct device *dev)
453{
454 struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
455
456 if (device_may_wakeup(dev))
457 mxs_phy_enable_ldo_in_suspend(mxs_phy, false);
458
459 return 0;
460}
461#endif /* CONFIG_PM_SLEEP */
462
463static SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend,
464 mxs_phy_system_resume);
465
406static struct platform_driver mxs_phy_driver = { 466static struct platform_driver mxs_phy_driver = {
407 .probe = mxs_phy_probe, 467 .probe = mxs_phy_probe,
408 .remove = mxs_phy_remove, 468 .remove = mxs_phy_remove,
@@ -410,6 +470,7 @@ static struct platform_driver mxs_phy_driver = {
410 .name = DRIVER_NAME, 470 .name = DRIVER_NAME,
411 .owner = THIS_MODULE, 471 .owner = THIS_MODULE,
412 .of_match_table = mxs_phy_dt_ids, 472 .of_match_table = mxs_phy_dt_ids,
473 .pm = &mxs_phy_pm,
413 }, 474 },
414}; 475};
415 476