Re: [PATCH] PCI: meson: Fix PERST# timing by asserting reset before LTSSM enable

gowtham <[email protected]>
Newsgroups org.infradead.lists.linux-amlogic,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci
Organization FerryFair
Message-ID <[email protected]>
Hi Ronald,
I see you submitted the patch. Last couple of days I've been fixing the
etherenet of my BPiCM4+Waveshare-io-base-b due to which I couldn't test
your patch any sooner. Now I got my ethernet working but now I couldn't
reproduce the issue *without* either of our patches!!!

Anyway it's proper to initialize PCIe with RESET Active but I think
meson_pcie_assert_reset(mp) will give sufficient time to PCIe devices
to complete the reset cycle.

---
 drivers/pci/controller/dwc/pci-meson.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-meson.c
b/drivers/pci/controller/dwc/pci-meson.c index 0694084f612..c28ab40c9ff
100644 --- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -308,8 +308,8 @@ static int meson_pcie_start_link(struct dw_pcie
*pci) {
 	struct meson_pcie *mp = to_meson_pcie(pci);
 
-	meson_pcie_ltssm_enable(mp);
 	meson_pcie_assert_reset(mp);
+	meson_pcie_ltssm_enable(mp);
 
 	return 0;
 }
-- 
---
 drivers/pci/controller/dwc/pci-meson.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-meson.c
b/drivers/pci/controller/dwc/pci-meson.c index c28ab40c9ff..2ef75157530
100644 --- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -308,7 +308,6 @@ static int meson_pcie_start_link(struct dw_pcie
*pci) {
 	struct meson_pcie *mp = to_meson_pcie(pci);
 
-	meson_pcie_assert_reset(mp);
 	meson_pcie_ltssm_enable(mp);
 
 	return 0;
@@ -362,6 +361,8 @@ static int meson_pcie_host_init(struct dw_pcie_rp
*pp) 
 	pp->bridge->ops = &meson_pci_ops;
 
+	meson_pcie_assert_reset(mp);
+
 	meson_set_max_payload(mp, MAX_PAYLOAD_SIZE);
 	meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE);
 
-- 

...Gowtham


On Wed, 17 Jun 2026 05:06:27 +0530
gowtham <[email protected]> wrote:

> Hi,
> 
> As Neil suggested I moved the PCIe reset to init; I've updated the tag
> at
> https://github.com/GowthamKudupudi/linux/tree/meson-pcie-warm-reset-linux-7.0.y
> 
> Ronald, yes, I do think its proper to initialize PCIe with RESET
> Active. Anyway we need the reset *cycle*. Please submit your patch as
> well.
> 
> Thank you!
> 
> ...Gowtham
> 
> On Tue, 16 Jun 2026 08:06:02 +0200
> [email protected] wrote:
> 
> > On 6/15/26 12:34, Ronald Claveau wrote:  
> > > On 6/14/26 3:56 AM, Gowtham Kudupudi wrote:    
> > >> On warm reboot, the PCIe controller's LTSSM starts link training
> > >> immediately if PERST# is already deasserted from the previous
> > >> boot. The driver then pulses PERST# for only 500us, which is too
> > >> short to properly reset the endpoint device that has already
> > >> started training.
> > >>
> > >> Fix by moving the PERST# assert/deassert pulse BEFORE enabling
> > >> LTSSM, so the endpoint gets a clean reset cycle before link
> > >> training begins.
> > >>
> > >> This was found on Amlogic G12B (A311D) with NVMe on an M.2 slot.
> > >> Cold boot worked because POR held PERST# low; warm reboot did
> > >> not. The fix was confirmed on a Banana Pi CM4 with Waveshare IO
> > >> base board.
> > >>
> > >> Signed-off-by: Gowtham Kudupudi <[email protected]>
> > >> ---
> > >>   drivers/pci/controller/dwc/pci-meson.c | 2 +-
> > >>   1 file changed, 1 insertion(+), 1 deletion(-)
> > >>
> > >> diff --git a/drivers/pci/controller/dwc/pci-meson.c
> > >> b/drivers/pci/controller/dwc/pci-meson.c index
> > >> 5f8e2f4b3c12..3a7e9f1d5b8c 100644 ---
> > >> a/drivers/pci/controller/dwc/pci-meson.c +++
> > >> b/drivers/pci/controller/dwc/pci-meson.c @@ -310,8 +310,8 @@
> > >> static int meson_pcie_start_link(struct dw_pcie *pci) {
> > >>   	struct meson_pcie *mp = to_meson_pcie(pci);
> > >>   
> > >> +	meson_pcie_assert_reset(mp);
> > >>   	meson_pcie_ltssm_enable(mp);
> > >> -	meson_pcie_assert_reset(mp);    
> > 
> > I think this change is valid, other controllers resets PERST
> > in the host init callback, so either this or move to the
> > init callback.
> > 
> > Reviewed-by: Neil Armstrong <[email protected]>
> >   
> > >>   
> > >>   	return 0;
> > >>   }    
> > > 
> > > Hi Gowtham,
> > > 
> > > I have a patch [1] that I haven't submitted yet.
> > > This might be related to your issue, what do you think ?    
> > 
> > Ronald, This fix is valid, it's definitely better to probe the
> > driver with PERST asserted, please send it.
> > 
> > Neil
> >   
> > > 
> > > [1]
> > > https://github.com/rclaveau-tech/linux-khadas/commit/bee0a02d9756
> > >   
> >   
>

_______________________________________________
linux-amlogic mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-amlogic
0001-PCI-meson-Fix-PERST-timing-by-asserting-reset-before.patch (text/x-patch, 1.5 KB)
From 852811b11795ee389ea6a953ed0db69b76722469 Mon Sep 17 00:00:00 2001
From: Gowtham Kudupudi <[email protected]>
Date: Sun, 14 Jun 2026 09:41:01 +0530
Subject: [PATCH 1/2] PCI: meson: Fix PERST# timing by asserting reset before
 LTSSM enable

On warm reboot, the PCIe controller's LTSSM starts link training
immediately if PERST# is already deasserted from the previous boot.
The driver then pulses PERST# for only 500us, which is too short to
properly reset the endpoint device that has already started training.

Fix by moving the PERST# assert/deassert pulse BEFORE enabling LTSSM,
so the endpoint gets a clean reset cycle before link training begins.

This was found on Amlogic G12B (A311D) with NVMe on an M.2 slot.
Cold boot worked because POR held PERST# low; warm reboot did not.
The fix was confirmed on a Banana Pi CM4 with Waveshare IO base board.

Signed-off-by: Gowtham Kudupudi <[email protected]>
---
 drivers/pci/controller/dwc/pci-meson.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 0694084f612..c28ab40c9ff 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -308,8 +308,8 @@ static int meson_pcie_start_link(struct dw_pcie *pci)
 {
 	struct meson_pcie *mp = to_meson_pcie(pci);
 
-	meson_pcie_ltssm_enable(mp);
 	meson_pcie_assert_reset(mp);
+	meson_pcie_ltssm_enable(mp);
 
 	return 0;
 }
-- 
2.54.0
0002-PCI-meson-pcie-reset-moved-to-meson_pcie_host_init.patch (text/x-patch, 1.1 KB)
From 1bcf2c787d72b2c25852cc598b1201510b4132b0 Mon Sep 17 00:00:00 2001
From: Gowtham Kudupudi <[email protected]>
Date: Wed, 17 Jun 2026 04:29:45 +0530
Subject: [PATCH 2/2] PCI: meson: pcie reset moved to meson_pcie_host_init

As per the Neil's suggestion, inititial PCIe reset is moved to init
to make it proper.

Signed-off-by: Gowtham Kudupudi <[email protected]>
---
 drivers/pci/controller/dwc/pci-meson.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index c28ab40c9ff..2ef75157530 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -308,7 +308,6 @@ static int meson_pcie_start_link(struct dw_pcie *pci)
 {
 	struct meson_pcie *mp = to_meson_pcie(pci);
 
-	meson_pcie_assert_reset(mp);
 	meson_pcie_ltssm_enable(mp);
 
 	return 0;
@@ -362,6 +361,8 @@ static int meson_pcie_host_init(struct dw_pcie_rp *pp)
 
 	pp->bridge->ops = &meson_pci_ops;
 
+	meson_pcie_assert_reset(mp);
+
 	meson_set_max_payload(mp, MAX_PAYLOAD_SIZE);
 	meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE);
 
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.