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

Commit 608fd900 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Support GFX CPR control in GPU driver"

parents 3cb56f01 500ef6e6
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -264,8 +264,14 @@
		label = "kgsl-gmu";
		compatible = "qcom,gpu-gmu";

		reg = <0x506a000 0x30000>, <0xb200000 0x300000>;
		reg-names = "kgsl_gmu_reg", "kgsl_gmu_pdc_reg";
		reg =
			<0x506a000 0x31000>,
			<0xb200000 0x300000>,
			<0xc200000 0x10000>;
		reg-names =
			"kgsl_gmu_reg",
			"kgsl_gmu_pdc_reg",
			"kgsl_gmu_cpr_reg";

		interrupts = <0 304 0>, <0 305 0>;
		interrupt-names = "kgsl_hfi_irq", "kgsl_gmu_irq";
+6 −0
Original line number Diff line number Diff line
@@ -965,6 +965,10 @@
#define A6XX_RSCC_TCS2_DRV0_STATUS                      0x23A16
#define A6XX_RSCC_TCS3_DRV0_STATUS                      0x23B7E


/* CPR controller */
#define A6XX_GPU_CPR_FSM_CTL				0x26801

/* GPU PDC sequencer registers in AOSS.RPMh domain */
#define	PDC_GPU_ENABLE_PDC			0x21140
#define PDC_GPU_SEQ_START_ADDR			0x21148
@@ -982,5 +986,7 @@
#define PDC_GPU_TCS1_CMD0_DATA			0x21577
#define PDC_GPU_SEQ_MEM_0			0xA0000

/* GFX rail CPR registers in AOSS.CPR domain */
#define CPR_CPRF_CPRF5_CTRL			0x1801
#endif /* _A6XX_REG_H */
+6 −0
Original line number Diff line number Diff line
@@ -1161,6 +1161,12 @@ static inline int adreno_is_a630v1(struct adreno_device *adreno_dev)
		(ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 0);
}

static inline int adreno_is_a630v2(struct adreno_device *adreno_dev)
{
	return (ADRENO_GPUREV(adreno_dev) == ADRENO_REV_A630) &&
		(ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 1);
}

/*
 * adreno_checkreg_off() - Checks the validity of a register enum
 * @adreno_dev:		Pointer to adreno device
+41 −2
Original line number Diff line number Diff line
@@ -871,6 +871,16 @@ static int _load_firmware(struct kgsl_device *device, const char *fwfile,

#define RSC_CMD_OFFSET 2
#define PDC_CMD_OFFSET 4
static void _regread(void __iomem *regbase,
		unsigned int offsetwords, unsigned int *value)
{
	void __iomem *reg;

	reg = regbase + (offsetwords << 2);
	*value = __raw_readl(reg);
	/* Ensure read completes */
	rmb();
}

static void _regwrite(void __iomem *regbase,
		unsigned int offsetwords, unsigned int value)
@@ -1387,6 +1397,8 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)
{
	struct gmu_device *gmu = &device->gmu;
	struct device *dev = &gmu->pdev->dev;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	unsigned int tmp;
	int val;

	kgsl_gmu_regread(device, A6XX_GPU_CC_GX_DOMAIN_MISC, &val);
@@ -1416,6 +1428,19 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)

	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0);

	/* Turn on GFX rail CPR */
	if (adreno_is_a630v2(adreno_dev)) {
		_regread(gmu->cpr_reg_virt, CPR_CPRF_CPRF5_CTRL, &tmp);
		tmp |= BIT(2);
		_regwrite(gmu->cpr_reg_virt, CPR_CPRF_CPRF5_CTRL, tmp);

		kgsl_gmu_regread(device, A6XX_GPU_CPR_FSM_CTL, &tmp);
		tmp |= BIT(0);
		kgsl_gmu_regwrite(device, A6XX_GPU_CPR_FSM_CTL, tmp);
		/* Ensure write happens before exit the function */
		wmb();
	}

	/* Enable the power counter because it was disabled before slumber */
	kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);

@@ -1428,9 +1453,23 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)
static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)
{
	struct gmu_device *gmu = &device->gmu;
	const struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	unsigned int tmp;
	int val;

	/* Turn off GFX rail CPR */
	if (adreno_is_a630v2(adreno_dev)) {
		_regread(gmu->cpr_reg_virt, CPR_CPRF_CPRF5_CTRL, &tmp);
		tmp &= ~BIT(2);
		_regwrite(gmu->cpr_reg_virt, CPR_CPRF_CPRF5_CTRL, tmp);

		kgsl_gmu_regread(device, A6XX_GPU_CPR_FSM_CTL, &tmp);
		tmp &= ~BIT(0);
		kgsl_gmu_regwrite(device, A6XX_GPU_CPR_FSM_CTL, tmp);
		/* Ensure write completes before starting sleep seq */
		wmb();
	}

	/* RSC sleep sequence */
	kgsl_gmu_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 1);
@@ -1942,7 +1981,7 @@ static int a6xx_gmu_suspend(struct kgsl_device *device)
	a6xx_sptprac_disable(adreno_dev);

	/* Disconnect GPU from BUS. Clear and reconnected after reset */
	adreno_vbif_clear_pending_transactions(device);
	/* adreno_vbif_clear_pending_transactions(device); */
	/* Unnecessary: a6xx_soft_reset(adreno_dev); */

	/* Check no outstanding RPMh voting */
+16 −5
Original line number Diff line number Diff line
@@ -862,7 +862,7 @@ static int gmu_pwrlevel_probe(struct gmu_device *gmu, struct device_node *node)
	return 0;
}

static int gmu_reg_probe(struct gmu_device *gmu, const char *name, bool is_gmu)
static int gmu_reg_probe(struct gmu_device *gmu, const char *name)
{
	struct resource *res;

@@ -880,7 +880,7 @@ static int gmu_reg_probe(struct gmu_device *gmu, const char *name, bool is_gmu)
		return -EINVAL;
	}

	if (is_gmu) {
	if (!strcmp(name, "kgsl_gmu_reg")) {
		gmu->reg_phys = res->start;
		gmu->reg_len = resource_size(res);
		gmu->reg_virt = devm_ioremap(&gmu->pdev->dev, res->start,
@@ -891,13 +891,20 @@ static int gmu_reg_probe(struct gmu_device *gmu, const char *name, bool is_gmu)
			return -ENODEV;
		}

	} else {
	} else if (!strcmp(name, "kgsl_gmu_pdc_reg")) {
		gmu->pdc_reg_virt = devm_ioremap(&gmu->pdev->dev, res->start,
				resource_size(res));
		if (gmu->pdc_reg_virt == NULL) {
			dev_err(&gmu->pdev->dev, "PDC regs ioremap failed\n");
			return -ENODEV;
		}
	} else if (!strcmp(name, "kgsl_gmu_cpr_reg")) {
		gmu->cpr_reg_virt = devm_ioremap(&gmu->pdev->dev, res->start,
				resource_size(res));
		if (gmu->cpr_reg_virt == NULL) {
			dev_err(&gmu->pdev->dev, "CPR regs ioremap failed\n");
			return -ENODEV;
		}
	}

	return 0;
@@ -1118,11 +1125,15 @@ int gmu_probe(struct kgsl_device *device)
	mem_addr = gmu->hfi_mem;

	/* Map and reserve GMU CSRs registers */
	ret = gmu_reg_probe(gmu, "kgsl_gmu_reg", true);
	ret = gmu_reg_probe(gmu, "kgsl_gmu_reg");
	if (ret)
		goto error;

	ret = gmu_reg_probe(gmu, "kgsl_gmu_pdc_reg");
	if (ret)
		goto error;

	ret = gmu_reg_probe(gmu, "kgsl_gmu_pdc_reg", false);
	ret = gmu_reg_probe(gmu, "kgsl_gmu_cpr_reg");
	if (ret)
		goto error;

Loading