From patchwork Fri Feb 23 16:05:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13569400 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 47FAEC54798 for ; Fri, 23 Feb 2024 16:06:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References:Message-Id :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=5n/MSyulGTESnwXspVdEHrEiD4wORkm+/b+0ru3kzXE=; b=RtWR42uVYHxilD u3KIbblK4CDOPvGfPu27Z1PotpKVbi+ESqqOhWnKe+G4wc+R0AusWTS4mES6PnSxCv0DYVGYv/G7h lcje6Gc1qjJUuZbgeGplH40PXnjLjiem++3SOw3EiOSdH+7CmoB4iXt8ojEmlXqlYfILwfIDxqj4m SsCGLrD5uc/NMCLlsGwpe/NR4tGu3LyGR/YGwiOf0Cn9ZG7BVJ49uTQgoDfiNizCJ7aQeA63wxIJ/ Z3tFDX2Fq4yku4POevlnsUisPsbRK3MNIpxkbGysv4UaB9SrzrwtKPgn4HRd4IWhwike8x/4AkZXK mKe7GdpB+Q9rOuFigOwQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rdY3U-0000000A81Y-1GB5; Fri, 23 Feb 2024 16:05:44 +0000 Received: from relay5-d.mail.gandi.net ([2001:4b98:dc4:8::225]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rdY3M-0000000A7wZ-1dgU for linux-arm-kernel@lists.infradead.org; Fri, 23 Feb 2024 16:05:38 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id E90951C0006; Fri, 23 Feb 2024 16:05:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1708704333; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=G36dyCsQS4BXpbV31b880qblN6dPbFme1l75T2Hw+Zk=; b=drQue52ulO+fuP1tUE11b21wt5CykxH2xQBy3/wI1NsvFmYUQsP5Pu8sX79JledvSmebZE INzRYr5fgMHge+zoW8S4PgVmcH/BK5jStiwnqU2h4dgG7stSNXTKqXyRwZY235LZMEORpr QwrmGtm58EW/INkHY3YgIaENj0HK/2rBkVtIzSTjttXK6sLL1Q6aZoFA8Sr9apEsrAb4Cm oRP04uQwJ6E84JcxjUEF4w6Q7WnxQqpwRwMMFkz0DeMqAAqYWSQu2w5PnNllgIREKIFBoK W/e1ctnjlUMERh85pezeu9GBN+k83wVPTb+AUMLl7OWqYOc0ef/0EP4GOaI23Q== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 23 Feb 2024 17:05:27 +0100 Subject: [PATCH v3 3/8] usb: cdns3-ti: move reg writes from probe into ->runtime_resume() MIME-Version: 1.0 Message-Id: <20240223-j7200-usb-suspend-v3-3-b41c9893a130@bootlin.com> References: <20240223-j7200-usb-suspend-v3-0-b41c9893a130@bootlin.com> In-Reply-To: <20240223-j7200-usb-suspend-v3-0-b41c9893a130@bootlin.com> To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Roger Quadros , Peter Chen , Pawel Laszczak , Nishanth Menon , Vignesh Raghavendra , Tero Kristo Cc: Thomas Petazzoni , =?utf-8?q?Gr=C3=A9gory_?= =?utf-8?q?Clement?= , Kevin Hilman , Alan Stern , linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240223_080536_857312_8735DAB4 X-CRM114-Status: GOOD ( 18.48 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The hardware initialisation register write sequence is only used at probe. Move it from being done at explicitely at probe to being done implicitely by pm_runtime_get_sync() that calls ->runtime_resume(). Keep devicetree parsing in probe and add a new field in the private struct to remember the USB2 refclk rate code computation result. This opens the door to having the init sequence being executed later down the road, at system-wide resume for example. This is NOT currently happening because runtime PM is disabled at suspend without the refcount being affected. Signed-off-by: Théo Lebrun --- drivers/usb/cdns3/cdns3-ti.c | 90 +++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c index 5945c4b1e11f..4c8a557e6a6f 100644 --- a/drivers/usb/cdns3/cdns3-ti.c +++ b/drivers/usb/cdns3/cdns3-ti.c @@ -57,6 +57,7 @@ struct cdns_ti { unsigned vbus_divider:1; struct clk *usb2_refclk; struct clk *lpm_clk; + int usb2_refclk_rate_code; }; static const int cdns_ti_rate_table[] = { /* in KHZ */ @@ -90,10 +91,8 @@ static int cdns_ti_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *node = pdev->dev.of_node; struct cdns_ti *data; - int error; - u32 reg; - int rate_code, i; unsigned long rate; + int error, i; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -133,7 +132,9 @@ static int cdns_ti_probe(struct platform_device *pdev) return -EINVAL; } - rate_code = i; + data->usb2_refclk_rate_code = i; + data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider"); + data->usb2_only = device_property_read_bool(dev, "ti,usb2-only"); pm_runtime_enable(dev); error = pm_runtime_get_sync(dev); @@ -142,40 +143,6 @@ static int cdns_ti_probe(struct platform_device *pdev) goto err; } - /* assert RESET */ - reg = cdns_ti_readl(data, USBSS_W1); - reg &= ~USBSS_W1_PWRUP_RST; - cdns_ti_writel(data, USBSS_W1, reg); - - /* set static config */ - reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); - reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK; - reg |= rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT; - - reg &= ~USBSS1_STATIC_VBUS_SEL_MASK; - data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider"); - if (data->vbus_divider) - reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT; - - cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg); - reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); - - /* set USB2_ONLY mode if requested */ - reg = cdns_ti_readl(data, USBSS_W1); - data->usb2_only = device_property_read_bool(dev, "ti,usb2-only"); - if (data->usb2_only) - reg |= USBSS_W1_USB2_ONLY; - - /* set default modestrap */ - reg |= USBSS_W1_MODESTRAP_SEL; - reg &= ~USBSS_W1_MODESTRAP_MASK; - reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT; - cdns_ti_writel(data, USBSS_W1, reg); - - /* de-assert RESET */ - reg |= USBSS_W1_PWRUP_RST; - cdns_ti_writel(data, USBSS_W1, reg); - error = of_platform_populate(node, NULL, NULL, dev); if (error) { dev_err(dev, "failed to create children: %d\n", error); @@ -211,6 +178,52 @@ static void cdns_ti_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); } +static int cdns_ti_runtime_resume(struct device *dev) +{ + struct cdns_ti *data = dev_get_drvdata(dev); + u32 reg; + + /* assert RESET */ + reg = cdns_ti_readl(data, USBSS_W1); + reg &= ~USBSS_W1_PWRUP_RST; + cdns_ti_writel(data, USBSS_W1, reg); + + /* set static config */ + reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); + reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK; + reg |= data->usb2_refclk_rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT; + + reg &= ~USBSS1_STATIC_VBUS_SEL_MASK; + + if (data->vbus_divider) + reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT; + + cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg); + reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); + + /* set USB2_ONLY mode if requested */ + reg = cdns_ti_readl(data, USBSS_W1); + + if (data->usb2_only) + reg |= USBSS_W1_USB2_ONLY; + + /* set default modestrap */ + reg |= USBSS_W1_MODESTRAP_SEL; + reg &= ~USBSS_W1_MODESTRAP_MASK; + reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT; + cdns_ti_writel(data, USBSS_W1, reg); + + /* de-assert RESET */ + reg |= USBSS_W1_PWRUP_RST; + cdns_ti_writel(data, USBSS_W1, reg); + + return 0; +} + +static const struct dev_pm_ops cdns_ti_pm_ops = { + RUNTIME_PM_OPS(NULL, cdns_ti_runtime_resume, NULL) +}; + static const struct of_device_id cdns_ti_of_match[] = { { .compatible = "ti,j721e-usb", }, { .compatible = "ti,am64-usb", }, @@ -224,6 +237,7 @@ static struct platform_driver cdns_ti_driver = { .driver = { .name = "cdns3-ti", .of_match_table = cdns_ti_of_match, + .pm = pm_ptr(&cdns_ti_pm_ops), }, };