diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 802df8e1a544..1b25eadc5940 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5154,11 +5154,7 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
 		goto out;
 	}
 
-	ret = intel_wopcm_init_hw(&dev_priv->wopcm);
-	if (ret) {
-		DRM_ERROR("Enabling WOPCM failed (%d)\n", ret);
-		goto out;
-	}
+	intel_wopcm_init_hw(&dev_priv->wopcm);
 
 	/* We can't enable contexts until all firmware is loaded */
 	ret = intel_uc_init_hw(dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_wopcm.c b/drivers/gpu/drm/i915/intel_wopcm.c
index 295d302e97b9..be8fca80aeca 100644
--- a/drivers/gpu/drm/i915/intel_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_wopcm.c
@@ -182,7 +182,7 @@ __guc_region_grow(struct intel_wopcm *wopcm, u32 size)
 	wopcm->guc.size += size;
 }
 
-static void wopcm_adjust_for_hw_restrictions(struct intel_wopcm *wopcm)
+static int wopcm_adjust_for_hw_restrictions(struct intel_wopcm *wopcm)
 {
 	struct drm_i915_private *i915 = wopcm_to_i915(wopcm);
 	u32 huc_fw_size = intel_uc_fw_get_upload_size(&i915->huc.fw);
@@ -191,19 +191,29 @@ static void wopcm_adjust_for_hw_restrictions(struct intel_wopcm *wopcm)
 	if (IS_GEN9(i915) || IS_CNL_REVID(i915, CNL_REVID_A0, CNL_REVID_A0)) {
 		size = gen9_size_for_dword_gap_restriction(wopcm->guc.base,
 							   wopcm->guc.size);
-		if (size)
+		if (size) {
+			if (wopcm->guc.base_locked || wopcm->guc.size_locked)
+				return -E2BIG;
+
 			__guc_region_grow(wopcm, size);
+		}
 
 		size = gen9_size_for_huc_restriction(wopcm->guc.size,
 						     huc_fw_size);
-		if (size)
+		if (size) {
+			if (wopcm->guc.base_locked || wopcm->guc.size_locked)
+				return -E2BIG;
+
 			__guc_region_grow(wopcm, size);
+		}
 
 		GEM_BUG_ON(gen9_size_for_dword_gap_restriction(wopcm->guc.base,
 							       wopcm->guc.size));
 		GEM_BUG_ON(gen9_size_for_huc_restriction(wopcm->guc.size,
 							 huc_fw_size));
 	}
+
+	return 0;
 }
 
 static bool wopcm_check_components_fit(struct intel_wopcm *wopcm)
@@ -233,12 +243,30 @@ static int wopcm_guc_region_init(struct intel_wopcm *wopcm)
 {
 	struct drm_i915_private *dev_priv = wopcm_to_i915(wopcm);
 	u32 guc_fw_size = intel_uc_fw_get_upload_size(&dev_priv->guc.fw);
+	u32 huc_fw_size = intel_uc_fw_get_upload_size(&dev_priv->huc.fw);
 	u32 ctx_rsvd = context_reserved_size(dev_priv);
+	u32 reg_val;
 
-	wopcm->guc.size = guc_fw_size_in_wopcm(guc_fw_size);
+	reg_val = I915_READ(GUC_WOPCM_SIZE);
+	if (reg_val & GUC_WOPCM_SIZE_LOCKED) {
+		wopcm->guc.size = (reg_val & GUC_WOPCM_SIZE_MASK);
+		wopcm->guc.size_locked = true;
+	} else {
+		wopcm->guc.size = guc_fw_size_in_wopcm(guc_fw_size);
+	}
 
-	wopcm->guc.base = ALIGN_DOWN(wopcm->size - ctx_rsvd - wopcm->guc.size,
-				     GUC_WOPCM_OFFSET_ALIGNMENT);
+	reg_val = I915_READ(DMA_GUC_WOPCM_OFFSET);
+	if (reg_val & GUC_WOPCM_OFFSET_VALID) {
+		if (huc_fw_size && !(reg_val & HUC_LOADING_AGENT_GUC))
+			return -EIO;
+
+		wopcm->guc.base = (reg_val & GUC_WOPCM_OFFSET_MASK);
+		wopcm->guc.base_locked = true;
+	} else {
+		wopcm->guc.base = ALIGN_DOWN(wopcm->size - wopcm->guc.size -
+					     ctx_rsvd,
+					     GUC_WOPCM_OFFSET_ALIGNMENT);
+	}
 
 	return 0;
 }
@@ -265,7 +293,9 @@ int intel_wopcm_init(struct intel_wopcm *wopcm)
 	if (err)
 		return err;
 
-	wopcm_adjust_for_hw_restrictions(wopcm);
+	err = wopcm_adjust_for_hw_restrictions(wopcm);
+	if (err)
+		return err;
 
 	err = wopcm_check_components_fit(wopcm);
 	if (err)
@@ -278,66 +308,37 @@ int intel_wopcm_init(struct intel_wopcm *wopcm)
 	return 0;
 }
 
