mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
Merge "msm: kgsl: Poll GDCSR for holi target to ensure CX collapse"
This commit is contained in:
commit
457deee787
7 changed files with 100 additions and 57 deletions
|
|
@ -2036,18 +2036,6 @@ static int _adreno_start(struct adreno_device *adreno_dev)
|
|||
if (regulator_left_on)
|
||||
_soft_reset(adreno_dev);
|
||||
|
||||
/*
|
||||
* During adreno_stop, GBIF halt is asserted to ensure
|
||||
* no further transaction can go through GPU before GPU
|
||||
* headswitch is turned off.
|
||||
*
|
||||
* This halt is deasserted once headswitch goes off but
|
||||
* incase headswitch doesn't goes off clear GBIF halt
|
||||
* here to ensure GPU wake-up doesn't fail because of
|
||||
* halted GPU transactions.
|
||||
*/
|
||||
adreno_deassert_gbif_halt(adreno_dev);
|
||||
|
||||
adreno_ringbuffer_set_global(adreno_dev, 0);
|
||||
|
||||
status = kgsl_mmu_start(device);
|
||||
|
|
@ -3522,7 +3510,7 @@ static int adreno_regulator_enable(struct kgsl_device *device)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool adreno_is_hw_collapsible(struct kgsl_device *device)
|
||||
static bool adreno_prepare_for_power_off(struct kgsl_device *device)
|
||||
{
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
|
||||
|
|
@ -3536,8 +3524,16 @@ static bool adreno_is_hw_collapsible(struct kgsl_device *device)
|
|||
device->pwrctrl.ctrl_flags)
|
||||
return false;
|
||||
|
||||
return adreno_isidle(adreno_dev) && (gpudev->is_sptp_idle ?
|
||||
gpudev->is_sptp_idle(adreno_dev) : true);
|
||||
if (!adreno_isidle(adreno_dev) || !(gpudev->is_sptp_idle ?
|
||||
gpudev->is_sptp_idle(adreno_dev) : true))
|
||||
return false;
|
||||
|
||||
if (gpudev->clear_pending_transactions(adreno_dev))
|
||||
return false;
|
||||
|
||||
adreno_dispatcher_stop_fault_timer(device);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void adreno_regulator_disable(struct kgsl_device *device)
|
||||
|
|
@ -3576,17 +3572,15 @@ static void adreno_clk_set_options(struct kgsl_device *device, const char *name,
|
|||
static void adreno_regulator_disable_poll(struct kgsl_device *device)
|
||||
{
|
||||
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
|
||||
const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(
|
||||
ADRENO_DEVICE(device));
|
||||
|
||||
/* Set the parent in retention voltage to disable CPR interrupts */
|
||||
kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent,
|
||||
pwr->gx_gdsc_parent_min_corner);
|
||||
if (gpudev->regulator_disable_poll)
|
||||
return gpudev->regulator_disable_poll(device);
|
||||
|
||||
if (!kgsl_regulator_disable_wait(pwr->gx_gdsc, 200))
|
||||
dev_err(device->dev, "Regulator vdd is stuck on\n");
|
||||
|
||||
/* Remove the vote for the vdd parent supply */
|
||||
kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent, 0);
|
||||
|
||||
if (!kgsl_regulator_disable_wait(pwr->cx_gdsc, 200))
|
||||
dev_err(device->dev, "Regulator vddcx is stuck on\n");
|
||||
}
|
||||
|
|
@ -3744,6 +3738,15 @@ static int adreno_gpu_bus_set(struct kgsl_device *device, int level, u32 ab)
|
|||
return adreno_interconnect_bus_set(adreno_dev, level, ab);
|
||||
}
|
||||
|
||||
static void adreno_deassert_gbif_halt(struct kgsl_device *device)
|
||||
{
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
|
||||
|
||||
if (gpudev->deassert_gbif_halt)
|
||||
gpudev->deassert_gbif_halt(adreno_dev);
|
||||
}
|
||||
|
||||
static const struct kgsl_functable adreno_functable = {
|
||||
/* Mandatory functions */
|
||||
.regread = adreno_regread,
|
||||
|
|
@ -3778,17 +3781,17 @@ static const struct kgsl_functable adreno_functable = {
|
|||
.drawctxt_sched = adreno_drawctxt_sched,
|
||||
.resume = adreno_dispatcher_start,
|
||||
.regulator_enable = adreno_regulator_enable,
|
||||
.is_hw_collapsible = adreno_is_hw_collapsible,
|
||||
.prepare_for_power_off = adreno_prepare_for_power_off,
|
||||
.regulator_disable = adreno_regulator_disable,
|
||||
.pwrlevel_change_settings = adreno_pwrlevel_change_settings,
|
||||
.regulator_disable_poll = adreno_regulator_disable_poll,
|
||||
.clk_set_options = adreno_clk_set_options,
|
||||
.gpu_model = adreno_gpu_model,
|
||||
.stop_fault_timer = adreno_dispatcher_stop_fault_timer,
|
||||
.query_property_list = adreno_query_property_list,
|
||||
.is_hwcg_on = adreno_is_hwcg_on,
|
||||
.gpu_clock_set = adreno_gpu_clock_set,
|
||||
.gpu_bus_set = adreno_gpu_bus_set,
|
||||
.deassert_gbif_halt = adreno_deassert_gbif_halt,
|
||||
};
|
||||
|
||||
static const struct component_master_ops adreno_ops = {
|
||||
|
|
|
|||
|
|
@ -696,9 +696,7 @@ enum adreno_regs {
|
|||
ADRENO_REG_RBBM_PERFCTR_RBBM_0_HI,
|
||||
ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO,
|
||||
ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
|
||||
ADRENO_REG_GBIF_HALT,
|
||||
ADRENO_REG_VBIF_VERSION,
|
||||
ADRENO_REG_RBBM_GBIF_HALT,
|
||||
ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
|
||||
ADRENO_REG_GMU_AHB_FENCE_STATUS,
|
||||
ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
|
||||
|
|
@ -813,6 +811,8 @@ struct adreno_gpudev {
|
|||
*/
|
||||
const struct adreno_power_ops *power_ops;
|
||||
int (*clear_pending_transactions)(struct adreno_device *adreno_dev);
|
||||
void (*deassert_gbif_halt)(struct adreno_device *adreno_dev);
|
||||
void (*regulator_disable_poll)(struct kgsl_device *device);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1692,22 +1692,6 @@ static inline int adreno_wait_for_halt_ack(struct kgsl_device *device,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline void adreno_deassert_gbif_halt(struct adreno_device *adreno_dev)
|
||||
{
|
||||
if (adreno_has_gbif(adreno_dev)) {
|
||||
adreno_writereg(adreno_dev, ADRENO_REG_GBIF_HALT, 0x0);
|
||||
|
||||
/*
|
||||
* Release GBIF GX halt. For A615 family, GPU GX halt
|
||||
* will be cleared automatically on reset.
|
||||
*/
|
||||
if (!gmu_core_gpmu_isenabled(KGSL_DEVICE(adreno_dev)) &&
|
||||
!adreno_is_a615_family(adreno_dev))
|
||||
adreno_writereg(adreno_dev,
|
||||
ADRENO_REG_RBBM_GBIF_HALT, 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* adreno_move_preempt_state - Update the preemption state
|
||||
* @adreno_dev: An Adreno GPU device handle
|
||||
|
|
@ -1753,8 +1737,6 @@ static inline u32 adreno_get_level(u32 priority)
|
|||
int adreno_gmu_fenced_write(struct adreno_device *adreno_dev,
|
||||
enum adreno_regs offset, unsigned int val,
|
||||
unsigned int fence_mask);
|
||||
int adreno_clear_pending_transactions(struct kgsl_device *device);
|
||||
|
||||
|
||||
/**
|
||||
* adreno_get_firwmare - Load firmware into a adreno_firmware struct
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "adreno_pm4types.h"
|
||||
#include "adreno_trace.h"
|
||||
#include "kgsl_trace.h"
|
||||
#include "kgsl_util.h"
|
||||
|
||||
/* IFPC & Preemption static powerup restore list */
|
||||
static u32 a6xx_pwrup_reglist[] = {
|
||||
|
|
@ -249,6 +250,7 @@ bool a6xx_cx_regulator_disable_wait(struct regulator *reg,
|
|||
{
|
||||
ktime_t tout = ktime_add_us(ktime_get(), timeout * 1000);
|
||||
unsigned int val;
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
|
||||
if (IS_ERR_OR_NULL(reg))
|
||||
return true;
|
||||
|
|
@ -256,13 +258,22 @@ bool a6xx_cx_regulator_disable_wait(struct regulator *reg,
|
|||
regulator_disable(reg);
|
||||
|
||||
for (;;) {
|
||||
gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, &val);
|
||||
if (adreno_is_a619_holi(adreno_dev))
|
||||
adreno_read_gmu_wrapper(adreno_dev,
|
||||
A6XX_GPU_CC_CX_GDSCR, &val);
|
||||
else
|
||||
gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, &val);
|
||||
|
||||
if (!(val & BIT(31)))
|
||||
return true;
|
||||
|
||||
if (ktime_compare(ktime_get(), tout) > 0) {
|
||||
gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, &val);
|
||||
if (adreno_is_a619_holi(adreno_dev))
|
||||
adreno_read_gmu_wrapper(adreno_dev,
|
||||
A6XX_GPU_CC_CX_GDSCR, &val);
|
||||
else
|
||||
gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR,
|
||||
&val);
|
||||
return (!(val & BIT(31)));
|
||||
}
|
||||
|
||||
|
|
@ -426,6 +437,18 @@ static void a6xx_set_secvid(struct kgsl_device *device)
|
|||
set = true;
|
||||
}
|
||||
|
||||
static void a6xx_deassert_gbif_halt(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
|
||||
kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0);
|
||||
|
||||
if (adreno_is_a619_holi(adreno_dev))
|
||||
kgsl_regwrite(device, A6XX_RBBM_GPR0_CNTL, 0x0);
|
||||
else
|
||||
kgsl_regwrite(device, A6XX_RBBM_GBIF_HALT, 0x0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some targets support marking certain transactions as always privileged which
|
||||
* allows us to mark more memory as privileged without having to explicitly set
|
||||
|
|
@ -696,6 +719,19 @@ void a6xx_start(struct adreno_device *adreno_dev)
|
|||
a6xx_patch_pwrup_reglist(adreno_dev);
|
||||
patch_reglist = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* During adreno_stop, GBIF halt is asserted to ensure
|
||||
* no further transaction can go through GPU before GPU
|
||||
* headswitch is turned off.
|
||||
*
|
||||
* This halt is deasserted once headswitch goes off but
|
||||
* incase headswitch doesn't goes off clear GBIF halt
|
||||
* here to ensure GPU wake-up doesn't fail because of
|
||||
* halted GPU transactions.
|
||||
*/
|
||||
a6xx_deassert_gbif_halt(adreno_dev);
|
||||
|
||||
}
|
||||
|
||||
/* Offsets into the MX/CX mapped register regions */
|
||||
|
|
@ -2300,9 +2336,6 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = {
|
|||
ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
|
||||
A6XX_RBBM_PERFCTR_LOAD_VALUE_HI),
|
||||
ADRENO_REG_DEFINE(ADRENO_REG_VBIF_VERSION, A6XX_VBIF_VERSION),
|
||||
ADRENO_REG_DEFINE(ADRENO_REG_RBBM_GBIF_HALT,
|
||||
A6XX_RBBM_GBIF_HALT),
|
||||
ADRENO_REG_DEFINE(ADRENO_REG_GBIF_HALT, A6XX_GBIF_HALT),
|
||||
ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
|
||||
A6XX_GMU_AO_HOST_INTERRUPT_MASK),
|
||||
ADRENO_REG_DEFINE(ADRENO_REG_GMU_AHB_FENCE_STATUS,
|
||||
|
|
@ -2454,6 +2487,24 @@ u64 a6xx_read_alwayson(struct adreno_device *adreno_dev)
|
|||
return (((u64) hi) << 32) | lo;
|
||||
}
|
||||
|
||||
static void a619_holi_regulator_disable_poll(struct kgsl_device *device)
|
||||
{
|
||||
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
|
||||
|
||||
/* Set the parent in retention voltage to disable CPR interrupts */
|
||||
kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent,
|
||||
pwr->gx_gdsc_parent_min_corner);
|
||||
|
||||
if (!kgsl_regulator_disable_wait(pwr->gx_gdsc, 200))
|
||||
dev_err(device->dev, "Regulator vdd is stuck on\n");
|
||||
|
||||
/* Remove the vote for the vdd parent supply */
|
||||
kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent, 0);
|
||||
|
||||
if (!a6xx_cx_regulator_disable_wait(pwr->cx_gdsc, device, 200))
|
||||
dev_err(device->dev, "Regulator vddcx is stuck on\n");
|
||||
}
|
||||
|
||||
const struct adreno_gpudev adreno_a6xx_gpudev = {
|
||||
.reg_offsets = a6xx_register_offsets,
|
||||
.probe = a6xx_probe,
|
||||
|
|
@ -2487,6 +2538,7 @@ const struct adreno_gpudev adreno_a6xx_gpudev = {
|
|||
.read_alwayson = a6xx_read_alwayson,
|
||||
.power_ops = &adreno_power_operations,
|
||||
.clear_pending_transactions = a6xx_clear_pending_transactions,
|
||||
.deassert_gbif_halt = a6xx_deassert_gbif_halt,
|
||||
};
|
||||
|
||||
const struct adreno_gpudev adreno_a6xx_hwsched_gpudev = {
|
||||
|
|
@ -2600,6 +2652,8 @@ const struct adreno_gpudev adreno_a619_holi_gpudev = {
|
|||
.read_alwayson = a6xx_read_alwayson,
|
||||
.power_ops = &adreno_power_operations,
|
||||
.clear_pending_transactions = a6xx_clear_pending_transactions,
|
||||
.deassert_gbif_halt = a6xx_deassert_gbif_halt,
|
||||
.regulator_disable_poll = a619_holi_regulator_disable_poll,
|
||||
};
|
||||
|
||||
const struct adreno_gpudev adreno_a630_gpudev = {
|
||||
|
|
|
|||
|
|
@ -1626,6 +1626,8 @@ static void a6xx_gmu_pwrctrl_suspend(struct adreno_device *adreno_dev)
|
|||
}
|
||||
/* Halt CX traffic */
|
||||
a6xx_halt_gbif(adreno_dev);
|
||||
/* De-assert the halts */
|
||||
kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0);
|
||||
}
|
||||
|
||||
if (a6xx_gmu_gx_is_on(device))
|
||||
|
|
@ -2764,9 +2766,6 @@ int a6xx_halt_gbif(struct adreno_device *adreno_dev)
|
|||
ret = adreno_wait_for_halt_ack(device,
|
||||
A6XX_GBIF_HALT_ACK, A6XX_GBIF_ARB_HALT_MASK);
|
||||
|
||||
/* De-assert the halts */
|
||||
kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2797,8 +2796,11 @@ static int a6xx_gmu_power_off(struct adreno_device *adreno_dev)
|
|||
a6xx_rdpm_mx_freq_update(gmu, 0);
|
||||
|
||||
/* Now that we are done with GMU and GPU, Clear the GBIF */
|
||||
if (!adreno_is_a630(adreno_dev))
|
||||
if (!adreno_is_a630(adreno_dev)) {
|
||||
ret = a6xx_halt_gbif(adreno_dev);
|
||||
/* De-assert the halts */
|
||||
kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0);
|
||||
}
|
||||
|
||||
a6xx_gmu_irq_disable(adreno_dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -373,6 +373,8 @@ static int a6xx_hwsched_gmu_power_off(struct adreno_device *adreno_dev)
|
|||
|
||||
/* Now that we are done with GMU and GPU, Clear the GBIF */
|
||||
ret = a6xx_halt_gbif(adreno_dev);
|
||||
/* De-assert the halts */
|
||||
kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0);
|
||||
|
||||
a6xx_gmu_irq_disable(adreno_dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ struct kgsl_functable {
|
|||
struct kgsl_context *context);
|
||||
void (*resume)(struct kgsl_device *device);
|
||||
int (*regulator_enable)(struct kgsl_device *device);
|
||||
bool (*is_hw_collapsible)(struct kgsl_device *device);
|
||||
bool (*prepare_for_power_off)(struct kgsl_device *device);
|
||||
void (*regulator_disable)(struct kgsl_device *device);
|
||||
void (*pwrlevel_change_settings)(struct kgsl_device *device,
|
||||
unsigned int prelevel, unsigned int postlevel, bool post);
|
||||
|
|
@ -157,7 +157,6 @@ struct kgsl_functable {
|
|||
const char *name, struct clk *clk, bool on);
|
||||
void (*gpu_model)(struct kgsl_device *device, char *str,
|
||||
size_t bufsz);
|
||||
void (*stop_fault_timer)(struct kgsl_device *device);
|
||||
/**
|
||||
* @query_property_list: query the list of properties
|
||||
* supported by the device. If 'list' is NULL just return the total
|
||||
|
|
@ -171,6 +170,7 @@ struct kgsl_functable {
|
|||
int (*gpu_clock_set)(struct kgsl_device *device, u32 pwrlevel);
|
||||
/** @gpu_bus_set: Target specific function to set gpu bandwidth */
|
||||
int (*gpu_bus_set)(struct kgsl_device *device, int bus_level, u32 ab);
|
||||
void (*deassert_gbif_halt)(struct kgsl_device *device);
|
||||
};
|
||||
|
||||
struct kgsl_ioctl {
|
||||
|
|
|
|||
|
|
@ -1859,6 +1859,7 @@ static int _wake(struct kgsl_device *device)
|
|||
/* Turn on the core clocks */
|
||||
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);
|
||||
|
||||
device->ftbl->deassert_gbif_halt(device);
|
||||
/*
|
||||
* No need to turn on/off irq here as it no longer affects
|
||||
* power collapse
|
||||
|
|
@ -1943,12 +1944,11 @@ _nap(struct kgsl_device *device)
|
|||
{
|
||||
switch (device->state) {
|
||||
case KGSL_STATE_ACTIVE:
|
||||
if (!device->ftbl->is_hw_collapsible(device)) {
|
||||
if (!device->ftbl->prepare_for_power_off(device)) {
|
||||
kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
device->ftbl->stop_fault_timer(device);
|
||||
kgsl_pwrscale_midframe_timer_cancel(device);
|
||||
|
||||
/*
|
||||
|
|
@ -2006,7 +2006,7 @@ _slumber(struct kgsl_device *device)
|
|||
|
||||
switch (device->state) {
|
||||
case KGSL_STATE_ACTIVE:
|
||||
if (!device->ftbl->is_hw_collapsible(device)) {
|
||||
if (!device->ftbl->prepare_for_power_off(device)) {
|
||||
kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue