> Subject: Re: [PATCH 03/25] drm/i915/ltphy: Phy lane reset for LT Phy
> 
> On 15-10-2025 09:37, Suraj Kandpal wrote:
> > Define function to bring phy lane out of reset for LT Phy and the
> > corresponding pre-requisite steps before we follow the steps for Phy
> > lane reset. Also create a skeleton of LT PHY PLL enable sequence
> > function in which we can place this function
> >
> > Bspec: 77449, 74749, 74499, 74495, 68960
> > Signed-off-by: Suraj Kandpal <[email protected]>
> > ---
> >   drivers/gpu/drm/i915/Makefile                 |   1 +
> >   drivers/gpu/drm/i915/display/intel_cx0_phy.c  |   2 +-
> >   drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   2 +
> >   .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   4 +
> >   drivers/gpu/drm/i915/display/intel_lt_phy.c   | 159 ++++++++++++++++++
> >   drivers/gpu/drm/i915/display/intel_lt_phy.h   |  17 ++
> >   .../gpu/drm/i915/display/intel_lt_phy_regs.h  |  17 ++
> >   drivers/gpu/drm/xe/Makefile                   |   1 +
> >   8 files changed, 202 insertions(+), 1 deletion(-)
> >   create mode 100644 drivers/gpu/drm/i915/display/intel_lt_phy.c
> >   create mode 100644 drivers/gpu/drm/i915/display/intel_lt_phy.h
> >
> > diff --git a/drivers/gpu/drm/i915/Makefile
> > b/drivers/gpu/drm/i915/Makefile index 6d7800e25e55..33836829d2c0
> > 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -352,6 +352,7 @@ i915-y += \
> >     display/intel_gmbus.o \
> >     display/intel_hdmi.o \
> >     display/intel_lspcon.o \
> > +   display/intel_lt_phy.o \
> >     display/intel_lvds.o \
> >     display/intel_panel.o \
> >     display/intel_pfit.o \
> > diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > index 6d9ebc8717ba..db2b05521c62 100644
> > --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> > @@ -2843,7 +2843,7 @@ static void
> intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder,
> >                      phy_name(phy),
> XELPDP_PORT_RESET_START_TIMEOUT_US);
> >   }
> >
> > -static void intel_cx0_setup_powerdown(struct intel_encoder *encoder)
> > +void intel_cx0_setup_powerdown(struct intel_encoder *encoder)
> >   {
> >     struct intel_display *display = to_intel_display(encoder);
> >     enum port port = encoder->port;
> > diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
> > b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
> > index c5a7b529955b..c92026fe7b8f 100644
> > --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
> > +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
> > @@ -41,6 +41,8 @@ bool intel_cx0pll_compare_hw_state(const struct
> intel_cx0pll_state *a,
> >                                const struct intel_cx0pll_state *b);
> >   void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
> >                                  const struct intel_crtc_state *crtc_state);
> > +int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int
> > +clock); void intel_cx0_setup_powerdown(struct intel_encoder
> > +*encoder);
> >   int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
> >   void intel_cx0_pll_power_save_wa(struct intel_display *display);
> >   void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder, diff
> > --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
> > b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
> > index 18b91c23d547..114f6b2113db 100644
> > --- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
> > +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
> > @@ -104,6 +104,8 @@
> >   #define   XELPDP_PORT_BUF_PORT_DATA_20BIT
>       REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 1)
> >   #define   XELPDP_PORT_BUF_PORT_DATA_40BIT
>       REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 2)
> >   #define   XELPDP_PORT_REVERSAL                            REG_BIT(16)
> > +#define   XE3PLPDP_PHY_MODE_MASK
>       REG_GENMASK(15, 12)
> > +#define   XE3PLPDP_PHY_MODE_DP
>       REG_FIELD_PREP(XE3PLPDP_PHY_MODE_MASK, 0x3)
> >   #define   XELPDP_PORT_BUF_IO_SELECT_TBT
>       REG_BIT(11)
> >   #define   XELPDP_PORT_BUF_PHY_IDLE                        REG_BIT(7)
> >   #define   XELPDP_TC_PHY_OWNERSHIP                 REG_BIT(6)
> > @@ -124,6 +126,7 @@
> >      _XELPDP_PORT_BUF_CTL2(port))
> >   #define   XELPDP_LANE_PIPE_RESET(lane)                    _PICK(lane,
> REG_BIT(31), REG_BIT(30))
> >   #define   XELPDP_LANE_PHY_CURRENT_STATUS(lane)
>       _PICK(lane, REG_BIT(29), REG_BIT(28))
> > +#define   XE3PLPDP_LANE_PHY_PULSE_STATUS(lane)
>       _PICK(lane, REG_BIT(27), REG_BIT(26))
> >   #define   XELPDP_LANE_POWERDOWN_UPDATE(lane)
>       _PICK(lane, REG_BIT(25), REG_BIT(24))
> >   #define   _XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK
>       REG_GENMASK(23, 20)
> >   #define   _XELPDP_LANE0_POWERDOWN_NEW_STATE(val)
>       REG_FIELD_PREP(_XELPDP_LANE0_POWERDOWN_NEW_STATE_MA
> SK, val)
> > @@ -151,6 +154,7 @@
> >   #define   XELPDP_POWER_STATE_ACTIVE(val)
>       REG_FIELD_PREP(XELPDP_POWER_STATE_ACTIVE_MASK, val)
> >   #define   XELPDP_P0_STATE_ACTIVE                  0x0
> >   #define   XELPDP_P2_STATE_READY                           0x2
> > +#define   XE3PLPD_P4_STATE_DISABLE                 0x4
> >   #define   XELPDP_P2PG_STATE_DISABLE                       0x9
> >   #define   XELPDP_P4PG_STATE_DISABLE                       0xC
> >   #define   XELPDP_P2_STATE_RESET                           0x2
> > diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c
> > b/drivers/gpu/drm/i915/display/intel_lt_phy.c
> > new file mode 100644
> > index 000000000000..c65333cc9494
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c
> > @@ -0,0 +1,159 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2025 Intel Corporation  */
> > +
> > +#include <drm/drm_print.h>
> > +
> > +#include "i915_reg.h"
> > +#include "intel_cx0_phy.h"
> > +#include "intel_cx0_phy_regs.h"
> > +#include "intel_de.h"
> > +#include "intel_display.h"
> > +#include "intel_display_types.h"
> > +#include "intel_lt_phy.h"
> > +#include "intel_lt_phy_regs.h"
> > +#include "intel_tc.h"
> > +
> > +#define INTEL_LT_PHY_LANE0         BIT(0)
> > +#define INTEL_LT_PHY_LANE1         BIT(1)
> > +#define INTEL_LT_PHY_BOTH_LANES
>       (INTEL_LT_PHY_LANE1 |\
> > +                                    INTEL_LT_PHY_LANE0)
> > +
> > +static u8 intel_lt_phy_get_owned_lane_mask(struct intel_encoder
> > +*encoder) {
> > +   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
> > +
> > +   if (!intel_tc_port_in_dp_alt_mode(dig_port))
> > +           return INTEL_LT_PHY_BOTH_LANES;
> > +
> > +   return intel_tc_port_max_lane_count(dig_port) > 2
> > +           ? INTEL_LT_PHY_BOTH_LANES : INTEL_LT_PHY_LANE0; }
> 
> Can the function in cx0 be exported/reused over here? This is just a duplicate
> of intel_cx0_phy_get_owned_lane_mask()