-static inline int write_and_verify(struct drm_i915_private *dev_priv,
-				   i915_reg_t reg, u32 val, u32 mask,
-				   u32 locked_bit)
-{
-	u32 reg_val;
-
-	GEM_BUG_ON(val & ~mask);
-
-	I915_WRITE(reg, val);
-
-	reg_val = I915_READ(reg);
-
-	return (reg_val & mask) != (val | locked_bit) ? -EIO : 0;
-}
-
 /**
  * intel_wopcm_init_hw() - Setup GuC WOPCM registers.
  * @wopcm: pointer to intel_wopcm.
  *
- * Setup the GuC WOPCM size and offset registers with the calculated values. It
- * will verify the register values to make sure the registers are locked with
- * correct values.
+ * Setup the GuC WOPCM size and offset registers with the calculated values.
  *
- * Return: 0 on success. -EIO if registers were locked with incorrect values.
  */
-int intel_wopcm_init_hw(struct intel_wopcm *wopcm)
+void intel_wopcm_init_hw(struct intel_wopcm *wopcm)
 {
 	struct drm_i915_private *dev_priv = wopcm_to_i915(wopcm);
-	u32 huc_agent;
-	u32 mask;
-	int err;
 
 	if (!USES_GUC(dev_priv))
-		return 0;
+		return;
 
 	GEM_BUG_ON(!HAS_GUC(dev_priv));
 	GEM_BUG_ON(!wopcm->guc.size);
 	GEM_BUG_ON(!wopcm->guc.base);
 
-	err = write_and_verify(dev_priv, GUC_WOPCM_SIZE, wopcm->guc.size,
-			       GUC_WOPCM_SIZE_MASK | GUC_WOPCM_SIZE_LOCKED,
-			       GUC_WOPCM_SIZE_LOCKED);
-	if (err)
-		goto err_out;
-
-	huc_agent = USES_HUC(dev_priv) ? HUC_LOADING_AGENT_GUC : 0;
-	mask = GUC_WOPCM_OFFSET_MASK | GUC_WOPCM_OFFSET_VALID | huc_agent;
-	err = write_and_verify(dev_priv, DMA_GUC_WOPCM_OFFSET,
-			       wopcm->guc.base | huc_agent, mask,
-			       GUC_WOPCM_OFFSET_VALID);
-	if (err)
-		goto err_out;
-
-	return 0;
-
-err_out:
-	DRM_ERROR("Failed to init WOPCM registers:\n");
-	DRM_ERROR("DMA_GUC_WOPCM_OFFSET=%#x\n",
-		  I915_READ(DMA_GUC_WOPCM_OFFSET));
-	DRM_ERROR("GUC_WOPCM_SIZE=%#x\n", I915_READ(GUC_WOPCM_SIZE));
+	if (!wopcm->guc.size_locked) {
+		I915_WRITE(GUC_WOPCM_SIZE, wopcm->guc.size &
+					   GUC_WOPCM_SIZE_MASK);
+		wopcm->guc.size_locked = true;
+		GEM_BUG_ON(!I915_READ(GUC_WOPCM_SIZE) & GUC_WOPCM_SIZE_LOCKED);
+	}
 
-	return err;
+	if (!wopcm->guc.base_locked) {
+		I915_WRITE(DMA_GUC_WOPCM_OFFSET,
+			   (GUC_WOPCM_OFFSET_MASK & wopcm->guc.base) |
+			   HUC_LOADING_AGENT_GUC);
+		wopcm->guc.size_locked = true;
+		GEM_BUG_ON(!I915_READ(DMA_GUC_WOPCM_OFFSET) &
+			   GUC_WOPCM_OFFSET_VALID);
+	}
 }
diff --git a/drivers/gpu/drm/i915/intel_wopcm.h b/drivers/gpu/drm/i915/intel_wopcm.h
index 6298910a384c..144232999bfe 100644
--- a/drivers/gpu/drm/i915/intel_wopcm.h
+++ b/drivers/gpu/drm/i915/intel_wopcm.h
@@ -14,18 +14,22 @@
  * @size: Size of overall WOPCM.
  * @guc: GuC WOPCM Region info.
  * @guc.base: GuC WOPCM base which is offset from WOPCM base.
+ * @guc.base_locked: True if base register was locked during partitioning.
  * @guc.size: Size of the GuC WOPCM region.
+ * @guc.size_locked: True if size register was locked during partitioning.
  */
 struct intel_wopcm {
 	u32 size;
 	struct {
 		u32 base;
+		bool base_locked;
 		u32 size;
+		bool size_locked;
 	} guc;
 };
 
 void intel_wopcm_init_early(struct intel_wopcm *wopcm);
 int intel_wopcm_init(struct intel_wopcm *wopcm);
-int intel_wopcm_init_hw(struct intel_wopcm *wopcm);
+void intel_wopcm_init_hw(struct intel_wopcm *wopcm);
 
 #endif
