* Re: [PATCH phy-next 01/13] dt-bindings: phy: lynx-10g: initial document
From: Rob Herring (Arm) @ 2026-06-05 19:04 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Conor Dooley, linux-kernel, Krzysztof Kozlowski, Tanjeff Moos,
linux-phy, Neil Armstrong, devicetree, Ioana Ciornei, Vinod Koul
In-Reply-To: <20260528172404.733196-2-vladimir.oltean@nxp.com>
On Thu, 28 May 2026 20:23:52 +0300, Vladimir Oltean wrote:
> Add a schema for the 10G Lynx SerDes. This is very similar to the modern
> form of the 28G Lynx SerDes, which is very much the intention.
>
> We allow both forms of #phy-cells = <1> in the top-level provider
> and #phy-cells = <0> in the per-lane provider for more flexibility to
> consumers, and because the kernel code is shared with the 28G Lynx which
> already has that support for compatibility reasons.
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
> Cc: devicetree@vger.kernel.org
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> Cc: Rob Herring <robh@kernel.org>
> ---
> .../devicetree/bindings/phy/fsl,lynx-10g.yaml | 131 ++++++++++++++++++
> 1 file changed, 131 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v4 5/5] phy: fsl-imx8mq-usb: keep PHY power domain runtime always-on for i.MX8MP
From: Frank Li @ 2026-06-05 15:30 UTC (permalink / raw)
To: Xu Yang
Cc: Vinod Koul, Neil Armstrong, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Jun Li, linux-phy, imx, linux-arm-kernel,
linux-kernel, Xu Yang
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-5-b2ddf2f3862c@nxp.com>
On Fri, Jun 05, 2026 at 07:13:06PM +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.
Does it need depend on if device enable wakeup?
Frank
>
> 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
> new imx95_usb_phy_ops for i.MX95 and introduce usb_phy_is_imx8mp() helper
> to identify i.MX8MP PHY instance.
>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
>
> ---
> Changes in v4:
> - no changes
> Changes in v3:
> - new patch
> ---
> drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> index e24f46d7924b..c8b93ae2035f 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>
> @@ -660,13 +661,20 @@ static const struct phy_ops imx8mp_usb_phy_ops = {
> .owner = THIS_MODULE,
> };
>
> +static const struct phy_ops imx95_usb_phy_ops = {
> + .init = imx8mp_usb_phy_init,
> + .power_on = imx8mq_phy_power_on,
> + .power_off = imx8mq_phy_power_off,
> + .owner = THIS_MODULE,
> +};
> +
> static const struct of_device_id imx8mq_usb_phy_of_match[] = {
> {.compatible = "fsl,imx8mq-usb-phy",
> .data = &imx8mq_usb_phy_ops,},
> {.compatible = "fsl,imx8mp-usb-phy",
> .data = &imx8mp_usb_phy_ops,},
> {.compatible = "fsl,imx95-usb-phy",
> - .data = &imx8mp_usb_phy_ops,},
> + .data = &imx95_usb_phy_ops,},
> { }
> };
> MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match);
> @@ -679,6 +687,11 @@ static const struct regmap_config imx_cr_regmap_config = {
> .max_register = 0x7,
> };
>
> +static bool usb_phy_is_imx8mp(const void *data)
> +{
> + return data == &imx8mp_usb_phy_ops;
> +}
> +
> static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> {
> struct phy_provider *phy_provider;
> @@ -723,6 +736,9 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> if (!phy_ops)
> return -EINVAL;
>
> + if (usb_phy_is_imx8mp(phy_ops))
> + dev_pm_genpd_rpm_always_on(dev, true);
> +
> imx_phy->phy = devm_phy_create(dev, NULL, phy_ops);
> if (IS_ERR(imx_phy->phy))
> return PTR_ERR(imx_phy->phy);
>
> --
> 2.34.1
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v4 4/5] phy: fsl-imx8mq-usb: add control register regmap
From: Frank Li @ 2026-06-05 15:28 UTC (permalink / raw)
To: Xu Yang
Cc: Vinod Koul, Neil Armstrong, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Jun Li, linux-phy, imx, linux-arm-kernel,
linux-kernel, Xu Yang
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-4-b2ddf2f3862c@nxp.com>
On Fri, Jun 05, 2026 at 07:13:05PM +0800, Xu Yang wrote:
> From: Xu Yang <xu.yang_2@nxp.com>
>
> The CR port is a simple 16-bit data/address parallel port that is
> accessed through 32-bit MMIO registers for on-chip access to the
> control registers inside the USB 3.0 femtoPHY. Add control register
> regmap and export these registers by debugfs to help PHY's diagnostic.
>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> ---
> Changes in v4:
> - improve commit message as Haibo's suggestion
> Changes in v3:
> - drop Frank's tag because it includes other changes
> - new patch
> ---
> drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 27 ++++++++++++++++++++++++++-
> 1 file changed, 26 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> index 27aa696f5dd4..e24f46d7924b 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> @@ -1,5 +1,5 @@
> // SPDX-License-Identifier: GPL-2.0+
> -/* Copyright (c) 2017 NXP. */
> +/* Copyright 2017-2026 NXP. */
>
> #include <linux/bitfield.h>
> #include <linux/clk.h>
> @@ -11,6 +11,7 @@
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> #include <linux/regulator/consumer.h>
> +#include <linux/regmap.h>
> #include <linux/usb/typec_mux.h>
>
> #define PHY_CTRL0 0x0
> @@ -56,6 +57,8 @@
> #define PHY_CTRL6_ALT_CLK_EN BIT(1)
> #define PHY_CTRL6_ALT_CLK_SEL BIT(0)
>
> +#define PHY_CRCTL 0x30
> +
> #define PHY_TUNE_DEFAULT 0xffffffff
>
> #define TCA_CLK_RST 0x00
> @@ -119,6 +122,7 @@ struct imx8mq_usb_phy {
> void __iomem *base;
> struct regulator *vbus;
> struct tca_blk *tca;
> + struct regmap *cr_regmap;
> u32 pcs_tx_swing_full;
> u32 pcs_tx_deemph_3p5db;
> u32 tx_vref_tune;
> @@ -667,6 +671,14 @@ static const struct of_device_id imx8mq_usb_phy_of_match[] = {
> };
> MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match);
>
> +static const struct regmap_config imx_cr_regmap_config = {
> + .name = "cr",
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x7,
> +};
> +
> static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> {
> struct phy_provider *phy_provider;
> @@ -696,6 +708,13 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> if (IS_ERR(imx_phy->base))
> return PTR_ERR(imx_phy->base);
>
> + imx_phy->cr_regmap = devm_regmap_init_mmio(dev, imx_phy->base + PHY_CRCTL,
> + &imx_cr_regmap_config);
> + if (IS_ERR(imx_phy->cr_regmap)) {
> + dev_warn(dev, "Fail to init debug register regmap\n");
> + imx_phy->cr_regmap = NULL;
> + }
> +
> ret = devm_pm_runtime_set_active_enabled(dev);
> if (ret)
> return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
> @@ -731,6 +750,9 @@ static int imx8mq_usb_phy_runtime_suspend(struct device *dev)
> {
> struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
>
> + if (imx_phy->cr_regmap)
> + regcache_cache_only(imx_phy->cr_regmap, true);
> +
I think this common problem, is possible to change
regmap_read_debugfs(), let it call runtime_pm_get(), there are already
have runtime_pm in regmap field.
So you debug fs always to get update value, instead cached value?
Frank
> clk_disable_unprepare(imx_phy->alt_clk);
> clk_disable_unprepare(imx_phy->clk);
>
> @@ -752,6 +774,9 @@ static int imx8mq_usb_phy_runtime_resume(struct device *dev)
> return ret;
> }
>
> + if (imx_phy->cr_regmap)
> + regcache_cache_only(imx_phy->cr_regmap, false);
> +
> return 0;
> }
>
>
> --
> 2.34.1
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v4 3/5] phy: fsl-imx8mq-usb: add runtime PM support
From: Frank Li @ 2026-06-05 15:14 UTC (permalink / raw)
To: Xu Yang
Cc: Vinod Koul, Neil Armstrong, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Jun Li, linux-phy, imx, linux-arm-kernel,
linux-kernel, Xu Yang
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-3-b2ddf2f3862c@nxp.com>
On Fri, Jun 05, 2026 at 07:13:04PM +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 v4:
> - replace guard() with PM_RUNTIME_ACQUIRE()
> Changes in v3:
> - new patch
> ---
> drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 62 +++++++++++++++++++++---------
> 1 file changed, 43 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> index 591ddf346061..27aa696f5dd4 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");
when driver remove, devm will disable clock, which may cause refcound
wrong if device already suspend by runtime pm
> 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,10 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> if (IS_ERR(imx_phy->base))
> return PTR_ERR(imx_phy->base);
>
> + ret = devm_pm_runtime_set_active_enabled(dev);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
> +
You have not set auto suspend, so runtime_suspend will never entry.
Frank
> phy_ops = of_device_get_match_data(dev);
> if (!phy_ops)
> return -EINVAL;
> @@ -735,11 +727,43 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> return PTR_ERR_OR_ZERO(phy_provider);
> }
>
> +static int imx8mq_usb_phy_runtime_suspend(struct device *dev)
> +{
> + struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
> +
> + clk_disable_unprepare(imx_phy->alt_clk);
> + clk_disable_unprepare(imx_phy->clk);
> +
> + return 0;
> +}
> +
> +static int imx8mq_usb_phy_runtime_resume(struct device *dev)
> +{
> + struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
> + int 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;
> + }
> +
> + return 0;
> +}
> +
> +static DEFINE_RUNTIME_DEV_PM_OPS(imx8mq_usb_phy_pm_ops, imx8mq_usb_phy_runtime_suspend,
> + imx8mq_usb_phy_runtime_resume, NULL);
> +
> static struct platform_driver imx8mq_usb_phy_driver = {
> .probe = imx8mq_usb_phy_probe,
> .driver = {
> .name = "imx8mq-usb-phy",
> .of_match_table = imx8mq_usb_phy_of_match,
> + .pm = pm_ptr(&imx8mq_usb_phy_pm_ops),
> .suppress_bind_attrs = true,
> }
> };
>
> --
> 2.34.1
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v2] phy: freescale: phy-fsl-imx8qm-lvds-phy: Fix missing pm_runtime_disable() on probe error path
From: Frank Li @ 2026-06-05 15:04 UTC (permalink / raw)
To: Felix Gu
Cc: Vinod Koul, Neil Armstrong, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Liu Ying, linux-phy, imx, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260605-lvds-v2-1-3ce7539d1104@gmail.com>
On Fri, Jun 05, 2026 at 07:57:20PM +0800, Felix Gu wrote:
> If mixel_lvds_phy_reset() fails in probe after pm_runtime_enable(),
> the function returns directly without calling pm_runtime_disable(),
> leaving runtime PM permanently enabled for the device.
>
> Fix this by using devm_pm_runtime_enable() so that cleanup is
> automatic on any probe failure or driver unbind. This also allows
> removing the manual err label and the .remove callback.
>
> Fixes: 06ff622d61d2 ("phy: freescale: Add i.MX8qm Mixel LVDS PHY support")
> Acked-by: Liu Ying <victor.liu@nxp.com>
> Signed-off-by: Felix Gu <ustc.gu@gmail.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Changes in v2:
> - Change the patch's subject prefix requested by Liu Ying.
> - Add Liu Ying's Acked-by.
> - Link to v1: https://patch.msgid.link/20260604-lvds-v1-1-b8e1ff1bdee7@gmail.com
>
> To: Vinod Koul <vkoul@kernel.org>
> To: Neil Armstrong <neil.armstrong@linaro.org>
> To: Frank Li <Frank.Li@nxp.com>
> To: Sascha Hauer <s.hauer@pengutronix.de>
> To: Pengutronix Kernel Team <kernel@pengutronix.de>
> To: Fabio Estevam <festevam@gmail.com>
> To: Liu Ying <victor.liu@nxp.com>
> Cc: linux-phy@lists.infradead.org
> Cc: imx@lists.linux.dev
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> ---
> drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c | 24 +++++++-----------------
> 1 file changed, 7 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
> index ece357443521..c662f91e598c 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
> @@ -345,7 +345,9 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev)
>
> dev_set_drvdata(dev, priv);
>
> - pm_runtime_enable(dev);
> + ret = devm_pm_runtime_enable(dev);
> + if (ret)
> + return ret;
>
> ret = mixel_lvds_phy_reset(dev);
> if (ret) {
> @@ -355,17 +357,15 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev)
>
> for (i = 0; i < PHY_NUM; i++) {
> lvds_phy = devm_kzalloc(dev, sizeof(*lvds_phy), GFP_KERNEL);
> - if (!lvds_phy) {
> - ret = -ENOMEM;
> - goto err;
> - }
> + if (!lvds_phy)
> + return -ENOMEM;
>
> phy = devm_phy_create(dev, NULL, &mixel_lvds_phy_ops);
> if (IS_ERR(phy)) {
> ret = PTR_ERR(phy);
> dev_err(dev, "failed to create PHY for channel%d: %d\n",
> i, ret);
> - goto err;
> + return ret;
> }
>
> lvds_phy->phy = phy;
> @@ -379,19 +379,10 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev)
> if (IS_ERR(phy_provider)) {
> ret = PTR_ERR(phy_provider);
> dev_err(dev, "failed to register PHY provider: %d\n", ret);
> - goto err;
> + return ret;
> }
>
> return 0;
> -err:
> - pm_runtime_disable(dev);
> -
> - return ret;
> -}
> -
> -static void mixel_lvds_phy_remove(struct platform_device *pdev)
> -{
> - pm_runtime_disable(&pdev->dev);
> }
>
> static int __maybe_unused mixel_lvds_phy_runtime_suspend(struct device *dev)
> @@ -432,7 +423,6 @@ MODULE_DEVICE_TABLE(of, mixel_lvds_phy_of_match);
>
> static struct platform_driver mixel_lvds_phy_driver = {
> .probe = mixel_lvds_phy_probe,
> - .remove = mixel_lvds_phy_remove,
> .driver = {
> .pm = &mixel_lvds_phy_pm_ops,
> .name = "mixel-lvds-phy",
>
> ---
> base-commit: a225caacc36546a09586e3ece36c0313146e7da9
> change-id: 20260604-lvds-d67cb619df17
>
> Best regards,
> --
> Felix Gu <ustc.gu@gmail.com>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v2] phy: freescale: phy-fsl-imx8qm-lvds-phy: Fix missing pm_runtime_disable() on probe error path
From: sashiko-bot @ 2026-06-05 12:04 UTC (permalink / raw)
To: Felix Gu; +Cc: neil.armstrong, vkoul, olteanv, linux-phy, Frank.Li, imx
In-Reply-To: <20260605-lvds-v2-1-3ce7539d1104@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Pending asynchronous suspend scheduled by `pm_runtime_put()` can be cancelled by `pm_runtime_disable()` during probe failure, leaving the hardware permanently in an active power state.
--
commit 8ed1a4a5b60301f95aa6700ff6d900f3ad7141f0
Author: Felix Gu <ustc.gu@gmail.com>
phy: freescale: phy-fsl-imx8qm-lvds-phy: Fix missing pm_runtime_disable() on probe error path
This commit replaces manual pm_runtime_disable() calls with
devm_pm_runtime_enable() to automatically clean up runtime PM during probe
failures or unbinds.
> diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
> index ece3574435217..c662f91e598c7 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
[ ... ]
> @@ -355,17 +357,15 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev)
>
> for (i = 0; i < PHY_NUM; i++) {
> lvds_phy = devm_kzalloc(dev, sizeof(*lvds_phy), GFP_KERNEL);
> - if (!lvds_phy) {
> - ret = -ENOMEM;
> - goto err;
> - }
> + if (!lvds_phy)
> + return -ENOMEM;
>
> phy = devm_phy_create(dev, NULL, &mixel_lvds_phy_ops);
> if (IS_ERR(phy)) {
> ret = PTR_ERR(phy);
> dev_err(dev, "failed to create PHY for channel%d: %d\n",
> i, ret);
> - goto err;
> + return ret;
[Severity: High]
This is a pre-existing issue, but will these error paths leave the hardware
powered on indefinitely if initialization fails?
Just prior to this loop, mixel_lvds_phy_probe() calls mixel_lvds_phy_reset(),
which finishes by queuing an asynchronous suspend:
drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c:mixel_lvds_phy_reset() {
...
regmap_write(priv->regmap, PHY_CTRL, CTRL_RESET_VAL);
pm_runtime_put(dev);
return 0;
}
If a subsequent initialization step fails and returns an error, the devres
cleanup will immediately execute pm_runtime_disable() (which was also the
case previously with the goto err label).
Because pm_runtime_disable() calls __pm_runtime_barrier(), it cancels any
pending asynchronous idle or suspend work. This means the runtime suspend
callback might never execute, leaving the PHY hardware fully powered up.
Should mixel_lvds_phy_reset() use pm_runtime_put_sync() instead to
guarantee the device is properly suspended before a potential error
disables runtime PM?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605-lvds-v2-1-3ce7539d1104@gmail.com?part=1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v2] phy: freescale: phy-fsl-imx8qm-lvds-phy: Fix missing pm_runtime_disable() on probe error path
From: Felix Gu @ 2026-06-05 11:57 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Liu Ying
Cc: linux-phy, imx, linux-arm-kernel, linux-kernel, Felix Gu
If mixel_lvds_phy_reset() fails in probe after pm_runtime_enable(),
the function returns directly without calling pm_runtime_disable(),
leaving runtime PM permanently enabled for the device.
Fix this by using devm_pm_runtime_enable() so that cleanup is
automatic on any probe failure or driver unbind. This also allows
removing the manual err label and the .remove callback.
Fixes: 06ff622d61d2 ("phy: freescale: Add i.MX8qm Mixel LVDS PHY support")
Acked-by: Liu Ying <victor.liu@nxp.com>
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
---
Changes in v2:
- Change the patch's subject prefix requested by Liu Ying.
- Add Liu Ying's Acked-by.
- Link to v1: https://patch.msgid.link/20260604-lvds-v1-1-b8e1ff1bdee7@gmail.com
To: Vinod Koul <vkoul@kernel.org>
To: Neil Armstrong <neil.armstrong@linaro.org>
To: Frank Li <Frank.Li@nxp.com>
To: Sascha Hauer <s.hauer@pengutronix.de>
To: Pengutronix Kernel Team <kernel@pengutronix.de>
To: Fabio Estevam <festevam@gmail.com>
To: Liu Ying <victor.liu@nxp.com>
Cc: linux-phy@lists.infradead.org
Cc: imx@lists.linux.dev
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
index ece357443521..c662f91e598c 100644
--- a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
+++ b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
@@ -345,7 +345,9 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev)
dev_set_drvdata(dev, priv);
- pm_runtime_enable(dev);
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
ret = mixel_lvds_phy_reset(dev);
if (ret) {
@@ -355,17 +357,15 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev)
for (i = 0; i < PHY_NUM; i++) {
lvds_phy = devm_kzalloc(dev, sizeof(*lvds_phy), GFP_KERNEL);
- if (!lvds_phy) {
- ret = -ENOMEM;
- goto err;
- }
+ if (!lvds_phy)
+ return -ENOMEM;
phy = devm_phy_create(dev, NULL, &mixel_lvds_phy_ops);
if (IS_ERR(phy)) {
ret = PTR_ERR(phy);
dev_err(dev, "failed to create PHY for channel%d: %d\n",
i, ret);
- goto err;
+ return ret;
}
lvds_phy->phy = phy;
@@ -379,19 +379,10 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev)
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
dev_err(dev, "failed to register PHY provider: %d\n", ret);
- goto err;
+ return ret;
}
return 0;
-err:
- pm_runtime_disable(dev);
-
- return ret;
-}
-
-static void mixel_lvds_phy_remove(struct platform_device *pdev)
-{
- pm_runtime_disable(&pdev->dev);
}
static int __maybe_unused mixel_lvds_phy_runtime_suspend(struct device *dev)
@@ -432,7 +423,6 @@ MODULE_DEVICE_TABLE(of, mixel_lvds_phy_of_match);
static struct platform_driver mixel_lvds_phy_driver = {
.probe = mixel_lvds_phy_probe,
- .remove = mixel_lvds_phy_remove,
.driver = {
.pm = &mixel_lvds_phy_pm_ops,
.name = "mixel-lvds-phy",
---
base-commit: a225caacc36546a09586e3ece36c0313146e7da9
change-id: 20260604-lvds-d67cb619df17
Best regards,
--
Felix Gu <ustc.gu@gmail.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* Re: [PATCH v4 2/5] phy: fsl-imx8mq-usb: set usb phy to be wakeup capable
From: sashiko-bot @ 2026-06-05 11:30 UTC (permalink / raw)
To: Xu Yang; +Cc: imx, neil.armstrong, linux-phy, vkoul, Frank.Li, olteanv
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-2-b2ddf2f3862c@nxp.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The PHY device is marked as wakeup capable, but the driver lacks the necessary PM callbacks and interrupt handling to actually implement wakeup functionality, rendering the exposed sysfs entry non-functional.
--
commit 8736c5d3dc323070e318c02e401cc5a5d6dd083d
Author: Xu Yang <xu.yang_2@nxp.com>
phy: fsl-imx8mq-usb: set usb phy to be wakeup capable
This commit marks the i.MX8MQ USB PHY device as wakeup capable. This
advertises the capability to the PM core and exposes a power/wakeup sysfs
entry to userspace.
> diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> index 88b804b2c982b..591ddf3460618 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> @@ -728,6 +728,7 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> "failed to get tca\n");
>
> imx8m_get_phy_tuning_data(imx_phy);
> + device_set_wakeup_capable(dev, true);
[Severity: Medium]
Does this regression expose a non-functional sysfs node to userspace?
The commit message notes that the PHY supports remote wakeup, but the
driver itself does not appear to implement any PM callbacks or interrupt
handling to actually process the wakeup or check device_may_wakeup(dev).
Because actual USB remote wakeup is typically managed by the parent USB
controller and its glue layer, which have their own functional wakeup
sysfs nodes, could this create a dead toggle in sysfs where userspace can
enable wakeup on the PHY device without any actual effect?
>
> phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.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 v4 4/5] phy: fsl-imx8mq-usb: add control register regmap
From: sashiko-bot @ 2026-06-05 11:29 UTC (permalink / raw)
To: Xu Yang; +Cc: olteanv, linux-phy, vkoul, Frank.Li, neil.armstrong, imx
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-4-b2ddf2f3862c@nxp.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Medium] Writes to the CR debugfs control registers are silently discarded without error if the PHY is runtime suspended.
Pre-existing issues:
- [High] Clock reference count underflow on driver unbind due to devm_clk_get_enabled() and Runtime PM.
--
commit 3bce0d41a4e2282036c6fa41e62f47cfe0788d65
Author: Xu Yang <xu.yang_2@nxp.com>
phy: fsl-imx8mq-usb: add control register regmap
The CR port is a simple 16-bit data/address parallel port that is
accessed through 32-bit MMIO registers for on-chip access to the
control registers inside the USB 3.0 femtoPHY. Add control register
regmap and export these registers by debugfs to help PHY's diagnostic.
> diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> index 27aa696f5dd40..e24f46d7924b6 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
[ ... ]
> @@ -667,6 +671,14 @@ static const struct of_device_id imx8mq_usb_phy_of_match[] = {
> };
> MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match);
>
> +static const struct regmap_config imx_cr_regmap_config = {
> + .name = "cr",
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x7,
> +};
[Severity: Medium]
Does this regmap configuration need a .cache_type?
Without one, it defaults to REGCACHE_NONE. Later in the patch,
imx8mq_usb_phy_runtime_suspend() puts the regmap into cache-only mode.
With REGCACHE_NONE, any debugfs writes while suspended will return success,
but the data is silently discarded because there is no cache backing it.
[ ... ]
> @@ -731,6 +750,9 @@ static int imx8mq_usb_phy_runtime_suspend(struct device *dev)
> {
> struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
>
> + if (imx_phy->cr_regmap)
> + regcache_cache_only(imx_phy->cr_regmap, true);
> +
> clk_disable_unprepare(imx_phy->alt_clk);
> clk_disable_unprepare(imx_phy->clk);
[Severity: High]
This is a pre-existing issue, but can this lead to a clock enable_count
underflow on driver unbind?
The driver acquires the clock using devm_clk_get_enabled() in
imx8mq_usb_phy_probe(), meaning devm manages the enable state. However, it
manually disables the clock here during runtime suspend.
If the driver is unbound while the device is in the runtime suspended state,
the devm cleanup function will call clk_disable_unprepare() a second time on
the already disabled clock, since there is no .remove callback to resume the
device first.
> @@ -752,6 +774,9 @@ static int imx8mq_usb_phy_runtime_resume(struct device *dev)
> return ret;
> }
>
> + if (imx_phy->cr_regmap)
> + regcache_cache_only(imx_phy->cr_regmap, false);
[Severity: Medium]
Should there be a regcache_sync() call here after disabling cache-only mode?
If a valid cache type is added to imx_cr_regmap_config, the cache will need
to be synchronized here to flush any pending diagnostic writes to the hardware
that occurred while the device was suspended.
> +
> return 0;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.com?part=4
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v4 3/5] phy: fsl-imx8mq-usb: add runtime PM support
From: sashiko-bot @ 2026-06-05 11:23 UTC (permalink / raw)
To: Xu Yang; +Cc: Frank.Li, olteanv, vkoul, imx, linux-phy, neil.armstrong
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-3-b2ddf2f3862c@nxp.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Mixing `devm_clk_get_enabled()` with manual `clk_disable_unprepare()` in runtime PM callbacks causes a clock enable count underflow during driver unbind.
--
commit 974b1a50a22e38e08aa5fd0139ae39d578c8f39c
Author: Xu Yang <xu.yang_2@nxp.com>
phy: fsl-imx8mq-usb: add runtime PM support
Add runtime PM to ensure the PHY is properly powered and clocked during
register access, preventing potential system hangs.
> diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> index 591ddf3460618..27aa696f5dd40 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
[ ... ]
> @@ -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");
[ ... ]
> @@ -735,11 +727,43 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
> return PTR_ERR_OR_ZERO(phy_provider);
> }
>
> +static int imx8mq_usb_phy_runtime_suspend(struct device *dev)
> +{
> + struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
> +
> + clk_disable_unprepare(imx_phy->alt_clk);
> + clk_disable_unprepare(imx_phy->clk);
[Severity: High]
Does this mix of devm_clk_get_enabled() and manual clk_disable_unprepare()
cause a clock enable count underflow during driver unbind?
During imx8mq_usb_phy_probe(), devm_clk_get_enabled() registers devres actions
that will unconditionally call clk_disable_unprepare() upon driver removal.
When the driver is unbound, the driver core calls pm_runtime_put_sync() before
triggering devres cleanup. This suspends the device, invoking
imx8mq_usb_phy_runtime_suspend() which drops the clock enable counts to 0.
Subsequently, device_unbind_cleanup() executes the devres actions, calling
clk_disable_unprepare() again on the already-disabled clocks. In the clock
framework, checking an enable_count of 0 results in a kernel warning.
To avoid this, the driver could either handle clock initialization manually
without devm_*_enabled variants, or implement a .remove callback that
explicitly wakes the device via pm_runtime_get_sync() and disables runtime PM
to prevent devres from executing on a suspended device.
> +
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.com?part=3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v4 1/5] phy: fsl-imx8mq-usb: fix typec switch leak on probe error path
From: sashiko-bot @ 2026-06-05 11:22 UTC (permalink / raw)
To: Xu Yang; +Cc: Frank.Li, linux-phy, vkoul, imx, neil.armstrong, olteanv
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-1-b2ddf2f3862c@nxp.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Race condition during probe leading to NULL pointer dereference.
- [High] Use-After-Free (UAF) of provider driver data on manual unbind.
--
commit 9dde5dedb4fbdef1b93e7e96ccdb22fc9407f2cc
Author: Felix Gu <ustc.gu@gmail.com>
phy: fsl-imx8mq-usb: fix typec switch leak on probe error path
This commit fixes a memory leak of the Type-C switch on the probe error
path by using devm_add_action_or_reset() for cleanup. This ensures the
switch is unregistered 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..88b804b2c982b 100644
> --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
> +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
[ ... ]
> @@ -248,6 +248,7 @@ static struct tca_blk *imx95_usb_phy_get_tca(struct platform_device *pdev,
> struct device *dev = &pdev->dev;
> struct resource *res;
> struct tca_blk *tca;
> + int ret;
>
> res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> if (!res)
> @@ -266,17 +267,11 @@ static struct tca_blk *imx95_usb_phy_get_tca(struct platform_device *pdev,
> tca->orientation = TYPEC_ORIENTATION_NORMAL;
> tca->sw = tca_blk_get_typec_switch(pdev, imx_phy);
[Severity: High]
This is a pre-existing issue, but does this create a race condition
during probe?
When tca_blk_get_typec_switch() registers the Type-C switch, it becomes
exposed to the subsystem. If a consumer binds asynchronously in this narrow
window and invokes the .set callback, could it dereference imx_phy->tca
before it gets assigned back in imx8mq_usb_phy_probe()?
drivers/phy/freescale/phy-fsl-imx8mq-usb.c:tca_blk_typec_switch_set() {
struct imx8mq_usb_phy *imx_phy = typec_switch_get_drvdata(sw);
struct tca_blk *tca = imx_phy->tca;
...
if (tca->orientation == orientation)
...
}
Would it be safer to assign imx_phy->tca before registering the
Type-C switch?
> - return tca;
> -}
> -
> -static void imx95_usb_phy_put_tca(struct imx8mq_usb_phy *imx_phy)
> -{
> - struct tca_blk *tca = imx_phy->tca;
> -
> - if (!tca)
> - return;
> + ret = devm_add_action_or_reset(&pdev->dev, tca_blk_put_typec_switch, tca->sw);
[Severity: High]
This is also a pre-existing issue, but can this lead to a Use-After-Free
if the driver is manually unbound?
If the driver is unbound via sysfs, devres will automatically free the
imx_phy and tca structures since they were allocated with devm_kzalloc().
However, if typec_switch_unregister() doesn't revoke existing consumer
references, could a consumer subsequently call typec_switch_set() and
access the already freed imx_phy and tca structures?
drivers/phy/freescale/phy-fsl-imx8mq-usb.c:tca_blk_typec_switch_set() {
struct imx8mq_usb_phy *imx_phy = typec_switch_get_drvdata(sw);
struct tca_blk *tca = imx_phy->tca;
...
if (tca->orientation == orientation)
...
}
> + if (ret)
> + return ERR_PTR(ret);
>
> - tca_blk_put_typec_switch(tca->sw);
> + return tca;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.com?part=1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v4 5/5] phy: fsl-imx8mq-usb: keep PHY power domain runtime always-on for i.MX8MP
From: Xu Yang @ 2026-06-05 11:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li
Cc: linux-phy, imx, linux-arm-kernel, linux-kernel, Xu Yang
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.com>
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
new imx95_usb_phy_ops for i.MX95 and introduce usb_phy_is_imx8mp() helper
to identify i.MX8MP PHY instance.
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v4:
- no changes
Changes in v3:
- new patch
---
drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
index e24f46d7924b..c8b93ae2035f 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>
@@ -660,13 +661,20 @@ static const struct phy_ops imx8mp_usb_phy_ops = {
.owner = THIS_MODULE,
};
+static const struct phy_ops imx95_usb_phy_ops = {
+ .init = imx8mp_usb_phy_init,
+ .power_on = imx8mq_phy_power_on,
+ .power_off = imx8mq_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
static const struct of_device_id imx8mq_usb_phy_of_match[] = {
{.compatible = "fsl,imx8mq-usb-phy",
.data = &imx8mq_usb_phy_ops,},
{.compatible = "fsl,imx8mp-usb-phy",
.data = &imx8mp_usb_phy_ops,},
{.compatible = "fsl,imx95-usb-phy",
- .data = &imx8mp_usb_phy_ops,},
+ .data = &imx95_usb_phy_ops,},
{ }
};
MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match);
@@ -679,6 +687,11 @@ static const struct regmap_config imx_cr_regmap_config = {
.max_register = 0x7,
};
+static bool usb_phy_is_imx8mp(const void *data)
+{
+ return data == &imx8mp_usb_phy_ops;
+}
+
static int imx8mq_usb_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
@@ -723,6 +736,9 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
if (!phy_ops)
return -EINVAL;
+ if (usb_phy_is_imx8mp(phy_ops))
+ dev_pm_genpd_rpm_always_on(dev, true);
+
imx_phy->phy = devm_phy_create(dev, NULL, phy_ops);
if (IS_ERR(imx_phy->phy))
return PTR_ERR(imx_phy->phy);
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v4 4/5] phy: fsl-imx8mq-usb: add control register regmap
From: Xu Yang @ 2026-06-05 11:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li
Cc: linux-phy, imx, linux-arm-kernel, linux-kernel, Xu Yang
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.com>
From: Xu Yang <xu.yang_2@nxp.com>
The CR port is a simple 16-bit data/address parallel port that is
accessed through 32-bit MMIO registers for on-chip access to the
control registers inside the USB 3.0 femtoPHY. Add control register
regmap and export these registers by debugfs to help PHY's diagnostic.
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v4:
- improve commit message as Haibo's suggestion
Changes in v3:
- drop Frank's tag because it includes other changes
- new patch
---
drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
index 27aa696f5dd4..e24f46d7924b 100644
--- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
+++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0+
-/* Copyright (c) 2017 NXP. */
+/* Copyright 2017-2026 NXP. */
#include <linux/bitfield.h>
#include <linux/clk.h>
@@ -11,6 +11,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/regmap.h>
#include <linux/usb/typec_mux.h>
#define PHY_CTRL0 0x0
@@ -56,6 +57,8 @@
#define PHY_CTRL6_ALT_CLK_EN BIT(1)
#define PHY_CTRL6_ALT_CLK_SEL BIT(0)
+#define PHY_CRCTL 0x30
+
#define PHY_TUNE_DEFAULT 0xffffffff
#define TCA_CLK_RST 0x00
@@ -119,6 +122,7 @@ struct imx8mq_usb_phy {
void __iomem *base;
struct regulator *vbus;
struct tca_blk *tca;
+ struct regmap *cr_regmap;
u32 pcs_tx_swing_full;
u32 pcs_tx_deemph_3p5db;
u32 tx_vref_tune;
@@ -667,6 +671,14 @@ static const struct of_device_id imx8mq_usb_phy_of_match[] = {
};
MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match);
+static const struct regmap_config imx_cr_regmap_config = {
+ .name = "cr",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x7,
+};
+
static int imx8mq_usb_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
@@ -696,6 +708,13 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
if (IS_ERR(imx_phy->base))
return PTR_ERR(imx_phy->base);
+ imx_phy->cr_regmap = devm_regmap_init_mmio(dev, imx_phy->base + PHY_CRCTL,
+ &imx_cr_regmap_config);
+ if (IS_ERR(imx_phy->cr_regmap)) {
+ dev_warn(dev, "Fail to init debug register regmap\n");
+ imx_phy->cr_regmap = NULL;
+ }
+
ret = devm_pm_runtime_set_active_enabled(dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
@@ -731,6 +750,9 @@ static int imx8mq_usb_phy_runtime_suspend(struct device *dev)
{
struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
+ if (imx_phy->cr_regmap)
+ regcache_cache_only(imx_phy->cr_regmap, true);
+
clk_disable_unprepare(imx_phy->alt_clk);
clk_disable_unprepare(imx_phy->clk);
@@ -752,6 +774,9 @@ static int imx8mq_usb_phy_runtime_resume(struct device *dev)
return ret;
}
+ if (imx_phy->cr_regmap)
+ regcache_cache_only(imx_phy->cr_regmap, false);
+
return 0;
}
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v4 3/5] phy: fsl-imx8mq-usb: add runtime PM support
From: Xu Yang @ 2026-06-05 11:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li
Cc: linux-phy, imx, linux-arm-kernel, linux-kernel, Xu Yang
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.com>
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 v4:
- replace guard() with PM_RUNTIME_ACQUIRE()
Changes in v3:
- new patch
---
drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 62 +++++++++++++++++++++---------
1 file changed, 43 insertions(+), 19 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
index 591ddf346061..27aa696f5dd4 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,10 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
if (IS_ERR(imx_phy->base))
return PTR_ERR(imx_phy->base);
+ ret = devm_pm_runtime_set_active_enabled(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
+
phy_ops = of_device_get_match_data(dev);
if (!phy_ops)
return -EINVAL;
@@ -735,11 +727,43 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR_OR_ZERO(phy_provider);
}
+static int imx8mq_usb_phy_runtime_suspend(struct device *dev)
+{
+ struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(imx_phy->alt_clk);
+ clk_disable_unprepare(imx_phy->clk);
+
+ return 0;
+}
+
+static int imx8mq_usb_phy_runtime_resume(struct device *dev)
+{
+ struct imx8mq_usb_phy *imx_phy = dev_get_drvdata(dev);
+ int 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;
+ }
+
+ return 0;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(imx8mq_usb_phy_pm_ops, imx8mq_usb_phy_runtime_suspend,
+ imx8mq_usb_phy_runtime_resume, NULL);
+
static struct platform_driver imx8mq_usb_phy_driver = {
.probe = imx8mq_usb_phy_probe,
.driver = {
.name = "imx8mq-usb-phy",
.of_match_table = imx8mq_usb_phy_of_match,
+ .pm = pm_ptr(&imx8mq_usb_phy_pm_ops),
.suppress_bind_attrs = true,
}
};
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v4 2/5] phy: fsl-imx8mq-usb: set usb phy to be wakeup capable
From: Xu Yang @ 2026-06-05 11:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li
Cc: linux-phy, imx, linux-arm-kernel, linux-kernel, Xu Yang
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.com>
From: Xu Yang <xu.yang_2@nxp.com>
Set PHY wakeup capable because this PHY supports remote wakeup function.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v4:
- add Rb tag
Changes in v3:
- no changes
Changes in v2:
- no changes
---
drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
index 88b804b2c982..591ddf346061 100644
--- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
+++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
@@ -728,6 +728,7 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
"failed to get tca\n");
imx8m_get_phy_tuning_data(imx_phy);
+ device_set_wakeup_capable(dev, true);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v4 1/5] phy: fsl-imx8mq-usb: fix typec switch leak on probe error path
From: Xu Yang @ 2026-06-05 11:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li
Cc: linux-phy, imx, linux-arm-kernel, linux-kernel, Felix Gu, stable,
Xu Yang
In-Reply-To: <20260605-imx8mp-usb-phy-improvement-v4-0-b2ddf2f3862c@nxp.com>
From: Felix Gu <ustc.gu@gmail.com>
If probe fails after imx95_usb_phy_get_tca() succeeds, the typec
switch leaks because the only cleanup path was in .remove, which
never runs on probe failure.
Use devm_add_action_or_reset() so the switch is cleaned up on both
probe failure and driver removal. The .remove callback and
imx95_usb_phy_put_tca() are no longer needed.
Fixes: b58f0f86fd61 ("phy: fsl-imx8mq-usb: add tca function driver for imx95")
Cc: stable@vger.kernel.org
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Xu Yang <xu.yang_2@nxp.com>
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v4:
- add my signed-off tag
Changes in v3:
- add R-b tag
- cc statble
- drop "sw = data" conversion
---
drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 27 +++++++--------------------
1 file changed, 7 insertions(+), 20 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
index b05d80e849a1..88b804b2c982 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);
}
static void tca_blk_orientation_set(struct tca_blk *tca,
@@ -248,6 +248,7 @@ static struct tca_blk *imx95_usb_phy_get_tca(struct platform_device *pdev,
struct device *dev = &pdev->dev;
struct resource *res;
struct tca_blk *tca;
+ int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res)
@@ -266,17 +267,11 @@ static struct tca_blk *imx95_usb_phy_get_tca(struct platform_device *pdev,
tca->orientation = TYPEC_ORIENTATION_NORMAL;
tca->sw = tca_blk_get_typec_switch(pdev, imx_phy);
- return tca;
-}
-
-static void imx95_usb_phy_put_tca(struct imx8mq_usb_phy *imx_phy)
-{
- struct tca_blk *tca = imx_phy->tca;
-
- if (!tca)
- return;
+ ret = devm_add_action_or_reset(&pdev->dev, tca_blk_put_typec_switch, tca->sw);
+ if (ret)
+ return ERR_PTR(ret);
- tca_blk_put_typec_switch(tca->sw);
+ return tca;
}
static u32 phy_tx_vref_tune_from_property(u32 percent)
@@ -739,16 +734,8 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR_OR_ZERO(phy_provider);
}
-static void imx8mq_usb_phy_remove(struct platform_device *pdev)
-{
- struct imx8mq_usb_phy *imx_phy = platform_get_drvdata(pdev);
-
- imx95_usb_phy_put_tca(imx_phy);
-}
-
static struct platform_driver imx8mq_usb_phy_driver = {
.probe = imx8mq_usb_phy_probe,
- .remove = imx8mq_usb_phy_remove,
.driver = {
.name = "imx8mq-usb-phy",
.of_match_table = imx8mq_usb_phy_of_match,
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v4 0/5] phy: fsl-imx8mq-usb: few improvements
From: Xu Yang @ 2026-06-05 11:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Jun Li
Cc: linux-phy, imx, linux-arm-kernel, linux-kernel, Felix Gu, stable,
Xu Yang
This patchset is a continuous of v2, it mainly resolves some concerns
reported by sashiko-bot.
Patch #1 fix Type-C switch resource leak if probe() fails.
Patch #3 add runtime PM support to avoid register access issue if the
USB controller enters into runtime suspended state, in this state
accessing USB PHY register may lack some resources. This will also
avoid regulator leak if power_on() fails.
Patch #4 add debug control register regmap
Patch #5 correct i.MX8MP USB runtime wakeup issue after introduce runtime
PM support.
---
Changes in v4:
- add Rb tag
- replace guard() with PM_RUNTIME_ACQUIRE()
- Link to v3: https://patch.msgid.link/20260603-imx8mp-usb-phy-improvement-v3-0-7afb8f89abc6@nxp.com
Link to v2:
- https://lore.kernel.org/linux-phy/20260512101046.1498096-1-xu.yang_2@nxp.com/
- https://lore.kernel.org/linux-phy/20260512101212.1498223-1-xu.yang_2@nxp.com/
---
Felix Gu (1):
phy: fsl-imx8mq-usb: fix typec switch leak on probe error path
Xu Yang (4):
phy: fsl-imx8mq-usb: set usb phy to be wakeup capable
phy: fsl-imx8mq-usb: add runtime PM support
phy: fsl-imx8mq-usb: add control register regmap
phy: fsl-imx8mq-usb: keep PHY power domain runtime always-on for i.MX8MP
drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 127 ++++++++++++++++++++---------
1 file changed, 90 insertions(+), 37 deletions(-)
---
base-commit: 08484c504b55a98bd100527fbe10a3caf55ff3ff
change-id: 20260602-imx8mp-usb-phy-improvement-4272d308d862
Best regards,
--
Xu Yang <xu.yang_2@nxp.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v8 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver
From: Bryan O'Donoghue @ 2026-06-05 10:30 UTC (permalink / raw)
To: Nihal Kumar Gupta, Dmitry Baryshkov, Vijay Kumar Tumati
Cc: Vladimir Zapolskiy, Vinod Koul, Kishon Vijay Abraham I,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong,
Bryan O'Donoghue, linux-arm-msm, linux-phy, linux-media,
devicetree, linux-kernel
In-Reply-To: <59331aa7-8430-4754-861c-4ba6a4810ccd@oss.qualcomm.com>
On 05/06/2026 10:31, Nihal Kumar Gupta wrote:
>> Having clock-names property doesn't mean that all values are valid.
>>
> CSI_COMMON_CTRL5 is a physical lane power-up bitmap:
> - Bits [0,2,4,6] → D-PHY data lanes(LN0, LN2, LN4, LN6)
> - Bits [1,3,5] → C-PHY trio lanes(LN1, LN3, LN5)
> - Bit [7] → D-PHY clock lane(LNCK) dedicated clock enable
>
> In combo mode, only LN6 can be configurable as a clock lane.
>
> The lane-enable computation in phy_qcom_mipi_csi2_lanes_enable() uses
> BIT(data[i].pos) directly, assuming physical bit positions <0 2 4 6>,
> but the DT [1] uses conventional indices <0 1 2 3>, producing 0x8F
> instead of the correct 0xD5.
>
> This goes unnoticed because the wrong value is immediately overwritten by the
> hardcoded 0xD5 in lane_regs_x1e80100, making the dynamic computation effectively dead.
>
> Could you please fix the driver to map logical lane indices, consistent with the gen2 camss convention.
>
> [1]https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-
> v3-5-1d5a9306116a@linaro.org
That's great, thank you for sharing this information, it moves us from
"I think" to "the documentation says"
---
bod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v8 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver
From: Nihal Kumar Gupta @ 2026-06-05 9:31 UTC (permalink / raw)
To: Dmitry Baryshkov, Vijay Kumar Tumati
Cc: Bryan O'Donoghue, Vladimir Zapolskiy, Vinod Koul,
Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Neil Armstrong, Bryan O'Donoghue, linux-arm-msm,
linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <htxqjgwjczsghunsbvo44lwkadzeg2kp6wfcksf3hkmcubvs2d@cw5r67uxskvu>
On 04-06-2026 03:44, Dmitry Baryshkov wrote:
> On Wed, Jun 03, 2026 at 02:37:48PM -0700, Vijay Kumar Tumati wrote:
>>
>>
>> On 6/3/2026 5:57 AM, Bryan O'Donoghue wrote:
>>> On 03/06/2026 13:40, Dmitry Baryshkov wrote:
>>>>> Are you sure about that ?
>>>> Yes.
>>>>
>>>>> ipcat I thought designated lane 7 specifically as clk-lane i.e. named it
>>>>> CLK_LN of some description.
>>>> Split configurations explicitly use other lanes for clocks. E.g. check
>>>> the RB5 Navigation schematics, CAM0B connector.
>>>
>>> Can you please check:
>>>
>>> CSI_3PHASE_COMMON.CSI_COMMON_CTRL5
>>>
>>> 0 LN0_PWRDN_B Lane 0
>>> ...
>>> 7 LNCK_PWRDN_B Clock Lane
>>>
>>> ... just a badly name field
>>>
>>> CSI_2PHASE_CTRL10
>>>
>>> Bit[2] = IS_CLKLANE
>>>
>>> Right so CSI_2PHASE_CTRL10 controls lane mode, indeed. Thanks for checking.
>> I can check this with the HW team. Although the SWI has this knob, there may
>> be some limitations to use any lane as the clk lane. AFAIK, only two
>> specific lanes are clk capable in DPHY mode.>
>
> Having clock-names property doesn't mean that all values are valid.
>
CSI_COMMON_CTRL5 is a physical lane power-up bitmap:
- Bits [0,2,4,6] → D-PHY data lanes(LN0, LN2, LN4, LN6)
- Bits [1,3,5] → C-PHY trio lanes(LN1, LN3, LN5)
- Bit [7] → D-PHY clock lane(LNCK) dedicated clock enable
In combo mode, only LN6 can be configurable as a clock lane.
The lane-enable computation in phy_qcom_mipi_csi2_lanes_enable() uses
BIT(data[i].pos) directly, assuming physical bit positions <0 2 4 6>,
but the DT [1] uses conventional indices <0 1 2 3>, producing 0x8F
instead of the correct 0xD5.
This goes unnoticed because the wrong value is immediately overwritten by the
hardcoded 0xD5 in lane_regs_x1e80100, making the dynamic computation effectively dead.
Could you please fix the driver to map logical lane indices, consistent with the gen2 camss convention.
[1] https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-5-1d5a9306116a@linaro.org
Regards,
Nihal
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v3 phy-next 14/16] dt-bindings: phy: lynx-10g: initial document
From: Vladimir Oltean @ 2026-06-05 8:37 UTC (permalink / raw)
To: Conor Dooley
Cc: sashiko-reviews, robh, vkoul, neil.armstrong, conor+dt, linux-phy,
devicetree, olteanv
In-Reply-To: <20260603-numerate-unbundle-ef259832006d@spud>
On Wed, Jun 03, 2026 at 04:50:39PM +0100, Conor Dooley wrote:
> On Wed, Jun 03, 2026 at 04:38:25PM +0300, Vladimir Oltean wrote:
> > On Wed, Jun 03, 2026 at 01:33:50PM +0000, sashiko-bot@kernel.org wrote:
> > > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> > > - [Medium] The `if` condition for enforcing the `big-endian` property incorrectly matches the `compatible` string array directly against an `enum`, which will always evaluate to false and cause the requirement to silently fail.
> > > --
> > >
> > > commit 8bd3982a89722b20a3686e42d4ab3b9f0711ae11
> > > Author: Vladimir Oltean <vladimir.oltean@nxp.com>
> > >
> > > dt-bindings: phy: lynx-10g: initial document
> > >
> > > This commit adds the schema for the 10G Lynx SerDes used on most QorIQ and
> > > Layerscape SoCs. It defines the valid compatible strings, PHY cell requirements,
> > > and enforces SoC-specific constraints such as lane counts and endianness.
> > >
> > > > diff --git a/Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml b/Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml
> > > > new file mode 100644
> > > > index 0000000000000..8cf6027a75b91
> > > > --- /dev/null
> > > > +++ b/Documentation/devicetree/bindings/phy/fsl,lynx-10g.yaml
> > > > + - if:
> > > > + properties:
> > > > + compatible:
> > > > + enum:
> > > > + - fsl,ls1046a-serdes1
> > > > + - fsl,ls1046a-serdes2
> > >
> > > [Severity: Medium]
> > > Does this conditional correctly enforce the big-endian property?
> > >
> > > Since the compatible property is a string array in device trees, evaluating it
> > > directly against an enum always returns false. Should this use "contains:"
> > > with the enum, similar to the preceding if block, so dt_binding_check
> > > correctly enforces the requirement?
> >
> > The tests I did suggest that it does enforce the requirement.
>
> Yeah, sashiko just doesn't understand how this works without "contains".
> "contains" is only actually required for validation purposes if there's
> fallback compatibles and you're trying to get a partial match.
Yeah, I have no clear understanding of the json-schema syntax either, I
just copied from another place where it was clear that the intention was
to have multiple matches on nodes having a single compatible string each.
But maybe it would be good from DT bindings maintainers to teach LLMs
where they get things wrong in this repo?
https://github.com/masoncl/review-prompts/blob/main/kernel/subsystem/dt-bindings.md
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
From: Petr Wozniak @ 2026-06-05 5:34 UTC (permalink / raw)
To: maxime.chevallier, netdev
Cc: kuba, andrew, hkallweit1, linux, davem, edumazet, pabeni,
linux-phy, linux-kernel, bjorn, olek2, Petr Wozniak
In-Reply-To: <19e947e08e51987b@gmail.com>
Hi Maxime,
Thank you for the question — it revealed a gap in the commit message.
The regression turns out to affect both boot-inserted and hotplugged
genuine RollBall modules. Aleksander Bajkowski confirmed that his FLYPRO
SFP-10GT-CS-30M (with Aquantia AQR113C) is broken even when hotplugged —
the PHY is no longer detected after 8fe125892f40.
So the root cause is not boot vs. hotplug specifically: sfp_sm_add_mdio_bus()
in SFP_S_INIT gives the bridge only a 200 ms window, which is insufficient on
hardware where bridge initialization takes longer, regardless of insertion
timing.
Jan Hoffmann also correctly pointed out that the commit message was wrong
about the state: the probe runs in SFP_S_INIT (which follows SFP_S_WAIT),
not "before initialization delays."
v2 with both corrections is at:
https://lore.kernel.org/netdev/20260605053056.1977-1-petr.wozniak@gmail.com/
Thanks,
Petr
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v2 net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
From: Petr Wozniak @ 2026-06-05 5:30 UTC (permalink / raw)
To: netdev
Cc: kuba, andrew, hkallweit1, linux, davem, edumazet, pabeni,
linux-phy, linux-kernel, maxime.chevallier, bjorn, olek2,
Petr Wozniak
In-Reply-To: <20260604181207.17468-1-petr.wozniak@gmail.com>
commit 8fe125892f40 ("net: phy: sfp: probe for RollBall I2C-to-MDIO
bridge in mdio-i2c") introduced a regression: the RollBall I2C-to-MDIO
bridge is not yet ready to respond to CMD_READ/CMD_DONE cycles when
sfp_sm_add_mdio_bus() runs in SFP_S_INIT. The 200 ms probe times out,
i2c_mii_probe_rollball() returns -ENODEV, and sfp_sm_add_mdio_bus()
sets mdio_protocol = MDIO_I2C_NONE. By the time sfp_sm_probe_for_phy()
runs (up to ~17 s later on affected hardware), the bridge is fully
initialized — but PHY probing is skipped because the protocol has
already been changed to NONE.
This affects both modules inserted before boot and hotplugged modules on
hardware where bridge initialization exceeds the 200 ms probe window
(confirmed: FLYPRO SFP-10GT-CS-30M with Aquantia AQR113C, hotplugged).
Move the probe from i2c_mii_init_rollball() — called at bus-creation
time — to sfp_sm_probe_for_phy() in sfp.c, where it runs after the SFP
state machine's module initialization delays. Export the probe function
as mdio_i2c_probe_rollball() so sfp.c can call it.
For RTL8261BE-based modules: the probe correctly returns -ENODEV at PHY
discovery time, causing sfp_sm_probe_for_phy() to destroy the MDIO bus
and set MDIO_I2C_NONE — eliminating the 5+ minute PHY probe retry loop.
For genuine RollBall modules (e.g. FLYPRO SFP-10GT-CS-30M with Aquantia
AQR113C): the probe now runs after initialization is complete and
correctly returns 0 — PHY detection proceeds normally.
Reported-by: Aleksander Bajkowski <olek2@wp.pl>
Fixes: 8fe125892f40 ("net: phy: sfp: probe for RollBall I2C-to-MDIO bridge in mdio-i2c")
Signed-off-by: Petr Wozniak <petr.wozniak@gmail.com>
---
Changes in v2:
- Generalize scope: regression affects both boot-inserted and hotplugged
modules on hardware where bridge init exceeds 200 ms; Aleksander
Bajkowski confirmed FLYPRO SFP-10GT-CS-30M / AQR113C broken even
when hotplugged
- Correct state machine description: probe runs in SFP_S_INIT (which
follows SFP_S_WAIT), not "before initialization delays" (Jan Hoffmann)
- No code changes from v1
drivers/net/mdio/mdio-i2c.c | 18 ++++--------------
drivers/net/phy/sfp.c | 18 ++++++++++++------
include/linux/mdio/mdio-i2c.h | 1 +
3 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
--- a/drivers/net/mdio/mdio-i2c.c
+++ b/drivers/net/mdio/mdio-i2c.c
@@ -352,7 +352,7 @@
return 0;
}
-static int i2c_mii_probe_rollball(struct i2c_adapter *i2c)
+int mdio_i2c_probe_rollball(struct i2c_adapter *i2c)
{
u8 data_buf[] = { ROLLBALL_DATA_ADDR, 0x01, 0x00, 0x00 };
u8 cmd_buf[] = { ROLLBALL_CMD_ADDR, ROLLBALL_CMD_READ };
@@ -397,9 +397,11 @@
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(mdio_i2c_probe_rollball);
static int i2c_mii_init_rollball(struct i2c_adapter *i2c)
{
+ /* Send the RollBall unlock password; bridge presence is verified
+ * later, in sfp_sm_probe_for_phy(), after module initialization. */
struct i2c_msg msg;
u8 pw[5];
int ret;
@@ -419,7 +421,7 @@
if (ret != 1)
return -EIO;
- return i2c_mii_probe_rollball(i2c);
+ return 0;
}
struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
@@ -444,12 +446,8 @@
case MDIO_I2C_ROLLBALL:
ret = i2c_mii_init_rollball(i2c);
if (ret < 0) {
- if (ret != -ENODEV)
- dev_err(parent,
- "Cannot initialize RollBall MDIO I2C protocol: %d\n",
- ret);
- /* -ENODEV propagates to caller: no bridge present,
- * PHY probing should be skipped for this module. */
+ dev_err(parent,
+ "Cannot initialize RollBall MDIO I2C protocol: %d\n",
+ ret);
mdiobus_free(mii);
return ERR_PTR(ret);
}
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -2028,17 +2028,8 @@ static int sfp_sm_add_mdio_bus(struct sfp *sfp)
dev_info(sfp->dev, "probing phy device through the [%s] protocol\n",
mdio_i2c_proto_type(sfp->mdio_protocol));
- int ret;
-
if (sfp->mdio_protocol == MDIO_I2C_NONE)
return 0;
- ret = sfp_i2c_mdiobus_create(sfp);
- if (ret == -ENODEV) {
- /* Probe confirmed no bridge present; skip PHY discovery. */
- sfp->mdio_protocol = MDIO_I2C_NONE;
- return 0;
- }
- return ret;
+ return sfp_i2c_mdiobus_create(sfp);
}
/* Probe a SFP for a PHY device if the module supports copper - the PHY
@@ -2058,8 +2049,23 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
case MDIO_I2C_ROLLBALL:
- err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR_ROLLBALL, true);
+ /* Probe here, after module initialization delays, so that
+ * genuine RollBall bridges have had time to start up.
+ * Modules without a bridge (e.g. RTL8261BE) return -ENODEV. */
+ err = mdio_i2c_probe_rollball(sfp->i2c);
+ if (err == -ENODEV) {
+ sfp_i2c_mdiobus_destroy(sfp);
+ sfp->mdio_protocol = MDIO_I2C_NONE;
+ break;
+ }
+ if (!err)
+ err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR_ROLLBALL, true);
break;
}
diff --git a/include/linux/mdio/mdio-i2c.h b/include/linux/mdio/mdio-i2c.h
--- a/include/linux/mdio/mdio-i2c.h
+++ b/include/linux/mdio/mdio-i2c.h
@@ -33,5 +33,6 @@
struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
enum mdio_i2c_proto protocol);
+int mdio_i2c_probe_rollball(struct i2c_adapter *i2c);
#endif
--
2.51.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH] phy: freescale: imx8qm-lvds-phy: Fix missing pm_runtime_disable() on probe error path
From: Liu Ying @ 2026-06-05 3:44 UTC (permalink / raw)
To: Felix Gu
Cc: Vinod Koul, Neil Armstrong, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-phy, imx,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260604-lvds-v1-1-b8e1ff1bdee7@gmail.com>
On Thu, Jun 04, 2026 at 10:39:07PM +0800, Felix Gu wrote:
> If mixel_lvds_phy_reset() fails in probe after pm_runtime_enable(),
> the function returns directly without calling pm_runtime_disable(),
> leaving runtime PM permanently enabled for the device.
>
> Fix this by using devm_pm_runtime_enable() so that cleanup is
> automatic on any probe failure or driver unbind. This also allows
> removing the manual err label and the .remove callback.
>
> Fixes: 06ff622d61d2 ("phy: freescale: Add i.MX8qm Mixel LVDS PHY support")
> Signed-off-by: Felix Gu <ustc.gu@gmail.com>
> ---
> drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c | 24 +++++++-----------------
> 1 file changed, 7 insertions(+), 17 deletions(-)
It would be good if the patch subject prefix can be changed to
"phy: freescale: phy-fsl-imx8qm-lvds-phy:".
With that done:
Acked-by: Liu Ying <victor.liu@nxp.com>
--
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 v8 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Vijay Kumar Tumati @ 2026-06-05 2:59 UTC (permalink / raw)
To: Bryan O'Donoghue, Vladimir Zapolskiy, Bryan O'Donoghue,
Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Neil Armstrong
Cc: linux-arm-msm, linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <21facbaa-c001-4e82-954d-f2f6838d41b3@oss.qualcomm.com>
Hi Bryan,
On 6/3/2026 2:46 PM, Vijay Kumar Tumati wrote:
>
>
> On 6/3/2026 2:18 PM, Bryan O'Donoghue wrote:
>> On 03/06/2026 21:51, Vladimir Zapolskiy wrote:
>>>> Actually, one more thing, Why isn't TITAN TOP GDSC here?>>>> +
>>> If CSIPHYs are true subdevices under the umbrella CAMSS device and well
>>> described as subnodes, then likely none of power domains are needed
>>> to be
>>> repeatedly described in the children device nodes, since this
>>> information
>>> can be obtained from the parent device by the driver.
>>>
>>> Technically 'power-domains' property can be safely removed, I believe.
>>
>> The policy is to describe the power-domain dependency fully since DT
>> describes hardware not software architecture.
>>
>> Also for a very practical reason a sub-devices can probe/run
>> asynchronously of the parent device being active so in fact we do need
>> to describe the PDs fully.
> This makes me think. When the PHY devices are made the sub nodes of the
> top camss node eventually, we can discuss for somethings to be avoided
> in each child, which we can come to later but for now, you need to add
> the top AHB clock as well in the PHY node, Bryan.>
Sorry, scratch this comment. You are indeed making PHYs as sub nodes to
the top CAMSS and not independent nodes like CCI.Just looked at your DTS
series and realized. I will let the discussion about enumerating TOP
resources in every child node continue in the other thread. Thanks.>> ---
>> bod
> Thanks,
> Vijay.
Thanks,
Vijay.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
From: Maxime Chevallier @ 2026-06-04 21:15 UTC (permalink / raw)
To: Petr Wozniak, netdev
Cc: kuba, andrew, hkallweit1, linux, davem, edumazet, pabeni,
linux-phy, linux-kernel, bjorn, olek2
In-Reply-To: <20260604181207.17468-1-petr.wozniak@gmail.com>
Hi,
On 6/4/26 20:12, Petr Wozniak wrote:
> commit 8fe125892f40 ("net: phy: sfp: probe for RollBall I2C-to-MDIO
> bridge in mdio-i2c") introduced a regression: for SFP modules inserted
> before system boot, the RollBall I2C-to-MDIO bridge is not yet ready to
> respond to CMD_READ/CMD_DONE cycles when sfp_sm_add_mdio_bus() runs.
> The 200 ms probe times out, i2c_mii_probe_rollball() returns -ENODEV,
> and sfp_sm_add_mdio_bus() sets mdio_protocol = MDIO_I2C_NONE. By the
> time sfp_sm_probe_for_phy() runs (up to ~17 s later on affected
> hardware), the bridge is fully initialized — but PHY probing is skipped
> because the protocol has already been changed to NONE.
>
> Move the probe from i2c_mii_init_rollball() — called at bus-creation
> time — to sfp_sm_probe_for_phy() in sfp.c, where it runs after the SFP
> state machine's module initialization delays. Export the probe function
> as mdio_i2c_probe_rollball() so sfp.c can call it.
>
> For RTL8261BE-based modules: the probe correctly returns -ENODEV at PHY
> discovery time, causing sfp_sm_probe_for_phy() to destroy the MDIO bus
> and set MDIO_I2C_NONE — eliminating the 5+ minute PHY probe retry loop.
>
> For genuine RollBall modules inserted before boot (e.g. FLYPRO
> SFP-10GT-CS-30M with Aquantia AQR113C): the probe now runs after
> initialization is complete and correctly returns 0 — PHY detection
> proceeds normally.
I'm not sure I'm getting it, how come the init doesn't have time to complete
for modules that are present at boot, while it works for hotplugged modules ?
I'd expect modules to take even longer to init for hotplugged modules, as they
aren't sitting in the cage during the whole linux boot.
Maxime
--
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