msm: kgsl: Disable memory retention for core clock before entering SLUMBER

Memory retention is needed only for NAP state but not for SLUMBER state.
Disables memory retention for core clock before entering SLUMBER to save
power.

Change-Id: I64a5ecec6fc90d662da8d9d793860e56b0c6473f
Signed-off-by: Deepak Kumar <dkumar@codeaurora.org>
This commit is contained in:
Deepak Kumar 2017-03-17 17:27:42 +05:30
parent f4a611a3af
commit c1de946ab2
5 changed files with 35 additions and 11 deletions

View file

@ -2675,11 +2675,11 @@ static void adreno_pwrlevel_change_settings(struct kgsl_device *device,
} }
static void adreno_clk_set_options(struct kgsl_device *device, const char *name, static void adreno_clk_set_options(struct kgsl_device *device, const char *name,
struct clk *clk) struct clk *clk, bool on)
{ {
if (ADRENO_GPU_DEVICE(ADRENO_DEVICE(device))->clk_set_options) if (ADRENO_GPU_DEVICE(ADRENO_DEVICE(device))->clk_set_options)
ADRENO_GPU_DEVICE(ADRENO_DEVICE(device))->clk_set_options( ADRENO_GPU_DEVICE(ADRENO_DEVICE(device))->clk_set_options(
ADRENO_DEVICE(device), name, clk); ADRENO_DEVICE(device), name, clk, on);
} }
static void adreno_iommu_sync(struct kgsl_device *device, bool sync) static void adreno_iommu_sync(struct kgsl_device *device, bool sync)

View file

@ -789,7 +789,7 @@ struct adreno_gpudev {
void (*preemption_schedule)(struct adreno_device *); void (*preemption_schedule)(struct adreno_device *);
void (*enable_64bit)(struct adreno_device *); void (*enable_64bit)(struct adreno_device *);
void (*clk_set_options)(struct adreno_device *, void (*clk_set_options)(struct adreno_device *,
const char *, struct clk *); const char *, struct clk *, bool on);
}; };
/** /**

View file

@ -1640,11 +1640,15 @@ static void a5xx_pwrlevel_change_settings(struct adreno_device *adreno_dev,
} }
static void a5xx_clk_set_options(struct adreno_device *adreno_dev, static void a5xx_clk_set_options(struct adreno_device *adreno_dev,
const char *name, struct clk *clk) const char *name, struct clk *clk, bool on)
{ {
if (!adreno_is_a540(adreno_dev) && !adreno_is_a512(adreno_dev) &&
!adreno_is_a508(adreno_dev))
return;
/* Handle clock settings for GFX PSCBCs */ /* Handle clock settings for GFX PSCBCs */
if (adreno_is_a540(adreno_dev) || adreno_is_a512(adreno_dev) || if (on) {
adreno_is_a508(adreno_dev)) {
if (!strcmp(name, "mem_iface_clk")) { if (!strcmp(name, "mem_iface_clk")) {
clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH);
clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); clk_set_flags(clk, CLKFLAG_NORETAIN_MEM);
@ -1652,6 +1656,11 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev,
clk_set_flags(clk, CLKFLAG_RETAIN_PERIPH); clk_set_flags(clk, CLKFLAG_RETAIN_PERIPH);
clk_set_flags(clk, CLKFLAG_RETAIN_MEM); clk_set_flags(clk, CLKFLAG_RETAIN_MEM);
} }
} else {
if (!strcmp(name, "core_clk")) {
clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH);
clk_set_flags(clk, CLKFLAG_NORETAIN_MEM);
}
} }
} }

View file

@ -166,7 +166,7 @@ struct kgsl_functable {
unsigned int prelevel, unsigned int postlevel, bool post); unsigned int prelevel, unsigned int postlevel, bool post);
void (*regulator_disable_poll)(struct kgsl_device *device); void (*regulator_disable_poll)(struct kgsl_device *device);
void (*clk_set_options)(struct kgsl_device *device, void (*clk_set_options)(struct kgsl_device *device,
const char *name, struct clk *clk); const char *name, struct clk *clk, bool on);
void (*gpu_model)(struct kgsl_device *device, char *str, void (*gpu_model)(struct kgsl_device *device, char *str,
size_t bufsz); size_t bufsz);
void (*stop_fault_timer)(struct kgsl_device *device); void (*stop_fault_timer)(struct kgsl_device *device);

View file

@ -2003,10 +2003,6 @@ static int _get_clocks(struct kgsl_device *device)
if (!strcmp(name, "isense_clk")) if (!strcmp(name, "isense_clk"))
pwr->isense_clk_indx = i; pwr->isense_clk_indx = i;
if (device->ftbl->clk_set_options)
device->ftbl->clk_set_options(device, name,
pwr->grp_clks[i]);
break; break;
} }
} }
@ -2453,6 +2449,22 @@ static void kgsl_pwrctrl_disable(struct kgsl_device *device)
kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_OFF); kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_OFF);
} }
static void
kgsl_pwrctrl_clk_set_options(struct kgsl_device *device, bool on)
{
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
int i;
for (i = 0; i < KGSL_MAX_CLKS; i++) {
if (pwr->grp_clks[i] == NULL)
continue;
if (device->ftbl->clk_set_options)
device->ftbl->clk_set_options(device, clocks[i],
pwr->grp_clks[i], on);
}
}
/** /**
* _init() - Get the GPU ready to start, but don't turn anything on * _init() - Get the GPU ready to start, but don't turn anything on
* @device - Pointer to the kgsl_device struct * @device - Pointer to the kgsl_device struct
@ -2499,6 +2511,7 @@ static int _wake(struct kgsl_device *device)
device->ftbl->resume(device); device->ftbl->resume(device);
/* fall through */ /* fall through */
case KGSL_STATE_SLUMBER: case KGSL_STATE_SLUMBER:
kgsl_pwrctrl_clk_set_options(device, true);
status = device->ftbl->start(device, status = device->ftbl->start(device,
device->pwrctrl.superfast); device->pwrctrl.superfast);
device->pwrctrl.superfast = false; device->pwrctrl.superfast = false;
@ -2535,6 +2548,7 @@ static int _wake(struct kgsl_device *device)
device->pwrctrl.interval_timeout); device->pwrctrl.interval_timeout);
break; break;
case KGSL_STATE_AWARE: case KGSL_STATE_AWARE:
kgsl_pwrctrl_clk_set_options(device, true);
/* Enable state before turning on irq */ /* Enable state before turning on irq */
kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
@ -2649,6 +2663,7 @@ _slumber(struct kgsl_device *device)
status = kgsl_pwrctrl_enable(device); status = kgsl_pwrctrl_enable(device);
device->ftbl->suspend_context(device); device->ftbl->suspend_context(device);
device->ftbl->stop(device); device->ftbl->stop(device);
kgsl_pwrctrl_clk_set_options(device, false);
kgsl_pwrctrl_disable(device); kgsl_pwrctrl_disable(device);
kgsl_pwrscale_sleep(device); kgsl_pwrscale_sleep(device);
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);