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

Commit a30d897c authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Add support for RSCC register section"

parents 357f309d 9d8bfa8d
Loading
Loading
Loading
Loading
+25 −18
Original line number Diff line number Diff line
@@ -1029,7 +1029,6 @@
#define A6XX_GMU_AO_RGMU_GLM_HW_CRC_DISABLE	0x23B82

/* GMU RSC control registers */
#define A6XX_GPU_RSCC_RSC_STATUS0_DRV0		0x23404
#define A6XX_GMU_RSCC_CONTROL_REQ		0x23B07
#define A6XX_GMU_RSCC_CONTROL_ACK		0x23B08

@@ -1042,23 +1041,24 @@
#define A6XX_GPU_CC_GX_DOMAIN_MISC		0x24542

/* GPU RSC sequencer registers */
#define	A6XX_RSCC_PDC_SEQ_START_ADDR			0x23408
#define A6XX_RSCC_PDC_MATCH_VALUE_LO			0x23409
#define A6XX_RSCC_PDC_MATCH_VALUE_HI			0x2340A
#define A6XX_RSCC_PDC_SLAVE_ID_DRV0			0x2340B
#define A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR			0x2340D
#define A6XX_RSCC_HIDDEN_TCS_CMD0_DATA			0x2340E
#define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0	0x23482
#define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0	0x23483
#define A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0		0x23489
#define A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0		0x2348C
#define A6XX_RSCC_OVERRIDE_START_ADDR			0x23500
#define A6XX_RSCC_SEQ_BUSY_DRV0				0x23501
#define A6XX_RSCC_SEQ_MEM_0_DRV0			0x23580
#define A6XX_RSCC_TCS0_DRV0_STATUS			0x23746
#define A6XX_RSCC_TCS1_DRV0_STATUS                      0x237EE
#define A6XX_RSCC_TCS2_DRV0_STATUS                      0x23896
#define A6XX_RSCC_TCS3_DRV0_STATUS                      0x2393E
#define A6XX_GPU_RSCC_RSC_STATUS0_DRV0			0x00004
#define A6XX_RSCC_PDC_SEQ_START_ADDR			0x00008
#define A6XX_RSCC_PDC_MATCH_VALUE_LO			0x00009
#define A6XX_RSCC_PDC_MATCH_VALUE_HI			0x0000A
#define A6XX_RSCC_PDC_SLAVE_ID_DRV0			0x0000B
#define A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR			0x0000D
#define A6XX_RSCC_HIDDEN_TCS_CMD0_DATA			0x0000E
#define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0	0x00082
#define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0	0x00083
#define A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0		0x00089
#define A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0		0x0008C
#define A6XX_RSCC_OVERRIDE_START_ADDR			0x00100
#define A6XX_RSCC_SEQ_BUSY_DRV0				0x00101
#define A6XX_RSCC_SEQ_MEM_0_DRV0			0x00180
#define A6XX_RSCC_TCS0_DRV0_STATUS			0x00346
#define A6XX_RSCC_TCS1_DRV0_STATUS                      0x003EE
#define A6XX_RSCC_TCS2_DRV0_STATUS                      0x00496
#define A6XX_RSCC_TCS3_DRV0_STATUS                      0x0053E

/* GPU PDC sequencer registers in AOSS.RPMh domain */
#define PDC_GPU_ENABLE_PDC			0x1140
@@ -1095,6 +1095,13 @@
 */
#define PDC_GPU_SEQ_MEM_0			0x0

/*
 * Legacy RSCC register range was a part of the GMU register space
 * now we are using a separate section for RSCC regsiters. Add the
 * offset for backward compatibility.
 */
#define RSCC_OFFSET_LEGACY			0x23400

/* RGMU(PCC) registers in A6X_GMU_CX_0_NON_CONTEXT_DEC domain */
#define A6XX_RGMU_CX_INTR_GEN_EN		0x1F80F
#define A6XX_RGMU_CX_RGMU_TIMER0		0x1F834
+38 −0
Original line number Diff line number Diff line
@@ -1210,6 +1210,25 @@ static void adreno_cx_misc_probe(struct kgsl_device *device)
					res->start, adreno_dev->cx_misc_len);
}

static void adreno_rscc_probe(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct resource *res;

	res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM,
						"rscc");

	if (res == NULL)
		return;

	adreno_dev->rscc_base = res->start - device->reg_phys;
	adreno_dev->rscc_len = resource_size(res);
	adreno_dev->rscc_virt = devm_ioremap(device->dev, res->start,
						adreno_dev->rscc_len);
	if (adreno_dev->rscc_virt == NULL)
		dev_warn(device->dev, "rscc ioremap failed\n");
}

