* [PATCH v5 01/10] phy: rockchip: samsung-hdptx: Fix rate recalculation for high bpc
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 02/10] phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate Cristian Ciocaltea
` (8 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Thomas Niederprüm, Simon Wright, Diederik de Haas, Andy Yan,
Dmitry Baryshkov
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>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS
Reviewed-by: Andy Yan <andyshrk@gmail.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
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.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v5 02/10] phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 01/10] phy: rockchip: samsung-hdptx: Fix rate recalculation for high bpc Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 19:55 ` sashiko-bot
2026-07-23 19:41 ` [PATCH v5 03/10] phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow Cristian Ciocaltea
` (7 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Sashiko, Diederik de Haas, Dmitry Baryshkov, Andy Yan
Calculating 'sdm' fraction in rk_hdptx_phy_clk_calc_rate_from_pll_cfg()
could trigger a divide-by-zero, as it uses div_u64() with a denominator
read directly from hardware: the values ropll_hw.sdm_deno,
ropll_hw.sdc_deno, ropll_hw.sdc_n, and ropll_hw.sdc_num are populated
from PLL registers which, in theory, could be left by the bootloader
uninitialized/misconfigured.
Provide the necessary sanitization to avoid trusting the hardware state.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260611-hdptx-clk-fixes-v3-0-67b1b0c00e16@collabora.com?part=1
Fixes: 3481fc04d969 ("phy: rockchip: samsung-hdptx: Compute clk rate from PLL config")
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Andy Yan <andy.yan@rock-chips.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 710603afff86..44e99343f249 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -2270,10 +2270,15 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
fout = PLL_REF_CLK * ropll_hw.pms_mdiv;
if (ropll_hw.sdm_en) {
+ val = 16U * ropll_hw.sdm_deno *
+ (ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num);
+ if (!val) {
+ dev_dbg(hdptx->dev, "Invalid ROPLL hw state: deno == 0\n");
+ return 0;
+ }
+
sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
- ropll_hw.pms_mdiv * ropll_hw.sdm_num,
- 16 * ropll_hw.sdm_deno *
- (ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num));
+ ropll_hw.pms_mdiv * ropll_hw.sdm_num, val);
if (ropll_hw.sdm_num_sign)
fout = fout - sdm;
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v5 02/10] phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate
2026-07-23 19:41 ` [PATCH v5 02/10] phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate Cristian Ciocaltea
@ 2026-07-23 19:55 ` sashiko-bot
2026-07-23 21:40 ` Cristian Ciocaltea
0 siblings, 1 reply; 19+ messages in thread
From: sashiko-bot @ 2026-07-23 19:55 UTC (permalink / raw)
To: Cristian Ciocaltea; +Cc: vkoul, olteanv, linux-phy, neil.armstrong
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Clock rate determination fails in FRL mode due to returning raw rate instead of 0.
- [High] Unintended state mutation of `hdmi_cfg` during `determine_rate` read queries.
--
--- Patch [2]: [PATCH v5 02/10] phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate ---
commit 3aac52ab862cd2c54c76fff590e3524e49936631
Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate
Calculating 'sdm' fraction in rk_hdptx_phy_clk_calc_rate_from_pll_cfg()
could trigger a divide-by-zero, as it uses div_u64() with a denominator
read directly from hardware. Provide the necessary sanitization to avoid
trusting the hardware state.
Link: https://sashiko.dev/#/patchset/20260611-hdptx-clk-fixes-v3-0-67b1b0c00e16@collabora.com?part=1
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index 710603afff866..44e99343f2499 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
[ ... ]
> @@ -2270,10 +2270,15 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
>
> fout = PLL_REF_CLK * ropll_hw.pms_mdiv;
> if (ropll_hw.sdm_en) {
> + val = 16U * ropll_hw.sdm_deno *
> + (ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num);
> + if (!val) {
> + dev_dbg(hdptx->dev, "Invalid ROPLL hw state: deno == 0\n");
> + return 0;
> + }
> +
> sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
> - ropll_hw.pms_mdiv * ropll_hw.sdm_num,
> - 16 * ropll_hw.sdm_deno *
> - (ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num));
> + ropll_hw.pms_mdiv * ropll_hw.sdm_num, val);
>
> if (ropll_hw.sdm_num_sign)
> fout = fout - sdm;
While reviewing this patch, I noticed a couple of pre-existing issues in the
adjacent rk_hdptx_phy_clk_determine_rate() function:
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c:rk_hdptx_phy_clk_determine_rate() {
...
if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
return hdptx->hdmi_cfg.rate;
[Severity: High]
This isn't a bug introduced by this patch, but does this violate the
determine_rate API contract?
When the PHY is in FRL mode, the callback directly returns
hdptx->hdmi_cfg.rate (e.g., up to 3.2GHz). However, the Common Clock
Framework expects determine_rate to return 0 on success and update
req->rate.
Returning these massive positive integers casts them to a signed 32-bit int,
causing rates like 3.2GHz to overflow into a negative error code
(e.g., -1094277376).
Will clk_core_determine_round_nolock() propagate this negative error,
causing clk_set_rate() to abort and fail completely for FRL modes?
...
int ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &hdmi, &hdptx->hdmi_cfg);
[Severity: High]
This is a pre-existing issue, but does this mutate the driver's internal
PHY configuration state during what should be a stateless query?
The determine_rate clock operation must be a stateless read query
(clk_round_rate). However, passing &hdptx->hdmi_cfg as the output parameter
to rk_hdptx_phy_verify_hdmi_config() modifies hdptx->hdmi_cfg.rate and bpc.
Since clk_round_rate can be called multiple times with different
hypothetical rates before any actual rate changes are committed, could
this corrupt the actual hardware tracking state?
If the rate change is subsequently aborted or clk_set_rate is called
with a different best rate, would hdptx->hdmi_cfg be left in an
inconsistent state, causing the actual hardware configuration to be
misconfigured?
}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260723-hdptx-clk-fixes-v5-0-8e786067865f@collabora.com?part=2
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v5 02/10] phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate
2026-07-23 19:55 ` sashiko-bot
@ 2026-07-23 21:40 ` Cristian Ciocaltea
0 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 21:40 UTC (permalink / raw)
To: sashiko-reviews; +Cc: vkoul, olteanv, linux-phy, neil.armstrong
On 7/23/26 10:55 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] Clock rate determination fails in FRL mode due to returning raw rate instead of 0.
> - [High] Unintended state mutation of `hdmi_cfg` during `determine_rate` read queries.
> --
>
> --- Patch [2]: [PATCH v5 02/10] phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate ---
> commit 3aac52ab862cd2c54c76fff590e3524e49936631
> Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
>
> phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate
>
> Calculating 'sdm' fraction in rk_hdptx_phy_clk_calc_rate_from_pll_cfg()
> could trigger a divide-by-zero, as it uses div_u64() with a denominator
> read directly from hardware. Provide the necessary sanitization to avoid
> trusting the hardware state.
>
> Link: https://sashiko.dev/#/patchset/20260611-hdptx-clk-fixes-v3-0-67b1b0c00e16@collabora.com?part=1
>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> index 710603afff866..44e99343f2499 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>
> [ ... ]
>
>> @@ -2270,10 +2270,15 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
>>
>> fout = PLL_REF_CLK * ropll_hw.pms_mdiv;
>> if (ropll_hw.sdm_en) {
>> + val = 16U * ropll_hw.sdm_deno *
>> + (ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num);
>> + if (!val) {
>> + dev_dbg(hdptx->dev, "Invalid ROPLL hw state: deno == 0\n");
>> + return 0;
>> + }
>> +
>> sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
>> - ropll_hw.pms_mdiv * ropll_hw.sdm_num,
>> - 16 * ropll_hw.sdm_deno *
>> - (ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num));
>> + ropll_hw.pms_mdiv * ropll_hw.sdm_num, val);
>>
>> if (ropll_hw.sdm_num_sign)
>> fout = fout - sdm;
>
> While reviewing this patch, I noticed a couple of pre-existing issues in the
> adjacent rk_hdptx_phy_clk_determine_rate() function:
>
> drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c:rk_hdptx_phy_clk_determine_rate() {
> ...
> if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
> return hdptx->hdmi_cfg.rate;
>
> [Severity: High]
> This isn't a bug introduced by this patch, but does this violate the
> determine_rate API contract?
Already answered:
https://lore.kernel.org/all/0afce8ee-0277-4fad-adbe-ceb064f66437@collabora.com/
> [Severity: High]
> This is a pre-existing issue, but does this mutate the driver's internal
> PHY configuration state during what should be a stateless query?
>
> The determine_rate clock operation must be a stateless read query
> (clk_round_rate). However, passing &hdptx->hdmi_cfg as the output parameter
> to rk_hdptx_phy_verify_hdmi_config() modifies hdptx->hdmi_cfg.rate and bpc.
This was part of the workaround removed via [PATCH v5 08/10] phy: rockchip:
samsung-hdptx: Drop restrict_rate_change handling:
- /*
- * FIXME: Temporarily allow altering TMDS char rate via CCF.
- * To be dropped as soon as the RK DW HDMI QP bridge driver
- * switches to make use of phy_configure().
- */
- if (!hdptx->restrict_rate_change && req->rate != hdptx->hdmi_cfg.rate) {
- struct phy_configure_opts_hdmi hdmi = {
- .tmds_char_rate = req->rate,
- };
-
- int ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &hdmi, &hdptx->hdmi_cfg);
-
- if (ret)
- return ret;
- }
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v5 03/10] phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 01/10] phy: rockchip: samsung-hdptx: Fix rate recalculation for high bpc Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 02/10] phy: rockchip: samsung-hdptx: Prevent divide-by-zero when computing clk rate Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 19:57 ` sashiko-bot
2026-07-23 19:41 ` [PATCH v5 04/10] phy: rockchip: samsung-hdptx: Fix rate recalculation for 3.2GHz FRL Cristian Ciocaltea
` (6 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Sashiko
The 'fout' subtraction in rk_hdptx_phy_clk_calc_rate_from_pll_cfg()
could result in an integer underflow, if the hardware registers are
misconfigured or contain uninitialized values, such that the computed
sigma-delta modulator offset sdm exceeds the base frequency fout.
This might lead to an absurdly high clock rate being returned to the
Common Clock Framework, with unpredictable effects on downstream clk
consumers.
Provide the necessary sanitization to avoid trusting the hardware state.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260611235702.0E9691F000E9@smtp.kernel.org/
Fixes: 3481fc04d969 ("phy: rockchip: samsung-hdptx: Compute clk rate from PLL config")
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 44e99343f249..fcf04e9814cc 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -2280,10 +2280,16 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
ropll_hw.pms_mdiv * ropll_hw.sdm_num, val);
- if (ropll_hw.sdm_num_sign)
+ if (ropll_hw.sdm_num_sign) {
+ if (sdm > fout) {
+ dev_dbg(hdptx->dev, "Invalid ROPLL hw state: sdm > fout\n");
+ return 0;
+ }
+
fout = fout - sdm;
- else
+ } else {
fout = fout + sdm;
+ }
}
return DIV_ROUND_CLOSEST_ULL(fout * 2 * 8, ropll_hw.pms_sdiv * 10 * bpc);
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v5 03/10] phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow
2026-07-23 19:41 ` [PATCH v5 03/10] phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow Cristian Ciocaltea
@ 2026-07-23 19:57 ` sashiko-bot
2026-07-23 21:22 ` Cristian Ciocaltea
0 siblings, 1 reply; 19+ messages in thread
From: sashiko-bot @ 2026-07-23 19:57 UTC (permalink / raw)
To: Cristian Ciocaltea; +Cc: olteanv, neil.armstrong, vkoul, linux-phy
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] rk_hdptx_phy_clk_determine_rate() incorrectly returns a clock rate directly instead of 0 on success, violating the CCF API.
--
--- Patch [3]: [PATCH v5 03/10] phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow ---
commit cf68603e6625cb39a98418e9f792a4e2e373dfcd
Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow
This commit adds a check to avoid an integer underflow in the ROPLL
hardware state calculation. By validating that the computed sigma-delta
modulator offset does not exceed the base frequency, it prevents
returning excessively high clock rates to the Common Clock Framework.
Closes: https://lore.kernel.org/all/20260611235702.0E9691F000E9@smtp.kernel.org/
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index 44e99343f2499..fcf04e9814cc6 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -2280,10 +2280,16 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
> sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
> ropll_hw.pms_mdiv * ropll_hw.sdm_num, val);
>
> - if (ropll_hw.sdm_num_sign)
> + if (ropll_hw.sdm_num_sign) {
> + if (sdm > fout) {
> + dev_dbg(hdptx->dev, "Invalid ROPLL hw state: sdm > fout\n");
> + return 0;
> + }
> +
> fout = fout - sdm;
> - else
> + } else {
> fout = fout + sdm;
> + }
> }
>
> return DIV_ROUND_CLOSEST_ULL(fout * 2 * 8, ropll_hw.pms_sdiv * 10 * bpc);
> }
[Severity: High]
This is a pre-existing issue, but I noticed a potential problem in
rk_hdptx_phy_clk_determine_rate() located nearby in the same file:
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c:rk_hdptx_phy_clk_determine_rate() {
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
return hdptx->hdmi_cfg.rate;
...
}
Does this violate the Common Clock Framework API contract for
.determine_rate callbacks?
The .determine_rate callback is expected to update req->rate and return 0
on success. By returning the rate directly, it appears this fails to update
the request and instead returns a massive integer.
For FRL_8G4L_RATE (3,200,000,000), casting it to a 32-bit signed int would
wrap around to a negative value (-1,094,967,296).
When the clock rate is negotiated or set for 8Gbps FRL mode, CCF could
receive this wrapped negative value, interpret it as an error code, and
cause clk_set_rate() to fail entirely.
Even for smaller rates that do not wrap, leaving req->rate unmodified might
bypass rounding and cause downstream failures in HDMI configuration.
Should this instead update req->rate and return 0?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260723-hdptx-clk-fixes-v5-0-8e786067865f@collabora.com?part=3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v5 03/10] phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow
2026-07-23 19:57 ` sashiko-bot
@ 2026-07-23 21:22 ` Cristian Ciocaltea
0 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 21:22 UTC (permalink / raw)
To: sashiko-reviews; +Cc: olteanv, neil.armstrong, vkoul, linux-phy
On 7/23/26 10:57 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] rk_hdptx_phy_clk_determine_rate() incorrectly returns a clock rate directly instead of 0 on success, violating the CCF API.
> --
>
> --- Patch [3]: [PATCH v5 03/10] phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow ---
> commit cf68603e6625cb39a98418e9f792a4e2e373dfcd
> Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
>
> phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow
>
> This commit adds a check to avoid an integer underflow in the ROPLL
> hardware state calculation. By validating that the computed sigma-delta
> modulator offset does not exceed the base frequency, it prevents
> returning excessively high clock rates to the Common Clock Framework.
>
> Closes: https://lore.kernel.org/all/20260611235702.0E9691F000E9@smtp.kernel.org/
>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> index 44e99343f2499..fcf04e9814cc6 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> @@ -2280,10 +2280,16 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
>> sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
>> ropll_hw.pms_mdiv * ropll_hw.sdm_num, val);
>>
>> - if (ropll_hw.sdm_num_sign)
>> + if (ropll_hw.sdm_num_sign) {
>> + if (sdm > fout) {
>> + dev_dbg(hdptx->dev, "Invalid ROPLL hw state: sdm > fout\n");
>> + return 0;
>> + }
>> +
>> fout = fout - sdm;
>> - else
>> + } else {
>> fout = fout + sdm;
>> + }
>> }
>>
>> return DIV_ROUND_CLOSEST_ULL(fout * 2 * 8, ropll_hw.pms_sdiv * 10 * bpc);
>> }
>
> [Severity: High]
> This is a pre-existing issue, but I noticed a potential problem in
> rk_hdptx_phy_clk_determine_rate() located nearby in the same file:
>
> drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c:rk_hdptx_phy_clk_determine_rate() {
> struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
>
> if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
> return hdptx->hdmi_cfg.rate;
> ...
> }
>
> Does this violate the Common Clock Framework API contract for
> .determine_rate callbacks?
>
> The .determine_rate callback is expected to update req->rate and return 0
> on success. By returning the rate directly, it appears this fails to update
> the request and instead returns a massive integer.
>
> For FRL_8G4L_RATE (3,200,000,000), casting it to a 32-bit signed int would
> wrap around to a negative value (-1,094,967,296).
>
> When the clock rate is negotiated or set for 8Gbps FRL mode, CCF could
> receive this wrapped negative value, interpret it as an error code, and
> cause clk_set_rate() to fail entirely.
>
> Even for smaller rates that do not wrap, leaving req->rate unmodified might
> bypass rounding and cause downstream failures in HDMI configuration.
>
> Should this instead update req->rate and return 0?
This is implicitly fixed by [PATCH v5 05/10] phy: rockchip: samsung-hdptx:
Handle uncommitted PHY config changes. If a new revision is required, I can
provide a dedicated patch.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v5 04/10] phy: rockchip: samsung-hdptx: Fix rate recalculation for 3.2GHz FRL
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
` (2 preceding siblings ...)
2026-07-23 19:41 ` [PATCH v5 03/10] phy: rockchip: samsung-hdptx: Guard against clk rate integer underflow Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 05/10] phy: rockchip: samsung-hdptx: Handle uncommitted PHY config changes Cristian Ciocaltea
` (5 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Sashiko, Diederik de Haas, Dmitry Baryshkov, Andy Yan
rk_hdptx_phy_clk_calc_rate_from_pll_cfg() is currently unable to handle
cascade mode for the 3.2GHz FRL operating mode, as it relies solely on
LCPLL_LCVCO_MODE_EN_MASK to determinate the rate from the
rk_hdptx_frl_lcpll_cfg array. Since there is no entry for this
particular rate, the function returns 0.
This is the only rate which requires LC_REF_CLK_SEL to be set in
GRF_HDPTX_CON0, hence extend the FRL matching accordingly.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260611-hdptx-clk-fixes-v3-0-67b1b0c00e16@collabora.com?part=1
Fixes: de5dba833118 ("phy: rockchip: samsung-hdptx: Add HDMI 2.1 FRL support")
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Andy Yan <andy.yan@rock-chips.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 33 ++++++++++++++++-------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index fcf04e9814cc..3a1a43ec2552 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -2206,16 +2206,31 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
return 0;
lcpll_hw.sdc_n = (val & LCPLL_SDC_N_MASK) >> 1;
- for (i = 0; i < ARRAY_SIZE(rk_hdptx_frl_lcpll_cfg); i++) {
- const struct lcpll_config *cfg = &rk_hdptx_frl_lcpll_cfg[i];
+ ret = regmap_read(hdptx->grf, GRF_HDPTX_CON0, &val);
+ if (ret)
+ return 0;
- if (cfg->pms_mdiv == lcpll_hw.pms_mdiv &&
- cfg->pms_sdiv == lcpll_hw.pms_sdiv &&
- cfg->sdm_num_sign == lcpll_hw.sdm_num_sign &&
- cfg->sdm_num == lcpll_hw.sdm_num &&
- cfg->sdm_deno == lcpll_hw.sdm_deno &&
- cfg->sdc_n == lcpll_hw.sdc_n)
- return cfg->rate;
+ if (val & LC_REF_CLK_SEL) {
+ if (lcpll_hw.pms_mdiv == 0x6b &&
+ lcpll_hw.sdm_num_sign == 0x01 &&
+ lcpll_hw.sdm_num == 0x02 &&
+ lcpll_hw.sdm_deno == 0x09 &&
+ lcpll_hw.sdc_n == FIELD_GET(LCPLL_SDC_N_MASK, 0x02))
+ return FRL_8G4L_RATE;
+ } else {
+ const struct lcpll_config *cfg;
+
+ for (i = 0; i < ARRAY_SIZE(rk_hdptx_frl_lcpll_cfg); i++) {
+ cfg = &rk_hdptx_frl_lcpll_cfg[i];
+
+ if (cfg->pms_mdiv == lcpll_hw.pms_mdiv &&
+ cfg->pms_sdiv == lcpll_hw.pms_sdiv &&
+ cfg->sdm_num_sign == lcpll_hw.sdm_num_sign &&
+ cfg->sdm_num == lcpll_hw.sdm_num &&
+ cfg->sdm_deno == lcpll_hw.sdm_deno &&
+ cfg->sdc_n == lcpll_hw.sdc_n)
+ return cfg->rate;
+ }
}
dev_dbg(hdptx->dev, "%s no FRL match found\n", __func__);
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v5 05/10] phy: rockchip: samsung-hdptx: Handle uncommitted PHY config changes
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
` (3 preceding siblings ...)
2026-07-23 19:41 ` [PATCH v5 04/10] phy: rockchip: samsung-hdptx: Fix rate recalculation for 3.2GHz FRL Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 20:00 ` sashiko-bot
2026-07-23 19:41 ` [PATCH v5 06/10] phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround Cristian Ciocaltea
` (4 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Thomas Niederprüm, Simon Wright, Diederik de Haas, Andy Yan
Any changes to the PHY link rate and/or color depth done via the HDMI
PHY configuration API are not immediately programmed into the hardware,
but are delayed until the PHY usage count gets incremented from 0 to 1,
that is when it is powered on or when the PLL clock exposed through
the CCF API is prepared, whichever comes first.
Since the clock might remain in prepared state after subsequent PHY
config changes, the programming can also be triggered via
clk_ops.set_rate(). However, from the clock consumer perspective (i.e.
VOP2 display controller), the (pixel) clock rate doesn't vary with bpc,
as that is handled internally by the PHY and reflected in the TDMS
character rate only.
As a consequence, changing the bpc while preserving the modeline may
lead to out-of-sync issues between CCF and HDMI PHY config state,
because the .set_rate() callback is not invoked when clock rate remains
constant. This may also happen when the PHY PLL has been pre-programmed
by an external entity, e.g. the bootloader, which is actually a
regression introduced by the recent FRL patches.
Introduce a pll_config_dirty flag to keep track of uncommitted PHY
config changes and use it in clk_ops.determine_rate() to invalidate the
current clock rate (as known by CCF) and, consequently, ensure those
changes are programmed into hardware via clk_ops.set_rate().
Moreover, proceed with a similar fix in phy_ops.power_on() callback, to
handle the scenario where the CCF API is not used due to operating in
FRL mode, while the clock is still in a prepared state and thus
preventing rk_hdptx_phy_consumer_get() to apply the updated PHY
configuration.
Fixes: de5dba833118 ("phy: rockchip: samsung-hdptx: Add HDMI 2.1 FRL support")
Fixes: 9d0ec51d7c22 ("phy: rockchip: samsung-hdptx: Add high color depth management")
Tested-by: Thomas Niederprüm <dubito@online.de>
Tested-by: Simon Wright <simon@symple.nz>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS
Reviewed-by: Andy Yan <andy.yan@rock-chips.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 84 +++++++++++++----------
1 file changed, 48 insertions(+), 36 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 3a1a43ec2552..792eb57755eb 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -413,6 +413,7 @@ struct rk_hdptx_phy {
/* clk provider */
struct clk_hw hw;
+ bool pll_config_dirty;
bool restrict_rate_change;
atomic_t usage_count;
@@ -1260,13 +1261,19 @@ static int rk_hdptx_tmds_ropll_cmn_config(struct rk_hdptx_phy *hdptx)
static int rk_hdptx_pll_cmn_config(struct rk_hdptx_phy *hdptx)
{
+ int ret;
+
if (hdptx->hdmi_cfg.rate <= HDMI20_MAX_RATE)
- return rk_hdptx_tmds_ropll_cmn_config(hdptx);
+ ret = rk_hdptx_tmds_ropll_cmn_config(hdptx);
+ else if (hdptx->hdmi_cfg.rate == FRL_8G4L_RATE)
+ ret = rk_hdptx_frl_lcpll_ropll_cmn_config(hdptx);
+ else
+ ret = rk_hdptx_frl_lcpll_cmn_config(hdptx);
- if (hdptx->hdmi_cfg.rate == FRL_8G4L_RATE)
- return rk_hdptx_frl_lcpll_ropll_cmn_config(hdptx);
+ if (!ret)
+ hdptx->pll_config_dirty = false;
- return rk_hdptx_frl_lcpll_cmn_config(hdptx);
+ return ret;
}
static int rk_hdptx_frl_lcpll_mode_config(struct rk_hdptx_phy *hdptx)
@@ -1347,25 +1354,22 @@ static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
return 0;
ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status);
- if (ret)
- goto dec_usage;
-
- if (status & HDPTX_O_PLL_LOCK_DONE)
- dev_warn(hdptx->dev, "PLL locked by unknown consumer!\n");
+ if (ret) {
+ atomic_dec(&hdptx->usage_count);
+ return ret;
+ }
if (mode == PHY_MODE_DP) {
rk_hdptx_dp_reset(hdptx);
} else {
- ret = rk_hdptx_pll_cmn_config(hdptx);
- if (ret)
- goto dec_usage;
+ /*
+ * Ignore PLL config errors at this point as pll_config_dirty
+ * was not reset and, therefore, operation will be retried.
+ */
+ rk_hdptx_pll_cmn_config(hdptx);
}
return 0;
-
-dec_usage:
- atomic_dec(&hdptx->usage_count);
- return ret;
}
static int rk_hdptx_phy_consumer_put(struct rk_hdptx_phy *hdptx, bool force)
@@ -1700,13 +1704,18 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
if (ret)
rk_hdptx_phy_consumer_put(hdptx, true);
} else {
- regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
+ if (hdptx->pll_config_dirty)
+ ret = rk_hdptx_pll_cmn_config(hdptx);
- if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
- ret = rk_hdptx_frl_lcpll_mode_config(hdptx);
- else
- ret = rk_hdptx_tmds_ropll_mode_config(hdptx);
+ if (!ret) {
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0,
+ HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
+
+ if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
+ ret = rk_hdptx_frl_lcpll_mode_config(hdptx);
+ else
+ ret = rk_hdptx_tmds_ropll_mode_config(hdptx);
+ }
if (ret)
rk_hdptx_phy_consumer_put(hdptx, true);
@@ -2081,7 +2090,10 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
} else {
hdptx->restrict_rate_change = true;
- dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
+ hdptx->pll_config_dirty = true;
+
+ dev_dbg(hdptx->dev, "%s %s rate=%llu bpc=%u\n", __func__,
+ hdptx->hdmi_cfg.mode ? "FRL" : "TMDS",
hdptx->hdmi_cfg.rate, hdptx->hdmi_cfg.bpc);
}
@@ -2329,8 +2341,19 @@ static int rk_hdptx_phy_clk_determine_rate(struct clk_hw *hw,
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
- if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
- return hdptx->hdmi_cfg.rate;
+ /*
+ * Invalidate current clock rate to ensure rk_hdptx_phy_clk_set_rate()
+ * will be invoked to commit PLL configuration.
+ */
+ if (hdptx->pll_config_dirty) {
+ req->rate = 0;
+ return 0;
+ }
+
+ if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL) {
+ req->rate = hdptx->hdmi_cfg.rate;
+ return 0;
+ }
/*
* FIXME: Temporarily allow altering TMDS char rate via CCF.
@@ -2362,17 +2385,6 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
- unsigned long long link_rate = rate;
-
- if (hdptx->hdmi_cfg.mode != PHY_HDMI_MODE_FRL)
- link_rate = DIV_ROUND_CLOSEST_ULL(rate * hdptx->hdmi_cfg.bpc, 8);
-
- /* Revert any unlikely link rate change since determine_rate() */
- if (hdptx->hdmi_cfg.rate != link_rate) {
- dev_warn(hdptx->dev, "Reverting unexpected rate change from %llu to %llu\n",
- link_rate, hdptx->hdmi_cfg.rate);
- hdptx->hdmi_cfg.rate = link_rate;
- }
/*
* The link rate would be normally programmed in HW during
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v5 05/10] phy: rockchip: samsung-hdptx: Handle uncommitted PHY config changes
2026-07-23 19:41 ` [PATCH v5 05/10] phy: rockchip: samsung-hdptx: Handle uncommitted PHY config changes Cristian Ciocaltea
@ 2026-07-23 20:00 ` sashiko-bot
2026-07-23 21:48 ` Cristian Ciocaltea
0 siblings, 1 reply; 19+ messages in thread
From: sashiko-bot @ 2026-07-23 20:00 UTC (permalink / raw)
To: Cristian Ciocaltea; +Cc: vkoul, olteanv, neil.armstrong, linux-phy
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Ignored PLL configuration errors lead to silent hardware failures and a permanent power leak.
--
--- Patch [5]: [PATCH v5 05/10] phy: rockchip: samsung-hdptx: Handle uncommitted PHY config changes ---
commit ecdc0a2489cf7f8fad47abbac851ea7a49482fed
Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
phy: rockchip: samsung-hdptx: Handle uncommitted PHY config changes
This commit introduces a flag to track uncommitted PHY configuration changes.
It uses this flag in the clock determine_rate and phy power_on callbacks to
ensure the configuration is properly programmed into the hardware, even when
the clock remains prepared or in FRL mode.
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
[ ... ]
> @@ -1347,25 +1354,22 @@ static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
> return 0;
>
> ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status);
> - if (ret)
> - goto dec_usage;
> -
> - if (status & HDPTX_O_PLL_LOCK_DONE)
> - dev_warn(hdptx->dev, "PLL locked by unknown consumer!\n");
> + if (ret) {
> + atomic_dec(&hdptx->usage_count);
> + return ret;
> + }
>
> if (mode == PHY_MODE_DP) {
> rk_hdptx_dp_reset(hdptx);
> } else {
> - ret = rk_hdptx_pll_cmn_config(hdptx);
> - if (ret)
> - goto dec_usage;
> + /*
> + * Ignore PLL config errors at this point as pll_config_dirty
> + * was not reset and, therefore, operation will be retried.
> + */
> + rk_hdptx_pll_cmn_config(hdptx);
> }
[Severity: High]
Is it safe to unconditionally ignore the PLL configuration error here?
If the display is disabled and re-enabled without a mode change (like a DPMS
off/on cycle), phy_configure() is not called, leaving pll_config_dirty = false.
If rk_hdptx_pll_cmn_config() fails (for example, due to a PLL lock timeout),
the error is swallowed and clk_prepare() will incorrectly report success.
> return 0;
> -
> -dec_usage:
> - atomic_dec(&hdptx->usage_count);
> - return ret;
> }
[ ... ]
> @@ -1700,13 +1704,18 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
> if (ret)
> rk_hdptx_phy_consumer_put(hdptx, true);
> } else {
> - regmap_write(hdptx->grf, GRF_HDPTX_CON0,
> - HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
> + if (hdptx->pll_config_dirty)
> + ret = rk_hdptx_pll_cmn_config(hdptx);
> +
[Severity: High]
Since pll_config_dirty can be false during a re-enable, the retry here would
be bypassed.
Will this cause the phy_power_on() callback to return success even though the
PLL is broken, leading to a silent failure and a black screen?
Additionally, if the PLL fails to lock during the earlier get() call, does
this prevent the cleanup sequence in rk_hdptx_phy_consumer_put() from
executing:
rk_hdptx_phy_consumer_put() {
...
if (status & HDPTX_O_PLL_LOCK_DONE) {
if (mode == PHY_MODE_DP)
rk_hdptx_dp_reset(hdptx);
else
rk_hdptx_phy_disable(hdptx);
}
...
}
Could this permanently leak the power resources allocated during the failed
rk_hdptx_phy_consumer_get() call?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260723-hdptx-clk-fixes-v5-0-8e786067865f@collabora.com?part=5
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v5 06/10] phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
` (4 preceding siblings ...)
2026-07-23 19:41 ` [PATCH v5 05/10] phy: rockchip: samsung-hdptx: Handle uncommitted PHY config changes Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 19:54 ` sashiko-bot
2026-07-23 19:41 ` [PATCH v5 07/10] phy: rockchip: samsung-hdptx: Consolidate consumer_put on error path Cristian Ciocaltea
` (3 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Thomas Niederprüm, Simon Wright, Diederik de Haas, Andy Yan
Since commit ba9c2fe18c17 ("drm/rockchip: dw_hdmi_qp: Switch to
phy_configure()") the TMDS rate setup doesn't rely anymore on the
unconventional usage of the bus width, instead it is managed exclusively
through the HDMI PHY configuration API.
Drop the now obsolete workaround to retrieve the TMDS character rate via
phy_get_bus_width() during power_on().
Tested-by: Thomas Niederprüm <dubito@online.de>
Tested-by: Simon Wright <simon@symple.nz>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS
Reviewed-by: Andy Yan <andy.yan@rock-chips.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 792eb57755eb..31abff5ada9e 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1660,22 +1660,6 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
enum phy_mode mode = phy_get_mode(phy);
int ret, lane;
- if (mode != PHY_MODE_DP) {
- if (!hdptx->hdmi_cfg.rate && hdptx->hdmi_cfg.mode != PHY_HDMI_MODE_FRL) {
- /*
- * FIXME: Temporary workaround to setup TMDS char rate
- * from the RK DW HDMI QP bridge driver.
- * Will be removed as soon the switch to the HDMI PHY
- * configuration API has been completed on both ends.
- */
- hdptx->hdmi_cfg.rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
- hdptx->hdmi_cfg.rate *= 100;
- }
-
- dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
- hdptx->hdmi_cfg.rate, hdptx->hdmi_cfg.bpc);
- }
-
ret = rk_hdptx_phy_consumer_get(hdptx);
if (ret)
return ret;
@@ -1704,6 +1688,9 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
if (ret)
rk_hdptx_phy_consumer_put(hdptx, true);
} else {
+ dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
+ hdptx->hdmi_cfg.rate, hdptx->hdmi_cfg.bpc);
+
if (hdptx->pll_config_dirty)
ret = rk_hdptx_pll_cmn_config(hdptx);
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v5 06/10] phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround
2026-07-23 19:41 ` [PATCH v5 06/10] phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround Cristian Ciocaltea
@ 2026-07-23 19:54 ` sashiko-bot
2026-07-23 20:50 ` Cristian Ciocaltea
0 siblings, 1 reply; 19+ messages in thread
From: sashiko-bot @ 2026-07-23 19:54 UTC (permalink / raw)
To: Cristian Ciocaltea; +Cc: vkoul, linux-phy, olteanv, neil.armstrong
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The commit claims to drop the TMDS rate setup workaround but fails to remove the corresponding CCF-based rate adjustment fallback, leaving the cleanup incomplete.
--
--- Patch [6]: [PATCH v5 06/10] phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround ---
commit 0f64c3b5ec0d09a00473e1362200c7598b861f9d
Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround
Since commit ba9c2fe18c17 ("drm/rockchip: dw_hdmi_qp: Switch to
phy_configure()") the TMDS rate setup doesn't rely anymore on the
unconventional usage of the bus width, instead it is managed exclusively
through the HDMI PHY configuration API.
Drop the now obsolete workaround to retrieve the TMDS character rate via
phy_get_bus_width() during power_on().
> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> index 792eb57755eb1..31abff5ada9e3 100644
> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
> @@ -1660,22 +1660,6 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
> enum phy_mode mode = phy_get_mode(phy);
> int ret, lane;
>
> - if (mode != PHY_MODE_DP) {
> - if (!hdptx->hdmi_cfg.rate && hdptx->hdmi_cfg.mode != PHY_HDMI_MODE_FRL) {
> - /*
> - * FIXME: Temporary workaround to setup TMDS char rate
> - * from the RK DW HDMI QP bridge driver.
> - * Will be removed as soon the switch to the HDMI PHY
> - * configuration API has been completed on both ends.
> - */
> - hdptx->hdmi_cfg.rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
> - hdptx->hdmi_cfg.rate *= 100;
> - }
> -
[Severity: Medium]
Since this patch drops the TMDS workaround here, should we also remove the
corresponding CCF-based rate adjustment fallback and the restrict_rate_change
state tracking?
Looking at rk_hdptx_phy_clk_determine_rate():
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c:rk_hdptx_phy_clk_determine_rate() {
...
/*
* FIXME: Temporarily allow altering TMDS char rate via CCF.
* To be dropped as soon as the RK DW HDMI QP bridge driver
* switches to make use of phy_configure().
*/
if (!hdptx->restrict_rate_change && req->rate != hdptx->hdmi_cfg.rate) {
struct phy_configure_opts_hdmi hdmi = {
.tmds_char_rate = req->rate,
};
...
}
Leaving this block behind seems to leave dead code, as the removal condition
(the bridge driver switching to phy_configure()) has been met.
Does this cleanup belong in this patch as well to ensure the workaround is
fully removed?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260723-hdptx-clk-fixes-v5-0-8e786067865f@collabora.com?part=6
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v5 06/10] phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround
2026-07-23 19:54 ` sashiko-bot
@ 2026-07-23 20:50 ` Cristian Ciocaltea
0 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 20:50 UTC (permalink / raw)
To: sashiko-reviews; +Cc: vkoul, linux-phy, olteanv, neil.armstrong
On 7/23/26 10:54 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] The commit claims to drop the TMDS rate setup workaround but fails to remove the corresponding CCF-based rate adjustment fallback, leaving the cleanup incomplete.
> --
>
> --- Patch [6]: [PATCH v5 06/10] phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround ---
> commit 0f64c3b5ec0d09a00473e1362200c7598b861f9d
> Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
>
> phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround
>
> Since commit ba9c2fe18c17 ("drm/rockchip: dw_hdmi_qp: Switch to
> phy_configure()") the TMDS rate setup doesn't rely anymore on the
> unconventional usage of the bus width, instead it is managed exclusively
> through the HDMI PHY configuration API.
>
> Drop the now obsolete workaround to retrieve the TMDS character rate via
> phy_get_bus_width() during power_on().
>
>> diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> index 792eb57755eb1..31abff5ada9e3 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
>> @@ -1660,22 +1660,6 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
>> enum phy_mode mode = phy_get_mode(phy);
>> int ret, lane;
>>
>> - if (mode != PHY_MODE_DP) {
>> - if (!hdptx->hdmi_cfg.rate && hdptx->hdmi_cfg.mode != PHY_HDMI_MODE_FRL) {
>> - /*
>> - * FIXME: Temporary workaround to setup TMDS char rate
>> - * from the RK DW HDMI QP bridge driver.
>> - * Will be removed as soon the switch to the HDMI PHY
>> - * configuration API has been completed on both ends.
>> - */
>> - hdptx->hdmi_cfg.rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
>> - hdptx->hdmi_cfg.rate *= 100;
>> - }
>> -
>
> [Severity: Medium]
> Since this patch drops the TMDS workaround here, should we also remove the
> corresponding CCF-based rate adjustment fallback and the restrict_rate_change
> state tracking?
>
> Looking at rk_hdptx_phy_clk_determine_rate():
>
> drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c:rk_hdptx_phy_clk_determine_rate() {
> ...
> /*
> * FIXME: Temporarily allow altering TMDS char rate via CCF.
> * To be dropped as soon as the RK DW HDMI QP bridge driver
> * switches to make use of phy_configure().
> */
> if (!hdptx->restrict_rate_change && req->rate != hdptx->hdmi_cfg.rate) {
> struct phy_configure_opts_hdmi hdmi = {
> .tmds_char_rate = req->rate,
> };
> ...
> }
>
> Leaving this block behind seems to leave dead code, as the removal condition
> (the bridge driver switching to phy_configure()) has been met.
>
> Does this cleanup belong in this patch as well to ensure the workaround is
> fully removed?
No, this is handled separately in [PATCH v5 08/10] phy: rockchip: samsung-hdptx:
Drop restrict_rate_change handling.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v5 07/10] phy: rockchip: samsung-hdptx: Consolidate consumer_put on error path
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
` (5 preceding siblings ...)
2026-07-23 19:41 ` [PATCH v5 06/10] phy: rockchip: samsung-hdptx: Drop TMDS rate setup workaround Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 08/10] phy: rockchip: samsung-hdptx: Drop restrict_rate_change handling Cristian Ciocaltea
` (2 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel
rk_hdptx_phy_consumer_put() is invoked in both branches of the mode
check conditional in rk_hdptx_phy_power_on() on the error path.
Simplify the code by moving the single call to the end of the
function.
No functional change intended.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 31abff5ada9e..eda8e5055588 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1685,8 +1685,6 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
rk_hdptx_dp_pll_init(hdptx);
ret = rk_hdptx_dp_aux_init(hdptx);
- if (ret)
- rk_hdptx_phy_consumer_put(hdptx, true);
} else {
dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
hdptx->hdmi_cfg.rate, hdptx->hdmi_cfg.bpc);
@@ -1703,11 +1701,11 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
else
ret = rk_hdptx_tmds_ropll_mode_config(hdptx);
}
-
- if (ret)
- rk_hdptx_phy_consumer_put(hdptx, true);
}
+ if (ret)
+ rk_hdptx_phy_consumer_put(hdptx, true);
+
return ret;
}
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v5 08/10] phy: rockchip: samsung-hdptx: Drop restrict_rate_change handling
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
` (6 preceding siblings ...)
2026-07-23 19:41 ` [PATCH v5 07/10] phy: rockchip: samsung-hdptx: Consolidate consumer_put on error path Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 09/10] phy: rockchip: samsung-hdptx: Simplify GRF access with FIELD_PREP_WM16() Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 10/10] phy: rockchip: samsung-hdptx: Consistently use bitfield macros Cristian Ciocaltea
9 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Thomas Niederprüm, Simon Wright, Diederik de Haas,
Dmitry Baryshkov
Since commit 6efbd0f46dd8 ("phy: rockchip: samsung-hdptx: Restrict
altering TMDS char rate via CCF"), adjusting the rate via the Common
Clock Framework API has been disallowed.
To avoid breaking existing users until switching to the PHY config API,
it introduced a temporary exception to the rule, controlled via the
'restrict_rate_change' flag.
As the API transition completed, remove the now deprecated exception
logic.
Tested-by: Thomas Niederprüm <dubito@online.de>
Tested-by: Simon Wright <simon@symple.nz>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 42 +++++------------------
1 file changed, 8 insertions(+), 34 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index eda8e5055588..da8f252fb719 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -414,7 +414,6 @@ struct rk_hdptx_phy {
/* clk provider */
struct clk_hw hw;
bool pll_config_dirty;
- bool restrict_rate_change;
atomic_t usage_count;
@@ -2074,7 +2073,6 @@ static int rk_hdptx_phy_configure(struct phy *phy, union phy_configure_opts *opt
if (ret) {
dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
} else {
- hdptx->restrict_rate_change = true;
hdptx->pll_config_dirty = true;
dev_dbg(hdptx->dev, "%s %s rate=%llu bpc=%u\n", __func__,
@@ -2327,41 +2325,17 @@ static int rk_hdptx_phy_clk_determine_rate(struct clk_hw *hw,
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
/*
- * Invalidate current clock rate to ensure rk_hdptx_phy_clk_set_rate()
- * will be invoked to commit PLL configuration.
+ * For uncommitted PLL configuration, invalidate the current clock rate
+ * to ensure rk_hdptx_phy_clk_set_rate() will be always invoked.
+ * Otherwise, restrict the rate according to the PHY link setup.
*/
- if (hdptx->pll_config_dirty) {
+ if (hdptx->pll_config_dirty)
req->rate = 0;
- return 0;
- }
-
- if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL) {
+ else if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
req->rate = hdptx->hdmi_cfg.rate;
- return 0;
- }
-
- /*
- * FIXME: Temporarily allow altering TMDS char rate via CCF.
- * To be dropped as soon as the RK DW HDMI QP bridge driver
- * switches to make use of phy_configure().
- */
- if (!hdptx->restrict_rate_change && req->rate != hdptx->hdmi_cfg.rate) {
- struct phy_configure_opts_hdmi hdmi = {
- .tmds_char_rate = req->rate,
- };
-
- int ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &hdmi, &hdptx->hdmi_cfg);
-
- if (ret)
- return ret;
- }
-
- /*
- * The TMDS char rate shall be adjusted via phy_configure() only,
- * hence ensure rk_hdptx_phy_clk_set_rate() won't be invoked with
- * a different rate argument.
- */
- req->rate = DIV_ROUND_CLOSEST_ULL(hdptx->hdmi_cfg.rate * 8, hdptx->hdmi_cfg.bpc);
+ else
+ req->rate = DIV_ROUND_CLOSEST_ULL(hdptx->hdmi_cfg.rate * 8,
+ hdptx->hdmi_cfg.bpc);
return 0;
}
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v5 09/10] phy: rockchip: samsung-hdptx: Simplify GRF access with FIELD_PREP_WM16()
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
` (7 preceding siblings ...)
2026-07-23 19:41 ` [PATCH v5 08/10] phy: rockchip: samsung-hdptx: Drop restrict_rate_change handling Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
2026-07-23 19:41 ` [PATCH v5 10/10] phy: rockchip: samsung-hdptx: Consistently use bitfield macros Cristian Ciocaltea
9 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Thomas Niederprüm, Simon Wright, Diederik de Haas,
Dmitry Baryshkov
The 16 most significant bits of the general-purpose register (GRF) are
used as a write-enable mask for the remaining 16 bits.
Make use of the recently introduced FIELD_PREP_WM16() macro to avoid
open-coding the bit shift operations and improve code readability.
Tested-by: Thomas Niederprüm <dubito@online.de>
Tested-by: Simon Wright <simon@symple.nz>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 52 +++++++++++------------
1 file changed, 25 insertions(+), 27 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index da8f252fb719..03977b830414 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
- * Copyright (c) 2024 Collabora Ltd.
+ * Copyright (c) 2024-2026 Collabora Ltd.
*
* Author: Algea Cao <algea.cao@rock-chips.com>
* Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
+#include <linux/hw_bitfield.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -949,7 +950,9 @@ static void rk_hdptx_pre_power_up(struct rk_hdptx_phy *hdptx)
reset_control_assert(hdptx->rsts[RST_CMN].rstc);
reset_control_assert(hdptx->rsts[RST_INIT].rstc);
- val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16;
+ val = (FIELD_PREP_WM16(HDPTX_I_PLL_EN, 0) |
+ FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 0) |
+ FIELD_PREP_WM16(HDPTX_I_BGR_EN, 0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
}
@@ -960,8 +963,8 @@ static int rk_hdptx_post_enable_lane(struct rk_hdptx_phy *hdptx)
reset_control_deassert(hdptx->rsts[RST_LANE].rstc);
- val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 |
- HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN;
+ val = (FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 1) |
+ FIELD_PREP_WM16(HDPTX_I_BGR_EN, 1));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
/* 3 lanes FRL mode */
@@ -990,16 +993,15 @@ static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx)
u32 val;
int ret;
- val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 |
- HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN;
+ val = (FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 1) |
+ FIELD_PREP_WM16(HDPTX_I_BGR_EN, 1));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
usleep_range(10, 15);
reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
usleep_range(10, 15);
- val = HDPTX_I_PLL_EN << 16 | HDPTX_I_PLL_EN;
- regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(HDPTX_I_PLL_EN, 1));
usleep_range(10, 15);
reset_control_deassert(hdptx->rsts[RST_CMN].rstc);
@@ -1037,7 +1039,9 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
reset_control_assert(hdptx->rsts[RST_CMN].rstc);
reset_control_assert(hdptx->rsts[RST_INIT].rstc);
- val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16;
+ val = (FIELD_PREP_WM16(HDPTX_I_PLL_EN, 0) |
+ FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 0) |
+ FIELD_PREP_WM16(HDPTX_I_BGR_EN, 0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
}
@@ -1135,7 +1139,7 @@ static int rk_hdptx_frl_lcpll_cmn_config(struct rk_hdptx_phy *hdptx)
rk_hdptx_pre_power_up(hdptx);
- regmap_write(hdptx->grf, GRF_HDPTX_CON0, LC_REF_CLK_SEL << 16);
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(LC_REF_CLK_SEL, 0));
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_frl_lcpll_cmn_init_seq);
@@ -1178,8 +1182,7 @@ static int rk_hdptx_frl_lcpll_ropll_cmn_config(struct rk_hdptx_phy *hdptx)
rk_hdptx_pre_power_up(hdptx);
/* ROPLL input reference clock from LCPLL (cascade mode) */
- regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- (LC_REF_CLK_SEL << 16) | LC_REF_CLK_SEL);
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(LC_REF_CLK_SEL, 1));
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_frl_lcpll_ropll_cmn_init_seq);
@@ -1218,7 +1221,7 @@ static int rk_hdptx_tmds_ropll_cmn_config(struct rk_hdptx_phy *hdptx)
rk_hdptx_pre_power_up(hdptx);
- regmap_write(hdptx->grf, GRF_HDPTX_CON0, LC_REF_CLK_SEL << 16);
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(LC_REF_CLK_SEL, 0));
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdptx_tmds_cmn_init_seq);
@@ -1336,11 +1339,9 @@ static void rk_hdptx_dp_reset(struct rk_hdptx_phy *hdptx)
FIELD_PREP(LN_TX_DRV_EI_EN_MASK, 0));
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x0));
- regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_I_BIAS_EN << 16 | FIELD_PREP(HDPTX_I_BIAS_EN, 0x0));
- regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x0));
+ FIELD_PREP_WM16(HDPTX_I_PLL_EN, 0) |
+ FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 0) |
+ FIELD_PREP_WM16(HDPTX_I_BGR_EN, 0));
}
static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
@@ -1616,9 +1617,8 @@ static int rk_hdptx_dp_aux_init(struct rk_hdptx_phy *hdptx)
FIELD_PREP(OVRD_SB_VREG_EN_MASK, 0x1));
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x1));
- regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_I_BIAS_EN << 16 | FIELD_PREP(HDPTX_I_BIAS_EN, 0x1));
+ FIELD_PREP_WM16(HDPTX_I_BGR_EN, 1) |
+ FIELD_PREP_WM16(HDPTX_I_BIAS_EN, 1));
usleep_range(20, 25);
reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
@@ -1665,7 +1665,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
if (mode == PHY_MODE_DP) {
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x1));
+ FIELD_PREP_WM16(HDPTX_MODE_SEL, 1));
for (lane = 0; lane < 4; lane++) {
regmap_update_bits(hdptx->regmap, LANE_REG(031e) + 0x400 * lane,
@@ -1693,7 +1693,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
if (!ret) {
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
+ FIELD_PREP_WM16(HDPTX_MODE_SEL, 0));
if (hdptx->hdmi_cfg.mode == PHY_HDMI_MODE_FRL)
ret = rk_hdptx_frl_lcpll_mode_config(hdptx);
@@ -1828,8 +1828,7 @@ static int rk_hdptx_phy_set_rate(struct rk_hdptx_phy *hdptx,
u32 bw, status;
int ret;
- regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x0));
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(HDPTX_I_PLL_EN, 0));
switch (dp->link_rate) {
case 1620:
@@ -1885,8 +1884,7 @@ static int rk_hdptx_phy_set_rate(struct rk_hdptx_phy *hdptx,
regmap_update_bits(hdptx->regmap, CMN_REG(0095), DP_TX_LINK_BW_MASK,
FIELD_PREP(DP_TX_LINK_BW_MASK, bw));
- regmap_write(hdptx->grf, GRF_HDPTX_CON0,
- HDPTX_I_PLL_EN << 16 | FIELD_PREP(HDPTX_I_PLL_EN, 0x1));
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, FIELD_PREP_WM16(HDPTX_I_PLL_EN, 1));
ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS,
status, FIELD_GET(HDPTX_O_PLL_LOCK_DONE, status),
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v5 10/10] phy: rockchip: samsung-hdptx: Consistently use bitfield macros
2026-07-23 19:41 [PATCH v5 00/10] phy: rockchip: samsung-hdptx: Clock fixes and API transition cleanups Cristian Ciocaltea
` (8 preceding siblings ...)
2026-07-23 19:41 ` [PATCH v5 09/10] phy: rockchip: samsung-hdptx: Simplify GRF access with FIELD_PREP_WM16() Cristian Ciocaltea
@ 2026-07-23 19:41 ` Cristian Ciocaltea
9 siblings, 0 replies; 19+ messages in thread
From: Cristian Ciocaltea @ 2026-07-23 19:41 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Algea Cao,
Dmitry Baryshkov
Cc: kernel, linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel,
Thomas Niederprüm, Simon Wright, Diederik de Haas,
Dmitry Baryshkov
Make the code more robust and improve readability by using the available
bitfield macros (e.g. FIELD_PREP, FIELD_GET) whenever possible, instead
of open coding the related bit operations.
Tested-by: Thomas Niederprüm <dubito@online.de>
Tested-by: Simon Wright <simon@symple.nz>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # NanoPC-T6 LTS
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 30 +++++++++++++++--------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 03977b830414..aa0e36260381 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -53,6 +53,12 @@
/* CMN_REG(001e) */
#define LCPLL_PI_EN_MASK BIT(5)
#define LCPLL_100M_CLK_EN_MASK BIT(0)
+/* CMN_REG(0022) */
+#define ANA_LCPLL_PMS_PDIV_MASK GENMASK(7, 4)
+#define ANA_LCPLL_PMS_REFDIV_MASK GENMASK(3, 0)
+/* CMN_REG(0023) */
+#define LCPLL_PMS_SDIV_RBR_MASK GENMASK(7, 4)
+#define LCPLL_PMS_SDIV_HBR_MASK GENMASK(3, 0)
/* CMN_REG(0025) */
#define LCPLL_PMS_IQDIV_RSTN_MASK BIT(4)
/* CMN_REG(0028) */
@@ -1157,9 +1163,11 @@ static int rk_hdptx_frl_lcpll_cmn_config(struct rk_hdptx_phy *hdptx)
regmap_write(hdptx->regmap, CMN_REG(0020), cfg->pms_mdiv);
regmap_write(hdptx->regmap, CMN_REG(0021), cfg->pms_mdiv_afc);
regmap_write(hdptx->regmap, CMN_REG(0022),
- (cfg->pms_pdiv << 4) | cfg->pms_refdiv);
+ FIELD_PREP(ANA_LCPLL_PMS_PDIV_MASK, cfg->pms_pdiv) |
+ FIELD_PREP(ANA_LCPLL_PMS_REFDIV_MASK, cfg->pms_refdiv));
regmap_write(hdptx->regmap, CMN_REG(0023),
- (cfg->pms_sdiv << 4) | cfg->pms_sdiv);
+ FIELD_PREP(LCPLL_PMS_SDIV_RBR_MASK, cfg->pms_sdiv) |
+ FIELD_PREP(LCPLL_PMS_SDIV_HBR_MASK, cfg->pms_sdiv));
regmap_write(hdptx->regmap, CMN_REG(002a), cfg->sdm_deno);
regmap_write(hdptx->regmap, CMN_REG(002b), cfg->sdm_num_sign);
regmap_write(hdptx->regmap, CMN_REG(002c), cfg->sdm_num);
@@ -1229,8 +1237,10 @@ static int rk_hdptx_tmds_ropll_cmn_config(struct rk_hdptx_phy *hdptx)
regmap_write(hdptx->regmap, CMN_REG(0051), cfg->pms_mdiv);
regmap_write(hdptx->regmap, CMN_REG(0055), cfg->pms_mdiv_afc);
regmap_write(hdptx->regmap, CMN_REG(0059),
- (cfg->pms_pdiv << 4) | cfg->pms_refdiv);
- regmap_write(hdptx->regmap, CMN_REG(005a), cfg->pms_sdiv << 4);
+ FIELD_PREP(ANA_ROPLL_PMS_PDIV_MASK, cfg->pms_pdiv) |
+ FIELD_PREP(ANA_ROPLL_PMS_REFDIV_MASK, cfg->pms_refdiv));
+ regmap_write(hdptx->regmap, CMN_REG(005a),
+ FIELD_PREP(ROPLL_PMS_SDIV_RBR_MASK, cfg->pms_sdiv));
regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK,
FIELD_PREP(ROPLL_SDM_EN_MASK, cfg->sdm_en));
@@ -2177,7 +2187,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(0023), &val);
if (ret)
return 0;
- lcpll_hw.pms_sdiv = val & 0xf;
+ lcpll_hw.pms_sdiv = FIELD_GET(LCPLL_PMS_SDIV_HBR_MASK, val);
ret = regmap_read(hdptx->regmap, CMN_REG(002B), &val);
if (ret)
@@ -2197,7 +2207,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(002D), &val);
if (ret)
return 0;
- lcpll_hw.sdc_n = (val & LCPLL_SDC_N_MASK) >> 1;
+ lcpll_hw.sdc_n = FIELD_GET(LCPLL_SDC_N_MASK, val);
ret = regmap_read(hdptx->grf, GRF_HDPTX_CON0, &val);
if (ret)
@@ -2238,12 +2248,12 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(005E), &val);
if (ret)
return 0;
- ropll_hw.sdm_en = val & ROPLL_SDM_EN_MASK;
+ ropll_hw.sdm_en = FIELD_GET(ROPLL_SDM_EN_MASK, val);
ret = regmap_read(hdptx->regmap, CMN_REG(0064), &val);
if (ret)
return 0;
- ropll_hw.sdm_num_sign = val & ROPLL_SDM_NUM_SIGN_RBR_MASK;
+ ropll_hw.sdm_num_sign = FIELD_GET(ROPLL_SDM_NUM_SIGN_RBR_MASK, val);
ret = regmap_read(hdptx->regmap, CMN_REG(0065), &val);
if (ret)
@@ -2258,7 +2268,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(0069), &val);
if (ret)
return 0;
- ropll_hw.sdc_n = (val & ROPLL_SDC_N_RBR_MASK) + 3;
+ ropll_hw.sdc_n = FIELD_GET(ROPLL_SDC_N_RBR_MASK, val) + 3;
ret = regmap_read(hdptx->regmap, CMN_REG(006c), &val);
if (ret)
@@ -2273,7 +2283,7 @@ static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
ret = regmap_read(hdptx->regmap, CMN_REG(0086), &val);
if (ret)
return 0;
- ropll_hw.pms_sdiv = ((val & PLL_PCG_POSTDIV_SEL_MASK) >> 4) + 1;
+ ropll_hw.pms_sdiv = FIELD_GET(PLL_PCG_POSTDIV_SEL_MASK, val) + 1;
bpc = (FIELD_GET(PLL_PCG_CLK_SEL_MASK, val) << 1) + 8;
fout = PLL_REF_CLK * ropll_hw.pms_mdiv;
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread