Linux-PHY Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v3 1/5] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add support for glymur Gen5 x8 bifurcation mode
From: Krzysztof Kozlowski @ 2026-04-22  6:27 UTC (permalink / raw)
  To: Qiang Yu
  Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio,
	linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <aeBQRStG3imY0cOe@hu-qianyu-lv.qualcomm.com>

On 16/04/2026 04:58, Qiang Yu wrote:
>>>    reset-names:
>>>      minItems: 1
>>>      items:
>>>        - const: phy
>>>        - const: phy_nocsr
>>> +      - const: phy_b
>>> +      - const: phy_b_nocsr
>>
>> And now I doubt that all the changes here are for duplicated node.
>>
> 
> All the changes here are for 1x8 PHY node.
> 
>> Maybe just the commit msg is confusing and instead of describing some
>> node which combines two other phys just say what device is here being
>> described.
>>
> 
> Okay, I will focus on describing the required resources. Is the
> description below clearer?
> 
> Glymur has two physical Gen5x4 PCIe PHY blocks: pcie3a phy and pcie3b phy.


I just proven you that it is not true.

Best regards,
Krzysztof

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v3 1/5] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add support for glymur Gen5 x8 bifurcation mode
From: Krzysztof Kozlowski @ 2026-04-22  6:27 UTC (permalink / raw)
  To: Qiang Yu
  Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio,
	linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <aeXUZ1uSEJ9InUtw@hu-qianyu-lv.qualcomm.com>

On 20/04/2026 09:23, Qiang Yu wrote:
>>> It is not the same as the 5x4 PHY. In DT, we model three PHY nodes:
>>> phy_3a (1x4), phy_3b (1x4), and a separate phy_1x8 node for x8 mode.
>>
>> OK, that's what I wanted to hear. And that's what should not be done,
>>
>> You should not have a separate node for the same hardware. First, DTC
>> will give you a W=1 warning, although warning itself should be moved to
>> W=2.
>>
>> Second, the warning tells important story - same hardware is described
>> twice.
>>
>> You only need phy_3a and phy_3b, so only two in total.
> 
> We can keep only phy_3a and phy_3b, but still add new compatible
> qcom,glymur-qmp-gen5x8-pcie-phy in binding, right?


No, you cannot. You cannot create fake device nodes.

Best regards,
Krzysztof

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH] phy: qualcomm: qmp-combo: update DP PHY PLL programming on Glymur
From: Konrad Dybcio @ 2026-04-22  9:36 UTC (permalink / raw)
  To: Mahadevan P, Vinod Koul, Neil Armstrong, Wesley Cheng, Abel Vesa,
	Dmitry Baryshkov, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-phy, linux-kernel, devicetree, Ritesh Kumar
In-Reply-To: <20260419-glymur_dp-v1-1-ad1067a8e8ae@oss.qualcomm.com>

On 4/19/26 12:15 PM, Mahadevan P wrote:
> The existing DP PHY PLL and AUX configuration for the Glymur platform
> does not fully follow the Hardware Programming Guide requirements for
> DP over Type-C, which results in DP link bring-up failures.
> 
> Update the DP PHY programming sequence and PLL-related register
> settings to align with the latest HPG recommendations. With this
> change, DP link training completes successfully on Glymur-based
> platforms.
> 
> Fixes: d10736db98d2 ("phy: qualcomm: qmp-combo: Add DP offsets and settings for Glymur platforms")
> Signed-off-by: Ritesh Kumar <ritesh.kumar@oss.qualcomm.com>
> Signed-off-by: Mahadevan P <mahadevan.p@oss.qualcomm.com>

The tag chain is invalid as-is.
Should this patch have "Author: Ritesh Kumar"?

Konrad


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH] phy: qualcomm: qmp-combo: update DP PHY PLL programming on Glymur
From: Konrad Dybcio @ 2026-04-22  9:54 UTC (permalink / raw)
  To: Mahadevan P, Dmitry Baryshkov
  Cc: Vinod Koul, Neil Armstrong, Wesley Cheng, Abel Vesa,
	Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, linux-phy, linux-kernel, devicetree,
	Ritesh Kumar
In-Reply-To: <a967d7ec-66f7-4eaa-91e3-0a96e5a8ec7f@oss.qualcomm.com>

On 4/20/26 4:18 PM, Mahadevan P wrote:
> 
> 
> On 4/19/2026 6:48 PM, Dmitry Baryshkov wrote:
>> On Sun, 19 Apr 2026 at 13:16, Mahadevan P <mahadevan.p@oss.qualcomm.com> wrote:
>>>
>>> The existing DP PHY PLL and AUX configuration for the Glymur platform
>>> does not fully follow the Hardware Programming Guide requirements for
>>> DP over Type-C, which results in DP link bring-up failures.
>>>
>>> Update the DP PHY programming sequence and PLL-related register
>>> settings to align with the latest HPG recommendations. With this
>>> change, DP link training completes successfully on Glymur-based
>>> platforms.
>>>
>>> Fixes: d10736db98d2 ("phy: qualcomm: qmp-combo: Add DP offsets and settings for Glymur platforms")
>>> Signed-off-by: Ritesh Kumar <ritesh.kumar@oss.qualcomm.com>
>>> Signed-off-by: Mahadevan P <mahadevan.p@oss.qualcomm.com>
>>> ---

[...]

>>> +       writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
>>> +
>>> +       writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
>>
>> Are you saying that we don't need to write 0x4c here in case of the
>> reverse mode? Was that changed and why?
> Yes for glymur it is changed
> DP2_PHY_DP_PHY_PD_CTL
> Normal Orientation: 0x7D for 4lane; 0x75 for 1Lane or 2Lanne
> Flip Orientation: 0x7D for 4Lane; 0x6D for 1Lane or 2Lane


Dmitry asked about the other register - DP_PHY_MODE.

I checked the reg description, and at least for Glymur, BIT(5)
(the difference between 0x4c and 0x5c) says "take bit 4 into
consideration, otherwise let the HW decide". I wonder if we need
to set it at all, for any target.

Konrad

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH] phy: qualcomm: qmp-combo: update DP PHY PLL programming on Glymur
From: Konrad Dybcio @ 2026-04-22 10:06 UTC (permalink / raw)
  To: Mahadevan P, Vinod Koul, Neil Armstrong, Wesley Cheng, Abel Vesa,
	Dmitry Baryshkov, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, linux-phy, linux-kernel, devicetree, Ritesh Kumar
In-Reply-To: <20260419-glymur_dp-v1-1-ad1067a8e8ae@oss.qualcomm.com>

On 4/19/26 12:15 PM, Mahadevan P wrote:
> The existing DP PHY PLL and AUX configuration for the Glymur platform
> does not fully follow the Hardware Programming Guide requirements for
> DP over Type-C, which results in DP link bring-up failures.

[...]

> @@ -283,8 +283,8 @@ static const unsigned int qmp_v8_n3_usb43dpphy_regs_layout[QPHY_LAYOUT_SIZE] = {
>  	[QPHY_DP_AON_TOGGLE_ENABLE]		= QPHY_V8_PCS_AON_DP_AON_TOGGLE_ENABLE,
>  
>  	[QPHY_COM_RESETSM_CNTRL]		= QSERDES_V8_COM_RESETSM_CNTRL,
> -	[QPHY_COM_C_READY_STATUS]		= QSERDES_V8_COM_C_READY_STATUS,
> -	[QPHY_COM_CMN_STATUS]			= QSERDES_V8_COM_CMN_STATUS,
> +	[QPHY_COM_C_READY_STATUS]		= QSERDES_V8_COM_C_READY_STATUS_N3,

This register is in the DP_QSERDES region, not in COM.

The updates to the reg addreses themselves seem to match the hw description.

[...]
> +static bool qmp_v8_combo_configure_dp_mode(struct qmp_combo *qmp)
> +{
> +	bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE);
> +	const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
> +	u32 val;
> +
> +	val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> +		DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
> +		DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;

The Hamoa (v6) HSR suggests we can use this broader value there too.
And same for e.g. Makena (v4), but not sdm845 (v3) (perhaps we could
use do it either way?).

With my response to Dmitry's comment in mind, the diff in this function
against qmp_combo_configure_dp_mode() should either be broadened to
other platforms, or the function should just be the same for all targets

[...]

>  
> +static int qmp_v8_helper_configure_dp_phy(struct qmp_combo *qmp)

This function would then be the same (except your v8 impl returns earlier
than the existing one, skipping a 0x19 write to QSERDES_DP_PHY_CFG and
QPHY_DP_PHY_STATUS reads)

Konrad

-- 
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: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
From: Konrad Dybcio @ 2026-04-22 10:42 UTC (permalink / raw)
  To: Yongxing Mou, Vinod Koul, Neil Armstrong, Stephen Boyd,
	Bjorn Andersson
  Cc: linux-arm-msm, linux-phy, linux-kernel
In-Reply-To: <20260422-edp_phy-v4-3-c38bef2d027b@oss.qualcomm.com>

On 4/22/26 8:01 AM, Yongxing Mou wrote:
> SC7280 and SC8180X previously shared the same cfg because they did not use
> swing/pre-emphasis tables. Add the corresponding tables for these
> platforms. Since they have different PHY sub-versions, their eDP/DP mode
> tables also differ, so move SC8180X to its own cfg instead of reusing the
> SC7280 one.
> 
> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
> ---



> +static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v2 = {
> +	.swing_hbr_rbr = &edp_swing_hbr_rbr,

For eDP / low-Vdiff:

I believe the RBR swing settings for 8180 should
instead be:

0x07 0x0f 0x17 0x1f (matches)
(the rest differs)
0x0d 0x16 0x1e
0x11 0x1b
0x16

The preem RBR almost matches, one byte is off
(arr[0][1] = 0x12 on poipu, 0x11 on kodiak)

The swing and preem settings for HBR3 look OK

For DP / low-Vdiff:

.swing_hbr3_hbr2 OK
.swing_hbr_rbr - I don't know. The docs are unclear whether the same
settings should be used for RBR and HBR3, but maybe? There's a
separate table for mini-DP but I doubt there's any poipu boards with
such a connector (maybe some obscure ones)

.pre_emphasis_hbr3_hbr2 OK
.pre_emphasis_hbr_rbr same as above

Konrad

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH] phy: qualcomm: qmp-combo: update DP PHY PLL programming on Glymur
From: Dmitry Baryshkov @ 2026-04-22 15:40 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Mahadevan P, Vinod Koul, Neil Armstrong, Wesley Cheng, Abel Vesa,
	Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, linux-phy, linux-kernel, devicetree,
	Ritesh Kumar
In-Reply-To: <b21b1f73-881a-40bd-aef6-5c34aed0e266@oss.qualcomm.com>

On Wed, Apr 22, 2026 at 11:54:30AM +0200, Konrad Dybcio wrote:
> On 4/20/26 4:18 PM, Mahadevan P wrote:
> > 
> > 
> > On 4/19/2026 6:48 PM, Dmitry Baryshkov wrote:
> >> On Sun, 19 Apr 2026 at 13:16, Mahadevan P <mahadevan.p@oss.qualcomm.com> wrote:
> >>>
> >>> The existing DP PHY PLL and AUX configuration for the Glymur platform
> >>> does not fully follow the Hardware Programming Guide requirements for
> >>> DP over Type-C, which results in DP link bring-up failures.
> >>>
> >>> Update the DP PHY programming sequence and PLL-related register
> >>> settings to align with the latest HPG recommendations. With this
> >>> change, DP link training completes successfully on Glymur-based
> >>> platforms.
> >>>
> >>> Fixes: d10736db98d2 ("phy: qualcomm: qmp-combo: Add DP offsets and settings for Glymur platforms")
> >>> Signed-off-by: Ritesh Kumar <ritesh.kumar@oss.qualcomm.com>
> >>> Signed-off-by: Mahadevan P <mahadevan.p@oss.qualcomm.com>
> >>> ---
> 
> [...]
> 
> >>> +       writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
> >>> +
> >>> +       writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
> >>
> >> Are you saying that we don't need to write 0x4c here in case of the
> >> reverse mode? Was that changed and why?
> > Yes for glymur it is changed
> > DP2_PHY_DP_PHY_PD_CTL
> > Normal Orientation: 0x7D for 4lane; 0x75 for 1Lane or 2Lanne
> > Flip Orientation: 0x7D for 4Lane; 0x6D for 1Lane or 2Lane
> 
> 
> Dmitry asked about the other register - DP_PHY_MODE.
> 
> I checked the reg description, and at least for Glymur, BIT(5)
> (the difference between 0x4c and 0x5c) says "take bit 4 into
> consideration, otherwise let the HW decide". I wonder if we need
> to set it at all, for any target.

I think it depends on the orientation GPIO being correctly wired from
PMIC to the device. I don't remember why, but it's easier to use the
software switch instead.

> 
> Konrad

-- 
With best wishes
Dmitry

-- 
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: qcom: edp: Unify generic DP/eDP swing and pre-emphasis tables
From: Dmitry Baryshkov @ 2026-04-22 16:10 UTC (permalink / raw)
  To: Yongxing Mou
  Cc: Vinod Koul, Neil Armstrong, Stephen Boyd, Bjorn Andersson,
	linux-arm-msm, linux-phy, linux-kernel, stable, Konrad Dybcio
In-Reply-To: <20260422-edp_phy-v4-1-c38bef2d027b@oss.qualcomm.com>

On Wed, Apr 22, 2026 at 02:01:51PM +0800, Yongxing Mou wrote:
> The current eDP and DP swing/pre-emphasis tables do not match the HPG
> requirements for the supported platforms, correct the table accordingly.
> 
> The generic tables which can be shared as follows:
> 
> DP mode:
> 	-sa8775p/sc7280/sc8280xp/x1e80100
> 	-glymur
> 	-sc8180x
> eDP mode(low vdiff):
> 	-glymur/sa8775p/sc8280xp/x1e80100
> 	-sc7280
> 	-sc8180x
> 
> The proper tables for SC8180X and SC7280 will be added in a later patch,
> since they need separate table.
> 
> Cc: stable@vger.kernel.org
> Fixes: f199223cb490 ("phy: qcom: Introduce new eDP PHY driver")
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
> ---
>  drivers/phy/qualcomm/phy-qcom-edp.c | 41 +++++++++----------------------------
>  1 file changed, 10 insertions(+), 31 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v4 2/5] phy: qcom: edp: Add eDP/DP mode switch support
From: Dmitry Baryshkov @ 2026-04-22 16:14 UTC (permalink / raw)
  To: Yongxing Mou
  Cc: Vinod Koul, Neil Armstrong, Stephen Boyd, Bjorn Andersson,
	linux-arm-msm, linux-phy, linux-kernel, stable, Konrad Dybcio
In-Reply-To: <20260422-edp_phy-v4-2-c38bef2d027b@oss.qualcomm.com>

On Wed, Apr 22, 2026 at 02:01:52PM +0800, Yongxing Mou wrote:
> The eDP PHY supports both eDP/DP modes, each requires a different table.
> The current driver doesn't support both modes and use either the eDP or
> DP table when enable the platform.

This is not quite true. The driver supports both modes, but it uses a
fixed static table for eDP programming.

Other than the commit message, LGTM.


> Add a separate set of tables for eDP
> and DP modes, and select the appropriate table based on the current mode.
> 
> Glymur's DP mode table differs from the other platforms, add a dedicated
> table for it.
> 
> Since both modes are supported, so also fixes the table mismatch for
> X1E80100(eDP) and SA8775P(DP).
> 
> Cc: stable@vger.kernel.org
> Fixes: 3f12bf16213c ("phy: qcom: edp: Add support for eDP PHY on SA8775P")
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
> ---
>  drivers/phy/qualcomm/phy-qcom-edp.c | 46 +++++++++++++++++++++++++++----------
>  1 file changed, 34 insertions(+), 12 deletions(-)
> 

-- 
With best wishes
Dmitry

-- 
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: qcom: edp: Fix AUX_CFG8 programming for DP mode
From: Dmitry Baryshkov @ 2026-04-22 16:31 UTC (permalink / raw)
  To: Yongxing Mou
  Cc: Vinod Koul, Neil Armstrong, Stephen Boyd, Bjorn Andersson,
	linux-arm-msm, linux-phy, linux-kernel, Konrad Dybcio
In-Reply-To: <20260422-edp_phy-v4-4-c38bef2d027b@oss.qualcomm.com>

On Wed, Apr 22, 2026 at 02:01:54PM +0800, Yongxing Mou wrote:
> AUX_CFG8 depends on whether the PHY is operating in eDP or DP mode, not
> the selected swing/pre-emphasis table. All supported platforms already
> have the proper tables, so remove the unnecessary check.
> 
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
> ---
>  drivers/phy/qualcomm/phy-qcom-edp.c | 7 +------
>  1 file changed, 1 insertion(+), 6 deletions(-)
> 

Fixes? 

With the tag in place,


Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>



-- 
With best wishes
Dmitry