static void adreno_efuse_read_soc_hw_rev(struct adreno_device *adreno_dev)
{
	unsigned int val;
@@ -1335,6 +1354,7 @@ static int adreno_probe(struct platform_device *pdev)
	/* Probe for the optional CX_MISC block */
	adreno_cx_misc_probe(device);

	adreno_rscc_probe(device);
	/*
	 * qcom,iommu-secure-id is used to identify MMUs that can handle secure
	 * content but that is only part of the story - the GPU also has to be
@@ -3205,6 +3225,24 @@ void adreno_cx_misc_regread(struct adreno_device *adreno_dev,
	 */
	rmb();
}
void adreno_rscc_regread(struct adreno_device *adreno_dev,
	unsigned int offsetwords, unsigned int *value)
{
	unsigned int rscc_offset;

	rscc_offset = (offsetwords << 2);
	if (!adreno_dev->rscc_virt ||
		(rscc_offset >= adreno_dev->rscc_len))
		return;

	*value =  __raw_readl(adreno_dev->rscc_virt + rscc_offset);

	/*
	 * ensure this read finishes before the next one.
	 * i.e. act like normal readl()
	 */
	rmb();
}

void adreno_cx_misc_regwrite(struct adreno_device *adreno_dev,
	unsigned int offsetwords, unsigned int value)
+8 −0
Original line number Diff line number Diff line
@@ -441,6 +441,9 @@ enum gpu_coresight_sources {
 * @gmem_size: GMEM size
 * @cx_misc_len: Length of the CX MISC register block
 * @cx_misc_virt: Pointer where the CX MISC block is mapped
 * @rscc_base: Base physical address of the RSCC
 * @rscc_len: Length of the RSCC register block
 * @rscc_virt: Pointer where RSCC block is mapped
 * @gpucore: Pointer to the adreno_gpu_core structure
 * @pfp_fw: Buffer which holds the pfp ucode
 * @pfp_fw_size: Size of pfp ucode buffer
@@ -523,6 +526,9 @@ struct adreno_device {
	void __iomem *cx_dbgc_virt;
	unsigned int cx_misc_len;
	void __iomem *cx_misc_virt;
	unsigned long rscc_base;
	unsigned int rscc_len;
	void __iomem *rscc_virt;
	const struct adreno_gpu_core *gpucore;
	struct adreno_firmware fw[2];
	size_t gpmu_cmds_size;
@@ -1182,6 +1188,8 @@ void adreno_cx_misc_regwrite(struct adreno_device *adreno_dev,
void adreno_cx_misc_regrmw(struct adreno_device *adreno_dev,
		unsigned int offsetwords,
		unsigned int mask, unsigned int bits);
void adreno_rscc_regread(struct adreno_device *adreno_dev,
		unsigned int offsetwords, unsigned int *value);


#define ADRENO_TARGET(_name, _id) \
+33 −0
Original line number Diff line number Diff line
@@ -135,6 +135,39 @@ static inline int timed_poll_check(struct kgsl_device *device,
	return -ETIMEDOUT;
}

static inline int timed_poll_check_rscc(struct kgsl_device *device,
		unsigned int offset, unsigned int expected_ret,
		unsigned int timeout, unsigned int mask)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	unsigned long t;
	unsigned int value;

	t = jiffies + msecs_to_jiffies(timeout);

	do {
		if (adreno_is_a650(adreno_dev))
			adreno_rscc_regread(adreno_dev, offset, &value);
		else
			gmu_core_regread(device, offset + RSCC_OFFSET_LEGACY,
						&value);
		if ((value & mask) == expected_ret)
			return 0;
		/* Wait 100us to reduce unnecessary AHB bus traffic */
		usleep_range(10, 100);
	} while (!time_after(jiffies, t));

	/* Double check one last time */
	if (adreno_is_a650(adreno_dev))
		adreno_rscc_regread(adreno_dev, offset, &value);
	else
		gmu_core_regread(device, offset + RSCC_OFFSET_LEGACY, &value);
	if ((value & mask) == expected_ret)
		return 0;

	return -ETIMEDOUT;
}

/*
 * read_AO_counter() - Returns the 64bit always on counter value
 *
+41 −41
Original line number Diff line number Diff line
@@ -81,8 +81,8 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device)
	struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct resource *res_pdc, *res_cfg, *res_seq;
	void __iomem *cfg = NULL, *seq = NULL;
	unsigned int cfg_offset, seq_offset;
	void __iomem *cfg = NULL, *seq = NULL, *rscc;
	unsigned int cfg_offset, seq_offset, rscc_offset;

	/* Offsets from the base PDC (if no PDC subsections in the DTSI) */
	if (adreno_is_a640v2(adreno_dev)) {
@@ -93,6 +93,10 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device)
		seq_offset = 0x280000;
	}

	if (adreno_is_a650(adreno_dev))
		rscc = adreno_dev->rscc_virt;
	else
		rscc = device->gmu_core.reg_virt + 0x23000;
	/*
	 * Older A6x platforms specified PDC registers in the DT using a
	 * single base pointer that encompassed the entire PDC range. Current
@@ -111,7 +115,6 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device)
			"kgsl_gmu_pdc_cfg");
	res_seq = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM,
			"kgsl_gmu_pdc_seq");

	/*
	 * Map the starting address for pdc_cfg programming. If the pdc_cfg
	 * resource is not available use an offset from the base PDC resource.
@@ -142,37 +145,33 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device)
	}

	/* Disable SDE clock gating */
	gmu_core_regwrite(device, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));
	_regwrite(rscc, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));

	/* Setup RSC PDC handshake for sleep and wakeup */
	gmu_core_regwrite(device, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1);
	gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0);
	gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0);
	gmu_core_regwrite(device,
			A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0);
	gmu_core_regwrite(device,
			A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0);
	gmu_core_regwrite(device,
			A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2,
	_regwrite(rscc, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1);
	_regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0);
	_regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0);
	_regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0);
	_regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0);
	_regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2,
			0x80000000);
	gmu_core_regwrite(device,
			A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2,
	_regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2,
			0);
	gmu_core_regwrite(device, A6XX_RSCC_OVERRIDE_START_ADDR, 0);
	gmu_core_regwrite(device, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520);
	gmu_core_regwrite(device, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510);
	gmu_core_regwrite(device, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514);
	_regwrite(rscc, A6XX_RSCC_OVERRIDE_START_ADDR, 0);
	_regwrite(rscc, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520);
	_regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510);
	_regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514);

	/* Enable timestamp event for v1 only */
	if (adreno_is_a630v1(adreno_dev))
		gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
		_regwrite(rscc, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);

	/* Load RSC sequencer uCode for sleep and wakeup */
	gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0);
	gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7);
	gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1);
	gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2);
	gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8);
	_regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0);
	_regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7);
	_regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1);
	_regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2);
	_regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8);

	/* Load PDC sequencer uCode for power up and power down sequence */
	_regwrite(seq, PDC_GPU_SEQ_MEM_0, 0xFEBEA1E1);
