linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/2] PCI: rockchip-host: Support quirky devices
@ 2025-06-10 16:36 Geraldo Nascimento
  2025-06-10 16:37 ` [RFC PATCH v2 1/2] PCI: rockchip-host: Retry link training on failure without PERST# Geraldo Nascimento
  2025-06-10 16:37 ` [RFC PATCH v2 2/2] arm64: dts: rockchip: drop PCIe 3v3 always-on and boot-on Geraldo Nascimento
  0 siblings, 2 replies; 5+ messages in thread
From: Geraldo Nascimento @ 2025-06-10 16:36 UTC (permalink / raw)
  To: linux-rockchip
  Cc: Hugh Cole-Baker, Shawn Lin, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
	Bjorn Helgaas, Heiko Stuebner, linux-pci, linux-arm-kernel,
	linux-kernel

Hi folks,

while I understand there are lots of already-working PCIe devices
on RK3399 there are also many quirky devices which fail link
training and refuse to enumerate. This RFC series is meant to
alleviate this problem and has been tested on my Rock Pi N10.

Note that with these patches, link will train for quirky devices
but with Gen1 only and only one lane (x1). I have separate patches
for improving to Gen2 and all four lanes (x4). They don't depend on
this fix however and since I predict the present patches are bound
to be controversial, I decided to send the quality improvements
separately.

Hopefully this time the series will be threaded. Thanks Heiko!

Geraldo Nascimento (2):
  PCI: rockchip-host: Retry link training on failure without PERST#
  arm64: dts: rockchip: drop PCIe 3v3 always-on and boot-on

 .../dts/rockchip/rk3399pro-vmarc-som.dtsi     |   2 -
 drivers/pci/controller/pcie-rockchip-host.c   | 141 +++++++++++-------
 2 files changed, 87 insertions(+), 56 deletions(-)

-- 
2.49.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RFC PATCH v2 1/2] PCI: rockchip-host: Retry link training on failure without PERST#
  2025-06-10 16:36 [RFC PATCH v2 0/2] PCI: rockchip-host: Support quirky devices Geraldo Nascimento
@ 2025-06-10 16:37 ` Geraldo Nascimento
  2025-06-10 18:44   ` Bjorn Helgaas
  2025-06-10 16:37 ` [RFC PATCH v2 2/2] arm64: dts: rockchip: drop PCIe 3v3 always-on and boot-on Geraldo Nascimento
  1 sibling, 1 reply; 5+ messages in thread
From: Geraldo Nascimento @ 2025-06-10 16:37 UTC (permalink / raw)
  To: linux-rockchip
  Cc: Hugh Cole-Baker, Shawn Lin, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
	Bjorn Helgaas, Heiko Stuebner, linux-pci, linux-arm-kernel,
	linux-kernel

After almost 30 days of battling with RK3399 buggy PCIe on my Rock Pi
N10 through trial-and-error debugging, I finally got positive results
with enumeration on the PCI bus for both a Realtek 8111E NIC and a
Samsung PM981a SSD.

The NIC was connected to a M.2->PCIe x4 riser card and it would get
stuck on Polling.Compliance, without breaking electrical idle on the
Host RX side. The Samsung PM981a SSD is directly connected to M.2
connector and that SSD is known to be quirky (OEM... no support)
and non-functional on the RK3399 platform.

The Samsung SSD was even worse than the NIC - it would get stuck on
Detect.Active like a bricked card, even though it was fully functional
via USB adapter.

It seems both devices benefit from retrying Link Training if - big if
here - PERST# is not toggled during retry.

For retry to work, flow must be exactly as handled by present patch,
that is, we must cut 3.3V power, disable the clocks, then re-enable
both clocks and power regulator and go through initialization
without touching PERST#. Then quirky devices are able to sucessfully
enumerate.

No functional change for already working devices.

Signed-off-by: Geraldo Nascimento <geraldogabriel@gmail.com>
---
 drivers/pci/controller/pcie-rockchip-host.c | 141 ++++++++++++--------
 1 file changed, 87 insertions(+), 54 deletions(-)

diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
index b9e7a8710cf0..67b3b379d277 100644
--- a/drivers/pci/controller/pcie-rockchip-host.c
+++ b/drivers/pci/controller/pcie-rockchip-host.c
@@ -284,6 +284,53 @@ static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip)
 	rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCR);
 }
 
+static int rockchip_pcie_set_vpcie(struct rockchip_pcie *rockchip)
+{
+	struct device *dev = rockchip->dev;
+	int err;
+
+	if (!IS_ERR(rockchip->vpcie12v)) {
+		err = regulator_enable(rockchip->vpcie12v);
+		if (err) {
+			dev_err(dev, "fail to enable vpcie12v regulator\n");
+			goto err_out;
+		}
+	}
+
+	if (!IS_ERR(rockchip->vpcie3v3)) {
+		err = regulator_enable(rockchip->vpcie3v3);
+		if (err) {
+			dev_err(dev, "fail to enable vpcie3v3 regulator\n");
+			goto err_disable_12v;
+		}
+	}
+
+	err = regulator_enable(rockchip->vpcie1v8);
+	if (err) {
+		dev_err(dev, "fail to enable vpcie1v8 regulator\n");
+		goto err_disable_3v3;
+	}
+
+	err = regulator_enable(rockchip->vpcie0v9);
+	if (err) {
+		dev_err(dev, "fail to enable vpcie0v9 regulator\n");
+		goto err_disable_1v8;
+	}
+
+	return 0;
+
+err_disable_1v8:
+	regulator_disable(rockchip->vpcie1v8);
+err_disable_3v3:
+	if (!IS_ERR(rockchip->vpcie3v3))
+		regulator_disable(rockchip->vpcie3v3);
+err_disable_12v:
+	if (!IS_ERR(rockchip->vpcie12v))
+		regulator_disable(rockchip->vpcie12v);
+err_out:
+	return err;
+}
+
 /**
  * rockchip_pcie_host_init_port - Initialize hardware
  * @rockchip: PCIe port information
@@ -291,11 +338,14 @@ static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip)
 static int rockchip_pcie_host_init_port(struct rockchip_pcie *rockchip)
 {
 	struct device *dev = rockchip->dev;
-	int err, i = MAX_LANE_NUM;
+	int err, i = MAX_LANE_NUM, is_reinit = 0;
 	u32 status;
 
-	gpiod_set_value_cansleep(rockchip->perst_gpio, 0);
+	if (!is_reinit) {
+		gpiod_set_value_cansleep(rockchip->perst_gpio, 0);
+	}
 
+reinit:
 	err = rockchip_pcie_init_port(rockchip);
 	if (err)
 		return err;
@@ -322,16 +372,46 @@ static int rockchip_pcie_host_init_port(struct rockchip_pcie *rockchip)
 	rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE,
 			    PCIE_CLIENT_CONFIG);
 
-	msleep(PCIE_T_PVPERL_MS);
-	gpiod_set_value_cansleep(rockchip->perst_gpio, 1);
-
-	msleep(PCIE_T_RRS_READY_MS);
+	if (!is_reinit) {
+		msleep(PCIE_T_PVPERL_MS);
+		gpiod_set_value_cansleep(rockchip->perst_gpio, 1);
+		msleep(PCIE_T_RRS_READY_MS);
+	}
 
 	/* 500ms timeout value should be enough for Gen1/2 training */
 	err = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1,
 				 status, PCIE_LINK_UP(status), 20,
 				 500 * USEC_PER_MSEC);
-	if (err) {
+
+	if (err && !is_reinit) {
+		while (i--)
+			phy_power_off(rockchip->phys[i]);
+		i = MAX_LANE_NUM;
+		while (i--)
+			phy_exit(rockchip->phys[i]);
+		i = MAX_LANE_NUM;
+		is_reinit = 1;
+		dev_dbg(dev, "Will reinit PCIe without toggling PERST#");
+		if (!IS_ERR(rockchip->vpcie12v))
+			regulator_disable(rockchip->vpcie12v);
+		if (!IS_ERR(rockchip->vpcie3v3))
+			regulator_disable(rockchip->vpcie3v3);
+		regulator_disable(rockchip->vpcie1v8);
+		regulator_disable(rockchip->vpcie0v9);
+		rockchip_pcie_disable_clocks(rockchip);
+		err = rockchip_pcie_enable_clocks(rockchip);
+		if (err)
+			return err;
+		err = rockchip_pcie_set_vpcie(rockchip);
+		if (err) {
+			dev_err(dev, "failed to set vpcie regulator\n");
+			rockchip_pcie_disable_clocks(rockchip);
+			return err;
+		}
+		goto reinit;
+	}
+
+	else if (err) {
 		dev_err(dev, "PCIe link training gen1 timeout!\n");
 		goto err_power_off_phy;
 	}
@@ -613,53 +693,6 @@ static int rockchip_pcie_parse_host_dt(struct rockchip_pcie *rockchip)
 	return 0;
 }
 
-static int rockchip_pcie_set_vpcie(struct rockchip_pcie *rockchip)
-{
-	struct device *dev = rockchip->dev;
-	int err;
-
-	if (!IS_ERR(rockchip->vpcie12v)) {
-		err = regulator_enable(rockchip->vpcie12v);
-		if (err) {
-			dev_err(dev, "fail to enable vpcie12v regulator\n");
-			goto err_out;
-		}
-	}
-
-	if (!IS_ERR(rockchip->vpcie3v3)) {
-		err = regulator_enable(rockchip->vpcie3v3);
-		if (err) {
-			dev_err(dev, "fail to enable vpcie3v3 regulator\n");
-			goto err_disable_12v;
-		}
-	}
-
-	err = regulator_enable(rockchip->vpcie1v8);
-	if (err) {
-		dev_err(dev, "fail to enable vpcie1v8 regulator\n");
-		goto err_disable_3v3;
-	}
-
-	err = regulator_enable(rockchip->vpcie0v9);
-	if (err) {
-		dev_err(dev, "fail to enable vpcie0v9 regulator\n");
-		goto err_disable_1v8;
-	}
-
-	return 0;
-
-err_disable_1v8:
-	regulator_disable(rockchip->vpcie1v8);
-err_disable_3v3:
-	if (!IS_ERR(rockchip->vpcie3v3))
-		regulator_disable(rockchip->vpcie3v3);
-err_disable_12v:
-	if (!IS_ERR(rockchip->vpcie12v))
-		regulator_disable(rockchip->vpcie12v);
-err_out:
-	return err;
-}
-
 static void rockchip_pcie_enable_interrupts(struct rockchip_pcie *rockchip)
 {
 	rockchip_pcie_write(rockchip, (PCIE_CLIENT_INT_CLI << 16) &
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFC PATCH v2 2/2] arm64: dts: rockchip: drop PCIe 3v3 always-on and boot-on
  2025-06-10 16:36 [RFC PATCH v2 0/2] PCI: rockchip-host: Support quirky devices Geraldo Nascimento
  2025-06-10 16:37 ` [RFC PATCH v2 1/2] PCI: rockchip-host: Retry link training on failure without PERST# Geraldo Nascimento
@ 2025-06-10 16:37 ` Geraldo Nascimento
  1 sibling, 0 replies; 5+ messages in thread
From: Geraldo Nascimento @ 2025-06-10 16:37 UTC (permalink / raw)
  To: linux-rockchip
  Cc: Hugh Cole-Baker, Shawn Lin, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
	Bjorn Helgaas, Heiko Stuebner, linux-pci, linux-arm-kernel,
	linux-kernel

Example commit of needed dropping of regulator always-on/boot-on
declarations to make sure quirky devices known to not be working
on RK3399 are able to enumerate on second try without
assertion/deassertion of PERST# in-band PCIe reset signal.

One example only, to avoid patch-bomb.

Signed-off-by: Geraldo Nascimento <geraldogabriel@gmail.com>
---
 arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi
index 8ce7cee92af0..d31fd3d34cda 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399pro-vmarc-som.dtsi
@@ -25,8 +25,6 @@ vcc3v3_pcie: regulator-vcc-pcie {
 		pinctrl-names = "default";
 		pinctrl-0 = <&pcie_pwr>;
 		regulator-name = "vcc3v3_pcie";
-		regulator-always-on;
-		regulator-boot-on;
 		vin-supply = <&vcc5v0_sys>;
 	};
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH v2 1/2] PCI: rockchip-host: Retry link training on failure without PERST#
  2025-06-10 16:37 ` [RFC PATCH v2 1/2] PCI: rockchip-host: Retry link training on failure without PERST# Geraldo Nascimento
@ 2025-06-10 18:44   ` Bjorn Helgaas
  2025-06-10 18:48     ` Geraldo Nascimento
  0 siblings, 1 reply; 5+ messages in thread
From: Bjorn Helgaas @ 2025-06-10 18:44 UTC (permalink / raw)
  To: Geraldo Nascimento
  Cc: linux-rockchip, Hugh Cole-Baker, Shawn Lin, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
	Bjorn Helgaas, Heiko Stuebner, linux-pci, linux-arm-kernel,
	linux-kernel

On Tue, Jun 10, 2025 at 01:37:12PM -0300, Geraldo Nascimento wrote:
> After almost 30 days of battling with RK3399 buggy PCIe on my Rock Pi
> N10 through trial-and-error debugging, I finally got positive results
> with enumeration on the PCI bus for both a Realtek 8111E NIC and a
> Samsung PM981a SSD.

> +static int rockchip_pcie_set_vpcie(struct rockchip_pcie *rockchip)
> +{
> +	struct device *dev = rockchip->dev;
> +	int err;
> +
> +	if (!IS_ERR(rockchip->vpcie12v)) {
> +		err = regulator_enable(rockchip->vpcie12v);
> +		if (err) {
> +			dev_err(dev, "fail to enable vpcie12v regulator\n");
> +			goto err_out;
> +		}
> +	}
> +
> +	if (!IS_ERR(rockchip->vpcie3v3)) {
> +		err = regulator_enable(rockchip->vpcie3v3);
> +		if (err) {
> +			dev_err(dev, "fail to enable vpcie3v3 regulator\n");
> +			goto err_disable_12v;
> +		}
> +	}
> +
> +	err = regulator_enable(rockchip->vpcie1v8);
> +	if (err) {
> +		dev_err(dev, "fail to enable vpcie1v8 regulator\n");
> +		goto err_disable_3v3;
> +	}
> +
> +	err = regulator_enable(rockchip->vpcie0v9);
> +	if (err) {
> +		dev_err(dev, "fail to enable vpcie0v9 regulator\n");
> +		goto err_disable_1v8;
> +	}
> +
> +	return 0;
> +
> +err_disable_1v8:
> +	regulator_disable(rockchip->vpcie1v8);
> +err_disable_3v3:
> +	if (!IS_ERR(rockchip->vpcie3v3))
> +		regulator_disable(rockchip->vpcie3v3);
> +err_disable_12v:
> +	if (!IS_ERR(rockchip->vpcie12v))
> +		regulator_disable(rockchip->vpcie12v);
> +err_out:
> +	return err;
> +}

This *looks* like it could be strictly a move of
rockchip_pcie_set_vpcie(), without changing it at all.

If that's the case, please make the move a separate patch so it's more
obvious what the interesting changes that actually make a difference
are.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH v2 1/2] PCI: rockchip-host: Retry link training on failure without PERST#
  2025-06-10 18:44   ` Bjorn Helgaas
@ 2025-06-10 18:48     ` Geraldo Nascimento
  0 siblings, 0 replies; 5+ messages in thread
From: Geraldo Nascimento @ 2025-06-10 18:48 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: linux-rockchip, Hugh Cole-Baker, Shawn Lin, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
	Bjorn Helgaas, Heiko Stuebner, linux-pci, linux-arm-kernel,
	linux-kernel

On Tue, Jun 10, 2025 at 01:44:49PM -0500, Bjorn Helgaas wrote:
> This *looks* like it could be strictly a move of
> rockchip_pcie_set_vpcie(), without changing it at all.

Hi Bjorn,

yes, a move of rockchip_pcie_set_vpcie() is needed for re-enabling
power rails, considering patch 2/2 was also applied and the regulator
is not always-on anymore.

> If that's the case, please make the move a separate patch so it's more
> obvious what the interesting changes that actually make a difference
> are.

Good idea, I'll send v3.

Thank you!
Geraldo Nascimento

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-06-10 18:48 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-10 16:36 [RFC PATCH v2 0/2] PCI: rockchip-host: Support quirky devices Geraldo Nascimento
2025-06-10 16:37 ` [RFC PATCH v2 1/2] PCI: rockchip-host: Retry link training on failure without PERST# Geraldo Nascimento
2025-06-10 18:44   ` Bjorn Helgaas
2025-06-10 18:48     ` Geraldo Nascimento
2025-06-10 16:37 ` [RFC PATCH v2 2/2] arm64: dts: rockchip: drop PCIe 3v3 always-on and boot-on Geraldo Nascimento

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).