From patchwork Mon Jun 5 09:42:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrice CHOTARD X-Patchwork-Id: 771176 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3wh96x2BfJz9s2P for ; Mon, 5 Jun 2017 19:50:49 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 0D63DC21C73; Mon, 5 Jun 2017 09:49:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=RCVD_IN_DNSWL_LOW autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id B8300C21C2B; Mon, 5 Jun 2017 09:43:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 96E91C21C95; Mon, 5 Jun 2017 09:42:41 +0000 (UTC) Received: from mx07-00178001.pphosted.com (mx08-00178001.pphosted.com [91.207.212.93]) by lists.denx.de (Postfix) with ESMTPS id A6E59C21C32 for ; Mon, 5 Jun 2017 09:42:38 +0000 (UTC) Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v559db5V002191; Mon, 5 Jun 2017 11:42:37 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-.pphosted.com with ESMTP id 2aum0d934r-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Mon, 05 Jun 2017 11:42:37 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id E20173D; Mon, 5 Jun 2017 09:42:35 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id AB66FE5E; Mon, 5 Jun 2017 09:42:35 +0000 (GMT) Received: from localhost (10.75.127.44) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1178.4; Mon, 5 Jun 2017 11:42:35 +0200 From: To: Marek Vasut , , Date: Mon, 5 Jun 2017 11:42:07 +0200 Message-ID: <1496655731-2251-8-git-send-email-patrice.chotard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1496655731-2251-1-git-send-email-patrice.chotard@st.com> References: <1496655731-2251-1-git-send-email-patrice.chotard@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.44] X-ClientProxiedBy: SFHDAG7NODE1.st.com (10.75.127.19) To SFHDAG6NODE3.st.com (10.75.127.18) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-06-05_03:, , signatures=0 Cc: christophe.kerello@st.com Subject: [U-Boot] [PATCH v6 07/11] usb: host: ehci-generic: add error path and .remove callback X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Patrice Chotard Use an array to save enabled clocks reference and deasserted resets in order to respectively disabled and asserted them in case of error during probe() or during driver removal. Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass --- v6: _ none v5: _ none v4: _ update the memory allocation for deasserted resets and enabled clocks reference list. Replace lists by arrays. _ usage of new RESET and CLOCK methods clk_count(), reset_count(), reset_assert_all() and clk_disable_all(). v3: _ keep enabled clocks and deasserted resets reference in list in order to disable clock or assert resets in error path or in .remove callback _ use struct generic_ehci * instead of struct udevice * as parameter for ehci_release_resets() and ehci_release_clocks() drivers/usb/host/ehci-generic.c | 114 +++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 24 deletions(-) diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2116ae1..1250d59 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -18,43 +18,109 @@ */ struct generic_ehci { struct ehci_ctrl ctrl; + struct clk *clocks; + struct reset_ctl *resets; + int clock_count; + int reset_count; }; static int ehci_usb_probe(struct udevice *dev) { + struct generic_ehci *priv = dev_get_priv(dev); struct ehci_hccr *hccr; struct ehci_hcor *hcor; - int i; - - for (i = 0; ; i++) { - struct clk clk; - int ret; - - ret = clk_get_by_index(dev, i, &clk); - if (ret < 0) - break; - if (clk_enable(&clk)) - error("failed to enable clock %d\n", i); - clk_free(&clk); - } + int i, err, ret, clock_nb, reset_nb; + + err = 0; + priv->clock_count = 0; + clock_nb = clk_count(dev); + + if (clock_nb) { + priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb, + GFP_KERNEL); + if (!priv->clocks) { + error("Can't allocate resource\n"); + return -ENOMEM; + } + + for (i = 0; i < clock_nb; i++) { + err = clk_get_by_index(dev, i, &priv->clocks[i]); + + if (err < 0) + break; - for (i = 0; ; i++) { - struct reset_ctl reset; - int ret; + priv->clock_count++; - ret = reset_get_by_index(dev, i, &reset); - if (ret < 0) - break; - if (reset_deassert(&reset)) - error("failed to deassert reset %d\n", i); - reset_free(&reset); + if (clk_enable(&priv->clocks[i])) { + error("failed to enable clock %d\n", i); + clk_free(&priv->clocks[i]); + goto clk_err; + } + clk_free(&priv->clocks[i]); + } } + priv->reset_count = 0; + reset_nb = reset_count(dev); + + if (reset_nb) { + priv->resets = devm_kmalloc(dev, + sizeof(struct reset_ctl) * reset_nb, + GFP_KERNEL); + if (!priv->resets) { + error("Can't allocate resource\n"); + return -ENOMEM; + } + + for (i = 0; i < reset_nb; i++) { + err = reset_get_by_index(dev, i, &priv->resets[i]); + if (err < 0) + break; + + priv->reset_count++; + + if (reset_deassert(&priv->resets[i])) { + error("failed to deassert reset %d\n", i); + reset_free(&priv->resets[i]); + goto reset_err; + } + reset_free(&priv->resets[i]); + } + } hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); + err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); + if (!err) + return err; + +reset_err: + ret = reset_assert_all(priv->resets, priv->reset_count); + if (ret) + return ret; +clk_err: + ret = clk_disable_all(priv->clocks, priv->clock_count); + if (ret) + return ret; + + return err; +} + +static int ehci_usb_remove(struct udevice *dev) +{ + struct generic_ehci *priv = dev_get_priv(dev); + int ret; + + ret = ehci_deregister(dev); + if (ret) + return ret; + + ret = reset_assert_all(priv->resets, priv->reset_count); + if (ret) + return ret; + + return clk_disable_all(priv->clocks, priv->clock_count); } static const struct udevice_id ehci_usb_ids[] = { @@ -67,7 +133,7 @@ U_BOOT_DRIVER(ehci_generic) = { .id = UCLASS_USB, .of_match = ehci_usb_ids, .probe = ehci_usb_probe, - .remove = ehci_deregister, + .remove = ehci_usb_remove, .ops = &ehci_usb_ops, .priv_auto_alloc_size = sizeof(struct generic_ehci), .flags = DM_FLAG_ALLOC_PRIV_DMA,