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

Commit 6918f9ff authored by Pankaj Gupta's avatar Pankaj Gupta
Browse files

msm: kgsl: Add support for gmu wrapper memory region



In some targets, SMMU memory region mapped in middle of GPU region.
Due to this overlapping, when we try to map full memory region of
GPU, request_mem_region will be failed. To avoid that issue, split
GPU memory region and program it in gmu_wrapper.

Change-Id: I735fde1b47161abe690a018c8642e4211a4c12a7
Signed-off-by: default avatarPankaj Gupta <gpankaj@codeaurora.org>
parent 6c24075f
Loading
Loading
Loading
Loading
+40 −3
Original line number Diff line number Diff line
@@ -2993,6 +2993,33 @@ static void adreno_regwrite(struct kgsl_device *device,
	__raw_writel(value, reg);
}

void adreno_read_gmu_wrapper(struct adreno_device *adreno_dev,
		u32 offsetwords, u32 *val)
{
	if (!adreno_dev->gmu_wrapper_virt)
		return;

	*val = __raw_readl(adreno_dev->gmu_wrapper_virt +
			(offsetwords << 2) - adreno_dev->gmu_wrapper_base);
	/* Order this read with respect to the following memory accesses */
	rmb();
}

void adreno_write_gmu_wrapper(struct adreno_device *adreno_dev,
		u32 offsetwords, u32 value)
{
	if (!adreno_dev->gmu_wrapper_virt)
		return;

	/*
	 * ensure previous writes post before this one,
	 * i.e. act like normal writel()
	 */
	wmb();
	__raw_writel(value, adreno_dev->gmu_wrapper_virt +
			(offsetwords << 2) - adreno_dev->gmu_wrapper_base);
}

/*
 * adreno_gmu_fenced_write() - Check if there is a GMU and it is enabled
 * @adreno_dev: Pointer to the Adreno device that owns the GMU
@@ -3367,12 +3394,22 @@ static void adreno_power_stats(struct kgsl_device *device,
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct adreno_busy_data *busy = &adreno_dev->busy_data;
	int64_t adj = 0;
	u64 gpu_busy;
	u64 gpu_busy = 0;
	unsigned int val;

	memset(stats, 0, sizeof(*stats));

	gpu_busy = counter_delta(device, adreno_dev->perfctr_pwr_lo,
		&busy->gpu_busy);
	if (adreno_is_a619_holi(adreno_dev))
		adreno_read_gmu_wrapper(adreno_dev,
			adreno_dev->perfctr_pwr_lo, &val);
	else
		kgsl_regread(device, adreno_dev->perfctr_pwr_lo, &val);

	if (busy->gpu_busy)
		gpu_busy = (val >= busy->gpu_busy) ? val - busy->gpu_busy :
			(~0UL - busy->gpu_busy) + val;

	busy->gpu_busy = val;

	if (gpudev->read_throttling_counters) {
		adj = gpudev->read_throttling_counters(adreno_dev);
+27 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#ifndef __ADRENO_H
#define __ADRENO_H

#include <linux/of.h>
#include "adreno_coresight.h"
#include "adreno_dispatch.h"
#include "adreno_drawctxt.h"
@@ -487,6 +488,8 @@ struct adreno_device {
	unsigned long isense_base;
	unsigned int isense_len;
	void __iomem *isense_virt;
	unsigned long gmu_wrapper_base;
	void __iomem *gmu_wrapper_virt;
	const struct adreno_gpu_core *gpucore;
	struct adreno_firmware fw[2];
	size_t gpmu_cmds_size;
@@ -1124,6 +1127,12 @@ static inline int adreno_is_a650_family(struct adreno_device *adreno_dev)
		rev == ADRENO_REV_A660);
}

static inline int adreno_is_a619_holi(struct adreno_device *adreno_dev)
{
	return of_device_is_compatible(adreno_dev->dev.pdev->dev.of_node,
		"qcom,adreno-gpu-a619-holi");
}

static inline int adreno_is_a620v1(struct adreno_device *adreno_dev)
{
	return (ADRENO_GPUREV(adreno_dev) == ADRENO_REV_A620) &&
@@ -1252,6 +1261,24 @@ static inline void adreno_write_gmureg(struct adreno_device *adreno_dev,
				gpudev->reg_offsets[offset_name], val);
}

/**
 * adreno_read_gmu_wrapper() - Read a GMU wrapper register
 * @adreno_dev: Pointer to the the adreno device
 * @offsetwords: Offset of the wrapper register
 * @val: Register value read is placed here
 */
void adreno_read_gmu_wrapper(struct adreno_device *adreno_dev,
	u32 offsetwords, u32 *val);

/**
 * adreno_write_gmu_wrapper() - write on a GMU wrapper register
 * @adreno_dev: Pointer to the the adreno device
 * @offsetwords: Offset of the wrapper register
 * @val: value to write on wrapper register
 */
void adreno_write_gmu_wrapper(struct adreno_device *adreno_dev,
	u32 offsetwords, u32 value);

