From nobody Sun Feb 8 05:59:09 2026 Received: from out-177.mta0.migadu.com (out-177.mta0.migadu.com [91.218.175.177]) (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 91B0719992C for ; Tue, 3 Feb 2026 00:21:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078111; cv=none; b=Xl3r7HgBinPJ64BuJtPMD8FNKiS70XICf63bWa5p6sdNGzSH07DsJE9hHWYSKynwKRxtoCV5H0E5uJZLtPr5yBL6+WUk4+WK+18lHLZXybJR2ZHVkz/Xv8ifRW5186kdPHVPbOYxyaDQy9VLP3NuciFPUEPaW8lCasWI67+iNYU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078111; c=relaxed/simple; bh=Qg515vPUC3kcI00i4qvUjLj97sIrt0kOOoiol4VVZXs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=EFN577ySe9cm6YNC57QZkHiAi9SBgIMgJpVNVA423GaVv1D+nEbKKTgUu2/+gc/WR7HqwKNfXcYNH5hH63zjA1h25GeCCsz/ANkuPGCEFrWWyY1izEY43pyr0RmfLl4wjf0bcfw9tEfYHb00E+NFUc274hbWCwZZ4jWdgGnGRI8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=W7r5iL5h; arc=none smtp.client-ip=91.218.175.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="W7r5iL5h" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770078107; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cuOWsCVIuR/WP5JRTGWbVJdWhDaeD5ZnnFP7ct7wKpA=; b=W7r5iL5hkTeQqW8Tiz4WLikSlkj4xcLTE/siInq6WUpr63vnkN3X7yN6abAqkxH0s5s6Ax oGrpdEON//phRH0Qy8HTJ5YB7JGd95fAeoarSq3vpBpn/QjbLoxjZderDJpwRRB5z0nPZH m+9cFfB2Ofzw3aDCUV7etEuM9laF1T8= From: Sean Anderson To: Laurent Pinchart , Vinod Koul , linux-phy@lists.infradead.org Cc: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Lorenzo Pieralisi , Radhey Shyam Pandey , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, Neil Armstrong , Rob Herring , Thippeswamy Havalige , Manivannan Sadhasivam , Bjorn Helgaas , Sean Anderson , Conor Dooley , Krzysztof Kozlowski , devicetree@vger.kernel.org Subject: [PATCH 1/8] dt-bindings: pci: xilinx-nwl: Add resets Date: Mon, 2 Feb 2026 19:21:21 -0500 Message-Id: <20260203002128.935842-2-sean.anderson@linux.dev> In-Reply-To: <20260203002128.935842-1-sean.anderson@linux.dev> References: <20260203002128.935842-1-sean.anderson@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Add resets so we can hold the bridge in reset while we perform phy calibration. Signed-off-by: Sean Anderson --- .../devicetree/bindings/pci/xlnx,nwl-pcie.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml b/Doc= umentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml index 9de3c09efb6e..7efb3dd9955f 100644 --- a/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml +++ b/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml @@ -69,6 +69,18 @@ properties: power-domains: maxItems: 1 =20 + resets: + maxItems: 3 + + reset-names: + items: + - description: APB register block reset + const: cfg + - description: AXI-PCIe bridge reset + const: bridge + - description: PCIe MAC reset + const: ctrl + iommus: maxItems: 1 =20 @@ -117,6 +129,7 @@ examples: #include #include #include + #include soc { #address-cells =3D <2>; #size-cells =3D <2>; @@ -146,6 +159,10 @@ examples: msi-parent =3D <&nwl_pcie>; phys =3D <&psgtr 0 PHY_TYPE_PCIE 0 0>; power-domains =3D <&zynqmp_firmware PD_PCIE>; + resets =3D <&zynqmp_reset ZYNQMP_RESET_PCIE_CFG>, + <&zynqmp_reset ZYNQMP_RESET_PCIE_BRIDGE>, + <&zynqmp_reset ZYNQMP_RESET_PCIE_CTRL>; + reset-names =3D "cfg", "bridge", "ctrl"; iommus =3D <&smmu 0x4d0>; pcie_intc: legacy-interrupt-controller { interrupt-controller; --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Feb 8 05:59:09 2026 Received: from out-183.mta0.migadu.com (out-183.mta0.migadu.com [91.218.175.183]) (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 B0A55191F84; Tue, 3 Feb 2026 00:21:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.183 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078113; cv=none; b=cFZVAVk22fgLyRRB5gZ5EdTnhNFnlBNqblam00Nw+zuF+4sLg+ZIFD+gRfalthcGmXI6Gp5ONukknxZaRD7VYNvxfxo6+eb7QGNvxrcldN1lGfTBENTjJVnNw8yoRVw72Ctfs92MYsmHK4v2yIryIiaUN+czwsA5JN7TfmyScl8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078113; c=relaxed/simple; bh=Vo467vveR/1rzNqRuyhiz3rkXqxzgUsbDQa4s1ebYGo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=d6kfaimAUfOj4zD43pLZRHcx4I4969JxKFLsQr8mmQ7S7gJIhFap2OwnAjMtm1UnLCWfU0Hs+Yf1XLx49b6uxxHLpSiQ/0o4WG4ZB8dEyS2nBBQUvLvKHJprbotZ3v9gGolvbinmW3Fp/O30VG3QOPnaejLHgqmxkEr41Uva5tg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=F56dhBSk; arc=none smtp.client-ip=91.218.175.183 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="F56dhBSk" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770078109; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=thJ1sEYwFgH0EvKxYK16kbar1XTDnkSFrt//2tTCrRU=; b=F56dhBSkAWENXfvqexDxxPOibf1MniHSlSg6KfR3MGZFA9/oZaLVyAlV1239KOjLP073rC dz2ohdPnqZpgUZakeqtU1ySICG7LLFePZbVos+3ZQvWxNIEPXwDBBFMzWqbo8KEuRgaL/F p9FMmbWygvHrJYq0b36bpoIQuRwu9m0= From: Sean Anderson To: Laurent Pinchart , Vinod Koul , linux-phy@lists.infradead.org Cc: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Lorenzo Pieralisi , Radhey Shyam Pandey , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, Neil Armstrong , Rob Herring , Thippeswamy Havalige , Manivannan Sadhasivam , Bjorn Helgaas , Sean Anderson Subject: [PATCH 2/8] phy: zynqmp: Refactor bus width configuration into helper Date: Mon, 2 Feb 2026 19:21:22 -0500 Message-Id: <20260203002128.935842-3-sean.anderson@linux.dev> In-Reply-To: <20260203002128.935842-1-sean.anderson@linux.dev> References: <20260203002128.935842-1-sean.anderson@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Split off the bus width configuration into a helper function for reuse. Signed-off-by: Sean Anderson --- drivers/phy/xilinx/phy-zynqmp.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqm= p.c index fe6b4925d166..0d3c578d0f3f 100644 --- a/drivers/phy/xilinx/phy-zynqmp.c +++ b/drivers/phy/xilinx/phy-zynqmp.c @@ -502,6 +502,17 @@ static void xpsgtr_lane_set_protocol(struct xpsgtr_phy= *gtr_phy) } } =20 +/* Set the bus width */ +static void xpsgtr_phy_init_bus_width(struct xpsgtr_phy *gtr_phy, u32 widt= h) +{ + struct xpsgtr_dev *gtr_dev =3D gtr_phy->dev; + u32 mask =3D PROT_BUS_WIDTH_MASK(gtr_phy->lane); + u32 val =3D width << PROT_BUS_WIDTH_SHIFT(gtr_phy->lane); + + xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, mask, val); + xpsgtr_clr_set(gtr_dev, RX_PROT_BUS_WIDTH, mask, val); +} + /* Bypass (de)scrambler and 8b/10b decoder and encoder. */ static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy) { @@ -535,14 +546,7 @@ static void xpsgtr_phy_init_sata(struct xpsgtr_phy *gt= r_phy) /* SGMII-specific initialization. */ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy) { - struct xpsgtr_dev *gtr_dev =3D gtr_phy->dev; - u32 mask =3D PROT_BUS_WIDTH_MASK(gtr_phy->lane); - u32 val =3D PROT_BUS_WIDTH_10 << PROT_BUS_WIDTH_SHIFT(gtr_phy->lane); - - /* Set SGMII protocol TX and RX bus width to 10 bits. */ - xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, mask, val); - xpsgtr_clr_set(gtr_dev, RX_PROT_BUS_WIDTH, mask, val); - + xpsgtr_phy_init_bus_width(gtr_phy, PROT_BUS_WIDTH_10); xpsgtr_bypass_scrambler_8b10b(gtr_phy); } =20 --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Feb 8 05:59:09 2026 Received: from out-171.mta0.migadu.com (out-171.mta0.migadu.com [91.218.175.171]) (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 C556B2F872 for ; Tue, 3 Feb 2026 00:21:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078115; cv=none; b=kuxJsuuhzIB2RSFJcmDgZDFRmLb0oPAE0ihNoveLOxGyAuQfpl0mZHMshh26dPCKMcFiDkxQ24FAqJaCM7WwFCcFomzweNXJ/dI/Ktw0Ioh4Vrv/Y0iqaBWtp7+byNlDJKp8fJUimgWvzQpVKv3SWJCYlGqccNsVNbG8gnyFr5Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078115; c=relaxed/simple; bh=5ZAeQfyJvvABXzYNXetE/mNDvGAHH5ZukN+JA2fOmvk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dd/8sTCoVdzsKiPzP1mcTrLDfRZojy0j2REA2ko2cvvXykqEZSIOFBr4qz41YtMfVTHi2vH0/EEvZeGYfh+uy3tvy331Eo3QnmaW/JRlGIaC1E/5ph2lqUvwRcwA4hbt7G4myVj2YOM/BGBGUtAlk4Y0gaPbu2DIgNIMnfFGCjg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=G4Sb+I8k; arc=none smtp.client-ip=91.218.175.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="G4Sb+I8k" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770078112; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BSzBHZdVygKXukk+iQ1E1BqwM0RrqN94x3Zvnkp6Hc8=; b=G4Sb+I8kM9gfwkpIfWB6Q9chGzCZDLL4XA7UXqu6mEzNp2obCYBdVFniqPfgV61J8gxLFl SwS8Tjh3iOEbVZuhJKic+JCuTd04pT7Et+ubEPZnnzeKiO0V2ywYm3UtmmG/dXUKPZKVSg Cn6NV7aXAr8CqQiyitJ5f1DUAqxAO/g= From: Sean Anderson To: Laurent Pinchart , Vinod Koul , linux-phy@lists.infradead.org Cc: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Lorenzo Pieralisi , Radhey Shyam Pandey , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, Neil Armstrong , Rob Herring , Thippeswamy Havalige , Manivannan Sadhasivam , Bjorn Helgaas , Sean Anderson Subject: [PATCH 3/8] phy: zynqmp: Refactor common phy initialization into a helper Date: Mon, 2 Feb 2026 19:21:23 -0500 Message-Id: <20260203002128.935842-4-sean.anderson@linux.dev> In-Reply-To: <20260203002128.935842-1-sean.anderson@linux.dev> References: <20260203002128.935842-1-sean.anderson@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" All lanes undergoing ILL calibration must be initialized. Split off common phy initialization into a helper so that we can ensure all lanes are initialized before performing calibration. Signed-off-by: Sean Anderson --- drivers/phy/xilinx/phy-zynqmp.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqm= p.c index 0d3c578d0f3f..152af1702bbd 100644 --- a/drivers/phy/xilinx/phy-zynqmp.c +++ b/drivers/phy/xilinx/phy-zynqmp.c @@ -520,6 +520,21 @@ static void xpsgtr_bypass_scrambler_8b10b(struct xpsgt= r_phy *gtr_phy) xpsgtr_write_phy(gtr_phy, L0_TX_DIG_61, L0_TM_DISABLE_SCRAMBLE_ENCODER); } =20 +static int xpsgtr_common_init(struct xpsgtr_phy *gtr_phy) +{ + int ret; + + /* Enable coarse code saturation limiting logic. */ + xpsgtr_write_phy(gtr_phy, L0_TM_PLL_DIG_37, L0_TM_COARSE_CODE_LIMIT); + + ret =3D xpsgtr_configure_pll(gtr_phy); + if (ret) + return ret; + + xpsgtr_lane_set_protocol(gtr_phy); + return 0; +} + /* DP-specific initialization. */ static void xpsgtr_phy_init_dp(struct xpsgtr_phy *gtr_phy) { @@ -682,19 +697,14 @@ static int xpsgtr_phy_init(struct phy *phy) gtr_dev->tx_term_fix =3D false; } =20 - /* Enable coarse code saturation limiting logic. */ - xpsgtr_write_phy(gtr_phy, L0_TM_PLL_DIG_37, L0_TM_COARSE_CODE_LIMIT); - /* * Configure the PLL, the lane protocol, and perform protocol-specific * initialization. */ - ret =3D xpsgtr_configure_pll(gtr_phy); + ret =3D xpsgtr_common_init(gtr_phy); if (ret) goto out; =20 - xpsgtr_lane_set_protocol(gtr_phy); - switch (gtr_phy->protocol) { case ICM_PROTOCOL_DP: xpsgtr_phy_init_dp(gtr_phy); --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Feb 8 05:59:09 2026 Received: from out-182.mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (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 549851A0712 for ; Tue, 3 Feb 2026 00:21:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078120; cv=none; b=DDF4sTR9MzQ6mI/tBFPQUUprbIr8HXoZH2aW5PxwaudTrScixoyHiJ1QzgrVoqi9ciF6zNNNFapiFh58pGAP5aFYJtNg7ZIXnGu6JStrU+RAxL7IIS5cKz3PJO/WUh26Bk0f5z3dwiLiKby7f645ZCKlh6v7f9dVrHt8i0ACSW4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078120; c=relaxed/simple; bh=OwJ63bWvia7d2mD4hwpP2DaFuXCiCmyBFm83IR79sj4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dnLL0H9HDVI0ElIHUtIWMVixHPpTum09t4sR7HcrHgHa7JcRjDe/W2v4A1r0+OOTea9sl9fZpMbz6to7ETmhugKnqY0g2wniOIyu5nitz5Ol62zYrV5ZcQYoQiXzBvyWxckQTMByXMNlo+R+hvdTh3yRxIroxZPm8t5wagyz66Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=MxL16stz; arc=none smtp.client-ip=91.218.175.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="MxL16stz" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770078114; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=w24IIxZZxLh5GU640i/JqJSLk3kZfm23UP8vitqz+Bc=; b=MxL16stz+gW8RY9EljLTEt97lkSXh9pAYaik3G6lt9dUPnhfA9cSXEq0VBusQEz6srMcBV 8Plczvz3bbf1IDPLiWUrDSe2FlRYtozu3BZn88MLSfD2UpjXE0rauvK6nA2UrOVZgGKMRU QaDZslpLuDw6uMEWEKaNXhJk/jzAxhY= From: Sean Anderson To: Laurent Pinchart , Vinod Koul , linux-phy@lists.infradead.org Cc: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Lorenzo Pieralisi , Radhey Shyam Pandey , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, Neil Armstrong , Rob Herring , Thippeswamy Havalige , Manivannan Sadhasivam , Bjorn Helgaas , Sean Anderson Subject: [PATCH 4/8] phy: zynqmp: Calibrate ILL if necessary Date: Mon, 2 Feb 2026 19:21:24 -0500 Message-Id: <20260203002128.935842-5-sean.anderson@linux.dev> In-Reply-To: <20260203002128.935842-1-sean.anderson@linux.dev> References: <20260203002128.935842-1-sean.anderson@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" init_serdes in psu_init_gpl is supposed to calibrate the ILL. However, this may fail if the reference clock is not running, such as if the clock needs to be configured on boot. To work around this, add support for ILL calibration in U-Boot. If the ILL is already calibrated (any non-zero value) we skip calibration. The algorithm is substantially the same as serdes_illcalib [1], but it has been updated for readability (and to remove all the "if (lane0_active)" conditions). Due to the amount of register fields, many of which are undocumented (especially the chicken bits), I have mostly used defines only for the register names. There are certainly areas where register writes are superfluous, but I have left these in order to minimize deviation from the procedure in serdes_illcalib. [1] Example implementation; xpsgtr_phy_illcalib coresponds to serdes_illcalib_pcie_gen1: https://source.denx.de/u-boot/u-boot/-/blob/v2026.01/board/xilinx/zynqmp/zy= nqmp-zcu208-revA/psu_init_gpl.c?ref_type=3Dtags#L710 Signed-off-by: Sean Anderson --- drivers/phy/xilinx/phy-zynqmp.c | 421 +++++++++++++++++++++++++++++++- 1 file changed, 420 insertions(+), 1 deletion(-) diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqm= p.c index 152af1702bbd..854b0ea04648 100644 --- a/drivers/phy/xilinx/phy-zynqmp.c +++ b/drivers/phy/xilinx/phy-zynqmp.c @@ -12,6 +12,7 @@ * PCIe should also work but that is experimental as of now. */ =20 +#include #include #include #include @@ -31,6 +32,7 @@ */ =20 /* TX De-emphasis parameters */ +#define L0_TX_ANA_TM_3 0x000c #define L0_TX_ANA_TM_18 0x0048 #define L0_TX_ANA_TM_118 0x01d8 #define L0_TX_ANA_TM_118_FORCE_17_0 BIT(0) @@ -50,16 +52,49 @@ #define L0_TXPMD_TM_45_ENABLE_DP_POST2 BIT(5) =20 /* PCS control parameters */ +#define L0_TM_ANA_BYP_4 0x1010 +#define L0_TM_ANA_BYP_7 0x1018 #define L0_TM_DIG_6 0x106c +#define L0_TM_DIG_22 0x10ac #define L0_TM_DIS_DESCRAMBLE_DECODER 0x0f #define L0_TX_DIG_61 0x00f4 #define L0_TM_DISABLE_SCRAMBLE_ENCODER 0x0f +#define L0_TM_AUX_0 0x10cc +#define L0_TM_MISC2 0x189c +#define L0_TM_MISC2_ILL_CAL_BYPASS BIT(7) +#define L0_TM_IQ_ILL1 0x18f8 +#define L0_TM_IQ_ILL2 0x18fc +#define L0_TM_ILL11 0x198c +#define L0_TM_ILL12 0x1990 +#define L0_TM_E_ILL1 0x1924 +#define L0_TM_E_ILL2 0x1928 +#define L0_TM_IQ_ILL3 0x1900 +#define L0_TM_E_ILL3 0x192c +#define L0_TM_IQ_ILL7 0x1910 +#define L0_TM_E_ILL7 0x193c +#define L0_TM_ILL8 0x1980 +#define L0_TM_IQ_ILL8 0x1914 +#define L0_TM_IQ_ILL9 0x1918 +#define L0_TM_EQ0 0x194c +#define L0_TM_EQ0_EQ_STG2_CTRL_BYP BIT(5) +#define L0_TM_EQ1 0x1950 +#define L0_TM_EQ1_EQ_STG2_RL_PROG GENMASK(1, 0) +#define L0_TM_EQ1_EQ_STG2_PREAMP_MODE_VAL BIT(2) +#define L0_TM_E_ILL8 0x1940 +#define L0_TM_E_ILL9 0x1944 +#define L0_TM_ILL13 0x1994 +#define L0_TM_CDR5 0x1c14 +#define L0_TM_CDR5_FPHL_FSM_ACC_CYCLES GENMASK(7, 5) +#define L0_TM_CDR5_FFL_PH0_INT_GAIN GENMASK(4, 0) +#define L0_TM_CDR16 0x1c40 =20 /* PLL Test Mode register parameters */ +#define L0_TM_PLL_DIG_33 0x2084 #define L0_TM_PLL_DIG_37 0x2094 #define L0_TM_COARSE_CODE_LIMIT 0x10 =20 /* PLL SSC step size offsets */ +#define L0_PLL_FBDIV_FRAC_3_MSB 0x2360 #define L0_PLL_SS_STEPS_0_LSB 0x2368 #define L0_PLL_SS_STEPS_1_MSB 0x236c #define L0_PLL_SS_STEP_SIZE_0_LSB 0x2370 @@ -69,6 +104,7 @@ #define L0_PLL_STATUS_READ_1 0x23e4 =20 /* SSC step size parameters */ +#define TM_FORCE_EN_FRAC BIT(6) #define STEP_SIZE_0_MASK 0xff #define STEP_SIZE_1_MASK 0xff #define STEP_SIZE_2_MASK 0xff @@ -76,6 +112,7 @@ #define STEP_SIZE_SHIFT 8 #define FORCE_STEP_SIZE 0x10 #define FORCE_STEPS 0x20 +#define TM_FORCE_EN BIT(7) #define STEPS_0_MASK 0xff #define STEPS_1_MASK 0x07 =20 @@ -84,6 +121,32 @@ #define L0_REF_CLK_LCL_SEL BIT(7) #define L0_REF_CLK_SEL_MASK 0x9f =20 +/* Built-in self-test parameters */ +#define L0_BIST_CTRL_1 0x3004 +#define L0_BIST_CTRL_2 0x3008 +#define L0_BIST_RUN_LEN_L 0x300c +#define L0_BIST_ERR_INJ_POINT_L 0x3010 +#define L0_BIST_RUNLEN_ERR_INJ_H 0x3014 +#define L0_BIST_IDLE_TIME 0x3018 +#define L0_BIST_MARKER_L 0x301c +#define L0_BIST_IDLE_CHAR_L 0x3020 +#define L0_BIST_MARKER_IDLE_H 0x3024 +#define L0_BIST_LOW_PULSE_TIME 0x3028 +#define L0_BIST_TOTAL_PULSE_TIME 0x302c +#define L0_BIST_TEST_PAT_1 0x3030 +#define L0_BIST_TEST_PAT_2 0x3034 +#define L0_BIST_TEST_PAT_3 0x3038 +#define L0_BIST_TEST_PAT_4 0x303c +#define L0_BIST_TEST_PAT_MSBS 0x3040 +#define L0_BIST_PKT_NUM 0x3044 +#define L0_BIST_FRM_IDLE_TIME 0x3048 +#define L0_BIST_PKT_CTR_L 0x304c +#define L0_BIST_PKT_CTR_H 0x3050 +#define L0_BIST_ERR_CTR_L 0x3054 +#define L0_BIST_ERR_CTR_H 0x3058 +#define L0_BIST_FILLER_OUT 0x3068 +#define L0_BIST_FORCE_MK_RST 0x306c + /* Calibration digital logic parameters */ #define L3_TM_CALIB_DIG19 0xec4c #define L3_CALIB_DONE_STATUS 0xef14 @@ -139,6 +202,9 @@ static const char *const xpsgtr_icm_str[] =3D { #define TM_CMN_RST_SET 0x2 #define TM_CMN_RST_MASK 0x3 =20 +#define LPBK_CTRL0 0x10038 +#define LPBK_CTRL1 0x1003c + /* Bus width parameters */ #define TX_PROT_BUS_WIDTH 0x10040 #define RX_PROT_BUS_WIDTH 0x10044 @@ -148,9 +214,13 @@ static const char *const xpsgtr_icm_str[] =3D { #define PROT_BUS_WIDTH_SHIFT(n) ((n) * 2) #define PROT_BUS_WIDTH_MASK(n) GENMASK((n) * 2 + 1, (n) * 2) =20 +#define UPHY_SPARE0 0X10098 + /* Number of GT lanes */ #define NUM_LANES 4 =20 +#define SIOU_ECO_0 0x1c + /* SIOU SATA control register */ #define SATA_CONTROL_OFFSET 0x0100 =20 @@ -338,6 +408,33 @@ static void xpsgtr_restore_lane_regs(struct xpsgtr_dev= *gtr_dev) gtr_dev->saved_regs[i]); } =20 +static inline void xpsgtr_write_lanes(struct xpsgtr_dev *gtr_dev, + unsigned long *lanes, u32 reg, u32 value) +{ + unsigned long lane; + + for_each_set_bit(lane, lanes, NUM_LANES) { + void __iomem *addr =3D gtr_dev->serdes + lane * PHY_REG_OFFSET + + reg; + + writel(value, addr); + } +} + +static inline void xpsgtr_clr_set_lanes(struct xpsgtr_dev *gtr_dev, + unsigned long *lanes, u32 reg, u32 clr, + u32 set) +{ + unsigned long lane; + + for_each_set_bit(lane, lanes, NUM_LANES) { + void __iomem *addr =3D gtr_dev->serdes + lane * PHY_REG_OFFSET + + reg; + + writel((readl(addr) & ~clr) | set, addr); + } +} + /* * Hardware Configuration */ @@ -351,7 +448,7 @@ static int xpsgtr_wait_pll_lock(struct phy *phy) u8 protocol =3D gtr_phy->protocol; int ret; =20 - dev_dbg(gtr_dev->dev, "Waiting for PLL lock\n"); + dev_vdbg(gtr_dev->dev, "Waiting for PLL lock\n"); =20 /* * For DP and PCIe, only the instance 0 PLL is used. Switch to that phy @@ -520,6 +617,231 @@ static void xpsgtr_bypass_scrambler_8b10b(struct xpsg= tr_phy *gtr_phy) xpsgtr_write_phy(gtr_phy, L0_TX_DIG_61, L0_TM_DISABLE_SCRAMBLE_ENCODER); } =20 +/* Enable or disable loopback */ +static void xpsgtr_phy_set_loopback(struct xpsgtr_phy *gtr_phy, bool enabl= ed) +{ + struct xpsgtr_dev *gtr_dev =3D gtr_phy->dev; + u32 reg =3D gtr_phy->lane >=3D 2 ? LPBK_CTRL1 : LPBK_CTRL0; + u32 shift =3D gtr_phy->lane & 1 ? 4 : 0; + + xpsgtr_clr_set(gtr_dev, reg, 7 << shift, (u32)enabled << shift); +} + +static void xpsgtr_phy_set_ill(struct xpsgtr_phy *gtr_phy, u32 ill, bool g= en2) +{ + u32 val =3D 4 + ill * 8; + + if (gen2) { + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL2, val & 0xff); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL12, 0x0f, + 1 << (val >> 8)); + } else { + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL1, val & 0xff); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL12, 0xf0, + (val >> 4) & 0x10); + } +} + +static bool xpsgtr_ill_calibrated(struct xpsgtr_phy *gtr_phy) +{ + u32 ill1 =3D xpsgtr_read_phy(gtr_phy, L0_TM_E_ILL1); + u32 ill2 =3D xpsgtr_read_phy(gtr_phy, L0_TM_E_ILL2); + u32 ill12 =3D xpsgtr_read_phy(gtr_phy, L0_TM_ILL12); + + dev_dbg(gtr_phy->dev->dev, "lane %u gen1 ILL was %u gen2 ILL was %u\n", + gtr_phy->lane, ill1 / 8 + (ill12 & 0x10 ? 32 : 0), + ill2 / 8 + (ill12 & 0x02 ? 32 : 0)); + return ill1 || ill2 || ill12; +} + +static void xpsgtr_init_ill(struct xpsgtr_phy *gtr_phy) +{ + struct xpsgtr_dev *gtr_dev =3D gtr_phy->dev; + struct clk *clk =3D gtr_dev->clk[gtr_phy->refclk]; + u32 ill123 =3D DIV_ROUND_CLOSEST(clk_get_rate(clk), 1000000); + + xpsgtr_clr_set_phy(gtr_phy, L0_TM_MISC2, 0, L0_TM_MISC2_ILL_CAL_BYPASS); + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL1, ill123); + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL2, ill123); + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL3, ill123); + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL7, 0xf3); + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL7, 0xf3); + xpsgtr_write_phy(gtr_phy, L0_TM_ILL8, 0xff); + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL8, 0xf3); + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL8, 0xf3); + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL9, 1); + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL9, 1); + xpsgtr_clr_set(gtr_dev, UPHY_SPARE0, BIT(5), 0); +} + +static void xpsgtr_phy_illcalib(struct xpsgtr_dev *gtr_dev, + unsigned long *lanes, bool gen2) +{ + bool last_ok[NUM_LANES] =3D { 0 }; + int pass[NUM_LANES] =3D { 0 }, altpass[NUM_LANES] =3D { 0 }; + int best[NUM_LANES] =3D { 0 }, altbest[NUM_LANES] =3D { 0 }; + unsigned long lane; + int i; + + /* Initialize the BIST */ + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0xe0, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FILLER_OUT, 1); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FORCE_MK_RST, 1); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_DIG_22, 0x20); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_2, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUN_LEN_L, 0xf4); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_INJ_POINT_L, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUNLEN_ERR_INJ_H, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_TIME, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_L, 0xfb); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_CHAR_L, 0xff); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_IDLE_H, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_LOW_PULSE_TIME, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TOTAL_PULSE_TIME, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_1, 0x4a); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_2, 0x4a); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_3, 0x4a); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_4, 0x4a); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_MSBS, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_NUM, 0x14); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FRM_IDLE_TIME, 2); + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0xe0, 0); + + for (i =3D 0; i < 64; i++) { + bool ok[NUM_LANES]; + + for_each_set_bit(lane, lanes, NUM_LANES) + xpsgtr_phy_set_ill(>r_dev->phys[lane], i, gen2); + + /* Reset lanes */ + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_7, 0x20, + 0x10); + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x00); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0x40); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0x80); + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x04); + udelay(50); + if (gen2) + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x0e); + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x06); + if (gen2) { + xpsgtr_write_lanes(gtr_dev, lanes, L0_TX_ANA_TM_3, 0x04); + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x07); + udelay(400); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TX_ANA_TM_3, 0x0c); + udelay(15); + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x0f); + udelay(100); + } + + if (xpsgtr_wait_pll_lock(gtr_dev->phys[0].phy)) { + memset(last_ok, 0, sizeof(last_ok)); + continue; + } + + udelay(50); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0xc0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0x80); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0xc0); + udelay(50); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0x80); + udelay(50); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_4, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_PLL_DIG_33, 0); + udelay(500); + + /* Do the BIST */ + for_each_set_bit(lane, lanes, NUM_LANES) { + struct xpsgtr_phy *gtr_phy =3D >r_dev->phys[lane]; + u32 packets, errors; + + xpsgtr_phy_init_bus_width(gtr_phy, PROT_BUS_WIDTH_10); + xpsgtr_phy_set_loopback(gtr_phy, true); + xpsgtr_write_phy(gtr_phy, L0_TM_DIG_22, 0x20); + xpsgtr_clr_set_phy(gtr_phy, L0_BIST_CTRL_1, 0, 1); + + udelay(200); + xpsgtr_write_phy(gtr_phy, L0_BIST_CTRL_1, 0); + packets =3D xpsgtr_read_phy(gtr_phy, L0_BIST_PKT_CTR_L); + packets |=3D xpsgtr_read_phy(gtr_phy, L0_BIST_PKT_CTR_H) << 8; + errors =3D xpsgtr_read_phy(gtr_phy, L0_BIST_ERR_CTR_L); + errors |=3D xpsgtr_read_phy(gtr_phy, L0_BIST_ERR_CTR_H) << 8; + ok[lane] =3D packets && !errors; + + dev_dbg(gtr_dev->dev, + "lane %lu ILL %d packets %10u errors %10u\n", + lane, i, packets, errors); + } + + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0); + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x00); + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0x02); + + for_each_set_bit(lane, lanes, NUM_LANES) { + pass[lane] +=3D ok[lane] && last_ok[lane]; + if (pass[lane] < 4) { + if (!ok[lane] && i > 2) { + if (altpass[lane] < pass[lane]) { + altpass[lane] =3D pass[lane]; + altbest[lane] =3D + (i - 1) - (pass[lane] + 1) / 2; + } + pass[lane] =3D 0; + } + } else if (!best[lane] && (!ok[lane] || i =3D=3D 63) && + last_ok[lane]) { + best[lane] =3D (i - 1) - (pass[lane] + 1) / 2; + } + } + + memcpy(last_ok, ok, sizeof(ok)); + } + + for_each_set_bit(lane, lanes, NUM_LANES) { + dev_dbg(gtr_dev->dev, "lane %lu ILL best %d alt best %d\n", + lane, best[lane], altbest[lane]); + + xpsgtr_phy_set_ill(>r_dev->phys[lane], + best[lane] ?: altbest[lane], gen2); + } + + /* Clean up */ + xpsgtr_clr_set_lanes(gtr_dev, lanes, L0_TM_ANA_BYP_7, 0x30, 0); + xpsgtr_write(gtr_dev, UPHY_SPARE0, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_1, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_CTRL_2, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUN_LEN_L, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_INJ_POINT_L, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_RUNLEN_ERR_INJ_H, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_TIME, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_L, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_IDLE_CHAR_L, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_MARKER_IDLE_H, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_LOW_PULSE_TIME, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TOTAL_PULSE_TIME, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_1, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_2, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_3, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_4, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_TEST_PAT_MSBS, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_NUM, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FRM_IDLE_TIME, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_CTR_L, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_PKT_CTR_H, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_CTR_L, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_ERR_CTR_H, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FILLER_OUT, 1); + xpsgtr_write_lanes(gtr_dev, lanes, L0_BIST_FORCE_MK_RST, 0); + xpsgtr_write_lanes(gtr_dev, lanes, L0_TM_DIG_22, 0); + + for_each_set_bit(lane, lanes, NUM_LANES) { + struct xpsgtr_phy *gtr_phy =3D >r_dev->phys[lane]; + + xpsgtr_phy_init_bus_width(gtr_phy, PROT_BUS_WIDTH_20); + xpsgtr_phy_set_loopback(gtr_phy, false); + } +} + static int xpsgtr_common_init(struct xpsgtr_phy *gtr_phy) { int ret; @@ -553,6 +875,37 @@ static void xpsgtr_phy_init_sata(struct xpsgtr_phy *gt= r_phy) { struct xpsgtr_dev *gtr_dev =3D gtr_phy->dev; =20 + if (!xpsgtr_ill_calibrated(gtr_phy)) { + DECLARE_BITMAP(lanes, NUM_LANES) =3D { 0 }; + + xpsgtr_init_ill(gtr_phy); + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL3, 100); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ILL11, 0xf0, 0x20); + + __set_bit(gtr_phy->lane, lanes); + xpsgtr_phy_illcalib(gtr_dev, lanes, false); + xpsgtr_phy_set_ill(gtr_phy, 7, true); + } + + /* Disable SSC */ + xpsgtr_write_phy(gtr_phy, L0_PLL_FBDIV_FRAC_3_MSB, TM_FORCE_EN_FRAC); + xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_3_MSB, 0, TM_FORCE_EN); + + /* Disable Tx deemphasis */ + xpsgtr_write_phy(gtr_phy, L0_TM_CDR5, + FIELD_PREP(L0_TM_CDR5_FPHL_FSM_ACC_CYCLES, 7) | + FIELD_PREP(L0_TM_CDR5_FFL_PH0_INT_GAIN, 6)); + xpsgtr_write_phy(gtr_phy, L0_TM_CDR16, 12); + + /* Configure equalization */ + xpsgtr_write_phy(gtr_phy, L0_TX_ANA_TM_118, + L0_TX_ANA_TM_118_FORCE_17_0); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_EQ0, 0, L0_TM_EQ0_EQ_STG2_CTRL_BYP); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_EQ1, L0_TM_EQ1_EQ_STG2_RL_PROG, + FIELD_PREP(L0_TM_EQ1_EQ_STG2_RL_PROG, 2) | + L0_TM_EQ1_EQ_STG2_PREAMP_MODE_VAL); + xpsgtr_write_phy(gtr_phy, L0_TX_ANA_TM_18, 2); /* -3.5 dB deemphasis */ + xpsgtr_bypass_scrambler_8b10b(gtr_phy); =20 writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET); @@ -565,6 +918,64 @@ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *g= tr_phy) xpsgtr_bypass_scrambler_8b10b(gtr_phy); } =20 +/* PCIe-specific initialization. */ +static int xpsgtr_phy_init_pcie(struct xpsgtr_phy *gtr_phy) +{ + struct xpsgtr_dev *gtr_dev =3D gtr_phy->dev; + DECLARE_BITMAP(lanes, NUM_LANES) =3D { 0 }; + unsigned long lane; + bool calibrated =3D false; + + xpsgtr_clr_set_phy(gtr_phy, L0_TM_AUX_0, 0, 0x20); + + for (lane =3D 0; lane < NUM_LANES; lane++) { + struct xpsgtr_phy *gtr_phy =3D >r_dev->phys[lane]; + + if (gtr_phy->protocol !=3D ICM_PROTOCOL_PCIE) + continue; + + __set_bit(lane, lanes); + calibrated =3D calibrated || xpsgtr_ill_calibrated(gtr_phy); + } + + if (calibrated) + return 0; + + /* Write default ILL config */ + for_each_set_bit(lane, lanes, NUM_LANES) { + struct xpsgtr_phy *p =3D >r_dev->phys[lane]; + + if (lane !=3D gtr_phy->lane) { + int ret =3D xpsgtr_common_init(p); + + if (ret) + return ret; + } + + xpsgtr_init_ill(p); + xpsgtr_write_phy(p, L0_TM_E_ILL3, 0); + xpsgtr_clr_set_phy(p, L0_TM_MISC2, 0, + L0_TM_MISC2_ILL_CAL_BYPASS); + } + + /* Perform the ILL calibration procedure */ + xpsgtr_phy_illcalib(gtr_dev, lanes, false); + xpsgtr_phy_illcalib(gtr_dev, lanes, true); + + /* Disable PCIe ECO */ + writel(1, gtr_dev->siou + SIOU_ECO_0); + return 0; +} + +/* USB-specific initialization. */ +static void xpsgtr_phy_init_usb(struct xpsgtr_phy *gtr_phy) +{ + xpsgtr_clr_set_phy(gtr_phy, L0_TM_AUX_0, 0, 0x20); + xpsgtr_write_phy(gtr_phy, L0_TM_IQ_ILL8, 0xf3); + xpsgtr_write_phy(gtr_phy, L0_TM_E_ILL8, 0xf3); + xpsgtr_phy_set_ill(gtr_phy, 7, false); +} + /* Configure TX de-emphasis and margining for DP. */ static void xpsgtr_phy_configure_dp(struct xpsgtr_phy *gtr_phy, unsigned i= nt pre, unsigned int voltage) @@ -710,6 +1121,10 @@ static int xpsgtr_phy_init(struct phy *phy) xpsgtr_phy_init_dp(gtr_phy); break; =20 + case ICM_PROTOCOL_PCIE: + ret =3D xpsgtr_phy_init_pcie(gtr_phy); + break; + case ICM_PROTOCOL_SATA: xpsgtr_phy_init_sata(gtr_phy); break; @@ -717,6 +1132,10 @@ static int xpsgtr_phy_init(struct phy *phy) case ICM_PROTOCOL_SGMII: xpsgtr_phy_init_sgmii(gtr_phy); break; + + case ICM_PROTOCOL_USB: + xpsgtr_phy_init_usb(gtr_phy); + break; } =20 out: --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Feb 8 05:59:09 2026 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (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 943C8199252 for ; Tue, 3 Feb 2026 00:21:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078120; cv=none; b=qoV+6YFMKWiPAkdPmcetKjVwpOrWNoNa0rxxo5dZfbKPCj6CFQsyHv9X0sZu1X+3og+r6XADW9TeNlBJZKko+AZaIZwhmzsO290IapIRGpo3rCPNIHdJeNa5iuoYeMXF8ivxsesm9eJdnGsGEuPN/iQzLGfa13xnzHuRGu6c/+8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078120; c=relaxed/simple; bh=IDh3rgzulIlQYxLxKdRaDE5kIgH6fUR26eEAf0iXhqI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=RqyEj2r7aZQVr/VdYlk8vKwt6vrUmDeE729NYa0vvNindU+kVLDL7O1BzGVOshTk6YPrewJM0YDg7hy5Q3l9avipjvieazWyfyX3HPFBuHhr+IIG5AkcubiDQMU63vzMHV2DEFvX0ZPjqH9WSDX+6+Xy51OhuPTOJB/A8lDB6Cg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=cJ2hR9uG; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="cJ2hR9uG" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770078116; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=z5LFXkBNsaVFgE+X7iTo/Y29wKqqTLybqX/8AfnQSGE=; b=cJ2hR9uGAGRArhS64fAzjFL3KYNeF222SksA8JH1aVxmvkavp+hI+5LmZxckuAV17UuUqX XyAKRZ1my27xviwXsb5wMwfM3B/3hzdzTtAN34AFDhYNRjVFI35BBUzwjG1ttooSReRjMp xOdbJjQLtcb1qlt8U/VFuTS9YhHZsyY= From: Sean Anderson To: Laurent Pinchart , Vinod Koul , linux-phy@lists.infradead.org Cc: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Lorenzo Pieralisi , Radhey Shyam Pandey , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, Neil Armstrong , Rob Herring , Thippeswamy Havalige , Manivannan Sadhasivam , Bjorn Helgaas , Sean Anderson Subject: [PATCH 5/8] phy: zynqmp: Initialize chicken bits Date: Mon, 2 Feb 2026 19:21:25 -0500 Message-Id: <20260203002128.935842-6-sean.anderson@linux.dev> In-Reply-To: <20260203002128.935842-1-sean.anderson@linux.dev> References: <20260203002128.935842-1-sean.anderson@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" These bits are all set by serdes_init(). Move them to the phy driver so we can skip serdes_init(). Signed-off-by: Sean Anderson --- drivers/phy/xilinx/phy-zynqmp.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqm= p.c index 854b0ea04648..1bdf29ba284c 100644 --- a/drivers/phy/xilinx/phy-zynqmp.c +++ b/drivers/phy/xilinx/phy-zynqmp.c @@ -54,7 +54,13 @@ /* PCS control parameters */ #define L0_TM_ANA_BYP_4 0x1010 #define L0_TM_ANA_BYP_7 0x1018 +#define L0_TM_ANA_BYP_12 0x102c +#define L0_TM_ANA_BYP_12_FORCE_UPHY_PSO_HSRXDIG BIT(6) +#define L0_TM_ANA_BYP_15 0x1038 +#define L0_TM_ANA_BYP_15_FORCE_UPHY_ENABLE_LOW_LEAKAGE BIT(6) #define L0_TM_DIG_6 0x106c +#define L0_TM_DIG_8 0x1074 +#define L0_TM_DIG_8_EYESURF BIT(4) #define L0_TM_DIG_22 0x10ac #define L0_TM_DIS_DESCRAMBLE_DECODER 0x0f #define L0_TX_DIG_61 0x00f4 @@ -82,7 +88,13 @@ #define L0_TM_EQ1_EQ_STG2_PREAMP_MODE_VAL BIT(2) #define L0_TM_E_ILL8 0x1940 #define L0_TM_E_ILL9 0x1944 +#define L0_TM_EQ11 0x1978 +#define L0_TM_EQ11_FORCE_EQ_OFFS_OFF BIT(4) #define L0_TM_ILL13 0x1994 +#define L0_TM_RST_DLY 0x19a4 +#define L0_TM_MISC3 0x19ac +#define L0_TM_MISC3_CDR_EN_FPL BIT(1) +#define L0_TM_MISC3_CDR_EN_FFL BIT(0) #define L0_TM_CDR5 0x1c14 #define L0_TM_CDR5_FPHL_FSM_ACC_CYCLES GENMASK(7, 5) #define L0_TM_CDR5_FFL_PH0_INT_GAIN GENMASK(4, 0) @@ -849,6 +861,18 @@ static int xpsgtr_common_init(struct xpsgtr_phy *gtr_p= hy) /* Enable coarse code saturation limiting logic. */ xpsgtr_write_phy(gtr_phy, L0_TM_PLL_DIG_37, L0_TM_COARSE_CODE_LIMIT); =20 + /* Miscellaneous chicken bits */ + xpsgtr_clr_set_phy(gtr_phy, L0_TM_DIG_8, 0, L0_TM_DIG_8_EYESURF); + xpsgtr_write_phy(gtr_phy, L0_TM_ILL13, 7); + xpsgtr_write_phy(gtr_phy, L0_TM_RST_DLY, 255); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ANA_BYP_15, 0, + L0_TM_ANA_BYP_15_FORCE_UPHY_ENABLE_LOW_LEAKAGE); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_ANA_BYP_12, 0, + L0_TM_ANA_BYP_12_FORCE_UPHY_PSO_HSRXDIG); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_MISC3, L0_TM_MISC3_CDR_EN_FPL | + L0_TM_MISC3_CDR_EN_FFL, 0); + xpsgtr_clr_set_phy(gtr_phy, L0_TM_EQ11, 0, L0_TM_EQ11_FORCE_EQ_OFFS_OFF); + ret =3D xpsgtr_configure_pll(gtr_phy); if (ret) return ret; --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Feb 8 05:59:09 2026 Received: from out-177.mta0.migadu.com (out-177.mta0.migadu.com [91.218.175.177]) (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 CA3F81C84CB for ; Tue, 3 Feb 2026 00:22:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078122; cv=none; b=juoO/I2TuHz4dg1c8GEf2wY5ZV0NXzlFtSmtFebkUAQFOuyKOFlfqz6ulwt4zaoR6RP6f3QTeprN5vLoxMBnSMSsD764E9gxuLwTGuhnh/e0tv+QVDwtGN3Cl5ix9T6dBy/2CmjUwCgWGFyoAy7J9wQlGhWN1g4Kfg+Apsxnads= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078122; c=relaxed/simple; bh=G/1ZJlP0fqcFtmStdil7zEuwpR1Mab+pnH0hFCakCR4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=JU8/tYguZZPQvfqUyWysqkHze9w1+rWJkSAU4dwzg9KuyHYNrF2PFYeN5LW1YQaO3V2UknFOwRe7EMplDEC1+ipwT8GlDvOwbx4RfehW4smKKMlpUftxhsUCzMn938Xrbr0He55rUVOyyHItdD2+KU8YBjRYc7VGl29J9FN3dmI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=pq/G6vrU; arc=none smtp.client-ip=91.218.175.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="pq/G6vrU" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770078119; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=laRHeOIKWBINYMn3qvuMftaW9eLnbEEB751RyH28DIA=; b=pq/G6vrUF2wQiZrQQ84P8h0KwT8wQUphdD0RU8p1qs+uyy5ypWBM86wvEfzZ/2qQYD1KH+ JzKVID4tFVYI7nFX7znWyF2/tZuQ0+6OjcHzlEby7U3VU5xEE6QK0nQB9rja125CvoSUfO UXb5Vj4iRnI8Yj4tIw5PC5Z5BJ5Bidg= From: Sean Anderson To: Laurent Pinchart , Vinod Koul , linux-phy@lists.infradead.org Cc: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Lorenzo Pieralisi , Radhey Shyam Pandey , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, Neil Armstrong , Rob Herring , Thippeswamy Havalige , Manivannan Sadhasivam , Bjorn Helgaas , Sean Anderson Subject: [PATCH 6/8] PCI: xilinx-nwl: Split phy_init from phy_power_on Date: Mon, 2 Feb 2026 19:21:26 -0500 Message-Id: <20260203002128.935842-7-sean.anderson@linux.dev> In-Reply-To: <20260203002128.935842-1-sean.anderson@linux.dev> References: <20260203002128.935842-1-sean.anderson@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" In preparation for reset support, split phy_init from phy_power_on. The former must be performed while the controller is in reset, while the latter must be performed while the controller is not in reset. Signed-off-by: Sean Anderson --- drivers/pci/controller/pcie-xilinx-nwl.c | 78 +++++++++++++----------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/control= ler/pcie-xilinx-nwl.c index 7db2c96c6cec..7cfdc21e6f40 100644 --- a/drivers/pci/controller/pcie-xilinx-nwl.c +++ b/drivers/pci/controller/pcie-xilinx-nwl.c @@ -517,56 +517,55 @@ static int nwl_pcie_init_msi_irq_domain(struct nwl_pc= ie *pcie) =20 static void nwl_pcie_phy_power_off(struct nwl_pcie *pcie, int i) { - int err =3D phy_power_off(pcie->phy[i]); + while (i--) { + int err =3D phy_power_off(pcie->phy[i]); =20 - if (err) - dev_err(pcie->dev, "could not power off phy %d (err=3D%d)\n", i, - err); + if (err) + dev_err(pcie->dev, + "could not power off phy %d (err=3D%d)\n", i, + err); + } } =20 static void nwl_pcie_phy_exit(struct nwl_pcie *pcie, int i) { - int err =3D phy_exit(pcie->phy[i]); + while (i--) { + int err =3D phy_exit(pcie->phy[i]); =20 - if (err) - dev_err(pcie->dev, "could not exit phy %d (err=3D%d)\n", i, err); + if (err) + dev_err(pcie->dev, "could not exit phy %d (err=3D%d)\n", + i, err); + } } =20 -static int nwl_pcie_phy_enable(struct nwl_pcie *pcie) +static int nwl_pcie_phy_init(struct nwl_pcie *pcie) { int i, ret; =20 - for (i =3D 0; i < ARRAY_SIZE(pcie->phy); i++) { + for (i =3D ARRAY_SIZE(pcie->phy) - 1; i >=3D 0; i--) { ret =3D phy_init(pcie->phy[i]); - if (ret) - goto err; - - ret =3D phy_power_on(pcie->phy[i]); if (ret) { nwl_pcie_phy_exit(pcie, i); - goto err; + return ret; } } =20 return 0; - -err: - while (i--) { - nwl_pcie_phy_power_off(pcie, i); - nwl_pcie_phy_exit(pcie, i); - } - - return ret; } =20 -static void nwl_pcie_phy_disable(struct nwl_pcie *pcie) +static int nwl_pcie_phy_power_on(struct nwl_pcie *pcie) { - int i; + int i, ret; =20 - for (i =3D ARRAY_SIZE(pcie->phy); i--;) { - nwl_pcie_phy_power_off(pcie, i); - nwl_pcie_phy_exit(pcie, i); + for (i =3D ARRAY_SIZE(pcie->phy) - 1; i >=3D 0; i--) { + ret =3D phy_power_on(pcie->phy[i]); + if (ret) { + nwl_pcie_phy_power_off(pcie, i); + return ret; + } } + + return 0; } =20 static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie) @@ -859,22 +858,28 @@ static int nwl_pcie_probe(struct platform_device *pde= v) return err; } =20 - err =3D nwl_pcie_phy_enable(pcie); + err =3D nwl_pcie_phy_init(pcie); if (err) { - dev_err(dev, "could not enable PHYs\n"); + dev_err(dev, "could not init PHYs\n"); goto err_clk; } =20 + err =3D nwl_pcie_phy_power_on(pcie); + if (err) { + dev_err(dev, "could not power on PHYs\n"); + goto err_phy_init; + } + err =3D nwl_pcie_bridge_init(pcie); if (err) { dev_err(dev, "HW Initialization failed\n"); - goto err_phy; + goto err_phy_power; } =20 err =3D nwl_pcie_init_irq_domain(pcie); if (err) { dev_err(dev, "Failed creating IRQ Domain\n"); - goto err_phy; + goto err_phy_power; } =20 bridge->sysdata =3D pcie; @@ -884,7 +889,7 @@ static int nwl_pcie_probe(struct platform_device *pdev) err =3D nwl_pcie_enable_msi(pcie); if (err < 0) { dev_err(dev, "failed to enable MSI support: %d\n", err); - goto err_phy; + goto err_phy_power; } } =20 @@ -892,8 +897,10 @@ static int nwl_pcie_probe(struct platform_device *pdev) if (!err) return 0; =20 -err_phy: - nwl_pcie_phy_disable(pcie); +err_phy_power: + nwl_pcie_phy_power_off(pcie, ARRAY_SIZE(pcie->phy)); +err_phy_init: + nwl_pcie_phy_exit(pcie, ARRAY_SIZE(pcie->phy)); err_clk: clk_disable_unprepare(pcie->clk); return err; @@ -903,7 +910,8 @@ static void nwl_pcie_remove(struct platform_device *pde= v) { struct nwl_pcie *pcie =3D platform_get_drvdata(pdev); =20 - nwl_pcie_phy_disable(pcie); + nwl_pcie_phy_power_off(pcie, ARRAY_SIZE(pcie->phy)); + nwl_pcie_phy_exit(pcie, ARRAY_SIZE(pcie->phy)); clk_disable_unprepare(pcie->clk); } =20 --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Feb 8 05:59:09 2026 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (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 7D3381EB9F2 for ; Tue, 3 Feb 2026 00:22:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078125; cv=none; b=O3qCKUTKhOMVe7xtcOPbBqBGkp4PNtfMYmeSkkTaYbdyTj2n0Ub94LXQakse18wIz4aDWN9VIZVjvXbu9rFhk+y9djGB3QnRQrQecH+DqG27NfeMknqW82HHW0sWxSxYWTLBdnItKUQgP9EIpvbu7l8fmZlF0i2dsZmv/H9fH34= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078125; c=relaxed/simple; bh=jPgUokafBxVCdJz4LqlA0/o5Ohi2gh9iWB161jNMzxo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Puaq8hAhjbBq25WnLeekEPY06x8BcyVzaGdE+riYNccNZrswWDcotePGd6DQTTsEDZe1tWrXdA97MmSezc4U+2XSwHIBQ2L3rhvDpA9Cci4MB7rY0BmOUL67wIO0ErM2GKo/iESycNVlHxoWxZ/VY6WEsuYgRnXkNVxzIjvIg04= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=dDj+rbSY; arc=none smtp.client-ip=91.218.175.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="dDj+rbSY" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770078121; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rkxWuhxsJXtIducWkJiHzdf+MwD5gAg0/A9IFcfPPIQ=; b=dDj+rbSY8nc7gWDxAmhfDNZJEmxRncGf5cxaNpHX/cThbWEj7uBjtrfH2zzgkYaQc+bNhP PuLWsA7uPU5zDtMD/iA4qSN0LZkBoFSON6TtnJ0GVpdUH3NkIZSGarvY/cNiYeIwZXLrT5 zxjL1E/75J0fA02Sip7WVVIhiuZuXxM= From: Sean Anderson To: Laurent Pinchart , Vinod Koul , linux-phy@lists.infradead.org Cc: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Lorenzo Pieralisi , Radhey Shyam Pandey , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, Neil Armstrong , Rob Herring , Thippeswamy Havalige , Manivannan Sadhasivam , Bjorn Helgaas , Sean Anderson Subject: [PATCH 7/8] PCI: xilinx-nwl: Reset the core during probe Date: Mon, 2 Feb 2026 19:21:27 -0500 Message-Id: <20260203002128.935842-8-sean.anderson@linux.dev> In-Reply-To: <20260203002128.935842-1-sean.anderson@linux.dev> References: <20260203002128.935842-1-sean.anderson@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" The PCIe core must be held in reset when initializing phys. Assert/deassert the appropriate resets. Resetting the core also resets the PCIe attributes to their default values, so initialize those too. For the most part the defaults are fine, but there are many attributes that default to an endpoint configuration and must be reprogrammed to function as a root device. We generally follow the controller programming sequence from UG1085. Xilinx was extremely imaginative and named all the registers ATTR_1, ATTR_2 etc. (with the fields organized in alphabetical order) so we follow the same convention. Only the fields are named, but sometimes a field is split across multiple registers. All the BARs are unused but some are repurposed as bridge registers when used as a root port. Signed-off-by: Sean Anderson --- drivers/pci/controller/pcie-xilinx-nwl.c | 177 +++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/control= ler/pcie-xilinx-nwl.c index 7cfdc21e6f40..b78fbad1efa5 100644 --- a/drivers/pci/controller/pcie-xilinx-nwl.c +++ b/drivers/pci/controller/pcie-xilinx-nwl.c @@ -22,6 +22,7 @@ #include #include #include +#include #include =20 #include "../pci.h" @@ -133,6 +134,54 @@ #define CFG_DMA_REG_BAR GENMASK(2, 0) #define CFG_PCIE_CACHE GENMASK(7, 0) =20 +#define PCIE_ATTR2_AER_CAP_PERMIT_ROOTERR_UPDATE BIT(0) + +#define PCIE_ATTR25_CPL_TIMEOUT_DISABLE_SUPPORTED BIT(9) +#define PCIE_ATTR25_INTX_IMPLEMENTED BIT(8) +#define PCIE_ATTR25_CLASS_CODE GENMASK(7, 0) + +#define PCIE_ATTR27_DEV_CAP_ENDPOINT_L1_LATENCY GENMASK(5, 3) + +#define PCIE_ATTR34_HEADER_TYPE GENMASK(7, 0) + +#define PCIE_ATTR35_LINK_CAP_DLL_ACTIVE_REPORTING BIT(15) + +#define PCIE_ATTR37_LINK_CAP_MAX_LINK_SPEED GENMASK(13, 10) +#define PCIE_ATTR37_LINK_CAP_MAX_LINK_SPEED_2_5 1 +#define PCIE_ATTR37_LINK_CAP_MAX_LINK_SPEED_5_0 2 +#define PCIE_ATTR37_LINK_CAP_BANDWIDTH_NOTIFICATION BIT(9) + +#define PCIE_ATTR50_CAP_DEVICE_PORT_TYPE GENMASK(7, 4) +#define PCIE_ATTR50_CAP_NEXTPTR GENMASK(15, 8) + +#define PCIE_ATTR53_CAP_NEXTPTR GENMASK(7, 0) + +#define PCIE_ATTR93_LL_REPLAY_TIMEOUT_EN BIT(15) + +#define PCIE_ATTR97_LTSSM_MAX_LINK_WIDTH GENMASK(11, 6) +#define PCIE_ATTR97_LINK_CAP_MAX_LINK_WIDTH GENMASK(5, 0) + +#define PCIE_ATTR100_UPSTREAM_FACING BIT(6) + +#define PCIE_ATTR101_EN_MSG_ROUTE GENMASK(15, 5) +#define PCIE_ATTR101_EN_MSG_ROUTE_PME_TURN_OFF BIT(15) +#define PCIE_ATTR101_EN_MSG_ROUTE_UNLOCK BIT(14) +#define PCIE_ATTR101_EN_MSG_ROUTE_PME_TO_ACK BIT(13) +#define PCIE_ATTR101_EN_MSG_ROUTE_PM_PME BIT(12) +#define PCIE_ATTR101_EN_MSG_ROUTE_INTD BIT(11) +#define PCIE_ATTR101_EN_MSG_ROUTE_INTC BIT(10) +#define PCIE_ATTR101_EN_MSG_ROUTE_INTB BIT(9) +#define PCIE_ATTR101_EN_MSG_ROUTE_INTA BIT(8) +#define PCIE_ATTR101_EN_MSG_ROUTE_ERR_FATAL BIT(7) +#define PCIE_ATTR101_EN_MSG_ROUTE_ERR_NONFATAL BIT(6) +#define PCIE_ATTR101_EN_MSG_ROUTE_ERR_COR BIT(5) +#define PCIE_ATTR101_DISABLE_BAR_FILTERING BIT(1) + +#define PCIE_ATTR106_VC0_TOTAL_CREDITS_NPH GENMASK(13, 7) +#define PCIE_ATTR106_VC0_TOTAL_CREDITS_CH GENMASK(6, 0) + +#define PCIE_ATTR109_VC0_TOTAL_CREDITS_PH GENMASK(6, 0) + #define INT_PCI_MSI_NR (2 * 32) =20 /* Readin the PS_LINKUP */ @@ -159,6 +208,7 @@ struct nwl_pcie { void __iomem *pcireg_base; void __iomem *ecam_base; struct phy *phy[4]; + struct reset_control *ctrl_reset; phys_addr_t phys_breg_base; /* Physical Bridge Register Base */ phys_addr_t phys_pcie_reg_base; /* Physical PCIe Controller Base */ phys_addr_t phys_ecam_base; /* Physical Configuration Base */ @@ -173,6 +223,115 @@ struct nwl_pcie { raw_spinlock_t leg_mask_lock; }; =20 +static void nwl_pcie_write_attr(struct nwl_pcie *pcie, u32 attr, u16 val) +{ + writel(val, pcie->pcireg_base + attr * 4); +} + +static void nwl_pcie_modify_attr(struct nwl_pcie *pcie, u32 attr, u16 clea= r, + u16 set) +{ + u32 val =3D readl(pcie->pcireg_base + attr * 4); + + nwl_pcie_write_attr(pcie, attr, (val & ~clear) | set); +} + +static void nwl_pcie_attr_init(struct nwl_pcie *pcie) +{ + unsigned int width; + + for (width =3D ARRAY_SIZE(pcie->phy); width; width--) + if (pcie->phy[width - 1]) + break; + + /* Set TLP header to type-1 */ + nwl_pcie_modify_attr(pcie, 34, PCIE_ATTR34_HEADER_TYPE, PCI_HEADER_TYPE_B= RIDGE); + nwl_pcie_modify_attr(pcie, 100, PCIE_ATTR100_UPSTREAM_FACING, 0); + + /* Disable BAR0/1 */ + nwl_pcie_write_attr(pcie, 7, 0); + nwl_pcie_write_attr(pcie, 8, 0); + nwl_pcie_write_attr(pcie, 9, 0); + nwl_pcie_write_attr(pcie, 10, 0); + /* Enable primary/secondary/subordinate busses, disable latency timer */ + nwl_pcie_write_attr(pcie, 11, 0xffff); + nwl_pcie_write_attr(pcie, 12, 0x00ff); + nwl_pcie_write_attr(pcie, 13, 0x0000); /* Disable I/O window */ + nwl_pcie_write_attr(pcie, 14, 0x0000); /* Enable secondary status */ + /* Enable memory window */ + nwl_pcie_write_attr(pcie, 15, (u16)PCI_MEMORY_RANGE_MASK); + nwl_pcie_write_attr(pcie, 16, (u16)PCI_MEMORY_RANGE_MASK); + /* Enable 64-bit prefetchable window */ + nwl_pcie_write_attr(pcie, 17, + (u16)PCI_PREF_RANGE_MASK | PCI_PREF_RANGE_TYPE_64); + nwl_pcie_write_attr(pcie, 18, + (u16)PCI_PREF_RANGE_MASK | PCI_PREF_RANGE_TYPE_64); + nwl_pcie_modify_attr(pcie, 101, 0, PCIE_ATTR101_DISABLE_BAR_FILTERING); + + /* Set class code to PCI_CLASS_BRIDGE_PCI_NORMAL */ + nwl_pcie_write_attr(pcie, 24, PCI_CLASS_BRIDGE_PCI_NORMAL & 0xffff); + nwl_pcie_modify_attr(pcie, 25, PCIE_ATTR25_CLASS_CODE, + PCIE_ATTR25_CPL_TIMEOUT_DISABLE_SUPPORTED | + PCI_BASE_CLASS_BRIDGE); + + /* Enable PCIe capability */ + nwl_pcie_modify_attr(pcie, 53, PCIE_ATTR53_CAP_NEXTPTR, 0x60); + nwl_pcie_modify_attr(pcie, 50, + PCIE_ATTR50_CAP_NEXTPTR | + PCIE_ATTR50_CAP_DEVICE_PORT_TYPE, + FIELD_PREP(PCIE_ATTR50_CAP_DEVICE_PORT_TYPE, + PCI_EXP_TYPE_ROOT_PORT)); + + /* Disable MSI(-X) capability */ + nwl_pcie_write_attr(pcie, 41, 0); + nwl_pcie_write_attr(pcie, 43, 0); + nwl_pcie_write_attr(pcie, 44, 0); + nwl_pcie_write_attr(pcie, 45, 0); + nwl_pcie_write_attr(pcie, 46, 0); + nwl_pcie_write_attr(pcie, 48, 0); + + /* Disable DSN capability */ + nwl_pcie_write_attr(pcie, 31, 0); + nwl_pcie_write_attr(pcie, 82, PCI_CFG_SPACE_SIZE); + + /* Enable AER */ + nwl_pcie_modify_attr(pcie, 2, 0, + PCIE_ATTR2_AER_CAP_PERMIT_ROOTERR_UPDATE); + + /* Disable L1 latency for root port */ + nwl_pcie_modify_attr(pcie, 27, + PCIE_ATTR27_DEV_CAP_ENDPOINT_L1_LATENCY, 0); + + /* Enable bandwidth notification */ + nwl_pcie_modify_attr(pcie, 37, 0, + PCIE_ATTR37_LINK_CAP_BANDWIDTH_NOTIFICATION); + + /* Set max link width */ + nwl_pcie_write_attr(pcie, 97, + FIELD_PREP(PCIE_ATTR97_LTSSM_MAX_LINK_WIDTH, width) | + FIELD_PREP(PCIE_ATTR97_LINK_CAP_MAX_LINK_WIDTH, width)); + + /* Route misc. TLPs to controller */ + nwl_pcie_modify_attr(pcie, 101, PCIE_ATTR101_EN_MSG_ROUTE, + PCIE_ATTR101_EN_MSG_ROUTE_INTA | + PCIE_ATTR101_EN_MSG_ROUTE_INTB | + PCIE_ATTR101_EN_MSG_ROUTE_INTC | + PCIE_ATTR101_EN_MSG_ROUTE_INTD | + PCIE_ATTR101_EN_MSG_ROUTE_PM_PME | + PCIE_ATTR101_EN_MSG_ROUTE_PME_TO_ACK | + PCIE_ATTR101_EN_MSG_ROUTE_UNLOCK | + PCIE_ATTR101_EN_MSG_ROUTE_PME_TURN_OFF); + + /* Initialize completion credits */ + nwl_pcie_write_attr(pcie, 105, 205); /* CD */ + nwl_pcie_write_attr(pcie, 106, + FIELD_PREP(PCIE_ATTR106_VC0_TOTAL_CREDITS_NPH, 12) | + FIELD_PREP(PCIE_ATTR106_VC0_TOTAL_CREDITS_CH, 36)); + nwl_pcie_write_attr(pcie, 107, 24); /* NPD */ + nwl_pcie_write_attr(pcie, 108, 181); /* PD */ + nwl_pcie_modify_attr(pcie, 109, PCIE_ATTR109_VC0_TOTAL_CREDITS_PH, 32); +} + static inline u32 nwl_bridge_readl(struct nwl_pcie *pcie, u32 off) { return readl(pcie->breg_base + off); @@ -806,6 +965,9 @@ static int nwl_pcie_parse_dt(struct nwl_pcie *pcie, irq_set_chained_handler_and_data(pcie->irq_intx, nwl_pcie_leg_handler, pcie); =20 + pcie->ctrl_reset =3D devm_reset_control_get_optional(dev, "ctrl"); + if (IS_ERR(pcie->ctrl_reset)) + return PTR_ERR(pcie->ctrl_reset); =20 for (i =3D 0; i < ARRAY_SIZE(pcie->phy); i++) { pcie->phy[i] =3D devm_of_phy_get_by_index(dev, dev->of_node, i); @@ -852,6 +1014,12 @@ static int nwl_pcie_probe(struct platform_device *pde= v) if (IS_ERR(pcie->clk)) return PTR_ERR(pcie->clk); =20 + err =3D reset_control_assert(pcie->ctrl_reset); + if (err) { + dev_err(dev, "could not enter reset\n"); + return err; + } + err =3D clk_prepare_enable(pcie->clk); if (err) { dev_err(dev, "can't enable PCIe ref clock\n"); @@ -864,6 +1032,15 @@ static int nwl_pcie_probe(struct platform_device *pde= v) goto err_clk; } =20 + if (pcie->ctrl_reset) + nwl_pcie_attr_init(pcie); + + err =3D reset_control_deassert(pcie->ctrl_reset); + if (err) { + dev_err(dev, "could not release from reset\n"); + goto err_phy_init; + } + err =3D nwl_pcie_phy_power_on(pcie); if (err) { dev_err(dev, "could not power on PHYs\n"); --=20 2.35.1.1320.gc452695387.dirty From nobody Sun Feb 8 05:59:09 2026 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (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 AFA681C84CB for ; Tue, 3 Feb 2026 00:22:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078127; cv=none; b=Dk9ejJNeb4J1ldaye0nFTWId1H4VkXRnMGNlCpKh5i+1JjJDaUEsxLObGX7t3MgAYwuv3Kak65VhOB+nDCTYWiPaJwSckzq3LTqbqaL6qpBFTqGLjVlDZwUrBBBvhYzWbSQ3MAdONsVvA5tLe8QViJcns7gjMqaFV+o1sy5/tNc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770078127; c=relaxed/simple; bh=HzuTMG6951tSYJCEaxJHqJek8qQ28BkOhuT5tQd7CoE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=KnSWHY9mxr8J3LHaQS3cf0yc0fRL5PoGm31d5EidzlEE2f+XJAXZOAhzub24LmXICUMYdIgRz0ZTTrh5KH/W6zR245+o576JZu/kL8/KsJN4tHsDnJ9T2DxjHeBxvYLLUzixgXLoYhm3HzcQDfPfVZVuncozgva5yt/wxhi1Vi0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=BKB6Y3pI; arc=none smtp.client-ip=91.218.175.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="BKB6Y3pI" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770078123; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xEDks71jPWIaYxTqElZUBzlKtd2fk7erRCnRdd5d4ug=; b=BKB6Y3pIE2fBGnuvhOOin7POuW77yEcRZpaJCYRLs0TbIu8wNx6XztyKKtkdrc7HGFjgqw FQiYsBC8g/AhJRteLaH5mEl7Kto4SI97SbUbkdjAmq/c9Y5vjww2OojVXZuelmsk0pEGsJ d7fOcDAsv8dE2AB1yRMZ10Vdb/9iyR8= From: Sean Anderson To: Laurent Pinchart , Vinod Koul , linux-phy@lists.infradead.org Cc: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , Lorenzo Pieralisi , Radhey Shyam Pandey , linux-kernel@vger.kernel.org, Michal Simek , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, Neil Armstrong , Rob Herring , Thippeswamy Havalige , Manivannan Sadhasivam , Bjorn Helgaas , Sean Anderson Subject: [PATCH 8/8] arm64: zynqmp: Add PCIe resets Date: Mon, 2 Feb 2026 19:21:28 -0500 Message-Id: <20260203002128.935842-9-sean.anderson@linux.dev> In-Reply-To: <20260203002128.935842-1-sean.anderson@linux.dev> References: <20260203002128.935842-1-sean.anderson@linux.dev> 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 X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Add PCIe reset bindings for the ZynqMP. Signed-off-by: Sean Anderson --- arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/x= ilinx/zynqmp.dtsi index 938b014ca923..178b4c3a7ba4 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi +++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi @@ -969,6 +969,10 @@ pcie: pcie@fd0e0000 { <0x0 0x0 0x0 0x4 &pcie_intc 0x4>; /* iommus =3D <&smmu 0x4d0>; */ power-domains =3D <&zynqmp_firmware PD_PCIE>; + resets =3D <&zynqmp_reset ZYNQMP_RESET_PCIE_CFG>, + <&zynqmp_reset ZYNQMP_RESET_PCIE_BRIDGE>, + <&zynqmp_reset ZYNQMP_RESET_PCIE_CTRL>; + reset-names =3D "cfg", "bridge", "ctrl"; pcie_intc: legacy-interrupt-controller { interrupt-controller; #address-cells =3D <0>; --=20 2.35.1.1320.gc452695387.dirty