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.c69
1 files changed, 25 insertions, 44 deletions
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index 0eabb049b6a9..a3d0c0405cca 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -26,10 +26,10 @@
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/usb/otg.h> 28#include <linux/usb/otg.h>
29#include <linux/usb/musb-omap.h>
29#include <linux/i2c/twl.h> 30#include <linux/i2c/twl.h>
30#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
31#include <linux/err.h> 32#include <linux/err.h>
32#include <linux/notifier.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/delay.h> 34#include <linux/delay.h>
35 35
@@ -100,7 +100,7 @@ struct twl6030_usb {
100 100
101 int irq1; 101 int irq1;
102 int irq2; 102 int irq2;
103 u8 linkstat; 103 enum omap_musb_vbus_id_status linkstat;
104 u8 asleep; 104 u8 asleep;
105 bool irq_enabled; 105 bool irq_enabled;
106 bool vbus_enable; 106 bool vbus_enable;
@@ -147,7 +147,7 @@ static int twl6030_phy_init(struct usb_phy *x)
147 dev = twl->dev; 147 dev = twl->dev;
148 pdata = dev->platform_data; 148 pdata = dev->platform_data;
149 149
150 if (twl->linkstat == USB_EVENT_ID) 150 if (twl->linkstat == OMAP_MUSB_ID_GROUND)
151 pdata->phy_power(twl->dev, 1, 1); 151 pdata->phy_power(twl->dev, 1, 1);
152 else 152 else
153 pdata->phy_power(twl->dev, 0, 1); 153 pdata->phy_power(twl->dev, 0, 1);
@@ -235,13 +235,13 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev,
235 spin_lock_irqsave(&twl->lock, flags); 235 spin_lock_irqsave(&twl->lock, flags);
236 236
237 switch (twl->linkstat) { 237 switch (twl->linkstat) {
238 case USB_EVENT_VBUS: 238 case OMAP_MUSB_VBUS_VALID:
239 ret = snprintf(buf, PAGE_SIZE, "vbus\n"); 239 ret = snprintf(buf, PAGE_SIZE, "vbus\n");
240 break; 240 break;
241 case USB_EVENT_ID: 241 case OMAP_MUSB_ID_GROUND:
242 ret = snprintf(buf, PAGE_SIZE, "id\n"); 242 ret = snprintf(buf, PAGE_SIZE, "id\n");
243 break; 243 break;
244 case USB_EVENT_NONE: 244 case OMAP_MUSB_VBUS_OFF:
245 ret = snprintf(buf, PAGE_SIZE, "none\n"); 245 ret = snprintf(buf, PAGE_SIZE, "none\n");
246 break; 246 break;
247 default: 247 default:
@@ -256,8 +256,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
256static irqreturn_t twl6030_usb_irq(int irq, void *_twl) 256static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
257{ 257{
258 struct twl6030_usb *twl = _twl; 258 struct twl6030_usb *twl = _twl;
259 struct usb_otg *otg = twl->phy.otg; 259 enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
260 int status;
261 u8 vbus_state, hw_state; 260 u8 vbus_state, hw_state;
262 261
263 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 262 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -268,22 +267,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
268 if (vbus_state & VBUS_DET) { 267 if (vbus_state & VBUS_DET) {
269 regulator_enable(twl->usb3v3); 268 regulator_enable(twl->usb3v3);
270 twl->asleep = 1; 269 twl->asleep = 1;
271 status = USB_EVENT_VBUS; 270 status = OMAP_MUSB_VBUS_VALID;
272 otg->default_a = false;
273 twl->phy.state = OTG_STATE_B_IDLE;
274 twl->linkstat = status; 271 twl->linkstat = status;
275 twl->phy.last_event = status; 272 omap_musb_mailbox(status);
276 atomic_notifier_call_chain(&twl->phy.notifier,
277 status, otg->gadget);
278 } else { 273 } else {
279 status = USB_EVENT_NONE; 274 if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
280 twl->linkstat = status; 275 status = OMAP_MUSB_VBUS_OFF;
281 twl->phy.last_event = status; 276 twl->linkstat = status;
282 atomic_notifier_call_chain(&twl->phy.notifier, 277 omap_musb_mailbox(status);
283 status, otg->gadget); 278 if (twl->asleep) {
284 if (twl->asleep) { 279 regulator_disable(twl->usb3v3);
285 regulator_disable(twl->usb3v3); 280 twl->asleep = 0;
286 twl->asleep = 0; 281 }
287 } 282 }
288 } 283 }
289 } 284 }
@@ -295,8 +290,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
295static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) 290static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
296{ 291{
297 struct twl6030_usb *twl = _twl; 292 struct twl6030_usb *twl = _twl;
298 struct usb_otg *otg = twl->phy.otg; 293 enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
299 int status = USB_EVENT_NONE;
300 u8 hw_state; 294 u8 hw_state;
301 295
302 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 296 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -307,13 +301,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
307 twl->asleep = 1; 301 twl->asleep = 1;
308 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); 302 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
309 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); 303 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
310 status = USB_EVENT_ID; 304 status = OMAP_MUSB_ID_GROUND;
311 otg->default_a = true; 305 otg->default_a = true;
312 twl->phy.state = OTG_STATE_A_IDLE; 306 twl->phy.state = OTG_STATE_A_IDLE;
313 twl->linkstat = status; 307 twl->linkstat = status;
314 twl->phy.last_event = status; 308 omap_musb_mailbox(status);
315 atomic_notifier_call_chain(&twl->phy.notifier, status,
316 otg->gadget);
317 } else { 309 } else {
318 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); 310 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
319 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); 311 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
@@ -402,20 +394,19 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
402 struct device *dev = &pdev->dev; 394 struct device *dev = &pdev->dev;
403 pdata = dev->platform_data; 395 pdata = dev->platform_data;
404 396
405 twl = kzalloc(sizeof *twl, GFP_KERNEL); 397 twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
406 if (!twl) 398 if (!twl)
407 return -ENOMEM; 399 return -ENOMEM;
408 400
409 otg = kzalloc(sizeof *otg, GFP_KERNEL); 401 otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL);
410 if (!otg) { 402 if (!otg)
411 kfree(twl);
412 return -ENOMEM; 403 return -ENOMEM;
413 }
414 404
415 twl->dev = &pdev->dev; 405 twl->dev = &pdev->dev;
416 twl->irq1 = platform_get_irq(pdev, 0); 406 twl->irq1 = platform_get_irq(pdev, 0);
417 twl->irq2 = platform_get_irq(pdev, 1); 407 twl->irq2 = platform_get_irq(pdev, 1);
418 twl->features = pdata->features; 408 twl->features = pdata->features;
409 twl->linkstat = OMAP_MUSB_UNKNOWN;
419 410
420 twl->phy.dev = twl->dev; 411 twl->phy.dev = twl->dev;
421 twl->phy.label = "twl6030"; 412 twl->phy.label = "twl6030";
@@ -436,18 +427,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
436 err = twl6030_usb_ldo_init(twl); 427 err = twl6030_usb_ldo_init(twl);
437 if (err) { 428 if (err) {
438 dev_err(&pdev->dev, "ldo init failed\n"); 429 dev_err(&pdev->dev, "ldo init failed\n");
439 kfree(otg);
440 kfree(twl);
441 return err; 430 return err;
442 } 431 }
443 usb_set_transceiver(&twl->phy); 432 usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
444 433
445 platform_set_drvdata(pdev, twl); 434 platform_set_drvdata(pdev, twl);
446 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 435 if (device_create_file(&pdev->dev, &dev_attr_vbus))
447 dev_warn(&pdev->dev, "could not create sysfs file\n"); 436 dev_warn(&pdev->dev, "could not create sysfs file\n");
448 437
449 ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
450
451 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); 438 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
452 439
453 twl->irq_enabled = true; 440 twl->irq_enabled = true;
@@ -458,8 +445,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
458 dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", 445 dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
459 twl->irq1, status); 446 twl->irq1, status);
460 device_remove_file(twl->dev, &dev_attr_vbus); 447 device_remove_file(twl->dev, &dev_attr_vbus);
461 kfree(otg);
462 kfree(twl);
463 return status; 448 return status;
464 } 449 }
465 450
@@ -471,8 +456,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
471 twl->irq2, status); 456 twl->irq2, status);
472 free_irq(twl->irq1, twl); 457 free_irq(twl->irq1, twl);
473 device_remove_file(twl->dev, &dev_attr_vbus); 458 device_remove_file(twl->dev, &dev_attr_vbus);
474 kfree(otg);
475 kfree(twl);
476 return status; 459 return status;
477 } 460 }
478 461
@@ -503,8 +486,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
503 pdata->phy_exit(twl->dev); 486 pdata->phy_exit(twl->dev);
504 device_remove_file(twl->dev, &dev_attr_vbus); 487 device_remove_file(twl->dev, &dev_attr_vbus);
505 cancel_work_sync(&twl->set_vbus_work); 488 cancel_work_sync(&twl->set_vbus_work);
506 kfree(twl->phy.otg);
507 kfree(twl);
508 489
509 return 0; 490 return 0;
510} 491}