-- 
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: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
From: Dmitry Baryshkov @ 2026-04-22 16:33 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Yongxing Mou, Vinod Koul, Neil Armstrong, Stephen Boyd,
	Bjorn Andersson, linux-arm-msm, linux-phy, linux-kernel
In-Reply-To: <df40b4d1-6133-4d49-a7e3-47cbb2b058e9@oss.qualcomm.com>

On Wed, Apr 22, 2026 at 12:42:56PM +0200, Konrad Dybcio wrote:
> On 4/22/26 8:01 AM, Yongxing Mou wrote:
> > SC7280 and SC8180X previously shared the same cfg because they did not use
> > swing/pre-emphasis tables. Add the corresponding tables for these
> > platforms. Since they have different PHY sub-versions, their eDP/DP mode
> > tables also differ, so move SC8180X to its own cfg instead of reusing the
> > SC7280 one.
> > 
> > Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
> > ---
> 
> 
> 
> > +static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v2 = {
> > +	.swing_hbr_rbr = &edp_swing_hbr_rbr,
> 
> For eDP / low-Vdiff:
> 
> I believe the RBR swing settings for 8180 should
> instead be:
> 
> 0x07 0x0f 0x17 0x1f (matches)

0x07, 0x0f, 0x16, 0x1f

> (the rest differs)
> 0x0d 0x16 0x1e
> 0x11 0x1b
> 0x16
> 
> The preem RBR almost matches, one byte is off
> (arr[0][1] = 0x12 on poipu, 0x11 on kodiak)
> 
> The swing and preem settings for HBR3 look OK
> 

-- 
With best wishes
Dmitry

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v4 0/5] phy: qcom: edp: Add DP/eDP switch for phys
From: Dmitry Baryshkov @ 2026-04-22 17:24 UTC (permalink / raw)
  To: Yongxing Mou
  Cc: Vinod Koul, Neil Armstrong, Stephen Boyd, Bjorn Andersson,
	linux-arm-msm, linux-phy, linux-kernel, stable, Konrad Dybcio
In-Reply-To: <20260422-edp_phy-v4-0-c38bef2d027b@oss.qualcomm.com>

On Wed, Apr 22, 2026 at 02:01:50PM +0800, Yongxing Mou wrote:
> Currently the PHY selects the DP/eDP configuration tables in a fixed way,
> choosing the table when enable. This driver has known issues:
> 1. The selected table does not match the actual platform mode.
> 2. It cannot support both modes at the same time.
> 
> As discussed here[1], this series:
> 1. Cleans up duplicated and incorrect tables based on the HPG.
> 2. Fixes the LDO programming error in eDP mode.
> 3. Adds DP/eDP mode switching support.
> 
> Note: x1e80100/sa8775p/sc7280/SC8280XP have been tested, while

Tested with eDP or with mini-DP too?

> glymur/sc8180x have not been tested.
> 
> [1] https://lore.kernel.org/all/20260119-klm_dpphy-v2-1-52252190940b@oss.qualcomm.com/
> 
> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
> ---
> Changes in v4:
> - Splite changes.[Dmitry]
> - Add sc8180x tables in a single chagne.[Dmitry][Konrad]
> - Link to v3: https://lore.kernel.org/r/20260302-edp_phy-v3-0-ca8888d793b0@oss.qualcomm.com
> 
> Changes in v3:
> - Rebase to next-20260224.[Dmitry]
> - Only enable TX1 LDO when lane counts > 2.[Konrad]
> - Link to v2: https://lore.kernel.org/all/20260213-edp_phy-v2-0-43c40976435e@oss.qualcomm.com/
> 
> Changes in v2:
> - Combine the third patch with the first one.[Dmitry]
> - Fix code formatting issues.[Konrad][Dmitry]
> - Update the commit message description.[Dmitry][Konrad]
> - Fix kodiak swing/pre_emp table values.[Konrad]
> 
> ---
> Yongxing Mou (5):
>       phy: qcom: edp: Unify generic DP/eDP swing and pre-emphasis tables
>       phy: qcom: edp: Add eDP/DP mode switch support
>       phy: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
>       phy: qcom: edp: Fix AUX_CFG8 programming for DP mode
>       phy: qcom: edp: Add PHY-specific LDO config for eDP low vdiff
> 
>  drivers/phy/qualcomm/phy-qcom-edp.c | 221 ++++++++++++++++++++++++++++--------
>  1 file changed, 173 insertions(+), 48 deletions(-)
> ---
> base-commit: bee6ea30c48788e18348309f891ed8afbf7702ac
> change-id: 20260205-edp_phy-1eca3ed074c0
> 
> Best regards,
> -- 
> Yongxing Mou <yongxing.mou@oss.qualcomm.com>
> 
> 
> -- 
> linux-phy mailing list
> linux-phy@lists.infradead.org
> https://lists.infradead.org/mailman/listinfo/linux-phy

-- 
With best wishes
Dmitry

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v4 2/5] phy: qcom: edp: Add eDP/DP mode switch support
From: Yongxing Mou @ 2026-04-23  3:14 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Vinod Koul, Neil Armstrong, Stephen Boyd, Bjorn Andersson,
	linux-arm-msm, linux-phy, linux-kernel, stable, Konrad Dybcio
In-Reply-To: <2cyvdtnnmrfz4zffhikfxl2goyby73gybgm3ih52rfpyvbhnzk@37x3g26o2t33>



On 4/23/2026 12:14 AM, Dmitry Baryshkov wrote:
> On Wed, Apr 22, 2026 at 02:01:52PM +0800, Yongxing Mou wrote:
>> The eDP PHY supports both eDP/DP modes, each requires a different table.
>> The current driver doesn't support both modes and use either the eDP or
>> DP table when enable the platform.
> 
> This is not quite true. The driver supports both modes, but it uses a
> fixed static table for eDP programming.
> 
> Other than the commit message, LGTM.
> 
Will modify next patch.
> 
>> Add a separate set of tables for eDP
>> and DP modes, and select the appropriate table based on the current mode.
>>
>> Glymur's DP mode table differs from the other platforms, add a dedicated
>> table for it.
>>
>> Since both modes are supported, so also fixes the table mismatch for
>> X1E80100(eDP) and SA8775P(DP).
>>
>> Cc: stable@vger.kernel.org
>> Fixes: 3f12bf16213c ("phy: qcom: edp: Add support for eDP PHY on SA8775P")
>> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>> ---
>>   drivers/phy/qualcomm/phy-qcom-edp.c | 46 +++++++++++++++++++++++++++----------
>>   1 file changed, 34 insertions(+), 12 deletions(-)
>>
> 


-- 
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: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
From: Yongxing Mou @ 2026-04-23  3:28 UTC (permalink / raw)
  To: Konrad Dybcio, Vinod Koul, Neil Armstrong, Stephen Boyd,
	Bjorn Andersson
  Cc: linux-arm-msm, linux-phy, linux-kernel
In-Reply-To: <df40b4d1-6133-4d49-a7e3-47cbb2b058e9@oss.qualcomm.com>



On 4/22/2026 6:42 PM, Konrad Dybcio wrote:
> On 4/22/26 8:01 AM, Yongxing Mou wrote:
>> SC7280 and SC8180X previously shared the same cfg because they did not use
>> swing/pre-emphasis tables. Add the corresponding tables for these
>> platforms. Since they have different PHY sub-versions, their eDP/DP mode
>> tables also differ, so move SC8180X to its own cfg instead of reusing the
>> SC7280 one.
>>
>> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>> ---
> 
> 
> 
>> +static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v2 = {
>> +	.swing_hbr_rbr = &edp_swing_hbr_rbr,
> 
> For eDP / low-Vdiff:
> 
> I believe the RBR swing settings for 8180 should
> instead be:
> 
> 0x07 0x0f 0x17 0x1f (matches)
Emm i see from ipcat eDP Low vdiff(Lower HBR)  swing settings is
0x07 0x0f 0x16 0x1f
> (the rest differs)
> 0x0d 0x16 0x1e
> 0x11 0x1b
> 0x16
> 


> The preem RBR almost matches, one byte is off
> (arr[0][1] = 0x12 on poipu, 0x11 on kodiak)
> 
Thanks,, here need to be fixed.

> The swing and preem settings for HBR3 look OK
> 
> For DP / low-Vdiff:
> 
> .swing_hbr3_hbr2 OK
> .swing_hbr_rbr - I don't know. The docs are unclear whether the same
> settings should be used for RBR and HBR3, but maybe? There's a
> separate table for mini-DP but I doubt there's any poipu boards with
> such a connector (maybe some obscure ones)
> 
> .pre_emphasis_hbr3_hbr2 OK
> .pre_emphasis_hbr_rbr same as above
> 
Thanks for point this, so pre_emphasis_hbr_rbr same with 
pre_emphasis_hbr3_hbr2?  I also don't get it's RBR or HBR3 from phy HPG. 
But now i think only eDP will be used in upstreamed poipu boards. i 
check the dts and not find any poipu boards will use DP mode(or mini DP)..
> Konrad


-- 
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: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
From: Dmitry Baryshkov @ 2026-04-23  4:41 UTC (permalink / raw)
  To: Yongxing Mou
  Cc: Konrad Dybcio, Vinod Koul, Neil Armstrong, Stephen Boyd,
	Bjorn Andersson, linux-arm-msm, linux-phy, linux-kernel
In-Reply-To: <cbfa3db8-e500-42ce-8302-16af7b19afe1@oss.qualcomm.com>

On Thu, Apr 23, 2026 at 11:28:44AM +0800, Yongxing Mou wrote:
> 
> 
> On 4/22/2026 6:42 PM, Konrad Dybcio wrote:
> > The swing and preem settings for HBR3 look OK
> > 
> > For DP / low-Vdiff:
> > 
> > .swing_hbr3_hbr2 OK
> > .swing_hbr_rbr - I don't know. The docs are unclear whether the same
> > settings should be used for RBR and HBR3, but maybe? There's a
> > separate table for mini-DP but I doubt there's any poipu boards with
> > such a connector (maybe some obscure ones)
> > 
> > .pre_emphasis_hbr3_hbr2 OK
> > .pre_emphasis_hbr_rbr same as above
> > 
> Thanks for point this, so pre_emphasis_hbr_rbr same with
> pre_emphasis_hbr3_hbr2?  I also don't get it's RBR or HBR3 from phy HPG. But
> now i think only eDP will be used in upstreamed poipu boards. i check the
> dts and not find any poipu boards will use DP mode(or mini DP)..

After checking the HPG, could you please actually talk to the colleagues
who brough up the PHY on those platforms (with the downstreaam kernels)?
They might know the details not captured in the HPG.

-- 
With best wishes
Dmitry

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v4 0/5] phy: qcom: edp: Add DP/eDP switch for phys
From: Yongxing Mou @ 2026-04-23  6:08 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Vinod Koul, Neil Armstrong, Stephen Boyd, Bjorn Andersson,
	linux-arm-msm, linux-phy, linux-kernel, stable, Konrad Dybcio
In-Reply-To: <ifwckc6zx3ymlyjpqyt6iqglgz2c4thianaxxups7h5ts7ikyk@m67gguvtkvzb>



On 4/23/2026 1:24 AM, Dmitry Baryshkov wrote:
> On Wed, Apr 22, 2026 at 02:01:50PM +0800, Yongxing Mou wrote:
>> Currently the PHY selects the DP/eDP configuration tables in a fixed way,
>> choosing the table when enable. This driver has known issues:
>> 1. The selected table does not match the actual platform mode.
>> 2. It cannot support both modes at the same time.
>>
>> As discussed here[1], this series:
>> 1. Cleans up duplicated and incorrect tables based on the HPG.
>> 2. Fixes the LDO programming error in eDP mode.
>> 3. Adds DP/eDP mode switching support.
>>
>> Note: x1e80100/sa8775p/sc7280/SC8280XP have been tested, while
> 
> Tested with eDP or with mini-DP too?
> 
x1e80100 eDP (hamoa-evk)
sa8775p DP(full-size)
sc7280 (rb3, mini-DP)
sorry for sa8775p mini-DP... i don't have the hardware to test.
>> glymur/sc8180x have not been tested.
>>
>> [1] https://lore.kernel.org/all/20260119-klm_dpphy-v2-1-52252190940b@oss.qualcomm.com/
>>
>> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>> ---
>> Changes in v4:
>> - Splite changes.[Dmitry]
>> - Add sc8180x tables in a single chagne.[Dmitry][Konrad]
>> - Link to v3: https://lore.kernel.org/r/20260302-edp_phy-v3-0-ca8888d793b0@oss.qualcomm.com
>>
>> Changes in v3:
>> - Rebase to next-20260224.[Dmitry]
>> - Only enable TX1 LDO when lane counts > 2.[Konrad]
>> - Link to v2: https://lore.kernel.org/all/20260213-edp_phy-v2-0-43c40976435e@oss.qualcomm.com/
>>
>> Changes in v2:
>> - Combine the third patch with the first one.[Dmitry]
>> - Fix code formatting issues.[Konrad][Dmitry]
>> - Update the commit message description.[Dmitry][Konrad]
>> - Fix kodiak swing/pre_emp table values.[Konrad]
>>
>> ---
>> Yongxing Mou (5):
>>        phy: qcom: edp: Unify generic DP/eDP swing and pre-emphasis tables
>>        phy: qcom: edp: Add eDP/DP mode switch support
>>        phy: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
>>        phy: qcom: edp: Fix AUX_CFG8 programming for DP mode
>>        phy: qcom: edp: Add PHY-specific LDO config for eDP low vdiff
>>
>>   drivers/phy/qualcomm/phy-qcom-edp.c | 221 ++++++++++++++++++++++++++++--------
>>   1 file changed, 173 insertions(+), 48 deletions(-)
>> ---
>> base-commit: bee6ea30c48788e18348309f891ed8afbf7702ac
>> change-id: 20260205-edp_phy-1eca3ed074c0
>>
>> Best regards,
>> -- 
>> Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>>
>>
>> -- 
>> linux-phy mailing list
>> linux-phy@lists.infradead.org
>> https://lists.infradead.org/mailman/listinfo/linux-phy
> 


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH v3 1/5] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add support for glymur Gen5 x8 bifurcation mode
From: Qiang Yu @ 2026-04-23  6:29 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio,
	linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <fb6e8d3c-4cb1-4c20-a570-e9f6ae9a651c@kernel.org>

On Wed, Apr 22, 2026 at 08:27:02AM +0200, Krzysztof Kozlowski wrote:
> On 16/04/2026 04:58, Qiang Yu wrote:
> >>>    reset-names:
> >>>      minItems: 1
> >>>      items:
> >>>        - const: phy
> >>>        - const: phy_nocsr
> >>> +      - const: phy_b
> >>> +      - const: phy_b_nocsr
> >>
> >> And now I doubt that all the changes here are for duplicated node.
> >>
> > 
> > All the changes here are for 1x8 PHY node.
> > 
> >> Maybe just the commit msg is confusing and instead of describing some
> >> node which combines two other phys just say what device is here being
> >> described.
> >>
> > 
> > Okay, I will focus on describing the required resources. Is the
> > description below clearer?
> > 
> > Glymur has two physical Gen5x4 PCIe PHY blocks: pcie3a phy and pcie3b phy.
> 
> 
> I just proven you that it is not true.
>

Yeah, I see it. I have to say you are right. It is a 1x8 PHY. We can set
the phy-cell to 1 and controller driver use different args to determine it
requires 1x4_a, 1x4_b or 1x8.

- Qiang Yu

> Best regards,
> Krzysztof

-- 
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: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
From: Konrad Dybcio @ 2026-04-23  9:31 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Yongxing Mou, Vinod Koul, Neil Armstrong, Stephen Boyd,
	Bjorn Andersson, linux-arm-msm, linux-phy, linux-kernel
In-Reply-To: <dyyfmgpxzpdlrutxi7gy4fudhpwvlljiylbbcirq6tgs2zr5yt@lpkrehmzgqpq>

On 4/22/26 6:33 PM, Dmitry Baryshkov wrote:
> On Wed, Apr 22, 2026 at 12:42:56PM +0200, Konrad Dybcio wrote:
>> On 4/22/26 8:01 AM, Yongxing Mou wrote:
>>> SC7280 and SC8180X previously shared the same cfg because they did not use
>>> swing/pre-emphasis tables. Add the corresponding tables for these
>>> platforms. Since they have different PHY sub-versions, their eDP/DP mode
>>> tables also differ, so move SC8180X to its own cfg instead of reusing the
>>> SC7280 one.
>>>
>>> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>>> ---
>>
>>
>>
>>> +static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v2 = {
>>> +	.swing_hbr_rbr = &edp_swing_hbr_rbr,
>>
>> For eDP / low-Vdiff:
>>
>> I believe the RBR swing settings for 8180 should
>> instead be:
>>
>> 0x07 0x0f 0x17 0x1f (matches)
> 
> 0x07, 0x0f, 0x16, 0x1f

Yes, you're right

Konrad


-- 
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: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
From: Konrad Dybcio @ 2026-04-23  9:32 UTC (permalink / raw)
  To: Yongxing Mou, Vinod Koul, Neil Armstrong, Stephen Boyd,
	Bjorn Andersson
  Cc: linux-arm-msm, linux-phy, linux-kernel
In-Reply-To: <cbfa3db8-e500-42ce-8302-16af7b19afe1@oss.qualcomm.com>

On 4/23/26 5:28 AM, Yongxing Mou wrote:
> 
> 
> On 4/22/2026 6:42 PM, Konrad Dybcio wrote:
>> On 4/22/26 8:01 AM, Yongxing Mou wrote:
>>> SC7280 and SC8180X previously shared the same cfg because they did not use
>>> swing/pre-emphasis tables. Add the corresponding tables for these
>>> platforms. Since they have different PHY sub-versions, their eDP/DP mode
>>> tables also differ, so move SC8180X to its own cfg instead of reusing the
>>> SC7280 one.
>>>
>>> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>>> ---
>>
>>
>>
>>> +static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v2 = {
>>> +    .swing_hbr_rbr = &edp_swing_hbr_rbr,
>>
>> For eDP / low-Vdiff:
>>
>> I believe the RBR swing settings for 8180 should
>> instead be:
>>
>> 0x07 0x0f 0x17 0x1f (matches)
> Emm i see from ipcat eDP Low vdiff(Lower HBR)  swing settings is
> 0x07 0x0f 0x16 0x1f

Yes, you're right, I made a typo

[...]

>> .pre_emphasis_hbr3_hbr2 OK
>> .pre_emphasis_hbr_rbr same as above
>>
> Thanks for point this, so pre_emphasis_hbr_rbr same with pre_emphasis_hbr3_hbr2?  I also don't get it's RBR or HBR3 from phy HPG. But now i think only eDP will be used in upstreamed poipu boards. i check the dts and not find any poipu boards will use DP mode(or mini DP)..

Yeah let's not worry about it today..

Konrad

-- 
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: qcom: edp: Add SC7280/SC8180X swing/pre-emphasis tables
From: Konrad Dybcio @ 2026-04-23  9:32 UTC (permalink / raw)
  To: Yongxing Mou, Vinod Koul, Neil Armstrong, Stephen Boyd,
	Bjorn Andersson
  Cc: linux-arm-msm, linux-phy, linux-kernel
In-Reply-To: <6a83b074-8a19-4148-a4df-bd11e27e7dce@oss.qualcomm.com>

On 4/23/26 11:32 AM, Konrad Dybcio wrote:
> On 4/23/26 5:28 AM, Yongxing Mou wrote:
>>
>>
>> On 4/22/2026 6:42 PM, Konrad Dybcio wrote:
>>> On 4/22/26 8:01 AM, Yongxing Mou wrote:
>>>> SC7280 and SC8180X previously shared the same cfg because they did not use
>>>> swing/pre-emphasis tables. Add the corresponding tables for these
>>>> platforms. Since they have different PHY sub-versions, their eDP/DP mode
>>>> tables also differ, so move SC8180X to its own cfg instead of reusing the
>>>> SC7280 one.
>>>>
>>>> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>>>> ---
>>>
>>>
>>>
>>>> +static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v2 = {
>>>> +    .swing_hbr_rbr = &edp_swing_hbr_rbr,
>>>
>>> For eDP / low-Vdiff:
>>>
>>> I believe the RBR swing settings for 8180 should
>>> instead be:
>>>
>>> 0x07 0x0f 0x17 0x1f (matches)
>> Emm i see from ipcat eDP Low vdiff(Lower HBR)  swing settings is
>> 0x07 0x0f 0x16 0x1f
> 
> Yes, you're right, I made a typo
> 
> [...]
> 
>>> .pre_emphasis_hbr3_hbr2 OK
>>> .pre_emphasis_hbr_rbr same as above
>>>
>> Thanks for point this, so pre_emphasis_hbr_rbr same with pre_emphasis_hbr3_hbr2?  I also don't get it's RBR or HBR3 from phy HPG. But now i think only eDP will be used in upstreamed poipu boards. i check the dts and not find any poipu boards will use DP mode(or mini DP)..
> 
> Yeah let's not worry about it today..

About mini-dp specifically that is

Konrad

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* Re: [PATCH 0/5] phy: qcom: qmp-pcie: Add PCIe Gen5 8-lane bifurcation support for Glymur
From: Konrad Dybcio @ 2026-04-24 10:58 UTC (permalink / raw)
  To: Neil Armstrong, Qiang Yu
  Cc: Vinod Koul, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Philipp Zabel, Bjorn Andersson, Konrad Dybcio, linux-arm-msm,
	linux-phy, devicetree, linux-kernel
In-Reply-To: <fb75023e-8fac-49c1-a8b7-2eb8b70fda3e@linaro.org>

On 3/6/26 11:34 AM, Neil Armstrong wrote:
> On 3/6/26 10:26, Qiang Yu wrote:
>> On Thu, Mar 05, 2026 at 10:14:05AM +0100, Konrad Dybcio wrote:
>>> On 3/4/26 9:21 AM, Qiang Yu wrote:
>>>> This patch series adds support for PCIe Gen5 8-lane bifurcation mode on
>>>> the Glymur SoC's third PCIe controller. In this configuration, pcie3a PHY
>>>> acts as leader and pcie3b PHY as follower to form a single 8-lane PCIe
>>>> Gen5 interface.
>>>>
>>>> To support 8-lanes mode, this patch series add multiple power domain and
>>>> multi nocsr reset infrastructure as the hardware programming guide
>>>> specifies a strict initialization sequence for bifurcation mode that
>>>> requires coordinated multi-PHY resource management:
>>>>
>>>> 1. Turn on both pcie3a_phy_gdsc and pcie3b_phy_gdsc power domains
>>>> 2. Assert both pcie3a and pcie3b nocsr resets, then deassert them together
>>>> 3. Enable all pcie3a PHY clocks and pcie3b PHY aux clock (bifur_aux)
>>>> 4. Poll for PHY ready status
>>>
>>> I think we never concluded the discussion where I suggested the
>>> bifurcated PHY may be better expressed as a single node with
>>> #phy-cells = <1>, removing the need for duplicated resource references
> 
> DT requires strict hardware description, no abstraction for HW, so if there's
> 2 PHYs, then add 2 separate phys and reference them from the PCie controller.

A single device *is* the strict HW description here. There's a single
shared top-level set of controls (mostly in the "COM[mon]" block) and
8 PCIe lanes that are (roughly speaking) unaware of what configuration
they're in

This is very much analogous to the USB3+DP combo PHY, where the USB and
DP parts are reasonably separate (you can turn the USB or the DP part off
independently), but those are building blocks that are sort of just two
"front-ends" to the rest of the QMPPHY hardware, that process data from
the otherwise unaware pairs of lanes in one configuration or another

Konrad


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* [PATCH v22 1/8] soc: cadence: Create helper functions for Cadence MHDP
From: Laurentiu Palcu @ 2026-04-24 11:07 UTC (permalink / raw)
  To: Parshuram Thombare, Swapnil Jakhade, Dmitry Baryshkov,
	Nikhil Devshatwar, Jayesh Choudhary
  Cc: dri-devel, devicetree, linux-kernel, linux-phy, imx,
	linux-arm-kernel, linux, Alexander Stein, Ying Liu
In-Reply-To: <20260424-dcss-hdmi-upstreaming-v22-0-30a28f89298d@oss.nxp.com>

From: Sandor Yu <Sandor.yu@nxp.com>

Cadence MHDP IP includes a firmware. Driver and firmware communicate
through a mailbox. The basic mailbox access functions in this patch are
derived from the DRM bridge MHDP8546 driver.  New mailbox access
functions have been created based on different mailbox return values and
security types, making them reusable across different MHDP driver
versions and SOCs.

These helper fucntions will be reused in both the DRM bridge driver
MDHP8501 and the i.MX8MQ HDPTX PHY driver.

Six mailbox access helper functions are introduced.
Three for non-secure mailbox access:
 - cdns_mhdp_mailbox_send()
 - cdns_mhdp_mailbox_send_recv()
 - cdns_mhdp_mailbox_send_recv_multi()
The other three for secure mailbox access:
 - cdns_mhdp_secure_mailbox_send()
 - cdns_mhdp_secure_mailbox_send_recv()
 - cdns_mhdp_secure_mailbox_send_recv_multi()

All MHDP commands that need to be passed through the mailbox
should be rewritten using these new helper functions.

The register read/write and DP DPCD read/write command functions
are also included in this new helper driver.

Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
Co-developed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
Signed-off-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>

---
To: Parshuram Thombare <pthombar@cadence.com>
To: Swapnil Jakhade <sjakhade@cadence.com>
To: Dmitry Baryshkov <lumag@kernel.org>
To: Nikhil Devshatwar <nikhil.nd@ti.com>
To: Jayesh Choudhary <j-choudhary@ti.com>
---
 drivers/soc/Kconfig                    |   1 +
 drivers/soc/Makefile                   |   1 +
 drivers/soc/cadence/Kconfig            |   9 +
 drivers/soc/cadence/Makefile           |   3 +
 drivers/soc/cadence/cdns-mhdp-helper.c | 611 +++++++++++++++++++++++++++++++++
 include/soc/cadence/cdns-mhdp-helper.h | 143 ++++++++
 6 files changed, 768 insertions(+)

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index a2d65adffb805..8f2114b9a6b7d 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -6,6 +6,7 @@ source "drivers/soc/apple/Kconfig"
 source "drivers/soc/aspeed/Kconfig"
 source "drivers/soc/atmel/Kconfig"
 source "drivers/soc/bcm/Kconfig"
+source "drivers/soc/cadence/Kconfig"
 source "drivers/soc/canaan/Kconfig"
 source "drivers/soc/cirrus/Kconfig"
 source "drivers/soc/fsl/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index c9e689080ceb7..33612ccdf5c47 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -7,6 +7,7 @@ obj-y				+= apple/
 obj-y				+= aspeed/
 obj-$(CONFIG_ARCH_AT91)		+= atmel/
 obj-y				+= bcm/
+obj-y				+= cadence/
 obj-$(CONFIG_ARCH_CANAAN)	+= canaan/
 obj-$(CONFIG_EP93XX_SOC)        += cirrus/
 obj-$(CONFIG_ARCH_DOVE)		+= dove/
diff --git a/drivers/soc/cadence/Kconfig b/drivers/soc/cadence/Kconfig
new file mode 100644
index 0000000000000..d4a8e8e751882
--- /dev/null
+++ b/drivers/soc/cadence/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config CDNS_MHDP_HELPER
+	tristate
+	help
+	  Enable Cadence MHDP helpers for mailbox, HDMI and DP.
+	  This driver provides a foundational layer of mailbox communication for
+	  various Cadence MHDP IP implementations, such as HDMI and DisplayPort.
+
diff --git a/drivers/soc/cadence/Makefile b/drivers/soc/cadence/Makefile
new file mode 100644
index 0000000000000..a1f42e1936ca5
--- /dev/null
+++ b/drivers/soc/cadence/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_CDNS_MHDP_HELPER) += cdns-mhdp-helper.o
diff --git a/drivers/soc/cadence/cdns-mhdp-helper.c b/drivers/soc/cadence/cdns-mhdp-helper.c
new file mode 100644
index 0000000000000..5657e88131ba1
--- /dev/null
+++ b/drivers/soc/cadence/cdns-mhdp-helper.c
@@ -0,0 +1,611 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023, 2024 NXP Semiconductor, Inc.
+ *
+ */
+#include <linux/dev_printk.h>
+#include <linux/module.h>
+#include <soc/cadence/cdns-mhdp-helper.h>
+
+/* Mailbox helper functions */
+static int mhdp_mailbox_read(struct cdns_mhdp_base *base)
+{
+	int ret, empty;
+
+	lockdep_assert_held(&base->mailbox_mutex);
+
+	ret = readx_poll_timeout(readl, base->regs + CDNS_MAILBOX_EMPTY,
+				 empty, !empty, MAILBOX_RETRY_US,
+				 MAILBOX_TIMEOUT_US);
+	if (ret < 0)
+		return ret;
+
+	return readl(base->regs + CDNS_MAILBOX_RX_DATA) & 0xff;
+}
+
+static int mhdp_mailbox_write(struct cdns_mhdp_base *base, u8 val)
+{
+	int ret, full;
+
+	lockdep_assert_held(&base->mailbox_mutex);
+
+	ret = readx_poll_timeout(readl, base->regs + CDNS_MAILBOX_FULL,
+				 full, !full, MAILBOX_RETRY_US,
+				 MAILBOX_TIMEOUT_US);
+	if (ret < 0)
+		return ret;
+
+	writel(val, base->regs + CDNS_MAILBOX_TX_DATA);
+
+	return 0;
+}
+
+static int mhdp_mailbox_read_secure(struct cdns_mhdp_base *base)
+{
+	int ret, empty;
+
+	lockdep_assert_held(&base->mailbox_mutex);
+
+	ret = readx_poll_timeout(readl, base->sapb_regs + CDNS_MAILBOX_EMPTY,
+				 empty, !empty, MAILBOX_RETRY_US,
+				 MAILBOX_TIMEOUT_US);
+	if (ret < 0)
+		return ret;
+
+	return readl(base->sapb_regs + CDNS_MAILBOX_RX_DATA) & 0xff;
+}
+
+static int mhdp_mailbox_write_secure(struct cdns_mhdp_base *base, u8 val)
+{
+	int ret, full;
+
+	lockdep_assert_held(&base->mailbox_mutex);
+
+	ret = readx_poll_timeout(readl, base->sapb_regs + CDNS_MAILBOX_FULL,
+				 full, !full, MAILBOX_RETRY_US,
+				 MAILBOX_TIMEOUT_US);
+	if (ret < 0)
+		return ret;
+
+	writel(val, base->sapb_regs + CDNS_MAILBOX_TX_DATA);
+
+	return 0;
+}
+
+static int mhdp_mailbox_recv_header(struct cdns_mhdp_base *base,
+				    u8 module_id, u8 opcode,
+				    u16 req_size, bool secure)
+{
+	u32 mbox_size, i;
+	u8 header[4];
+	int ret;
+
+	/* read the header of the message */
+	for (i = 0; i < sizeof(header); i++) {
+		if (secure)
+			ret = mhdp_mailbox_read_secure(base);
+		else
+			ret = mhdp_mailbox_read(base);
+		if (ret < 0)
+			return ret;
+
+		header[i] = ret;
+	}
+
+	mbox_size = get_unaligned_be16(header + 2);
+
+	/*
+	 * If the message in mailbox is not what we want, we need to
+	 * clear the mailbox by reading its contents.
+	 * Response data length for HDCP TX HDCP_TRAN_IS_REC_ID_VALID depend on
+	 * case.
+	 */
+	if (opcode != header[0] ||
+	    module_id != header[1] ||
+	   (opcode != HDCP_TRAN_IS_REC_ID_VALID && req_size != mbox_size)) {
+		for (i = 0; i < mbox_size; i++) {
+			if (secure)
+				ret = mhdp_mailbox_read_secure(base);
+			else
+				ret = mhdp_mailbox_read(base);
+			if (ret < 0)
+				break;
+		}
+
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mhdp_mailbox_recv_data(struct cdns_mhdp_base *base,
+				  u8 *buff, u16 buff_size, bool secure)
+{
+	u32 i;
+	int ret;
+
+	for (i = 0; i < buff_size; i++) {
+		if (secure)
+			ret = mhdp_mailbox_read_secure(base);
+		else
+			ret = mhdp_mailbox_read(base);
+		if (ret < 0)
+			return ret;
+
+		buff[i] = ret;
+	}
+
+	return 0;
+}
+
+static int mhdp_mailbox_send(struct cdns_mhdp_base *base, u8 module_id,
+			     u8 opcode, u16 size, u8 *message, bool secure)
+{
+	u8 header[4];
+	int ret, i;
+
+	header[0] = opcode;
+	header[1] = module_id;
+	put_unaligned_be16(size, header + 2);
+
+	for (i = 0; i < sizeof(header); i++) {
+		if (secure)
+			ret = mhdp_mailbox_write_secure(base, header[i]);
+		else
+			ret = mhdp_mailbox_write(base, header[i]);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < size; i++) {
+		if (secure)
+			ret = mhdp_mailbox_write_secure(base, message[i]);
+		else
+			ret = mhdp_mailbox_write(base, message[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * cdns_mhdp_mailbox_send - Sends a message via the MHDP mailbox.
+ *
+ * This function sends a message via the MHDP mailbox.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @module_id: ID of the module to send the message to.
+ * @opcode: Operation code of the message.
+ * @size: Size of the message data.
+ * @message: Pointer to the message data.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_mailbox_send(struct cdns_mhdp_base *base, u8 module_id,
+			   u8 opcode, u16 size, u8 *message)
+{
+	guard(mutex)(&base->mailbox_mutex);
+
+	return mhdp_mailbox_send(base, module_id, opcode, size, message, false);
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_mailbox_send);
+
+/**
+ * cdns_mhdp_mailbox_send_recv - Sends a message and receives a response.
+ *
+ * This function sends a message via the mailbox and then receives a response.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @module_id: ID of the module to send the message to.
+ * @opcode: Operation code of the message.
+ * @msg_size: Size of the message data.
+ * @msg: Pointer to the message data.
+ * @resp_size: Size of the response buffer.
+ * @resp: Pointer to the response buffer.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_mailbox_send_recv(struct cdns_mhdp_base *base,
+				u8 module_id, u8 opcode,
+				u16 msg_size, u8 *msg,
+				u16 resp_size, u8 *resp)
+{
+	int ret;
+
+	guard(mutex)(&base->mailbox_mutex);
+
+	ret = mhdp_mailbox_send(base, module_id, opcode, msg_size, msg, false);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, CMD=%d send failed: %d\n",
+			module_id, opcode, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_header(base, module_id, opcode, resp_size, false);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, CMD=%d recv header failed: %d\n",
+			module_id, opcode, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_data(base, resp, resp_size, false);
+	if (ret)
+		dev_err(base->dev, "ModuleID=%d, CMD=%d recv data failed: %d\n",
+			module_id, opcode, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_mailbox_send_recv);
+
+/**
+ * cdns_mhdp_mailbox_send_recv_multi - Sends a message and receives multiple
+ * responses.
+ *
+ * This function sends a message to a specified module via the MHDP mailbox and
+ * then receives multiple responses from the module.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @module_id: ID of the module to send the message to.
+ * @opcode: Operation code of the message.
+ * @msg_size: Size of the message data.
+ * @msg: Pointer to the message data.
+ * @opcode_resp: Operation code of the response.
+ * @resp1_size: Size of the first response buffer.
+ * @resp1: Pointer to the first response buffer.
+ * @resp2_size: Size of the second response buffer.
+ * @resp2: Pointer to the second response buffer.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_mailbox_send_recv_multi(struct cdns_mhdp_base *base,
+				      u8 module_id, u8 opcode,
+				      u16 msg_size, u8 *msg,
+				      u8 opcode_resp,
+				      u16 resp1_size, u8 *resp1,
+				      u16 resp2_size, u8 *resp2)
+{
+	int ret;
+
+	guard(mutex)(&base->mailbox_mutex);
+
+	ret = mhdp_mailbox_send(base, module_id, opcode, msg_size, msg, false);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, CMD=%d send failed: %d\n",
+			module_id, opcode, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_header(base, module_id, opcode_resp,
+				       resp1_size + resp2_size, false);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv header failed: %d\n",
+			module_id, opcode_resp, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_data(base, resp1, resp1_size, false);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv data1 failed: %d\n",
+			module_id, opcode_resp, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_data(base, resp2, resp2_size, false);
+	if (ret)
+		dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv data2 failed: %d\n",
+			module_id, opcode_resp, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_mailbox_send_recv_multi);
+
+/**
+ * cdns_mhdp_secure_mailbox_send - Sends a secure message via the mailbox.
+ *
+ * This function sends a secure message to a specified module via the MHDP
+ * mailbox.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @module_id: ID of the module to send the message to.
+ * @opcode: Operation code of the message.
+ * @size: Size of the message data.
+ * @message: Pointer to the message data.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_base *base, u8 module_id,
+				  u8 opcode, u16 size, u8 *message)
+{
+	guard(mutex)(&base->mailbox_mutex);
+
+	return mhdp_mailbox_send(base, module_id, opcode, size, message, true);
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_secure_mailbox_send);
+
+/**
+ * cdns_mhdp_secure_mailbox_send_recv - Sends a secure message and receives a
+ * response.
+ *
+ * This function sends a secure message to a specified module via the mailbox
+ * and then receives a response from the module.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @module_id: ID of the module to send the message to.
+ * @opcode: Operation code of the message.
+ * @msg_size: Size of the message data.
+ * @msg: Pointer to the message data.
+ * @resp_size: Size of the response buffer.
+ * @resp: Pointer to the response buffer.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_secure_mailbox_send_recv(struct cdns_mhdp_base *base,
+				       u8 module_id, u8 opcode,
+				       u16 msg_size, u8 *msg,
+				       u16 resp_size, u8 *resp)
+{
+	int ret;
+
+	guard(mutex)(&base->mailbox_mutex);
+
+	ret = mhdp_mailbox_send(base, module_id, opcode, msg_size, msg, true);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, CMD=%d send failed: %d\n",
+			module_id, opcode, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_header(base, module_id, opcode, resp_size, true);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, CMD=%d recv header failed: %d\n",
+			module_id, opcode, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_data(base, resp, resp_size, true);
+	if (ret)
+		dev_err(base->dev, "ModuleID=%d, CMD=%d recv data failed: %d\n",
+			module_id, opcode, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_secure_mailbox_send_recv);
+
+/**
+ * cdns_mhdp_secure_mailbox_send_recv_multi - Sends a secure message and
+ * receives multiple responses.
+ *
+ * This function sends a secure message to a specified module and receives
+ * multiple responses.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @module_id: ID of the module to send the message to.
+ * @opcode: Operation code of the message.
+ * @msg_size: Size of the message data.
+ * @msg: Pointer to the message data.
+ * @opcode_resp: Operation code of the response.
+ * @resp1_size: Size of the first response buffer.
+ * @resp1: Pointer to the first response buffer.
+ * @resp2_size: Size of the second response buffer.
+ * @resp2: Pointer to the second response buffer.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_secure_mailbox_send_recv_multi(struct cdns_mhdp_base *base,
+					     u8 module_id, u8 opcode,
+					     u16 msg_size, u8 *msg,
+					     u8 opcode_resp,
+					     u16 resp1_size, u8 *resp1,
+					     u16 resp2_size, u8 *resp2)
+{
+	int ret;
+
+	guard(mutex)(&base->mailbox_mutex);
+
+	ret = mhdp_mailbox_send(base, module_id, opcode, msg_size, msg, true);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, CMD=%d send failed: %d\n",
+			module_id, opcode, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_header(base, module_id, opcode_resp,
+				       resp1_size + resp2_size, true);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv header failed: %d\n",
+			module_id, opcode_resp, ret);
+		return ret;
+	}
+
+	ret = mhdp_mailbox_recv_data(base, resp1, resp1_size, true);
+	if (ret) {
+		dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv data1 failed: %d\n",
+			module_id, opcode_resp, ret);
+		return ret;
+	}
+
+	/*
+	 * Response data length for HDCP TX HDCP_TRAN_IS_REC_ID_VALID depend on
+	 * the number of HDCP receivers in resp1[0].
+	 * 1 for regular case, more can be in repeater.
+	 */
+	if (module_id == MB_MODULE_ID_HDCP_TX &&
+	    opcode == HDCP_TRAN_IS_REC_ID_VALID)
+		ret = mhdp_mailbox_recv_data(base, resp2, 5 * resp1[0], true);
+	else
+		ret = mhdp_mailbox_recv_data(base, resp2, resp2_size, true);
+	if (ret)
+		dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv data2 failed: %d\n",
+			module_id, opcode_resp, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_secure_mailbox_send_recv_multi);
+
+/**
+ * cdns_mhdp_reg_read - Reads a general register value.
+ *
+ * This function reads the value from a general register
+ * using the mailbox.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @addr: Address of the register to read.
+ * @value: Pointer to store the read value.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_reg_read(struct cdns_mhdp_base *base, u32 addr, u32 *value)
+{
+	u8 msg[4], resp[8];
+	int ret;
+
+	put_unaligned_be32(addr, msg);
+
+	ret = cdns_mhdp_mailbox_send_recv(base, MB_MODULE_ID_GENERAL,
+					  GENERAL_REGISTER_READ,
+					  sizeof(msg), msg, sizeof(resp), resp);
+	if (ret)
+		goto out;
+
+	/* Returned address value should be the same as requested */
+	if (memcmp(msg, resp, sizeof(msg))) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	*value = get_unaligned_be32(resp + 4);
+out:
+	if (ret) {
+		dev_err(base->dev, "Failed to read register\n");
+		*value = 0;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_reg_read);
+
+/**
+ * cdns_mhdp_reg_write - Writes a value to a general register.
+ *
+ * This function writes a value to a general register using the mailbox.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @addr: Address of the register to write to.
+ * @val: Value to write to the register.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_reg_write(struct cdns_mhdp_base *base, u32 addr, u32 val)
+{
+	u8 msg[8];
+
+	put_unaligned_be32(addr, msg);
+	put_unaligned_be32(val, msg + 4);
+
+	return cdns_mhdp_mailbox_send(base, MB_MODULE_ID_GENERAL,
+				     GENERAL_REGISTER_WRITE,
+				     sizeof(msg), msg);
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_reg_write);
+
+/* DPTX helper functions */
+/**
+ * cdns_mhdp_dp_reg_write_bit - Writes a bit field to a DP register.
+ *
+ * This function writes a specific bit field within a DP register
+ * using the MHDP mailbox.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @addr: Address of the DP register.
+ * @start_bit: Starting bit position within the register.
+ * @bits_no: Number of bits to write.
+ * @val: Value to write to the bit field.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_dp_reg_write_bit(struct cdns_mhdp_base *base, u16 addr,
+			       u8 start_bit, u8 bits_no, u32 val)
+{
+	u8 field[8];
+
+	put_unaligned_be16(addr, field);
+	field[2] = start_bit;
+	field[3] = bits_no;
+	put_unaligned_be32(val, field + 4);
+
+	return cdns_mhdp_mailbox_send(base, MB_MODULE_ID_DP_TX,
+				      DPTX_WRITE_FIELD, sizeof(field), field);
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_dp_reg_write_bit);
+
+/**
+ * cdns_mhdp_dpcd_read - Reads data from a DPCD register.
+ *
+ * This function reads data from a specified DPCD register
+ * using the MHDP mailbox.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @addr: Address of the DPCD register to read.
+ * @data: Buffer to store the read data.
+ * @len: Length of the data to read.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_dpcd_read(struct cdns_mhdp_base *base,
+			u32 addr, u8 *data, u16 len)
+{
+	u8 msg[5], reg[5];
+
+	put_unaligned_be16(len, msg);
+	put_unaligned_be24(addr, msg + 2);
+
+	return cdns_mhdp_mailbox_send_recv_multi(base,
+						 MB_MODULE_ID_DP_TX,
+						 DPTX_READ_DPCD,
+						 sizeof(msg), msg,
+						 DPTX_READ_DPCD,
+						 sizeof(reg), reg,
+						 len, data);
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_dpcd_read);
+
+/**
+ * cdns_mhdp_dpcd_write - Writes data to a DPCD register.
+ *
+ * This function writes data to a specified DPCD register
+ * using the MHDP mailbox.
+ *
+ * @base: Pointer to the CDNS MHDP base structure.
+ * @addr: Address of the DPCD register to write to.
+ * @value: Value to write to the register.
+ *
+ * Returns: 0 on success, negative error code on failure.
+ */
+int cdns_mhdp_dpcd_write(struct cdns_mhdp_base *base, u32 addr, u8 value)
+{
+	u8 msg[6], reg[5];
+	int ret;
+
+	put_unaligned_be16(1, msg);
+	put_unaligned_be24(addr, msg + 2);
+	msg[5] = value;
+
+	ret = cdns_mhdp_mailbox_send_recv(base, MB_MODULE_ID_DP_TX,
+					  DPTX_WRITE_DPCD,
+					  sizeof(msg), msg, sizeof(reg), reg);
+	if (ret) {
+		dev_err(base->dev, "dpcd write failed: %d\n", ret);
+		return ret;
+	}
+
+	if (addr != get_unaligned_be24(reg + 2)) {
+		dev_err(base->dev,
+			"Invalid response: expected address 0x%06x, got 0x%06x\n",
+			addr, get_unaligned_be24(reg + 2));
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cdns_mhdp_dpcd_write);
+
+MODULE_DESCRIPTION("Cadence MHDP Helper driver");
+MODULE_AUTHOR("Sandor Yu <Sandor.yu@nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/soc/cadence/cdns-mhdp-helper.h b/include/soc/cadence/cdns-mhdp-helper.h
new file mode 100644
index 0000000000000..7e2ceb848fc2d
--- /dev/null
+++ b/include/soc/cadence/cdns-mhdp-helper.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023-2024 NXP Semiconductor, Inc.
+ */
+#ifndef __CDNS_MHDP_HELPER_H__
+#define __CDNS_MHDP_HELPER_H__
+
+#include <linux/iopoll.h>
+#include <linux/mutex.h>
+#include <linux/unaligned.h>
+
+/* mailbox regs offset */
+#define CDNS_MAILBOX_FULL			0x00008
+#define CDNS_MAILBOX_EMPTY			0x0000c
+#define CDNS_MAILBOX_TX_DATA			0x00010
+#define CDNS_MAILBOX_RX_DATA			0x00014
+
+#define MAILBOX_RETRY_US			1000
+#define MAILBOX_TIMEOUT_US			2000000
+
+/* Module ID Code */
+#define MB_MODULE_ID_DP_TX			0x01
+#define MB_MODULE_ID_HDMI_TX			0x03
+#define MB_MODULE_ID_HDCP_TX			0x07
+#define MB_MODULE_ID_HDCP_RX			0x08
+#define MB_MODULE_ID_HDCP_GENERAL		0x09
+#define MB_MODULE_ID_GENERAL			0x0A
+
+/* General Commands */
+#define GENERAL_MAIN_CONTROL			0x01
+#define GENERAL_TEST_ECHO			0x02
+#define GENERAL_BUS_SETTINGS			0x03
+#define GENERAL_TEST_ACCESS			0x04
+#define GENERAL_REGISTER_WRITE			0x05
+#define GENERAL_WRITE_FIELD			0x06
+#define GENERAL_REGISTER_READ			0x07
+#define GENERAL_GET_HPD_STATE			0x11
+
+/* DPTX Commands */
+#define DPTX_SET_POWER_MNG			0x00
+#define DPTX_SET_HOST_CAPABILITIES		0x01
+#define DPTX_GET_EDID				0x02
+#define DPTX_READ_DPCD				0x03
+#define DPTX_WRITE_DPCD				0x04
+#define DPTX_ENABLE_EVENT			0x05
+#define DPTX_WRITE_REGISTER			0x06
+#define DPTX_READ_REGISTER			0x07
+#define DPTX_WRITE_FIELD			0x08
+#define DPTX_TRAINING_CONTROL			0x09
+#define DPTX_READ_EVENT				0x0a
+#define DPTX_READ_LINK_STAT			0x0b
+#define DPTX_SET_VIDEO				0x0c
+#define DPTX_SET_AUDIO				0x0d
+#define DPTX_GET_LAST_AUX_STAUS			0x0e
+#define DPTX_SET_LINK_BREAK_POINT		0x0f
+#define DPTX_FORCE_LANES			0x10
+#define DPTX_HPD_STATE				0x11
+#define DPTX_ADJUST_LT				0x12
+
+/* HDMI TX Commands */
+#define HDMI_TX_READ				0x00
+#define HDMI_TX_WRITE				0x01
+#define HDMI_TX_UPDATE_READ			0x02
+#define HDMI_TX_EDID				0x03
+#define HDMI_TX_EVENTS				0x04
+#define HDMI_TX_HPD_STATUS			0x05
+
+/* HDCP TX Commands */
+#define HDCP_TRAN_CONFIGURATION			0x00
+#define HDCP2X_TX_SET_PUBLIC_KEY_PARAMS		0x01
+#define HDCP2X_TX_SET_DEBUG_RANDOM_NUMBERS	0x02
+#define HDCP2X_TX_RESPOND_KM			0x03
+#define HDCP1_TX_SEND_KEYS			0x04
+#define HDCP1_TX_SEND_RANDOM_AN			0x05
+#define HDCP_TRAN_STATUS_CHANGE			0x06
+#define HDCP2X_TX_IS_KM_STORED			0x07
+#define HDCP2X_TX_STORE_KM			0x08
+#define HDCP_TRAN_IS_REC_ID_VALID		0x09
+#define HDCP_TRAN_RESPOND_RECEIVER_ID_VALID	0x0a
+#define HDCP_TRAN_TEST_KEYS			0x0b
+#define HDCP2X_TX_SET_KM_KEY_PARAMS		0x0c
+#define HDCP_NUM_OF_SUPPORTED_MESSAGES		0x0d
+
+/**
+ * struct cdns_mhdp_base - Base structure for CDNS MHDP devices
+ * @dev: Pointer to the device structure
+ * @regs: Base address of the regular register space
+ * @sapb_regs: Base address of the secure APB register space
+ * @mailbox_mutex: Mutex to protect mailbox communications with firmware
+ *
+ * This structure contains the base resources needed for CDNS MHDP helper
+ * functions. Each device instance should have its own cdns_mhdp_base structure
+ * to ensure proper isolation of mailbox operations between multiple devices.
+ */
+struct cdns_mhdp_base {
+	struct device *dev;
+	void __iomem *regs;
+	void __iomem *sapb_regs;
+	struct mutex mailbox_mutex;
+};
+
+/* Mailbox helper functions */
+int cdns_mhdp_mailbox_send(struct cdns_mhdp_base *base,
+			   u8 module_id, u8 opcode,
+			   u16 size, u8 *message);
+int cdns_mhdp_mailbox_send_recv(struct cdns_mhdp_base *base,
+				u8 module_id, u8 opcode,
+				u16 msg_size, u8 *msg,
+				u16 resp_size, u8 *resp);
+int cdns_mhdp_mailbox_send_recv_multi(struct cdns_mhdp_base *base,
+				      u8 module_id, u8 opcode,
+				      u16 msg_size, u8 *msg,
+				      u8 opcode_resp,
+				      u16 resp1_size, u8 *resp1,
+				      u16 resp2_size, u8 *resp2);
+
+/* Secure mailbox helper functions */
+int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_base *base,
+				  u8 module_id, u8 opcode,
+				  u16 size, u8 *message);
+int cdns_mhdp_secure_mailbox_send_recv(struct cdns_mhdp_base *base,
+				       u8 module_id, u8 opcode,
+				       u16 msg_size, u8 *msg,
+				       u16 resp_size, u8 *resp);
+int cdns_mhdp_secure_mailbox_send_recv_multi(struct cdns_mhdp_base *base,
+					     u8 module_id, u8 opcode,
+					     u16 msg_size, u8 *msg,
+					     u8 opcode_resp,
+					     u16 resp1_size, u8 *resp1,
+					     u16 resp2_size, u8 *resp2);
+
+/* General commands helper functions */
+int cdns_mhdp_reg_read(struct cdns_mhdp_base *base, u32 addr, u32 *value);
+int cdns_mhdp_reg_write(struct cdns_mhdp_base *base, u32 addr, u32 val);
+
+/* DPTX commands helper functions */
+int cdns_mhdp_dp_reg_write_bit(struct cdns_mhdp_base *base, u16 addr,
+			       u8 start_bit, u8 bits_no, u32 val);
+int cdns_mhdp_dpcd_read(struct cdns_mhdp_base *base,
+			u32 addr, u8 *data, u16 len);
+int cdns_mhdp_dpcd_write(struct cdns_mhdp_base *base, u32 addr, u8 value);
+
+#endif /* __CDNS_MHDP_HELPER_H__ */

-- 
2.51.0

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH v22 0/8] Initial support Cadence MHDP8501(HDMI/DP) for i.MX8MQ
From: Laurentiu Palcu @ 2026-04-24 11:07 UTC (permalink / raw)
  To: Parshuram Thombare, Swapnil Jakhade, Dmitry Baryshkov,
	Nikhil Devshatwar, Jayesh Choudhary, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
	Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Vinod Koul, Frank Li,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
  Cc: dri-devel, devicetree, linux-kernel, linux-phy, imx,
	linux-arm-kernel, linux, Alexander Stein, Ying Liu

Hi,

Since Sandor left NXP some time back, I'll be taking over this patchset
and continue the upstreaming process from where he left off.

The patchset adds initial support for Cadence MHDP8501(HDMI/DP) DRM bridge
and Cadence HDP-TX PHY(HDMI/DP) for Freescale i.MX8MQ.

I addressed all remaining reviewers' comments from v20 but I'm not sure
whether Alexander's issue is still present. Alexander, let me know if
you're still experiencing a black screen with this patch-set and I'll
try to address it in the next revision.

Thanks,
Laurentiu

--
Changes in v22:
 - Addressed most of Sashiko review comments (per-patch changelog below):
   https://sashiko.dev/#/patchset/20260407-dcss-hdmi-upstreaming-v21-0-4681070ab82f%40oss.nxp.com
 - Removed all existing r-b tags since pretty much all patches have
   changes;
 - 0001 - soc: cadence: Create helper functions for Cadence MHDP
   - Global mailbox mutex replaced with a per-instance mailbox_mutex in struct
     cdns_mhdp_base
   - Added dedicated mhdp_mailbox_read/write_secure() functions; all mailbox
     helpers now take a bool secure parameter instead of a raw regs pointer
   - Fixed HDCP opcode numbering (values 0x09–0x0c shifted up by one)
   - KDoc style fixes throughout, added a kernel-doc comment to cdns_mhdp_base;
 - 0002 - drm: bridge: cadence: Update mhdp8546 mailbox access functions
   - Added mutex_init / mutex_destroy calls for the new per-instance mailbox
     mutex
 - 0003 - dt-bindings: display: bridge: Add Cadence MHDP8501
   - Dropped 'cdns,bridge-type' property (Krzysztof); added 'phy' child-node
     property to avoid having 2 nodes with the same address;
     fixed mdhp_phy -> mhdp_phy typo
 - 0004 - drm: bridge: Cadence: Add MHDP8501 DP/HDMI driver
   - Bridge type is now auto-detected by traversing the OF graph to the
     connector (DP or HDMI), replacing the removed DT property
   - Since PHY is now a child platform device, use devm_of_platform_populate
   - Extensive error handling improvements (goto labels, proper unwinding)
   - HDMI: fixed uninitialised packet[] buffer, SCDC read rewritten for
     correctness, hotplug handler uses proper modeset locking, atomic commit
     handles -EDEADLK, infoframe update moved after hardware config
 - 0005 - dt-bindings: phy: Add Freescale iMX8MQ DP and HDMI PHY
   - Binding file renamed to fsl,imx8mq-hdptx-phy.yaml to comply with DT spec;
     removed reg property (PHY inherits parent MMIO now); expanded example
     showing PHY as a child node
 - 0006 - phy: freescale: Add DisplayPort/HDMI Combo-PHY driver for i.MX8MQ
   - MMIO now mapped via devm_of_iomap(...parent...) instead of its own reg
     resource
   - Fixed uninitialised variable, wrong return type on link-rate error, NULL
     dereference in phy_valid, and swallowed error code in clock enable
 - 0007 - arm64: dts: imx8mq: Add DCSS + HDMI/DP display pipeline
   - PHY moved from top-level bus node to child of the bridge node;
     fixed mdhp_phy -> mhdp_phy typo
 - 0008 - arm64: dts: imx8mq: tqma8mq-mba8mx: Enable HDMI support
   - Added status = "okay" on the HDMI connector; removed now-gone
     cdns,bridge-type; added status = "disabled" in shared dtsi
 - Link to v21: https://lore.kernel.org/r/20260407-dcss-hdmi-upstreaming-v21-0-4681070ab82f@oss.nxp.com

Changes in v21:
 - Dropped "phy: Add HDMI configuration options" patch because it was
   already merged separately;
 - Rebased to latest linux-next (7.0-rc6) and fixed all issues
   introduced by API changes in DRM;
 - Addressed Maxime's comment on patch #5 and used debugfs file instead
   of sysfs for printing firmware version;
 - Addressed all Dmitry's comments: handled the
   cdns_mhdp_mailbox_send_recv_multi() error, removed the RGB 10bit
   unused code, added a dts property in order to get the bridge type (I
   couldn't find another way to do it...);
 - Dropped Krzysztof's r-b tag for patch #4 (which is now patch #3)
   since I added a new property;
 - Link to v20: https://lore.kernel.org/r/cover.1734340233.git.Sandor.yu@nxp.com

Changes in v20:
 - Patch #1: soc: cadence: Create helper functions for Cadence MHDP
 - Patch #2: drm: bridge: cadence: Update mhdp8546 mailbox access functions
   - The two patches are split from Patch #1 in v19.  The MHDP helper
     functions have been moved in a new "cadence" directory under the
     SOC directory in patch #1, in order to promote code reuse among
     MHDP8546, MHDP8501, and the i.MX8MQ HDMI/DP PHY drivers,
 - Patch #3: phy: Add HDMI configuration options
   - Add a-b tag
 - Patch #4: dt-bindings: display: bridge: Add Cadence MHDP8501
   - remove data type link of data-lanes
 - Patch #5: drm: bridge: Cadence: Add MHDP8501 DP/HDMI driver
   - Dump mhdp FW version by debugfs
   - Combine HDMI and DP cable detect functions into one function
   - Combine HDMI and DP cable bridge_mode_valid() functions into one function
   - Rename cdns_hdmi_reset_link() to cdns_hdmi_handle_hotplug()
   - Add comments for EDID in cdns_hdmi_handle_hotplug() and cdns_dp_check_link_state()
   - Add atomic_get_input_bus_fmts() and bridge_atomic_check() for DP driver
   - Remove bpc and color_fmt init in atomic_enable() function.
   - More detail comments for DDC adapter only support SCDC_I2C_SLAVE_ADDRESS
     read and write in HDMI driver.
 - Patch #7: phy: freescale: Add DisplayPort/HDMI Combo-PHY driver for i.MX8MQ
   - implify DP configuration handling by directly copying
     the configuration options to the driver's internal structure.
   - return the error code directly instead of logging an error message in `hdptx_clk_enable`
   - Remove redundant ref_clk_rate check
 - Link to v19: https://lore.kernel.org/r/cover.1732627815.git.Sandor.yu@nxp.com

Changes in v19:
 - Patch #1
   - use guard(mutex)
   - Add kerneldocs for all new APIs.
   - Detail comments for mailbox access specific case.
   - remove cdns_mhdp_dp_reg_write() because it is not needed by driver now.
 - Patch #3
   - move property data-lanes to endpoint of port@1
 - Patch #4
   - get endpoint for data-lanes as it had move to endpoint of port@1
   - update clock management as devm_clk_get_enabled() introduced.
   - Fix clear_infoframe() function is not work issue.
   - Manage PHY power state via phy_power_on() and phy_power_off().
 - Patch #6
   - Simplify the PLL table by removing unused and constant data
   - Remove PHY power management, controller driver will handle them.
   - Remove enum dp_link_rate
   - introduce read_pll_timeout.
   - update clock management as devm_clk_get_enabled() introduced.
   - remove cdns_hdptx_phy_init() and cdns_hdptx_phy_remove().
 - Patch #8:
   - move property data-lanes to endpoint of port@1
 - Link to v18: https://lore.kernel.org/r/cover.1730172244.git.Sandor.yu@nxp.com

Changes in v18:
 - Patch #1
   - Create three ordinary mailbox access APIs
       cdns_mhdp_mailbox_send
       cdns_mhdp_mailbox_send_recv
       cdns_mhdp_mailbox_send_recv_multi
   - Create three secure mailbox access APIs
       cdns_mhdp_secure_mailbox_send
       cdns_mhdp_secure_mailbox_send_recv
       cdns_mhdp_secure_mailbox_send_recv_multi
   - MHDP8546 DP and HDCP commands that need access mailbox are rewrited
     with above 6 API functions.
 - Patch #3
   - remove lane-mapping and replace it with data-lanes
   - remove r-b tag as property changed.
 - Patch #4
   - MHDP8501 HDMI and DP commands that need access mailbox are rewrited
     with new API functions created in patch #1.
   - replace lane-mapping with data-lanes, use the value from data-lanes
     to reorder HDMI and DP lane mapping.
   - create I2C adapter for HDMI SCDC, remove cdns_hdmi_scdc_write() function.
   - Rewrite cdns_hdmi_sink_config() function, use HDMI SCDC helper function
     drm_scdc_set_high_tmds_clock_ratio() and drm_scdc_set_scrambling()
     to config HDMI sink TMDS.
   - Remove struct video_info from HDMI driver.
   - Remove tmds_char_rate_valid() be called in bridge_mode_valid(),
     community had patch in reviewing to implement the function.
   - Remove warning message print when get unknown HPD cable status.
   - Add more detail comments for HDP plugin and plugout interrupt.
   - use dev_dbg to repleace DRM_INFO when cable HPD status changed.
   - Remove t-b tag as above code change.
 - Patch #6
   - fix build error as code rebase to latest kernel version.
 - Patch #8:
   - replace lane-mapping with data-lanes
 - Link to v17: https://lore.kernel.org/r/cover.1727159906.git.Sandor.yu@nxp.com

Changes in v17:
 - Patch #1:
   - Replaces the local mutex mbox_mutex with a global mutex mhdp_mailbox_mutex
 - Patch #2:
   - remove hdmi.h
   - add 2024 year to copyright
   - Add r-b tag.
 - Patch #3:
   - Add lane-mapping property.
 - Patch #4:
   - Reset the HDMI/DP link when an HPD (Hot Plug Detect) event is detected
   - Move the HDMI protocol settings from hdmi_ctrl_init() to a new function
     cdns_hdmi_set_hdmi_mode_type(), to align with the introduced link reset functionality.
   - Implement logic to check the type of HDMI sink.
     If the sink is not a hdmi display, set the default mode to DVI.
   - Implement hdmi_reset_infoframe function
   - Reorder certain bit definitions in the header file to follow a descending order.
   - Add "lane-mapping" property for both HDMI and DP, remove platform data from driver.
     lane-mapping should be setting in dts according different board layout.
   - Remove variable mode in struct cdns_mhdp8501_device, video mode could get from struct drm_crtc_state
   - Remove variable char_rate in  struct cdns_mhdp8501_device, it could get from struct struct drm_connector_state.hdmi
   - Replaces the local mutex mbox_mutex with a global mutex mhdp_mailbox_mutex
   - Remove mutext protect for phy_api access functions.
 - Patch #6:
   - Remove mbox_mutex
 - Link to v16: https://lore.kernel.org/r/cover.1719903904.git.Sandor.yu@nxp.com

Changes in v16:
 - Patch #2:
   - Remove pixel_clk_rate, bpc and color_space fields from struct
     phy_configure_opts_hdmi, they were replaced by
     unsigned long long tmds_char_rate.
   - Remove r-b and a-c tags because this patch have important change.
 - Patch #4:
   - Add DRM_BRIDGE_OP_HDMI flags for HDMI driver,
   - Introduce the hdmi info frame helper functions,
     added hdmi_clear_infoframe(), hdmi_write_infoframe() and
     hdmi_tmds_char_rate_valid() according Dmitry's patch
     'make use of the HDMI connector infrastructure' patchset ([2]).
   - mode_fixup() is replaced by atomic_check().
   - Fix video mode 4Kp30 did not work on some displays that support
     LTE_340Mcsc_scramble.
   - updated for tmds_char_rate added in patch #2.
 - Patch #6:
   - updated for tmds_char_rate added in patch #2.
 - Link to v15: https://lore.kernel.org/r/20240306101625.795732-1-alexander.stein@ew.tq-group.com

Changes in v15:
 - Patch #6 + #7:
   -  Merged PHY driver into a single combo PHY driver
 - Patch #7 + #8:
   - Add DT patches for a running HDMI setup

Changes in v14:
 - Patch #4:
   - Rebase to next-20240219, replace get_edid function by edid_read
     function as commits d807ad80d811b ("drm/bridge: add ->edid_read
     hook and drm_bridge_edid_read()") and 27b8f91c08d99 ("drm/bridge:
     remove ->get_edid callback") had change the API.

Changes in v13:
 - Patch #4:
   - Explicitly include linux/platform_device.h for cdns-mhdp8501-core.c
   - Fix build warning
   - Order bit bpc and color_space in descending shit.
 - Patch #7:
   - Fix build warning

Changes in v12:
 - Patch #1:
   - Move status initialize out of mbox_mutex.
   - Reorder API functions in alphabetical.
   - Add notes for malibox access functions.
   - Add year 2024 to copyright.
 - Patch #4:
   - Replace DRM_INFO with dev_info or dev_warn.
   - Replace DRM_ERROR with dev_err.
   - Return ret when cdns_mhdp_dpcd_read failed in function cdns_dp_aux_transferi().
   - Remove unused parmeter in function cdns_dp_get_msa_misc
     and use two separate variables for color space and bpc.
   - Add year 2024 to copyright.
 - Patch #6:
   - Return error code to replace -1 for function wait_for_ack().
   - Set cdns_phy->power_up = false in phy_power_down function.
   - Remove "RATE_8_1 = 810000", it is not used in driver.
   - Add year 2024 to copyright.
 - Patch #7:
   - Adjust clk disable order.
   - Return error code to replace -1 for function wait_for_ack().
   - Use bool for variable pclk_in.
   - Add year 2024 to copyright.

Changes in v11:
 - rewrite cdns_mhdp_set_firmware_active() in mhdp8546 core driver,
   use cdns_mhdp_mailbox_send() to replace cdns_mhdp_mailbox_write()
   same as the other mailbox access functions.
 - use static for cdns_mhdp_mailbox_write() and
   cdns_mhdp_mailbox_read() and remove them from EXPORT_SYMBOL_GPL().
 - remove MODULE_ALIAS() from mhdp8501 driver.

Changes in v10:
 - Create mhdp helper driver to replace macro functions, move all mhdp
   mailbox access functions and common functions into the helper
   driver.  Patch #1:drm: bridge: Cadence: Creat mhdp helper driver it
   is totaly different with v9.

Changes in v9:
 - Remove compatible string "cdns,mhdp8501" that had removed
   from dt-bindings file in v8.
 - Add Dmitry's R-b tag to patch #2
 - Add Krzysztof's R-b tag to patch #3

Changes in v8:
 - MHDP8501 HDMI/DP:
   - Correct DT node name to "display-bridge".
   - Remove "cdns,mhdp8501" from mhdp8501 dt-binding doc.

 - HDMI/DP PHY:
   - Introduced functions `wait_for_ack` and `wait_for_ack_clear` to handle
     waiting with acknowledgment bits set and cleared respectively.
   - Use FIELD_PRE() to set bitfields for both HDMI and DP PHY.

Changes in v7:
 - MHDP8501 HDMI/DP:
   - Combine HDMI and DP driver into one mhdp8501 driver.
     Use the connector type to load the corresponding functions.
   - Remove connector init functions.
   - Add <linux/hdmi.h> in phy_hdmi.h to reuse 'enum hdmi_colorspace'.

 - HDMI/DP PHY:
   - Lowercase hex values
   - Fix parameters indent issue on some functions
   - Replace 'udelay' with 'usleep_range'

Changes in v6:
 - HDMI/DP bridge driver
   - 8501 is the part number of Cadence MHDP on i.MX8MQ.
     Use MHDP8501 to name hdmi/dp drivers and files.
   - Add compatible "fsl,imx8mq-mhdp8501-dp" for i.MX8MQ DP driver
   - Add compatible "fsl,imx8mq-mhdp8501-hdmi" for i.MX8MQ HDMI driver
   - Combine HDMI and DP dt-bindings into one file cdns,mhdp8501.yaml
   - Fix HDMI scrambling is not enable issue when driver working in 4Kp60
     mode.
   - Add HDMI/DP PHY API mailbox protect.

 - HDMI/DP PHY driver:
   - Rename DP and HDMI PHY files and move to folder phy/freescale/
   - Remove properties num_lanes and link_rate from DP PHY driver.
   - Combine HDMI and DP dt-bindings into one file fsl,imx8mq-dp-hdmi-phy.yaml
   - Update compatible string to "fsl,imx8mq-dp-phy".
   - Update compatible string to "fsl,imx8mq-hdmi-phy".

Changes in v5:
 - Drop "clk" suffix in clock name.
 - Add output port property in the example of hdmi/dp.

Changes in v4:
 - dt-bindings:
   - Correct dt-bindings coding style and address review comments.
   - Add apb_clk description.
   - Add output port for HDMI/DP connector
 - PHY:
   - Alphabetically sorted in Kconfig and Makefile for DP and HDMI PHY
   - Remove unused registers define from HDMI and DP PHY drivers.
   - More description in phy_hdmi.h.
   - Add apb_clk to HDMI and DP phy driver.
 - HDMI/DP:
   - Use get_unaligned_le32() to replace hardcode type conversion
     in HDMI AVI infoframe data fill function.
   - Add mailbox mutex lock in HDMI/DP driver for phy functions
     to reslove race conditions between HDMI/DP and PHY drivers.
   - Add apb_clk to both HDMI and DP driver.
   - Rename some function names and add prefix with "cdns_hdmi/cdns_dp".
   - Remove bpc 12 and 16 optional that not supported.

Changes in v3:
 - Address comments for dt-bindings files.
   - Correct dts-bindings file names
     Rename phy-cadence-hdptx-dp.yaml to cdns,mhdp-imx8mq-dp.yaml
     Rename phy-cadence-hdptx-hdmi.yaml to cdns,mhdp-imx8mq-hdmi.yaml
   - Drop redundant words and descriptions.
   - Correct hdmi/dp node name.

Changes in v2:
 - Reuse Cadence mailbox access functions from mhdp8546 instead of
   rockchip DP.
 - Mailbox access functions be convert to marco functions
   that will be referenced by HDP-TX PHY(HDMI/DP) driver too.
 - Plain bridge instead of component driver.
 - Standalone Cadence HDP-TX PHY(HDMI/DP) driver.
 - Audio driver are removed from the patch set, it will be add in another
   patch set later.

---
Alexander Stein (2):
      arm64: dts: imx8mq: Add DCSS + HDMI/DP display pipeline
      arm64: dts: imx8mq: tqma8mq-mba8mx: Enable HDMI support

Sandor Yu (6):
      soc: cadence: Create helper functions for Cadence MHDP
      drm: bridge: cadence: Update mhdp8546 mailbox access functions
      dt-bindings: display: bridge: Add Cadence MHDP8501
      drm: bridge: Cadence: Add MHDP8501 DP/HDMI driver
      dt-bindings: phy: Add Freescale iMX8MQ DP and HDMI PHY
      phy: freescale: Add DisplayPort/HDMI Combo-PHY driver for i.MX8MQ

 .../bindings/display/bridge/cdns,mhdp8501.yaml     |  135 +++
 .../bindings/phy/fsl,imx8mq-hdptx-phy.yaml         |   80 ++
 .../boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts   |   28 +
 arch/arm64/boot/dts/freescale/imx8mq.dtsi          |   67 ++
 arch/arm64/boot/dts/freescale/mba8mx.dtsi          |   12 +
 drivers/gpu/drm/bridge/cadence/Kconfig             |   17 +
 drivers/gpu/drm/bridge/cadence/Makefile            |    2 +
 .../gpu/drm/bridge/cadence/cdns-mhdp8501-core.c    |  456 ++++++++
 .../gpu/drm/bridge/cadence/cdns-mhdp8501-core.h    |  382 ++++++
 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-dp.c  |  724 ++++++++++++
 .../gpu/drm/bridge/cadence/cdns-mhdp8501-hdmi.c    |  780 +++++++++++++
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-core.c    |  489 ++------
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-core.h    |   47 +-
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c    |  212 +---
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h    |   18 +-
 drivers/phy/freescale/Kconfig                      |   10 +
 drivers/phy/freescale/Makefile                     |    1 +
 drivers/phy/freescale/phy-fsl-imx8mq-hdptx.c       | 1233 ++++++++++++++++++++
 drivers/soc/Kconfig                                |    1 +
 drivers/soc/Makefile                               |    1 +
 drivers/soc/cadence/Kconfig                        |    9 +
 drivers/soc/cadence/Makefile                       |    3 +
 drivers/soc/cadence/cdns-mhdp-helper.c             |  611 ++++++++++
 include/soc/cadence/cdns-mhdp-helper.h             |  143 +++
 24 files changed, 4800 insertions(+), 661 deletions(-)
---
base-commit: fbddb4aaabc2b3b250552eb4ed8074b06acb4e0e
change-id: 20260406-dcss-hdmi-upstreaming-28998a88e911

Best regards,
-- 
Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply

* [PATCH v22 2/8] drm: bridge: cadence: Update mhdp8546 mailbox access functions
From: Laurentiu Palcu @ 2026-04-24 11:07 UTC (permalink / raw)
  To: Parshuram Thombare, Swapnil Jakhade, Dmitry Baryshkov,
	Nikhil Devshatwar, Jayesh Choudhary, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
	Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: dri-devel, devicetree, linux-kernel, linux-phy, imx,
	linux-arm-kernel, linux, Alexander Stein, Ying Liu
In-Reply-To: <20260424-dcss-hdmi-upstreaming-v22-0-30a28f89298d@oss.nxp.com>

From: Sandor Yu <Sandor.yu@nxp.com>

Basic mailbox access functions are removed, they are replaced by
mailbox helper functions:
- cdns_mhdp_mailbox_send()
- cdns_mhdp_mailbox_send_recv()
- cdns_mhdp_mailbox_send_recv_multi()
- cdns_mhdp_secure_mailbox_send()
- cdns_mhdp_secure_mailbox_send_recv()
- cdns_mhdp_secure_mailbox_send_recv_multi()

All MHDP commands that need to be passed through the mailbox
have been rewritten using these new helper functions.

Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
Co-developed-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
Signed-off-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>

---
To: Parshuram Thombare <pthombar@cadence.com>
To: Swapnil Jakhade <sjakhade@cadence.com>
To: Dmitry Baryshkov <lumag@kernel.org>
To: Nikhil Devshatwar <nikhil.nd@ti.com>
To: Jayesh Choudhary <j-choudhary@ti.com>
---
 drivers/gpu/drm/bridge/cadence/Kconfig             |   1 +
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-core.c    | 489 ++++-----------------
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-core.h    |  47 +-
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c    | 212 +--------
 .../gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h    |  18 +-
 5 files changed, 106 insertions(+), 661 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig
index f1d8a8a151d84..2ff261e18bf1c 100644
--- a/drivers/gpu/drm/bridge/cadence/Kconfig
+++ b/drivers/gpu/drm/bridge/cadence/Kconfig
@@ -29,6 +29,7 @@ config DRM_CDNS_MHDP8546
 	select DRM_DISPLAY_HELPER
 	select DRM_KMS_HELPER
 	select DRM_PANEL_BRIDGE
+	select CDNS_MHDP_HELPER
 	depends on OF
 	help
 	  Support Cadence DPI to DP bridge. This is an internal
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 064c6915c8960..435c006ab0c34 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -73,302 +73,18 @@ static void cdns_mhdp_bridge_hpd_disable(struct drm_bridge *bridge)
 	       mhdp->regs + CDNS_APB_INT_MASK);
 }
 
-static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp)
-{
-	int ret, empty;
-
-	WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
-
-	ret = readx_poll_timeout(readl, mhdp->regs + CDNS_MAILBOX_EMPTY,
-				 empty, !empty, MAILBOX_RETRY_US,
-				 MAILBOX_TIMEOUT_US);
-	if (ret < 0)
-		return ret;
-
-	return readl(mhdp->regs + CDNS_MAILBOX_RX_DATA) & 0xff;
-}
-
-static int cdns_mhdp_mailbox_write(struct cdns_mhdp_device *mhdp, u8 val)
-{
-	int ret, full;
-
-	WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
-
-	ret = readx_poll_timeout(readl, mhdp->regs + CDNS_MAILBOX_FULL,
-				 full, !full, MAILBOX_RETRY_US,
-				 MAILBOX_TIMEOUT_US);
-	if (ret < 0)
-		return ret;
-
-	writel(val, mhdp->regs + CDNS_MAILBOX_TX_DATA);
-
-	return 0;
-}
-
-static int cdns_mhdp_mailbox_recv_header(struct cdns_mhdp_device *mhdp,
-					 u8 module_id, u8 opcode,
-					 u16 req_size)
-{
-	u32 mbox_size, i;
-	u8 header[4];
-	int ret;
-
-	/* read the header of the message */
-	for (i = 0; i < sizeof(header); i++) {
-		ret = cdns_mhdp_mailbox_read(mhdp);
-		if (ret < 0)
-			return ret;
-
-		header[i] = ret;
-	}
-
-	mbox_size = get_unaligned_be16(header + 2);
-
-	if (opcode != header[0] || module_id != header[1] ||
-	    req_size != mbox_size) {
-		/*
-		 * If the message in mailbox is not what we want, we need to
-		 * clear the mailbox by reading its contents.
-		 */
-		for (i = 0; i < mbox_size; i++)
-			if (cdns_mhdp_mailbox_read(mhdp) < 0)
-				break;
-
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int cdns_mhdp_mailbox_recv_data(struct cdns_mhdp_device *mhdp,
-				       u8 *buff, u16 buff_size)
-{
-	u32 i;
-	int ret;
-
-	for (i = 0; i < buff_size; i++) {
-		ret = cdns_mhdp_mailbox_read(mhdp);
-		if (ret < 0)
-			return ret;
-
-		buff[i] = ret;
-	}
-
-	return 0;
-}
-
-static int cdns_mhdp_mailbox_send(struct cdns_mhdp_device *mhdp, u8 module_id,
-				  u8 opcode, u16 size, u8 *message)
-{
-	u8 header[4];
-	int ret, i;
-
-	header[0] = opcode;
-	header[1] = module_id;
-	put_unaligned_be16(size, header + 2);
-
-	for (i = 0; i < sizeof(header); i++) {
-		ret = cdns_mhdp_mailbox_write(mhdp, header[i]);
-		if (ret)
-			return ret;
-	}
-
-	for (i = 0; i < size; i++) {
-		ret = cdns_mhdp_mailbox_write(mhdp, message[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static
-int cdns_mhdp_reg_read(struct cdns_mhdp_device *mhdp, u32 addr, u32 *value)
-{
-	u8 msg[4], resp[8];
-	int ret;
-
-	put_unaligned_be32(addr, msg);
-
-	mutex_lock(&mhdp->mbox_mutex);
-
-	ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_GENERAL,
-				     GENERAL_REGISTER_READ,
-				     sizeof(msg), msg);
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_GENERAL,
-					    GENERAL_REGISTER_READ,
-					    sizeof(resp));
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, resp, sizeof(resp));
-	if (ret)
-		goto out;
-
-	/* Returned address value should be the same as requested */
-	if (memcmp(msg, resp, sizeof(msg))) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	*value = get_unaligned_be32(resp + 4);
-
-out:
-	mutex_unlock(&mhdp->mbox_mutex);
-	if (ret) {
-		dev_err(mhdp->dev, "Failed to read register\n");
-		*value = 0;
-	}
-
-	return ret;
-}
-
-static
-int cdns_mhdp_reg_write(struct cdns_mhdp_device *mhdp, u16 addr, u32 val)
-{
-	u8 msg[6];
-	int ret;
-
-	put_unaligned_be16(addr, msg);
-	put_unaligned_be32(val, msg + 2);
-
-	mutex_lock(&mhdp->mbox_mutex);
-
-	ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
-				     DPTX_WRITE_REGISTER, sizeof(msg), msg);
-
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
-}
-
-static
-int cdns_mhdp_reg_write_bit(struct cdns_mhdp_device *mhdp, u16 addr,
-			    u8 start_bit, u8 bits_no, u32 val)
-{
-	u8 field[8];
-	int ret;
-
-	put_unaligned_be16(addr, field);
-	field[2] = start_bit;
-	field[3] = bits_no;
-	put_unaligned_be32(val, field + 4);
-
-	mutex_lock(&mhdp->mbox_mutex);
-
-	ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
-				     DPTX_WRITE_FIELD, sizeof(field), field);
-
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
-}
-
-static
-int cdns_mhdp_dpcd_read(struct cdns_mhdp_device *mhdp,
-			u32 addr, u8 *data, u16 len)
-{
-	u8 msg[5], reg[5];
-	int ret;
-
-	put_unaligned_be16(len, msg);
-	put_unaligned_be24(addr, msg + 2);
-
-	mutex_lock(&mhdp->mbox_mutex);
-
-	ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
-				     DPTX_READ_DPCD, sizeof(msg), msg);
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX,
-					    DPTX_READ_DPCD,
-					    sizeof(reg) + len);
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg));
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, data, len);
-
-out:
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
-}
-
-static
-int cdns_mhdp_dpcd_write(struct cdns_mhdp_device *mhdp, u32 addr, u8 value)
-{
-	u8 msg[6], reg[5];
-	int ret;
-
-	put_unaligned_be16(1, msg);
-	put_unaligned_be24(addr, msg + 2);
-	msg[5] = value;
-
-	mutex_lock(&mhdp->mbox_mutex);
-
-	ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
-				     DPTX_WRITE_DPCD, sizeof(msg), msg);
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX,
-					    DPTX_WRITE_DPCD, sizeof(reg));
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg));
-	if (ret)
-		goto out;
-
-	if (addr != get_unaligned_be24(reg + 2))
-		ret = -EINVAL;
-
-out:
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	if (ret)
-		dev_err(mhdp->dev, "dpcd write failed: %d\n", ret);
-	return ret;
-}
-
 static
 int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable)
 {
-	u8 msg[5];
-	int ret, i;
-
-	msg[0] = GENERAL_MAIN_CONTROL;
-	msg[1] = MB_MODULE_ID_GENERAL;
-	msg[2] = 0;
-	msg[3] = 1;
-	msg[4] = enable ? FW_ACTIVE : FW_STANDBY;
-
-	mutex_lock(&mhdp->mbox_mutex);
-
-	for (i = 0; i < sizeof(msg); i++) {
-		ret = cdns_mhdp_mailbox_write(mhdp, msg[i]);
-		if (ret)
-			goto out;
-	}
-
-	/* read the firmware state */
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, msg, sizeof(msg));
-	if (ret)
-		goto out;
-
-	ret = 0;
+	u8 status;
+	int ret;
 
