diff mbox

[24/24] drm/i915/icl: toggle PHY clock gating around link training

Message ID 20180522002558.29262-25-paulo.r.zanoni@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Zanoni, Paulo R May 22, 2018, 12:25 a.m. UTC
The Gen11 TypeC PHY DDI Buffer chapter, PHY Clock Gating Programming
section says that PHY clock gating should be disabled before starting
voltage swing programming, then enabled after any link training is
complete.

Cc: Animesh Manna <animesh.manna@intel.com>
Cc: Manasi Navare <manasi.d.navare@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h  | 21 +++++++++++++
 drivers/gpu/drm/i915/intel_ddi.c |  3 ++
 drivers/gpu/drm/i915/intel_dp.c  | 66 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  2 ++
 4 files changed, 92 insertions(+)

Comments

Maarten Lankhorst June 19, 2018, 1:22 p.m. UTC | #1
Op 22-05-18 om 02:25 schreef Paulo Zanoni:
> The Gen11 TypeC PHY DDI Buffer chapter, PHY Clock Gating Programming
> section says that PHY clock gating should be disabled before starting
> voltage swing programming, then enabled after any link training is
> complete.
>
> Cc: Animesh Manna <animesh.manna@intel.com>
> Cc: Manasi Navare <manasi.d.navare@intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h  | 21 +++++++++++++
>  drivers/gpu/drm/i915/intel_ddi.c |  3 ++
>  drivers/gpu/drm/i915/intel_dp.c  | 66 ++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |  2 ++
>  4 files changed, 92 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 2ccae6c3e905..9d2c022bc3a1 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1957,6 +1957,27 @@ enum i915_power_well_id {
>  				      _MG_DP_MODE_LN1_ACU_PORT1)
>  #define   MG_DP_MODE_CFG_DP_X2_MODE			(1 << 7)
>  #define   MG_DP_MODE_CFG_DP_X1_MODE			(1 << 6)
> +#define   MG_DP_MODE_CFG_TR2PWR_GATING			(1 << 5)
> +#define   MG_DP_MODE_CFG_TRPWR_GATING			(1 << 4)
> +#define   MG_DP_MODE_CFG_CLNPWR_GATING			(1 << 3)
> +#define   MG_DP_MODE_CFG_DIGPWR_GATING			(1 << 2)
> +#define   MG_DP_MODE_CFG_GAONPWR_GATING			(1 << 1)
> +
> +#define _MG_MISC_SUS0_PORT1				0x168814
> +#define _MG_MISC_SUS0_PORT2				0x169814
> +#define _MG_MISC_SUS0_PORT3				0x16A814
> +#define _MG_MISC_SUS0_PORT4				0x16B814
> +#define MG_MISC_SUS0(tc_port) \
> +	_MMIO(_PORT(tc_port, _MG_MISC_SUS0_PORT1, _MG_MISC_SUS0_PORT2))
> +#define   MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE_MASK	(3 << 14)
> +#define   MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE(x)	((x) << 14)
> +#define   MG_MISC_SUS0_CFG_TR2PWR_GATING		(1 << 12)
> +#define   MG_MISC_SUS0_CFG_CL2PWR_GATING		(1 << 11)
> +#define   MG_MISC_SUS0_CFG_GAONPWR_GATING		(1 << 10)
> +#define   MG_MISC_SUS0_CFG_TRPWR_GATING			(1 << 7)
> +#define   MG_MISC_SUS0_CFG_CL1PWR_GATING		(1 << 6)
> +#define   MG_MISC_SUS0_CFG_DGPWR_GATING			(1 << 5)
> +
>  
>  /* The spec defines this only for BXT PHY0, but lets assume that this
>   * would exist for PHY1 too if it had a second channel.
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index c3c29565b863..6617950a28a9 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2668,6 +2668,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
>  	intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
>  
>  	icl_program_mg_dp_mode(intel_dp);
> +	icl_disable_phy_clock_gating(dig_port);
>  
>  	if (IS_ICELAKE(dev_priv))
>  		icl_ddi_vswing_sequence(encoder, level, encoder->type);
> @@ -2684,6 +2685,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
>  	intel_dp_start_link_train(intel_dp);
>  	if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
>  		intel_dp_stop_link_train(intel_dp);
> +
> +	icl_enable_phy_clock_gating(dig_port);
>  }
>  
>  static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 1228d6185f76..e898d61b5924 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -295,6 +295,72 @@ void icl_program_mg_dp_mode(struct intel_dp *intel_dp)
>  	I915_WRITE(MG_DP_MODE(port, 1), ln1);
>  }
>  
> +void icl_enable_phy_clock_gating(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum port port = dig_port->base.port;
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> +	i915_reg_t mg_regs[2] = { MG_DP_MODE(port, 0), MG_DP_MODE(port, 1) };
> +	u32 val;
> +	int i;
> +
> +	if (tc_port == PORT_TC_NONE)
> +		return;
> +
> +	for (i = 0; i < ARRAY_SIZE(mg_regs); i++) {
> +		val = I915_READ(mg_regs[i]);
> +		val |= MG_DP_MODE_CFG_TR2PWR_GATING |
> +		       MG_DP_MODE_CFG_TRPWR_GATING |
> +		       MG_DP_MODE_CFG_CLNPWR_GATING |
> +		       MG_DP_MODE_CFG_DIGPWR_GATING |
> +		       MG_DP_MODE_CFG_GAONPWR_GATING;
> +		I915_WRITE(mg_regs[i], val);
> +	}
> +
> +	val = I915_READ(MG_MISC_SUS0(tc_port));
> +	val |= MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE(3) |
> +	       MG_MISC_SUS0_CFG_TR2PWR_GATING |
> +	       MG_MISC_SUS0_CFG_CL2PWR_GATING |
> +	       MG_MISC_SUS0_CFG_GAONPWR_GATING |
> +	       MG_MISC_SUS0_CFG_TRPWR_GATING |
> +	       MG_MISC_SUS0_CFG_CL1PWR_GATING |
> +	       MG_MISC_SUS0_CFG_DGPWR_GATING;
> +	I915_WRITE(MG_MISC_SUS0(tc_port), val);
> +}
> +
> +void icl_disable_phy_clock_gating(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum port port = dig_port->base.port;
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> +	i915_reg_t mg_regs[2] = { MG_DP_MODE(port, 0), MG_DP_MODE(port, 1) };
> +	u32 val;
> +	int i;
> +
> +	if (tc_port == PORT_TC_NONE)
> +		return;
> +
> +	for (i = 0; i < ARRAY_SIZE(mg_regs); i++) {
> +		val = I915_READ(mg_regs[i]);
> +		val &= ~(MG_DP_MODE_CFG_TR2PWR_GATING |
> +			 MG_DP_MODE_CFG_TRPWR_GATING |
> +			 MG_DP_MODE_CFG_CLNPWR_GATING |
> +			 MG_DP_MODE_CFG_DIGPWR_GATING |
> +			 MG_DP_MODE_CFG_GAONPWR_GATING);
> +		I915_WRITE(mg_regs[i], val);
> +	}
> +
> +	val = I915_READ(MG_MISC_SUS0(tc_port));
> +	val &= ~(MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE_MASK |
> +		 MG_MISC_SUS0_CFG_TR2PWR_GATING |
> +		 MG_MISC_SUS0_CFG_CL2PWR_GATING |
> +		 MG_MISC_SUS0_CFG_GAONPWR_GATING |
> +		 MG_MISC_SUS0_CFG_TRPWR_GATING |
> +		 MG_MISC_SUS0_CFG_CL1PWR_GATING |
> +		 MG_MISC_SUS0_CFG_DGPWR_GATING);
> +	I915_WRITE(MG_MISC_SUS0(tc_port), val);
> +}
> +
>  int
>  intel_dp_max_data_rate(int max_link_clock, int max_lanes)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d04be4c1f30e..8c77e0499b44 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1703,6 +1703,8 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
>  void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
>  			  unsigned int frontbuffer_bits);
>  void icl_program_mg_dp_mode(struct intel_dp *intel_dp);
> +void icl_enable_phy_clock_gating(struct intel_digital_port *dig_port);
> +void icl_disable_phy_clock_gating(struct intel_digital_port *dig_port);
>  
>  void
>  intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,

Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2ccae6c3e905..9d2c022bc3a1 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1957,6 +1957,27 @@  enum i915_power_well_id {
 				      _MG_DP_MODE_LN1_ACU_PORT1)
 #define   MG_DP_MODE_CFG_DP_X2_MODE			(1 << 7)
 #define   MG_DP_MODE_CFG_DP_X1_MODE			(1 << 6)
+#define   MG_DP_MODE_CFG_TR2PWR_GATING			(1 << 5)
+#define   MG_DP_MODE_CFG_TRPWR_GATING			(1 << 4)
+#define   MG_DP_MODE_CFG_CLNPWR_GATING			(1 << 3)
+#define   MG_DP_MODE_CFG_DIGPWR_GATING			(1 << 2)
+#define   MG_DP_MODE_CFG_GAONPWR_GATING			(1 << 1)
+
+#define _MG_MISC_SUS0_PORT1				0x168814
+#define _MG_MISC_SUS0_PORT2				0x169814
+#define _MG_MISC_SUS0_PORT3				0x16A814
+#define _MG_MISC_SUS0_PORT4				0x16B814
+#define MG_MISC_SUS0(tc_port) \
+	_MMIO(_PORT(tc_port, _MG_MISC_SUS0_PORT1, _MG_MISC_SUS0_PORT2))
+#define   MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE_MASK	(3 << 14)
+#define   MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE(x)	((x) << 14)
+#define   MG_MISC_SUS0_CFG_TR2PWR_GATING		(1 << 12)
+#define   MG_MISC_SUS0_CFG_CL2PWR_GATING		(1 << 11)
+#define   MG_MISC_SUS0_CFG_GAONPWR_GATING		(1 << 10)
+#define   MG_MISC_SUS0_CFG_TRPWR_GATING			(1 << 7)
+#define   MG_MISC_SUS0_CFG_CL1PWR_GATING		(1 << 6)
+#define   MG_MISC_SUS0_CFG_DGPWR_GATING			(1 << 5)
+
 
 /* The spec defines this only for BXT PHY0, but lets assume that this
  * would exist for PHY1 too if it had a second channel.
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index c3c29565b863..6617950a28a9 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2668,6 +2668,7 @@  static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 	intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
 
 	icl_program_mg_dp_mode(intel_dp);
+	icl_disable_phy_clock_gating(dig_port);
 
 	if (IS_ICELAKE(dev_priv))
 		icl_ddi_vswing_sequence(encoder, level, encoder->type);
@@ -2684,6 +2685,8 @@  static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 	intel_dp_start_link_train(intel_dp);
 	if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
 		intel_dp_stop_link_train(intel_dp);
+
+	icl_enable_phy_clock_gating(dig_port);
 }
 
 static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1228d6185f76..e898d61b5924 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -295,6 +295,72 @@  void icl_program_mg_dp_mode(struct intel_dp *intel_dp)
 	I915_WRITE(MG_DP_MODE(port, 1), ln1);
 }
 
+void icl_enable_phy_clock_gating(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum port port = dig_port->base.port;
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
+	i915_reg_t mg_regs[2] = { MG_DP_MODE(port, 0), MG_DP_MODE(port, 1) };
+	u32 val;
+	int i;
+
+	if (tc_port == PORT_TC_NONE)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(mg_regs); i++) {
+		val = I915_READ(mg_regs[i]);
+		val |= MG_DP_MODE_CFG_TR2PWR_GATING |
+		       MG_DP_MODE_CFG_TRPWR_GATING |
+		       MG_DP_MODE_CFG_CLNPWR_GATING |
+		       MG_DP_MODE_CFG_DIGPWR_GATING |
+		       MG_DP_MODE_CFG_GAONPWR_GATING;
+		I915_WRITE(mg_regs[i], val);
+	}
+
+	val = I915_READ(MG_MISC_SUS0(tc_port));
+	val |= MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE(3) |
+	       MG_MISC_SUS0_CFG_TR2PWR_GATING |
+	       MG_MISC_SUS0_CFG_CL2PWR_GATING |
+	       MG_MISC_SUS0_CFG_GAONPWR_GATING |
+	       MG_MISC_SUS0_CFG_TRPWR_GATING |
+	       MG_MISC_SUS0_CFG_CL1PWR_GATING |
+	       MG_MISC_SUS0_CFG_DGPWR_GATING;
+	I915_WRITE(MG_MISC_SUS0(tc_port), val);
+}
+
+void icl_disable_phy_clock_gating(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum port port = dig_port->base.port;
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
+	i915_reg_t mg_regs[2] = { MG_DP_MODE(port, 0), MG_DP_MODE(port, 1) };
+	u32 val;
+	int i;
+
+	if (tc_port == PORT_TC_NONE)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(mg_regs); i++) {
+		val = I915_READ(mg_regs[i]);
+		val &= ~(MG_DP_MODE_CFG_TR2PWR_GATING |
+			 MG_DP_MODE_CFG_TRPWR_GATING |
+			 MG_DP_MODE_CFG_CLNPWR_GATING |
+			 MG_DP_MODE_CFG_DIGPWR_GATING |
+			 MG_DP_MODE_CFG_GAONPWR_GATING);
+		I915_WRITE(mg_regs[i], val);
+	}
+
+	val = I915_READ(MG_MISC_SUS0(tc_port));
+	val &= ~(MG_MISC_SUS0_SUSCLK_DYNCLKGATE_MODE_MASK |
+		 MG_MISC_SUS0_CFG_TR2PWR_GATING |
+		 MG_MISC_SUS0_CFG_CL2PWR_GATING |
+		 MG_MISC_SUS0_CFG_GAONPWR_GATING |
+		 MG_MISC_SUS0_CFG_TRPWR_GATING |
+		 MG_MISC_SUS0_CFG_CL1PWR_GATING |
+		 MG_MISC_SUS0_CFG_DGPWR_GATING);
+	I915_WRITE(MG_MISC_SUS0(tc_port), val);
+}
+
 int
 intel_dp_max_data_rate(int max_link_clock, int max_lanes)
 {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d04be4c1f30e..8c77e0499b44 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1703,6 +1703,8 @@  void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
 void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
 			  unsigned int frontbuffer_bits);
 void icl_program_mg_dp_mode(struct intel_dp *intel_dp);
+void icl_enable_phy_clock_gating(struct intel_digital_port *dig_port);
+void icl_disable_phy_clock_gating(struct intel_digital_port *dig_port);
 
 void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,