aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/musb/omap2430.c94
-rw-r--r--drivers/usb/otg/twl4030-usb.c46
-rw-r--r--drivers/usb/otg/twl6030-usb.c47
-rw-r--r--include/linux/usb/musb-omap.h30
4 files changed, 133 insertions, 84 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index f40c8053a291..063687085d1e 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -34,6 +34,7 @@
34#include <linux/dma-mapping.h> 34#include <linux/dma-mapping.h>
35#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
36#include <linux/err.h> 36#include <linux/err.h>
37#include <linux/usb/musb-omap.h>
37 38
38#include "musb_core.h" 39#include "musb_core.h"
39#include "omap2430.h" 40#include "omap2430.h"
@@ -41,11 +42,13 @@
41struct omap2430_glue { 42struct omap2430_glue {
42 struct device *dev; 43 struct device *dev;
43 struct platform_device *musb; 44 struct platform_device *musb;
44 u8 xceiv_event; 45 enum omap_musb_vbus_id_status status;
45 struct work_struct omap_musb_mailbox_work; 46 struct work_struct omap_musb_mailbox_work;
46}; 47};
47#define glue_to_musb(g) platform_get_drvdata(g->musb) 48#define glue_to_musb(g) platform_get_drvdata(g->musb)
48 49
50struct omap2430_glue *_glue;
51
49static struct timer_list musb_idle_timer; 52static struct timer_list musb_idle_timer;
50 53
51static void musb_do_idle(unsigned long _musb) 54static void musb_do_idle(unsigned long _musb)
@@ -225,54 +228,58 @@ static inline void omap2430_low_level_init(struct musb *musb)
225 musb_writel(musb->mregs, OTG_FORCESTDBY, l); 228 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
226} 229}
227 230
228static int musb_otg_notifications(struct notifier_block *nb, 231void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
229 unsigned long event, void *unused)
230{ 232{
231 struct musb *musb = container_of(nb, struct musb, nb); 233 struct omap2430_glue *glue = _glue;
232 struct device *dev = musb->controller; 234 struct musb *musb = glue_to_musb(glue);
233 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
234 235
235 glue->xceiv_event = event; 236 glue->status = status;
236 schedule_work(&glue->omap_musb_mailbox_work); 237 if (!musb) {
238 dev_err(glue->dev, "musb core is not yet ready\n");
239 return;
240 }
237 241
238 return NOTIFY_OK; 242 schedule_work(&glue->omap_musb_mailbox_work);
239} 243}
244EXPORT_SYMBOL_GPL(omap_musb_mailbox);
240 245
241static void omap_musb_mailbox_work(struct work_struct *data_notifier_work) 246static void omap_musb_set_mailbox(struct omap2430_glue *glue)
242{ 247{
243 struct omap2430_glue *glue = container_of(data_notifier_work,
244 struct omap2430_glue, omap_musb_mailbox_work);
245 struct musb *musb = glue_to_musb(glue); 248 struct musb *musb = glue_to_musb(glue);
246 struct device *dev = musb->controller; 249 struct device *dev = musb->controller;
247 struct musb_hdrc_platform_data *pdata = dev->platform_data; 250 struct musb_hdrc_platform_data *pdata = dev->platform_data;
248 struct omap_musb_board_data *data = pdata->board_data; 251 struct omap_musb_board_data *data = pdata->board_data;
249 252
250 switch (glue->xceiv_event) { 253 switch (glue->status) {
251 case USB_EVENT_ID: 254 case OMAP_MUSB_ID_GROUND:
252 dev_dbg(musb->controller, "ID GND\n"); 255 dev_dbg(dev, "ID GND\n");
253 256
257 musb->xceiv->last_event = USB_EVENT_ID;
254 if (!is_otg_enabled(musb) || musb->gadget_driver) { 258 if (!is_otg_enabled(musb) || musb->gadget_driver) {
255 pm_runtime_get_sync(musb->controller); 259 pm_runtime_get_sync(dev);
256 usb_phy_init(musb->xceiv); 260 usb_phy_init(musb->xceiv);
257 omap2430_musb_set_vbus(musb, 1); 261 omap2430_musb_set_vbus(musb, 1);
258 } 262 }
259 break; 263 break;
260 264
261 case USB_EVENT_VBUS: 265 case OMAP_MUSB_VBUS_VALID:
262 dev_dbg(musb->controller, "VBUS Connect\n"); 266 dev_dbg(dev, "VBUS Connect\n");
263 267
268 musb->xceiv->last_event = USB_EVENT_VBUS;
264 if (musb->gadget_driver) 269 if (musb->gadget_driver)
265 pm_runtime_get_sync(musb->controller); 270 pm_runtime_get_sync(dev);
266 usb_phy_init(musb->xceiv); 271 usb_phy_init(musb->xceiv);
267 break; 272 break;
268 273
269 case USB_EVENT_NONE: 274 case OMAP_MUSB_ID_FLOAT:
270 dev_dbg(musb->controller, "VBUS Disconnect\n"); 275 case OMAP_MUSB_VBUS_OFF:
276 dev_dbg(dev, "VBUS Disconnect\n");
271 277
278 musb->xceiv->last_event = USB_EVENT_NONE;
272 if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) 279 if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
273 if (musb->gadget_driver) { 280 if (musb->gadget_driver) {
274 pm_runtime_mark_last_busy(musb->controller); 281 pm_runtime_mark_last_busy(dev);
275 pm_runtime_put_autosuspend(musb->controller); 282 pm_runtime_put_autosuspend(dev);
276 } 283 }
277 284
278 if (data->interface_type == MUSB_INTERFACE_UTMI) { 285 if (data->interface_type == MUSB_INTERFACE_UTMI) {
@@ -282,15 +289,24 @@ static void omap_musb_mailbox_work(struct work_struct *data_notifier_work)
282 usb_phy_shutdown(musb->xceiv); 289 usb_phy_shutdown(musb->xceiv);
283 break; 290 break;
284 default: 291 default:
285 dev_dbg(musb->controller, "ID float\n"); 292 dev_dbg(dev, "ID float\n");
286 } 293 }
287} 294}
288 295
296
297static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
298{
299 struct omap2430_glue *glue = container_of(mailbox_work,
300 struct omap2430_glue, omap_musb_mailbox_work);
301 omap_musb_set_mailbox(glue);
302}
303
289static int omap2430_musb_init(struct musb *musb) 304static int omap2430_musb_init(struct musb *musb)
290{ 305{
291 u32 l; 306 u32 l;
292 int status = 0; 307 int status = 0;
293 struct device *dev = musb->controller; 308 struct device *dev = musb->controller;
309 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
294 struct musb_hdrc_platform_data *plat = dev->platform_data; 310 struct musb_hdrc_platform_data *plat = dev->platform_data;
295 struct omap_musb_board_data *data = plat->board_data; 311 struct omap_musb_board_data *data = plat->board_data;
296 312
@@ -330,14 +346,11 @@ static int omap2430_musb_init(struct musb *musb)
330 musb_readl(musb->mregs, OTG_INTERFSEL), 346 musb_readl(musb->mregs, OTG_INTERFSEL),
331 musb_readl(musb->mregs, OTG_SIMENABLE)); 347 musb_readl(musb->mregs, OTG_SIMENABLE));
332 348
333 musb->nb.notifier_call = musb_otg_notifications;
334 status = usb_register_notifier(musb->xceiv, &musb->nb);
335
336 if (status)
337 dev_dbg(musb->controller, "notification register failed\n");
338
339 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); 349 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
340 350
351 if (glue->status != OMAP_MUSB_UNKNOWN)
352 omap_musb_set_mailbox(glue);
353
341 pm_runtime_put_noidle(musb->controller); 354 pm_runtime_put_noidle(musb->controller);
342 return 0; 355 return 0;
343 356
@@ -350,12 +363,13 @@ static void omap2430_musb_enable(struct musb *musb)
350 u8 devctl; 363 u8 devctl;
351 unsigned long timeout = jiffies + msecs_to_jiffies(1000); 364 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
352 struct device *dev = musb->controller; 365 struct device *dev = musb->controller;
366 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
353 struct musb_hdrc_platform_data *pdata = dev->platform_data; 367 struct musb_hdrc_platform_data *pdata = dev->platform_data;
354 struct omap_musb_board_data *data = pdata->board_data; 368 struct omap_musb_board_data *data = pdata->board_data;
355 369
356 switch (musb->xceiv->last_event) { 370 switch (glue->status) {
357 371
358 case USB_EVENT_ID: 372 case OMAP_MUSB_ID_GROUND:
359 usb_phy_init(musb->xceiv); 373 usb_phy_init(musb->xceiv);
360 if (data->interface_type != MUSB_INTERFACE_UTMI) 374 if (data->interface_type != MUSB_INTERFACE_UTMI)
361 break; 375 break;
@@ -374,7 +388,7 @@ static void omap2430_musb_enable(struct musb *musb)
374 } 388 }
375 break; 389 break;
376 390
377 case USB_EVENT_VBUS: 391 case OMAP_MUSB_VBUS_VALID:
378 usb_phy_init(musb->xceiv); 392 usb_phy_init(musb->xceiv);
379 break; 393 break;
380 394
@@ -385,7 +399,10 @@ static void omap2430_musb_enable(struct musb *musb)
385 399
386static void omap2430_musb_disable(struct musb *musb) 400static void omap2430_musb_disable(struct musb *musb)
387{ 401{
388 if (musb->xceiv->last_event) 402 struct device *dev = musb->controller;
403 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
404
405 if (glue->status != OMAP_MUSB_UNKNOWN)
389 usb_phy_shutdown(musb->xceiv); 406 usb_phy_shutdown(musb->xceiv);
390} 407}
391 408
@@ -439,11 +456,18 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
439 456
440 glue->dev = &pdev->dev; 457 glue->dev = &pdev->dev;
441 glue->musb = musb; 458 glue->musb = musb;
459 glue->status = OMAP_MUSB_UNKNOWN;
442 460
443 pdata->platform_ops = &omap2430_ops; 461 pdata->platform_ops = &omap2430_ops;
444 462
445 platform_set_drvdata(pdev, glue); 463 platform_set_drvdata(pdev, glue);
446 464
465 /*
466 * REVISIT if we ever have two instances of the wrapper, we will be
467 * in big trouble
468 */
469 _glue = glue;
470
447 INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work); 471 INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
448 472
449 ret = platform_device_add_resources(musb, pdev->resource, 473 ret = platform_device_add_resources(musb, pdev->resource,
@@ -552,7 +576,7 @@ static int __init omap2430_init(void)
552{ 576{
553 return platform_driver_register(&omap2430_driver); 577 return platform_driver_register(&omap2430_driver);
554} 578}
555module_init(omap2430_init); 579subsys_initcall(omap2430_init);
556 580
557static void __exit omap2430_exit(void) 581static void __exit omap2430_exit(void)
558{ 582{
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 25a09fabbe35..a7b809e217ea 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -33,11 +33,11 @@
33#include <linux/io.h> 33#include <linux/io.h>
34#include <linux/delay.h> 34#include <linux/delay.h>
35#include <linux/usb/otg.h> 35#include <linux/usb/otg.h>
36#include <linux/usb/musb-omap.h>
36#include <linux/usb/ulpi.h> 37#include <linux/usb/ulpi.h>
37#include <linux/i2c/twl.h> 38#include <linux/i2c/twl.h>
38#include <linux/regulator/consumer.h> 39#include <linux/regulator/consumer.h>
39#include <linux/err.h> 40#include <linux/err.h>
40#include <linux/notifier.h>
41#include <linux/slab.h> 41#include <linux/slab.h>
42 42
43/* Register defines */ 43/* Register defines */
@@ -159,7 +159,7 @@ struct twl4030_usb {
159 enum twl4030_usb_mode usb_mode; 159 enum twl4030_usb_mode usb_mode;
160 160
161 int irq; 161 int irq;
162 u8 linkstat; 162 enum omap_musb_vbus_id_status linkstat;
163 bool vbus_supplied; 163 bool vbus_supplied;
164 u8 asleep; 164 u8 asleep;
165 bool irq_enabled; 165 bool irq_enabled;
@@ -246,10 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
246 246
247/*-------------------------------------------------------------------------*/ 247/*-------------------------------------------------------------------------*/
248 248
249static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) 249static enum omap_musb_vbus_id_status
250 twl4030_usb_linkstat(struct twl4030_usb *twl)
250{ 251{
251 int status; 252 int status;
252 int linkstat = USB_EVENT_NONE; 253 enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
253 struct usb_otg *otg = twl->phy.otg; 254 struct usb_otg *otg = twl->phy.otg;
254 255
255 twl->vbus_supplied = false; 256 twl->vbus_supplied = false;
@@ -273,24 +274,24 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
273 twl->vbus_supplied = true; 274 twl->vbus_supplied = true;
274 275
275 if (status & BIT(2)) 276 if (status & BIT(2))
276 linkstat = USB_EVENT_ID; 277 linkstat = OMAP_MUSB_ID_GROUND;
277 else 278 else
278 linkstat = USB_EVENT_VBUS; 279 linkstat = OMAP_MUSB_VBUS_VALID;
279 } else 280 } else {
280 linkstat = USB_EVENT_NONE; 281 if (twl->linkstat != OMAP_MUSB_UNKNOWN)
282 linkstat = OMAP_MUSB_VBUS_OFF;
283 }
281 284
282 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", 285 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
283 status, status, linkstat); 286 status, status, linkstat);
284 287
285 twl->phy.last_event = linkstat;
286
287 /* REVISIT this assumes host and peripheral controllers 288 /* REVISIT this assumes host and peripheral controllers
288 * are registered, and that both are active... 289 * are registered, and that both are active...
289 */ 290 */
290 291
291 spin_lock_irq(&twl->lock); 292 spin_lock_irq(&twl->lock);
292 twl->linkstat = linkstat; 293 twl->linkstat = linkstat;
293 if (linkstat == USB_EVENT_ID) { 294 if (linkstat == OMAP_MUSB_ID_GROUND) {
294 otg->default_a = true; 295 otg->default_a = true;
295 twl->phy.state = OTG_STATE_A_IDLE; 296 twl->phy.state = OTG_STATE_A_IDLE;
296 } else { 297 } else {
@@ -501,10 +502,10 @@ static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
501static irqreturn_t twl4030_usb_irq(int irq, void *_twl) 502static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
502{ 503{
503 struct twl4030_usb *twl = _twl; 504 struct twl4030_usb *twl = _twl;
504 int status; 505 enum omap_musb_vbus_id_status status;
505 506
506 status = twl4030_usb_linkstat(twl); 507 status = twl4030_usb_linkstat(twl);
507 if (status >= 0) { 508 if (status > 0) {
508 /* FIXME add a set_power() method so that B-devices can 509 /* FIXME add a set_power() method so that B-devices can
509 * configure the charger appropriately. It's not always 510 * configure the charger appropriately. It's not always
510 * correct to consume VBUS power, and how much current to 511 * correct to consume VBUS power, and how much current to
@@ -516,13 +517,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
516 * USB_LINK_VBUS state. musb_hdrc won't care until it 517 * USB_LINK_VBUS state. musb_hdrc won't care until it
517 * starts to handle softconnect right. 518 * starts to handle softconnect right.
518 */ 519 */
519 if (status == USB_EVENT_NONE) 520 if (status == OMAP_MUSB_VBUS_OFF ||
521 status == OMAP_MUSB_ID_FLOAT)
520 twl4030_phy_suspend(twl, 0); 522 twl4030_phy_suspend(twl, 0);
521 else 523 else
522 twl4030_phy_resume(twl); 524 twl4030_phy_resume(twl);
523 525
524 atomic_notifier_call_chain(&twl->phy.notifier, status, 526 omap_musb_mailbox(twl->linkstat);
525 twl->phy.otg->gadget);
526 } 527 }
527 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 528 sysfs_notify(&twl->dev->kobj, NULL, "vbus");
528 529
@@ -531,11 +532,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
531 532
532static void twl4030_usb_phy_init(struct twl4030_usb *twl) 533static void twl4030_usb_phy_init(struct twl4030_usb *twl)
533{ 534{
534 int status; 535 enum omap_musb_vbus_id_status status;
535 536
536 status = twl4030_usb_linkstat(twl); 537 status = twl4030_usb_linkstat(twl);
537 if (status >= 0) { 538 if (status > 0) {
538 if (status == USB_EVENT_NONE) { 539 if (status == OMAP_MUSB_VBUS_OFF ||
540 status == OMAP_MUSB_ID_FLOAT) {
539 __twl4030_phy_power(twl, 0); 541 __twl4030_phy_power(twl, 0);
540 twl->asleep = 1; 542 twl->asleep = 1;
541 } else { 543 } else {
@@ -543,8 +545,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
543 twl->asleep = 0; 545 twl->asleep = 0;
544 } 546 }
545 547
546 atomic_notifier_call_chain(&twl->phy.notifier, status, 548 omap_musb_mailbox(twl->linkstat);
547 twl->phy.otg->gadget);
548 } 549 }
549 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); 550 sysfs_notify(&twl->dev->kobj, NULL, "vbus");
550} 551}
@@ -613,6 +614,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
613 twl->usb_mode = pdata->usb_mode; 614 twl->usb_mode = pdata->usb_mode;
614 twl->vbus_supplied = false; 615 twl->vbus_supplied = false;
615 twl->asleep = 1; 616 twl->asleep = 1;
617 twl->linkstat = OMAP_MUSB_UNKNOWN;
616 618
617 twl->phy.dev = twl->dev; 619 twl->phy.dev = twl->dev;
618 twl->phy.label = "twl4030"; 620 twl->phy.label = "twl4030";
@@ -639,8 +641,6 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
639 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 641 if (device_create_file(&pdev->dev, &dev_attr_vbus))
640 dev_warn(&pdev->dev, "could not create sysfs file\n"); 642 dev_warn(&pdev->dev, "could not create sysfs file\n");
641 643
642 ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
643
644 /* Our job is to use irqs and status from the power module 644 /* Our job is to use irqs and status from the power module
645 * to keep the transceiver disabled when nothing's connected. 645 * to keep the transceiver disabled when nothing's connected.
646 * 646 *
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index dbee00aea755..6c758836cfb1 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:
@@ -257,7 +257,7 @@ static 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 struct usb_otg *otg = twl->phy.otg;
260 int status; 260 enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
261 u8 vbus_state, hw_state; 261 u8 vbus_state, hw_state;
262 262
263 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 263 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -268,22 +268,20 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
268 if (vbus_state & VBUS_DET) { 268 if (vbus_state & VBUS_DET) {
269 regulator_enable(twl->usb3v3); 269 regulator_enable(twl->usb3v3);
270 twl->asleep = 1; 270 twl->asleep = 1;
271 status = USB_EVENT_VBUS; 271 status = OMAP_MUSB_VBUS_VALID;
272 otg->default_a = false; 272 otg->default_a = false;
273 twl->phy.state = OTG_STATE_B_IDLE; 273 twl->phy.state = OTG_STATE_B_IDLE;
274 twl->linkstat = status; 274 twl->linkstat = status;
275 twl->phy.last_event = status; 275 omap_musb_mailbox(status);
276 atomic_notifier_call_chain(&twl->phy.notifier,
277 status, otg->gadget);
278 } else { 276 } else {
279 status = USB_EVENT_NONE; 277 if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
280 twl->linkstat = status; 278 status = OMAP_MUSB_VBUS_OFF;
281 twl->phy.last_event = status; 279 twl->linkstat = status;
282 atomic_notifier_call_chain(&twl->phy.notifier, 280 omap_musb_mailbox(status);
283 status, otg->gadget); 281 if (twl->asleep) {
284 if (twl->asleep) { 282 regulator_disable(twl->usb3v3);
285 regulator_disable(twl->usb3v3); 283 twl->asleep = 0;
286 twl->asleep = 0; 284 }
287 } 285 }
288 } 286 }
289 } 287 }
@@ -296,7 +294,7 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
296{ 294{
297 struct twl6030_usb *twl = _twl; 295 struct twl6030_usb *twl = _twl;
298 struct usb_otg *otg = twl->phy.otg; 296 struct usb_otg *otg = twl->phy.otg;
299 int status = USB_EVENT_NONE; 297 enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
300 u8 hw_state; 298 u8 hw_state;
301 299
302 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); 300 hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -308,13 +306,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
308 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1); 306 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
309 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 307 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
310 0x10); 308 0x10);
311 status = USB_EVENT_ID; 309 status = OMAP_MUSB_ID_GROUND;
312 otg->default_a = true; 310 otg->default_a = true;
313 twl->phy.state = OTG_STATE_A_IDLE; 311 twl->phy.state = OTG_STATE_A_IDLE;
314 twl->linkstat = status; 312 twl->linkstat = status;
315 twl->phy.last_event = status; 313 omap_musb_mailbox(status);
316 atomic_notifier_call_chain(&twl->phy.notifier, status,
317 otg->gadget);
318 } else { 314 } else {
319 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 315 twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
320 0x10); 316 0x10);
@@ -419,6 +415,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
419 twl->irq1 = platform_get_irq(pdev, 0); 415 twl->irq1 = platform_get_irq(pdev, 0);
420 twl->irq2 = platform_get_irq(pdev, 1); 416 twl->irq2 = platform_get_irq(pdev, 1);
421 twl->features = pdata->features; 417 twl->features = pdata->features;
418 twl->linkstat = OMAP_MUSB_UNKNOWN;
422 419
423 twl->phy.dev = twl->dev; 420 twl->phy.dev = twl->dev;
424 twl->phy.label = "twl6030"; 421 twl->phy.label = "twl6030";
@@ -449,8 +446,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
449 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 446 if (device_create_file(&pdev->dev, &dev_attr_vbus))
450 dev_warn(&pdev->dev, "could not create sysfs file\n"); 447 dev_warn(&pdev->dev, "could not create sysfs file\n");
451 448
452 ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
453
454 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); 449 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
455 450
456 twl->irq_enabled = true; 451 twl->irq_enabled = true;
diff --git a/include/linux/usb/musb-omap.h b/include/linux/usb/musb-omap.h
new file mode 100644
index 000000000000..7774c5986f07
--- /dev/null
+++ b/include/linux/usb/musb-omap.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2011-2012 by Texas Instruments
3 *
4 * The Inventra Controller Driver for Linux is free software; you
5 * can redistribute it and/or modify it under the terms of the GNU
6 * General Public License version 2 as published by the Free Software
7 * Foundation.
8 */
9
10#ifndef __MUSB_OMAP_H__
11#define __MUSB_OMAP_H__
12
13enum omap_musb_vbus_id_status {
14 OMAP_MUSB_UNKNOWN = 0,
15 OMAP_MUSB_ID_GROUND,
16 OMAP_MUSB_ID_FLOAT,
17 OMAP_MUSB_VBUS_VALID,
18 OMAP_MUSB_VBUS_OFF,
19};
20
21#if (defined(CONFIG_USB_MUSB_OMAP2PLUS) || \
22 defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE))
23void omap_musb_mailbox(enum omap_musb_vbus_id_status status);
24#else
25static inline void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
26{
27}
28#endif
29
30#endif /* __MUSB_OMAP_H__ */