The patch below does not apply to the 6.1-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to stable@vger.kernel.org.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y git checkout FETCH_HEAD git cherry-pick -x 2c27aaee934a1b5229152fe33a14f1fdf50da143 # <resolve conflicts, build, test, etc.> git commit -s git send-email --to 'stable@vger.kernel.org' --in-reply-to '2025101626-squeamish-relock-6780@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2c27aaee934a1b5229152fe33a14f1fdf50da143 Mon Sep 17 00:00:00 2001 From: Devarsh Thakkar devarsht@ti.com Date: Fri, 4 Jul 2025 18:29:15 +0530 Subject: [PATCH] phy: cadence: cdns-dphy: Update calibration wait time for startup state machine
Do read-modify-write so that we re-use the characterized reset value as specified in TRM [1] to program calibration wait time which defines number of cycles to wait for after startup state machine is in bandgap enable state.
This fixes PLL lock timeout error faced while using RPi DSI Panel on TI's AM62L and J721E SoC since earlier calibration wait time was getting overwritten to zero value thus failing the PLL to lockup and causing timeout.
[1] AM62P TRM (Section 14.8.6.3.2.1.1 DPHY_TX_DPHYTX_CMN0_CMN_DIG_TBIT2): Link: https://www.ti.com/lit/pdf/spruj83
Cc: stable@vger.kernel.org Fixes: 7a343c8bf4b5 ("phy: Add Cadence D-PHY support") Signed-off-by: Devarsh Thakkar devarsht@ti.com Tested-by: Harikrishna Shenoy h-shenoy@ti.com Reviewed-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Link: https://lore.kernel.org/r/20250704125915.1224738-3-devarsht@ti.com Signed-off-by: Vinod Koul vkoul@kernel.org
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c index da8de0a9d086..24a25606996c 100644 --- a/drivers/phy/cadence/cdns-dphy.c +++ b/drivers/phy/cadence/cdns-dphy.c @@ -30,6 +30,7 @@
#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20) #define DPHY_CMN_SSM_EN BIT(0) +#define DPHY_CMN_SSM_CAL_WAIT_TIME GENMASK(8, 1) #define DPHY_CMN_TX_MODE_EN BIT(9)
#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40) @@ -410,7 +411,8 @@ static int cdns_dphy_power_on(struct phy *phy) writel(reg, dphy->regs + DPHY_BAND_CFG);
/* Start TX state machine. */ - writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN, + reg = readl(dphy->regs + DPHY_CMN_SSM); + writel((reg & DPHY_CMN_SSM_CAL_WAIT_TIME) | DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN, dphy->regs + DPHY_CMN_SSM);
ret = cdns_dphy_wait_for_pll_lock(dphy);
From: Tomi Valkeinen tomi.valkeinen@ideasonboard.com
[ Upstream commit 689a54acb56858c85de8c7285db82b8ae6dbf683 ]
The DPHY driver does not return the actual hs_clk_rate, so the DSI driver has no idea what clock was actually achieved. Set the realized hs_clk_rate to the opts struct, so that the DSI driver gets it back.
Reviewed-by: Aradhya Bhatia aradhya.bhatia@linux.dev Tested-by: Parth Pancholi parth.pancholi@toradex.com Tested-by: Jayesh Choudhary j-choudhary@ti.com Acked-by: Vinod Koul vkoul@kernel.org Reviewed-by: Devarsh Thakkar devarsht@ti.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Link: https://lore.kernel.org/r/20250723-cdns-dphy-hs-clk-rate-fix-v1-1-d4539d44cb... Signed-off-by: Vinod Koul vkoul@kernel.org Stable-dep-of: 2c27aaee934a ("phy: cadence: cdns-dphy: Update calibration wait time for startup state machine") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/cadence/cdns-dphy.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c index 3dfdfb33cd0ac..23ab48671b79c 100644 --- a/drivers/phy/cadence/cdns-dphy.c +++ b/drivers/phy/cadence/cdns-dphy.c @@ -80,6 +80,7 @@ struct cdns_dphy_cfg { u8 pll_ipdiv; u8 pll_opdiv; u16 pll_fbdiv; + u32 hs_clk_rate; unsigned int nlanes; };
@@ -155,6 +156,9 @@ static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy, cfg->pll_ipdiv, pll_ref_hz);
+ cfg->hs_clk_rate = div_u64((u64)pll_ref_hz * cfg->pll_fbdiv, + 2 * cfg->pll_opdiv * cfg->pll_ipdiv); + return 0; }
@@ -298,6 +302,7 @@ static int cdns_dphy_config_from_opts(struct phy *phy, if (ret) return ret;
+ opts->hs_clk_rate = cfg->hs_clk_rate; opts->wakeup = cdns_dphy_get_wakeup_time_ns(dphy) / 1000;
return 0;
From: Devarsh Thakkar devarsht@ti.com
[ Upstream commit 284fb19a3ffb1083c3ad9c00d29749d09dddb99c ]
PLL lockup and O_CMN_READY assertion can only happen after common state machine gets enabled by programming DPHY_CMN_SSM register, but driver was polling them before the common state machine was enabled which is incorrect. This is as per the DPHY initialization sequence as mentioned in J721E TRM [1] at section "12.7.2.4.1.2.1 Start-up Sequence Timing Diagram". It shows O_CMN_READY polling at the end after common configuration pin setup where the common configuration pin setup step enables state machine as referenced in "Table 12-1533. Common Configuration-Related Setup mentions state machine"
To fix this : - Add new function callbacks for polling on PLL lock and O_CMN_READY assertion. - As state machine and clocks get enabled in power_on callback only, move the clock related programming part from configure callback to power_on callback and poll for the PLL lockup and O_CMN_READY assertion after state machine gets enabled. - The configure callback only saves the PLL configuration received from the client driver which will be applied later on in power_on callback. - Add checks to ensure configure is called before power_on and state machine is in disabled state before power_on callback is called. - Disable state machine in power_off so that client driver can re-configure the PLL by following up a power_off, configure, power_on sequence.
[1]: https://www.ti.com/lit/zip/spruil1
Cc: stable@vger.kernel.org Fixes: 7a343c8bf4b5 ("phy: Add Cadence D-PHY support") Signed-off-by: Devarsh Thakkar devarsht@ti.com Tested-by: Harikrishna Shenoy h-shenoy@ti.com Reviewed-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Link: https://lore.kernel.org/r/20250704125915.1224738-2-devarsht@ti.com Signed-off-by: Vinod Koul vkoul@kernel.org Stable-dep-of: 2c27aaee934a ("phy: cadence: cdns-dphy: Update calibration wait time for startup state machine") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/cadence/cdns-dphy.c | 124 +++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 32 deletions(-)
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c index 23ab48671b79c..3d62553a630d6 100644 --- a/drivers/phy/cadence/cdns-dphy.c +++ b/drivers/phy/cadence/cdns-dphy.c @@ -101,6 +101,8 @@ struct cdns_dphy_ops { void (*set_pll_cfg)(struct cdns_dphy *dphy, const struct cdns_dphy_cfg *cfg); unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy); + int (*wait_for_pll_lock)(struct cdns_dphy *dphy); + int (*wait_for_cmn_ready)(struct cdns_dphy *dphy); };
struct cdns_dphy { @@ -110,6 +112,8 @@ struct cdns_dphy { struct clk *pll_ref_clk; const struct cdns_dphy_ops *ops; struct phy *phy; + bool is_configured; + bool is_powered; };
/* Order of bands is important since the index is the band number. */ @@ -196,6 +200,16 @@ static unsigned long cdns_dphy_get_wakeup_time_ns(struct cdns_dphy *dphy) return dphy->ops->get_wakeup_time_ns(dphy); }
+static int cdns_dphy_wait_for_pll_lock(struct cdns_dphy *dphy) +{ + return dphy->ops->wait_for_pll_lock ? dphy->ops->wait_for_pll_lock(dphy) : 0; +} + +static int cdns_dphy_wait_for_cmn_ready(struct cdns_dphy *dphy) +{ + return dphy->ops->wait_for_cmn_ready ? dphy->ops->wait_for_cmn_ready(dphy) : 0; +} + static unsigned long cdns_dphy_ref_get_wakeup_time_ns(struct cdns_dphy *dphy) { /* Default wakeup time is 800 ns (in a simulated environment). */ @@ -237,7 +251,6 @@ static unsigned long cdns_dphy_j721e_get_wakeup_time_ns(struct cdns_dphy *dphy) static void cdns_dphy_j721e_set_pll_cfg(struct cdns_dphy *dphy, const struct cdns_dphy_cfg *cfg) { - u32 status;
/* * set the PWM and PLL Byteclk divider settings to recommended values @@ -254,13 +267,6 @@ static void cdns_dphy_j721e_set_pll_cfg(struct cdns_dphy *dphy,
writel(DPHY_TX_J721E_WIZ_LANE_RSTB, dphy->regs + DPHY_TX_J721E_WIZ_RST_CTRL); - - readl_poll_timeout(dphy->regs + DPHY_TX_J721E_WIZ_PLL_CTRL, status, - (status & DPHY_TX_WIZ_PLL_LOCK), 0, POLL_TIMEOUT_US); - - readl_poll_timeout(dphy->regs + DPHY_TX_J721E_WIZ_STATUS, status, - (status & DPHY_TX_WIZ_O_CMN_READY), 0, - POLL_TIMEOUT_US); }
static void cdns_dphy_j721e_set_psm_div(struct cdns_dphy *dphy, u8 div) @@ -268,6 +274,23 @@ static void cdns_dphy_j721e_set_psm_div(struct cdns_dphy *dphy, u8 div) writel(div, dphy->regs + DPHY_TX_J721E_WIZ_PSM_FREQ); }
+static int cdns_dphy_j721e_wait_for_pll_lock(struct cdns_dphy *dphy) +{ + u32 status; + + return readl_poll_timeout(dphy->regs + DPHY_TX_J721E_WIZ_PLL_CTRL, status, + status & DPHY_TX_WIZ_PLL_LOCK, 0, POLL_TIMEOUT_US); +} + +static int cdns_dphy_j721e_wait_for_cmn_ready(struct cdns_dphy *dphy) +{ + u32 status; + + return readl_poll_timeout(dphy->regs + DPHY_TX_J721E_WIZ_STATUS, status, + status & DPHY_TX_WIZ_O_CMN_READY, 0, + POLL_TIMEOUT_US); +} + /* * This is the reference implementation of DPHY hooks. Specific integration of * this IP may have to re-implement some of them depending on how they decided @@ -283,6 +306,8 @@ static const struct cdns_dphy_ops j721e_dphy_ops = { .get_wakeup_time_ns = cdns_dphy_j721e_get_wakeup_time_ns, .set_pll_cfg = cdns_dphy_j721e_set_pll_cfg, .set_psm_div = cdns_dphy_j721e_set_psm_div, + .wait_for_pll_lock = cdns_dphy_j721e_wait_for_pll_lock, + .wait_for_cmn_ready = cdns_dphy_j721e_wait_for_cmn_ready, };
static int cdns_dphy_config_from_opts(struct phy *phy, @@ -340,21 +365,36 @@ static int cdns_dphy_validate(struct phy *phy, enum phy_mode mode, int submode, static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts) { struct cdns_dphy *dphy = phy_get_drvdata(phy); - struct cdns_dphy_cfg cfg = { 0 }; - int ret, band_ctrl; - unsigned int reg; + int ret;
- ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &cfg); - if (ret) - return ret; + ret = cdns_dphy_config_from_opts(phy, &opts->mipi_dphy, &dphy->cfg); + if (!ret) + dphy->is_configured = true; + + return ret; +} + +static int cdns_dphy_power_on(struct phy *phy) +{ + struct cdns_dphy *dphy = phy_get_drvdata(phy); + int ret; + u32 reg; + + if (!dphy->is_configured || dphy->is_powered) + return -EINVAL; + + clk_prepare_enable(dphy->psm_clk); + clk_prepare_enable(dphy->pll_ref_clk);
/* * Configure the internal PSM clk divider so that the DPHY has a * 1MHz clk (or something close). */ ret = cdns_dphy_setup_psm(dphy); - if (ret) - return ret; + if (ret) { + dev_err(&dphy->phy->dev, "Failed to setup PSM with error %d\n", ret); + goto err_power_on; + }
/* * Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes @@ -369,40 +409,60 @@ static int cdns_dphy_configure(struct phy *phy, union phy_configure_opts *opts) * Configure the DPHY PLL that will be used to generate the TX byte * clk. */ - cdns_dphy_set_pll_cfg(dphy, &cfg); + cdns_dphy_set_pll_cfg(dphy, &dphy->cfg);
- band_ctrl = cdns_dphy_tx_get_band_ctrl(opts->mipi_dphy.hs_clk_rate); - if (band_ctrl < 0) - return band_ctrl; + ret = cdns_dphy_tx_get_band_ctrl(dphy->cfg.hs_clk_rate); + if (ret < 0) { + dev_err(&dphy->phy->dev, "Failed to get band control value with error %d\n", ret); + goto err_power_on; + }
- reg = FIELD_PREP(DPHY_BAND_CFG_LEFT_BAND, band_ctrl) | - FIELD_PREP(DPHY_BAND_CFG_RIGHT_BAND, band_ctrl); + reg = FIELD_PREP(DPHY_BAND_CFG_LEFT_BAND, ret) | + FIELD_PREP(DPHY_BAND_CFG_RIGHT_BAND, ret); writel(reg, dphy->regs + DPHY_BAND_CFG);
- return 0; -} - -static int cdns_dphy_power_on(struct phy *phy) -{ - struct cdns_dphy *dphy = phy_get_drvdata(phy); - - clk_prepare_enable(dphy->psm_clk); - clk_prepare_enable(dphy->pll_ref_clk); - /* Start TX state machine. */ writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN, dphy->regs + DPHY_CMN_SSM);
+ ret = cdns_dphy_wait_for_pll_lock(dphy); + if (ret) { + dev_err(&dphy->phy->dev, "Failed to lock PLL with error %d\n", ret); + goto err_power_on; + } + + ret = cdns_dphy_wait_for_cmn_ready(dphy); + if (ret) { + dev_err(&dphy->phy->dev, "O_CMN_READY signal failed to assert with error %d\n", + ret); + goto err_power_on; + } + + dphy->is_powered = true; + return 0; + +err_power_on: + clk_disable_unprepare(dphy->pll_ref_clk); + clk_disable_unprepare(dphy->psm_clk); + + return ret; }
static int cdns_dphy_power_off(struct phy *phy) { struct cdns_dphy *dphy = phy_get_drvdata(phy); + u32 reg;
clk_disable_unprepare(dphy->pll_ref_clk); clk_disable_unprepare(dphy->psm_clk);
+ /* Stop TX state machine. */ + reg = readl(dphy->regs + DPHY_CMN_SSM); + writel(reg & ~DPHY_CMN_SSM_EN, dphy->regs + DPHY_CMN_SSM); + + dphy->is_powered = false; + return 0; }
From: Devarsh Thakkar devarsht@ti.com
[ Upstream commit 2c27aaee934a1b5229152fe33a14f1fdf50da143 ]
Do read-modify-write so that we re-use the characterized reset value as specified in TRM [1] to program calibration wait time which defines number of cycles to wait for after startup state machine is in bandgap enable state.
This fixes PLL lock timeout error faced while using RPi DSI Panel on TI's AM62L and J721E SoC since earlier calibration wait time was getting overwritten to zero value thus failing the PLL to lockup and causing timeout.
[1] AM62P TRM (Section 14.8.6.3.2.1.1 DPHY_TX_DPHYTX_CMN0_CMN_DIG_TBIT2): Link: https://www.ti.com/lit/pdf/spruj83
Cc: stable@vger.kernel.org Fixes: 7a343c8bf4b5 ("phy: Add Cadence D-PHY support") Signed-off-by: Devarsh Thakkar devarsht@ti.com Tested-by: Harikrishna Shenoy h-shenoy@ti.com Reviewed-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Link: https://lore.kernel.org/r/20250704125915.1224738-3-devarsht@ti.com Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/phy/cadence/cdns-dphy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c index 3d62553a630d6..d65a7aeefe792 100644 --- a/drivers/phy/cadence/cdns-dphy.c +++ b/drivers/phy/cadence/cdns-dphy.c @@ -31,6 +31,7 @@
#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20) #define DPHY_CMN_SSM_EN BIT(0) +#define DPHY_CMN_SSM_CAL_WAIT_TIME GENMASK(8, 1) #define DPHY_CMN_TX_MODE_EN BIT(9)
#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40) @@ -422,7 +423,8 @@ static int cdns_dphy_power_on(struct phy *phy) writel(reg, dphy->regs + DPHY_BAND_CFG);
/* Start TX state machine. */ - writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN, + reg = readl(dphy->regs + DPHY_CMN_SSM); + writel((reg & DPHY_CMN_SSM_CAL_WAIT_TIME) | DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN, dphy->regs + DPHY_CMN_SSM);
ret = cdns_dphy_wait_for_pll_lock(dphy);
linux-stable-mirror@lists.linaro.org