-out:
-	mutex_unlock(&mhdp->mbox_mutex);
+	status = enable ? FW_ACTIVE : FW_STANDBY;
 
+	ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_GENERAL,
+					  GENERAL_MAIN_CONTROL,
+					  sizeof(status), &status,
+					  sizeof(status), &status);
 	if (ret < 0)
 		dev_err(mhdp->dev, "set firmware active failed\n");
 	return ret;
@@ -380,34 +96,18 @@ int cdns_mhdp_get_hpd_status(struct cdns_mhdp_device *mhdp)
 	u8 status;
 	int ret;
 
-	mutex_lock(&mhdp->mbox_mutex);
-
-	ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
-				     DPTX_HPD_STATE, 0, NULL);
-	if (ret)
-		goto err_get_hpd;
-
-	ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX,
-					    DPTX_HPD_STATE,
-					    sizeof(status));
-	if (ret)
-		goto err_get_hpd;
+	ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_DP_TX,
+					  DPTX_HPD_STATE,
+					  0, NULL,
+					  sizeof(status), &status);
 
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, &status, sizeof(status));
 	if (ret)
-		goto err_get_hpd;
-
-	mutex_unlock(&mhdp->mbox_mutex);
+		return ret;
 
 	dev_dbg(mhdp->dev, "%s: HPD %splugged\n", __func__,
 		status ? "" : "un");
 
 	return status;
