Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c9478c7 authored by Kyle Piefer's avatar Kyle Piefer
Browse files

msm: kgsl: Use proper check for idle



The sequence to check for GMU idle is changed.
The new sequence is to check GPUBusyIgnAHB, then
do notify slumber, then check CXGXCPUBusyIgnAHB.
Also check for nonzero error case instead of 0
when calling wait_for_gmu_idle().

Additionally, check for the proper slumber value and
write a register to make GMU not busy before reading
status. Also remove a redundant slumber check.

CRs-Fixed: 2017390
Change-Id: I5ad8f7af941ebe08f9ce41ea9c68eae0c8d3c47b
Signed-off-by: default avatarKyle Piefer <kpiefer@codeaurora.org>
parent 16496105
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -678,6 +678,7 @@
#define A6XX_GMU_DCVS_RETURN			0x1CBFF
#define A6XX_GMU_CM3_SYSRESET			0x1F800
#define A6XX_GMU_CM3_BOOT_CONFIG		0x1F801
#define A6XX_GMU_CM3_FW_BUSY			0x1F81A
#define A6XX_GMU_CM3_FW_INIT_RESULT		0x1F81C
#define A6XX_GMU_PWR_COL_INTER_FRAME_CTRL	0x1F8C0
#define A6XX_GMU_PWR_COL_INTER_FRAME_HYST	0x1F8C1
+3 −8
Original line number Diff line number Diff line
@@ -1302,13 +1302,8 @@ static int a6xx_wait_for_gmu_idle(struct adreno_device *adreno_dev)
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct gmu_device *gmu = &device->gmu;

	if (timed_poll_check(device, A6XX_GMU_RPMH_POWER_STATE,
		gmu->idle_level, GMU_START_TIMEOUT, 0xf)) {
		dev_err(&gmu->pdev->dev,
			"GMU is not going to powerstate %d\n",
			gmu->idle_level);
		return -ETIMEDOUT;
	}
	/* TODO: Remove this register write when firmware is updated */
	kgsl_gmu_regwrite(device, A6XX_GMU_CM3_FW_BUSY, 0);

	if (timed_poll_check(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS,
			0, GMU_START_TIMEOUT, CXGXCPUBUSYIGNAHB)) {
+19 −4
Original line number Diff line number Diff line
@@ -1369,24 +1369,39 @@ int gmu_start(struct kgsl_device *device)
	return ret;
}

#define GMU_IDLE_TIMEOUT	10 /* ms */

/* Caller shall ensure GPU is ready for SLUMBER */
void gmu_stop(struct kgsl_device *device)
{
	struct gmu_device *gmu = &device->gmu;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	unsigned long t;
	bool idle = false;

	if (!test_bit(GMU_CLK_ON, &gmu->flags))
		return;

	if (gpudev->wait_for_gmu_idle &&
		!gpudev->wait_for_gmu_idle(adreno_dev)) {
		dev_err(&gmu->pdev->dev, "Failure to stop gmu");
		return;
	if (gpudev->hw_isidle) {
		t = jiffies + msecs_to_jiffies(GMU_IDLE_TIMEOUT);
		while (!time_after(jiffies, t)) {
			if (gpudev->hw_isidle(adreno_dev)) {
				idle = true;
				break;
			}
			cpu_relax();
		}
	}

	gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_NOTIFY_SLUMBER, 0, 0);

	if (!idle || (gpudev->wait_for_gmu_idle &&
			gpudev->wait_for_gmu_idle(adreno_dev))) {
		dev_err(&gmu->pdev->dev, "Failure to stop GMU");
		return;
	}

	/* Pending message in all queues are abandoned */
	hfi_stop(gmu);
	clear_bit(GMU_HFI_ON, &gmu->flags);
+1 −1
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ enum gpu_idle_level {
	GPU_HW_NAP = 0x4,
	GPU_HW_MIN_VOLT = 0x5,
	GPU_HW_MIN_DDR = 0x6,
	GPU_HW_SLUMBER = 0xF
	GPU_HW_SLUMBER = 0x7
};

/**