* Re: [PATCH 2/2] phy: mediatek: Add support for PCI-Express Gen4 S-PHY
From: sashiko-bot @ 2026-07-16 15:24 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: devicetree, olteanv, linux-phy, neil.armstrong, conor+dt, robh,
vkoul
In-Reply-To: <20260716151333.77254-3-angelogioacchino.delregno@collabora.com>
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [High] The 4-bit bitfields in `struct mtk_pcie_sphy_imp_sel` will silently truncate 5-bit TX impedance calibration values.
- [High] Probe fails when CONFIG_NVMEM is disabled due to unhandled -EOPNOTSUPP.
- [Medium] Unconditional read of lane 1 calibration data needlessly disables calibration entirely for 1-lane PHYs.
- [Medium] Valid calibration data containing the value '0' incorrectly aborts the entire calibration process.
- [Medium] PHY provider is registered before Runtime PM is enabled, creating a probe race condition.
- [Low] Expected missing calibration data and probe deferrals trigger unconditional dev_err() logs.
- [Low] Missing `#include <linux/pm_runtime.h>` while using `devm_pm_runtime_enable()`.
--
--- Patch [2]: [PATCH 2/2] phy: mediatek: Add support for PCI-Express Gen4 S-PHY ---
commit 7cbdba90e32bbdc889bb04306231fd5de6141303
Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
phy: mediatek: Add support for PCI-Express Gen4 S-PHY
Add support for the PCI-Express Gen4 S-PHY found in the latest
MediaTek SoCs, including MT8196, MT8894 and similar.
> diff --git a/drivers/phy/mediatek/phy-mtk-pcie-sphy.c b/drivers/phy/mediatek/phy-mtk-pcie-sphy.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-pcie-sphy.c
> @@ -0,0 +1,560 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022 MediaTek Inc.
> + * Copyright (c) 2026 Collabora Ltd.
> + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-consumer.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
[Severity: Low]
Does this need linux/pm_runtime.h included since devm_pm_runtime_enable()
is used later in the file?
[ ... ]
> +/**
> + * struct mtk_pcie_sphy_imp_sel - Impedance Selection parameters
> + * @pmos: Impedance selection for P-Channel MOSFET
> + * @nmos: Impedance selection for N-Channel MOSFET
> + */
> +struct mtk_pcie_sphy_imp_sel {
> + u8 pmos : 4;
> + u8 nmos : 4;
> +};
[Severity: High]
Can this truncate calibration values? The eFuse data read for tx-lanes-pmos
and tx-lanes-nmos uses FIELD_MAX(RG_XTP_LN_TX_IMPSEL_PMOS), which is
GENMASK(4, 0), allowing 5-bit values up to 31. Will values greater than 15
be silently truncated here?
[ ... ]
> +static int mtk_pcie_sphy_get_one_cal_para(struct device *dev, const char *name, u8 max_val)
> +{
> + u16 buf;
> + u8 tmp;
> + int ret;
> +
> + /*
> + * All of the calibrations are always max 8 bits long, but some may
> + * be split between two different 8-bits cells: handle this corner
> + * case by retrying reading as u16.
> + */
> + ret = nvmem_cell_read_u8(dev, name, &tmp);
> + if (ret == 0)
> + buf = tmp;
> + else
> + ret = nvmem_cell_read_u16(dev, name, &buf);
> +
> + if (ret) {
> + dev_err(dev, "Cannot get calibration data for %s: %d\n", name, ret);
> + return ret;
> + };
[Severity: Low]
Does this unconditionally log an error for expected missing cells (-ENOENT)
or during probe deferral (-EPROBE_DEFER)?
> +
> + if (buf == 0) {
> + dev_warn(dev, "No calibration for %s. Using defaults\n", name);
> + return -ENOENT;
> + }
[Severity: Medium]
Is 0 an invalid calibration value?
Later code checks if the calibration version is <= 4, which implies version
0 could exist. If a valid cell contains 0, will this mistakenly abort the
entire calibration process?
[ ... ]
> +static int mtk_pcie_sphy_get_calibration_data(struct mtk_pcie_sphy *pcie_sphy)
> +{
[ ... ]
> + ret = mtk_pcie_sphy_get_one_cal_para(dev, "tx-ln0-rswn",
> + FIELD_MAX(RG_XTP_LN_TX_RSWN_IMPSEL));
> + if (ret < 0)
> + goto end;
> + cal->tx_rswn_impsel[0] = ret;
> +
> + ret = mtk_pcie_sphy_get_one_cal_para(dev, "tx-ln1-rswn",
> + FIELD_MAX(RG_XTP_LN_TX_RSWN_IMPSEL));
> + if (ret < 0)
> + goto end;
> + cal->tx_rswn_impsel[1] = ret;
[Severity: Medium]
Will this break calibration on 1-lane PHYs?
If num_lanes is 1, the device tree might naturally omit lane 1 data. Would
the read for tx-ln1-rswn then return -ENOENT and cause all valid lane 0
calibration to be discarded?
[ ... ]
> +end:
> + if (ret < 0) {
> + /*
> + * If any of the calibration values is missing, or if there is
> + * no calibration at all in the eFuses, this is not a problem,
> + * as the PHY doesn't require one to actually work.
> + */
> + if (ret == -ENOENT) {
> + cal->supported = false;
> + return 0;
> + }
> + return ret;
> + };
[Severity: High]
If the kernel is compiled without CONFIG_NVMEM, nvmem_cell_read_u8 returns
-EOPNOTSUPP. Does this cause the entire PHY probe to fail on systems without
NVMEM, even though calibration is optional?
[ ... ]
> +static int mtk_pcie_sphy_probe(struct platform_device *pdev)
> +{
[ ... ]
> + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> + if (IS_ERR(provider))
> + return dev_err_probe(dev, PTR_ERR(provider),
> + "Could not register PCI-Express S-PHY\n");
> +
> + ret = devm_pm_runtime_enable(dev);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
[Severity: Medium]
Could registering the PHY provider before enabling Runtime PM lead to a race
condition?
If a consumer driver probes concurrently and immediately calls phy_init(),
could it try to interact with the device before devm_pm_runtime_enable() has
completed?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260716151333.77254-1-angelogioacchino.delregno@collabora.com?part=2
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: phy: Document MT8196 MediaTek PCI-Express Gen4 S-PHY
From: sashiko-bot @ 2026-07-16 15:21 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: devicetree, olteanv, neil.armstrong, robh, conor+dt, linux-phy,
vkoul
In-Reply-To: <20260716151333.77254-2-angelogioacchino.delregno@collabora.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Missing upper bound (`maxItems`) for the `reg` property array.
--
--- Patch [1]: [PATCH 1/2] dt-bindings: phy: Document MT8196 MediaTek PCI-Express Gen4 S-PHY ---
commit 46cb0bc5744a1aaeece570f9d383cc948bbcab79
Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
dt-bindings: phy: Document MT8196 MediaTek PCI-Express Gen4 S-PHY
This commit introduces the device tree binding documentation for the
PCI-Express Gen4 S-PHY found in newer MediaTek SoCs like the MT8196. It
details the required properties, nvmem cells, and power domains for this
hardware.
> diff --git a/Documentation/devicetree/bindings/phy/mediatek,mt8196-pcie-sphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,mt8196-pcie-sphy.yaml
> new file mode 100644
> index 0000000000000..2b61882c402c2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/mediatek,mt8196-pcie-sphy.yaml
[ ... ]
> +properties:
> + compatible:
> + const: mediatek,mt8196-pcie-sphy
> +
> + reg:
> + minItems: 2
> +
> + reg-names:
> + items:
> + - const: sif
> + - const: ckm
[Severity: Low]
Is an upper bound missing for the reg property array here?
The schema defines minItems: 2 but omits maxItems. Since reg-names explicitly
defines exactly two items, should reg include maxItems: 2 as well to fully
bound the array and prevent potential dt_binding_check validation warnings?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260716151333.77254-1-angelogioacchino.delregno@collabora.com?part=1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH 2/2] phy: mediatek: Add support for PCI-Express Gen4 S-PHY
From: AngeloGioacchino Del Regno @ 2026-07-16 15:13 UTC (permalink / raw)
To: chunfeng.yun
Cc: vkoul, neil.armstrong, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-arm-kernel, linux-mediatek,
linux-phy, devicetree, linux-kernel, kernel
In-Reply-To: <20260716151333.77254-1-angelogioacchino.delregno@collabora.com>
Add support for the PCI-Express Gen4 S-PHY found in the latest
MediaTek SoCs, including MT8196, MT8894 and similar.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/phy/mediatek/Kconfig | 9 +
drivers/phy/mediatek/Makefile | 1 +
drivers/phy/mediatek/phy-mtk-pcie-sphy.c | 560 +++++++++++++++++++++++
3 files changed, 570 insertions(+)
create mode 100644 drivers/phy/mediatek/phy-mtk-pcie-sphy.c
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index ba6461350951..77236f3084c8 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -13,6 +13,15 @@ config PHY_MTK_PCIE
callback for PCIe GEN3 port, it supports software efuse
initialization.
+config PHY_MTK_PCIE_SPHY
+ tristate "MediaTek PCIe S-PHY Driver"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ help
+ Say 'Y' here to add support for MediaTek PCIe S-PHY driver for
+ PCI-Express Gen4 controllers as found in MT6991, MT8196 and others.
+
config PHY_MTK_XFI_TPHY
tristate "MediaTek 10GE SerDes XFI T-PHY driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
index ed0da708759b..7e984c7cfea3 100644
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_PHY_MTK_DP) += phy-mtk-dp.o
obj-$(CONFIG_PHY_MTK_PCIE) += phy-mtk-pcie.o
+obj-$(CONFIG_PHY_MTK_PCIE_SPHY) += phy-mtk-pcie-sphy.o
obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o
obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o
obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o
diff --git a/drivers/phy/mediatek/phy-mtk-pcie-sphy.c b/drivers/phy/mediatek/phy-mtk-pcie-sphy.c
new file mode 100644
index 000000000000..c794505060a8
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-pcie-sphy.c
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Copyright (c) 2026 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "phy-mtk-io.h"
+
+/* PHY System Interface (SIF) registers */
+#define PEXTP_DIG_GLB_TOP 0x20
+# define RG_XTP_BYPASS_PIPE_RST_RC BIT(17)
+#define PEXTP_DIG_GLB_CKBG0 0x30
+# define RG_XTP_CKBG_XTAL_STABLE_TIME_SEL GENMASK(25, 16)
+#define PEXTP_DIG_GLB_TPLL_CTL0 0x38
+# define RG_XTP_TPLL_SET_STABLE_TIME_SEL GENMASK(7, 2)
+# define RG_XTP_TPLL_PWE_ON_STABLE_TIME_SEL GENMASK(9, 8)
+#define PEXTP_DIG_GLB_CLKREQ_CTL 0x50
+# define RG_XTP_CKM_EN_L1S0 BIT(13)
+# define RG_XTP_CKM_EN_L1S1 BIT(14)
+#define PEXTP_DIG_GLB_TPLL_CTL2 0xf4
+# define RG_XTP_TPLL_ISO_EN_STABLE_TIME_SEL GENMASK(13, 12)
+
+/* PHY System Interface Digital registers */
+#define PEXTP_DIG_LN_TRX_PIPE_IF_17 0x30e8
+# define RG_XTP_LN_RX_LF_CTLE_CSEL_GEN4 GENMASK(14, 12)
+#define PEXTP_DIG_LN_RX_F0 0x50f0
+# define RG_XTP_LN_RX_GEN1_CTLE1_CSEL GENMASK(3, 0)
+# define RG_XTP_LN_RX_GEN2_CTLE1_CSEL GENMASK(7, 4)
+# define RG_XTP_LN_RX_GEN3_CTLE1_CSEL GENMASK(11, 8)
+# define RG_XTP_LN_RX_GEN4_CTLE1_CSEL GENMASK(15, 12)
+#define PEXTP_DIG_LN_RX2_AEQ_EDGE_0 0x6004
+# define RG_XTP_LN_RX_AEQ_EGEQ_RATIO_GEN3 GENMASK(21, 16)
+# define RG_XTP_LN_RX_AEQ_EGEQ_RATIO_GEN4 GENMASK(29, 24)
+# define AEQ_EGEQ_RATIO_GEN3_TO_22 0x16
+# define AEQ_EGEQ_RATIO_GEN4_TO_22 0x16
+
+/* PHY System Interface Analog registers */
+#define PEXTP_ANA_GLB_TPLL1_RSVD 0x902c
+# define RG_XTP_GLB_TPLL1_P_PATH_GAIN GENMASK(2, 0)
+#define PEXTP_ANA_GLB_BIAS_0 0x9060
+# define RG_XTP_GLB_BIAS_INTR_CTRL GENMASK(5, 0)
+#define PEXTP_ANA_GLB_BIAS_1 0x90c0
+# define RG_XTP_GLB_BIAS_V2V_VTRIM GENMASK(9, 6)
+#define PEXTP_ANA_LN_TRX_0C 0xa00c
+# define RG_XTP_LN_TX_RSWN_IMPSEL GENMASK(20, 16)
+#define PEXTP_ANA_LN_TRX_34 0xa034
+# define RG_XTP_LN_RX_FE BIT(15)
+#define PEXTP_ANA_LN_TRX_6C 0xa06c
+# define RG_XTP_LN_RX_AEQ_CTLE_ERR_TYPE GENMASK(14, 13)
+# define AEQ_CTLE_SEARCH_ERR_TYPE_H1P5 0
+# define AEQ_CTLE_SEARCH_ERR_TYPE_H1P5_H2P5 1
+# define AEQ_CTLE_SEARCH_ERR_TYPE_P1P5_H2P5_H3P5 2
+#define PEXTP_ANA_LN_TRX_A0 0xa0a0
+# define RG_XTP_LN_TX_IMPSEL_PMOS GENMASK(4, 0)
+# define RG_XTP_LN_TX_IMPSEL_NMOS GENMASK(11, 7)
+# define RG_XTP_LN_RX_IMPSEL GENMASK(15, 12)
+#define PEXTP_ANA_LN_TRX_A8 0xa0a8
+# define RG_XTP_LN_RX_LEQ_RL_CTLE_CAL GENMASK(6, 2)
+# define RG_XTP_LN_RX_LEQ_RL_VGA_CAL GENMASK(11, 7)
+# define RG_XTP_LN_RX_LEQ_RL_DFE_CAL GENMASK(23, 19)
+#define PEXTP_DIG_LN_TX_LC_TABLE_RSWN_4 0xb004
+#define PEXTP_DIG_LN_TX_LC_TABLE_RSWN_8 0xb008
+#define PEXTP_DIG_LN_TX_LC_TABLE_RSWN_C 0xb00c
+#define PEXTP_DIG_LN_TX_LC_TABLE_RSWN_10 0xb010
+#define PEXTP_DIG_LN_TX_LC_TABLE_RSWN_14 0xb014
+#define PEXTP_DIG_LN_TX_LC_TABLE_RSWN_18 0xb018
+# define RG_XTP_LN_TX_LC_PRESET_MGx_Px_CM1 GENMASK(5, 0)
+# define RG_XTP_LN_TX_LC_PRESET_MGx_Px_C0 GENMASK(13, 8)
+# define RG_XTP_LN_TX_LC_PRESET_MGx_Px_CP1 GENMASK(21, 16)
+#define PEXTP_REG_LANE(x) ((x) * 0x100)
+
+/* PHY Clock Management (CKM) registers */
+#define XTP_CKM_FORCE_6 0x38
+# define RG_CKM_BIAS_WAIT_PRD_US GENMASK(21, 16)
+#define XTP_CKM_REG_SPLL_FBKDIV_5 0xd4
+# define RG_CKM_CKTX_IMPSEL_PMOS GENMASK(19, 16)
+# define RG_CKM_CKTX_IMPSEL_NMOS GENMASK(23, 20)
+# define RG_CKM_CKTX_IMPSEL_SW GENMASK(27, 24)
+
+/* Calibration data from eFuses */
+#define MTK_PCIE_SPHY_CALIBRATION_MAX_DATA_LANES 2
+#define MTK_PCIE_SPHY_CALIBRATION_LAST_QUIRK_VER 4
+
+/**
+ * struct mtk_pcie_sphy_imp_sel - Impedance Selection parameters
+ * @pmos: Impedance selection for P-Channel MOSFET
+ * @nmos: Impedance selection for N-Channel MOSFET
+ */
+struct mtk_pcie_sphy_imp_sel {
+ u8 pmos : 4;
+ u8 nmos : 4;
+};
+
+/**
+ * struct mtk_pcie_sphy_efuse - eFuse calibration data for S-PHY
+ * @int_r_ctrl: Internal resistor selection of TX Bias Current
+ * @xtp_vtrim: XTP Bias V2V voltage calibration
+ * @cktx_impsel: SPLL CKTX Impedance Selection (P and N MOSFET)
+ * @cktx_r_mid: SPLL CKTX Intermediate Transition Impedance (Rmid)
+ * @rx_leq_rl_ctle: RX Front-End Return Loss Continuous Time Linear Equalization value
+ * @rx_leq_rl_vga: RX Front-End Return Loss Variable Gain Amplifier value
+ * @rx_leq_rl_dfe: RX Front-End Return Loss Decision Feedback Equalization value
+ * @rx_impsel: RX Impedance Selection
+ * @tx_impsel: TX Impedance Selection (P and N MOSFET)
+ * @tx_rswn_impsel: TX RSWn (Switch Resistance) impedance selection
+ * @supported: eFuse calibration data is supported
+ */
+struct mtk_pcie_sphy_efuse {
+ u8 int_r_ctrl;
+ u8 xtp_vtrim;
+ struct mtk_pcie_sphy_imp_sel cktx_impsel;
+ u8 cktx_r_mid;
+ u8 rx_leq_rl_ctle;
+ u8 rx_leq_rl_vga;
+ u8 rx_leq_rl_dfe;
+ u8 rx_impsel;
+ struct mtk_pcie_sphy_imp_sel tx_impsel;
+ u8 tx_rswn_impsel[MTK_PCIE_SPHY_CALIBRATION_MAX_DATA_LANES];
+ bool supported;
+};
+
+/**
+ * struct mtk_pcie_sphy - PCI-Express S-PHY driver main structure
+ * @dev: Pointer to device structure
+ * @phy: Pointer to generic phy structure
+ * @sif_base: IO mapped register base address of system interface
+ * @ckm_base: IO mapped register base address of clock management interface
+ * @num_lanes: Number of lanes
+ * @calibration: eFuse calibration data for S-PHY
+ */
+struct mtk_pcie_sphy {
+ struct device *dev;
+ struct phy *phy;
+ void __iomem *sif_base;
+ void __iomem *ckm_base;
+ u8 num_lanes;
+ struct mtk_pcie_sphy_efuse calibration;
+};
+
+static void mtk_pcie_sphy_apply_calibration(struct mtk_pcie_sphy *pcie_sphy)
+{
+ struct mtk_pcie_sphy_efuse *cal = &pcie_sphy->calibration;
+ int i;
+
+ mtk_phy_update_field(pcie_sphy->sif_base + PEXTP_ANA_GLB_BIAS_0,
+ RG_XTP_GLB_BIAS_INTR_CTRL, cal->int_r_ctrl);
+
+ mtk_phy_update_field(pcie_sphy->sif_base + PEXTP_ANA_GLB_BIAS_1,
+ RG_XTP_GLB_BIAS_V2V_VTRIM, cal->xtp_vtrim);
+
+ mtk_phy_update_field(pcie_sphy->ckm_base + XTP_CKM_REG_SPLL_FBKDIV_5,
+ RG_CKM_CKTX_IMPSEL_PMOS, cal->cktx_impsel.pmos);
+
+ mtk_phy_update_field(pcie_sphy->ckm_base + XTP_CKM_REG_SPLL_FBKDIV_5,
+ RG_CKM_CKTX_IMPSEL_NMOS, cal->cktx_impsel.nmos);
+
+ mtk_phy_update_field(pcie_sphy->ckm_base + XTP_CKM_REG_SPLL_FBKDIV_5,
+ RG_CKM_CKTX_IMPSEL_SW, cal->cktx_r_mid);
+
+ for (i = 0; i < pcie_sphy->num_lanes; i++) {
+ void __iomem *sif_lane_base = pcie_sphy->sif_base + PEXTP_REG_LANE(i);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_0C,
+ RG_XTP_LN_TX_RSWN_IMPSEL, cal->tx_rswn_impsel[i]);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_A8,
+ RG_XTP_LN_RX_LEQ_RL_CTLE_CAL, cal->rx_leq_rl_ctle);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_A8,
+ RG_XTP_LN_RX_LEQ_RL_VGA_CAL, cal->rx_leq_rl_vga);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_A8,
+ RG_XTP_LN_RX_LEQ_RL_DFE_CAL, cal->rx_leq_rl_dfe);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_A0,
+ RG_XTP_LN_RX_IMPSEL, cal->rx_impsel);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_A0,
+ RG_XTP_LN_TX_IMPSEL_PMOS, cal->tx_impsel.pmos);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_A0,
+ RG_XTP_LN_TX_IMPSEL_NMOS, cal->tx_impsel.nmos);
+ }
+}
+
+/**
+ * mtk_pcie_sphy_init() - Initialize the PCI-Express S-PHY
+ * @phy: the phy to be initialized
+ *
+ * The hardware settings will be reset during suspend, it should be
+ * reinitialized when the consumer calls phy_init() again on resume.
+ */
+static int mtk_pcie_sphy_init(struct phy *phy)
+{
+ struct mtk_pcie_sphy *pcie_sphy = phy_get_drvdata(phy);
+ struct mtk_pcie_sphy_imp_sel tx_impsel;
+ int i;
+
+ /* Set CKM Bias wait time to 4 microseconds */
+ mtk_phy_update_field(pcie_sphy->ckm_base + XTP_CKM_FORCE_6,
+ RG_CKM_BIAS_WAIT_PRD_US, 4);
+
+ /* TPLL needs 63 ref_ck ticks to stabilize when setting frequency */
+ mtk_phy_update_field(pcie_sphy->sif_base + PEXTP_DIG_GLB_TPLL_CTL0,
+ RG_XTP_TPLL_SET_STABLE_TIME_SEL, 63);
+
+ /* TPLL needs 3 ref_ck ticks to stabilize when powering on... */
+ mtk_phy_update_field(pcie_sphy->sif_base + PEXTP_DIG_GLB_TPLL_CTL0,
+ RG_XTP_TPLL_PWE_ON_STABLE_TIME_SEL, 3);
+
+ /* ...and the same goes for setting isolation */
+ mtk_phy_update_field(pcie_sphy->sif_base + PEXTP_DIG_GLB_TPLL_CTL2,
+ RG_XTP_TPLL_ISO_EN_STABLE_TIME_SEL, 3);
+
+ /* XTAL doesn't need any stabilization time */
+ mtk_phy_update_field(pcie_sphy->sif_base + PEXTP_DIG_GLB_CKBG0,
+ RG_XTP_CKBG_XTAL_STABLE_TIME_SEL, 0);
+
+ /* Keep pextp_ckm enabled when in L1SS_L1S1 state */
+ mtk_phy_clear_bits(pcie_sphy->sif_base + PEXTP_DIG_GLB_CLKREQ_CTL, RG_XTP_CKM_EN_L1S1);
+
+ /* Set PIPE to reset TPLL */
+ mtk_phy_clear_bits(pcie_sphy->sif_base + PEXTP_DIG_GLB_TOP, RG_XTP_BYPASS_PIPE_RST_RC);
+
+ /* Set TPLL P-Path gain compensation to 1 */
+ mtk_phy_update_field(pcie_sphy->sif_base + PEXTP_ANA_GLB_TPLL1_RSVD,
+ RG_XTP_GLB_TPLL1_P_PATH_GAIN, 1);
+
+ for (i = 0; i < pcie_sphy->num_lanes; i++) {
+ void __iomem *sif_lane_base = pcie_sphy->sif_base + PEXTP_REG_LANE(i);
+
+ /* Set RX Lane AEQ CTRL-E Search Error type to h1.5 + h2.5 */
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_6C,
+ RG_XTP_LN_RX_AEQ_CTLE_ERR_TYPE,
+ AEQ_CTLE_SEARCH_ERR_TYPE_H1P5_H2P5);
+
+ mtk_phy_set_bits(sif_lane_base + PEXTP_ANA_LN_TRX_34, RG_XTP_LN_RX_FE);
+
+ /* TRX: Select CTLE1 for RX Lane AutoEQ CTRL-E Setting on Gen4 */
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TRX_PIPE_IF_17,
+ RG_XTP_LN_RX_LF_CTLE_CSEL_GEN4, 1);
+
+ /* Set RX Lane AutoEQ CTRL-E for PCI-Express Gen1 to Gen 4 */
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_RX_F0,
+ RG_XTP_LN_RX_GEN1_CTLE1_CSEL, 13);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_RX_F0,
+ RG_XTP_LN_RX_GEN2_CTLE1_CSEL, 13);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_RX_F0,
+ RG_XTP_LN_RX_GEN3_CTLE1_CSEL, 13);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_RX_F0,
+ RG_XTP_LN_RX_GEN4_CTLE1_CSEL, 0);
+
+ /* Set RX Lane AutoEQ's Edge EQ Ratio to 22 * 0.0625 = 1.375 */
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_RX2_AEQ_EDGE_0,
+ RG_XTP_LN_RX_AEQ_EGEQ_RATIO_GEN3, 22);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_RX2_AEQ_EDGE_0,
+ RG_XTP_LN_RX_AEQ_EGEQ_RATIO_GEN4, 22);
+
+ /* Setup Digital lane TX Link Characteristics Table */
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_4,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_C0, 10);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_4,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_CP1, 2);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_8,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_C0, 11);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_8,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_CP1, 1);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_C,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_C0, 12);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_10,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_C0, 13);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_10,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_CM1, 1);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_14,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_C0, 11);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_14,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_CM1, 1);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_18,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_C0, 10);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_DIG_LN_TX_LC_TABLE_RSWN_18,
+ RG_XTP_LN_TX_LC_PRESET_MGx_Px_CM1, 2);
+ }
+
+ if (pcie_sphy->calibration.supported) {
+ mtk_pcie_sphy_apply_calibration(pcie_sphy);
+
+ tx_impsel.pmos = pcie_sphy->calibration.tx_impsel.pmos;
+ tx_impsel.nmos = pcie_sphy->calibration.tx_impsel.nmos;
+ } else {
+ /* Set P=10, N=9 to prevent EMI if no calibration present */
+ tx_impsel.pmos = 10;
+ tx_impsel.nmos = 9;
+ }
+
+ /* Select TX Impedance on N and P MOSFETs */
+ for (i = 0; i < pcie_sphy->num_lanes; i++) {
+ void __iomem *sif_lane_base = pcie_sphy->sif_base + PEXTP_REG_LANE(i);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_A0,
+ RG_XTP_LN_TX_IMPSEL_PMOS, tx_impsel.pmos);
+
+ mtk_phy_update_field(sif_lane_base + PEXTP_ANA_LN_TRX_A0,
+ RG_XTP_LN_TX_IMPSEL_NMOS, tx_impsel.nmos);
+ }
+
+ return 0;
+}
+
+static const struct phy_ops mtk_pcie_sphy_ops = {
+ .init = mtk_pcie_sphy_init,
+ .owner = THIS_MODULE,
+};
+
+static int mtk_pcie_sphy_get_one_cal_para(struct device *dev, const char *name, u8 max_val)
+{
+ u16 buf;
+ u8 tmp;
+ int ret;
+
+ /*
+ * All of the calibrations are always max 8 bits long, but some may
+ * be split between two different 8-bits cells: handle this corner
+ * case by retrying reading as u16.
+ */
+ ret = nvmem_cell_read_u8(dev, name, &tmp);
+ if (ret == 0)
+ buf = tmp;
+ else
+ ret = nvmem_cell_read_u16(dev, name, &buf);
+
+ if (ret) {
+ dev_err(dev, "Cannot get calibration data for %s: %d\n", name, ret);
+ return ret;
+ };
+
+ if (buf == 0) {
+ dev_warn(dev, "No calibration for %s. Using defaults\n", name);
+ return -ENOENT;
+ }
+
+ if (buf > max_val) {
+ dev_err(dev, "Bad value %u retrieved for %s. Returning.\n", buf, name);
+ return -ERANGE;
+ };
+
+ return buf;
+}
+
+static int mtk_pcie_sphy_get_calibration_data(struct mtk_pcie_sphy *pcie_sphy)
+{
+ struct mtk_pcie_sphy_efuse *cal = &pcie_sphy->calibration;
+ struct device *dev = pcie_sphy->dev;
+ u8 version;
+ int ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "int-r",
+ FIELD_MAX(RG_XTP_GLB_BIAS_INTR_CTRL));
+ if (ret < 0)
+ goto end;
+ cal->int_r_ctrl = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "xtp-vtrim",
+ FIELD_MAX(RG_XTP_GLB_BIAS_V2V_VTRIM));
+ if (ret < 0)
+ goto end;
+ cal->xtp_vtrim = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "cktx-pmos",
+ FIELD_MAX(RG_CKM_CKTX_IMPSEL_PMOS));
+ if (ret < 0)
+ goto end;
+ cal->cktx_impsel.pmos = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "cktx-nmos",
+ FIELD_MAX(RG_CKM_CKTX_IMPSEL_NMOS));
+ if (ret < 0)
+ goto end;
+ cal->cktx_impsel.nmos = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "cktx-r-mid",
+ FIELD_MAX(RG_CKM_CKTX_IMPSEL_SW));
+ if (ret < 0)
+ goto end;
+ cal->cktx_r_mid = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "rxfe-lanes-rl-ctle",
+ FIELD_MAX(RG_XTP_LN_RX_LEQ_RL_CTLE_CAL));
+ if (ret < 0)
+ goto end;
+ cal->rx_leq_rl_ctle = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "rxfe-lanes-rl-vga",
+ FIELD_MAX(RG_XTP_LN_RX_LEQ_RL_VGA_CAL));
+ if (ret < 0)
+ goto end;
+ cal->rx_leq_rl_vga = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "rxfe-lanes-rl-dfe",
+ FIELD_MAX(RG_XTP_LN_RX_LEQ_RL_DFE_CAL));
+ if (ret < 0)
+ goto end;
+ cal->rx_leq_rl_dfe = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "rx-lanes-imp",
+ FIELD_MAX(RG_XTP_LN_RX_IMPSEL));
+ if (ret < 0)
+ goto end;
+ cal->rx_impsel = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "tx-lanes-pmos",
+ FIELD_MAX(RG_XTP_LN_TX_IMPSEL_PMOS));
+ if (ret < 0)
+ goto end;
+ cal->tx_impsel.pmos = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "tx-lanes-nmos",
+ FIELD_MAX(RG_XTP_LN_TX_IMPSEL_NMOS));
+ if (ret < 0)
+ goto end;
+ cal->tx_impsel.nmos = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "tx-ln0-rswn",
+ FIELD_MAX(RG_XTP_LN_TX_RSWN_IMPSEL));
+ if (ret < 0)
+ goto end;
+ cal->tx_rswn_impsel[0] = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "tx-ln1-rswn",
+ FIELD_MAX(RG_XTP_LN_TX_RSWN_IMPSEL));
+ if (ret < 0)
+ goto end;
+ cal->tx_rswn_impsel[1] = ret;
+
+ ret = mtk_pcie_sphy_get_one_cal_para(dev, "cal-version", 15);
+ if (ret < 0)
+ goto end;
+ version = ret;
+
+ /* Quirk for eFuse calibration table versions 0 to 4 */
+ if ((version <= MTK_PCIE_SPHY_CALIBRATION_LAST_QUIRK_VER) &&
+ cal->rx_leq_rl_ctle == 10) {
+ cal->rx_leq_rl_vga = cal->rx_leq_rl_ctle;
+ cal->rx_leq_rl_dfe = cal->rx_leq_rl_ctle;
+ }
+
+end:
+ if (ret < 0) {
+ /*
+ * If any of the calibration values is missing, or if there is
+ * no calibration at all in the eFuses, this is not a problem,
+ * as the PHY doesn't require one to actually work.
+ */
+ if (ret == -ENOENT) {
+ cal->supported = false;
+ return 0;
+ }
+ return ret;
+ };
+ cal->supported = true;
+
+ return 0;
+}
+
+static int mtk_pcie_sphy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *provider;
+ struct mtk_pcie_sphy *pcie_sphy;
+ u32 num_lanes;
+ int ret;
+
+ pcie_sphy = devm_kzalloc(dev, sizeof(*pcie_sphy), GFP_KERNEL);
+ if (!pcie_sphy)
+ return -ENOMEM;
+
+ pcie_sphy->sif_base = devm_platform_ioremap_resource_byname(pdev, "sif");
+ if (IS_ERR(pcie_sphy->sif_base))
+ return dev_err_probe(dev, PTR_ERR(pcie_sphy->sif_base),
+ "Failed to map phy-sif base\n");
+
+ pcie_sphy->ckm_base = devm_platform_ioremap_resource_byname(pdev, "ckm");
+ if (IS_ERR(pcie_sphy->ckm_base))
+ return dev_err_probe(dev, PTR_ERR(pcie_sphy->ckm_base),
+ "Failed to map phy-ckm base\n");
+
+ pcie_sphy->phy = devm_phy_create(dev, dev->of_node, &mtk_pcie_sphy_ops);
+ if (IS_ERR(pcie_sphy->phy))
+ return dev_err_probe(dev, PTR_ERR(pcie_sphy->phy),
+ "Failed to create PCIe phy\n");
+
+ ret = of_property_read_u32(dev->of_node, "num-lanes", &num_lanes);
+ if (ret)
+ num_lanes = 1;
+ else if (num_lanes > 4)
+ return dev_err_probe(dev, -EINVAL, "Invalid number of lanes.\n");
+
+ pcie_sphy->num_lanes = num_lanes;
+ pcie_sphy->dev = dev;
+
+ if (pcie_sphy->num_lanes <= MTK_PCIE_SPHY_CALIBRATION_MAX_DATA_LANES) {
+ ret = mtk_pcie_sphy_get_calibration_data(pcie_sphy);
+ if (ret)
+ return ret;
+ }
+
+ phy_set_drvdata(pcie_sphy->phy, pcie_sphy);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(provider))
+ return dev_err_probe(dev, PTR_ERR(provider),
+ "Could not register PCI-Express S-PHY\n");
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pcie_sphy_of_match[] = {
+ { .compatible = "mediatek,mt8196-pcie-sphy" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mtk_pcie_sphy_of_match);
+
+static struct platform_driver mtk_pcie_sphy_driver = {
+ .probe = mtk_pcie_sphy_probe,
+ .driver = {
+ .name = "mtk-pcie-sphy",
+ .of_match_table = mtk_pcie_sphy_of_match,
+ },
+};
+module_platform_driver(mtk_pcie_sphy_driver);
+
+MODULE_DESCRIPTION("MediaTek PCIe SPHY driver");
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_LICENSE("GPL");
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: phy: Document MT8196 MediaTek PCI-Express Gen4 S-PHY
From: AngeloGioacchino Del Regno @ 2026-07-16 15:13 UTC (permalink / raw)
To: chunfeng.yun
Cc: vkoul, neil.armstrong, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-arm-kernel, linux-mediatek,
linux-phy, devicetree, linux-kernel, kernel
In-Reply-To: <20260716151333.77254-1-angelogioacchino.delregno@collabora.com>
This adds bindings for the PCI-Express Gen4 S-PHY found in newer
MediaTek SoCs, such as MT8196 and its variants.
In the current "revision 3", depending on the specific port, this
S-PHY supports up to two lanes of PCI-Express Gen 4 and both EP
and RC modes.
It is not clear whether revisions/versions earlier than 3 have
ever been shipped in any other MediaTek SoC.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
.../phy/mediatek,mt8196-pcie-sphy.yaml | 91 +++++++++++++++++++
1 file changed, 91 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/mediatek,mt8196-pcie-sphy.yaml
diff --git a/Documentation/devicetree/bindings/phy/mediatek,mt8196-pcie-sphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,mt8196-pcie-sphy.yaml
new file mode 100644
index 000000000000..2b61882c402c
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/mediatek,mt8196-pcie-sphy.yaml
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/mediatek,mt8196-pcie-sphy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek PCI-Express Gen4 S-PHY
+
+maintainers:
+ - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+description:
+ The MediaTek PCI-Express Gen4 S-PHY is capable of data serialization
+ and de-serialization with 8, 10, 128 or 130 bits (16GT/s) encoding
+ and decoding, has analog buffers, elastic buffers and mechanisms for
+ receiver detection.
+ This PHY supports link rates of 2.5, 5.0, 6.0 and 16.0 GT/s per-lane
+ in both Root Complex (RC) and End Point (EP) modes, depending on the
+ chosen port.
+ The Digital PHY (PHYD) part adheres to the Intel PIPE (PHY Interface
+ for the PCIe) specification.
+
+properties:
+ compatible:
+ const: mediatek,mt8196-pcie-sphy
+
+ reg:
+ minItems: 2
+
+ reg-names:
+ items:
+ - const: sif
+ - const: ckm
+
+ "#phy-cells":
+ const: 0
+
+ nvmem-cells:
+ items:
+ - description: Internal resistor selection of TX Bias Current
+ - description: XTP Bias V2V voltage calibration
+ - description: S-PLL CKTX Impedance Selection (P-MOSFET side)
+ - description: S-PLL CKTX Impedance Selection (N-MOSFET side)
+ - description: S-PLL CKTX Intermediate Transition Impedance
+ - description: RX Front-End Return Loss Continuous Time Linear EQ
+ - description: RX Front-End Return Loss Variable Gain Amplifier
+ - description: RX Front-End Return Loss Decision Feedback EQ
+ - description: RX Impedance Selection
+ - description: TX Impedance Selection (P-MOSFET side)
+ - description: TX Impedance Selection (N-MOSFET side)
+ - description: TX Lane 0 Switch Resistance (RSWn)
+ - description: TX Lane 1 Switch Resistance (RSWn)
+ - description: eFuse calibration table version
+
+ nvmem-cell-names:
+ items:
+ - const: int-r
+ - const: xtp-vtrim
+ - const: cktx-pmos
+ - const: cktx-nmos
+ - const: cktx-r-mid
+ - const: rxfe-lanes-rl-ctle
+ - const: rxfe-lanes-rl-vga
+ - const: rxfe-lanes-rl-dfe
+ - const: rx-lanes-imp
+ - const: tx-lanes-pmos
+ - const: tx-lanes-nmos
+ - const: tx-ln0-rswn
+ - const: tx-ln1-rswn
+ - const: cal-version
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ phy@16900000 {
+ compatible = "mediatek,mt8196-pcie-sphy";
+ reg = <0x16900000 0x10000>, <0x16920000 0x10000>;
+ reg-names = "sif", "ckm";
+ power-domains = <&spm 10>;
+ #phy-cells = <0>;
+ };
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 0/2] PHY: Add MediaTek PCI-Express Gen4 S-PHY Driver
From: AngeloGioacchino Del Regno @ 2026-07-16 15:13 UTC (permalink / raw)
To: chunfeng.yun
Cc: vkoul, neil.armstrong, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, linux-arm-kernel, linux-mediatek,
linux-phy, devicetree, linux-kernel, kernel
This adds a driver for the PCI-Express Gen4 "S-PHY" found in the
Genio MT8894, Kompanio MT8196, Dimensity MT6991 SoCs (which are
all variants of the same chip).
This was successfully tested on MT8894 and MT8196.
AngeloGioacchino Del Regno (2):
dt-bindings: phy: Document MT8196 MediaTek PCI-Express Gen4 S-PHY
phy: mediatek: Add support for PCI-Express Gen4 S-PHY
.../phy/mediatek,mt8196-pcie-sphy.yaml | 91 +++
drivers/phy/mediatek/Kconfig | 9 +
drivers/phy/mediatek/Makefile | 1 +
drivers/phy/mediatek/phy-mtk-pcie-sphy.c | 560 ++++++++++++++++++
4 files changed, 661 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/mediatek,mt8196-pcie-sphy.yaml
create mode 100644 drivers/phy/mediatek/phy-mtk-pcie-sphy.c
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Bryan O'Donoghue @ 2026-07-16 12:52 UTC (permalink / raw)
To: Loic Poulain
Cc: Bryan O'Donoghue, Vladimir Zapolskiy, Vinod Koul,
Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Neil Armstrong, linux-arm-msm, linux-phy,
linux-media, devicetree, linux-kernel
In-Reply-To: <CAFEp6-3U66hvi0iZrtRbyY3B-uwEap6xDFHFkVoaEBwWhV74Uw@mail.gmail.com>
On 16/07/2026 12:28, Loic Poulain wrote:
>> I just wonder if there's any real upside to all that additional work and
>> delay/churn.
> There is no really need to support runtime configuration as of now
> since we only support D-PHY, so the delta for v10*should* be tiny,
> either a bus-type sanity read in parse_routing(), or even nothing at
> DT parse and a future configure() branch when C-PHY lands.
Right, well I tend to agree that a runtime configure() is out of scope,
so, I'm going to stick to Rob's guidance.
If you look at other upstream stuff you will see phy-cells = 0 for
single mode PHYs and phy-cells = 1 for PHYs that can be in any mode.
Consumer configures the mode in DT like every other upstream MIPI CSI2 PHY.
---
bod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v6 3/6] phy: fsl-imx8mq-usb: add runtime PM support
From: Frank Li @ 2026-07-16 12:41 UTC (permalink / raw)
To: Xu Yang
Cc: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li, linux-phy, imx,
linux-arm-kernel, linux-kernel, Xu Yang
In-Reply-To: <omitpksxmr657vlmjs3ybzhiq6zj4znrsp2tereofqees27z36@m3lhmrbufqay>
On Thu, Jul 16, 2026 at 07:32:59PM +0800, Xu Yang wrote:
> On Wed, Jul 15, 2026 at 10:28:05AM -0500, Frank Li wrote:
> > On Wed, Jul 15, 2026 at 07:33:58PM +0800, Xu Yang wrote:
> > > From: Xu Yang <xu.yang_2@nxp.com>
> > >
> > > Add runtime PM to ensure the PHY is properly powered and clocked during
> > > register access, preventing potential system hangs.
> > >
> > > It guards register access in the following scenarios:
> > > - PHY operations: init() and power_on/off() callbacks are guarded by
> > > phy core
> > > - Type-C orientation switching when PHY/Controller are suspended which
> > > needs explicitly care
> > > - Future PHY control port register regmap debugfs access
> > >
> > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> > >
> > > ---
> > > Changes in v6:
> > > - use devm_pm_runtime_enable() to disable runtime PM when probe fails
> > > - simply pm_runtime_get_sync/disable/put_noidle() to pm_runtime_resume()
> > > Changes in v5:
> > > - use non-devm PM runtime callback to correctly enable/disable clocks
> > > when unbind the device
> > > Changes in v4:
> > > - replace guard() with PM_RUNTIME_ACQUIRE()
> > > Changes in v3:
> > > - new patch
> > > ---
> > > drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 67 +++++++++++++++++++++---------
> > > 1 file changed, 48 insertions(+), 19 deletions(-)
> > >
> > > diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > > index 3a5788c609e1..bc804d2b5aee 100644
> > > --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > > +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > > @@ -9,6 +9,7 @@
> > > #include <linux/of.h>
> > > #include <linux/phy/phy.h>
> > > #include <linux/platform_device.h>
> > > +#include <linux/pm_runtime.h>
> > > #include <linux/regulator/consumer.h>
> > > #include <linux/usb/typec_mux.h>
> > >
> > > @@ -136,17 +137,15 @@ static int tca_blk_typec_switch_set(struct typec_switch_dev *sw,
> > > {
> > > struct imx8mq_usb_phy *imx_phy = typec_switch_get_drvdata(sw);
> > > struct tca_blk *tca = imx_phy->tca;
> > > - int ret;
> > >
> > > if (tca->orientation == orientation)
> > > return 0;
> > >
> > > - ret = clk_prepare_enable(imx_phy->clk);
> > > - if (ret)
> > > - return ret;
> > > + PM_RUNTIME_ACQUIRE(&imx_phy->phy->dev, pm);
> > > + if (PM_RUNTIME_ACQUIRE_ERR(&pm))
> > > + return -ENXIO;
> > >
> > > tca_blk_orientation_set(tca, orientation);
> > > - clk_disable_unprepare(imx_phy->clk);
> > >
> > > return 0;
> > > }
> > > @@ -620,16 +619,6 @@ static int imx8mq_phy_power_on(struct phy *phy)
> > > if (ret)
> > > return ret;
> > >
> > > - ret = clk_prepare_enable(imx_phy->clk);
> > > - if (ret)
> > > - return ret;
> > > -
> > > - ret = clk_prepare_enable(imx_phy->alt_clk);
> > > - if (ret) {
> > > - clk_disable_unprepare(imx_phy->clk);
> > > - return ret;
> > > - }
> > > -
> > > /* Disable rx term override */
> > > value = readl(imx_phy->base + PHY_CTRL6);
> > > value &= ~PHY_CTRL6_RXTERM_OVERRIDE_SEL;
> > > @@ -648,8 +637,6 @@ static int imx8mq_phy_power_off(struct phy *phy)
> > > value |= PHY_CTRL6_RXTERM_OVERRIDE_SEL;
> > > writel(value, imx_phy->base + PHY_CTRL6);
> > >
> > > - clk_disable_unprepare(imx_phy->alt_clk);
> > > - clk_disable_unprepare(imx_phy->clk);
> > > regulator_disable(imx_phy->vbus);
> > >
> > > return 0;
> > > @@ -686,6 +673,7 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> > > struct device *dev = &pdev->dev;
> > > struct imx8mq_usb_phy *imx_phy;
> > > const struct phy_ops *phy_ops;
> > > + int ret;
> > >
> > > imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL);
> > > if (!imx_phy)
> > > @@ -693,13 +681,13 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> > >
> > > platform_set_drvdata(pdev, imx_phy);
> > >
> > > - imx_phy->clk = devm_clk_get(dev, "phy");
> > > + imx_phy->clk = devm_clk_get_enabled(dev, "phy");
> > > if (IS_ERR(imx_phy->clk)) {
> > > dev_err(dev, "failed to get imx8mq usb phy clock\n");
> > > return PTR_ERR(imx_phy->clk);
> > > }
> > >
> > > - imx_phy->alt_clk = devm_clk_get_optional(dev, "alt");
> > > + imx_phy->alt_clk = devm_clk_get_optional_enabled(dev, "alt");
> > > if (IS_ERR(imx_phy->alt_clk))
> > > return dev_err_probe(dev, PTR_ERR(imx_phy->alt_clk),
> > > "Failed to get alt clk\n");
> > > @@ -708,6 +696,11 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> > > if (IS_ERR(imx_phy->base))
> > > return PTR_ERR(imx_phy->base);
> > >
> > > + pm_runtime_set_active(dev);
> > > + ret = devm_pm_runtime_enable(dev);
> > > + if (ret)
> > > + return dev_err_probe(dev, ret, "failed to enable runtime PM\n");
> > > +
> >
> > no place to call pm runtime suspend, so whole driver's life cycle runtime
> > pm is on, is it expected?
>
> First, at the end of __driver_probe_device(), it will call pm_request_idle()
> for the device. So runtime_suspend() will run.
> Second, this platform device is the parent of created phy device, the runtime status
> of phy device is managed by phy core, so this platform device will be managed by phy
> core indirectly.
>
> Just found it's not suitable to call devm_pm_runtime_enable() here. Because
>
> pm_runtime_disable_action()
> pm_runtime_dont_use_autosuspend()
> update_autosuspend()
> rpm_idle()
>
> then after remove(), runtime suspend func will still be called. Clocks may be
> disabled twice. I will use non-devm version pm_runtime_enable() in next version.
This should be common problem. Your case should be typical one.
try devm_pm_runtime_set_active_enabled().
Frank
>
> Thanks,
> Xu Yang
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v4 1/8] phy: rockchip: samsung-hdptx: Fix rate recalculation for high bpc
From: Andy Yan @ 2026-07-16 12:27 UTC (permalink / raw)
To: Cristian Ciocaltea
Cc: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov, kernel, linux-phy, linux-arm-kernel,
linux-rockchip, linux-kernel, Thomas Niederprüm,
Simon Wright
In-Reply-To: <20260612-hdptx-clk-fixes-v4-1-ce5e1d456cda@collabora.com>
Hello,
Cristian Ciocaltea <cristian.ciocaltea@collabora.com> 于2026年6月12日周五 07:45写道:
>
> The PHY PLL can be programmed by an external component, e.g. the
> bootloader, just before the recalc_rate() callback is invoked during
> devm_clk_hw_register() in the probe path.
>
> Therefore rk_hdptx_phy_clk_recalc_rate() finds the PLL enabled and
> attempts to compute the clock rate, while making use of the bpc value
> from the HDMI PHY configuration, which always defaults to 8 because
> phy_configure() was not run at that point. As a consequence, the
> (re)calculated rate is incorrect when the actual bpc was higher than 8.
>
> Do not rely on any of the hdmi_cfg members when computing the clock rate
> and, instead, read the required input data (i.e. bpc), directly from the
> hardware registers.
>
> Fixes: 3481fc04d969 ("phy: rockchip: samsung-hdptx: Compute clk rate from PLL config")
> Tested-by: Thomas Niederprüm <dubito@online.de>
> Tested-by: Simon Wright <simon@symple.nz>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Reviewed-by:Andy Yan <andyshrk@gmail.com>
Thanks
> ---
> drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 13 ++++---------
> 1 file changed, 4 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index 2d973bc37f07..710603afff86 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -2168,7 +2168,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
> struct lcpll_config lcpll_hw;
> struct ropll_config ropll_hw;
> u64 fout, sdm;
> - u32 mode, val;
> + u32 mode, bpc, val;
> int ret, i;
>
> ret = regmap_read(hdptx->regmap, CMN_REG(0008), &mode);
> @@ -2266,6 +2266,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
> if (ret)
> return 0;
> ropll_hw.pms_sdiv = ((val & PLL_PCG_POSTDIV_SEL_MASK) >> 4) + 1;
> + bpc = (FIELD_GET(PLL_PCG_CLK_SEL_MASK, val) << 1) + 8;
>
> fout = PLL_REF_CLK * ropll_hw.pms_mdiv;
> if (ropll_hw.sdm_en) {
> @@ -2280,7 +2281,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
> fout = fout + sdm;
> }
>
> - return div_u64(fout * 2, ropll_hw.pms_sdiv * 10);
> + return DIV_ROUND_CLOSEST_ULL(fout * 2 * 8, ropll_hw.pms_sdiv * 10 * bpc);
> }
>
> static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
> @@ -2288,19 +2289,13 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
> {
> struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
> u32 status;
> - u64 rate;
> int ret;
>
> ret = regmap_read(hdptx->grf, GRF_HDPTX_CON0, &status);
> if (ret || !(status & HDPTX_I_PLL_EN))
> return 0;
>
> - rate = rk_hdptx_phy_clk_calc_rate_from_pll_cfg(hdptx);
> -
> - if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
> - return rate;
> -
> - return DIV_ROUND_CLOSEST_ULL(rate * 8, hdptx->hdmi_cfg.bpc);
> + return rk_hdptx_phy_clk_calc_rate_from_pll_cfg(hdptx);
> }
>
> static int rk_hdptx_phy_clk_determine_rate(struct clk_hw *hw,
>
> --
> 2.54.0
>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v6 3/6] phy: fsl-imx8mq-usb: add runtime PM support
From: Xu Yang @ 2026-07-16 11:32 UTC (permalink / raw)
To: Frank Li
Cc: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li, linux-phy, imx,
linux-arm-kernel, linux-kernel, Xu Yang
In-Reply-To: <alenBaMOTSPo7DJV@SMW015318>
On Wed, Jul 15, 2026 at 10:28:05AM -0500, Frank Li wrote:
> On Wed, Jul 15, 2026 at 07:33:58PM +0800, Xu Yang wrote:
> > From: Xu Yang <xu.yang_2@nxp.com>
> >
> > Add runtime PM to ensure the PHY is properly powered and clocked during
> > register access, preventing potential system hangs.
> >
> > It guards register access in the following scenarios:
> > - PHY operations: init() and power_on/off() callbacks are guarded by
> > phy core
> > - Type-C orientation switching when PHY/Controller are suspended which
> > needs explicitly care
> > - Future PHY control port register regmap debugfs access
> >
> > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> >
> > ---
> > Changes in v6:
> > - use devm_pm_runtime_enable() to disable runtime PM when probe fails
> > - simply pm_runtime_get_sync/disable/put_noidle() to pm_runtime_resume()
> > Changes in v5:
> > - use non-devm PM runtime callback to correctly enable/disable clocks
> > when unbind the device
> > Changes in v4:
> > - replace guard() with PM_RUNTIME_ACQUIRE()
> > Changes in v3:
> > - new patch
> > ---
> > drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 67 +++++++++++++++++++++---------
> > 1 file changed, 48 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > index 3a5788c609e1..bc804d2b5aee 100644
> > --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > @@ -9,6 +9,7 @@
> > #include <linux/of.h>
> > #include <linux/phy/phy.h>
> > #include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> > #include <linux/regulator/consumer.h>
> > #include <linux/usb/typec_mux.h>
> >
> > @@ -136,17 +137,15 @@ static int tca_blk_typec_switch_set(struct typec_switch_dev *sw,
> > {
> > struct imx8mq_usb_phy *imx_phy = typec_switch_get_drvdata(sw);
> > struct tca_blk *tca = imx_phy->tca;
> > - int ret;
> >
> > if (tca->orientation == orientation)
> > return 0;
> >
> > - ret = clk_prepare_enable(imx_phy->clk);
> > - if (ret)
> > - return ret;
> > + PM_RUNTIME_ACQUIRE(&imx_phy->phy->dev, pm);
> > + if (PM_RUNTIME_ACQUIRE_ERR(&pm))
> > + return -ENXIO;
> >
> > tca_blk_orientation_set(tca, orientation);
> > - clk_disable_unprepare(imx_phy->clk);
> >
> > return 0;
> > }
> > @@ -620,16 +619,6 @@ static int imx8mq_phy_power_on(struct phy *phy)
> > if (ret)
> > return ret;
> >
> > - ret = clk_prepare_enable(imx_phy->clk);
> > - if (ret)
> > - return ret;
> > -
> > - ret = clk_prepare_enable(imx_phy->alt_clk);
> > - if (ret) {
> > - clk_disable_unprepare(imx_phy->clk);
> > - return ret;
> > - }
> > -
> > /* Disable rx term override */
> > value = readl(imx_phy->base + PHY_CTRL6);
> > value &= ~PHY_CTRL6_RXTERM_OVERRIDE_SEL;
> > @@ -648,8 +637,6 @@ static int imx8mq_phy_power_off(struct phy *phy)
> > value |= PHY_CTRL6_RXTERM_OVERRIDE_SEL;
> > writel(value, imx_phy->base + PHY_CTRL6);
> >
> > - clk_disable_unprepare(imx_phy->alt_clk);
> > - clk_disable_unprepare(imx_phy->clk);
> > regulator_disable(imx_phy->vbus);
> >
> > return 0;
> > @@ -686,6 +673,7 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> > struct device *dev = &pdev->dev;
> > struct imx8mq_usb_phy *imx_phy;
> > const struct phy_ops *phy_ops;
> > + int ret;
> >
> > imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL);
> > if (!imx_phy)
> > @@ -693,13 +681,13 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> >
> > platform_set_drvdata(pdev, imx_phy);
> >
> > - imx_phy->clk = devm_clk_get(dev, "phy");
> > + imx_phy->clk = devm_clk_get_enabled(dev, "phy");
> > if (IS_ERR(imx_phy->clk)) {
> > dev_err(dev, "failed to get imx8mq usb phy clock\n");
> > return PTR_ERR(imx_phy->clk);
> > }
> >
> > - imx_phy->alt_clk = devm_clk_get_optional(dev, "alt");
> > + imx_phy->alt_clk = devm_clk_get_optional_enabled(dev, "alt");
> > if (IS_ERR(imx_phy->alt_clk))
> > return dev_err_probe(dev, PTR_ERR(imx_phy->alt_clk),
> > "Failed to get alt clk\n");
> > @@ -708,6 +696,11 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> > if (IS_ERR(imx_phy->base))
> > return PTR_ERR(imx_phy->base);
> >
> > + pm_runtime_set_active(dev);
> > + ret = devm_pm_runtime_enable(dev);
> > + if (ret)
> > + return dev_err_probe(dev, ret, "failed to enable runtime PM\n");
> > +
>
> no place to call pm runtime suspend, so whole driver's life cycle runtime
> pm is on, is it expected?
First, at the end of __driver_probe_device(), it will call pm_request_idle()
for the device. So runtime_suspend() will run.
Second, this platform device is the parent of created phy device, the runtime status
of phy device is managed by phy core, so this platform device will be managed by phy
core indirectly.
Just found it's not suitable to call devm_pm_runtime_enable() here. Because
pm_runtime_disable_action()
pm_runtime_dont_use_autosuspend()
update_autosuspend()
rpm_idle()
then after remove(), runtime suspend func will still be called. Clocks may be
disabled twice. I will use non-devm version pm_runtime_enable() in next version.
Thanks,
Xu Yang
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Loic Poulain @ 2026-07-16 11:28 UTC (permalink / raw)
To: Bryan O'Donoghue
Cc: Bryan O'Donoghue, Vladimir Zapolskiy, Vinod Koul,
Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Neil Armstrong, linux-arm-msm, linux-phy,
linux-media, devicetree, linux-kernel
In-Reply-To: <c731b03e-b550-48af-b338-37ac53018247@linaro.org>
Hi Bryan,
On Thu, Jul 16, 2026 at 11:42 AM Bryan O'Donoghue
<bryan.odonoghue@linaro.org> wrote:
>
> On 16/07/2026 09:56, Loic Poulain wrote:
> > On Mon, Jul 13, 2026 at 1:18 AM Bryan O'Donoghue <bod@kernel.org> wrote:
> >>
> >> On 09/07/2026 08:40, Vladimir Zapolskiy wrote:
> >>>> As explained in the cover letter: I'm following guidance from Rob on that.
> >>> Pehaps you've misread a given review comment, because Rob's guidance is
> >>> to remove 'phy-type' property,
> >>
> >> I'll just quote verbatim "Perhaps putting this in phy cells would be
> >> better because the consumer decides on the mode."
> >>
> >> That is not "remove phy-type" - it's "move the mode into the cell". I'm
> >> shifting this back to the DT schema maintainers since, I take their
> >> feedback literally, seriously and canonically.
> >>
> >> Any of the triumvirate will do, Rob, Krzysztof or Conor.
> >>
> >> Absent a different answer from the DT schema guys, v10 ships with the
> >> consumer deciding the mode as per Rob's original guidance.
> >
> > On the #phy-cells question, IMO we should drop #phy-cells to 0 and
> > derive the C-PHY/D-PHY mode from the endpoint bus-type. The operating
> > mode is really a configuration of the link rather than a hardware
> > description/limitation of the PHY block itself,and the sensor endpoint
> > is conventionally where the bus type originates. I guess this costs us
> > nothing on the driver side today, we only support D-PHY, so the
> > mode-check just moves into the endpoint parsing we already do in
> > phy_qcom_mipi_csi2_parse_routing(). It can be a minimal
> > fwnode_property_read_u32(ep, "bus-type", ...) sanity check and adding
> > C-PHY later is then a one-line case MEDIA_BUS_TYPE_CSI2_CPHY
> > with no DT ABI change.
>
> So I take your point on link-type - in theory you can select the mode
> from the sensor @ config time. The established practice is that the
> consumer decides the PHY mode, so if we wanted to make this a _runtime_
> configuration - then that should be information that is passed to the
> PHY via configure() not via DT because we've said its a link-mode
> abstracted from the DT entirely.
>
> In the extreme case I have a user-space utility selecting sensor mode,
> which the CSI controller parses and then signals the PHY to switch modes.
>
> If its a run-time config, then its a run-time config and DT should be
> excluded from the mode selection tree.
>
> I'm in fact willing to entertain this idea - but it will require passing
> the PHY mode to configure() not consuming - DT data from the endpoint.
>
> My core point here is both acknowleding Rob's point the consumer decides
> the mode - and _if_ we go the runtime configuration route, then actually
> making the selection @ configure not at probe/dt parse time.
I agree this is/could-be a runtime configuration/negotiation.
> I just wonder if there's any real upside to all that additional work and
> delay/churn.
There is no really need to support runtime configuration as of now
since we only support D-PHY, so the delta for v10 *should* be tiny,
either a bus-type sanity read in parse_routing(), or even nothing at
DT parse and a future configure() branch when C-PHY lands.
Regards,
Loic
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v6 6/6] phy: fsl-imx8mq-usb: keep PHY power domain runtime always-on for i.MX8MP
From: Xu Yang @ 2026-07-16 10:42 UTC (permalink / raw)
To: Frank Li
Cc: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li, linux-phy, imx,
linux-arm-kernel, linux-kernel, Xu Yang
In-Reply-To: <aleoGO5hBWCl6ZgE@SMW015318>
On Wed, Jul 15, 2026 at 10:32:40AM -0500, Frank Li wrote:
> On Wed, Jul 15, 2026 at 07:34:01PM +0800, Xu Yang wrote:
> > From: Xu Yang <xu.yang_2@nxp.com>
> >
> > On i.MX8MP, the USB PHY has a dedicated power domain that was previously
> > never powered off at runtime. With the introduction of runtime PM support,
> > the power domain will be powered off if the device is runtime suspended,
> > which breaks USB wakeup functionality.
> >
> > To preserve wakeup functionality, mark the PHY power domain as runtime
> > always-on for i.MX8MP platform. To limit the behavior to i.MX8MP, add a
> > need_genpd_rpm_on to imx8mq_usb_phy_drvdata and set it as true for i.MX8MP.
> >
> > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> >
> > ---
> > Changes in v6:
> > - set need_genpd_rpm_on flag for i.MX8MP and call dev_pm_genpd_rpm_always_on()
> > if the flag is true
> > Changes in v5:
> > - no changes
> > Changes in v4:
> > - no changes
> > Changes in v3:
> > - new patch
> > ---
> > drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 9 +++++++++
> > 1 file changed, 9 insertions(+)
> >
> > diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > index f0bdfa75d586..2398bda50eb8 100644
> > --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > @@ -9,6 +9,7 @@
> > #include <linux/of.h>
> > #include <linux/phy/phy.h>
> > #include <linux/platform_device.h>
> > +#include <linux/pm_domain.h>
> > #include <linux/pm_runtime.h>
> > #include <linux/regulator/consumer.h>
> > #include <linux/regmap.h>
> > @@ -134,6 +135,7 @@ struct imx8mq_usb_phy {
> >
> > struct imx8mq_usb_phy_drvdata {
> > const struct phy_ops *ops;
> > + bool need_genpd_rpm_on;
> > };
> >
> > static void tca_blk_orientation_set(struct tca_blk *tca,
> > @@ -669,6 +671,7 @@ static const struct imx8mq_usb_phy_drvdata imx8mq_usb_phy_data = {
> >
> > static const struct imx8mq_usb_phy_drvdata imx8mp_usb_phy_data = {
> > .ops = &imx8mp_usb_phy_ops,
> > + .need_genpd_rpm_on = true,
> > };
> >
> > static const struct imx8mq_usb_phy_drvdata imx95_usb_phy_data = {
> > @@ -739,6 +742,12 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> > if (!phy_data)
> > return -EINVAL;
> >
> > + if (phy_data->need_genpd_rpm_on) {
> > + ret = dev_pm_genpd_rpm_always_on(dev, true);
> > + if (ret)
> > + return dev_err_probe(dev, ret, "failed to set genpd rpm always on\n");
> > + }
> > +
>
> need set false at driver remove?
Not need. Because this device will be deteched from the power domain after driver removal.
Thanks,
Xu Yang
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v6 1/6] phy: fsl-imx8mq-usb: fix typec switch leak on probe error path
From: Xu Yang @ 2026-07-16 10:40 UTC (permalink / raw)
To: sashiko-reviews; +Cc: olteanv, linux-phy, imx, vkoul, Frank.Li, neil.armstrong
In-Reply-To: <20260715114626.651A81F000E9@smtp.kernel.org>
On Wed, Jul 15, 2026 at 11:46:25AM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] The Type-C switch callback `tca_blk_typec_switch_set` can be invoked after the PHY driver is unbound, leading to a Use-After-Free of the driver context.
It's a common issue and it should be fixed in Typec-C subsystem.
Thanks,
Xu Yang
> --
>
> --- Patch [1]: [PATCH v6 1/6] phy: fsl-imx8mq-usb: fix typec switch leak on probe error path ---
> commit 5e0093cfdd6e9dd648ed3549eb93bacb54164be2
> Author: Felix Gu <ustc.gu@gmail.com>
>
> phy: fsl-imx8mq-usb: fix typec switch leak on probe error path
>
> This commit fixes a typec switch resource leak when probe fails after
> imx95_usb_phy_get_tca() succeeds. It transitions the cleanup of the switch
> to use devm_add_action_or_reset() so that it is properly freed on both
> probe failure and driver removal.
>
> > diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > index b05d80e849a14..9a33c06d6fc39 100644
> > --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> > @@ -173,9 +173,9 @@ static struct typec_switch_dev *tca_blk_get_typec_switch(struct platform_device
> > return sw;
> > }
> >
> > -static void tca_blk_put_typec_switch(struct typec_switch_dev *sw)
> > +static void tca_blk_put_typec_switch(void *data)
> > {
> > - typec_switch_unregister(sw);
> > + typec_switch_unregister(data);
>
> [Severity: High]
> This is a pre-existing issue, but does typec_switch_unregister() guarantee
> that no consumers will invoke the .set callback afterwards?
>
> If a consumer acquires the switch using fwnode_typec_switch_get() and holds
> a reference, it appears typec_switch_unregister() removes the device from
> sysfs but doesn't revoke the consumer's ability to call sw_dev->set().
>
> Because imx_phy and tca are allocated with devm_kzalloc() during probe, they
> are automatically freed when the provider unbinds. Could this lead to a
> use-after-free if the consumer asynchronously calls typec_switch_set():
>
> tca_blk_typec_switch_set()
> struct imx8mq_usb_phy *imx_phy = typec_switch_get_drvdata(sw);
> struct tca_blk *tca = imx_phy->tca;
>
> where imx_phy has already been freed by the devm teardown?
>
> > }
> >
> > static void tca_blk_orientation_set(struct tca_blk *tca,
>
> [ ... ]
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260715-imx8mp-usb-phy-improvement-v6-0-00d95e270e4c@nxp.com?part=1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Bryan O'Donoghue @ 2026-07-16 9:42 UTC (permalink / raw)
To: Loic Poulain, Bryan O'Donoghue
Cc: Vladimir Zapolskiy, Vinod Koul, Kishon Vijay Abraham I,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong,
linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <CAFEp6-2J0WGF6g0K7s--PxciO+d9MR-SCVnrWJ3u=sgQNwA59A@mail.gmail.com>
On 16/07/2026 09:56, Loic Poulain wrote:
> On Mon, Jul 13, 2026 at 1:18 AM Bryan O'Donoghue <bod@kernel.org> wrote:
>>
>> On 09/07/2026 08:40, Vladimir Zapolskiy wrote:
>>>> As explained in the cover letter: I'm following guidance from Rob on that.
>>> Pehaps you've misread a given review comment, because Rob's guidance is
>>> to remove 'phy-type' property,
>>
>> I'll just quote verbatim "Perhaps putting this in phy cells would be
>> better because the consumer decides on the mode."
>>
>> That is not "remove phy-type" - it's "move the mode into the cell". I'm
>> shifting this back to the DT schema maintainers since, I take their
>> feedback literally, seriously and canonically.
>>
>> Any of the triumvirate will do, Rob, Krzysztof or Conor.
>>
>> Absent a different answer from the DT schema guys, v10 ships with the
>> consumer deciding the mode as per Rob's original guidance.
>
> On the #phy-cells question, IMO we should drop #phy-cells to 0 and
> derive the C-PHY/D-PHY mode from the endpoint bus-type. The operating
> mode is really a configuration of the link rather than a hardware
> description/limitation of the PHY block itself,and the sensor endpoint
> is conventionally where the bus type originates. I guess this costs us
> nothing on the driver side today, we only support D-PHY, so the
> mode-check just moves into the endpoint parsing we already do in
> phy_qcom_mipi_csi2_parse_routing(). It can be a minimal
> fwnode_property_read_u32(ep, "bus-type", ...) sanity check and adding
> C-PHY later is then a one-line case MEDIA_BUS_TYPE_CSI2_CPHY
> with no DT ABI change.
So I take your point on link-type - in theory you can select the mode
from the sensor @ config time. The established practice is that the
consumer decides the PHY mode, so if we wanted to make this a _runtime_
configuration - then that should be information that is passed to the
PHY via configure() not via DT because we've said its a link-mode
abstracted from the DT entirely.
In the extreme case I have a user-space utility selecting sensor mode,
which the CSI controller parses and then signals the PHY to switch modes.
If its a run-time config, then its a run-time config and DT should be
excluded from the mode selection tree.
I'm in fact willing to entertain this idea - but it will require passing
the PHY mode to configure() not consuming - DT data from the endpoint.
My core point here is both acknowleding Rob's point the consumer decides
the mode - and _if_ we go the runtime configuration route, then actually
making the selection @ configure not at probe/dt parse time.
I just wonder if there's any real upside to all that additional work and
delay/churn.
> On data-lanes numbering, I don't have a strong opinion here. Keeping
> the current 0-based values is defensible, in this driver the value is
> used as a physical lane index and it selects the per-lane register
> bank (0x200 * n), so 0 maps to physical LN0. In that sense 0-based is
> a faithful representation of the physical lane position on the SoC.
>
> Regards,
> Loic
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Loic Poulain @ 2026-07-16 8:56 UTC (permalink / raw)
To: Bryan O'Donoghue
Cc: Vladimir Zapolskiy, Bryan O'Donoghue, Vinod Koul,
Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Neil Armstrong, linux-arm-msm, linux-phy,
linux-media, devicetree, linux-kernel
In-Reply-To: <4d7a0e59-7c34-4557-a475-8cd7fd2ad2d9@kernel.org>
On Mon, Jul 13, 2026 at 1:18 AM Bryan O'Donoghue <bod@kernel.org> wrote:
>
> On 09/07/2026 08:40, Vladimir Zapolskiy wrote:
> >> As explained in the cover letter: I'm following guidance from Rob on that.
> > Pehaps you've misread a given review comment, because Rob's guidance is
> > to remove 'phy-type' property,
>
> I'll just quote verbatim "Perhaps putting this in phy cells would be
> better because the consumer decides on the mode."
>
> That is not "remove phy-type" - it's "move the mode into the cell". I'm
> shifting this back to the DT schema maintainers since, I take their
> feedback literally, seriously and canonically.
>
> Any of the triumvirate will do, Rob, Krzysztof or Conor.
>
> Absent a different answer from the DT schema guys, v10 ships with the
> consumer deciding the mode as per Rob's original guidance.
On the #phy-cells question, IMO we should drop #phy-cells to 0 and
derive the C-PHY/D-PHY mode from the endpoint bus-type. The operating
mode is really a configuration of the link rather than a hardware
description/limitation of the PHY block itself,and the sensor endpoint
is conventionally where the bus type originates. I guess this costs us
nothing on the driver side today, we only support D-PHY, so the
mode-check just moves into the endpoint parsing we already do in
phy_qcom_mipi_csi2_parse_routing(). It can be a minimal
fwnode_property_read_u32(ep, "bus-type", ...) sanity check and adding
C-PHY later is then a one-line case MEDIA_BUS_TYPE_CSI2_CPHY
with no DT ABI change.
On data-lanes numbering, I don't have a strong opinion here. Keeping
the current 0-based values is defensible, in this driver the value is
used as a physical lane index and it selects the per-lane register
bank (0x200 * n), so 0 maps to physical LN0. In that sense 0-based is
a faithful representation of the physical lane position on the SoC.
Regards,
Loic
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 00/19] Add Freescale i.MX8qxp Display Controller support
From: Liu Ying @ 2026-07-16 6:49 UTC (permalink / raw)
To: Francesco Dolcini
Cc: dri-devel, devicetree, imx, linux-arm-kernel, linux-kernel,
linux-phy, p.zabel, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, tglx, vkoul, kishon, Frank.Li, lumag, aisheng.dong, agx,
u.kleine-koenig, marek.vasut
In-Reply-To: <20260716062612.GC9973@francesco-nb>
On Thu, Jul 16, 2026 at 08:26:12AM +0200, Francesco Dolcini wrote:
> On Thu, Jul 16, 2026 at 02:21:31PM +0800, Liu Ying wrote:
> > On Tue, Jul 14, 2026 at 09:36:27PM +0200, Francesco Dolcini wrote:
> > > On Mon, Apr 14, 2025 at 11:50:09AM +0800, Liu Ying wrote:
> > > > Hi,
> > > >
> > > > This patch series aims to add Freescale i.MX8qxp Display Controller support.
> > > >
> > > > The controller is comprised of three main components that include a blit
> > > > engine for 2D graphics accelerations, display controller for display output
> > > > processing, as well as a command sequencer.
> > >
> > > ...
> > >
> > > >
> > > > To follow up i.MX8qxp TRM, I changed the controller name to "Display Controller"
> > > > instead of the previous "DPU". "DPU" is only mentioned in the SoC block
> > > > diagram and represents the whole display subsystem which includes the display
> > > > controller and prefech engines, etc.
> > > >
> > > > With an additional patch[1] for simple-pm-bus.c, this series facilitates
> > > > testing a LVDS panel on i.MX8qxp MEK.
> > > >
> > > > Please do NOT merge patch 14-19. They are only used to facilitate testing
> > > > the LVDS panel.
> > >
> > > What's the plan to conclude this work? What's the latest status?
> > > I am looking forward to have a way to use the i.MX8QXP display with
> > > mainline, but to my understanding some required changes on the SOC dtsi
> > > are not merged.
> > >
> > > Can you help?
> >
> > I planned to add display controller DT node after prefetch engine support [1]
> > is picked up so that the prefetch engine could be enabled together with the
> > display controller. Just want to avoid a DT that only enables the display
> > controller or bypasses the prefetch engine. It makes the display controller
> > driver simpler.
> >
> > [1] https://lore.kernel.org/all/20251027-imx8-dc-prefetch-v5-0-4ecb6c6d4941@nxp.com/
>
> That series is from October 2025, is there anything blocking to move it
> forward?
It lacks a Reviewed-by tag(at least a Acked-by tag) from a drm-misc committer
for every driver patch in that series. Also, it seems that Marek(Cc'ed) is
not a big fan of [1](See i.MX95 display support discussion[2]).
[2] https://lore.kernel.org/dri-devel/aiZzxhljfyYQ68Gl@raspi/
>
> Francesco
>
>
> --
> linux-phy mailing list
> linux-phy@lists.infradead.org
> https://lists.infradead.org/mailman/listinfo/linux-phy
--
Regards,
Liu Ying
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 00/19] Add Freescale i.MX8qxp Display Controller support
From: Francesco Dolcini @ 2026-07-16 6:26 UTC (permalink / raw)
To: Liu Ying
Cc: Francesco Dolcini, dri-devel, devicetree, imx, linux-arm-kernel,
linux-kernel, linux-phy, p.zabel, airlied, simona,
maarten.lankhorst, mripard, tzimmermann, robh, krzk+dt, conor+dt,
shawnguo, s.hauer, kernel, festevam, tglx, vkoul, kishon,
Frank.Li, lumag, aisheng.dong, agx, u.kleine-koenig,
dmitry.baryshkov
In-Reply-To: <alh4a66fEro05ShA@raspi>
On Thu, Jul 16, 2026 at 02:21:31PM +0800, Liu Ying wrote:
> On Tue, Jul 14, 2026 at 09:36:27PM +0200, Francesco Dolcini wrote:
> > On Mon, Apr 14, 2025 at 11:50:09AM +0800, Liu Ying wrote:
> > > Hi,
> > >
> > > This patch series aims to add Freescale i.MX8qxp Display Controller support.
> > >
> > > The controller is comprised of three main components that include a blit
> > > engine for 2D graphics accelerations, display controller for display output
> > > processing, as well as a command sequencer.
> >
> > ...
> >
> > >
> > > To follow up i.MX8qxp TRM, I changed the controller name to "Display Controller"
> > > instead of the previous "DPU". "DPU" is only mentioned in the SoC block
> > > diagram and represents the whole display subsystem which includes the display
> > > controller and prefech engines, etc.
> > >
> > > With an additional patch[1] for simple-pm-bus.c, this series facilitates
> > > testing a LVDS panel on i.MX8qxp MEK.
> > >
> > > Please do NOT merge patch 14-19. They are only used to facilitate testing
> > > the LVDS panel.
> >
> > What's the plan to conclude this work? What's the latest status?
> > I am looking forward to have a way to use the i.MX8QXP display with
> > mainline, but to my understanding some required changes on the SOC dtsi
> > are not merged.
> >
> > Can you help?
>
> I planned to add display controller DT node after prefetch engine support [1]
> is picked up so that the prefetch engine could be enabled together with the
> display controller. Just want to avoid a DT that only enables the display
> controller or bypasses the prefetch engine. It makes the display controller
> driver simpler.
>
> [1] https://lore.kernel.org/all/20251027-imx8-dc-prefetch-v5-0-4ecb6c6d4941@nxp.com/
That series is from October 2025, is there anything blocking to move it
forward?
Francesco
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v9 00/19] Add Freescale i.MX8qxp Display Controller support
From: Liu Ying @ 2026-07-16 6:21 UTC (permalink / raw)
To: Francesco Dolcini
Cc: dri-devel, devicetree, imx, linux-arm-kernel, linux-kernel,
linux-phy, p.zabel, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, shawnguo, s.hauer, kernel,
festevam, tglx, vkoul, kishon, Frank.Li, lumag, aisheng.dong, agx,
u.kleine-koenig, dmitry.baryshkov
In-Reply-To: <20260714193627.GA9616@francesco-nb>
On Tue, Jul 14, 2026 at 09:36:27PM +0200, Francesco Dolcini wrote:
> Hello Liu,
Hello Francesco,
>
> On Mon, Apr 14, 2025 at 11:50:09AM +0800, Liu Ying wrote:
> > Hi,
> >
> > This patch series aims to add Freescale i.MX8qxp Display Controller support.
> >
> > The controller is comprised of three main components that include a blit
> > engine for 2D graphics accelerations, display controller for display output
> > processing, as well as a command sequencer.
>
> ...
>
> >
> > To follow up i.MX8qxp TRM, I changed the controller name to "Display Controller"
> > instead of the previous "DPU". "DPU" is only mentioned in the SoC block
> > diagram and represents the whole display subsystem which includes the display
> > controller and prefech engines, etc.
> >
> > With an additional patch[1] for simple-pm-bus.c, this series facilitates
> > testing a LVDS panel on i.MX8qxp MEK.
> >
> > Please do NOT merge patch 14-19. They are only used to facilitate testing
> > the LVDS panel.
>
> What's the plan to conclude this work? What's the latest status?
> I am looking forward to have a way to use the i.MX8QXP display with
> mainline, but to my understanding some required changes on the SOC dtsi
> are not merged.
>
> Can you help?
I planned to add display controller DT node after prefetch engine support [1]
is picked up so that the prefetch engine could be enabled together with the
display controller. Just want to avoid a DT that only enables the display
controller or bypasses the prefetch engine. It makes the display controller
driver simpler.
[1] https://lore.kernel.org/all/20251027-imx8-dc-prefetch-v5-0-4ecb6c6d4941@nxp.com/
>
> Thanks,
> Francesco
>
--
Regards,
Liu Ying
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v13 00/35] phy: rockchip: usbdp: Clean up the mess
From: Frank Wang @ 2026-07-16 2:50 UTC (permalink / raw)
To: Sebastian Reichel, Andy Yan, William Wu, Heiko Stuebner,
Vinod Koul, Neil Armstrong, Thinh Nguyen
Cc: Greg Kroah-Hartman, Dmitry Baryshkov, Yubing Zhang,
Alexey Charkov, linux-arm-kernel, linux-rockchip, linux-kernel,
kernel, devicetree, Sashiko, linux-usb, linux-phy, wmc
In-Reply-To: <alfM6dFBovHMaYn2@venus>
Hi Sebastian,
On 2026/7/16 2:24, Sebastian Reichel wrote:
> Hi,
>
> I've gone through the Sashiko feedback for v13 and I do not plan
> to submit a v14 for Sashiko feedback at this point. The issues
> it reported in v13 are either fixed in later patches - especially
> all those "pre-existing problems" - or do not apply.
>
> The series fixes a massive amount of problems in the USBDP driver
> and unblocks USB-C DP AltMode at the same point. It would be good if
> we get this into 7.3, so that the DRM series is unblocked for 7.4
> allowing users to have USB-C DP AltMode in 2027.
>
One thought I had was whether you've considered splitting this patch series into several smaller, targeted series, for
instance, one covering code optimizations, and separate series for distinct groups of bug fixes. This would keep each
series lean and easier for maintainers to review.
> My proposed merge strategy is to route everything through the PHY
> subsystem as the changes in the DWC3 driver are not very complex
> (purely additions), so a merge conflict should be easy to solve.
>
On the dwc3 core changes, based on Rockchip's internal testing and experience, runtime suspend does not kick in as
intended during hotplug events. The dwc3 core uses a default autosuspend delay of 5 seconds (defined as
DWC3_DEFAULT_AUTOSUSPEND_DELAY). I think we can try to make this parameter configurable via device tree properties, as
this approach would result in a smaller, less invasive change overall.
Best regards,
Frank
> Greetings,
>
> -- Sebastian
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v13 29/35] usb: dwc3: core: support PHY reset notifications
From: Thinh Nguyen @ 2026-07-16 0:38 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel, Andy Yan, Dmitry Baryshkov,
Yubing Zhang, Alexey Charkov, linux-phy@lists.infradead.org,
linux-arm-kernel@lists.infradead.org,
linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, devicetree@vger.kernel.org,
linux-usb@vger.kernel.org
In-Reply-To: <20260714-rockchip-usbdp-cleanup-v13-29-6cb3e769d4c5@collabora.com>
On Tue, Jul 14, 2026, Sebastian Reichel wrote:
> On recent Rockchip platforms (at least RK3588 & RK3576), DWC3 IP is used
> with a USBDP PHY providing USB3 and DP. This PHY needs to be reset when
> the mode changes, which may happen when plugging in different USB-C
> devices.
>
> If the USBDP PHY resets with the DWC3 IP running, its internal state
> corrupts resulting in the USBDP PHY not being able to lock some PLL
> clocks, which effectively renders USB3 unusable.
>
> To fix the issue this adds handling for the new PHY framework reset
> notifications, which will assert PHYSOFTRST before the actual PHY
> is disabled and will deassert it once the PHY returns.
>
> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
> ---
> drivers/usb/dwc3/core.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/usb/dwc3/core.h | 18 +++++++++
> 2 files changed, 119 insertions(+)
>
These changes should not be in the core. This is specific to Rockchip
and not every phy needs this. Perhaps you can create a new glue driver
for this.
Thanks,
Thinh
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [RFC PATCH 07/10] net: pcs: xpcs: add Rockchip RK3568 platform glue driver
From: Coia Prant @ 2026-07-15 23:01 UTC (permalink / raw)
To: Andrew Lunn
Cc: Maxime Chevallier, kuba, davem, edumazet, pabeni, andrew+netdev,
robh, krzk+dt, heiko, netdev, linux-rockchip, devicetree,
linux-arm-kernel, linux-phy
In-Reply-To: <039c2cce-e76e-4321-ba4a-cd80801f136e@lunn.ch>
Andrew Lunn <andrew@lunn.ch> 于2026年7月16日周四 06:25写道:
>
> > The current design
> > ==================
> > The dependency chain I chose is simple:
> >
> > stmmac (GMAC) -> pcs-handle -> XPCS node -> phys -> SerDes PHY
>
> Maybe we need to be more accurate here.
>
> In QSGMII I _think_ it is actually
>
> stmmac (GMAC) -> pcs-handle -> XPCS node -\
> stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
> stmmac (GMAC) -> pcs-handle -> XPCS node -/ /
> stmmac (GMAC) -> pcs-handle -> XPCS node --/
>
> There are four instances of stmmac, four instances of the XPCS, which
> then all come together into one PHY.
>
> When using SGMII, does it look like this ?
>
> stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
> stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
> stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
> stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
>
> There are four of everything, all working independently.
>
> Is there 1 QSGMII PHY and 4 SGMII PHYs? Or does one of the 4 phys
> support SGMII + QSGMII, while 3 are SGMII only?
>
> > 2. User misconfiguration: even with reference counting, if a user sets
> > `phys = <&combphy2 PHY_TYPE_SGMII>` for GMAC0 and
> > `phys = <&combphy2 PHY_TYPE_QSGMII>` for GMAC1, the same PHY would
> > be initialized in two different modes.
>
> I would hope that results in -EINVAL.
>
> Andrew
Hi Andrew,
Thanks for the follow-up. I've dug through Rockchip's BSP and found the
exact device tree configurations they use for their EVBs, which I think
clears up the topology question.
For reference, here are the relevant BSP device tree files:
- QSGMII: https://github.com/armbian/linux-rockchip/blob/rk-6.1-rkr6.1/arch/arm64/boot/dts/rockchip/rk3568-evb2-lp4x-v10.dtsi#L185
- SGMII: https://github.com/armbian/linux-rockchip/blob/rk-6.1-rkr6.1/arch/arm64/boot/dts/rockchip/rk3568-evb5-ddr4-v10.dtsi#L208
Hardware topology confirmed
===========================
The BSP shows that for RK3568, the hardware is indeed a shared resource.
One important clarification: the XPCS block has four logical entities
(corresponding to the four MII ports, pcs-mii@0..3). In my driver, these
are all attached to the same MDIO bus and distinguished by address.
To clarify the PHY topology: there is only one physical SerDes PHY on
RK3568 (combphy1_usq). In QSGMII mode, this single PHY provides four
logical ports via time-division multiplexing. In the device tree, all
four ports are attached to the same MDIO bus and distinguished by
address (pcs-mii@0..3).
So it's not "4 PHYs" but "1 PHY with 4 logical ports", all accessible
through the same MDIO bus with different address. The BSP EVB2
configuration confirms this:
both gmac0 and gmac1 reference the same combphy1_usq with
PHY_TYPE_QSGMII.
To clarify the difference between SGMII and QSGMII:
- SGMII is a single serial link at 1.25 Gbaud, providing one Gigabit port.
- QSGMII is a 5 Gbaud SerDes protocol that multiplexes four SGMII links
onto the same physical lanes.
So for RK3568: one PHY for SGMII, or one PHY for QSGMII (both GMACs share
the same PHY, each using a dedicated logical port).
For SGMII mode, only one of these ports can be used at a time, and only
one GMAC can use the SGMII link. The BSP EVB5 configuration shows this
clearly: gmac0 uses SGMII, while gmac1 falls back to RGMII.
For QSGMII mode, the BSP EVB2 configuration shows both gmac0 and gmac1
configured with phy-mode = "qsgmii", both referencing the same combphy1_usq
as their phys. This confirms your diagram: multiple MACs converge on a
single SerDes PHY via the XPCS, with the four logical ports time-division
multiplexed onto the single PHY.
Why this matters for the design
===============================
This BSP evidence supports my current design where the XPCS node owns
the SerDes PHY:
1. It matches the hardware: the XPCS is the central multiplexer.
Placing the PHY under the XPCS node in the device tree accurately
reflects this hardware reality.
2. It's the only viable path for QSGMII: as the BSP shows, QSGMII
requires multiple MACs to share one PHY. If the PHY were owned by the
MAC driver (dwmac-rk), we'd need complex refcounting and cross-MAC
coordination. The XPCS-owner model solves this cleanly by making the
XPCS the single point of control.
3. It aligns with the BSP's own logic: even though the BSP uses a
non-standard property (rockchip,xpcs), the underlying idea is the
same: the MACs point to a shared XPCS node, which then manages the
PHY. My design just does this using the standard kernel frameworks.
So, I believe the current design is correct. It's based on the hardware
reality confirmed by Rockchip's own BSP, and it uses the standard kernel
interfaces to do so. I'm happy to keep the XPCS as the owner of the
SerDes PHY in v2 if you agree.
Thanks,
Coia
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [RFC PATCH 07/10] net: pcs: xpcs: add Rockchip RK3568 platform glue driver
From: Andrew Lunn @ 2026-07-15 22:25 UTC (permalink / raw)
To: Coia Prant
Cc: Maxime Chevallier, kuba, davem, edumazet, pabeni, andrew+netdev,
robh, krzk+dt, heiko, netdev, linux-rockchip, devicetree,
linux-arm-kernel, linux-phy
In-Reply-To: <CALj3r0gBnyEVwo3rK-dKssYN9F4nFn93QJ24FVv8YBLjNNgPmg@mail.gmail.com>
> The current design
> ==================
> The dependency chain I chose is simple:
>
> stmmac (GMAC) -> pcs-handle -> XPCS node -> phys -> SerDes PHY
Maybe we need to be more accurate here.
In QSGMII I _think_ it is actually
stmmac (GMAC) -> pcs-handle -> XPCS node -\
stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
stmmac (GMAC) -> pcs-handle -> XPCS node -/ /
stmmac (GMAC) -> pcs-handle -> XPCS node --/
There are four instances of stmmac, four instances of the XPCS, which
then all come together into one PHY.
When using SGMII, does it look like this ?
stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
stmmac (GMAC) -> pcs-handle -> XPCS node -------> phys -> SerDes PHY
There are four of everything, all working independently.
Is there 1 QSGMII PHY and 4 SGMII PHYs? Or does one of the 4 phys
support SGMII + QSGMII, while 3 are SGMII only?
> 2. User misconfiguration: even with reference counting, if a user sets
> `phys = <&combphy2 PHY_TYPE_SGMII>` for GMAC0 and
> `phys = <&combphy2 PHY_TYPE_QSGMII>` for GMAC1, the same PHY would
> be initialized in two different modes.
I would hope that results in -EINVAL.
Andrew
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [RFC PATCH 07/10] net: pcs: xpcs: add Rockchip RK3568 platform glue driver
From: Coia Prant @ 2026-07-15 22:04 UTC (permalink / raw)
To: sashiko-reviews
Cc: vkoul, neil.armstrong, linux-phy, conor+dt, devicetree, robh,
olteanv
In-Reply-To: <20260715191454.D12521F00AC4@smtp.kernel.org>
> [Severity: Low]
> Does this change cause build failures when CONFIG_PCS_XPCS=m?
>
> Replacing the composite module assignment (pcs_xpcs-y) with individual
> object assignments causes Kbuild to build separate modules instead of one
> composite module, which can lead to undefined references during modpost.
>
> > +obj-$(CONFIG_PCS_XPCS_PLATFORM) += pcs-xpcs-plat.o
> > +obj-$(CONFIG_PCS_XPCS_ROCKCHIP) += pcs-xpcs-rk.o
No. This change is intentional. pcs-xpcs-rk is a platform-specific
driver and should be built as a separate module, not linked into
the composite pcs_xpcs module. There are no undefined references.
> [ ... ]
>
> > diff --git a/drivers/net/pcs/pcs-xpcs-rk.c b/drivers/net/pcs/pcs-xpcs-rk.c
> > new file mode 100644
> > index 0000000000000..ed969a38d544d
> > --- /dev/null
> > +++ b/drivers/net/pcs/pcs-xpcs-rk.c
> [ ... ]
> > +static int xpcs_rk_mdio_read_remapping(int addr, int dev, int reg)
> > +{
> > + switch (dev) {
> > + case MDIO_MMD_PMAPMD:
> > + return ROCKCHIP_MMD_PMAPMD;
> > + case MDIO_MMD_VEND2:
> > + break;
> > + default:
> > + return -ENXIO;
> > + }
> > +
> > + switch (addr) {
> > + case 0:
> > + return ROCKCHIP_MMD_MII;
> > + case 1:
> > + return ROCKCHIP_MMD_MII1;
> [ ... ]
> > +static int xpcs_rk_mdio_write_remapping(int addr, int dev, int reg)
> > +{
> > + switch (dev) {
> > + case MDIO_MMD_PMAPMD:
> > + return ROCKCHIP_MMD_PMAPMD;
> > + case MDIO_MMD_VEND2:
> > + break;
> > + default:
> > + return -ENXIO;
> > + }
> > +
> > + /* Writable only on MII */
> > + switch (reg) {
> > + case DW_VR_MII_AN_CTRL:
> > + case DW_VR_MII_AN_INTR_STS:
> > + case DW_VR_MII_EEE_MCTRL0:
> > + case DW_VR_MII_EEE_MCTRL1:
> > + case DW_VR_MII_DIG_CTRL2:
> > + return ROCKCHIP_MMD_MII;
> > + default:
> > + break;
> > + }
>
> [Severity: High]
> Can this asymmetric remapping between reads and writes cause configuration
> corruption on port 0?
>
> In xpcs_rk_mdio_write_remapping(), writes to these VEND2 registers are
> unconditionally mapped to ROCKCHIP_MMD_MII (port 0). However,
> xpcs_rk_mdio_read_remapping() lacks an equivalent redirect for reads.
>
> Because the generic XPCS driver uses read-modify-write operations on VEND2
> control registers for ports 1-3, this will result in reading from the target
> port's MMD but overwriting port 0's configuration.
No. Read remapping is performed by hardware. The VEND2 registers
reflect the settings of MII0; the corresponding bits for MII1-3 are
read-only. This is a hardware feature, not a bug.
> [ ... ]
>
> > +static int xpcs_rk_init_clk(struct dw_xpcs_rk *pxpcs)
> > +{
> > + struct device *dev = &pxpcs->pdev->dev;
> > + int ret;
> > +
> > + pxpcs->csr_clk = devm_clk_get(dev, "csr");
> > + if (IS_ERR(pxpcs->csr_clk))
> > + return dev_err_probe(dev, PTR_ERR(pxpcs->csr_clk),
> > + "Failed to get CSR clock\n");
> > +
> > + pm_runtime_set_suspended(dev);
> > + ret = devm_pm_runtime_enable(dev);
>
> [Severity: Medium]
> Will this leak the csr_clk if the device is removed while active?
>
> The generic devm_pm_runtime_enable() runs pm_runtime_disable() on cleanup,
> which cancels pending suspends but does not synchronously suspend an active
> device.
>
> Since this driver lacks a .remove callback to manually suspend the device,
> xpcs_rk_pm_runtime_suspend() might never be invoked on unbind, leaving the
> clock prepare and enable counts unbalanced.
You are correct. I followed the same pattern as pcs-xpcs-plat.c,
but I agree this could be a problem. I will add a .remove callback
in v2 that calls pm_runtime_force_suspend() before devres cleanup
runs, ensuring the clock enable count is balanced before clk_put().
> [Severity: Medium]
> Could this blind cast lead to type confusion?
>
> The code extracts driver data from the platform device associated with
> pcs_np without validating if the device is actually compatible with
> rockchip,rk3568-xpcs or bound to this driver.
>
> If a misconfigured device tree points to a different type of device (like
> an I2C controller), casting its drvdata to struct dw_xpcs_rk * and
> dereferencing it could crash the system.
This would only happen with a misconfigured device tree. However,
for robustness, I will add a compatible string check in v2 before
dereferencing drvdata.
> [Severity: High]
> Is there a use-after-free race condition when accessing drvdata here?
>
> This checks and dereferences pxpcs->bus before establishing a device link
> to lock the supplier.
>
> If a user concurrently unbinds the XPCS supplier driver (for example, via
> sysfs), devres will free the dw_xpcs_rk structure and clear the drvdata.
> The consumer driver might then dereference the freed pxpcs->bus before
> device_link_add() is called.
No. of_find_device_by_node() increments the reference count of the
device. The supplier cannot be unbound between of_find_device_by_node()
and put_device() because the reference count is held.
> [ ... ]
>
> > +static struct platform_driver xpcs_rk_driver = {
> > + .probe = xpcs_rk_probe,
> > + .driver = {
> > + .name = "rk_xpcs-dwxpcs",
> > + .pm = &xpcs_rk_pm_ops,
>
> [Severity: Low]
> Will this assignment cause dead code when CONFIG_PM is disabled?
>
> Assigning the dev_pm_ops structure unconditionally to the .pm field without
> the pm_ptr() wrapper results in dead code and possible compiler warnings
> when CONFIG_PM is not set, which violates the PM subsystem guidelines.
You are correct. I will use pm_ptr() to wrap the PM ops in v2.
Thanks,
Coia
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [RFC PATCH 01/10] net: stmmac: move XPCS lifetime management to platform drivers
From: Coia Prant @ 2026-07-15 21:39 UTC (permalink / raw)
To: Andrew Lunn
Cc: Maxime Chevallier, kuba, davem, edumazet, pabeni, andrew+netdev,
robh, krzk+dt, heiko, netdev, linux-rockchip, devicetree,
linux-arm-kernel, linux-phy, Christian Marangi
In-Reply-To: <685d91a3-be6f-42c6-9e23-07629e21bcee@lunn.ch>
Andrew Lunn <andrew@lunn.ch> 于2026年7月16日周四 03:57写道:
>
> > I actually spent all night debugging call traces caused by the current
> > stmmac PCS lifetime management, and it was not a pleasant experience.
> > The code feels like accumulated technical debt that should be cleaned
> > up.
>
> Russell King will strongly agree with you, if he was around. The
> phylink integration into stmmac causes a lot of pain, and he wanted to
> rip it all out and start again. But doing that without breaking stuff
> is going to be interesting.
>
> If you feel up to it, have a go. But take a good look around first,
> make sure you understand the different variant, internal vs external
> PCS.
>
> Andrew
Hi Andrew,
Thanks for sharing this. It's reassuring to know that I'm not alone in
finding this code painful.
I fully agree that ripping it out and starting over would be a huge
undertaking, and I'm definitely not confident enough to take that on
right now - especially given the risk of breaking existing platforms.
My current focus is on getting this RK3568 SGMII support into a
mergeable state, rather than attempting a full redesign of the
stmmac PCS layer.
That said, I'll keep this in mind. Once my current series lands and I
have a better understanding of the different PCS variants, maybe I'll
be in a better position to contribute to that long-term effort.
For now, I'll stick to the incremental fix that this series provides.
Thanks,
Coia
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [RFC PATCH 07/10] net: pcs: xpcs: add Rockchip RK3568 platform glue driver
From: Coia Prant @ 2026-07-15 21:23 UTC (permalink / raw)
To: Andrew Lunn
Cc: Maxime Chevallier, kuba, davem, edumazet, pabeni, andrew+netdev,
robh, krzk+dt, heiko, netdev, linux-rockchip, devicetree,
linux-arm-kernel, linux-phy
In-Reply-To: <1d92078f-3009-43d1-a228-c3e67a1f4f4c@lunn.ch>
Andrew Lunn <andrew@lunn.ch> 于2026年7月16日周四 03:57写道:
>
> > This is intentional. The SerDes is attached to the XPCS node because
> > on RK3568, a single SerDes serves all four XPCS MII ports in QSGMII
> > mode.
>
> This is not the only device supporting QSGMII, and so the issues you
> are addressing should be common to many QSGMII implementations.
>
> Please take a step back. What would a generic solution look like?
>
> Can the reference counting be placed into the core somewhere? The
> common clock framework allows a clock to be enabled and disabled by
> multiple consumers, and the core clock code does the reference
> counting, only calling into the clock driver when state change is
> actually needed. Maybe the generic PHY core needs something similar?
>
> Andrew
On Thu, Jul 16, 2026 at 03:57:22AM +0200, Andrew Lunn wrote:
> > This is intentional. The SerDes is attached to the XPCS node because
> > on RK3568, a single SerDes serves all four XPCS MII ports in QSGMII
> > mode.
>
> This is not the only device supporting QSGMII, and so the issues you
> are addressing should be common to many QSGMII implementations.
>
> Please take a step back. What would a generic solution look like?
>
> Can the reference counting be placed into the core somewhere? The
> common clock framework allows a clock to be enabled and disabled by
> multiple consumers, and the core clock code does the reference
> counting, only calling into the clock driver when state change is
> actually needed. Maybe the generic PHY core needs something similar?
Hi Andrew,
Thanks for the thoughtful question. Let me walk through the design
constraints on RK3568 and explain why I chose the current approach.
First, I want to emphasize that this is still RFC, so the binding is not
frozen. However, DT is ABI once merged, and changing it later is painful
and often requires maintaining compatibility with old bindings. So I
would like to be careful about the architecture we settle on.
The current design
==================
The dependency chain I chose is simple:
stmmac (GMAC) -> pcs-handle -> XPCS node -> phys -> SerDes PHY
The XPCS driver is the single owner of both the SerDes PHY and the
power domain. The MAC driver doesn't need to know about them at all.
On RK3568, phy_power_on() is effectively a no-op for the Combo PHY in
SGMII mode; only phy_init() is required. So the PHY is not a
power-controlled resource — it's just a one-time initialization.
Power domain management is handled via PM runtime:
- XPCS probe: dev_pm_genpd_rpm_always_on() ensures PD_PIPE is powered
(this allows us to use PM to manage csr_clk)
- Each register access: pm_runtime_resume_and_get()/put() controls
the CSR clock
This is the simplest model that works for SGMII/QSGMII today.
Why not move SerDes to stmmac?
==============================
If we move SerDes and power domain control to the MAC driver, we
run into several problems:
1. Reference counting for phy_init()/phy_exit(): in QSGMII mode, four
MACs would all call phy_init() on the same hardware. The generic PHY
core does not currently provide reference counting for these calls.
Adding it would be a larger change affecting all PHY users.
2. User misconfiguration: even with reference counting, if a user sets
`phys = <&combphy2 PHY_TYPE_SGMII>` for GMAC0 and
`phys = <&combphy2 PHY_TYPE_QSGMII>` for GMAC1, the same PHY would
be initialized in two different modes.
3. The stmmac SerDes callbacks are legacy: the existing
serdes_poweron/serdes_powerdown hooks are called from
stmmac_legacy_serdes_power_on/down functions. They are marked as
legacy and not intended for new hardware designs. Building new
support on top of legacy APIs seems like the wrong direction.
Current QSGMII usage on RK3568
===============================
I searched OpenWrt, Armbian, ImmortalWrt, and GitHub for any actual
device using "rockchip,rk3568-xpcs" with QSGMII and found none. It seems
QSGMII on RK3568 is limited to specialized evaluation boards or niche
industrial applications. Even SGMII users are rare — most boards use
RGMII simply because the pins cannot be repurposed.
If QSGMII does become a real requirement in the future, the generic PHY
core could be extended with reference counting for phy_init()/phy_exit().
That would be a cleaner solution than pushing SerDes management into each
MAC driver, and would benefit all platforms with shared SerDes resources.
That said, I had an earlier test with serdes_poweron/serdes_powerdown
callbacks in stmmac, so if the community strongly prefers to move
SerDes control to dwmac-rk, I can do that in v2.
But my preference is to keep the current design: XPCS as the single
owner of the SerDes and power domain. It works today, keeps the DT
binding stable for future QSGMII, and avoids complexity.
Do you think the generic PHY core should grow reference counting for
phy_init()/phy_exit()? Or would you prefer to see a more generic
abstraction for shared SerDes resources?
Thanks,
Coia
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [RFC PATCH 08/10] net: stmmac: dwmac-rk: add SGMII support for RK3568
From: Coia Prant @ 2026-07-15 20:33 UTC (permalink / raw)
To: sashiko-reviews
Cc: robh, devicetree, neil.armstrong, olteanv, linux-phy, vkoul,
conor+dt
In-Reply-To: <20260715191455.D033A1F00ACA@smtp.kernel.org>
> [ ... ]
> > @@ -1379,6 +1441,9 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
> > if (ret)
> > return ret;
> >
> > + if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_SGMII)
> > + goto set_mode;
> > +
>
> [Severity: High]
> Does this goto skip enabling the MAC clocks? By jumping directly to set_mode,
> we bypass the call to gmac_clk_enable() further down in this function.
>
> Can this cause a synchronous external abort when the MAC registers are accessed
> subsequently while their clock domain remains disabled?
You are correct. The original RFC patch had this issue: the SGMII path
bypassed `gmac_clk_enable()` via the `goto set_mode`, which could lead
to hardware faults when accessing MAC registers with the clock disabled.
This has been fixed in the updated version of the patch. The clock enable
is now moved before the SGMII check:
ret = gmac_clk_enable(bsp_priv, true);
if (ret)
return ret;
if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_SGMII)
goto set_mode;
So the clocks are always enabled before any register access, regardless of
the interface mode.
The error handling has also been cleaned up with a unified `clk_disable`
label, and the default (unhandled interface) case now properly returns an
error and disables the clocks.
Regarding stable backport: this issue does not exist in the 6.18
kernel that I am using for backport testing, as the code structure in
`rk_gmac_powerup()` is significantly different there. The fix only
affects the mainline version of the patch.
Thanks,
Coia
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox