msm: kgsl: Move always on timer reads to target specific code

Instead of using adreno_readreg and a bunch of if statemnts, move the
always on timer functionality to the target specific code where it
belongs. This lets us do local variations without a bunch of hacks.

Change-Id: Ic0dedbad91b6a46f55c813f83360cb205bf5e357
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
This commit is contained in:
Jordan Crouse 2019-10-14 10:41:00 -06:00
commit b0de8bff7d
9 changed files with 72 additions and 79 deletions

View file

@ -663,8 +663,6 @@ enum adreno_regs {
ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO,
ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
ADRENO_REG_RBBM_SECVID_TRUST_CONTROL,
ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI,
ADRENO_REG_RBBM_SECVID_TRUST_CONFIG,
ADRENO_REG_RBBM_SECVID_TSB_CONTROL,
ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE,
@ -827,6 +825,8 @@ struct adreno_gpudev {
int (*perfcounter_update)(struct adreno_device *adreno_dev,
struct adreno_perfcount_register *reg,
bool update_reg);
/** @read_alwayson: Return the current value of the alwayson counter */
u64 (*read_alwayson)(struct adreno_device *adreno_dev);
};
/**

View file

@ -1431,6 +1431,12 @@ static void a3xx_clk_set_options(struct adreno_device *adreno_dev,
}
}
static u64 a3xx_read_alwayson(struct adreno_device *adreno_dev)
{
/* A3XX does not have a always on timer */
return 0;
}
struct adreno_gpudev adreno_a3xx_gpudev = {
.reg_offsets = a3xx_register_offsets,
.int_bits = a3xx_int_bits,
@ -1451,4 +1457,5 @@ struct adreno_gpudev adreno_a3xx_gpudev = {
.coresight = {&a3xx_coresight},
#endif
.clk_set_options = a3xx_clk_set_options,
.read_alwayson = a3xx_read_alwayson,
};

View file

@ -2506,10 +2506,6 @@ static unsigned int a5xx_register_offsets[ADRENO_REG_REGISTER_MAX] = {
A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI),
ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE,
A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE),
ADRENO_REG_DEFINE(ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
A5XX_RBBM_ALWAYSON_COUNTER_LO),
ADRENO_REG_DEFINE(ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI,
A5XX_RBBM_ALWAYSON_COUNTER_HI),
ADRENO_REG_DEFINE(ADRENO_REG_VBIF_XIN_HALT_CTRL0,
A5XX_VBIF_XIN_HALT_CTRL0),
ADRENO_REG_DEFINE(ADRENO_REG_VBIF_XIN_HALT_CTRL1,
@ -2789,6 +2785,20 @@ static void a5x_gpc_err_int_callback(struct adreno_device *adreno_dev, int bit)
adreno_dispatcher_schedule(device);
}
static u64 a5xx_read_alwayson(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
u32 lo = 0, hi = 0;
kgsl_regread(device, A5XX_RBBM_ALWAYSON_COUNTER_LO, &lo);
/* The upper 32 bits are only reliable on A540 targets */
if (adreno_is_a540(adreno_dev))
kgsl_regread(device, A5XX_RBBM_ALWAYSON_COUNTER_HI, &hi);
return (((u64) hi) << 32) | lo;
}
#define A5XX_INT_MASK \
((1 << A5XX_INT_RBBM_AHB_ERROR) | \
(1 << A5XX_INT_RBBM_TRANSFER_TIMEOUT) | \
@ -3087,4 +3097,5 @@ struct adreno_gpudev adreno_a5xx_gpudev = {
.preemption_close = a5xx_preemption_close,
.preemption_schedule = a5xx_preemption_schedule,
.clk_set_options = a5xx_clk_set_options,
.read_alwayson = a5xx_read_alwayson,
};

View file

@ -102,17 +102,6 @@ static u32 a612_pwrup_reglist[] = {
A6XX_RBBM_PERFCTR_CNTL,
};
static void _update_always_on_regs(struct adreno_device *adreno_dev)
{
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
unsigned int *const regs = gpudev->reg_offsets;
regs[ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO] =
A6XX_CP_ALWAYS_ON_COUNTER_LO;
regs[ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI] =
A6XX_CP_ALWAYS_ON_COUNTER_HI;
}
static void a6xx_init(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@ -134,13 +123,6 @@ static void a6xx_init(struct adreno_device *adreno_dev)
a6xx_crashdump_init(adreno_dev);
/*
* If the GMU is not enabled, rewrite the offset for the always on
* counters to point to the CP always on instead of GMU always on
*/
if (!gmu_core_isenabled(device))
_update_always_on_regs(adreno_dev);
kgsl_allocate_global(device, &adreno_dev->pwrup_reglist,
PAGE_SIZE, 0, KGSL_MEMDESC_CONTIG | KGSL_MEMDESC_PRIVILEGED,
"powerup_register_list");
@ -2409,10 +2391,6 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = {
A6XX_RBBM_GBIF_HALT_ACK),
ADRENO_REG_DEFINE(ADRENO_REG_GBIF_HALT, A6XX_GBIF_HALT),
ADRENO_REG_DEFINE(ADRENO_REG_GBIF_HALT_ACK, A6XX_GBIF_HALT_ACK),
ADRENO_REG_DEFINE(ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
A6XX_GMU_ALWAYS_ON_COUNTER_L),
ADRENO_REG_DEFINE(ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI,
A6XX_GMU_ALWAYS_ON_COUNTER_H),
ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_AHB_FENCE_CTRL,
A6XX_GMU_AO_AHB_FENCE_CTRL),
ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_INTERRUPT_EN,
@ -2585,6 +2563,32 @@ static void a6xx_clk_set_options(struct adreno_device *adreno_dev,
}
}
u64 a6xx_read_alwayson(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
u32 lo = 0, hi = 0, tmp = 0;
if (!gmu_core_isenabled(device)) {
kgsl_regread(device, A6XX_CP_ALWAYS_ON_COUNTER_LO, &lo);
kgsl_regread(device, A6XX_CP_ALWAYS_ON_COUNTER_HI, &hi);
} else {
/* Always use the GMU AO counter when doing a AHB read */
gmu_core_regread(device, A6XX_GMU_ALWAYS_ON_COUNTER_H, &hi);
gmu_core_regread(device, A6XX_GMU_ALWAYS_ON_COUNTER_L, &lo);
/* Check for overflow */
gmu_core_regread(device, A6XX_GMU_ALWAYS_ON_COUNTER_H, &tmp);
if (hi != tmp) {
gmu_core_regread(device, A6XX_GMU_ALWAYS_ON_COUNTER_L,
&lo);
hi = tmp;
}
}
return (((u64) hi) << 32) | lo;
}
struct adreno_gpudev adreno_a6xx_gpudev = {
.reg_offsets = a6xx_register_offsets,
.start = a6xx_start,
@ -2620,4 +2624,5 @@ struct adreno_gpudev adreno_a6xx_gpudev = {
.coresight = {&a6xx_coresight, &a6xx_coresight_cx},
#endif
.clk_set_options = a6xx_clk_set_options,
.read_alwayson = a6xx_read_alwayson,
};

View file

@ -244,31 +244,6 @@ static inline int timed_poll_check_rscc(struct kgsl_device *device,
return -ETIMEDOUT;
}
/*
* read_AO_counter() - Returns the 64bit always on counter value
*
* @device: Pointer to KGSL device
*/
static inline uint64_t read_AO_counter(struct kgsl_device *device)
{
unsigned int l, h, h1;
gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h);
gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l);
gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_H, &h1);
/*
* If there's no change in COUNTER_H we have no overflow so return,
* otherwise read COUNTER_L again
*/
if (h == h1)
return (uint64_t) l | ((uint64_t) h << 32);
gmu_core_regread(device, A6XX_GMU_CX_GMU_ALWAYS_ON_COUNTER_L, &l);
return (uint64_t) l | ((uint64_t) h1 << 32);
}
/* Preemption functions */
void a6xx_preemption_trigger(struct adreno_device *adreno_dev);
void a6xx_preemption_schedule(struct adreno_device *adreno_dev);
@ -297,4 +272,12 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev);
int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev);
void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev);
bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev);
/**
* a6xx_read_alwayson: Read the current always on clock value
* @adreno_dev: An Adreno GPU handle
*
* Return: The current value of the GMU always on counter
*/
u64 a6xx_read_alwayson(struct adreno_device *adreno_dev);
#endif

View file

@ -886,7 +886,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device)
unsigned long t;
uint64_t ts1, ts2, ts3;
ts1 = read_AO_counter(device);
ts1 = a6xx_read_alwayson(ADRENO_DEVICE(device));
t = jiffies + msecs_to_jiffies(GMU_IDLE_TIMEOUT);
do {
@ -901,7 +901,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device)
usleep_range(10, 100);
} while (!time_after(jiffies, t));
ts2 = read_AO_counter(device);
ts2 = a6xx_read_alwayson(ADRENO_DEVICE(device));
/* Check one last time */
gmu_core_regread(device, A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE, &reg);
@ -910,7 +910,7 @@ static int a6xx_gmu_wait_for_lowest_idle(struct kgsl_device *device)
if (idle_trandition_complete(gmu->idle_level, reg, reg1))
return 0;
ts3 = read_AO_counter(device);
ts3 = a6xx_read_alwayson(ADRENO_DEVICE(device));
/* Collect abort data to help with debugging */
gmu_core_regread(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, &reg2);
@ -954,14 +954,15 @@ static int a6xx_gmu_wait_for_idle(struct kgsl_device *device)
unsigned int status2;
uint64_t ts1;
ts1 = read_AO_counter(device);
ts1 = a6xx_read_alwayson(ADRENO_DEVICE(device));
if (timed_poll_check(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS,
0, GMU_START_TIMEOUT, CXGXCPUBUSYIGNAHB)) {
gmu_core_regread(device,
A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2, &status2);
dev_err(&gmu->pdev->dev,
"GMU not idling: status2=0x%x %llx %llx\n",
status2, ts1, read_AO_counter(device));
status2, ts1,
a6xx_read_alwayson(ADRENO_DEVICE(device)));
return -ETIMEDOUT;
}

