From: Dikshita Agarwal Date: Fri, 22 Aug 2025 05:53:30 +0000 (+0530) Subject: media: iris: vpu3x: Add MNoC low power handshake during hardware power-off X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=93fad55aa996eef17a837ed95b1d621ef05d967b;p=thirdparty%2Fkernel%2Fstable.git media: iris: vpu3x: Add MNoC low power handshake during hardware power-off Add the missing write to AON_WRAPPER_MVP_NOC_LPI_CONTROL before reading the LPI status register. Introduce a handshake loop to ensure MNoC enters low power mode reliably during VPU3 hardware power-off with timeout handling. Fixes: 02083a1e00ae ("media: platform: qcom/iris: add support for vpu33") Cc: stable@vger.kernel.org Tested-by: Neil Armstrong # on SM8650-QRD Tested-by: Neil Armstrong # on SM8650-HDK Reviewed-by: Bryan O'Donoghue Signed-off-by: Dikshita Agarwal Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c index 9b7c9a1495ee2..bfc52eb04ed0e 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c @@ -19,6 +19,9 @@ #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL (WRAPPER_BASE_OFFS + 0x5C) #define REQ_POWER_DOWN_PREP BIT(0) #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS (WRAPPER_BASE_OFFS + 0x60) +#define NOC_LPI_STATUS_DONE BIT(0) /* Indicates the NOC handshake is complete */ +#define NOC_LPI_STATUS_DENY BIT(1) /* Indicates the NOC handshake is denied */ +#define NOC_LPI_STATUS_ACTIVE BIT(2) /* Indicates the NOC is active */ #define WRAPPER_CORE_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x88) #define CORE_CLK_RUN 0x0 @@ -109,7 +112,9 @@ disable_power: static void iris_vpu33_power_off_hardware(struct iris_core *core) { + bool handshake_done = false, handshake_busy = false; u32 reg_val = 0, value, i; + u32 count = 0; int ret; if (iris_vpu3x_hw_power_collapsed(core)) @@ -128,13 +133,36 @@ static void iris_vpu33_power_off_hardware(struct iris_core *core) goto disable_power; } + /* Retry up to 1000 times as recommended by hardware documentation */ + do { + /* set MNoC to low power */ + writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + udelay(15); + + value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS); + + handshake_done = value & NOC_LPI_STATUS_DONE; + handshake_busy = value & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE); + + if (handshake_done || !handshake_busy) + break; + + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + + udelay(15); + + } while (++count < 1000); + + if (!handshake_done && handshake_busy) + dev_err(core->dev, "LPI handshake timeout\n"); + ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS, reg_val, reg_val & BIT(0), 200, 2000); if (ret) goto disable_power; - /* set MNoC to low power, set PD_NOC_QREQ (bit 0) */ - writel(BIT(0), core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); + writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL); writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);