aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg/twl4030-usb.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/otg/twl4030-usb.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/usb/otg/twl4030-usb.c')
-rw-r--r--drivers/usb/otg/twl4030-usb.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 0bc97698af15..efeb4d1517ff 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -124,7 +124,6 @@
124#define PHY_DPLL_CLK (1 << 0) 124#define PHY_DPLL_CLK (1 << 0)
125 125
126/* In module TWL4030_MODULE_PM_MASTER */ 126/* In module TWL4030_MODULE_PM_MASTER */
127#define PROTECT_KEY 0x0E
128#define STS_HW_CONDITIONS 0x0F 127#define STS_HW_CONDITIONS 0x0F
129 128
130/* In module TWL4030_MODULE_PM_RECEIVER */ 129/* In module TWL4030_MODULE_PM_RECEIVER */
@@ -161,6 +160,7 @@ struct twl4030_usb {
161 160
162 int irq; 161 int irq;
163 u8 linkstat; 162 u8 linkstat;
163 bool vbus_supplied;
164 u8 asleep; 164 u8 asleep;
165 bool irq_enabled; 165 bool irq_enabled;
166}; 166};
@@ -251,6 +251,8 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl)
251 int status; 251 int status;
252 int linkstat = USB_EVENT_NONE; 252 int linkstat = USB_EVENT_NONE;
253 253
254 twl->vbus_supplied = false;
255
254 /* 256 /*
255 * For ID/VBUS sensing, see manual section 15.4.8 ... 257 * For ID/VBUS sensing, see manual section 15.4.8 ...
256 * except when using only battery backup power, two 258 * except when using only battery backup power, two
@@ -266,6 +268,9 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl)
266 if (status < 0) 268 if (status < 0)
267 dev_err(twl->dev, "USB link status err %d\n", status); 269 dev_err(twl->dev, "USB link status err %d\n", status);
268 else if (status & (BIT(7) | BIT(2))) { 270 else if (status & (BIT(7) | BIT(2))) {
271 if (status & (BIT(7)))
272 twl->vbus_supplied = true;
273
269 if (status & BIT(2)) 274 if (status & BIT(2))
270 linkstat = USB_EVENT_ID; 275 linkstat = USB_EVENT_ID;
271 else 276 else
@@ -276,6 +281,8 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl)
276 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", 281 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
277 status, status, linkstat); 282 status, status, linkstat);
278 283
284 twl->otg.last_event = linkstat;
285
279 /* REVISIT this assumes host and peripheral controllers 286 /* REVISIT this assumes host and peripheral controllers
280 * are registered, and that both are active... 287 * are registered, and that both are active...
281 */ 288 */
@@ -418,8 +425,13 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
418static int twl4030_usb_ldo_init(struct twl4030_usb *twl) 425static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
419{ 426{
420 /* Enable writing to power configuration registers */ 427 /* Enable writing to power configuration registers */
421 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); 428 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
422 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); 429 TWL4030_PM_MASTER_KEY_CFG1,
430 TWL4030_PM_MASTER_PROTECT_KEY);
431
432 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
433 TWL4030_PM_MASTER_KEY_CFG2,
434 TWL4030_PM_MASTER_PROTECT_KEY);
423 435
424 /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ 436 /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
425 /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ 437 /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
@@ -455,7 +467,8 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
455 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); 467 twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
456 468
457 /* disable access to power configuration registers */ 469 /* disable access to power configuration registers */
458 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); 470 twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
471 TWL4030_PM_MASTER_PROTECT_KEY);
459 472
460 return 0; 473 return 0;
461 474
@@ -477,7 +490,7 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev,
477 490
478 spin_lock_irqsave(&twl->lock, flags); 491 spin_lock_irqsave(&twl->lock, flags);
479 ret = sprintf(buf, "%s\n", 492 ret = sprintf(buf, "%s\n",
480 (twl->linkstat == USB_EVENT_VBUS) ? "on" : "off"); 493 twl->vbus_supplied ? "on" : "off");
481 spin_unlock_irqrestore(&twl->lock, flags); 494 spin_unlock_irqrestore(&twl->lock, flags);
482 495
483 return ret; 496 return ret;
@@ -507,7 +520,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
507 else 520 else
508 twl4030_phy_resume(twl); 521 twl4030_phy_resume(twl);
509 522
510 blocking_notifier_call_chain(&twl->otg.notifier, status, 523 atomic_notifier_call_chain(&twl->otg.notifier, status,
511 twl->otg.gadget); 524 twl->otg.gadget);
512 } 525 }
513 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 526 sysfs_notify(&twl->dev->kobj, NULL, "vbus");
@@ -529,7 +542,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
529 twl->asleep = 0; 542 twl->asleep = 0;
530 } 543 }
531 544
532 blocking_notifier_call_chain(&twl->otg.notifier, status, 545 atomic_notifier_call_chain(&twl->otg.notifier, status,
533 twl->otg.gadget); 546 twl->otg.gadget);
534 } 547 }
535 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 548 sysfs_notify(&twl->dev->kobj, NULL, "vbus");
@@ -601,6 +614,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
601 twl->otg.set_peripheral = twl4030_set_peripheral; 614 twl->otg.set_peripheral = twl4030_set_peripheral;
602 twl->otg.set_suspend = twl4030_set_suspend; 615 twl->otg.set_suspend = twl4030_set_suspend;
603 twl->usb_mode = pdata->usb_mode; 616 twl->usb_mode = pdata->usb_mode;
617 twl->vbus_supplied = false;
604 twl->asleep = 1; 618 twl->asleep = 1;
605 619
606 /* init spinlock for workqueue */ 620 /* init spinlock for workqueue */
@@ -618,7 +632,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
618 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 632 if (device_create_file(&pdev->dev, &dev_attr_vbus))
619 dev_warn(&pdev->dev, "could not create sysfs file\n"); 633 dev_warn(&pdev->dev, "could not create sysfs file\n");
620 634
621 BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier); 635 ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
622 636
623 /* Our job is to use irqs and status from the power module 637 /* Our job is to use irqs and status from the power module
624 * to keep the transceiver disabled when nothing's connected. 638 * to keep the transceiver disabled when nothing's connected.
@@ -673,7 +687,8 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)
673 /* disable complete OTG block */ 687 /* disable complete OTG block */
674 twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); 688 twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
675 689
676 twl4030_phy_power(twl, 0); 690 if (!twl->asleep)
691 twl4030_phy_power(twl, 0);
677 regulator_put(twl->usb1v5); 692 regulator_put(twl->usb1v5);
678 regulator_put(twl->usb1v8); 693 regulator_put(twl->usb1v8);
679 regulator_put(twl->usb3v1); 694 regulator_put(twl->usb3v1);