瀏覽代碼

video: driver: use readl_relaxed_poll_timeout instead of register_read

Upstream recommends to use readl_relaxed_poll_timeout instead of reading
register in a loop with sleep. So replaced with readl_relaxed_poll_timeout
in all possible places.

Change-Id: Ide1758314128751a6876678d4265bb77c52de25f
Signed-off-by: Govindaraj Rajagopal <[email protected]>
Govindaraj Rajagopal 3 年之前
父節點
當前提交
10a6e51ef2
共有 3 個文件被更改,包括 71 次插入82 次删除
  1. 35 82
      driver/variant/iris2/src/msm_vidc_iris2.c
  2. 2 0
      driver/vidc/inc/venus_hfi.h
  3. 34 0
      driver/vidc/src/venus_hfi.c

+ 35 - 82
driver/variant/iris2/src/msm_vidc_iris2.c

@@ -432,8 +432,7 @@ static int __setup_ucregion_memory_map_iris2(struct msm_vidc_core *vidc_core)
 static int __power_off_iris2_hardware(struct msm_vidc_core *core)
 {
 	int rc = 0, i;
-	u32 value = 0, count = 0;
-	const u32 max_count = 10;
+	u32 value = 0;
 
 	if (core->hw_power_control) {
 		d_vpr_h("%s: hardware power control enabled\n", __func__);
@@ -459,18 +458,9 @@ static int __power_off_iris2_hardware(struct msm_vidc_core *core)
 	 * poll for NoC DMA idle -> HPG 6.1.1
 	 */
 	for (i = 0; i < core->capabilities[NUM_VPP_PIPE].value; i++) {
-		count = 0;
-		do {
-			value = __read_register(core,
-				VCODEC_SS_IDLE_STATUSn + 4*i);
-			if (value & 0x400000)
-				break;
-			else
-				usleep_range(1000, 2000);
-			count++;
-		} while (count < max_count);
-
-		if (count == max_count)
+		rc = __read_register_with_poll_timeout(core, VCODEC_SS_IDLE_STATUSn + 4*i,
+				0x400000, 0x400000, 2000, 20000);
+		if (rc)
 			d_vpr_h("%s: VCODEC_SS_IDLE_STATUSn (%d) is not idle (%#x)\n",
 				__func__, i, value);
 	}
@@ -479,32 +469,20 @@ static int __power_off_iris2_hardware(struct msm_vidc_core *core)
 	rc = __write_register(core, AON_WRAPPER_MVP_NOC_RESET_REQ, 0x3);
 	if (rc)
 		return rc;
-	count = 0;
-	do {
-		value = __read_register(core, AON_WRAPPER_MVP_NOC_RESET_ACK);
-		if ((value & 0x3) == 0x3)
-			break;
-		else
-			usleep_range(100, 200);
-		count++;
-	} while (count < max_count);
-	if (count == max_count)
+
+	rc = __read_register_with_poll_timeout(core, AON_WRAPPER_MVP_NOC_RESET_ACK,
+			0x3, 0x3, 200, 2000);
+	if (rc)
 		d_vpr_h("%s: AON_WRAPPER_MVP_NOC_RESET assert failed\n", __func__);
 
 	/* De-assert partial reset on MSF interface and wait for ACK */
 	rc = __write_register(core, AON_WRAPPER_MVP_NOC_RESET_REQ, 0x0);
 	if (rc)
 		return rc;
-	count = 0;
-	do {
-		value = __read_register(core, AON_WRAPPER_MVP_NOC_RESET_ACK);
-		if ((value & 0x3) == 0x0)
-			break;
-		else
-			usleep_range(100, 200);
-		count++;
-	} while (count < max_count);
-	if (count == max_count)
+
+	rc = __read_register_with_poll_timeout(core, AON_WRAPPER_MVP_NOC_RESET_ACK,
+			0x3, 0x0, 200, 2000);
+	if (rc)
 		d_vpr_h("%s: AON_WRAPPER_MVP_NOC_RESET de-assert failed\n", __func__);
 
 	/*
@@ -540,8 +518,6 @@ disable_power:
 static int __power_off_iris2_controller(struct msm_vidc_core *core)
 {
 	int rc = 0;
-	u32 value = 0, count = 0;
-	const u32 max_count = 10;
 
 	/*
 	 * mask fal10_veto QLPAC error since fal10_veto can go 1
@@ -556,33 +532,20 @@ static int __power_off_iris2_controller(struct msm_vidc_core *core)
 			0x1, BIT(0));
 	if (rc)
 		return rc;
-	count = 0;
-	do {
-		value = __read_register(core, AON_WRAPPER_MVP_NOC_LPI_STATUS);
-		if ((value & 0x1) == 0x1)
-			break;
-		else
-			usleep_range(100, 200);
-		count++;
-	} while (count < max_count);
-	if (count == max_count)
+
+	rc = __read_register_with_poll_timeout(core, AON_WRAPPER_MVP_NOC_LPI_STATUS,
+			0x1, 0x1, 200, 2000);
+	if (rc)
 		d_vpr_h("%s: AON_WRAPPER_MVP_NOC_LPI_CONTROL failed\n", __func__);
 
 	/* Set Debug bridge Low power */
 	rc = __write_register(core, WRAPPER_DEBUG_BRIDGE_LPI_CONTROL_IRIS2, 0x7);
 	if (rc)
 		return rc;
-	count = 0;
-	do {
-		value = __read_register(core,
-			WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2);
-		if ((value & 0x7) == 0x7)
-			break;
-		else
-			usleep_range(100, 200);
-		count++;
-	} while (count < max_count);
-	if (count == max_count)
+
+	rc = __read_register_with_poll_timeout(core, WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2,
+			0x7, 0x7, 200, 2000);
+	if (rc)
 		d_vpr_h("%s: debug bridge low power failed\n", __func__);
 
 	/* Debug bridge LPI release */
@@ -590,17 +553,9 @@ static int __power_off_iris2_controller(struct msm_vidc_core *core)
 	if (rc)
 		return rc;
 
-	count = 0;
-	do {
-		value = __read_register(core,
-			WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2);
-		if (value == 0x0)
-			break;
-		else
-			usleep_range(100, 200);
-		count++;
-	} while (count < max_count);
-	if (count == max_count)
+	rc = __read_register_with_poll_timeout(core, WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2,
+			0xffffffff, 0x0, 200, 2000);
+	if (rc)
 		d_vpr_h("%s: debug bridge release failed\n", __func__);
 
 	/* power down process */
@@ -767,8 +722,6 @@ static int __prepare_pc_iris2(struct msm_vidc_core *vidc_core)
 	int rc = 0;
 	u32 wfi_status = 0, idle_status = 0, pc_ready = 0;
 	u32 ctrl_status = 0;
-	int count = 0;
-	const int max_tries = 10;
 	struct msm_vidc_core *core = vidc_core;
 
 	if (!core) {
@@ -797,25 +750,25 @@ static int __prepare_pc_iris2(struct msm_vidc_core *vidc_core)
 		goto skip_power_off;
 	}
 
-	while (count < max_tries) {
-		wfi_status = BIT(0) & __read_register(core,
-				WRAPPER_TZ_CPU_STATUS);
-		ctrl_status = __read_register(core,
-				CTRL_STATUS_IRIS2);
-		if (wfi_status && (ctrl_status & CTRL_STATUS_PC_READY_IRIS2))
-			break;
-		usleep_range(150, 250);
-		count++;
+	rc = __read_register_with_poll_timeout(core, CTRL_STATUS_IRIS2,
+			CTRL_STATUS_PC_READY_IRIS2, CTRL_STATUS_PC_READY_IRIS2, 250, 2500);
+	if (rc) {
+		d_vpr_e("%s: Skip PC. Ctrl status not set\n", __func__);
+		goto skip_power_off;
 	}
 
-	if (count == max_tries) {
-		d_vpr_e("Skip PC. Core is not in right state\n");
+	rc = __read_register_with_poll_timeout(core, WRAPPER_TZ_CPU_STATUS,
+			BIT(0), 0x1, 250, 2500);
+	if (rc) {
+		d_vpr_e("%s: Skip PC. Wfi status not set\n", __func__);
 		goto skip_power_off;
 	}
-
 	return rc;
 
 skip_power_off:
+	wfi_status = BIT(0) & __read_register(core, WRAPPER_TZ_CPU_STATUS);
+	ctrl_status = __read_register(core, CTRL_STATUS_IRIS2);
+
 	d_vpr_e("Skip PC, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n",
 		wfi_status, idle_status, pc_ready, ctrl_status);
 	return -EAGAIN;

+ 2 - 0
driver/vidc/inc/venus_hfi.h

@@ -67,6 +67,8 @@ int __write_register_masked(struct msm_vidc_core *core,
 int __write_register(struct msm_vidc_core *core,
 		u32 reg, u32 value);
 int __read_register(struct msm_vidc_core *core, u32 reg);
+int __read_register_with_poll_timeout(struct msm_vidc_core *core,
+	u32 reg, u32 mask, u32 exp_val, u32 sleep_us, u32 timeout_us);
 int __iface_cmdq_write(struct msm_vidc_core *core,
 	void *pkt);
 int __iface_msgq_read(struct msm_vidc_core *core, void *pkt);

+ 34 - 0
driver/vidc/src/venus_hfi.c

@@ -14,6 +14,7 @@
 #include <linux/firmware.h>
 #include <linux/qcom_scm.h>
 #include <linux/soc/qcom/mdt_loader.h>
+#include <linux/iopoll.h>
 
 #include "venus_hfi.h"
 #include "msm_vidc_core.h"
@@ -335,6 +336,39 @@ int __read_register(struct msm_vidc_core *core, u32 reg)
 	return rc;
 }
 
+int __read_register_with_poll_timeout(struct msm_vidc_core *core,
+	u32 reg, u32 mask, u32 exp_val, u32 sleep_us, u32 timeout_us)
+{
+	int rc = 0;
+	u32 val = 0;
+	u8 *addr;
+
+	if (!core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!core->power_enabled) {
+		d_vpr_e("%s failed: Power is OFF\n", __func__);
+		return -EINVAL;
+	}
+
+	addr = (u8 *)core->register_base_addr + reg;
+
+	rc = readl_relaxed_poll_timeout(addr, val, ((val & mask) == exp_val), sleep_us, timeout_us);
+	/*
+	 * Memory barrier to make sure value is read correctly from the
+	 * register.
+	 */
+	rmb();
+	d_vpr_l(
+		"regread(%pK + %#x) = %#x. rc %d, mask %#x, exp_val %#x, cond %u, sleep %u, timeout %u\n",
+		core->register_base_addr, reg, val, rc, mask, exp_val,
+		((val & mask) == exp_val), sleep_us, timeout_us);
+
+	return rc;
+}
+
 static void __schedule_power_collapse_work(struct msm_vidc_core *core)
 {
 	if (!core || !core->capabilities) {