From nobody Thu Sep 24 15:10:57 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C4FBF3911AF; Tue, 22 Sep 2026 14:46:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088404; cv=none; b=sZnmXX+uBWlsBxAjpj4tsYcuz3kG+OSlzYbNNBELqNbIS7fbTYW9G5udv7rn8kF8d03xdlG6Zra9YOEZxIiBJsftuDKzeUxNhFnD+Vs0aXnZxJKZOVMgtDz2m9d+v9DmJVw4KWA38zBHMEewXxkiA6aQhkpgwjp1JUwNNGro4LM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088404; c=relaxed/simple; bh=1kZch10bGj8PCCnDosR7xVAAGOeC5xf//7Byt2ewcz4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tnngWGn5xM0UyUsdAnGG6Xd6x3pncWsU+bzW7mEYdzUj/RpGq6IcB4rxlsn+vJM7MxXd51CTA/DfUITnzsa1jkI+XoNKxQiKRv/guztsi6ZR9vMWXmuXj9X5hrZq92h0xMJEqYA/dl+auCqWfJEf5pQK6MlW2PBPM5NLA2L7y2M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cgZ2qpZc; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cgZ2qpZc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 871BC1F00899; Tue, 22 Sep 2026 14:46:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790088402; bh=MlpgsnaDiTpidihd3mBcz2ZDd8K8o0293XNhbkNgmmM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=cgZ2qpZcINv5q5/oUFQR2RZdb3XRIVfCbt8mOHnssVxzKyKhbuVjO7AyusulY4nMw A42PJ2VP4PE2sUkuz5WpEm/DxKYtTw8L07HJLp5xai1ngV3grxKIY3KxF+8Bgs2r0j 65S0d2e6zIIk/cuC5oOD29lPcwBQnjp9QvO8FZ2WzgpKD2s1rV/2l69yCDA+byHPVG sdtTh/Qwh9+gtqc6EREYVH4qMHigIv9cECa5jbEFJdkHl2jnfTuZqFETZK5jw1ekNz ujG07RCIzEAVXNINbJL7nHbP5TcsURKD/Y8w7P5gkp0zq1gPGxjkWig1uDIHmBichH yATv0LWPFJAnw== From: Claudiu Beznea To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, p.zabel@pengutronix.de Cc: claudiu.beznea@tuxon.dev, linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Claudiu Beznea , stable@vger.kernel.org Subject: [PATCH v4 1/8] PCI: rzg3s-host: Follow hardware manual clock/reset initialization order Date: Tue, 22 Sep 2026 17:46:21 +0300 Message-ID: <20260922144629.586997-2-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922144629.586997-1-claudiu.beznea@kernel.org> References: <20260922144629.586997-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Claudiu Beznea The RZ/G3S PCIe hardware manual specifies that the clocks must be enabled before the reset signals are deasserted during initialization. Follow this sequence in the probe(), suspend(), and resume() paths to match the hardware requirements and avoid potential issues. Fixes: 7ef502fb35b2 ("PCI: Add Renesas RZ/G3S host controller driver") Cc: stable@vger.kernel.org Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Tested-by: Lad Prabhakar --- Changes in v4: - none Changes in v3: - none, this patch is new drivers/pci/controller/pcie-rzg3s-host.c | 40 +++++++++++++----------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index 077cfb0834b3..e1105b1f2652 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -1888,10 +1888,6 @@ static int rzg3s_pcie_probe(struct platform_device *= pdev) if (ret) goto sysc_signal_restore; =20 - ret =3D rzg3s_pcie_power_resets_deassert(host); - if (ret) - goto sysc_signal_restore; - pm_runtime_enable(dev); =20 /* @@ -1902,12 +1898,16 @@ static int rzg3s_pcie_probe(struct platform_device = *pdev) if (ret) goto rpm_disable; =20 + ret =3D rzg3s_pcie_power_resets_deassert(host); + if (ret) + goto rpm_put; + raw_spin_lock_init(&host->hw_lock); =20 ret =3D rzg3s_pcie_host_setup(host, rzg3s_pcie_init_irqdomain, rzg3s_pcie_teardown_irqdomain); if (ret) - goto rpm_put; + goto power_resets_assert; =20 bridge->sysdata =3D host; bridge->ops =3D &rzg3s_pcie_root_ops; @@ -1922,12 +1922,13 @@ static int rzg3s_pcie_probe(struct platform_device = *pdev) clk_disable_unprepare(host->port.refclk); rzg3s_pcie_teardown_irqdomain(host); host->data->config_deinit(host); +power_resets_assert: + reset_control_bulk_assert(host->data->num_power_resets, + host->power_resets); rpm_put: pm_runtime_put_sync(dev); rpm_disable: pm_runtime_disable(dev); - reset_control_bulk_assert(host->data->num_power_resets, - host->power_resets); sysc_signal_restore: /* * SYSC RST_RSM_B signal need to be asserted before turning off the @@ -1948,10 +1949,6 @@ static int rzg3s_pcie_suspend_noirq(struct device *d= ev) struct rzg3s_sysc *sysc =3D host->sysc; int ret; =20 - ret =3D pm_runtime_put_sync(dev); - if (ret) - return ret; - clk_disable_unprepare(port->refclk); =20 /* SoC-specific de-initialization */ @@ -1964,13 +1961,19 @@ static int rzg3s_pcie_suspend_noirq(struct device *= dev) if (ret) goto config_reinit; =20 - ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); + ret =3D pm_runtime_put_sync(dev); if (ret) goto power_resets_restore; =20 + ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); + if (ret) + goto rpm_resume; + return 0; =20 /* Restore the previous state if any error happens */ +rpm_resume: + pm_runtime_resume_and_get(dev); power_resets_restore: reset_control_bulk_deassert(data->num_power_resets, host->power_resets); @@ -1980,7 +1983,6 @@ static int rzg3s_pcie_suspend_noirq(struct device *de= v) data->config_post_init(host); refclk_restore: clk_prepare_enable(port->refclk); - pm_runtime_resume_and_get(dev); return ret; } =20 @@ -2009,18 +2011,18 @@ static int rzg3s_pcie_resume_noirq(struct device *d= ev) goto assert_rst_rsm_b; } =20 - ret =3D rzg3s_pcie_power_resets_deassert(host); + ret =3D pm_runtime_resume_and_get(dev); if (ret) goto assert_rst_rsm_b; =20 - ret =3D pm_runtime_resume_and_get(dev); + ret =3D rzg3s_pcie_power_resets_deassert(host); if (ret) - goto assert_power_resets; + goto rpm_put; =20 ret =3D rzg3s_pcie_host_setup(host, rzg3s_pcie_msi_hw_setup, rzg3s_pcie_msi_hw_teardown); if (ret) - goto rpm_put; + goto assert_power_resets; =20 return 0; =20 @@ -2028,11 +2030,11 @@ static int rzg3s_pcie_resume_noirq(struct device *d= ev) * If any error happens there is no way to recover the IP. Put it in the * lowest possible power state. */ -rpm_put: - pm_runtime_put_sync(dev); assert_power_resets: reset_control_bulk_assert(data->num_power_resets, host->power_resets); +rpm_put: + pm_runtime_put_sync(dev); assert_rst_rsm_b: rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); return ret; --=20 2.43.0 From nobody Thu Sep 24 15:10:57 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B16C3518159; Tue, 22 Sep 2026 14:46:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088408; cv=none; b=aOx/F7Fp0YoHCTe1lgDvHzjBKGCx1SHvN02pfAAqqymsp349ZBFYNh96gzSRyNE5Gyb8RRG4yY88s3szZde0745x5s4rQ/fcJtdd6Qv3i0eT6ELQWL2QDhH8ZrfRCia8uKnjlK9064HyPJMVaYg5aqSXgGxRqg+zhQxgf2q6T+Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088408; c=relaxed/simple; bh=E4cSuppnIp2pwOfBP/pUAETACaKGAEzCsLOo2D2Ta4o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rIjJEc+iB5qNQWVhwJCjZFpfQuBcmBxuVGn3GaHijPXKm+Td8XgGLIhvjSiuFETq6BGh7P0JdxBFtxGCNjVvZq4IErQ9MQ9pK/qVNVZGI8pDbzTkP7uOKDLvoQWp7Ms5Pk6Nc3jvdqn3OnniXUHObDSAwVT+GJVTfrnRvW5UXUE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VrpDDnjv; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VrpDDnjv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 067D31F000FF; Tue, 22 Sep 2026 14:46:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790088406; bh=fP7jaUZpZpC0yyACVfmaXPb1j6WuKsKDVWes/4ekrk8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=VrpDDnjvzNuAu9gzfSTcFMvhVLbnl0oppvMJVDI/I5WA+v8OJygBw3M2VUTpl7KYI 3CAm2B60beuoNd9YxRkyjJCrm2VRqNCEOM6G8KMCr4TwxXwHhVSiwTTi/PnyX4AlhK WCXMdBKLgc8qgsaVBi13t3vvxnB6W2UMF461BsPjWBYMtkA72l2ZONs2fFCfvaBjMQ H9r4yhHXx2Xz9nhDsxFYkY8S8Rtdm1PAoYjmd4lPgJKnTIX/NFcNHcdx02q7k0TNSZ PJsdHF/PzdDmbIWm0CVJ5+wsJjJ3jygHuefnZEtsI1Y5ejz4XXcxHve5Ux0Akp5E5e rUTlxuFshUCjg== From: Claudiu Beznea To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, p.zabel@pengutronix.de Cc: claudiu.beznea@tuxon.dev, linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Claudiu Beznea , stable@vger.kernel.org Subject: [PATCH v4 2/8] PCI: rzg3s-host: Fix runtime PM handling in the NOIRQ suspend/resume phase Date: Tue, 22 Sep 2026 17:46:22 +0300 Message-ID: <20260922144629.586997-3-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922144629.586997-1-claudiu.beznea@kernel.org> References: <20260922144629.586997-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Claudiu Beznea The runtime PM documentation states the following: - During system suspend, pm_runtime_get_noresume() is called for every device right before executing the subsystem-level .prepare() callback (in device_prepare()). In addition, the PM core disables runtime PM for every device right before executing the subsystem-level .suspend_late() callback (in device_suspend_late()). - During system resume, pm_runtime_enable() is called for every device right after executing the subsystem-level .resume_early() callback (in device_resume_early()), and pm_runtime_put() is called right after executing the subsystem-level .complete() callback (in device_complete()). The driver's .suspend_noirq() callback is invoked after .suspend_late(), while .resume_noirq() is invoked before .resume_early(). If: - the device is not part of the wake-up path, and - its runtime PM status is not RPM_SUSPENDED, the generic power domain .suspend_noirq()/.resume_noirq() callbacks (genpd_suspend_noirq()/genpd_resume_noirq()) invoke the driver's .suspend_noirq()/.resume_noirq() callbacks and call genpd_stop_dev()/genpd_start_dev() before and after them, respectively. Calling genpd_stop_dev()/genpd_start_dev() allows devices whose power is controlled by generic power domains to be powered off and on during system suspend and resume, even though their runtime PM usage count does not reach zero. Since the runtime PM usage count is incremented in device_prepare() and decremented in device_complete(), runtime PM operations performed from the driver's .suspend_noirq()/.resume_noirq() callbacks are no-ops. The actual power transitions are handled by the generic power domain .suspend_noirq()/.resume_noirq() callbacks. Moreover, attempting to runtime resume a device while runtime PM is disabled may return -EACCES. This may cause system resume to fail when resuming after a failed Root Port reset, as described in a subsequent patch adding hot-plug support. Remove the runtime PM calls from the driver's .suspend_noirq()/.resume_noirq() callbacks and rely on the generic power domain callbacks to power the device off and on. Fixes: 7ef502fb35b2 ("PCI: Add Renesas RZ/G3S host controller driver") Cc: stable@vger.kernel.org Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Tested-by: Lad Prabhakar --- Changes in v4: - simplified the comments in rzg3s_pcie_suspend_noirq()/rzg3s_pcie_resume_n= oirq() Changes in v3: - none, this patch is new drivers/pci/controller/pcie-rzg3s-host.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index e1105b1f2652..0ef49bb5ab1a 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -1961,19 +1961,18 @@ static int rzg3s_pcie_suspend_noirq(struct device *= dev) if (ret) goto config_reinit; =20 - ret =3D pm_runtime_put_sync(dev); - if (ret) - goto power_resets_restore; + /* + * Since the power domain's genpd_suspend_noirq() will disable clocks, + * there is no need to manually invoke runtime PM API here. + */ =20 ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); if (ret) - goto rpm_resume; + goto power_resets_restore; =20 return 0; =20 /* Restore the previous state if any error happens */ -rpm_resume: - pm_runtime_resume_and_get(dev); power_resets_restore: reset_control_bulk_deassert(data->num_power_resets, host->power_resets); @@ -2011,13 +2010,14 @@ static int rzg3s_pcie_resume_noirq(struct device *d= ev) goto assert_rst_rsm_b; } =20 - ret =3D pm_runtime_resume_and_get(dev); - if (ret) - goto assert_rst_rsm_b; + /* + * Since the power domain's genpd_resume_noirq() will enable clocks, + * there is no need to manually invoke runtime PM API here. + */ =20 ret =3D rzg3s_pcie_power_resets_deassert(host); if (ret) - goto rpm_put; + goto assert_rst_rsm_b; =20 ret =3D rzg3s_pcie_host_setup(host, rzg3s_pcie_msi_hw_setup, rzg3s_pcie_msi_hw_teardown); @@ -2033,8 +2033,6 @@ static int rzg3s_pcie_resume_noirq(struct device *dev) assert_power_resets: reset_control_bulk_assert(data->num_power_resets, host->power_resets); -rpm_put: - pm_runtime_put_sync(dev); assert_rst_rsm_b: rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); return ret; --=20 2.43.0 From nobody Thu Sep 24 15:10:57 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2659C38F93B; Tue, 22 Sep 2026 14:46:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088411; cv=none; b=k8VGRhzahqsIdZu2lUNMoXyZWCy9nlaisWJOSRrXDP+MtEL437i+wgmbghbDIGMoV9YyjGIKx5m3zEIf/DEnshLdxW6ZTqC8AAjirIv6fbpuDUP46oUWu3g0G71EUWQ9SA9VmiS+xyGGXS3mtSt5lk/B0HGTsaO5JQT4bnOEZ/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088411; c=relaxed/simple; bh=wwufuLELSds9wVTxto/dkja2RbQ8fZWFw747b6hTBaI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cLorIVwmyY4fMCgaLgb/TKPW+xz3GvtFr/nI4CoSYpI1f33cghWoBXhFVNjZFf9endLG2PoTQdwH55m0BJNrcs1GHoPfnbDfUZI+s8UOli/BbaM5vErSUyJ253m9oYIcGyJ9oytIzaalFrvYdkWj/w/nXcqv92ZIzmWXOKC0aP0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ijqDtvNn; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ijqDtvNn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CB13D1F00898; Tue, 22 Sep 2026 14:46:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790088409; bh=4TYtF8vLa45WgaHozUCIJlTCj/3EIrIVec6Tu44b0Uo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ijqDtvNn8KedVa8AGAV4J9pvnyYZufE2KXSg8oKE2iYsgB1nVJcnTjD1Jda9/GYzR 9tSMFK9nppZYvG7NjXhEoiHG0lTj9XGprIJA6vqLAUtZOkMruugajYJ3af/GOidp+Z OxVU6Ja3EBp2mPgEtrCu2la39sse9a6S42oic6wgE58KrWFQt1gsK8pk1jK+eCJ5XR KAnk0NP0+1574EbaAhzLikmOS2i/EQkAEYzroGKATaT7OecVukpSnz9h3YDfdCindc 8jJGxmnFt7Q76TwBFXOR2xp+V7Q9ES9Y83TdvQmmlRGnRLZTphW3S+UqfBQ3kBrFJ6 1AknoAGFznSOg== From: Claudiu Beznea To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, p.zabel@pengutronix.de Cc: claudiu.beznea@tuxon.dev, linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Claudiu Beznea Subject: [PATCH v4 3/8] PCI: rzg3s-host: Drop nop instructions Date: Tue, 22 Sep 2026 17:46:23 +0300 Message-ID: <20260922144629.586997-4-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922144629.586997-1-claudiu.beznea@kernel.org> References: <20260922144629.586997-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Claudiu Beznea On the RZ/G3S PCIe IP variant (which is similar to those used on the RZ/G3E, RZ/V2H, and RZ/V2N SoCs), access to the PCIe Type 1 registers requires setting the PCI_PERM.CFG_HWINIT_EN bit. Since this bit is not set on the code paths where rzg3s_pcie_set_max_link_speed() is called, the writes to PCI_EXP_LNKCTL2.TLS are nops. Drop them. Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Tested-by: Lad Prabhakar --- Changes in v4: - none Changes in v3: - none, this patch is new drivers/pci/controller/pcie-rzg3s-host.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index 0ef49bb5ab1a..362aa923978f 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -1144,11 +1144,6 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3= s_pcie_host *host) remote_supported_link_speeds !=3D max_supported_link_speeds) return 0; =20 - /* Set target Link speed */ - rzg3s_pcie_update_bits(host->pcie, pcie_cap + PCI_EXP_LNKCTL2, - PCI_EXP_LNKCTL2_TLS, - FIELD_PREP(PCI_EXP_LNKCTL2_TLS, link_speed)); - /* Request link speed change */ rzg3s_pcie_update_bits(host->axi, RZG3S_PCI_PCCTRL2, RZG3S_PCI_PCCTRL2_LS_CHG_REQ | --=20 2.43.0 From nobody Thu Sep 24 15:10:57 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6A0254A7C5; Tue, 22 Sep 2026 14:46:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088414; cv=none; b=mpLihmzrvXMnn3nfGFkFuqRvDZ/FgVZzYdSak5gQJxYdZvYDz0R2qGKmYjTYvqKSy7uYOAU0taVYhKnNJItYeiPv1WTBGC8hECG78zQAtfQdY29Xdxc494zBYAo9QhYll4fgO1M9NPW2vzgrzuJ2kUaE2UUOLH3QeSVa3OwbN48= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088414; c=relaxed/simple; bh=io0K/CqdBrXCogNTcvf+KXzDl+H2UCqVqvIVohiFSPU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ggWZGOTvJcmbwhp1+erwKdDh6VdgnQKVWQ/SloEj/7CongdZk5RTuaaHtm6Qi04l+5lWguJBRGrIF5LskVvE2tm3yYK6K7J7B1V5+DFw8X5HyZzQWQRsHLnFlB3d/Fa+aHsm7Chyhbsn7k11GbIHGkazkewL9VTfszY8OPx+LtA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=V4tcwqwj; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="V4tcwqwj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 301161F000FF; Tue, 22 Sep 2026 14:46:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790088412; bh=PNktF+6n/Gs/V1cbxFgmCuRJFNKJvqmwqFpO6sc2PY4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=V4tcwqwjVwn7iAqEH0LAOJLYaxeyP9MRYtBMmXOKceJwhuvCQ9KERVup4BwwEgzv0 6y5M0+qaH4J/0F2pJZe5vRrH0S+IDQhOXN67D66ef1e0v6O610P2Xt4l3HBoTCIutx 0OHy2dIR9wc09+uBSVOe6itVD4/77uYbjWDSoS2XDnpni579+Uj624AMwFqKgPYogQ uOAV92aNe2Xl/ERtSDQYPTS7kjX4X2uv5ZYzQfQHRcH4NLu+6E663exVbGsaGptqFs SoOtplKsnO9DpcbtV2LlrzhQJ/+eL4LNf6NMBYYjKj9WwAcvnVy1EKbsMx8LtNcP86 uOooTAx0FqLGA== From: Claudiu Beznea To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, p.zabel@pengutronix.de Cc: claudiu.beznea@tuxon.dev, linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Claudiu Beznea Subject: [PATCH v4 4/8] PCI: rzg3s-host: Move host configuration code together Date: Tue, 22 Sep 2026 17:46:24 +0300 Message-ID: <20260922144629.586997-5-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922144629.586997-1-claudiu.beznea@kernel.org> References: <20260922144629.586997-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Claudiu Beznea Move host configuration code together to have it grouped. This prepares for the addition of hotplug support. Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Tested-by: Lad Prabhakar --- Changes in v4: - none Changes in v3: - none, this patch is new drivers/pci/controller/pcie-rzg3s-host.c | 230 +++++++++++------------ 1 file changed, 115 insertions(+), 115 deletions(-) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index 362aa923978f..3ecada238402 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -1356,121 +1356,6 @@ static int rzg3s_pcie_resets_prepare_and_get(struct= rzg3s_pcie_host *host) host->cfg_resets); } =20 -static int rzg3s_pcie_host_parse_port(struct rzg3s_pcie_host *host) -{ - struct device_node *of_port __free(device_node) =3D - of_get_next_child(host->dev->of_node, NULL); - struct rzg3s_pcie_port *port =3D &host->port; - int ret; - - ret =3D of_property_read_u32(of_port, "vendor-id", &port->vendor_id); - if (ret) - return ret; - - ret =3D of_property_read_u32(of_port, "device-id", &port->device_id); - if (ret) - return ret; - - port->refclk =3D of_clk_get_by_name(of_port, "ref"); - if (IS_ERR(port->refclk)) - return PTR_ERR(port->refclk); - - return 0; -} - -static int rzg3s_pcie_host_init_port(struct rzg3s_pcie_host *host) -{ - struct rzg3s_pcie_port *port =3D &host->port; - struct device *dev =3D host->dev; - int ret; - - /* Enable access control to the CFGU */ - writel_relaxed(RZG3S_PCI_PERM_CFG_HWINIT_EN, - host->axi + RZG3S_PCI_PERM); - - /* Update vendor ID and device ID */ - writew_relaxed(port->vendor_id, host->pcie + PCI_VENDOR_ID); - writew_relaxed(port->device_id, host->pcie + PCI_DEVICE_ID); - - /* Disable access control to the CFGU */ - writel_relaxed(0, host->axi + RZG3S_PCI_PERM); - - ret =3D clk_prepare_enable(port->refclk); - if (ret) - return dev_err_probe(dev, ret, "Failed to enable refclk!\n"); - - /* Set the PHY, if any */ - if (host->data->init_phy) { - ret =3D host->data->init_phy(host); - if (ret) { - dev_err_probe(dev, ret, "Failed to set the PHY!\n"); - goto refclk_disable; - } - } - - return 0; - -refclk_disable: - clk_disable_unprepare(port->refclk); - return ret; -} - -static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host) -{ - u32 val; - int ret; - - /* SoC-specific pre-configuration */ - if (host->data->config_pre_init) - host->data->config_pre_init(host); - - /* Initialize the PCIe related registers */ - ret =3D rzg3s_pcie_config_init(host); - if (ret) - goto config_deinit; - - ret =3D rzg3s_pcie_host_init_port(host); - if (ret) - goto config_deinit; - - /* Enable ASPM L1 transition for SoCs that use it */ - ret =3D rzg3s_sysc_config_func(host->sysc, - RZG3S_SYSC_FUNC_ID_L1_ALLOW, 1); - if (ret) - goto config_deinit_and_refclk; - - /* Initialize the interrupts */ - rzg3s_pcie_irq_init(host); - - /* SoC-specific post-configuration */ - ret =3D host->data->config_post_init(host); - if (ret) - goto config_deinit_and_refclk; - - /* Wait for link up */ - ret =3D readl_poll_timeout(host->axi + RZG3S_PCI_PCSTAT1, val, - !(val & RZG3S_PCI_PCSTAT1_DL_DOWN_STS), - PCIE_LINK_WAIT_SLEEP_MS * MILLI, - PCIE_LINK_WAIT_SLEEP_MS * MILLI * - PCIE_LINK_WAIT_MAX_RETRIES); - if (ret) - goto config_deinit_post; - - val =3D readl_relaxed(host->axi + RZG3S_PCI_PCSTAT2); - dev_info(host->dev, "PCIe link status [0x%x]\n", val); - - return 0; - -config_deinit_post: - host->data->config_deinit(host); -config_deinit_and_refclk: - clk_disable_unprepare(host->port.refclk); -config_deinit: - if (host->data->config_pre_init) - host->data->config_deinit(host); - return ret; -} - static void rzg3s_pcie_set_inbound_window(struct rzg3s_pcie_host *host, u64 cpu_addr, u64 pci_addr, u64 size, int id) @@ -1698,6 +1583,121 @@ static int rzg3s_soc_pcie_init_phy(struct rzg3s_pci= e_host *host) return 0; } =20 +static int rzg3s_pcie_host_parse_port(struct rzg3s_pcie_host *host) +{ + struct device_node *of_port __free(device_node) =3D + of_get_next_child(host->dev->of_node, NULL); + struct rzg3s_pcie_port *port =3D &host->port; + int ret; + + ret =3D of_property_read_u32(of_port, "vendor-id", &port->vendor_id); + if (ret) + return ret; + + ret =3D of_property_read_u32(of_port, "device-id", &port->device_id); + if (ret) + return ret; + + port->refclk =3D of_clk_get_by_name(of_port, "ref"); + if (IS_ERR(port->refclk)) + return PTR_ERR(port->refclk); + + return 0; +} + +static int rzg3s_pcie_host_init_port(struct rzg3s_pcie_host *host) +{ + struct rzg3s_pcie_port *port =3D &host->port; + struct device *dev =3D host->dev; + int ret; + + /* Enable access control to the CFGU */ + writel_relaxed(RZG3S_PCI_PERM_CFG_HWINIT_EN, + host->axi + RZG3S_PCI_PERM); + + /* Update vendor ID and device ID */ + writew_relaxed(port->vendor_id, host->pcie + PCI_VENDOR_ID); + writew_relaxed(port->device_id, host->pcie + PCI_DEVICE_ID); + + /* Disable access control to the CFGU */ + writel_relaxed(0, host->axi + RZG3S_PCI_PERM); + + ret =3D clk_prepare_enable(port->refclk); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable refclk!\n"); + + /* Set the PHY, if any */ + if (host->data->init_phy) { + ret =3D host->data->init_phy(host); + if (ret) { + dev_err_probe(dev, ret, "Failed to set the PHY!\n"); + goto refclk_disable; + } + } + + return 0; + +refclk_disable: + clk_disable_unprepare(port->refclk); + return ret; +} + +static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host) +{ + u32 val; + int ret; + + /* SoC-specific pre-configuration */ + if (host->data->config_pre_init) + host->data->config_pre_init(host); + + /* Initialize the PCIe related registers */ + ret =3D rzg3s_pcie_config_init(host); + if (ret) + goto config_deinit; + + ret =3D rzg3s_pcie_host_init_port(host); + if (ret) + goto config_deinit; + + /* Enable ASPM L1 transition for SoCs that use it */ + ret =3D rzg3s_sysc_config_func(host->sysc, + RZG3S_SYSC_FUNC_ID_L1_ALLOW, 1); + if (ret) + goto config_deinit_and_refclk; + + /* Initialize the interrupts */ + rzg3s_pcie_irq_init(host); + + /* SoC-specific post-configuration */ + ret =3D host->data->config_post_init(host); + if (ret) + goto config_deinit_and_refclk; + + /* Wait for link up */ + ret =3D readl_poll_timeout(host->axi + RZG3S_PCI_PCSTAT1, val, + !(val & RZG3S_PCI_PCSTAT1_DL_DOWN_STS), + PCIE_LINK_WAIT_SLEEP_MS * MILLI, + PCIE_LINK_WAIT_SLEEP_MS * MILLI * + PCIE_LINK_WAIT_MAX_RETRIES); + if (ret) + goto config_deinit_post; + + val =3D readl_relaxed(host->axi + RZG3S_PCI_PCSTAT2); + dev_info(host->dev, "PCIe link status [0x%x]\n", val); + + return 0; + +config_deinit_post: + host->data->config_deinit(host); +config_deinit_and_refclk: + clk_disable_unprepare(host->port.refclk); +config_deinit: + if (host->data->config_pre_init) + host->data->config_deinit(host); + return ret; +} + static int rzg3s_pcie_host_setup(struct rzg3s_pcie_host *host, int (*init_irqdomain)(struct rzg3s_pcie_host *host), --=20 2.43.0 From nobody Thu Sep 24 15:10:57 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 443A1550DC6; Tue, 22 Sep 2026 14:46:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088417; cv=none; b=d1q04EqefjNVxbbkT9s3ZMGFFeaAxfTI9S2A8GM77gCTPDC35La+tq2Jgy3A/szySzv34+8cpsbwbpYMElKE4P399+kyGOd4MFOMrxgo8iVu3CwM8rfX78yk622C+j/SeO89OMaIYfHOAYoQjC1kRHjKT6OAI+Rc9KEqnfV+mJ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088417; c=relaxed/simple; bh=fhQ7m14xEUAZIkilajcn1iH0SvFTIcgTHDR5cYlVXP4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KkQDupNVCDOWmRI0oq+g0N10fQne6AKwbmppfwTYRekqrJDyKGZ+dL3OGkTbKICy3pjXRxorwGNsDA5ArKpEGNNhwgU/rr/uhaF6ZZQVVXBZDQOPt8iHzFFQfo4Lnps6DVWBlzIachnXR+ZOkvKSIDGVD9jbLQDAB6m1x4jclYc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dTvqgl+Z; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dTvqgl+Z" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E8F71F00893; Tue, 22 Sep 2026 14:46:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790088416; bh=lS2mTdZyVHI8GlU+ga0yqBI6/w5Zg0KCWwB/zVFjIQo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=dTvqgl+ZiRCVgnHulaNjaytbGvw0UhbL4POvIvwXMQnvWyWPrG+GttRaUrvtiM0XX ojiqeFzDVPxO6deIlc8fyY0PPvwMjSvnGuQeJCwVUoqp4vt8lPFghGTLmEIlLgRWaV bhodqT28KH4NbxZ84RBX2sIFiDkAnq5I22DCAUeGgk9rmF+FaC2P870cZ7lSQmFaJF cYexwJCHDH5HT/v8oa/2zp6zQG+ZhBYqyrscv3hrb7sDesonN4nNqfK4Q5E5/Vzsu7 j/FjchsLHYAMkiv/nrAYDYssfMUXKOoN/oD9xPf/9rj59D2e4NGPdyRt/Awsai4Zf1 96/VYPomr83QA== From: Claudiu Beznea To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, p.zabel@pengutronix.de Cc: claudiu.beznea@tuxon.dev, linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Claudiu Beznea Subject: [PATCH v4 5/8] PCI: rzg3s-host: Move suspend/resume code into dedicated functions Date: Tue, 22 Sep 2026 17:46:25 +0300 Message-ID: <20260922144629.586997-6-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922144629.586997-1-claudiu.beznea@kernel.org> References: <20260922144629.586997-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Claudiu Beznea In preparation for implementing hotplug using pci_host_bridge::reset_root_port(), move the suspend/resume code into rzg3s_pcie_host_stop() and rzg3s_pcie_host_start(). These functions will later be reused by the hotplug implementation through pci_host_bridge::reset_root_port(). Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Tested-by: Lad Prabhakar --- Changes in v4: - none Changes in v3: - none, this patch is new drivers/pci/controller/pcie-rzg3s-host.c | 181 ++++++++++++----------- 1 file changed, 96 insertions(+), 85 deletions(-) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index 3ecada238402..40d5ef3e347e 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -1742,6 +1742,100 @@ rzg3s_pcie_host_setup(struct rzg3s_pcie_host *host, return ret; } =20 +static int rzg3s_pcie_host_stop(struct rzg3s_pcie_host *host) +{ + const struct rzg3s_pcie_soc_data *data =3D host->data; + struct rzg3s_pcie_port *port =3D &host->port; + struct rzg3s_sysc *sysc =3D host->sysc; + int ret; + + clk_disable_unprepare(port->refclk); + + /* SoC-specific de-initialization */ + ret =3D data->config_deinit(host); + if (ret) + goto refclk_restore; + + ret =3D reset_control_bulk_assert(data->num_power_resets, + host->power_resets); + if (ret) + goto config_reinit; + + /* + * Since the power domain's genpd_suspend_noirq() will disable clocks, + * there is no need to manually invoke runtime PM API here. + */ + + ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); + if (ret) + goto power_resets_restore; + + return 0; + + /* Restore the previous state if any error happens */ +power_resets_restore: + reset_control_bulk_deassert(data->num_power_resets, + host->power_resets); +config_reinit: + if (data->config_pre_init) + data->config_pre_init(host); + data->config_post_init(host); +refclk_restore: + clk_prepare_enable(port->refclk); + return ret; +} + +static int rzg3s_pcie_host_start(struct rzg3s_pcie_host *host) +{ + const struct rzg3s_pcie_soc_data *data =3D host->data; + struct rzg3s_sysc *sysc =3D host->sysc; + int ret; + + ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_MODE, 1); + if (ret) + return ret; + + ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 1); + if (ret) + return ret; + + if (host->num_lanes) { + ret =3D rzg3s_sysc_config_func(host->sysc, + RZG3S_SYSC_FUNC_ID_LINK_MASTER, + host->num_lanes =3D=3D 2 ? + RZG3S_SYSC_LINK_MODE_DUAL_X2 : + RZG3S_SYSC_LINK_MODE_SINGLE_X4); + if (ret) + goto assert_rst_rsm_b; + } + + /* + * Since the power domain's genpd_resume_noirq() will enable clocks, + * there is no need to manually invoke runtime PM API here. + */ + + ret =3D rzg3s_pcie_power_resets_deassert(host); + if (ret) + goto assert_rst_rsm_b; + + ret =3D rzg3s_pcie_host_setup(host, rzg3s_pcie_msi_hw_setup, + rzg3s_pcie_msi_hw_teardown); + if (ret) + goto assert_power_resets; + + return 0; + + /* + * If any error happens there is no way to recover the IP. Put it in the + * lowest possible power state. + */ +assert_power_resets: + reset_control_bulk_assert(data->num_power_resets, host->power_resets); +assert_rst_rsm_b: + rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); + return ret; +} + static int rzg3s_pcie_get_controller_id(struct rzg3s_pcie_host *host) { struct device_node *np =3D host->dev->of_node; @@ -1939,98 +2033,15 @@ static int rzg3s_pcie_probe(struct platform_device = *pdev) static int rzg3s_pcie_suspend_noirq(struct device *dev) { struct rzg3s_pcie_host *host =3D dev_get_drvdata(dev); - const struct rzg3s_pcie_soc_data *data =3D host->data; - struct rzg3s_pcie_port *port =3D &host->port; - struct rzg3s_sysc *sysc =3D host->sysc; - int ret; - - clk_disable_unprepare(port->refclk); - - /* SoC-specific de-initialization */ - ret =3D data->config_deinit(host); - if (ret) - goto refclk_restore; - - ret =3D reset_control_bulk_assert(data->num_power_resets, - host->power_resets); - if (ret) - goto config_reinit; - - /* - * Since the power domain's genpd_suspend_noirq() will disable clocks, - * there is no need to manually invoke runtime PM API here. - */ - - ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); - if (ret) - goto power_resets_restore; =20 - return 0; - - /* Restore the previous state if any error happens */ -power_resets_restore: - reset_control_bulk_deassert(data->num_power_resets, - host->power_resets); -config_reinit: - if (data->config_pre_init) - data->config_pre_init(host); - data->config_post_init(host); -refclk_restore: - clk_prepare_enable(port->refclk); - return ret; + return rzg3s_pcie_host_stop(host); } =20 static int rzg3s_pcie_resume_noirq(struct device *dev) { struct rzg3s_pcie_host *host =3D dev_get_drvdata(dev); - const struct rzg3s_pcie_soc_data *data =3D host->data; - struct rzg3s_sysc *sysc =3D host->sysc; - int ret; =20 - ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_MODE, 1); - if (ret) - return ret; - - ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 1); - if (ret) - return ret; - - if (host->num_lanes) { - ret =3D rzg3s_sysc_config_func(host->sysc, - RZG3S_SYSC_FUNC_ID_LINK_MASTER, - host->num_lanes =3D=3D 2 ? - RZG3S_SYSC_LINK_MODE_DUAL_X2 : - RZG3S_SYSC_LINK_MODE_SINGLE_X4); - if (ret) - goto assert_rst_rsm_b; - } - - /* - * Since the power domain's genpd_resume_noirq() will enable clocks, - * there is no need to manually invoke runtime PM API here. - */ - - ret =3D rzg3s_pcie_power_resets_deassert(host); - if (ret) - goto assert_rst_rsm_b; - - ret =3D rzg3s_pcie_host_setup(host, rzg3s_pcie_msi_hw_setup, - rzg3s_pcie_msi_hw_teardown); - if (ret) - goto assert_power_resets; - - return 0; - - /* - * If any error happens there is no way to recover the IP. Put it in the - * lowest possible power state. - */ -assert_power_resets: - reset_control_bulk_assert(data->num_power_resets, - host->power_resets); -assert_rst_rsm_b: - rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); - return ret; + return rzg3s_pcie_host_start(host); } =20 static const struct dev_pm_ops rzg3s_pcie_pm_ops =3D { --=20 2.43.0 From nobody Thu Sep 24 15:10:57 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA86E5519B0; Tue, 22 Sep 2026 14:46:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088421; cv=none; b=c2lUhmPB5S8wYkhRSNaeZ+rpycxVjfns9QAUAPD0SRgdL0DX51WWn5cxYofKm53hnE0XdXlI4aIINXTSl5WVdSt+jBTcvchL1g8gh6C94rMNY0ThdHKVUybbKnjK6zZf5PieBxrzzEtybpP+pO0wsZt9AESC9CVTJ5elHMZ2KCk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088421; c=relaxed/simple; bh=8lPDNNzBmKuMlsZoIjBNbIi5cSRJ8hcKLBvBSFzXhqk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FBLsi+53U7zzcBKsqLXnatabVJ91Nbl0pK79va1ICxxQi/rohKdhdZAu6OMMjpgt88FQbdDOjJC6c7vcSH7EU89tC/6XnjWY7jBetCL8jkUETsiPaLXlF58rdUrXg8OA/bGlO7cOFRsNrtWyCBPBtisbtCTpufa6VVsFS9LLTPw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Sfsl+7vJ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Sfsl+7vJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ACE701F00898; Tue, 22 Sep 2026 14:46:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790088419; bh=7VgnifC5bLSn4l21Fhvw+lIrmHDxv1AceVCvE7hJVOk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Sfsl+7vJ6LyuUZxzMtKYQiKjj+FuS+ema70Sq/EeF7PlL8HXootOJxqXqaCeTuB0E hvzAGwuJNpXYoOJ1K491PXQS+l3coTXpQTq1U2Z3vhg0wy3EAXkOXmTWxRkg80BTiM yico0+9mu0Ba1+kcq6bvzipA/YemVvKspiumdP7unuBLIUwBIgHL8nwsWy+eb5xd01 bzX4hK8EgB6jb/lJVUMTL91KUJaerBTKQHixvlCouQNMae0U3f/k7CeqchlMb3nn0L bAArf0hLkz9g6K/YspzSQaIgK9gRIm/BmeiXhke4GpA88s6laFlMi7AWQAr2wkThO+ wxacykPLjj4Xw== From: Claudiu Beznea To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, p.zabel@pengutronix.de Cc: claudiu.beznea@tuxon.dev, linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Claudiu Beznea Subject: [PATCH v4 6/8] PCI: rzg3s-host: Move IRQ domain setup code Date: Tue, 22 Sep 2026 17:46:26 +0300 Message-ID: <20260922144629.586997-7-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922144629.586997-1-claudiu.beznea@kernel.org> References: <20260922144629.586997-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Claudiu Beznea Subsequent patches add support for the event IRQ to handle link up/down events. The event IRQ handler will use rzg3s_pcie_set_max_link_speed(). In preparation for adding event IRQ support, move the IRQ domain initialization code after rzg3s_pcie_set_max_link_speed(). Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Tested-by: Lad Prabhakar --- Changes in v4: - none Changes in v3: - none, this patch is new drivers/pci/controller/pcie-rzg3s-host.c | 147 +++++++++++------------ 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index 40d5ef3e347e..f4b27a77a89d 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -1006,80 +1006,6 @@ static const struct irq_domain_ops rzg3s_pcie_intx_d= omain_ops =3D { .xlate =3D irq_domain_xlate_onetwocell, }; =20 -static void rzg3s_pcie_teardown_intx(struct rzg3s_pcie_host *host, - int count) -{ - while (--count >=3D 0) { - irq_set_chained_handler_and_data(host->intx_irqs[count], NULL, - NULL); - } - - if (host->intx_domain) - irq_domain_remove(host->intx_domain); -} - -static int rzg3s_pcie_init_irqdomain(struct rzg3s_pcie_host *host) -{ - struct device *dev =3D host->dev; - struct platform_device *pdev =3D to_platform_device(dev); - int i, ret; - - for (i =3D 0; i < PCI_NUM_INTX; i++) { - char irq_name[5] =3D {0}; - int irq; - - scnprintf(irq_name, ARRAY_SIZE(irq_name), "int%c", 'a' + i); - - irq =3D platform_get_irq_byname(pdev, irq_name); - if (irq < 0) { - ret =3D irq; - dev_err_probe(dev, ret, - "Failed to parse and map INT%c IRQ\n", - 'A' + i); - goto teardown_intx; - } - - host->intx_irqs[i] =3D irq; - irq_set_chained_handler_and_data(irq, - rzg3s_pcie_intx_irq_handler, - host); - } - - host->intx_domain =3D irq_domain_create_linear(dev_fwnode(dev), - PCI_NUM_INTX, - &rzg3s_pcie_intx_domain_ops, - host); - if (!host->intx_domain) { - ret =3D -EINVAL; - dev_err_probe(dev, ret, - "Failed to add irq domain for INTx IRQs\n"); - goto teardown_intx; - } - irq_domain_update_bus_token(host->intx_domain, DOMAIN_BUS_WIRED); - - if (IS_ENABLED(CONFIG_PCI_MSI)) { - ret =3D rzg3s_pcie_init_msi(host); - - if (ret) - goto teardown_intx; - } - - return 0; - -teardown_intx: - rzg3s_pcie_teardown_intx(host, i); - - return ret; -} - -static void rzg3s_pcie_teardown_irqdomain(struct rzg3s_pcie_host *host) -{ - if (IS_ENABLED(CONFIG_PCI_MSI)) - rzg3s_pcie_teardown_msi(host); - - rzg3s_pcie_teardown_intx(host, PCI_NUM_INTX); -} - static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host) { u32 remote_supported_link_speeds, max_supported_link_speeds; @@ -1169,6 +1095,79 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3= s_pcie_host *host) return ret; } =20 +static void rzg3s_pcie_teardown_intx(struct rzg3s_pcie_host *host, int cou= nt) +{ + if (host->intx_domain) + irq_domain_remove(host->intx_domain); + + while (--count >=3D 0) { + irq_set_chained_handler_and_data(host->intx_irqs[count], NULL, + NULL); + } +} + +static int rzg3s_pcie_init_irqdomain(struct rzg3s_pcie_host *host) +{ + struct device *dev =3D host->dev; + struct platform_device *pdev =3D to_platform_device(dev); + int i, ret; + + for (i =3D 0; i < PCI_NUM_INTX; i++) { + char irq_name[5] =3D {0}; + int irq; + + scnprintf(irq_name, ARRAY_SIZE(irq_name), "int%c", 'a' + i); + + irq =3D platform_get_irq_byname(pdev, irq_name); + if (irq < 0) { + ret =3D irq; + dev_err_probe(dev, ret, + "Failed to parse and map INT%c IRQ\n", + 'A' + i); + goto teardown_intx; + } + + host->intx_irqs[i] =3D irq; + irq_set_chained_handler_and_data(irq, + rzg3s_pcie_intx_irq_handler, + host); + } + + host->intx_domain =3D irq_domain_create_linear(dev_fwnode(dev), + PCI_NUM_INTX, + &rzg3s_pcie_intx_domain_ops, + host); + if (!host->intx_domain) { + ret =3D -EINVAL; + dev_err_probe(dev, ret, + "Failed to add irq domain for INTx IRQs\n"); + goto teardown_intx; + } + irq_domain_update_bus_token(host->intx_domain, DOMAIN_BUS_WIRED); + + if (IS_ENABLED(CONFIG_PCI_MSI)) { + ret =3D rzg3s_pcie_init_msi(host); + + if (ret) + goto teardown_intx; + } + + return 0; + +teardown_intx: + rzg3s_pcie_teardown_intx(host, i); + + return ret; +} + +static void rzg3s_pcie_teardown_irqdomain(struct rzg3s_pcie_host *host) +{ + if (IS_ENABLED(CONFIG_PCI_MSI)) + rzg3s_pcie_teardown_msi(host); + + rzg3s_pcie_teardown_intx(host, PCI_NUM_INTX); +} + static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host) { struct pci_host_bridge *bridge =3D pci_host_bridge_from_priv(host); --=20 2.43.0 From nobody Thu Sep 24 15:10:57 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 06C4938F951; Tue, 22 Sep 2026 14:47:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088425; cv=none; b=obDM/3ZBq/85cTfTwCTCJQhZz3crVXAsta56FBg2BQBBAkHXMlPBdH097r8lmpDlbVdUParKQNNfJo2Nbbtze8bg7wu3JdesmOpUsbUrIdzO6v4xmi1w5/kydbBW/fcXFD/fgTK8Nr0zuhq/sN8U5DSHq6oSaxAkYH4g7wq5X+Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088425; c=relaxed/simple; bh=y0G68FUnKuhdlz8E/0b/HHB6com4da912sJGuCuDPkI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=n1mVUQ9uGu/osQMeFdOhN6+YVn50g9CA79tklBESTPRxS3Lz5LVI0Z4CK0N8q95xrBl86XLTQCPOXl7FmDBRzUsOmffNM+LKDIFhyubGeCjCSuFuou2jq3spWDlwrjAecdKbrIXgAUd94fUPCDfsSz07/3h16ixHVJua7vsd8+0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NmiGelxW; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NmiGelxW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3C2951F00893; Tue, 22 Sep 2026 14:46:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790088423; bh=joSU7EzkrZ0Mny1IL9YvQWzLKBnb8avCW8mYTMW38Vk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=NmiGelxWy5lPiI8OSB7ZySUbaMHIu6ompdUPDNn1kAzT6kajoDfGXkyn6TDUK6ns8 /joNrPl6SbZCMkt1DY62m4TkeBwOZv1Tv9M+D77yz8YEUiNdUv4ePMo0S8p2vnzwNT CFq10sRbKPI1KqyAMWSyd6JlSuUe+5QBMRG6BzNi5W+Tv7sOmUlWyXwXkv4IUKKAao U4hJB90Wq/H4ws2QsfqM2FzwKWTtypuRUHicpUYV4ZO0Di13iFuLLTOWyaWdDrQiMJ UgxWiXo1U6w8sxWH4uWFKNHzc7FKHoxB6Q6JKl1pDpmheUqYBCjxPNUXYmZZKO8wbe sJ/NIylLGB8Ig== From: Claudiu Beznea To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, p.zabel@pengutronix.de Cc: claudiu.beznea@tuxon.dev, linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, John Madieu , Claudiu Beznea Subject: [PATCH v4 7/8] PCI: rzg3s-host: Re-enumerate the bus on PCIe link-state changes Date: Tue, 22 Sep 2026 17:46:27 +0300 Message-ID: <20260922144629.586997-8-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922144629.586997-1-claudiu.beznea@kernel.org> References: <20260922144629.586997-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: John Madieu The RZ/G3{E, S}, RZ/V2{H(P), N} PCIe controllers does not expose the standard PCIe Slot Capability registers, so the generic pciehp driver cannot be used. The only link-state signal the hardware provides is the DL_UpDown bit in the PEIS0 event status register, which is raised on every Data Link layer up/down transition. Enable DL_UpDown in PEIE0 and hook up an interrupt handler so the driver can react to link-state changes: a device that trains after boot gets enumerated, and a device that disappears on link loss is removed. This provides hotplug-like behavior without the PCI hotplug core, which is unavailable for the reason above. On a DL_UpDown event the handler acks the W1C status bit and schedules a worker that inspects PCSTAT1.DL_DOWN_STS: - link up: re-run max link speed negotiation, wait for the link to settle and pci_rescan_bus() the root bus; - link down: walk the bus in reverse and pci_stop_and_remove_bus_device() each child. Both paths take pci_lock_rescan_remove() to serialize against the PCI core. Link events are processed only after the controller has been fully initialized. While at it, make probe tolerant of an absent device. Previously, if the link failed to come up during rzg3s_pcie_host_init(), probe tore the controller back down and failed. Distinguish this case with -ENODEV, leave the controller and refclk running, and let the link-up path enumerate the device once it appears. Signed-off-by: John Madieu Co-developed-by: Claudiu Beznea Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Tested-by: Lad Prabhakar --- Changes in v4: - dropped .reset_root_port() changes Changes in v3: - added RZG3S_PCI_PEIE0_DL_UPDOWN - re-worked the support by implemeting struct pci_host_bridge::reset_root_port() - introduced the struct rzg3s_pcie_host::state to: -- avoid touching the controller while a reset root port is in progress -- and avoid touching the controller in case a reset root port failed -- and to be able to re-use the already existing code in the reset root port function -- and added CLASS() constructs helpers for it to keep the state handling code simpler - updated the patch description to reflect the updates drivers/pci/controller/pcie-rzg3s-host.c | 155 ++++++++++++++++++++--- 1 file changed, 139 insertions(+), 16 deletions(-) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index f4b27a77a89d..1c0353598b59 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -86,6 +86,7 @@ #define RZG3S_PCI_MSGRCVIS_MRI BIT(24) =20 #define RZG3S_PCI_PEIE0 0x200 +#define RZG3S_PCI_PEIE0_DL_UPDOWN BIT(9) =20 #define RZG3S_PCI_PEIS0 0x204 #define RZG3S_PCI_PEIS0_RX_DLLP_PM_ENTER BIT(12) @@ -323,6 +324,7 @@ struct rzg3s_pcie_port { * @msi: MSI data structure * @port: PCIe Root Port * @hw_lock: lock for access to the HW resources + * @event_irq: PCIe event interrupt for DL_UpDown detection * @intx_irqs: INTx interrupts * @max_link_speed: maximum supported link speed * @controller_id: PCIe controller identifier, used for System Controller = access @@ -340,6 +342,7 @@ struct rzg3s_pcie_host { struct rzg3s_pcie_msi msi; struct rzg3s_pcie_port port; raw_spinlock_t hw_lock; + int event_irq; int intx_irqs[PCI_NUM_INTX]; int max_link_speed; enum rzg3s_pcie_controller_id controller_id; @@ -1095,6 +1098,89 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3= s_pcie_host *host) return ret; } =20 +static void rzg3s_pcie_link_event(struct rzg3s_pcie_host *host) +{ + struct pci_host_bridge *bridge =3D pci_host_bridge_from_priv(host); + struct pci_bus *bus =3D bridge->bus; + u32 val; + + val =3D readl_relaxed(host->axi + RZG3S_PCI_PCSTAT1); + if (val & RZG3S_PCI_PCSTAT1_DL_DOWN_STS) { + struct pci_dev *dev, *tmp; + + dev_info(host->dev, "PCIe link down, removing devices\n"); + + pci_lock_rescan_remove(); + list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, + bus_list) + pci_stop_and_remove_bus_device(dev); + pci_unlock_rescan_remove(); + } else { + int ret; + + dev_info(host->dev, "PCIe link up, rescanning bus\n"); + + /* + * Attempt link speed negotiation now that the link is up. + * Failure is non-fatal: the device works at the negotiated + * speed. + */ + ret =3D rzg3s_pcie_set_max_link_speed(host); + if (ret) + dev_info(host->dev, "Failed to set max link speed\n"); + + pci_host_common_link_train_delay(host->max_link_speed); + + pci_lock_rescan_remove(); + pci_rescan_bus(bus); + pci_unlock_rescan_remove(); + } +} + +static irqreturn_t rzg3s_pcie_event_irq_thread(int irq, void *data) +{ + struct rzg3s_pcie_host *host =3D data; + u32 status; + + status =3D readl_relaxed(host->axi + RZG3S_PCI_PEIS0); + + if (!(status & RZG3S_PCI_PEIS0_DL_UPDOWN)) + return IRQ_NONE; + + /* Clear the DL_UpDown status (W1C) */ + writel_relaxed(RZG3S_PCI_PEIS0_DL_UPDOWN, host->axi + RZG3S_PCI_PEIS0); + + rzg3s_pcie_link_event(host); + + return IRQ_HANDLED; +} + +static int rzg3s_pcie_request_event_irq(struct rzg3s_pcie_host *host) +{ + struct device *dev =3D host->dev; + struct platform_device *pdev =3D to_platform_device(dev); + const char *evt_name; + int ret, irq; + + evt_name =3D devm_kasprintf(dev, GFP_KERNEL, "%s-evt", dev_name(dev)); + if (!evt_name) + return -ENOMEM; + + irq =3D platform_get_irq_byname(pdev, "pcie_evt"); + if (irq < 0) + return irq; + + ret =3D request_threaded_irq(irq, NULL, rzg3s_pcie_event_irq_thread, + IRQF_ONESHOT, evt_name, host); + if (ret) { + return dev_err_probe(dev, ret, + "Failed to request pcie_evt IRQ\n"); + } + host->event_irq =3D irq; + + return 0; +} + static void rzg3s_pcie_teardown_intx(struct rzg3s_pcie_host *host, int cou= nt) { if (host->intx_domain) @@ -1106,6 +1192,17 @@ static void rzg3s_pcie_teardown_intx(struct rzg3s_pc= ie_host *host, int count) } } =20 +static void rzg3s_pcie_teardown_irqdomain(struct rzg3s_pcie_host *host) +{ + if (host->event_irq > 0) + free_irq(host->event_irq, host); + + if (IS_ENABLED(CONFIG_PCI_MSI)) + rzg3s_pcie_teardown_msi(host); + + rzg3s_pcie_teardown_intx(host, PCI_NUM_INTX); +} + static int rzg3s_pcie_init_irqdomain(struct rzg3s_pcie_host *host) { struct device *dev =3D host->dev; @@ -1152,22 +1249,21 @@ static int rzg3s_pcie_init_irqdomain(struct rzg3s_p= cie_host *host) goto teardown_intx; } =20 + ret =3D rzg3s_pcie_request_event_irq(host); + if (ret) + goto teardown_msi; + return 0; =20 +teardown_msi: + if (IS_ENABLED(CONFIG_PCI_MSI)) + rzg3s_pcie_teardown_msi(host); teardown_intx: rzg3s_pcie_teardown_intx(host, i); =20 return ret; } =20 -static void rzg3s_pcie_teardown_irqdomain(struct rzg3s_pcie_host *host) -{ - if (IS_ENABLED(CONFIG_PCI_MSI)) - rzg3s_pcie_teardown_msi(host); - - rzg3s_pcie_teardown_intx(host, PCI_NUM_INTX); -} - static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host) { struct pci_host_bridge *bridge =3D pci_host_bridge_from_priv(host); @@ -1679,16 +1775,21 @@ static int rzg3s_pcie_host_init(struct rzg3s_pcie_h= ost *host) PCIE_LINK_WAIT_SLEEP_MS * MILLI, PCIE_LINK_WAIT_SLEEP_MS * MILLI * PCIE_LINK_WAIT_MAX_RETRIES); - if (ret) - goto config_deinit_post; + if (ret) { + /* + * Link is down. Leave the controller running so the + * DL_UpDown handler can enumerate a device that appears + * later. + */ + dev_info(host->dev, "PCIe link down, waiting for DL_UpDown\n"); + ret =3D -ENODEV; + } =20 val =3D readl_relaxed(host->axi + RZG3S_PCI_PCSTAT2); dev_info(host->dev, "PCIe link status [0x%x]\n", val); =20 - return 0; + return ret; =20 -config_deinit_post: - host->data->config_deinit(host); config_deinit_and_refclk: clk_disable_unprepare(host->port.refclk); config_deinit: @@ -1723,8 +1824,14 @@ rzg3s_pcie_host_setup(struct rzg3s_pcie_host *host, =20 ret =3D rzg3s_pcie_host_init(host); if (ret) { - dev_err_probe(dev, ret, "Failed to initialize the HW!\n"); - goto teardown_irqdomain; + if (ret !=3D -ENODEV) { + dev_err_probe(dev, ret, + "Failed to initialize the HW!\n"); + goto teardown_irqdomain; + } + + /* Link is down: hotplug via DL_UpDown will recover. */ + return 0; } =20 ret =3D rzg3s_pcie_set_max_link_speed(host); @@ -2004,6 +2111,14 @@ static int rzg3s_pcie_probe(struct platform_device *= pdev) if (ret) goto host_probe_teardown; =20 + /* + * Unmask the PCIe event IRQ at the end of probe to avoid + * spurious link-state events during controller setup and bus + * enumeration. From here on, DL_UpDown events trigger the link + * IRQ thread to (re)scan the bus. + */ + writel_relaxed(RZG3S_PCI_PEIE0_DL_UPDOWN, host->axi + RZG3S_PCI_PEIE0); + return 0; =20 host_probe_teardown: @@ -2039,8 +2154,16 @@ static int rzg3s_pcie_suspend_noirq(struct device *d= ev) static int rzg3s_pcie_resume_noirq(struct device *dev) { struct rzg3s_pcie_host *host =3D dev_get_drvdata(dev); + int ret; =20 - return rzg3s_pcie_host_start(host); + ret =3D rzg3s_pcie_host_start(host); + if (ret) + return ret; + + /* Unmask link up/down IRQ. */ + writel_relaxed(RZG3S_PCI_PEIE0_DL_UPDOWN, host->axi + RZG3S_PCI_PEIE0); + + return 0; } =20 static const struct dev_pm_ops rzg3s_pcie_pm_ops =3D { --=20 2.43.0 From nobody Thu Sep 24 15:10:57 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5FFAE5540BD; Tue, 22 Sep 2026 14:47:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088428; cv=none; b=faggQqu2ExE5WZfmay0B/KEaiNgSPzgVhWoONnJ9m68j74rSk05raXow9hCONKeQqYDbYagYw40WRWsKeph7ZJZiKqloZLPW9PjvxOwLPyTdxi9la+Gt2VMog1VMZB/695SYnK6TAO9bjcHcCmFt84sotglKpPcC0BUTj+NOf30= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790088428; c=relaxed/simple; bh=1Im1ZNFIJrfPREwypW1FsEYCrX+6t9WZt5z+WJz1I+8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jJN25j/pFc0qeFOfjl+bh3r6KGkoquRGIYX0mBDomJ+JKtLcZQ+vnWlD1AXwRFWnL5xn3K8PSub8sjxPW4k9UoaRZoNqHH5gytX7304qBi/gHXDK/TT3V+jfH8fBmyQUDB8QVZ3KQ6nA+r4oVVQ6v9k32bo2XYxQJxVW0CAV3bE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=R+m9bqcK; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="R+m9bqcK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0CD831F00898; Tue, 22 Sep 2026 14:47:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790088426; bh=DEEddTTRgzBSKA0H/RopE6I+anHr4ayJ/E3G54xl/zg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=R+m9bqcKpAqgKKUqFefEpFRVG/j9FzKeqdrasfDm7OP9hUsf+FJ3EN4Rv2hHc/Gwi le4ke/FFDy30BBseC8U1n0770KMK/iN05YULeutV4l7WAJOUMQxVQtJ7YF629oYOK1 QTPDnHrwjy8SpfYqZnzxh28aYm7A+Kh6mfNKNBCG5kvPhYVdSJD7Z0j7utI+1C29/n /UGyHsQNaVizRqtXIhOaXl1I82DofZCSRXQ8f68Aq8SLSc+Z3VCHJr3bnrr44XbnVe N/7YbgVKwrYnlTBlw2ETDKcL24wmqFCzd8YxZ5cUtzOs3gMnBLkXxQgY38zo8ZINNo a8js4vQywFW6g== From: Claudiu Beznea To: lpieralisi@kernel.org, kwilczynski@kernel.org, mani@kernel.org, robh@kernel.org, bhelgaas@google.com, p.zabel@pengutronix.de Cc: claudiu.beznea@tuxon.dev, linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Claudiu Beznea Subject: [PATCH v4 8/8] PCI: rzg3s-host: Add bridge::reset_root_port() Date: Tue, 22 Sep 2026 17:46:28 +0300 Message-ID: <20260922144629.586997-9-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260922144629.586997-1-claudiu.beznea@kernel.org> References: <20260922144629.586997-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Claudiu Beznea Add bridge::reset_root_port(). This allows, on some devices, performing reads and writes to an NVMe endpoint after a link down/link up cycle without failures. The implementation of struct pci_host_bridge::reset_root_port() masks all enabled interrupts and synchronizes them before resetting the controller to prevent asynchronous events from interfering with the reset operation. struct rzg3s_pcie_host::started boolean was added to keep track of the controller state, since rzg3s_pcie_host_start() and rzg3s_pcie_host_stop() are called from multiple paths: .reset_root_port(), .suspend_noirq() and .resume_noirq(). The flag prevents double start/stop and breaking reference counters for clocks and resets. Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Tested-by: Lad Prabhakar --- Changes in v4: - this patch is new and is a split from patch 7 of v3 - use a boolean to keep track of the controller start state; with this the state management code from patch 7 of v3 was dropped=20 drivers/pci/controller/pcie-rzg3s-host.c | 77 +++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/control= ler/pcie-rzg3s-host.c index 1c0353598b59..9cba898a9536 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -328,6 +328,7 @@ struct rzg3s_pcie_port { * @intx_irqs: INTx interrupts * @max_link_speed: maximum supported link speed * @controller_id: PCIe controller identifier, used for System Controller = access + * @started: The PCIe controller state (started or not) * @num_lanes: The number of lanes */ struct rzg3s_pcie_host { @@ -346,6 +347,7 @@ struct rzg3s_pcie_host { int intx_irqs[PCI_NUM_INTX]; int max_link_speed; enum rzg3s_pcie_controller_id controller_id; + bool started; u8 num_lanes; }; =20 @@ -1110,6 +1112,11 @@ static void rzg3s_pcie_link_event(struct rzg3s_pcie_= host *host) =20 dev_info(host->dev, "PCIe link down, removing devices\n"); =20 + for_each_pci_bridge(dev, bridge->bus) { + if (pci_pcie_type(dev) =3D=3D PCI_EXP_TYPE_ROOT_PORT) + pci_host_handle_link_down(dev); + } + pci_lock_rescan_remove(); list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) @@ -1855,6 +1862,9 @@ static int rzg3s_pcie_host_stop(struct rzg3s_pcie_hos= t *host) struct rzg3s_sysc *sysc =3D host->sysc; int ret; =20 + if (!host->started) + return 0; + clk_disable_unprepare(port->refclk); =20 /* SoC-specific de-initialization */ @@ -1876,6 +1886,8 @@ static int rzg3s_pcie_host_stop(struct rzg3s_pcie_hos= t *host) if (ret) goto power_resets_restore; =20 + host->started =3D false; + return 0; =20 /* Restore the previous state if any error happens */ @@ -1891,12 +1903,15 @@ static int rzg3s_pcie_host_stop(struct rzg3s_pcie_h= ost *host) return ret; } =20 -static int rzg3s_pcie_host_start(struct rzg3s_pcie_host *host) +static int rzg3s_pcie_host_start(struct rzg3s_pcie_host *host, bool set_st= arted) { const struct rzg3s_pcie_soc_data *data =3D host->data; struct rzg3s_sysc *sysc =3D host->sysc; int ret; =20 + if (host->started) + return 0; + ret =3D rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_MODE, 1); if (ret) return ret; @@ -1929,6 +1944,9 @@ static int rzg3s_pcie_host_start(struct rzg3s_pcie_ho= st *host) if (ret) goto assert_power_resets; =20 + if (set_started) + host->started =3D true; + return 0; =20 /* @@ -1942,6 +1960,58 @@ static int rzg3s_pcie_host_start(struct rzg3s_pcie_h= ost *host) return ret; } =20 +static int rzg3s_pcie_host_reset_root_port(struct pci_host_bridge *bridge, + struct pci_dev *pdev) +{ + struct rzg3s_pcie_host *host =3D pci_host_bridge_priv(bridge); + u32 irqs; + int ret; + + /* Mask link up/down interrupts. */ + writel(0, host->axi + RZG3S_PCI_PEIE0); + + /* Mask INTx and MSI interrupts. */ + irqs =3D readl_relaxed(host->axi + RZG3S_PCI_PINTRCVIE); + writel(0, host->axi + RZG3S_PCI_PINTRCVIE); + + /* + * Make sure the next operations are not disturbed by any pending + * IRQs. + */ + synchronize_irq(host->msi.irq); + for (unsigned int i =3D 0; i < PCI_NUM_INTX; i++) + synchronize_irq(host->intx_irqs[i]); + + ret =3D rzg3s_pcie_host_stop(host); + if (ret) { + dev_err(host->dev, "Failed to stop the host!\n"); + goto unmask_irqs; + } + + ret =3D rzg3s_pcie_host_start(host, false); + if (ret) { + dev_err(host->dev, "Failed to start the host!\n"); + + /* + * Don't unmask IRQs. We are in a bad state here and we + * can recover only through a suspend/resume cycle. Just + * return and preserve the stop state. + */ + return ret; + } + +unmask_irqs: + /* Unmask INTx and MSI interrupts. */ + writel_relaxed(irqs, host->axi + RZG3S_PCI_PINTRCVIE); + + /* Unmask link up/down interrupts. */ + writel(RZG3S_PCI_PEIE0_DL_UPDOWN, host->axi + RZG3S_PCI_PEIE0); + + host->started =3D true; + + return ret; +} + static int rzg3s_pcie_get_controller_id(struct rzg3s_pcie_host *host) { struct device_node *np =3D host->dev->of_node; @@ -2104,9 +2174,12 @@ static int rzg3s_pcie_probe(struct platform_device *= pdev) if (ret) goto power_resets_assert; =20 + host->started =3D true; + bridge->sysdata =3D host; bridge->ops =3D &rzg3s_pcie_root_ops; bridge->child_ops =3D &rzg3s_pcie_child_ops; + bridge->reset_root_port =3D rzg3s_pcie_host_reset_root_port; ret =3D pci_host_probe(bridge); if (ret) goto host_probe_teardown; @@ -2156,7 +2229,7 @@ static int rzg3s_pcie_resume_noirq(struct device *dev) struct rzg3s_pcie_host *host =3D dev_get_drvdata(dev); int ret; =20 - ret =3D rzg3s_pcie_host_start(host); + ret =3D rzg3s_pcie_host_start(host, true); if (ret) return ret; =20 --=20 2.43.0