From df8923da19429824de5a442cc571398f5b9ce7c9 Mon Sep 17 00:00:00 2001 From: Sakethram Bommisetti Date: Tue, 15 Nov 2011 13:49:23 +0530 Subject: u8500:USB:Handle multiple Link status fn calls During boot time, multiple calls are made to Link status function by otg_set_host and otg_set_peripheral. This in turn calls clock and regulator enabling multiple times which creates problem with the reference count of regulators. Hence this blocks the CPU idle since the regulators are not released properly due to multiple acquire. So, Link status function calls are removed from otg_set_host and otg_set_peripheral which are not needed. The Link status call during boot shall be handled by the ab8500_usb_boot_detect function. ST-Ericsson ID: 373105 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I2ead5b546273be822b3e9e9f588a1954b3fa10f2 Signed-off-by: Sakethram Bommisetti --- drivers/usb/otg/ab8500-usb.c | 67 ++++---------------------------------------- 1 file changed, 6 insertions(+), 61 deletions(-) diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index ed82c9859b9..511dd058cd1 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -478,23 +478,13 @@ static int ab8500_usb_set_peripheral(struct otg_transceiver *otg, ab = xceiv_to_ab(otg); + ab->otg.gadget = gadget; /* Some drivers call this function in atomic context. * Do not update ab8500 registers directly till this * is fixed. */ - - if (!gadget) { - ab->otg.gadget = NULL; + if (!gadget) schedule_work(&ab->phy_dis_work); - } else { - ab->otg.gadget = gadget; - - /* Phy will not be enabled if cable is already - * plugged-in. Schedule to enable phy. - * Use same delay to avoid any race condition. - */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); - } return 0; } @@ -509,22 +499,14 @@ static int ab8500_usb_set_host(struct otg_transceiver *otg, ab = xceiv_to_ab(otg); + ab->otg.host = host; + /* Some drivers call this function in atomic context. * Do not update ab8500 registers directly till this * is fixed. */ - - if (!host) { - ab->otg.host = NULL; + if (!host) schedule_work(&ab->phy_dis_work); - } else { - ab->otg.host = host; - /* Phy will not be enabled if cable is already - * plugged-in. Schedule to enable phy. - * Use same delay to avoid any race condition. - */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); - } return 0; } @@ -536,11 +518,6 @@ static int ab8500_usb_set_host(struct otg_transceiver *otg, */ static int ab8500_usb_boot_detect(struct ab8500_usb *ab) { - int err; - struct device *device = ab->dev; - u8 usb_status = 0; - u8 val = 0; - /* Disabling PHY before selective enable or disable */ abx500_mask_and_set_register_interruptible(ab->dev, AB8500_USB, @@ -570,39 +547,7 @@ static int ab8500_usb_boot_detect(struct ab8500_usb *ab) AB8500_BIT_PHY_CTRL_HOST_EN, 0); - - err = abx500_get_register_interruptible(device, - AB8500_INTERRUPT, AB8500_IT_SOURCE20_REG, - &usb_status); - if (err < 0) { - dev_err(device, "Read IT 20 failed\n"); - return err; - } - - if (usb_status & AB8500_SRC_INT_USB_HOST) - ab8500_usb_host_phy_en(ab); - - - err = abx500_get_register_interruptible(device, - AB8500_INTERRUPT, AB8500_IT_SOURCE2_REG, - &usb_status); - if (err < 0) { - dev_err(device, "Read IT 2 failed\n"); - return err; - } - - if (usb_status & AB8500_SRC_INT_USB_DEVICE) { - /* Check if it is a dedicated charger */ - (void)abx500_get_register_interruptible(device, - AB8500_USB, AB8500_USB_LINE_STAT_REG, &val); - - val = (val >> 3) & 0x0F; - - if (val == USB_LINK_DEDICATED_CHG) - ab->mode = USB_DEDICATED_CHG; - else - ab8500_usb_peri_phy_en(ab); - } + ab8500_usb_link_status_update(ab); return 0; } -- cgit v1.2.3 From 387120c164d27475bbaea872636fed9400b07ebb Mon Sep 17 00:00:00 2001 From: Thirupathi Chippakurthy Date: Wed, 23 Nov 2011 18:07:24 +0530 Subject: musb: host: Wait for TXPKTRDY to clear in host MUSB_TXCSR_TXPKTRDY will not get cleared if the data is not on the bus. So, need to wait for it to clear in the DMA completion callback.As per musb datasheet, generally mode 1 needs to be used for data length greater than or equal to max packet size. Bus reset happening due to scsi timeout,since in this case should not return continue for next transfers. ST-Ericsson ID:ER 365087 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: NA Signed-off-by: Thirupathi --- drivers/usb/musb/musb_host.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 07e25fa1bf2..f12b046b0d6 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1169,7 +1169,6 @@ void musb_host_tx(struct musb *musb, u8 epnum) } while ((tx_csr & MUSB_TXCSR_TXPKTRDY) != 0); dev_dbg(musb->controller, "TXPKTRDY Cleared. Continue...\n"); - return; } else if (tx_csr & MUSB_TXCSR_H_NAKTIMEOUT) { dev_dbg(musb->controller, "TX end=%d device not responding\n", epnum); -- cgit v1.2.3 From d1c951bf6d73d7daaf74bb8e0f83e02531b0f7f6 Mon Sep 17 00:00:00 2001 From: Thirupathi Chippakurthy Date: Tue, 29 Nov 2011 18:37:44 +0530 Subject: ux500: usb:handle connection of microA to A cable Connect Micro-A to phone first,Then connect device usb session should be valid to detect the connected device,Until host cable (micro-A) removal. MUSB session bit is cleared when usb host cable (Micro-A) removal from the phone,Not in case of only device disconnection from the usb host cable. ST-Ericsson ID: 364426 ST-Ericsson FOSS-OUT ID: NA ST-Ericsson Linux next: NA Signed-off-by: Thirupathi --- drivers/usb/musb/ux500.c | 14 ++++++++++---- drivers/usb/otg/ab8500-usb.c | 9 ++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 9eaa8b1a8df..2b63da5d48a 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -228,11 +228,15 @@ static void musb_notify_idle(unsigned long _musb) 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); + if (devctl & MUSB_DEVCTL_BDEVICE) { + musb->xceiv->state = OTG_STATE_B_IDLE; + MUSB_DEV_MODE(musb); + } else { + musb->xceiv->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + } break; + case OTG_STATE_A_SUSPEND: default: break; @@ -261,6 +265,8 @@ static int musb_otg_notifications(struct notifier_block *nb, case USB_EVENT_NONE: dev_dbg(musb->controller, "VBUS Disconnect\n"); + if (is_otg_enabled(musb)) + ux500_musb_set_vbus(musb, 0); break; default: diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index 511dd058cd1..881729da89c 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -391,10 +391,17 @@ static void ab8500_usb_delayed_work(struct work_struct *work) static irqreturn_t ab8500_usb_disconnect_irq(int irq, void *data) { struct ab8500_usb *ab = (struct ab8500_usb *) data; + enum usb_xceiv_events event; /* Link status will not be updated till phy is disabled. */ - if (ab->mode == USB_HOST) + if (ab->mode == USB_HOST) { + event = USB_EVENT_NONE; + ab->otg.default_a = false; + ab->vbus_draw = 0; + atomic_notifier_call_chain(&ab->otg.notifier, + event, &ab->vbus_draw); ab8500_usb_host_phy_dis(ab); + } else if (ab->mode == USB_PERIPHERAL) ab8500_usb_peri_phy_dis(ab); else if (ab->mode == USB_DEDICATED_CHG && ab->rev == 0x20) { -- cgit v1.2.3