diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f6afa5e5e7c1..5d7736117cb9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5318,6 +5318,7 @@ enum {
 #define _DPA_AUX_CH_DATA3	(dev_priv->info.display_mmio_offset + 0x6401c)
 #define _DPA_AUX_CH_DATA4	(dev_priv->info.display_mmio_offset + 0x64020)
 #define _DPA_AUX_CH_DATA5	(dev_priv->info.display_mmio_offset + 0x64024)
+#define _DPA_AUX_CH_MUTEX	(dev_priv->info.display_mmio_offset + 0x6402C)
 
 #define _DPB_AUX_CH_CTL		(dev_priv->info.display_mmio_offset + 0x64110)
 #define _DPB_AUX_CH_DATA1	(dev_priv->info.display_mmio_offset + 0x64114)
@@ -5325,6 +5326,7 @@ enum {
 #define _DPB_AUX_CH_DATA3	(dev_priv->info.display_mmio_offset + 0x6411c)
 #define _DPB_AUX_CH_DATA4	(dev_priv->info.display_mmio_offset + 0x64120)
 #define _DPB_AUX_CH_DATA5	(dev_priv->info.display_mmio_offset + 0x64124)
+#define _DPB_AUX_CH_MUTEX	(dev_priv->info.display_mmio_offset + 0x6412C)
 
 #define _DPC_AUX_CH_CTL		(dev_priv->info.display_mmio_offset + 0x64210)
 #define _DPC_AUX_CH_DATA1	(dev_priv->info.display_mmio_offset + 0x64214)
@@ -5332,6 +5334,7 @@ enum {
 #define _DPC_AUX_CH_DATA3	(dev_priv->info.display_mmio_offset + 0x6421c)
 #define _DPC_AUX_CH_DATA4	(dev_priv->info.display_mmio_offset + 0x64220)
 #define _DPC_AUX_CH_DATA5	(dev_priv->info.display_mmio_offset + 0x64224)
+#define _DPC_AUX_CH_MUTEX	(dev_priv->info.display_mmio_offset + 0x6422C)
 
 #define _DPD_AUX_CH_CTL		(dev_priv->info.display_mmio_offset + 0x64310)
 #define _DPD_AUX_CH_DATA1	(dev_priv->info.display_mmio_offset + 0x64314)
@@ -5339,6 +5342,7 @@ enum {
 #define _DPD_AUX_CH_DATA3	(dev_priv->info.display_mmio_offset + 0x6431c)
 #define _DPD_AUX_CH_DATA4	(dev_priv->info.display_mmio_offset + 0x64320)
 #define _DPD_AUX_CH_DATA5	(dev_priv->info.display_mmio_offset + 0x64324)
+#define _DPD_AUX_CH_MUTEX	(dev_priv->info.display_mmio_offset + 0x6432C)
 
 #define _DPF_AUX_CH_CTL		(dev_priv->info.display_mmio_offset + 0x64510)
 #define _DPF_AUX_CH_DATA1	(dev_priv->info.display_mmio_offset + 0x64514)
@@ -5346,9 +5350,11 @@ enum {
 #define _DPF_AUX_CH_DATA3	(dev_priv->info.display_mmio_offset + 0x6451c)
 #define _DPF_AUX_CH_DATA4	(dev_priv->info.display_mmio_offset + 0x64520)
 #define _DPF_AUX_CH_DATA5	(dev_priv->info.display_mmio_offset + 0x64524)
+#define _DPF_AUX_CH_MUTEX	(dev_priv->info.display_mmio_offset + 0x6452C)
 
 #define DP_AUX_CH_CTL(port)	_MMIO_PORT(port, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL)
 #define DP_AUX_CH_DATA(port, i)	_MMIO(_PORT(port, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
+#define DP_AUX_CH_MUTEX(port)	_MMIO_PORT(port, _DPA_AUX_CH_MUTEX, _DPB_AUX_CH_MUTEX)
 
 #define   DP_AUX_CH_CTL_SEND_BUSY	    (1 << 31)
 #define   DP_AUX_CH_CTL_DONE		    (1 << 30)
@@ -5378,6 +5384,9 @@ enum {
 #define   DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(c) (((c) - 1) << 5)
 #define   DP_AUX_CH_CTL_SYNC_PULSE_SKL(c)   ((c) - 1)
 
+#define   DP_AUX_CH_MUTEX_ENABLE		(1 << 31)
+#define   DP_AUX_CH_MUTEX_STATUS		(1 << 30)
+
 /*
  * Computing GMCH M and N values for the Display Port link
  *
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f20b25f98e5a..bd5f1bb730ff 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1081,6 +1081,28 @@ static uint32_t intel_dp_get_aux_send_ctl(struct intel_dp *intel_dp,
 						aux_clock_divider);
 }
 
+static bool intel_dp_aux_get(struct drm_i915_private *dev_priv,
+			     struct intel_dp *intel_dp)
+{
+	int try, ret;
+
+	for (try = 0, ret = -1; try < 3 && ret; try++)
+		ret = wait_for(!(I915_READ_NOTRACE(intel_dp->aux_ch_mutex_reg)
+				 & DP_AUX_CH_MUTEX_STATUS), 0.5);
+
+	return ret == 0;
+}
+
+static void intel_dp_aux_put(struct drm_i915_private *dev_priv,
+			     struct intel_dp *intel_dp)
+{
+	/* setting the status bit releases the mutex + keep set the bit
+	 * to keep the mutex enabled.
+	 */
+	I915_WRITE(intel_dp->aux_ch_mutex_reg, DP_AUX_CH_MUTEX_ENABLE |
+		   DP_AUX_CH_MUTEX_STATUS);
+}
+
 static int
 intel_dp_aux_ch(struct intel_dp *intel_dp,
 		const uint8_t *send, int send_bytes,
@@ -1115,6 +1137,21 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 
 	intel_dp_check_edp(intel_dp);
 
+	/* Get hardware mutex when PSR is enabled */
+	if (dev_priv->psr.enabled == intel_dp) {
+		if (intel_dp->aux_ch_mutex_reg.reg) {
+			if (intel_dp_aux_get(dev_priv, intel_dp)) {
+				DRM_WARN("dp_aux_ch port locked for too long");
+				ret = -EBUSY;
+				goto out_locked;
+			}
+		} else {
+			/* TODO: go to PSR exit state waiting for change before
+			 * do a aux ch transaction.
+			 */
+		}
+	}
+
 	/* Try to wait for any previous AUX channel activity */
 	for (try = 0; try < 3; try++) {
 		status = I915_READ_NOTRACE(ch_ctl);
@@ -1243,7 +1280,16 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 				    recv + i, recv_bytes - i);
 
 	ret = recv_bytes;
+
 out:
+	if (dev_priv->psr.enabled == intel_dp) {
+		if (intel_dp->aux_ch_mutex_reg.reg)
+			intel_dp_aux_put(dev_priv, intel_dp);
+		else
+			/* TODO: schedule PSR work to active PSR again */
+	}
+
+out_locked:
 	pm_qos_update_request(&dev_priv->pm_qos, PM_QOS_DEFAULT_VALUE);
 
 	if (vdd)
@@ -1496,6 +1542,8 @@ static void intel_aux_reg_init(struct intel_dp *intel_dp)
 	intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port);
 	for (i = 0; i < ARRAY_SIZE(intel_dp->aux_ch_data_reg); i++)
 		intel_dp->aux_ch_data_reg[i] = intel_aux_data_reg(dev_priv, port, i);
+	if (INTEL_INFO(dev_priv)->gen >= 9)
+		intel_dp->aux_ch_mutex_reg = DP_AUX_CH_MUTEX(port);
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 898064e8bea7..0d235b7dab21 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1040,6 +1040,7 @@ struct intel_dp {
 	i915_reg_t output_reg;
 	i915_reg_t aux_ch_ctl_reg;
 	i915_reg_t aux_ch_data_reg[5];
+	i915_reg_t aux_ch_mutex_reg;
 	uint32_t DP;
 	int link_rate;
 	uint8_t lane_count;
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 2ef374f936b9..8b456e4e1b47 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -484,6 +484,9 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp,
 			   EDP_PSR_DEBUG_MASK_HPD |
 			   EDP_PSR_DEBUG_MASK_LPSP);
 	}
+
+	if (intel_dp->aux_ch_mutex_reg.reg)
+		I915_WRITE(intel_dp->aux_ch_mutex_reg, DP_AUX_CH_MUTEX_ENABLE);
 }
 
 /**
@@ -617,6 +620,9 @@ static void hsw_psr_disable(struct intel_dp *intel_dp,
 		else
 			WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
 	}
+
+	if (intel_dp->aux_ch_mutex_reg.reg)
+		I915_WRITE(intel_dp->aux_ch_mutex_reg, ~DP_AUX_CH_MUTEX_ENABLE);
 }
 
 /**
