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

This commit is contained in:
qctecmdr 2020-08-02 21:38:52 -07:00 • committed by Gerrit - the friendly Code Review server
commit deefc4a259
4 changed files with 171 additions and 8 deletions

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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));
}