View file

@ -259,7 +259,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device)
if (rgmu->idle_level != GPU_HW_IFPC)
return 0;
ts1 = read_AO_counter(device);
ts1 = a6xx_read_alwayson(ADRENO_DEVICE(device));
t = jiffies + msecs_to_jiffies(RGMU_IDLE_TIMEOUT);
do {
@ -273,7 +273,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device)
usleep_range(10, 100);
} while (!time_after(jiffies, t));
ts2 = read_AO_counter(device);
ts2 = a6xx_read_alwayson(ADRENO_DEVICE(device));
/* Do one last read incase it succeeds */
gmu_core_regread(device,
@ -282,7 +282,7 @@ static int a6xx_rgmu_wait_for_lowest_idle(struct kgsl_device *device)
if (reg[0] & GX_GDSC_POWER_OFF)
return 0;
ts3 = read_AO_counter(device);
ts3 = a6xx_read_alwayson(ADRENO_DEVICE(device));
/* Collect abort data to help with debugging */
gmu_core_regread(device, A6XX_RGMU_CX_PCC_DEBUG, &reg[1]);

View file

@ -885,12 +885,9 @@ static int adreno_perfcounter_enable(struct adreno_device *adreno_dev,
static uint64_t _perfcounter_read_alwayson(struct adreno_device *adreno_dev,
struct adreno_perfcount_group *group, unsigned int counter)
{
uint64_t val = 0;
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
adreno_readreg64(adreno_dev, ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI, &val);
return val + group->regs[counter].value;
return gpudev->read_alwayson(adreno_dev) + group->regs[counter].value;
}
static uint64_t _perfcounter_read_pwr(struct adreno_device *adreno_dev,

View file

@ -32,6 +32,7 @@ static void adreno_get_submit_time(struct adreno_device *adreno_dev,
struct adreno_ringbuffer *rb,
struct adreno_submit_time *time)
{
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
unsigned long flags;
/*
* Here we are attempting to create a mapping between the
@ -45,19 +46,7 @@ static void adreno_get_submit_time(struct adreno_device *adreno_dev,
local_irq_save(flags);
/* Read always on registers */
if (!adreno_is_a3xx(adreno_dev)) {
adreno_readreg64(adreno_dev,
ADRENO_REG_RBBM_ALWAYSON_COUNTER_LO,
ADRENO_REG_RBBM_ALWAYSON_COUNTER_HI,
&time->ticks);
/* Mask hi bits as they may be incorrect on some targets */
if (ADRENO_GPUREV(adreno_dev) >= 400 &&
ADRENO_GPUREV(adreno_dev) <= ADRENO_REV_A530)
time->ticks &= 0xFFFFFFFF;
} else
time->ticks = 0;
time->ticks = gpudev->read_alwayson(adreno_dev);
/* Trace the GPU time to create a mapping to ftrace time */
trace_adreno_cmdbatch_sync(rb->drawctxt_active, time->ticks);