[Intel-gfx] [PATCH v2] drm/i915/cx0: Add step for programming msgbus timer

Kahola, Mika mika.kahola at intel.com
Wed Sep 13 06:46:41 UTC 2023


> -----Original Message-----
> From: Sousa, Gustavo <gustavo.sousa at intel.com>
> Sent: Tuesday, September 12, 2023 6:59 PM
> To: intel-gfx at lists.freedesktop.org
> Cc: Kahola, Mika <mika.kahola at intel.com>; Taylor, Clinton A <clinton.a.taylor at intel.com>
> Subject: [PATCH v2] drm/i915/cx0: Add step for programming msgbus timer
> 
> There was a recent update in the BSpec adding an extra step to the PLL enable sequence, which is for programming the msgbus
> timer. Since we also touch PHY registers during hw readout, let's do the programming when starting a transaction rather than only
> when doing the PLL enable sequence.
> 
> This might be the missing step that was causing the timeouts that we have recently seen during C20 SRAM register programming
> sequences. With this in place, we shouldn't need the logic to bump the timer thresholds, since now we have a documented value
> that should be set peform programming the registers. As such, let's also remove intel_cx0_bus_check_and_bump_timer(), but
> keep the part that checks if hardware really detected a timeout, which might be useful debugging information.
> 
> v2:
>   - Use debug level instead of warning for the message notifying that
>     the hardware did not detect the timeout. (Mika)
>   - Got a new BSpec update clarifying that we need to program the msgbus
>     timer of both PHY lanes. Update the changes to reflect that.
>     (Gustavo)
> 
> BSpec: 64568
> Cc: Mika Kahola <mika.kahola at intel.com>

Reviewed-by: Mika Kahola <mika.kahola at intel.com>

> Signed-off-by: Gustavo Sousa <gustavo.sousa at intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 87 +++++++++----------  .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  2 +-
>  2 files changed, 41 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> index e6d3027c821d..abd607b564f1 100644
> --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
> @@ -29,8 +29,6 @@
>  #define INTEL_CX0_LANE1		BIT(1)
>  #define INTEL_CX0_BOTH_LANES	(INTEL_CX0_LANE1 | INTEL_CX0_LANE0)
> 
> -#define INTEL_CX0_MSGBUS_TIMER_BUMPED_VAL	0x200
> -
>  bool intel_is_c10phy(struct drm_i915_private *i915, enum phy phy)  {
>  	if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0) && phy < PHY_C) @@ -73,19 +71,38 @@ assert_dc_off(struct
> drm_i915_private *i915)
>  	drm_WARN_ON(&i915->drm, !enabled);
>  }
> 
> +static void intel_cx0_program_msgbus_timer(struct intel_encoder
> +*encoder) {
> +	int lane;
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> +	for_each_cx0_lane_in_mask(INTEL_CX0_BOTH_LANES, lane)
> +		intel_de_rmw(i915,
> +			     XELPDP_PORT_MSGBUS_TIMER(encoder->port, lane),
> +			     XELPDP_PORT_MSGBUS_TIMER_VAL_MASK,
> +			     XELPDP_PORT_MSGBUS_TIMER_VAL);
> +}
> +
>  /*
>   * Prepare HW for CX0 phy transactions.
>   *
>   * It is required that PSR and DC5/6 are disabled before any CX0 message
>   * bus transaction is executed.
> + *
> + * We also do the msgbus timer programming here to ensure that the
> + timer
> + * is already programmed before any access to the msgbus.
>   */
>  static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)  {
> +	intel_wakeref_t wakeref;
>  	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
>  	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> 
>  	intel_psr_pause(intel_dp);
> -	return intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
> +	wakeref = intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
> +	intel_cx0_program_msgbus_timer(encoder);
> +
> +	return wakeref;
>  }
> 
>  static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref) @@ -121,42 +138,6 @@
> static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, i
>  	intel_clear_response_ready_flag(i915, port, lane);  }
> 
> -/*
> - * Check if there was a timeout detected by the hardware in the message bus
> - * and bump the threshold if so.
> - */
> -static void intel_cx0_bus_check_and_bump_timer(struct drm_i915_private *i915,
> -					       enum port port, int lane)
> -{
> -	enum phy phy = intel_port_to_phy(i915, port);
> -	i915_reg_t reg;
> -	u32 val;
> -	u32 timer_val;
> -
> -	reg = XELPDP_PORT_MSGBUS_TIMER(port, lane);
> -	val = intel_de_read(i915, reg);
> -
> -	if (!(val & XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT)) {
> -		drm_warn(&i915->drm,
> -			 "PHY %c lane %d: hardware did not detect a timeout\n",
> -			 phy_name(phy), lane);
> -		return;
> -	}
> -
> -	timer_val = REG_FIELD_GET(XELPDP_PORT_MSGBUS_TIMER_VAL_MASK, val);
> -
> -	if (timer_val == INTEL_CX0_MSGBUS_TIMER_BUMPED_VAL)
> -		return;
> -
> -	val &= ~XELPDP_PORT_MSGBUS_TIMER_VAL_MASK;
> -	val |= XELPDP_PORT_MSGBUS_TIMER_VAL(INTEL_CX0_MSGBUS_TIMER_BUMPED_VAL);
> -
> -	drm_dbg_kms(&i915->drm,
> -		    "PHY %c lane %d: increasing msgbus timer threshold to %#x\n",
> -		    phy_name(phy), lane, INTEL_CX0_MSGBUS_TIMER_BUMPED_VAL);
> -	intel_de_write(i915, reg, val);
> -}
> -
>  static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port,
>  				  int command, int lane, u32 *val)
>  {
> @@ -170,7 +151,13 @@ static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port,
>  					 XELPDP_MSGBUS_TIMEOUT_SLOW, val)) {
>  		drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n",
>  			    phy_name(phy), *val);
> -		intel_cx0_bus_check_and_bump_timer(i915, port, lane);
> +
> +		if (!(intel_de_read(i915, XELPDP_PORT_MSGBUS_TIMER(port, lane)) &
> +		      XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT))
> +			drm_dbg_kms(&i915->drm,
> +				    "PHY %c Hardware did not detect a timeout\n",
> +				    phy_name(phy));
> +
>  		intel_cx0_bus_reset(i915, port, lane);
>  		return -ETIMEDOUT;
>  	}
> @@ -2737,39 +2724,45 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
>  	intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES,
>  					    CX0_P2_STATE_READY);
> 
> -	/* 4. Program PHY internal PLL internal registers. */
> +	/*
> +	 * 4. Program PORT_MSGBUS_TIMER register's Message Bus Timer field to 0xA000.
> +	 *    (This is done inside intel_cx0_phy_transaction_begin(), since we would need
> +	 *    the right timer thresholds for readouts too.)
> +	 */
> +
> +	/* 5. Program PHY internal PLL internal registers. */
>  	if (intel_is_c10phy(i915, phy))
>  		intel_c10_pll_program(i915, crtc_state, encoder);
>  	else
>  		intel_c20_pll_program(i915, crtc_state, encoder);
> 
>  	/*
> -	 * 5. Program the enabled and disabled owned PHY lane
> +	 * 6. Program the enabled and disabled owned PHY lane
>  	 * transmitters over message bus
>  	 */
>  	intel_cx0_program_phy_lane(i915, encoder, crtc_state->lane_count, lane_reversal);
> 
>  	/*
> -	 * 6. Follow the Display Voltage Frequency Switching - Sequence
> +	 * 7. Follow the Display Voltage Frequency Switching - Sequence
>  	 * Before Frequency Change. We handle this step in bxt_set_cdclk().
>  	 */
> 
>  	/*
> -	 * 7. Program DDI_CLK_VALFREQ to match intended DDI
> +	 * 8. Program DDI_CLK_VALFREQ to match intended DDI
>  	 * clock frequency.
>  	 */
>  	intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
>  		       crtc_state->port_clock);
> 
>  	/*
> -	 * 8. Set PORT_CLOCK_CTL register PCLK PLL Request
> +	 * 9. Set PORT_CLOCK_CTL register PCLK PLL Request
>  	 * LN<Lane for maxPCLK> to "1" to enable PLL.
>  	 */
>  	intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
>  		     intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES),
>  		     intel_cx0_get_pclk_pll_request(maxpclk_lane));
> 
> -	/* 9. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */
> +	/* 10. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> ==
> +"1". */
>  	if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
>  					 intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES),
>  					 intel_cx0_get_pclk_pll_ack(maxpclk_lane),
> @@ -2778,7 +2771,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
>  			 phy_name(phy), XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US);
> 
>  	/*
> -	 * 10. Follow the Display Voltage Frequency Switching Sequence After
> +	 * 11. Follow the Display Voltage Frequency Switching Sequence After
>  	 * Frequency Change. We handle this step in bxt_set_cdclk().
>  	 */
> 
> 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 b2db4cc366d6..adf8f4ce0d49 100644
> --- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
> @@ -121,7 +121,7 @@
> 
> _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC2) + (lane) * 4)
>  #define   XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT		REG_BIT(31)
>  #define   XELPDP_PORT_MSGBUS_TIMER_VAL_MASK		REG_GENMASK(23, 0)
> -#define   XELPDP_PORT_MSGBUS_TIMER_VAL(val)		REG_FIELD_PREP(XELPDP_PORT_MSGBUS_TIMER_VAL_MASK,
> val)
> +#define   XELPDP_PORT_MSGBUS_TIMER_VAL			REG_FIELD_PREP(XELPDP_PORT_MSGBUS_TIMER_VAL_MASK,
> 0xa000)
> 
>  #define _XELPDP_PORT_CLOCK_CTL_A			0x640E0
>  #define _XELPDP_PORT_CLOCK_CTL_B			0x641E0
> --
> 2.42.0



More information about the Intel-gfx mailing list