From patchwork Sun Mar 10 01:07:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grazvydas Ignotas X-Patchwork-Id: 2242761 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 801403FCF2 for ; Sun, 10 Mar 2013 01:08:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751852Ab3CJBI0 (ORCPT ); Sat, 9 Mar 2013 20:08:26 -0500 Received: from mail-ee0-f54.google.com ([74.125.83.54]:50962 "EHLO mail-ee0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751523Ab3CJBIT (ORCPT ); Sat, 9 Mar 2013 20:08:19 -0500 Received: by mail-ee0-f54.google.com with SMTP id c41so1673000eek.41 for ; Sat, 09 Mar 2013 17:08:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=Avk4XfH+XYMI/bCHA+SitSmO6afAu8CypFJvzECS1ek=; b=HtrcAm/Pqy2649iA1D10/CQVGY9GTkRQ8sdKWoYyIi8FJnvyYcAgI997FULUi24MLG gxxCN4YGwGKcm8rwiejb1MwM2SSriV/d8ie+z9FpUSd5uFIJLsYj6DAroKca5EaMDaqb C62KH+vSuVGBkL+bA7gdsbPMQy/qjVY7bbY0CRV6umFPeBWtfgGfXgTpBtHNdwA8JBqs JR2XulHqjJC8dUm/1Ki3UB0MDuxa0b2ru1cVnqnpzJYOqf693XCQqQau5GFMj5FxE97r hI3kOu/VTMt8FLaWZH1AqMGWpZ7LYXDon9hZkJjfQ0ACOMQQY7PcEky+9zfrXvrS7LD4 hHuA== X-Received: by 10.15.22.197 with SMTP id f45mr20291673eeu.46.1362877697616; Sat, 09 Mar 2013 17:08:17 -0800 (PST) Received: from localhost.localdomain (ip-88-119-226-136.static.b4net.lt. [88.119.226.136]) by mx.google.com with ESMTPS id ca4sm12081493eeb.15.2013.03.09.17.08.16 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 09 Mar 2013 17:08:16 -0800 (PST) From: Grazvydas Ignotas To: linux-usb@vger.kernel.org Cc: linux-omap@vger.kernel.org, Felipe Balbi , NeilBrown , Grazvydas Ignotas Subject: [PATCH 4/7] usb: otg: twl4030-usb: poll for ID disconnect Date: Sun, 10 Mar 2013 03:07:58 +0200 Message-Id: <1362877681-8102-5-git-send-email-notasas@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1362877681-8102-1-git-send-email-notasas@gmail.com> References: <1362877681-8102-1-git-send-email-notasas@gmail.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org On pandora, STS_USB interrupt doesn't arrive on USB host cable disconnect for some reason while VBUS is driven by twl itself, but STS_HW_CONDITIONS is updated correctly. It does work fine when PHY is powered down though. To work around that we have to poll. TI PSP kernels have similar workarounds, so (many?) more boards are likely affected. Signed-off-by: Grazvydas Ignotas --- drivers/usb/otg/twl4030-usb.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 90a19ff..2c1c27e 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -163,6 +163,8 @@ struct twl4030_usb { bool vbus_supplied; u8 asleep; bool irq_enabled; + + struct delayed_work id_workaround_work; }; /* internal define on top of container_of */ @@ -412,6 +414,16 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) __twl4030_phy_resume(twl); twl->asleep = 0; dev_dbg(twl->dev, "%s\n", __func__); + + /* + * XXX When VBUS gets driven after musb goes to A mode, + * ID_PRES related interrupts no longer arrive, why? + * Register itself is updated fine though, so we must poll. + */ + if (twl->linkstat == OMAP_MUSB_ID_GROUND) { + cancel_delayed_work(&twl->id_workaround_work); + schedule_delayed_work(&twl->id_workaround_work, HZ); + } } static int twl4030_usb_ldo_init(struct twl4030_usb *twl) @@ -513,6 +525,28 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) return IRQ_HANDLED; } +static void twl4030_id_workaround_work(struct work_struct *work) +{ + struct twl4030_usb *twl = container_of(work, struct twl4030_usb, + id_workaround_work.work); + enum omap_musb_vbus_id_status status_prev = twl->linkstat; + enum omap_musb_vbus_id_status status; + + status = twl4030_usb_linkstat(twl); + if (status != status_prev) { + dev_dbg(twl->dev, "handle missing status change: %d->%d\n", + status_prev, status); + twl->linkstat = status_prev; + twl4030_usb_irq(0, twl); + } + + /* don't schedule during sleep - irq works right then */ + if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { + cancel_delayed_work(&twl->id_workaround_work); + schedule_delayed_work(&twl->id_workaround_work, HZ); + } +} + static void twl4030_usb_phy_init(struct twl4030_usb *twl) { enum omap_musb_vbus_id_status status; @@ -613,6 +647,8 @@ static int twl4030_usb_probe(struct platform_device *pdev) /* init spinlock for workqueue */ spin_lock_init(&twl->lock); + INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work); + err = twl4030_usb_ldo_init(twl); if (err) { dev_err(&pdev->dev, "ldo init failed\n"); @@ -653,6 +689,7 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; + cancel_delayed_work(&twl->id_workaround_work); free_irq(twl->irq, twl); device_remove_file(twl->dev, &dev_attr_vbus);