From patchwork Thu Apr 19 11:03:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 133755 Delivered-To: patch@linaro.org Received: by 10.46.66.142 with SMTP id h14csp496742ljf; Thu, 19 Apr 2018 04:05:00 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/GJfYU/XRoDcVBPBylTHyHR5wMiqXknLR1xi5H0sPUQ0tXOzDc+1tpZ2reSv0PQJYo+nnJ X-Received: by 10.98.27.13 with SMTP id b13mr5444978pfb.254.1524135900426; Thu, 19 Apr 2018 04:05:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524135900; cv=none; d=google.com; s=arc-20160816; b=Vx7eJz8LhnM3RXXzP+S7SqG8wKZz23KFISC6/udSMAyWxlT+Kh9hZ/N8lXMmRF6r+l vQJxx/7ipvciJipFGnjXwwL5gwWCxGJlA1oDf7rzJkOl8b2ga7lsZMzHgAX17RAG3kkX kyJmQVLma3aVGv5yDErywtEhxY9TEZNc7G0t04ksq6g+XzOcn9t1cR3RAT1Mdc3CGcgh AFO45YP0KDPrsKxn+1OTidjZ+lfllW2tjNMS4bt9ulmgFuWMtz9Co3pegwQZWVu0oPLL vuJrUQjnqZoPjj1vtmStskbsHkYPQPrZNWe+5ymhPHASmvoHgkHzRB5BAQ+xyDWXr3eB ZK7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:dkim-filter :arc-authentication-results; bh=gmLG3aLJOXND0/s3i7yNkV+rfqnJW1BajHRrtXTiX+I=; b=Yg6dQq09gq49XxUYjZpa0ATnK8JxCSl0CIwIY5HovDzek+3Rzq9Dkf9z4XH9o7feVV JmHM7dbTe8cP/PZ+mqcqVqFNQlAtAC71CQtdzD+5Gi0BIDZoVu1VVz7VJ2B6U75x+9RO n3uWB5JSETKGfsF2C1MGvnXhcC9cTY9MuHLGnrFJJ90CqU5aw63m8J/RECgBD6dde7ui nljXvtVrcbnAg1hOG4PrHe2dcCx+Gs8LVNL0amzZnx9evM9V3+CJ7Q1+5csb2gxJEXUP wKntxZu8CMovyiasqJhOThWm2skFyghasWT4VYEPTX1AYkAMroJALfjMSJ2YJpo6mAKQ qvWw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@nifty.com header.s=dec2015msa header.b=bdXAf2nv; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x10si3208178pfh.85.2018.04.19.04.05.00; Thu, 19 Apr 2018 04:05:00 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@nifty.com header.s=dec2015msa header.b=bdXAf2nv; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751420AbeDSLE7 (ORCPT + 6 others); Thu, 19 Apr 2018 07:04:59 -0400 Received: from conuserg-11.nifty.com ([210.131.2.78]:21468 "EHLO conuserg-11.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751168AbeDSLE5 (ORCPT ); Thu, 19 Apr 2018 07:04:57 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-11.nifty.com with ESMTP id w3JB42us024223; Thu, 19 Apr 2018 20:04:05 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-11.nifty.com w3JB42us024223 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1524135846; bh=XOhdjxxnobuxpEtybpk81F84gRJ4Z7rS7l8ZmVyxYEw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bdXAf2nv9JnAEiavYmh5uJuIOxxCKy1/XIuGJpbCdaJkSigWo3QyXSF8mspDs+6Xv 3VuDPDtfV6agobJXXxtVKq75VvpyoSXbHBdU3kUGVVJBJujNlfGdbNfR6Wgy75Y1R/ NsIYZzAwleU6uv9yJTpcBjf+6k+KdVdl/OvKPKzuXsTG1kECrVAbmPcguyt23p6Tgh IZandbnkGvrnV5W0YfB6QBzcx1OwZz6FWOP+8mI7+MqmBjwTyZ/e+PThZ0H9UZnxcs +/cL5KmIJfp86wRlY1sn2rEEkidIBhrrfW25mdbe0GEfI0DS3Sg/T1DPD++8aqPLjX /TNWb7FISL7QA== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-usb@vger.kernel.org, Felipe Balbi Cc: Rob Herring , Roger Quadros , Martin Blumenstingl , Masami Hiramatsu , Jassi Brar , Kunihiko Hayashi , Masahiro Yamada , devicetree@vger.kernel.org, Felipe Balbi , linux-kernel@vger.kernel.org, Rob Herring , Greg Kroah-Hartman , Mark Rutland Subject: [PATCH v2 2/2] usb: dwc3: support clocks and resets for DWC3 core Date: Thu, 19 Apr 2018 20:03:38 +0900 Message-Id: <1524135818-14825-3-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1524135818-14825-1-git-send-email-yamada.masahiro@socionext.com> References: <1524135818-14825-1-git-send-email-yamada.masahiro@socionext.com> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Historically, the clocks and resets are handled on the glue layer side instead of the DWC3 core. For simple cases, dwc3-of-simple.c takes care of arbitrary number of clocks and resets. The DT node structure typically looks like as follows: dwc3-glue { compatible = "foo,dwc3"; clocks = ...; resets = ...; ... dwc3 { compatible = "snps,dwc3"; ... }; } By supporting the clocks and the reset in the dwc3/core.c, it will be turned into a single node: dwc3 { compatible = "foo,dwc3", "snps,dwc3"; clocks = ...; resets = ...; ... } This commit adds the binding of clocks and resets specific to this IP. The number of clocks should generally be the same across SoCs, it is just some SoCs either tie clocks together or do not provide software control of some of the clocks. I took the clock names from the Synopsys datasheet: "ref" (ref_clk), "bus_early" (bus_clk_early), and "suspend" (suspend_clk). I found only one reset line in the datasheet, hence the reset-names property is omitted. Supporting those clocks and resets is the requirement for new platforms. Enforcing the new binding breaks existing platforms since they specify clocks and resets in their glue layer node, but nothing in the core node. I listed such exceptional cases in the DT binding. The driver code is loosened up to accept no clock/reset. This change is based on the discussion [1]. I inserted reset_control_deassert() and clk_bulk_enable() before the first register access, i.e. dwc3_cache_hwparams(). [1] https://patchwork.kernel.org/patch/10284265/ Signed-off-by: Masahiro Yamada --- Changes in v2: - Make clocks specific to this IP based on Synopsys datasheet - Use clk_bulk API - Add description to struct header Documentation/devicetree/bindings/usb/dwc3.txt | 21 ++++++ drivers/usb/dwc3/core.c | 89 +++++++++++++++++++++++++- drivers/usb/dwc3/core.h | 8 +++ 3 files changed, 116 insertions(+), 2 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Reviewed-by: Rob Herring diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 0dbd308..feb1cc33 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -7,6 +7,27 @@ Required properties: - compatible: must be "snps,dwc3" - reg : Address and length of the register set for the device - interrupts: Interrupts used by the dwc3 controller. + - clock-names: should contain "ref", "bus_early", "suspend" + - clocks: list of phandle and clock specifier pairs corresponding to + entries in the clock-names property. + - resets: a single pair of phandle and reset specifier + +Exception for clocks and resets: + clocks and resets are optional if the parent node (i.e. glue-layer) + is compatible to one of the following: + "amlogic,meson-axg-dwc3" + "amlogic,meson-gxl-dwc3" + "cavium,octeon-7130-usb-uctl" + "qcom,dwc3" + "samsung,exynos5250-dwusb3" + "samsung,exynos7-dwusb3" + "sprd,sc9860-dwc3" + "st,stih407-dwc3" + "ti,am437x-dwc3" + "ti,dwc3" + "ti,keystone-dwc3" + "rockchip,rk3399-dwc3" + "xlnx,zynqmp-dwc3" Optional properties: - usb-phy : array of phandle for the PHY device. The first element diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 8e66edd..15e1613 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -8,6 +8,7 @@ * Sebastian Andrzej Siewior */ +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -266,6 +268,12 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) return 0; } +static const struct clk_bulk_data dwc3_core_clks[] = { + { .id = "ref" }, + { .id = "bus_early" }, + { .id = "suspend" }, +}; + /* * dwc3_frame_length_adjustment - Adjusts frame length if required * @dwc3: Pointer to our controller context structure @@ -667,6 +675,9 @@ static void dwc3_core_exit(struct dwc3 *dwc) usb_phy_set_suspend(dwc->usb3_phy, 1); phy_power_off(dwc->usb2_generic_phy); phy_power_off(dwc->usb3_generic_phy); + clk_bulk_disable(dwc->num_clks, dwc->clks); + clk_bulk_unprepare(dwc->num_clks, dwc->clks); + reset_control_assert(dwc->reset); } static bool dwc3_core_is_valid(struct dwc3 *dwc) @@ -1256,6 +1267,12 @@ static int dwc3_probe(struct platform_device *pdev) if (!dwc) return -ENOMEM; + dwc->clks = devm_kmemdup(dev, dwc3_core_clks, sizeof(dwc3_core_clks), + GFP_KERNEL); + if (!dwc->clks) + return -ENOMEM; + + dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1286,6 +1303,33 @@ static int dwc3_probe(struct platform_device *pdev) dwc3_get_properties(dwc); + /* Reset is optional to save existing platforms. */ + dwc->reset = devm_reset_control_get_optional_shared(dev, NULL); + if (IS_ERR(dwc->reset)) + return PTR_ERR(dwc->reset); + + ret = clk_bulk_get(dev, dwc->num_clks, dwc->clks); + if (ret == -EPROBE_DEFER) + return ret; + /* + * Clocks are optional to save existing platforms. New platforms should + * support all clocks as required by the DT-binding. + */ + if (ret) + dwc->num_clks = 0; + + ret = reset_control_deassert(dwc->reset); + if (ret) + goto put_clks; + + ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); + if (ret) + goto assert_reset; + + ret = clk_bulk_enable(dwc->num_clks, dwc->clks); + if (ret) + goto unprepare_clks; + platform_set_drvdata(pdev, dwc); dwc3_cache_hwparams(dwc); @@ -1349,6 +1393,14 @@ static int dwc3_probe(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); + clk_bulk_disable(dwc->num_clks, dwc->clks); +unprepare_clks: + clk_bulk_unprepare(dwc->num_clks, dwc->clks); +assert_reset: + reset_control_assert(dwc->reset); +put_clks: + clk_bulk_put(dwc->num_clks, dwc->clks); + return ret; } @@ -1370,11 +1422,44 @@ static int dwc3_remove(struct platform_device *pdev) dwc3_free_event_buffers(dwc); dwc3_free_scratch_buffers(dwc); + clk_bulk_put(dwc->num_clks, dwc->clks); return 0; } #ifdef CONFIG_PM +static int dwc3_core_init_for_resume(struct dwc3 *dwc) +{ + int ret; + + ret = reset_control_deassert(dwc->reset); + if (ret) + return ret; + + ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); + if (ret) + goto assert_reset; + + ret = clk_bulk_enable(dwc->num_clks, dwc->clks); + if (ret) + goto unprepare_clks; + + ret = dwc3_core_init(dwc); + if (ret) + goto disable_clks; + + return 0; + +disable_clks: + clk_bulk_disable(dwc->num_clks, dwc->clks); +unprepare_clks: + clk_bulk_unprepare(dwc->num_clks, dwc->clks); +assert_reset: + reset_control_assert(dwc->reset); + + return ret; +} + static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) { unsigned long flags; @@ -1420,7 +1505,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) switch (dwc->current_dr_role) { case DWC3_GCTL_PRTCAP_DEVICE: - ret = dwc3_core_init(dwc); + ret = dwc3_core_init_for_resume(dwc); if (ret) return ret; @@ -1432,7 +1517,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) case DWC3_GCTL_PRTCAP_HOST: /* nothing to do on host runtime_resume */ if (!PMSG_IS_AUTO(msg)) { - ret = dwc3_core_init(dwc); + ret = dwc3_core_init_for_resume(dwc); if (ret) return ret; dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4f3b438..1765e01 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -891,6 +891,9 @@ struct dwc3_scratchpad_array { * @eps: endpoint array * @gadget: device side representation of the peripheral controller * @gadget_driver: pointer to the gadget driver + * @clks: array of clocks + * @num_clks: number of clocks + * @reset: reset control * @regs: base address for our registers * @regs_size: address space size * @fladj: frame length adjustment @@ -1013,6 +1016,11 @@ struct dwc3 { struct usb_gadget gadget; struct usb_gadget_driver *gadget_driver; + struct clk_bulk_data *clks; + int num_clks; + + struct reset_control *reset; + struct usb_phy *usb2_phy; struct usb_phy *usb3_phy;