aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2013-08-19 06:39:44 -0400
committerFelipe Balbi <balbi@ti.com>2013-10-01 10:31:11 -0400
commita12226394e7d19734d129766676a5668efd50d5c (patch)
tree29e62ed87e7641b9f2d210c661fd7b622fae171a /drivers/usb
parent4d175f340c9c055482688d2205038413dc7b6f1e (diff)
usb: phy: am335x: add wakeup support
This is based on George Cherian's patch which added power & wakeup support to am335x and does no longer apply since I took some if the code apart in favor of the multi instance support. This compiles and I boots and later it detects a device after I plug it in :) Could somebody please test it so it does what it should? Cc: George Cherian <george.cherian@ti.com> Reviewed-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/phy/phy-am335x-control.c42
-rw-r--r--drivers/usb/phy/phy-am335x.c35
2 files changed, 77 insertions, 0 deletions
diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
index 22cf07d62e4c..0fac976b63b5 100644
--- a/drivers/usb/phy/phy-am335x-control.c
+++ b/drivers/usb/phy/phy-am335x-control.c
@@ -26,6 +26,41 @@ struct am335x_control_usb {
26#define USBPHY_OTGVDET_EN (1 << 19) 26#define USBPHY_OTGVDET_EN (1 << 19)
27#define USBPHY_OTGSESSEND_EN (1 << 20) 27#define USBPHY_OTGSESSEND_EN (1 << 20)
28 28
29#define AM335X_PHY0_WK_EN (1 << 0)
30#define AM335X_PHY1_WK_EN (1 << 8)
31
32static void am335x_phy_wkup(struct phy_control *phy_ctrl, u32 id, bool on)
33{
34 struct am335x_control_usb *usb_ctrl;
35 u32 val;
36 u32 reg;
37
38 usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl);
39
40 switch (id) {
41 case 0:
42 reg = AM335X_PHY0_WK_EN;
43 break;
44 case 1:
45 reg = AM335X_PHY1_WK_EN;
46 break;
47 default:
48 WARN_ON(1);
49 return;
50 }
51
52 spin_lock(&usb_ctrl->lock);
53 val = readl(usb_ctrl->wkup);
54
55 if (on)
56 val |= reg;
57 else
58 val &= ~reg;
59
60 writel(val, usb_ctrl->wkup);
61 spin_unlock(&usb_ctrl->lock);
62}
63
29static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on) 64static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
30{ 65{
31 struct am335x_control_usb *usb_ctrl; 66 struct am335x_control_usb *usb_ctrl;
@@ -59,6 +94,7 @@ static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
59 94
60static const struct phy_control ctrl_am335x = { 95static const struct phy_control ctrl_am335x = {
61 .phy_power = am335x_phy_power, 96 .phy_power = am335x_phy_power,
97 .phy_wkup = am335x_phy_wkup,
62}; 98};
63 99
64static const struct of_device_id omap_control_usb_id_table[] = { 100static const struct of_device_id omap_control_usb_id_table[] = {
@@ -117,6 +153,12 @@ static int am335x_control_usb_probe(struct platform_device *pdev)
117 ctrl_usb->phy_reg = devm_ioremap_resource(&pdev->dev, res); 153 ctrl_usb->phy_reg = devm_ioremap_resource(&pdev->dev, res);
118 if (IS_ERR(ctrl_usb->phy_reg)) 154 if (IS_ERR(ctrl_usb->phy_reg))
119 return PTR_ERR(ctrl_usb->phy_reg); 155 return PTR_ERR(ctrl_usb->phy_reg);
156
157 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wakeup");
158 ctrl_usb->wkup = devm_ioremap_resource(&pdev->dev, res);
159 if (IS_ERR(ctrl_usb->wkup))
160 return PTR_ERR(ctrl_usb->wkup);
161
120 spin_lock_init(&ctrl_usb->lock); 162 spin_lock_init(&ctrl_usb->lock);
121 ctrl_usb->phy_ctrl = *phy_ctrl; 163 ctrl_usb->phy_ctrl = *phy_ctrl;
122 164
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index f836dc68104c..f3478a856edb 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -78,6 +78,40 @@ static int am335x_phy_remove(struct platform_device *pdev)
78 return 0; 78 return 0;
79} 79}
80 80
81#ifdef CONFIG_PM_RUNTIME
82
83static int am335x_phy_runtime_suspend(struct device *dev)
84{
85 struct platform_device *pdev = to_platform_device(dev);
86 struct am335x_phy *am_phy = platform_get_drvdata(pdev);
87
88 if (device_may_wakeup(dev))
89 phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, true);
90 phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
91 return 0;
92}
93
94static int am335x_phy_runtime_resume(struct device *dev)
95{
96 struct platform_device *pdev = to_platform_device(dev);
97 struct am335x_phy *am_phy = platform_get_drvdata(pdev);
98
99 phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true);
100 if (device_may_wakeup(dev))
101 phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, false);
102 return 0;
103}
104
105static const struct dev_pm_ops am335x_pm_ops = {
106 SET_RUNTIME_PM_OPS(am335x_phy_runtime_suspend,
107 am335x_phy_runtime_resume, NULL)
108};
109
110#define DEV_PM_OPS (&am335x_pm_ops)
111#else
112#define DEV_PM_OPS NULL
113#endif
114
81static const struct of_device_id am335x_phy_ids[] = { 115static const struct of_device_id am335x_phy_ids[] = {
82 { .compatible = "ti,am335x-usb-phy" }, 116 { .compatible = "ti,am335x-usb-phy" },
83 { } 117 { }
@@ -90,6 +124,7 @@ static struct platform_driver am335x_phy_driver = {
90 .driver = { 124 .driver = {
91 .name = "am335x-phy-driver", 125 .name = "am335x-phy-driver",
92 .owner = THIS_MODULE, 126 .owner = THIS_MODULE,
127 .pm = DEV_PM_OPS,
93 .of_match_table = of_match_ptr(am335x_phy_ids), 128 .of_match_table = of_match_ptr(am335x_phy_ids),
94 }, 129 },
95}; 130};