Commit 93fad55a authored by Dikshita Agarwal's avatar Dikshita Agarwal Committed by Mauro Carvalho Chehab
Browse files

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: 02083a1e ("media: platform: qcom/iris: add support for vpu33")
Cc: stable@vger.kernel.org
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-QRD
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-HDK
Reviewed-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: default avatarDikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: default avatarBryan O'Donoghue <bod@kernel.org>
Signed-off-by: default avatarHans Verkuil <hverkuil+cisco@kernel.org>
parent fde38008
Loading
Loading
Loading
Loading
+30 −2
Original line number Diff line number Diff line
@@ -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 @@ static void iris_vpu3_power_off_hardware(struct iris_core *core)

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);