Not right now I do forsee some changes that may come in tc side of things later
Hence kept is separate for now

> 
> > +
> > +static void
> > +intel_lt_phy_setup_powerdown(struct intel_encoder *encoder, u8
> > +lane_count) {
> > +   /*
> > +    * The new PORT_BUF_CTL6 stuff for dc5 entry and exit needs to be
> handled
> > +    * by dmc firmware not explicitly mentioned in Bspec. This leaves this
> > +    * function as a wrapper only but keeping it expecting future changes.
> > +    */
> > +   intel_cx0_setup_powerdown(encoder);
> > +}
> > +
> > +static void
> > +intel_lt_phy_lane_reset(struct intel_encoder *encoder,
> > +                   u8 lane_count)
> > +{
> > +   struct intel_display *display = to_intel_display(encoder);
> > +   enum port port = encoder->port;
> > +   enum phy phy = intel_encoder_to_phy(encoder);
> > +   u8 owned_lane_mask =
> intel_lt_phy_get_owned_lane_mask(encoder);
> > +   u32 lane_pipe_reset = owned_lane_mask ==
> INTEL_LT_PHY_BOTH_LANES
> > +                           ? XELPDP_LANE_PIPE_RESET(0) |
> XELPDP_LANE_PIPE_RESET(1)
> > +                           : XELPDP_LANE_PIPE_RESET(0);
> > +   u32 lane_phy_current_status = owned_lane_mask ==
> INTEL_LT_PHY_BOTH_LANES
> > +                                   ?
> (XELPDP_LANE_PHY_CURRENT_STATUS(0) |
> > +
> XELPDP_LANE_PHY_CURRENT_STATUS(1))
> > +                                   :
> XELPDP_LANE_PHY_CURRENT_STATUS(0);
> > +   u32 lane_phy_pulse_status = owned_lane_mask ==
> INTEL_LT_PHY_BOTH_LANES
> > +                                   ?
> (XE3PLPDP_LANE_PHY_PULSE_STATUS(0) |
> > +
> XE3PLPDP_LANE_PHY_PULSE_STATUS(1))
> > +                                   :
> XE3PLPDP_LANE_PHY_PULSE_STATUS(0);
> > +
> > +   intel_de_rmw(display, XE3PLPD_PORT_BUF_CTL5(port),
> > +                XE3PLPD_MACCLK_RATE_MASK,
> XE3PLPD_MACCLK_RATE_DEF);
> > +
> > +   intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, port),
> > +                XE3PLPDP_PHY_MODE_MASK,
> XE3PLPDP_PHY_MODE_DP);
> > +
> > +   intel_lt_phy_setup_powerdown(encoder, lane_count);
> > +
> > +   intel_de_rmw(display, XE3PLPD_PORT_BUF_CTL5(port),
> > +                XE3PLPD_MACCLK_RESET_0, 0);
> > +
> > +   intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port),
> > +                XELPDP_LANE_PCLK_PLL_REQUEST(0),
> > +                XELPDP_LANE_PCLK_PLL_REQUEST(0));
> > +
> > +   if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display,
> port),
> > +                            XELPDP_LANE_PCLK_PLL_ACK(0),
> > +                            XELPDP_LANE_PCLK_PLL_ACK(0),
> > +                            XE3PLPD_MACCLK_TURNON_LATENCY_US,
> > +                            XE3PLPD_MACCLK_TURNON_LATENCY_MS,
> NULL))
> > +           drm_warn(display->drm, "PHY %c PLL MacCLK assertion Ack
> not done after %dus.\n",
> > +                    phy_name(phy),
> XE3PLPD_MACCLK_TURNON_LATENCY_MS * 1000);
> > +
> > +   intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port),
> > +                XELPDP_FORWARD_CLOCK_UNGATE,
> > +                XELPDP_FORWARD_CLOCK_UNGATE);
> > +
> > +   intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port),
> > +                lane_pipe_reset | lane_phy_pulse_status, 0);
> > +
> > +   if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display,
> port),
> > +                            lane_phy_current_status, 0,
> > +                            XE3PLPD_RESET_END_LATENCY_US, 2,
> NULL))
> > +           drm_warn(display->drm,
> > +                    "PHY %c failed to bring out of Lane reset after
> %dus.\n",
> > +                    phy_name(phy),
> XE3PLPD_RESET_END_LATENCY_US);
> > +
> > +   if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display,
> port),
> > +                            lane_phy_pulse_status,
> lane_phy_pulse_status,
> > +                            XE3PLPD_RATE_CALIB_DONE_LATENCY_US,
> 0, NULL))
> > +           drm_warn(display->drm, "PHY %c PLL rate not changed after
> %dus.\n",
> > +                    phy_name(phy),
> XE3PLPD_RATE_CALIB_DONE_LATENCY_US);
> > +
> > +   intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port),
> > +lane_phy_pulse_status, 0); }
> > +
> > +void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
> > +                        const struct intel_crtc_state *crtc_state) {
> > +   /* 1. Enable MacCLK at default 162 MHz frequency. */
> > +   intel_lt_phy_lane_reset(encoder, crtc_state->lane_count);
> > +
> Should the entire steps be added over here or add them in the respective
> patches!
> > +   /* 2. Program PORT_CLOCK_CTL register to configure clock muxes,
> gating, and SSC. */
> > +   /* 3. Change owned PHY lanes power to Ready state. */
> > +   /*
> > +    * 4. Read the PHY message bus VDR register PHY_VDR_0_Config
> check enabled PLL type,
> > +    * encoded rate and encoded mode.
> > +    */
> > +   /*
> > +    * 5. Program the PHY internal PLL registers over PHY message bus for
> the desired
> > +    * frequency and protocol type
> > +    */
> > +   /* 6. Use the P2P transaction flow */
> > +   /*
> > +    * 6.1. Set the PHY VDR register 0xCC4[Rate Control VDR Update] = 1
> over PHY message
> > +    * bus for Owned PHY Lanes.
> > +    */
> > +   /*
> > +    * 6.2. Poll for P2P Transaction Ready = "1" and read the MAC
> message bus VDR register
> > +    * at offset 0xC00 for Owned PHY Lanes.
> > +    */
> > +   /* 6.3. Clear P2P transaction Ready bit. */
> > +   /* 7. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 0. */
> > +   /* 8. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 0. */
> > +   /*
> > +    * 9. Follow the Display Voltage Frequency Switching - Sequence
> Before Frequency Change.
> > +    * We handle this step in bxt_set_cdclk()
> > +    */
> > +   /* 10. Program DDI_CLK_VALFREQ to match intended DDI clock
> frequency. */
> > +   /* 11. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 1. */
> > +   /* 12. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 1. */
> > +   /* 13. Ungate the forward clock by setting PORT_CLOCK_CTL[Forward
> Clock Ungate] = 1. */
> > +   /* 14. SW clears PORT_BUF_CTL2 [PHY Pulse Status]. */
> > +   /*
> > +    * 15. Clear the PHY VDR register 0xCC4[Rate Control VDR Update]
> over PHY message bus for
> > +    * Owned PHY Lanes.
> > +    */
> > +   /* 16. Poll for PORT_BUF_CTL2 register PHY Pulse Status = 1 for
> Owned PHY Lanes. */
> > +   /* 17. SW clears PORT_BUF_CTL2 [PHY Pulse Status]. */
> > +   /*
> > +    * 18. Follow the Display Voltage Frequency Switching - Sequence
> After Frequency Change.
> > +    * We handle this step in bxt_set_cdclk()
> > +    */
> > +   /* 19. Move the PHY powerdown state to Active and program to
> > +enable/disable transmitters */ }
> > diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.h
> > b/drivers/gpu/drm/i915/display/intel_lt_phy.h
> > new file mode 100644
> > index 000000000000..bd3ff3007e1d
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/display/intel_lt_phy.h
> > @@ -0,0 +1,17 @@
> > +/* SPDX-License-Identifier: MIT
> > + *
> > + * Copyright © 2025 Intel Corporation  */
> > +
> > +#ifndef __INTEL_LT_PHY_H__
> > +#define __INTEL_LT_PHY_H__
> > +
> > +#include <linux/types.h>
> > +
> > +struct intel_encoder;
> > +struct intel_crtc_state;
> > +
> > +void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
> > +                        const struct intel_crtc_state *crtc_state);
> > +
> > +#endif /* __INTEL_LT_PHY_H__ */
> > diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
> > b/drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
> > index 499acb1975d1..a4aa2a3e0425 100644
> > --- a/drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
> > +++ b/drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
> > @@ -9,6 +9,12 @@
> >   #include "i915_reg_defs.h"
> >   #include "intel_display_limits.h"
> >
> > +#define XE3PLPD_MACCLK_TURNON_LATENCY_MS   1
> > +#define XE3PLPD_MACCLK_TURNON_LATENCY_US   21
> > +#define XE3PLPD_RATE_CALIB_DONE_LATENCY_US 50
> > +#define XE3PLPD_RESET_START_LATENCY_US     10
> > +#define XE3PLPD_RESET_END_LATENCY_US       200
> > +
> 
> Can the values be aligned?

They seem to be aligned

Regards,
Suraj Kandpal

> 
> Thanks and Regards,
> Arun R Murthy
> --------------------
> 
> >   /* LT Phy Vendor Register */
> >   #define LT_PHY_VDR_0_CONFIG       0xC02
> >   #define  LT_PHY_VDR_DP_PLL_ENABLE REG_BIT(7)
> > @@ -24,4 +30,15 @@
> >
> >   #define LT_PHY_RATE_UPDATE                0xCC4
> >
> > +#define _XE3PLPD_PORT_BUF_CTL5(idx)
>       _MMIO(_PICK_EVEN_2RANGES(idx, PORT_TC1, \
> > +
> _XELPDP_PORT_BUF_CTL1_LN0_A, \
> > +
> _XELPDP_PORT_BUF_CTL1_LN0_B, \
> > +
> _XELPDP_PORT_BUF_CTL1_LN0_USBC1, \
> > +
> _XELPDP_PORT_BUF_CTL1_LN0_USBC2) \
> > +                                                           + 0x34)
> > +#define XE3PLPD_PORT_BUF_CTL5(port)
>       _XE3PLPD_PORT_BUF_CTL5(__xe2lpd_port_idx(port))
> > +#define  XE3PLPD_MACCLK_RESET_0            REG_BIT(11)
> > +#define  XE3PLPD_MACCLK_RATE_MASK  REG_GENMASK(4, 0)
> > +#define  XE3PLPD_MACCLK_RATE_DEF
>       REG_FIELD_PREP(XE3PLPD_MACCLK_RATE_MASK, 0x1F)
> > +
> >   #endif /* __INTEL_LT_PHY_REGS_H__ */ diff --git
> > a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index
> > 84321fad3265..314aeea0f1e3 100644
> > --- a/drivers/gpu/drm/xe/Makefile
> > +++ b/drivers/gpu/drm/xe/Makefile
> > @@ -291,6 +291,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
> >     i915-display/intel_hti.o \
> >     i915-display/intel_link_bw.o \
> >     i915-display/intel_lspcon.o \
> > +   i915-display/intel_lt_phy.o \
> >     i915-display/intel_modeset_lock.o \
> >     i915-display/intel_modeset_setup.o \
> >     i915-display/intel_modeset_verify.o \

Reply via email to