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 <grajagop@codeaurora.org>
Bu işleme şunda yer alıyor:
@@ -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++;
|
||||
}
|
||||
|
||||
if (count == max_tries) {
|
||||
d_vpr_e("Skip PC. Core is not in right state\n");
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
Yeni konuda referans
Bir kullanıcı engelle