-
-err_get_hpd:
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
 }
 
 static
@@ -418,28 +118,17 @@ int cdns_mhdp_get_edid_block(void *data, u8 *edid,
 	u8 msg[2], reg[2], i;
 	int ret;
 
-	mutex_lock(&mhdp->mbox_mutex);
-
 	for (i = 0; i < 4; i++) {
 		msg[0] = block / 2;
 		msg[1] = block % 2;
 
-		ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
-					     DPTX_GET_EDID, sizeof(msg), msg);
-		if (ret)
-			continue;
-
-		ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX,
-						    DPTX_GET_EDID,
-						    sizeof(reg) + length);
-		if (ret)
-			continue;
-
-		ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg));
-		if (ret)
-			continue;
-
-		ret = cdns_mhdp_mailbox_recv_data(mhdp, edid, length);
+		ret = cdns_mhdp_mailbox_send_recv_multi(&mhdp->base,
+							MB_MODULE_ID_DP_TX,
+							DPTX_GET_EDID,
+							sizeof(msg), msg,
+							DPTX_GET_EDID,
+							sizeof(reg), reg,
+							length, edid);
 		if (ret)
 			continue;
 
@@ -447,8 +136,6 @@ int cdns_mhdp_get_edid_block(void *data, u8 *edid,
 			break;
 	}
 
-	mutex_unlock(&mhdp->mbox_mutex);
-
 	if (ret)
 		dev_err(mhdp->dev, "get block[%d] edid failed: %d\n",
 			block, ret);
@@ -462,21 +149,9 @@ int cdns_mhdp_read_hpd_event(struct cdns_mhdp_device *mhdp)
 	u8 event = 0;
 	int ret;
 
-	mutex_lock(&mhdp->mbox_mutex);
-
-	ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
-				     DPTX_READ_EVENT, 0, NULL);
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX,
-					    DPTX_READ_EVENT, sizeof(event));
-	if (ret < 0)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, &event, sizeof(event));
-out:
-	mutex_unlock(&mhdp->mbox_mutex);
+	ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_DP_TX,
+					  DPTX_READ_EVENT,
+					  0, NULL, sizeof(event), &event);
 
 	if (ret < 0)
 		return ret;
@@ -510,35 +185,23 @@ int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp, unsigned int nlanes,
 	put_unaligned_be16(udelay, payload + 1);
 	memcpy(payload + 3, lanes_data, nlanes);
 
-	mutex_lock(&mhdp->mbox_mutex);
-
-	ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX,
-				     DPTX_ADJUST_LT,
-				     sizeof(payload), payload);
-	if (ret)
-		goto out;
-
 	/* Yes, read the DPCD read command response */
-	ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX,
-					    DPTX_READ_DPCD,
-					    sizeof(hdr) + DP_LINK_STATUS_SIZE);
-	if (ret)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, hdr, sizeof(hdr));
+	ret = cdns_mhdp_mailbox_send_recv_multi(&mhdp->base,
+						MB_MODULE_ID_DP_TX,
+						DPTX_ADJUST_LT,
+						sizeof(payload), payload,
+						DPTX_READ_DPCD,
+						sizeof(hdr), hdr,
+						DP_LINK_STATUS_SIZE,
+						link_status);
 	if (ret)
 		goto out;
 
 	addr = get_unaligned_be24(hdr + 2);
 	if (addr != DP_LANE0_1_STATUS)
-		goto out;
-
-	ret = cdns_mhdp_mailbox_recv_data(mhdp, link_status,
-					  DP_LINK_STATUS_SIZE);
+		ret = -EINVAL;
 
 out:
-	mutex_unlock(&mhdp->mbox_mutex);
-
 	if (ret)
 		dev_err(mhdp->dev, "Failed to adjust Link Training.\n");
 
@@ -773,7 +436,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux,
 		unsigned int i;
 
 		for (i = 0; i < msg->size; ++i) {
-			ret = cdns_mhdp_dpcd_write(mhdp,
+			ret = cdns_mhdp_dpcd_write(&mhdp->base,
 						   msg->address + i, buf[i]);
 			if (!ret)
 				continue;
@@ -785,7 +448,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux,
 			return ret;
 		}
 	} else {
-		ret = cdns_mhdp_dpcd_read(mhdp, msg->address,
+		ret = cdns_mhdp_dpcd_read(&mhdp->base, msg->address,
 					  msg->buffer, msg->size);
 		if (ret) {
 			dev_dbg(mhdp->dev,
@@ -813,12 +476,12 @@ static int cdns_mhdp_link_training_init(struct cdns_mhdp_device *mhdp)
 	if (!mhdp->host.scrambler)
 		reg32 |= CDNS_PHY_SCRAMBLER_BYPASS;
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, reg32);
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_ENHNCD,
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_ENHNCD,
 			    mhdp->sink.enhanced & mhdp->host.enhanced);
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_LANE_EN,
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_LANE_EN,
 			    CDNS_DP_LANE_EN_LANES(mhdp->link.num_lanes));
 
 	cdns_mhdp_link_configure(&mhdp->aux, &mhdp->link);
@@ -839,7 +502,7 @@ static int cdns_mhdp_link_training_init(struct cdns_mhdp_device *mhdp)
 		return ret;
 	}
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG,
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG,
 			    CDNS_PHY_COMMON_CONFIG |
 			    CDNS_PHY_TRAINING_EN |
 			    CDNS_PHY_TRAINING_TYPE(1) |
@@ -984,7 +647,7 @@ static bool cdns_mhdp_link_training_channel_eq(struct cdns_mhdp_device *mhdp,
 		CDNS_PHY_TRAINING_TYPE(eq_tps);
 	if (eq_tps != 4)
 		reg32 |= CDNS_PHY_SCRAMBLER_BYPASS;
-	cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, reg32);
 
 	drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET,
 			   (eq_tps != 4) ? eq_tps | DP_LINK_SCRAMBLING_DISABLE :
@@ -1248,7 +911,7 @@ static int cdns_mhdp_link_training(struct cdns_mhdp_device *mhdp,
 			   mhdp->host.scrambler ? 0 :
 			   DP_LINK_SCRAMBLING_DISABLE);
 
-	ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &reg32);
+	ret = cdns_mhdp_reg_read(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, &reg32);
 	if (ret < 0) {
 		dev_err(mhdp->dev,
 			"Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n",
@@ -1259,13 +922,13 @@ static int cdns_mhdp_link_training(struct cdns_mhdp_device *mhdp,
 	reg32 |= CDNS_DP_NUM_LANES(mhdp->link.num_lanes);
 	reg32 |= CDNS_DP_WR_FAILING_EDGE_VSYNC;
 	reg32 |= CDNS_DP_FRAMER_EN;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, reg32);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, reg32);
 
 	/* Reset PHY config */
 	reg32 = CDNS_PHY_COMMON_CONFIG | CDNS_PHY_TRAINING_TYPE(1);
 	if (!mhdp->host.scrambler)
 		reg32 |= CDNS_PHY_SCRAMBLER_BYPASS;
-	cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, reg32);
 
 	return 0;
 err:
@@ -1273,7 +936,7 @@ static int cdns_mhdp_link_training(struct cdns_mhdp_device *mhdp,
 	reg32 = CDNS_PHY_COMMON_CONFIG | CDNS_PHY_TRAINING_TYPE(1);
 	if (!mhdp->host.scrambler)
 		reg32 |= CDNS_PHY_SCRAMBLER_BYPASS;
-	cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, reg32);
 
 	drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET,
 			   DP_TRAINING_PATTERN_DISABLE);
@@ -1387,7 +1050,7 @@ static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp)
 	mhdp->link.num_lanes = cdns_mhdp_max_num_lanes(mhdp);
 
 	/* Disable framer for link training */
-	err = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
+	err = cdns_mhdp_reg_read(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
 	if (err < 0) {
 		dev_err(mhdp->dev,
 			"Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n",
@@ -1396,7 +1059,7 @@ static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp)
 	}
 
 	resp &= ~CDNS_DP_FRAMER_EN;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp);
 
 	/* Spread AMP if required, enable 8b/10b coding */
 	amp[0] = cdns_mhdp_get_ssc_supported(mhdp) ? DP_SPREAD_AMP_0_5 : 0;
@@ -1605,7 +1268,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 		bnd_hsync2vsync |= CDNS_IP_DET_INTERLACE_FORMAT;
 
-	cdns_mhdp_reg_write(mhdp, CDNS_BND_HSYNC2VSYNC(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_BND_HSYNC2VSYNC(stream_id),
 			    bnd_hsync2vsync);
 
 	hsync2vsync_pol_ctrl = 0;
@@ -1613,10 +1276,10 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
 		hsync2vsync_pol_ctrl |= CDNS_H2V_HSYNC_POL_ACTIVE_LOW;
 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 		hsync2vsync_pol_ctrl |= CDNS_H2V_VSYNC_POL_ACTIVE_LOW;
-	cdns_mhdp_reg_write(mhdp, CDNS_HSYNC2VSYNC_POL_CTRL(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_HSYNC2VSYNC_POL_CTRL(stream_id),
 			    hsync2vsync_pol_ctrl);
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_PXL_REPR(stream_id), pxl_repr);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_PXL_REPR(stream_id), pxl_repr);
 
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 		dp_framer_sp |= CDNS_DP_FRAMER_INTERLACE;
@@ -1624,19 +1287,19 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
 		dp_framer_sp |= CDNS_DP_FRAMER_HSYNC_POL_LOW;
 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 		dp_framer_sp |= CDNS_DP_FRAMER_VSYNC_POL_LOW;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_SP(stream_id), dp_framer_sp);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_SP(stream_id), dp_framer_sp);
 
 	front_porch = mode->crtc_hsync_start - mode->crtc_hdisplay;
 	back_porch = mode->crtc_htotal - mode->crtc_hsync_end;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_FRONT_BACK_PORCH(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRONT_BACK_PORCH(stream_id),
 			    CDNS_DP_FRONT_PORCH(front_porch) |
 			    CDNS_DP_BACK_PORCH(back_porch));
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_BYTE_COUNT(stream_id),
 			    mode->crtc_hdisplay * bpp / 8);
 
 	msa_h0 = mode->crtc_htotal - mode->crtc_hsync_start;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_0(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_HORIZONTAL_0(stream_id),
 			    CDNS_DP_MSAH0_H_TOTAL(mode->crtc_htotal) |
 			    CDNS_DP_MSAH0_HSYNC_START(msa_h0));
 
@@ -1645,11 +1308,11 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
 			   CDNS_DP_MSAH1_HDISP_WIDTH(mode->crtc_hdisplay);
 	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 		msa_horizontal_1 |= CDNS_DP_MSAH1_HSYNC_POL_LOW;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_1(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_HORIZONTAL_1(stream_id),
 			    msa_horizontal_1);
 
 	msa_v0 = mode->crtc_vtotal - mode->crtc_vsync_start;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_VERTICAL_0(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_VERTICAL_0(stream_id),
 			    CDNS_DP_MSAV0_V_TOTAL(mode->crtc_vtotal) |
 			    CDNS_DP_MSAV0_VSYNC_START(msa_v0));
 
@@ -1658,7 +1321,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
 			 CDNS_DP_MSAV1_VDISP_WIDTH(mode->crtc_vdisplay);
 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 		msa_vertical_1 |= CDNS_DP_MSAV1_VSYNC_POL_LOW;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_VERTICAL_1(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_VERTICAL_1(stream_id),
 			    msa_vertical_1);
 
 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
@@ -1670,14 +1333,14 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
 	if (pxlfmt == DRM_OUTPUT_COLOR_FORMAT_YCBCR420)
 		misc1 = CDNS_DP_TEST_VSC_SDP;
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_MISC(stream_id),
 			    misc0 | (misc1 << 8));
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_HORIZONTAL(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_HORIZONTAL(stream_id),
 			    CDNS_DP_H_HSYNC_WIDTH(hsync) |
 			    CDNS_DP_H_H_TOTAL(mode->crtc_hdisplay));
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_VERTICAL_0(stream_id),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_VERTICAL_0(stream_id),
 			    CDNS_DP_V0_VHEIGHT(mode->crtc_vdisplay) |
 			    CDNS_DP_V0_VSTART(msa_v0));
 
@@ -1686,13 +1349,13 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
 	    mode->crtc_vtotal % 2 == 0)
 		dp_vertical_1 |= CDNS_DP_V1_VTOTAL_EVEN;
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_VERTICAL_1(stream_id), dp_vertical_1);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_VERTICAL_1(stream_id), dp_vertical_1);
 
-	cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_VB_ID(stream_id), 2, 1,
-				(mode->flags & DRM_MODE_FLAG_INTERLACE) ?
-				CDNS_DP_VB_ID_INTERLACED : 0);
+	cdns_mhdp_dp_reg_write_bit(&mhdp->base, CDNS_DP_VB_ID(stream_id), 2, 1,
+				   (mode->flags & DRM_MODE_FLAG_INTERLACE) ?
+				   CDNS_DP_VB_ID_INTERLACED : 0);
 
-	ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer);
+	ret = cdns_mhdp_reg_read(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer);
 	if (ret < 0) {
 		dev_err(mhdp->dev,
 			"Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n",
@@ -1701,7 +1364,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
 	}
 	framer |= CDNS_DP_FRAMER_EN;
 	framer &= ~CDNS_DP_NO_VIDEO_MODE;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer);
 }
 
 static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
@@ -1734,15 +1397,15 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
 
 	mhdp->stream_id = 0;
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_TU,
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_TU,
 			    CDNS_DP_FRAMER_TU_VS(vs) |
 			    CDNS_DP_FRAMER_TU_SIZE(tu_size) |
 			    CDNS_DP_FRAMER_TU_CNT_RST_EN);
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_LINE_THRESH(0),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_LINE_THRESH(0),
 			    line_thresh & GENMASK(5, 0));
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_STREAM_CONFIG_2(0),
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_STREAM_CONFIG_2(0),
 			    CDNS_DP_SC2_TU_VS_DIFF((tu_size - vs > 3) ?
 						   0 : tu_size - vs));
 
@@ -1784,13 +1447,13 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
 		mhdp->info->ops->enable(mhdp);
 
 	/* Enable VIF clock for stream 0 */
-	ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp);
+	ret = cdns_mhdp_reg_read(&mhdp->base, CDNS_DPTX_CAR, &resp);
 	if (ret < 0) {
 		dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret);
 		goto out;
 	}
 
-	cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_CAR,
 			    resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
 
 	if (mhdp->hdcp_supported &&
@@ -1854,16 +1517,16 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
 		cdns_mhdp_hdcp_disable(mhdp);
 
 	mhdp->bridge_enabled = false;
-	cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
+	cdns_mhdp_reg_read(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
 	resp &= ~CDNS_DP_FRAMER_EN;
 	resp |= CDNS_DP_NO_VIDEO_MODE;
-	cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp);
 
 	cdns_mhdp_link_down(mhdp);
 
 	/* Disable VIF clock for stream 0 */
-	cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp);
-	cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
+	cdns_mhdp_reg_read(&mhdp->base, CDNS_DPTX_CAR, &resp);
+	cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_CAR,
 			    resp & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN));
 
 	if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable)
@@ -2280,7 +1943,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
 
 	mhdp->clk = clk;
 	mhdp->dev = dev;
-	mutex_init(&mhdp->mbox_mutex);
 	mutex_init(&mhdp->link_mutex);
 	spin_lock_init(&mhdp->start_lock);
 
@@ -2311,6 +1973,12 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mhdp);
 
+	/* init base struct for access mailbox  */
+	mhdp->base.dev = mhdp->dev;
+	mhdp->base.regs = mhdp->regs;
+	mhdp->base.sapb_regs = mhdp->sapb_regs;
+	mutex_init(&mhdp->base.mailbox_mutex);
+
 	mhdp->info = of_device_get_match_data(dev);
 
 	pm_runtime_enable(dev);
@@ -2435,6 +2103,7 @@ static void cdns_mhdp_remove(struct platform_device *pdev)
 
 	cancel_work_sync(&mhdp->modeset_retry_work);
 	flush_work(&mhdp->hpd_work);
+	mutex_destroy(&mhdp->base.mailbox_mutex);
 	/* Ignoring mhdp->hdcp.check_work and mhdp->hdcp.prop_work here. */
 }
 
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
index b53335b0d22c3..ae7b85e56e986 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
@@ -18,6 +18,7 @@
 #include <drm/display/drm_dp_helper.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_connector.h>
+#include <soc/cadence/cdns-mhdp-helper.h>
 
 struct clk;
 struct device;
@@ -27,10 +28,6 @@ struct phy;
 #define CDNS_APB_CTRL				0x00000
 #define CDNS_CPU_STALL				BIT(3)
 
-#define CDNS_MAILBOX_FULL			0x00008
-#define CDNS_MAILBOX_EMPTY			0x0000c
-#define CDNS_MAILBOX_TX_DATA			0x00010
-#define CDNS_MAILBOX_RX_DATA			0x00014
 #define CDNS_KEEP_ALIVE				0x00018
 #define CDNS_KEEP_ALIVE_MASK			GENMASK(7, 0)
 
@@ -198,45 +195,10 @@ struct phy;
 #define CDNS_DP_BYTE_COUNT(s)			(CDNS_DPTX_STREAM(s) + 0x7c)
 #define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT	16
 
-/* mailbox */
-#define MAILBOX_RETRY_US			1000
-#define MAILBOX_TIMEOUT_US			2000000
-
-#define MB_OPCODE_ID				0
-#define MB_MODULE_ID				1
-#define MB_SIZE_MSB_ID				2
-#define MB_SIZE_LSB_ID				3
-#define MB_DATA_ID				4
-
-#define MB_MODULE_ID_DP_TX			0x01
-#define MB_MODULE_ID_HDCP_TX			0x07
-#define MB_MODULE_ID_HDCP_RX			0x08
-#define MB_MODULE_ID_HDCP_GENERAL		0x09
-#define MB_MODULE_ID_GENERAL			0x0a
-
-/* firmware and opcodes */
+/* firmware */
 #define FW_NAME					"cadence/mhdp8546.bin"
 #define CDNS_MHDP_IMEM				0x10000
 
-#define GENERAL_MAIN_CONTROL			0x01
-#define GENERAL_TEST_ECHO			0x02
-#define GENERAL_BUS_SETTINGS			0x03
-#define GENERAL_TEST_ACCESS			0x04
-#define GENERAL_REGISTER_READ			0x07
-
-#define DPTX_SET_POWER_MNG			0x00
-#define DPTX_GET_EDID				0x02
-#define DPTX_READ_DPCD				0x03
-#define DPTX_WRITE_DPCD				0x04
-#define DPTX_ENABLE_EVENT			0x05
-#define DPTX_WRITE_REGISTER			0x06
-#define DPTX_READ_REGISTER			0x07
-#define DPTX_WRITE_FIELD			0x08
-#define DPTX_READ_EVENT				0x0a
-#define DPTX_GET_LAST_AUX_STAUS			0x0e
-#define DPTX_HPD_STATE				0x11
-#define DPTX_ADJUST_LT				0x12
-
 #define FW_STANDBY				0
 #define FW_ACTIVE				1
 
@@ -352,6 +314,8 @@ struct cdns_mhdp_hdcp {
 };
 
 struct cdns_mhdp_device {
+	struct cdns_mhdp_base base;
+
 	void __iomem *regs;
 	void __iomem *sapb_regs;
 	void __iomem *j721e_regs;
@@ -362,9 +326,6 @@ struct cdns_mhdp_device {
 
 	const struct cdns_mhdp_platform_info *info;
 
-	/* This is to protect mailbox communications with the firmware */
-	struct mutex mbox_mutex;
-
 	/*
 	 * "link_mutex" protects the access to all the link parameters
 	 * including the link training process. Link training will be
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
index 5cd0b873e16f9..1b5c90af63dee 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
@@ -15,144 +15,20 @@
 
 #include "cdns-mhdp8546-hdcp.h"
 
-static int cdns_mhdp_secure_mailbox_read(struct cdns_mhdp_device *mhdp)
-{
-	int ret, empty;
-
-	WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
-
-	ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_EMPTY,
-				 empty, !empty, MAILBOX_RETRY_US,
-				 MAILBOX_TIMEOUT_US);
-	if (ret < 0)
-		return ret;
-
-	return readl(mhdp->sapb_regs + CDNS_MAILBOX_RX_DATA) & 0xff;
-}
-
-static int cdns_mhdp_secure_mailbox_write(struct cdns_mhdp_device *mhdp,
-					  u8 val)
-{
-	int ret, full;
-
-	WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex));
-
-	ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_FULL,
-				 full, !full, MAILBOX_RETRY_US,
-				 MAILBOX_TIMEOUT_US);
-	if (ret < 0)
-		return ret;
-
-	writel(val, mhdp->sapb_regs + CDNS_MAILBOX_TX_DATA);
-
-	return 0;
-}
-
-static int cdns_mhdp_secure_mailbox_recv_header(struct cdns_mhdp_device *mhdp,
-						u8 module_id,
-						u8 opcode,
-						u16 req_size)
-{
-	u32 mbox_size, i;
-	u8 header[4];
-	int ret;
-
-	/* read the header of the message */
-	for (i = 0; i < sizeof(header); i++) {
-		ret = cdns_mhdp_secure_mailbox_read(mhdp);
-		if (ret < 0)
-			return ret;
-
-		header[i] = ret;
-	}
-
-	mbox_size = get_unaligned_be16(header + 2);
-
-	if (opcode != header[0] || module_id != header[1] ||
-	    (opcode != HDCP_TRAN_IS_REC_ID_VALID && req_size != mbox_size)) {
-		for (i = 0; i < mbox_size; i++)
-			if (cdns_mhdp_secure_mailbox_read(mhdp) < 0)
-				break;
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int cdns_mhdp_secure_mailbox_recv_data(struct cdns_mhdp_device *mhdp,
-					      u8 *buff, u16 buff_size)
-{
-	int ret;
-	u32 i;
-
-	for (i = 0; i < buff_size; i++) {
-		ret = cdns_mhdp_secure_mailbox_read(mhdp);
-		if (ret < 0)
-			return ret;
-
-		buff[i] = ret;
-	}
-
-	return 0;
-}
-
-static int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_device *mhdp,
-					 u8 module_id,
-					 u8 opcode,
-					 u16 size,
-					 u8 *message)
-{
-	u8 header[4];
-	int ret;
-	u32 i;
-
-	header[0] = opcode;
-	header[1] = module_id;
-	put_unaligned_be16(size, header + 2);
-
-	for (i = 0; i < sizeof(header); i++) {
-		ret = cdns_mhdp_secure_mailbox_write(mhdp, header[i]);
-		if (ret)
-			return ret;
-	}
-
-	for (i = 0; i < size; i++) {
-		ret = cdns_mhdp_secure_mailbox_write(mhdp, message[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
 static int cdns_mhdp_hdcp_get_status(struct cdns_mhdp_device *mhdp,
 				     u16 *hdcp_port_status)
 {
 	u8 hdcp_status[HDCP_STATUS_SIZE];
 	int ret;
 
-	mutex_lock(&mhdp->mbox_mutex);
-	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
-					    HDCP_TRAN_STATUS_CHANGE, 0, NULL);
-	if (ret)
-		goto err_get_hdcp_status;
-
-	ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
-						   HDCP_TRAN_STATUS_CHANGE,
-						   sizeof(hdcp_status));
-	if (ret)
-		goto err_get_hdcp_status;
-
-	ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_status,
-						 sizeof(hdcp_status));
+	ret = cdns_mhdp_secure_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_HDCP_TX,
+						 HDCP_TRAN_STATUS_CHANGE, 0, NULL,
+						 sizeof(hdcp_status), hdcp_status);
 	if (ret)
-		goto err_get_hdcp_status;
+		return ret;
 
 	*hdcp_port_status = ((u16)(hdcp_status[0] << 8) | hdcp_status[1]);
 
-err_get_hdcp_status:
-	mutex_unlock(&mhdp->mbox_mutex);
-
 	return ret;
 }
 
@@ -170,98 +46,52 @@ static u8 cdns_mhdp_hdcp_handle_status(struct cdns_mhdp_device *mhdp,
 static int cdns_mhdp_hdcp_rx_id_valid_response(struct cdns_mhdp_device *mhdp,
 					       u8 valid)
 {
-	int ret;
-
-	mutex_lock(&mhdp->mbox_mutex);
-	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
+	return cdns_mhdp_secure_mailbox_send(&mhdp->base, MB_MODULE_ID_HDCP_TX,
 					    HDCP_TRAN_RESPOND_RECEIVER_ID_VALID,
 					    1, &valid);
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
 }
 
 static int cdns_mhdp_hdcp_rx_id_valid(struct cdns_mhdp_device *mhdp,
 				      u8 *recv_num, u8 *hdcp_rx_id)
 {
 	u8 rec_id_hdr[2];
-	u8 status;
 	int ret;
 
-	mutex_lock(&mhdp->mbox_mutex);
-	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
-					    HDCP_TRAN_IS_REC_ID_VALID, 0, NULL);
-	if (ret)
-		goto err_rx_id_valid;
-
-	ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
-						   HDCP_TRAN_IS_REC_ID_VALID,
-						   sizeof(status));
-	if (ret)
-		goto err_rx_id_valid;
-
-	ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, rec_id_hdr, 2);
+	ret = cdns_mhdp_secure_mailbox_send_recv_multi(&mhdp->base,
+						       MB_MODULE_ID_HDCP_TX,
+						       HDCP_TRAN_IS_REC_ID_VALID,
+						       0, NULL,
+						       HDCP_TRAN_IS_REC_ID_VALID,
+						       sizeof(rec_id_hdr), rec_id_hdr,
+						       0, hdcp_rx_id);
 	if (ret)
-		goto err_rx_id_valid;
+		return ret;
 
 	*recv_num = rec_id_hdr[0];
 
-	ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_rx_id, 5 * *recv_num);
-
-err_rx_id_valid:
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
+	return 0;
 }
 
 static int cdns_mhdp_hdcp_km_stored_resp(struct cdns_mhdp_device *mhdp,
 					 u32 size, u8 *km)
 {
-	int ret;
-
-	mutex_lock(&mhdp->mbox_mutex);
-	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
-					    HDCP2X_TX_RESPOND_KM, size, km);
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
+	return cdns_mhdp_secure_mailbox_send(&mhdp->base, MB_MODULE_ID_HDCP_TX,
+					     HDCP2X_TX_RESPOND_KM, size, km);
 }
 
 static int cdns_mhdp_hdcp_tx_is_km_stored(struct cdns_mhdp_device *mhdp,
 					  u8 *resp, u32 size)
 {
-	int ret;
-
-	mutex_lock(&mhdp->mbox_mutex);
-	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
-					    HDCP2X_TX_IS_KM_STORED, 0, NULL);
-	if (ret)
-		goto err_is_km_stored;
-
-	ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX,
-						   HDCP2X_TX_IS_KM_STORED,
-						   size);
-	if (ret)
-		goto err_is_km_stored;
-
-	ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, resp, size);
-err_is_km_stored:
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
+	return cdns_mhdp_secure_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_HDCP_TX,
+						 HDCP2X_TX_IS_KM_STORED,
+						 0, NULL, size, resp);
 }
 
 static int cdns_mhdp_hdcp_tx_config(struct cdns_mhdp_device *mhdp,
 				    u8 hdcp_cfg)
 {
-	int ret;
-
-	mutex_lock(&mhdp->mbox_mutex);
-	ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX,
-					    HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg);
-	mutex_unlock(&mhdp->mbox_mutex);
-
-	return ret;
+	return cdns_mhdp_secure_mailbox_send(&mhdp->base, MB_MODULE_ID_HDCP_TX,
+					     HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg);
 }
 
 static int cdns_mhdp_hdcp_set_config(struct cdns_mhdp_device *mhdp,
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h
index 3b6ec9c3a8d8b..1e68530e72229 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h
@@ -9,6 +9,7 @@
 #ifndef CDNS_MHDP8546_HDCP_H
 #define CDNS_MHDP8546_HDCP_H
 
+#include <soc/cadence/cdns-mhdp-helper.h>
 #include "cdns-mhdp8546-core.h"
 
 #define HDCP_MAX_RECEIVERS 32
@@ -32,23 +33,6 @@ enum {
 	HDCP_SET_SEED,
 };
 
-enum {
-	HDCP_TRAN_CONFIGURATION,
-	HDCP2X_TX_SET_PUBLIC_KEY_PARAMS,
-	HDCP2X_TX_SET_DEBUG_RANDOM_NUMBERS,
-	HDCP2X_TX_RESPOND_KM,
-	HDCP1_TX_SEND_KEYS,
-	HDCP1_TX_SEND_RANDOM_AN,
-	HDCP_TRAN_STATUS_CHANGE,
-	HDCP2X_TX_IS_KM_STORED,
-	HDCP2X_TX_STORE_KM,
-	HDCP_TRAN_IS_REC_ID_VALID,
-	HDCP_TRAN_RESPOND_RECEIVER_ID_VALID,
-	HDCP_TRAN_TEST_KEYS,
-	HDCP2X_TX_SET_KM_KEY_PARAMS,
-	HDCP_NUM_OF_SUPPORTED_MESSAGES
-};
-
 enum {
 	HDCP_CONTENT_TYPE_0,
 	HDCP_CONTENT_TYPE_1,

-- 
2.51.0

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related

* [PATCH v22 3/8] dt-bindings: display: bridge: Add Cadence MHDP8501
From: Laurentiu Palcu @ 2026-04-24 11:07 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: dri-devel, devicetree, linux-kernel, linux-phy, imx,
	linux-arm-kernel, linux, Alexander Stein, Ying Liu
In-Reply-To: <20260424-dcss-hdmi-upstreaming-v22-0-30a28f89298d@oss.nxp.com>

From: Sandor Yu <Sandor.yu@nxp.com>

Add bindings for Cadence MHDP8501 DisplayPort/HDMI bridge.

Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
Signed-off-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
---
 .../bindings/display/bridge/cdns,mhdp8501.yaml     | 135 +++++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8501.yaml b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8501.yaml
new file mode 100644
index 0000000000000..de549471c6859
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8501.yaml
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/cdns,mhdp8501.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cadence MHDP8501 DP/HDMI bridge
+
+maintainers:
+  - Sandor Yu <Sandor.yu@nxp.com>
+
+description:
+  Cadence MHDP8501 DisplayPort/HDMI interface.
+
+properties:
+  compatible:
+    enum:
+      - fsl,imx8mq-mhdp8501
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: MHDP8501 DP/HDMI APB clock.
+
+  phys:
+    maxItems: 1
+    description:
+      phandle to the DP/HDMI PHY
+
+  interrupts:
+    items:
+      - description: Hotplug cable plugin.
+      - description: Hotplug cable plugout.
+
+  interrupt-names:
+    items:
+      - const: plug_in
+      - const: plug_out
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/properties/port
+        description:
+          Input port from display controller output.
+
+      port@1:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description:
+          Output port to DisplayPort or HDMI connector.
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              data-lanes:
+                description: Lane reordering for HDMI or DisplayPort interface.
+                minItems: 4
+                maxItems: 4
+
+            required:
+              - data-lanes
+
+    required:
+      - port@0
+      - port@1
+
+  phy:
+    description:
+      Child node describing the Cadence HDP-TX DP/HDMI PHY, which shares
+      the same MMIO region as the bridge.
+    $ref: /schemas/phy/fsl,imx8mq-hdptx-phy.yaml#
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - interrupts
+  - interrupt-names
+  - phys
+  - ports
+  - phy
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/imx8mq-clock.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    mhdp: display-bridge@32c00000 {
+        compatible = "fsl,imx8mq-mhdp8501";
+        reg = <0x32c00000 0x100000>;
+        interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+                     <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+        interrupt-names = "plug_in", "plug_out";
+        clocks = <&clk IMX8MQ_CLK_DISP_APB_ROOT>;
+        phys = <&mhdp_phy>;
+
+        ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port@0 {
+                reg = <0>;
+
+                mhdp_in: endpoint {
+                    remote-endpoint = <&dcss_out>;
+                };
+            };
+
+            port@1 {
+                reg = <1>;
+
+                mhdp_out: endpoint {
+                    remote-endpoint = <&dp_connector>;
+                    data-lanes = <2 1 0 3>;
+                };
+            };
+        };
+
+        mhdp_phy: phy {
+            compatible = "fsl,imx8mq-hdptx-phy";
+            #phy-cells = <0>;
+            clocks = <&hdmi_phy_27m>, <&clk IMX8MQ_CLK_DISP_APB_ROOT>;
+            clock-names = "ref", "apb";
+        };
+    };

-- 
2.51.0

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox