Devicetree
 help / color / mirror / Atom feed
* [PATCH 0/2] Support updating the PCIe3 PHY firmware on RK3568
@ 2026-10-20  3:16 Shawn Lin
  2026-10-20  3:16 ` [PATCH 1/2] dt-bindings: phy: rockchip,pcie3-phy: Document firmware-name Shawn Lin
  2026-10-20  3:16 ` [PATCH 2/2] phy: rockchip: snps-pcie3: Load updated PHY firmware on RK3568 Shawn Lin
  0 siblings, 2 replies; 4+ messages in thread
From: Shawn Lin @ 2026-10-20  3:16 UTC (permalink / raw)
  To: Vinod Koul, Heiko Stuebner, Krzysztof Kozlowski, Conor Dooley,
	Rob Herring
  Cc: linux-rockchip, linux-phy, Manivannan Sadhasivam, Neil Armstrong,
	devicetree, Samuel Holland, Coia Prant, Shawn Lin


The RK3568 PCIe3 PHY contains a small controller that runs microcode
from an internal SRAM. The microcode present in the PHY is not always
the latest one; with a stale version the PHY may fail to establish a
stable link or come up with other issues that are otherwise very hard
to diagnose from the host side.

The firmware stays optional: when firmware-name is not described in DT
(older DTBs) or the file cannot be requested, the driver keeps the
existing behaviour and runs with the microcode already present in the
PHY, so there is no new hard dependency for existing boards.

Patch 2 for the PHY driver depends on a pending patch that fixes another
issue if anyone wants to apply this series for test:

lore.kernel.org/linux-rockchip/1792286036-208067-1-git-send-email-shawn.lin@rock-chips.com/


The required firmware file is available in the rockchip directory of
the linux-firmware repository:

  https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git

Load firmware during kernel compilation using the extra firmware assignment:

CONFIG_EXTRA_FIRMWARE="rockchip/pcie3-t22-c8g2-1.6.3-202a-p7.fw"
CONFIG_EXTRA_FIRMWARE_DIR="/home/lt/linux-firmware"

Tested on a RK3568 EVB1 with a PCIe3 x2 NVMe SSD, the firmware is loaded
and the link comes up:

  phy phy-fe8c0000.phy.0: lane number 0, val 1
  rockchip-snps-pcie3-phy fe8c0000.phy: loaded PHY firmware rockchip/pcie3-t22-c8g2-1.6.3-202a-p7.fw, size 16384
  rockchip-dw-pcie 3c0800000.pcie: host bridge /pcie@fe280000 ranges:
  ...
  pci 0002:21:00.0: [1e0f:0009] type 00 class 0x010802 PCIe Endpoint
  pci 0002:21:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
  pci 0002:21:00.0: 15.752 Gb/s available PCIe bandwidth, limited by 8.0 GT/s PCIe x2 link at 0002:20:00.0 (capable of 31.504 Gb/s with 8.0 GT/s PCIe x4 link)
  pci 0002:21:00.0: ASPM: default states L1



Shawn Lin (2):
  dt-bindings: phy: rockchip,pcie3-phy: Document firmware-name
  phy: rockchip: snps-pcie3: Load updated PHY firmware on RK3568

 .../bindings/phy/rockchip,pcie3-phy.yaml           |   6 ++
 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c     | 101 ++++++++++++++++++++-
 2 files changed, 105 insertions(+), 2 deletions(-)

-- 
2.7.4


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

* [PATCH 1/2] dt-bindings: phy: rockchip,pcie3-phy: Document firmware-name
  2026-10-20  3:16 [PATCH 0/2] Support updating the PCIe3 PHY firmware on RK3568 Shawn Lin
@ 2026-10-20  3:16 ` Shawn Lin
  2026-10-22  9:57   ` Krzysztof Kozlowski
  2026-10-20  3:16 ` [PATCH 2/2] phy: rockchip: snps-pcie3: Load updated PHY firmware on RK3568 Shawn Lin
  1 sibling, 1 reply; 4+ messages in thread
From: Shawn Lin @ 2026-10-20  3:16 UTC (permalink / raw)
  To: Vinod Koul, Heiko Stuebner, Krzysztof Kozlowski, Conor Dooley,
	Rob Herring
  Cc: linux-rockchip, linux-phy, Manivannan Sadhasivam, Neil Armstrong,
	devicetree, Samuel Holland, Coia Prant, Shawn Lin

RK3568 can load an updated PHY firmware into its internal SRAM. The
firmware file is named by the optional firmware-name property; when it
is not described the microcode already present in the PHY is used.

Document the property and add it to the RK3568 example.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---

 Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
index d7de8b5..2356812 100644
--- a/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
@@ -67,6 +67,11 @@ properties:
       minimum: 0
       maximum: 1
 
+  firmware-name:
+    description:
+      Name of the PHY firmware loaded into the internal SRAM on RK3568.
+      If omitted, the firmware already present in the PHY is used.
+
 required:
   - compatible
   - reg
@@ -113,4 +118,5 @@ examples:
       resets = <&cru SRST_PCIE30PHY>;
       reset-names = "phy";
       rockchip,phy-grf = <&pcie30_phy_grf>;
+      firmware-name = "rockchip/pcie3-t22-c8g2-1.6.3-202a-p7.fw";
     };
-- 
2.7.4


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

* [PATCH 2/2] phy: rockchip: snps-pcie3: Load updated PHY firmware on RK3568
  2026-10-20  3:16 [PATCH 0/2] Support updating the PCIe3 PHY firmware on RK3568 Shawn Lin
  2026-10-20  3:16 ` [PATCH 1/2] dt-bindings: phy: rockchip,pcie3-phy: Document firmware-name Shawn Lin
@ 2026-10-20  3:16 ` Shawn Lin
  1 sibling, 0 replies; 4+ messages in thread
From: Shawn Lin @ 2026-10-20  3:16 UTC (permalink / raw)
  To: Vinod Koul, Heiko Stuebner, Krzysztof Kozlowski, Conor Dooley,
	Rob Herring
  Cc: linux-rockchip, linux-phy, Manivannan Sadhasivam, Neil Armstrong,
	devicetree, Samuel Holland, Coia Prant, Shawn Lin

The RK3568 PCIe3 PHY can load an updated firmware into its internal
SRAM during initialization. Without it the PHY may come up with a stale
microcode and fail to establish a stable link.

Load the firmware named by the optional firmware-name DT property during
probe, so that it is available in the phy_init() context and is not read
from the filesystem on every init. During initialization, clear SDRAM
load done and bypass, wait for the SRAM to lock, map the SRAM into the
register window, write the firmware and finally signal SDRAM load done.

The firmware is optional: when firmware-name is absent (older DTBs) or
the file cannot be loaded, the driver keeps the behaviour unchanged and
uses the microcode already present in the PHY.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---

 drivers/phy/rockchip/phy-rockchip-snps-pcie3.c | 101 ++++++++++++++++++++++++-
 1 file changed, 99 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
index ce7d8db..bc1b4d0 100644
--- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
+++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
@@ -7,6 +7,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/firmware.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
@@ -19,11 +20,13 @@
 #include <linux/regmap.h>
 #include <linux/reset.h>
 #include <linux/units.h>
+#include <linux/unaligned.h>
 
 #define RK_PCIE_SRAM_INIT_TIMEOUT_US		(20 * USEC_PER_MSEC)
 
 /* Register for RK3568 */
 #define GRF_PCIE30PHY_CON1			0x4
+#define GRF_PCIE30PHY_CON4			0x10
 #define GRF_PCIE30PHY_CON6			0x18
 #define GRF_PCIE30PHY_CON9			0x24
 #define GRF_PCIE30PHY_DA_OCM			(BIT(15) | BIT(31))
@@ -31,6 +34,11 @@
 #define GRF_PCIE30PHY_WR_EN			(0xf << 16)
 #define SRAM_INIT_DONE(reg)			(reg & BIT(14))
 
+#define GRF_PCIE30PHY_CON4_SDRAM_LD_DONE	BIT(14)
+#define GRF_PCIE30PHY_CON4_SDRAM_BYPASS		BIT(13)
+#define GRF_PCIE30PHY_CON9_SRAM_MAP		(0x3 << 8)
+#define GRF_PCIE30PHY_CON9_SRAM_MAP_WE		(0x3 << 24)
+
 #define RK3568_BIFURCATION_LANE_0_1		BIT(0)
 
 /* Register for RK3588 */
@@ -56,6 +64,7 @@ struct rockchip_p3phy_ops;
 
 struct rockchip_p3phy_priv {
 	const struct rockchip_p3phy_ops *ops;
+	struct device *dev;
 	void __iomem *mmio;
 	/* mode: RC, EP */
 	int mode;
@@ -70,6 +79,8 @@ struct rockchip_p3phy_priv {
 	int num_lanes;
 	u32 lanes[4];
 	u32 rx_cmn_refclk_mode[4];
+	const struct firmware *fw;
+	const char *fw_name;
 };
 
 struct rockchip_p3phy_ops {
@@ -96,6 +107,34 @@ static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int subm
 	return 0;
 }
 
+static void rockchip_p3phy_release_fw(void *data)
+{
+	struct rockchip_p3phy_priv *priv = data;
+
+	release_firmware(priv->fw);
+	priv->fw = NULL;
+}
+
+static void rockchip_p3phy_rk3568_load_fw(struct rockchip_p3phy_priv *priv)
+{
+	const struct firmware *fw = priv->fw;
+	int i;
+
+	/* Map the PHY SRAM into the register window to write the firmware. */
+	regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9,
+		     GRF_PCIE30PHY_CON9_SRAM_MAP | GRF_PCIE30PHY_CON9_SRAM_MAP_WE);
+
+	for (i = 0; i < fw->size / sizeof(u16); i++)
+		writel(get_unaligned_le16(fw->data + i * sizeof(u16)),
+		       priv->mmio + (i << 2));
+
+	dev_dbg(priv->dev, "loaded PHY firmware %s, size %zu\n",
+		priv->fw_name, fw->size);
+
+	/* Unmap: field back to 0 with the write-enable for bits[9:8] */
+	regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_CON9_SRAM_MAP_WE);
+}
+
 static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
 {
 	struct phy *phy = priv->phy;
@@ -125,16 +164,41 @@ static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
 			     GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1);
 	}
 
+	/* Clear SDRAM load done and bypass before loading the new firmware. */
+	if (priv->fw) {
+		regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4,
+			     GRF_PCIE30PHY_CON4_SDRAM_LD_DONE << 16);
+		regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4,
+			     GRF_PCIE30PHY_CON4_SDRAM_BYPASS << 16);
+	}
+
 	reset_control_deassert(priv->p30phy);
 
 	ret = regmap_read_poll_timeout(priv->phy_grf,
 				       GRF_PCIE30PHY_STATUS0,
 				       reg, SRAM_INIT_DONE(reg),
 				       1000, RK_PCIE_SRAM_INIT_TIMEOUT_US);
-	if (ret)
+	if (ret) {
 		dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n",
 		       __func__, reg);
-	return ret;
+		return ret;
+	}
+
+	/*
+	 * Load the updated PHY firmware into the internal SRAM and signal
+	 * SDRAM load done once it has been written. The firmware update is
+	 * optional: when no firmware-name is described in DT (older DTBs)
+	 * the microcode already present in the PHY is used as-is.
+	 */
+	if (priv->fw) {
+		rockchip_p3phy_rk3568_load_fw(priv);
+
+		regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4,
+			     (GRF_PCIE30PHY_CON4_SDRAM_LD_DONE << 16) |
+			     GRF_PCIE30PHY_CON4_SDRAM_LD_DONE);
+	}
+
+	return 0;
 }
 
 static const struct rockchip_p3phy_ops rk3568_ops = {
@@ -250,12 +314,14 @@ static int rockchip_p3phy_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct rockchip_p3phy_priv *priv;
 	struct device_node *np = dev->of_node;
+	const char *fw_name;
 	int ret;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
+	priv->dev = dev;
 	priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
 	if (IS_ERR(priv->mmio)) {
 		ret = PTR_ERR(priv->mmio);
@@ -268,6 +334,37 @@ static int rockchip_p3phy_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
+	/*
+	 * RK3568 can load an updated PHY firmware into its internal SRAM. The
+	 * firmware file is named by the optional firmware-name property; when
+	 * it is not described (older DTBs) or cannot be loaded, keep using the
+	 * microcode already present in the PHY.
+	 */
+	if (priv->ops == &rk3568_ops && !of_property_read_string(np, "firmware-name",
+								 &fw_name)) {
+		ret = request_firmware(&priv->fw, fw_name, dev);
+		if (ret) {
+			dev_warn(dev, "PHY firmware %s not available: %d\n",
+				 fw_name, ret);
+			priv->fw = NULL;
+		} else if (priv->fw->size % sizeof(u16)) {
+			dev_warn(dev, "invalid PHY firmware size %zu, skip update\n",
+				 priv->fw->size);
+			release_firmware(priv->fw);
+			priv->fw = NULL;
+		} else {
+			priv->fw_name = fw_name;
+		}
+
+		if (priv->fw) {
+			ret = devm_add_action_or_reset(dev,
+						       rockchip_p3phy_release_fw,
+						       priv);
+			if (ret)
+				return ret;
+		}
+	}
+
 	priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf");
 	if (IS_ERR(priv->phy_grf)) {
 		dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
-- 
2.7.4


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

* Re: [PATCH 1/2] dt-bindings: phy: rockchip,pcie3-phy: Document firmware-name
  2026-10-20  3:16 ` [PATCH 1/2] dt-bindings: phy: rockchip,pcie3-phy: Document firmware-name Shawn Lin
@ 2026-10-22  9:57   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 4+ messages in thread
From: Krzysztof Kozlowski @ 2026-10-22  9:57 UTC (permalink / raw)
  To: Shawn Lin
  Cc: Vinod Koul, Heiko Stuebner, Krzysztof Kozlowski, Conor Dooley,
	Rob Herring, linux-rockchip, linux-phy, Manivannan Sadhasivam,
	Neil Armstrong, devicetree, Samuel Holland, Coia Prant

On Tue, Oct 20, 2026 at 11:16:45AM +0800, Shawn Lin wrote:
> RK3568 can load an updated PHY firmware into its internal SRAM. The
> firmware file is named by the optional firmware-name property; when it
> is not described the microcode already present in the PHY is used.
> 
> Document the property and add it to the RK3568 example.
> 
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> ---
> 
>  Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
> index d7de8b5..2356812 100644
> --- a/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/rockchip,pcie3-phy.yaml
> @@ -67,6 +67,11 @@ properties:
>        minimum: 0
>        maximum: 1
>  
> +  firmware-name:

missing maxItems

> +    description:

Best regards,
Krzysztof


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

end of thread, other threads:[~2026-10-22  9:57 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-20  3:16 [PATCH 0/2] Support updating the PCIe3 PHY firmware on RK3568 Shawn Lin
2026-10-20  3:16 ` [PATCH 1/2] dt-bindings: phy: rockchip,pcie3-phy: Document firmware-name Shawn Lin
2026-10-22  9:57   ` Krzysztof Kozlowski
2026-10-20  3:16 ` [PATCH 2/2] phy: rockchip: snps-pcie3: Load updated PHY firmware on RK3568 Shawn Lin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox