From patchwork Tue Jan 20 21:23:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sylvain Rochet X-Patchwork-Id: 5672371 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 07B51C058D for ; Tue, 20 Jan 2015 21:26:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C385E204EB for ; Tue, 20 Jan 2015 21:26:13 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BED6A204EC for ; Tue, 20 Jan 2015 21:26:12 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YDgHm-0008LN-Lt; Tue, 20 Jan 2015 21:24:30 +0000 Received: from mx-guillaumet.finsecur.com ([91.217.234.131] helo=guillaumet.finsecur.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YDgHG-000812-50 for linux-arm-kernel@lists.infradead.org; Tue, 20 Jan 2015 21:24:00 +0000 Received: from [172.16.8.13] (helo=spice.lan) by guillaumet.finsecur.com with esmtps (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1YDgGq-0006pR-0U; Tue, 20 Jan 2015 22:23:32 +0100 Received: from gradator by spice.lan with local (Exim 4.84) (envelope-from ) id 1YDgGp-0005sF-P5; Tue, 20 Jan 2015 22:23:31 +0100 From: Sylvain Rochet To: Boris Brezillon , Alexandre Belloni , plagnioj@jcrosoft.com, nicolas.ferre@atmel.com, linux-arm-kernel@lists.infradead.org, voice.shen@atmel.com, Felipe Balbi , Greg Kroah-Hartman , linux-usb@vger.kernel.org, Wenyou Yang Date: Tue, 20 Jan 2015 22:23:29 +0100 Message-Id: <1421789010-21900-3-git-send-email-sylvain.rochet@finsecur.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1421789010-21900-1-git-send-email-sylvain.rochet@finsecur.com> References: <1421789010-21900-1-git-send-email-sylvain.rochet@finsecur.com> X-SA-Exim-Connect-IP: 172.16.8.13 X-SA-Exim-Mail-From: sylvain.rochet@finsecur.com X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Subject: [PATCHv4 2/3] USB: gadget: atmel_usba_udc: Enable Vbus signal IRQ in UDC start instead of UDC probe X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:24:06 +0000) X-SA-Exim-Scanned: Yes (on guillaumet.finsecur.com) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150120_132358_414192_DE311EE5 X-CRM114-Status: GOOD ( 15.20 ) X-Spam-Score: -0.7 (/) Cc: Sylvain Rochet X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Vbus IRQ handler needs a started UDC driver to work because it uses udc->driver, which is set by the UDC start handler. The previous way chosen was to return from interrupt if udc->driver is NULL using a spinlock. This patch now request the Vbus signal IRQ in UDC start instead of UDC probe and release the IRQ in UDC stop before udc->driver is set back to NULL. This way we don't need the check about udc->driver in interruption handler, therefore we don't need the spinlock as well anymore. This was chosen against using set_irq_flags() to request a not auto enabled IRQ (IRQF_NOAUTOEN flag) because set_irq_flags() can't change just one flag, therefore it must be called with all flags, without respecting what the AIC previously did. Naively copying IRQ flags currently set by the AIC looked like error-prone if defaults flags change at some point in the future. Signed-off-by: Sylvain Rochet Suggested-by: Boris Brezillon --- drivers/usb/gadget/udc/atmel_usba_udc.c | 64 ++++++++++++++++----------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index e207d75..546da63 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -1729,10 +1729,6 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid) spin_lock(&udc->lock); - /* May happen if Vbus pin toggles during probe() */ - if (!udc->driver) - goto out; - vbus = vbus_is_present(udc); if (vbus != udc->vbus_prev) { if (vbus) { @@ -1753,7 +1749,6 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid) udc->vbus_prev = vbus; } -out: spin_unlock(&udc->lock); return IRQ_HANDLED; @@ -1767,23 +1762,27 @@ static int atmel_usba_start(struct usb_gadget *gadget, unsigned long flags; spin_lock_irqsave(&udc->lock, flags); - udc->devstatus = 1 << USB_DEVICE_SELF_POWERED; udc->driver = driver; spin_unlock_irqrestore(&udc->lock, flags); ret = clk_prepare_enable(udc->pclk); if (ret) - return ret; + goto err_pclk; ret = clk_prepare_enable(udc->hclk); - if (ret) { - clk_disable_unprepare(udc->pclk); - return ret; - } + if (ret) + goto err_hclk; udc->vbus_prev = 0; - if (gpio_is_valid(udc->vbus_pin)) - enable_irq(gpio_to_irq(udc->vbus_pin)); + if (gpio_is_valid(udc->vbus_pin)) { + ret = request_irq(gpio_to_irq(udc->vbus_pin), + usba_vbus_irq, 0, + "atmel_usba_udc", udc); + if (ret) { + udc->vbus_pin = -ENODEV; + goto err; + } + } /* If Vbus is present, enable the controller and wait for reset */ spin_lock_irqsave(&udc->lock, flags); @@ -1797,6 +1796,17 @@ static int atmel_usba_start(struct usb_gadget *gadget, spin_unlock_irqrestore(&udc->lock, flags); return 0; + +err: + clk_disable_unprepare(udc->hclk); +err_hclk: + clk_disable_unprepare(udc->pclk); +err_pclk: + spin_lock_irqsave(&udc->lock, flags); + udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); + udc->driver = NULL; + spin_unlock_irqrestore(&udc->lock, flags); + return ret; } static int atmel_usba_stop(struct usb_gadget *gadget) @@ -1805,7 +1815,7 @@ static int atmel_usba_stop(struct usb_gadget *gadget) unsigned long flags; if (gpio_is_valid(udc->vbus_pin)) - disable_irq(gpio_to_irq(udc->vbus_pin)); + free_irq(gpio_to_irq(udc->vbus_pin), udc); spin_lock_irqsave(&udc->lock, flags); udc->gadget.speed = USB_SPEED_UNKNOWN; @@ -2047,24 +2057,14 @@ static int usba_udc_probe(struct platform_device *pdev) } udc->irq = irq; - if (gpio_is_valid(udc->vbus_pin)) { - if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) { - ret = devm_request_irq(&pdev->dev, - gpio_to_irq(udc->vbus_pin), - usba_vbus_irq, 0, - "atmel_usba_udc", udc); - if (ret) { - udc->vbus_pin = -ENODEV; - dev_warn(&udc->pdev->dev, - "failed to request vbus irq; " - "assuming always on\n"); - } else { - disable_irq(gpio_to_irq(udc->vbus_pin)); - } - } else { - /* gpio_request fail so use -EINVAL for gpio_is_valid */ - udc->vbus_pin = -EINVAL; - } + if (gpio_is_valid(udc->vbus_pin) + && devm_gpio_request(&pdev->dev, udc->vbus_pin, + "atmel_usba_udc")) { + /* gpio_request fail so use -EINVAL for gpio_is_valid */ + udc->vbus_pin = -EINVAL; + dev_warn(&udc->pdev->dev, + "failed to request vbus gpio; " + "assuming always on\n"); } ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);