aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg/twl6030-usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/otg/twl6030-usb.c')
-rw-r--r--drivers/usb/otg/twl6030-usb.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index 28f770103640..8a91b4b832a1 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -149,7 +149,6 @@ static int twl6030_set_phy_clk(struct otg_transceiver *x, int on)
149 149
150static int twl6030_phy_init(struct otg_transceiver *x) 150static int twl6030_phy_init(struct otg_transceiver *x)
151{ 151{
152 u8 hw_state;
153 struct twl6030_usb *twl; 152 struct twl6030_usb *twl;
154 struct device *dev; 153 struct device *dev;
155 struct twl4030_usb_data *pdata; 154 struct twl4030_usb_data *pdata;
@@ -158,11 +157,7 @@ static int twl6030_phy_init(struct otg_transceiver *x)
158 dev = twl->dev; 157 dev = twl->dev;
159 pdata = dev->platform_data; 158 pdata = dev->platform_data;
160 159
161 regulator_enable(twl->usb3v3); 160 if (twl->linkstat == USB_EVENT_ID)
162
163 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
164
165 if (hw_state & STS_USB_ID)
166 pdata->phy_power(twl->dev, 1, 1); 161 pdata->phy_power(twl->dev, 1, 1);
167 else 162 else
168 pdata->phy_power(twl->dev, 0, 1); 163 pdata->phy_power(twl->dev, 0, 1);
@@ -180,7 +175,17 @@ static void twl6030_phy_shutdown(struct otg_transceiver *x)
180 dev = twl->dev; 175 dev = twl->dev;
181 pdata = dev->platform_data; 176 pdata = dev->platform_data;
182 pdata->phy_power(twl->dev, 0, 0); 177 pdata->phy_power(twl->dev, 0, 0);
183 regulator_disable(twl->usb3v3); 178}
179
180static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend)
181{
182 struct twl6030_usb *twl = xceiv_to_twl(x);
183 struct device *dev = twl->dev;
184 struct twl4030_usb_data *pdata = dev->platform_data;
185
186 pdata->phy_suspend(dev, suspend);
187
188 return 0;
184} 189}
185 190
186static int twl6030_usb_ldo_init(struct twl6030_usb *twl) 191static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
@@ -199,16 +204,6 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
199 if (IS_ERR(twl->usb3v3)) 204 if (IS_ERR(twl->usb3v3))
200 return -ENODEV; 205 return -ENODEV;
201 206
202 regulator_enable(twl->usb3v3);
203
204 /* Program the VUSB_CFG_TRANS for ACTIVE state. */
205 twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x3F,
206 VUSB_CFG_TRANS);
207
208 /* Program the VUSB_CFG_STATE register to ON on all groups. */
209 twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0xE1,
210 VUSB_CFG_STATE);
211
212 /* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */ 207 /* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
213 twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET); 208 twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
214 209
@@ -261,16 +256,25 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
261 CONTROLLER_STAT1); 256 CONTROLLER_STAT1);
262 if (!(hw_state & STS_USB_ID)) { 257 if (!(hw_state & STS_USB_ID)) {
263 if (vbus_state & VBUS_DET) { 258 if (vbus_state & VBUS_DET) {
259 regulator_enable(twl->usb3v3);
260 twl->asleep = 1;
264 status = USB_EVENT_VBUS; 261 status = USB_EVENT_VBUS;
265 twl->otg.default_a = false; 262 twl->otg.default_a = false;
266 twl->otg.state = OTG_STATE_B_IDLE; 263 twl->otg.state = OTG_STATE_B_IDLE;
264 twl->linkstat = status;
265 twl->otg.last_event = status;
266 atomic_notifier_call_chain(&twl->otg.notifier,
267 status, twl->otg.gadget);
267 } else { 268 } else {
268 status = USB_EVENT_NONE; 269 status = USB_EVENT_NONE;
269 }
270 if (status >= 0) {
271 twl->linkstat = status; 270 twl->linkstat = status;
272 blocking_notifier_call_chain(&twl->otg.notifier, 271 twl->otg.last_event = status;
272 atomic_notifier_call_chain(&twl->otg.notifier,
273 status, twl->otg.gadget); 273 status, twl->otg.gadget);
274 if (twl->asleep) {
275 regulator_disable(twl->usb3v3);
276 twl->asleep = 0;
277 }
274 } 278 }
275 } 279 }
276 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 280 sysfs_notify(&twl->dev->kobj, NULL, "vbus");
@@ -288,13 +292,17 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
288 292
289 if (hw_state & STS_USB_ID) { 293 if (hw_state & STS_USB_ID) {
290 294
295 regulator_enable(twl->usb3v3);
296 twl->asleep = 1;
291 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1); 297 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
292 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 298 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
293 0x10); 299 0x10);
294 status = USB_EVENT_ID; 300 status = USB_EVENT_ID;
295 twl->otg.default_a = true; 301 twl->otg.default_a = true;
296 twl->otg.state = OTG_STATE_A_IDLE; 302 twl->otg.state = OTG_STATE_A_IDLE;
297 blocking_notifier_call_chain(&twl->otg.notifier, status, 303 twl->linkstat = status;
304 twl->otg.last_event = status;
305 atomic_notifier_call_chain(&twl->otg.notifier, status,
298 twl->otg.gadget); 306 twl->otg.gadget);
299 } else { 307 } else {
300 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 308 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
@@ -303,7 +311,6 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
303 0x1); 311 0x1);
304 } 312 }
305 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status); 313 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status);
306 twl->linkstat = status;
307 314
308 return IRQ_HANDLED; 315 return IRQ_HANDLED;
309} 316}
@@ -395,6 +402,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
395 twl->otg.set_vbus = twl6030_set_vbus; 402 twl->otg.set_vbus = twl6030_set_vbus;
396 twl->otg.init = twl6030_phy_init; 403 twl->otg.init = twl6030_phy_init;
397 twl->otg.shutdown = twl6030_phy_shutdown; 404 twl->otg.shutdown = twl6030_phy_shutdown;
405 twl->otg.set_suspend = twl6030_phy_suspend;
398 406
399 /* init spinlock for workqueue */ 407 /* init spinlock for workqueue */
400 spin_lock_init(&twl->lock); 408 spin_lock_init(&twl->lock);
@@ -411,7 +419,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
411 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 419 if (device_create_file(&pdev->dev, &dev_attr_vbus))
412 dev_warn(&pdev->dev, "could not create sysfs file\n"); 420 dev_warn(&pdev->dev, "could not create sysfs file\n");
413 421
414 BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier); 422 ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
415 423
416 twl->irq_enabled = true; 424 twl->irq_enabled = true;
417 status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, 425 status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
@@ -437,7 +445,9 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
437 return status; 445 return status;
438 } 446 }
439 447
448 twl->asleep = 0;
440 pdata->phy_init(dev); 449 pdata->phy_init(dev);
450 twl6030_phy_suspend(&twl->otg, 0);
441 twl6030_enable_irq(&twl->otg); 451 twl6030_enable_irq(&twl->otg);
442 dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); 452 dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
443 453