@@ -389,7 +388,7 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device)
		return -EINVAL;
	}

	if (timed_poll_check(device,
	if (timed_poll_check_rscc(device,
			A6XX_RSCC_SEQ_BUSY_DRV0,
			0,
			GPU_START_TIMEOUT,
@@ -425,20 +424,21 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)

	/* RSC sleep sequence is different on v1 */
	if (adreno_is_a630v1(adreno_dev))
		gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
		gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 +
						RSCC_OFFSET_LEGACY, 1);

	gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 1);
	/* Make sure the request completes before continuing */
	wmb();

	if (adreno_is_a630v1(adreno_dev))
		ret = timed_poll_check(device,
		ret = timed_poll_check_rscc(device,
				A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0,
				BIT(0),
				GPU_START_TIMEOUT,
				BIT(0));
	else
		ret = timed_poll_check(device,
		ret = timed_poll_check_rscc(device,
				A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
				BIT(16),
				GPU_START_TIMEOUT,
@@ -452,11 +452,11 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device)
	/* Read to clear the timestamp valid signal. Don't care what we read. */
	if (adreno_is_a630v1(adreno_dev)) {
		gmu_core_regread(device,
				A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0,
				&ret);
				A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 +
					RSCC_OFFSET_LEGACY, &ret);
		gmu_core_regread(device,
				A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0,
				&ret);
				A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 +
					RSCC_OFFSET_LEGACY, &ret);
	}

	gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0);
@@ -700,14 +700,14 @@ static int a6xx_complete_rpmh_votes(struct kgsl_device *device)
	if (!gmu_core_isenabled(device))
		return ret;

	ret |= timed_poll_check(device, A6XX_RSCC_TCS0_DRV0_STATUS, BIT(0),
			GPU_RESET_TIMEOUT, BIT(0));
	ret |= timed_poll_check(device, A6XX_RSCC_TCS1_DRV0_STATUS, BIT(0),
			GPU_RESET_TIMEOUT, BIT(0));
	ret |= timed_poll_check(device, A6XX_RSCC_TCS2_DRV0_STATUS, BIT(0),
			GPU_RESET_TIMEOUT, BIT(0));
	ret |= timed_poll_check(device, A6XX_RSCC_TCS3_DRV0_STATUS, BIT(0),
			GPU_RESET_TIMEOUT, BIT(0));
	ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS0_DRV0_STATUS,
			BIT(0), GPU_RESET_TIMEOUT, BIT(0));
	ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS1_DRV0_STATUS,
			BIT(0), GPU_RESET_TIMEOUT, BIT(0));
	ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS2_DRV0_STATUS,
			BIT(0), GPU_RESET_TIMEOUT, BIT(0));
	ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS3_DRV0_STATUS,
			BIT(0), GPU_RESET_TIMEOUT, BIT(0));

	return ret;
}