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

Commit 568aac7b authored by Akhil P Oommen's avatar Akhil P Oommen
Browse files

msm: kgsl: Poll GDSCR to ensure CX collapse



The regulator_is_enabled() API doesn't guarantee that CX gdsc has
collapsed at hardware. There could be a vote on the GDSC from another
subsystem like TZ. So poll the CX GDSCR register to ensure that CX has
indeed collapsed.

Change-Id: Id98c5318d5358b16f4277cb5d96027add63ad801
Signed-off-by: default avatarAkhil P Oommen <akhilpo@codeaurora.org>
parent 84b56d3a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1112,6 +1112,7 @@
/* GPUCC registers */
#define A6XX_GPU_CC_GX_GDSCR                   0x24403
#define A6XX_GPU_CC_GX_DOMAIN_MISC		0x24542
#define A6XX_GPU_CC_CX_GDSCR                   0x2441B

/* GPU RSC sequencer registers */
#define A6XX_GPU_RSCC_RSC_STATUS0_DRV0			0x00004
+13 −0
Original line number Diff line number Diff line
@@ -834,6 +834,18 @@ static bool a6xx_gmu_gx_is_on(struct kgsl_device *device)
	return is_on(val);
}

/*
 * a6xx_gmu_cx_is_on() - Check if CX is on using GPUCC register
 * @device - Pointer to KGSL device struct
 */
static bool a6xx_gmu_cx_is_on(struct kgsl_device *device)
{
	unsigned int val;

	gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, &val);
	return (val & BIT(31));
}

/*
 * a6xx_gmu_sptprac_is_on() - Check if SPTP is on using pwr status register
 * @adreno_dev - Pointer to adreno_device
@@ -1754,6 +1766,7 @@ struct gmu_dev_ops adreno_a6xx_gmudev = {
	.enable_lm = a6xx_gmu_enable_lm,
	.rpmh_gpu_pwrctrl = a6xx_gmu_rpmh_gpu_pwrctrl,
	.gx_is_on = a6xx_gmu_gx_is_on,
	.cx_is_on = a6xx_gmu_cx_is_on,
	.wait_for_lowest_idle = a6xx_gmu_wait_for_lowest_idle,
	.wait_for_gmu_idle = a6xx_gmu_wait_for_idle,
	.ifpc_store = a6xx_gmu_ifpc_store,
+6 −5
Original line number Diff line number Diff line
@@ -1471,8 +1471,9 @@ static int gmu_enable_gdsc(struct gmu_device *gmu)
}

#define CX_GDSC_TIMEOUT	5000	/* ms */
static int gmu_disable_gdsc(struct gmu_device *gmu)
static int gmu_disable_gdsc(struct kgsl_device *device)
{
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	int ret;
	unsigned long t;

@@ -1494,13 +1495,13 @@ static int gmu_disable_gdsc(struct gmu_device *gmu)
	 */
	t = jiffies + msecs_to_jiffies(CX_GDSC_TIMEOUT);
	do {
		if (!regulator_is_enabled(gmu->cx_gdsc))
		if (!gmu_core_dev_cx_is_on(device))
			return 0;
		usleep_range(10, 100);

	} while (!(time_after(jiffies, t)));

	if (!regulator_is_enabled(gmu->cx_gdsc))
	if (!gmu_core_dev_cx_is_on(device))
		return 0;

	dev_err(&gmu->pdev->dev, "GMU CX gdsc off timeout\n");
@@ -1528,7 +1529,7 @@ static int gmu_suspend(struct kgsl_device *device)
	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CX_GDSC))
		regulator_set_mode(gmu->cx_gdsc, REGULATOR_MODE_IDLE);

	gmu_disable_gdsc(gmu);
	gmu_disable_gdsc(device);

	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CX_GDSC))
		regulator_set_mode(gmu->cx_gdsc, REGULATOR_MODE_NORMAL);
@@ -1703,7 +1704,7 @@ static void gmu_stop(struct kgsl_device *device)

	gmu_dev_ops->rpmh_gpu_pwrctrl(device, GMU_FW_STOP, 0, 0);
	gmu_disable_clks(device);
	gmu_disable_gdsc(gmu);
	gmu_disable_gdsc(device);

	msm_bus_scale_client_update_request(gmu->pcl, 0);
	return;
+11 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/of.h>
@@ -343,6 +343,16 @@ bool gmu_core_dev_gx_is_on(struct kgsl_device *device)
	return true;
}

bool gmu_core_dev_cx_is_on(struct kgsl_device *device)
{
	struct gmu_dev_ops *ops = GMU_DEVICE_OPS(device);

	if (ops && ops->cx_is_on)
		return ops->cx_is_on(device);

	return true;
}

int gmu_core_dev_ifpc_show(struct kgsl_device *device)
{
	struct gmu_dev_ops *ops = GMU_DEVICE_OPS(device);
+3 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */
#ifndef __KGSL_GMU_CORE_H
#define __KGSL_GMU_CORE_H
@@ -138,6 +138,7 @@ struct gmu_dev_ops {
	int (*wait_for_lowest_idle)(struct kgsl_device *device);
	int (*wait_for_gmu_idle)(struct kgsl_device *device);
	bool (*gx_is_on)(struct kgsl_device *device);
	bool (*cx_is_on)(struct kgsl_device *device);
	void (*prepare_stop)(struct kgsl_device *device);
	int (*ifpc_store)(struct kgsl_device *device, unsigned int val);
	unsigned int (*ifpc_show)(struct kgsl_device *device);
@@ -224,6 +225,7 @@ void gmu_core_dev_enable_lm(struct kgsl_device *device);
void gmu_core_dev_snapshot(struct kgsl_device *device,
		struct kgsl_snapshot *snapshot);
bool gmu_core_dev_gx_is_on(struct kgsl_device *device);
bool gmu_core_dev_cx_is_on(struct kgsl_device *device);
int gmu_core_dev_ifpc_show(struct kgsl_device *device);
int gmu_core_dev_ifpc_store(struct kgsl_device *device, unsigned int val);
void gmu_core_dev_prepare_stop(struct kgsl_device *device);