summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSakethram Bommisetti <sakethram.bommisetti@stericsson.com>2011-09-22 15:15:47 +0530
committerSrinidhi KASAGAR <srinidhi.kasagar@stericsson.com>2011-09-27 08:42:31 +0200
commitb75313d0a9177ea4e43a99dffe001485871652ba (patch)
tree7cd7fe53f83d366d5892c22a215f2685a032854f
parentb986d4e86ab7beb5562716d1721c9d4c6ba6de98 (diff)
ux500:USB:Handing the state machine for Host and Device modes
Setting the default state OTG_STATE_B_IDLE when there is removal of USB cable(Either Host or Device). ST-Ericsson ID: 363539 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: NA Change-Id: Ia066f9a1cb3433bc54bc934f9b0e9eeaf222f89b Signed-off-by: Sakethram Bommisetti <sakethram.bommisetti@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31860 Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com> Reviewed-by: Praveena NADAHALLY <praveen.nadahally@stericsson.com> Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
-rw-r--r--drivers/usb/musb/ux500.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index f860b5ce59a..95f7fa4a831 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -37,6 +37,32 @@ struct ux500_glue {
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
+static struct timer_list notify_timer;
+
+static void musb_notify_idle(unsigned long _musb)
+{
+ struct musb *musb = (void *)_musb;
+ unsigned long flags;
+
+ u8 devctl;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ devctl &= ~MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ break;
+ case OTG_STATE_A_SUSPEND:
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
/* blocking notifier support */
static int musb_otg_notifications(struct notifier_block *nb,
unsigned long event, void *unused)
@@ -126,6 +152,40 @@ static void ux500_musb_set_vbus(struct musb *musb, int is_on)
musb_readb(musb->mregs, MUSB_DEVCTL));
}
+static void ux500_musb_try_idle(struct musb *musb, unsigned long timeout)
+{
+ static unsigned long last_timer;
+
+ if (timeout == 0)
+ timeout = jiffies + msecs_to_jiffies(3);
+
+ /* Never idle if active, or when VBUS timeout is not set as host */
+ if (musb->is_active || ((musb->a_wait_bcon == 0)
+ && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
+ dev_dbg(musb->controller, "%s active, deleting timer\n",
+ otg_state_string(musb->xceiv->state));
+ del_timer(&notify_timer);
+ last_timer = jiffies;
+ return;
+ }
+
+ if (time_after(last_timer, timeout)) {
+ if (!timer_pending(&notify_timer))
+ last_timer = timeout;
+ else {
+ dev_dbg(musb->controller, "Longer idle timer "
+ "already pending, ignoring\n");
+ return;
+ }
+ }
+ last_timer = timeout;
+
+ dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
+ otg_state_string(musb->xceiv->state),
+ (unsigned long)jiffies_to_msecs(timeout - jiffies));
+ mod_timer(&notify_timer, timeout);
+}
+
static int ux500_musb_init(struct musb *musb)
{
int status;
@@ -143,6 +203,8 @@ static int ux500_musb_init(struct musb *musb)
goto err1;
}
+ setup_timer(&notify_timer, musb_notify_idle, (unsigned long) musb);
+
return 0;
err1:
return status;
@@ -166,6 +228,7 @@ static const struct musb_platform_ops ux500_ops = {
.exit = ux500_musb_exit,
.set_vbus = ux500_musb_set_vbus,
+ .try_idle = ux500_musb_try_idle,
};
/**