/**
 * adreno_gpu_fault() - Return the current state of the GPU
 * @adreno_dev: A pointer to the adreno_device to query
+42 −3
Original line number Diff line number Diff line
@@ -121,10 +121,32 @@ static u32 a615_pwrup_reglist[] = {

static int a6xx_get_cp_init_cmds(struct adreno_device *adreno_dev);

static void a6xx_gmu_wrapper_init(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct resource *res;

	if (adreno_dev->gmu_wrapper_virt)
		return;

	res = platform_get_resource_byname(device->pdev,
		IORESOURCE_MEM, "gmu_wrapper");
	if (!res)
		return;

	adreno_dev->gmu_wrapper_base = res->start - device->reg_phys;
	adreno_dev->gmu_wrapper_virt = devm_ioremap(&device->pdev->dev,
		res->start, resource_size(res));

	if (!adreno_dev->gmu_wrapper_virt)
		dev_warn(device->dev, "gmu_wrapper ioremap failed\n");
}

int a6xx_init(struct adreno_device *adreno_dev)
{
	const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev);

	a6xx_gmu_wrapper_init(adreno_dev);
	adreno_dev->highest_bank_bit = a6xx_core->highest_bank_bit;

	/* If the memory type is DDR 4, override the existing configuration */
@@ -605,10 +627,27 @@ void a6xx_start(struct adreno_device *adreno_dev)
	 * Enable GMU power counter 0 to count GPU busy. This is applicable to
	 * all a6xx targets
	 */
	kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000);
	kgsl_regrmw(device, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20);
	kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1);
	if (adreno_is_a619_holi(adreno_dev)) {
		unsigned int val;

		adreno_write_gmu_wrapper(adreno_dev,
			A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000);
		adreno_read_gmu_wrapper(adreno_dev,
			A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, &val);
		adreno_write_gmu_wrapper(adreno_dev,
			A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0,
			(val & 0xff) | 0x20);
		adreno_write_gmu_wrapper(adreno_dev,
			A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0x1);

	} else {
		kgsl_regwrite(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK,
			0xff000000);
		kgsl_regrmw(device, A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0,
			0xff, 0x20);
		kgsl_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE,
			0x1);
	}
	a6xx_protect_init(adreno_dev);
	/*
	 * We start LM here because we want all the following to be up
+62 −2
Original line number Diff line number Diff line
@@ -923,6 +923,32 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev)
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);

	if (adreno_is_a619_holi(adreno_dev)) {
		u32 val;
		void __iomem *addr = adreno_dev->gmu_wrapper_virt +
				(A6XX_GMU_SPTPRAC_PWR_CLK_STATUS << 2) -
				adreno_dev->gmu_wrapper_base;

		if (!adreno_dev->gmu_wrapper_virt) {
			dev_err(device->dev,
				"invalid gmu_wrapper addr, power on SPTPRAC fail\n");
			return -EINVAL;
		}

		adreno_write_gmu_wrapper(adreno_dev,
			A6XX_GMU_GX_SPTPRAC_POWER_CONTROL,
			SPTPRAC_POWERON_CTRL_MASK);

		if (readl_poll_timeout(addr, val,
			(val & SPTPRAC_POWERON_STATUS_MASK) ==
			SPTPRAC_POWERON_STATUS_MASK, 10,
			10 * 1000)) {
			dev_err(device->dev, "power on SPTPRAC fail\n");
			return -EINVAL;
		}
		return 0;
	}

	if (!gmu_core_gpmu_isenabled(device) ||
			!adreno_has_sptprac_gdsc(adreno_dev))
		return 0;
@@ -952,6 +978,35 @@ void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev)
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);

	if (adreno_is_a619_holi(adreno_dev)) {
		u32 val;
		void __iomem *addr = adreno_dev->gmu_wrapper_virt +
				(A6XX_GMU_SPTPRAC_PWR_CLK_STATUS << 2) -
				adreno_dev->gmu_wrapper_base;

		if (!adreno_dev->gmu_wrapper_virt) {
			dev_err(device->dev,
				"invalid gmu_wrapper addr, power off SPTPRAC fail\n");
			return;
		}

		/* Ensure that retention is on */
		adreno_read_gmu_wrapper(adreno_dev,
			A6XX_GPU_CC_GX_GDSCR, &val);
		adreno_write_gmu_wrapper(adreno_dev,
			A6XX_GPU_CC_GX_GDSCR,
			(val | A6XX_RETAIN_FF_ENABLE_ENABLE_MASK));
		adreno_write_gmu_wrapper(adreno_dev,
			A6XX_GMU_GX_SPTPRAC_POWER_CONTROL,
			SPTPRAC_POWEROFF_CTRL_MASK);
		if (readl_poll_timeout(addr, val,
			(val & SPTPRAC_POWEROFF_STATUS_MASK) ==
			SPTPRAC_POWEROFF_STATUS_MASK, 10,
			10 * 1000))
			dev_err(device->dev, "power off SPTPRAC fail\n");
		return;
	}

	if (!gmu_core_gpmu_isenabled(device) ||
			!adreno_has_sptprac_gdsc(adreno_dev))
		return;
@@ -996,10 +1051,15 @@ bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev)
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	unsigned int val;

	if (!gmu_core_isenabled(device))
	if (gmu_core_isenabled(device))
		gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS,
			&val);
	else if (adreno_is_a619_holi(adreno_dev))
		adreno_read_gmu_wrapper(adreno_dev,
			A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val);
	else
		return true;

	gmu_core_regread(device, A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, &val);
	return !(val & (SPTPRAC_POWER_OFF | SP_CLK_OFF));
}