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

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

Merge "msm: kgsl: Add support for gmu wrapper memory region"

parents ad03b037 6918f9ff
Loading
Loading
Loading
Loading
+40 −3
Original line number Diff line number Diff line
@@ -3004,6 +3004,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
@@ -3378,12 +3405,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));
}