msm: kgsl: Vote for l3 via icc_set_bw

Henceforth, l3 clock is scaled using icc api instead
of the clock api.

Change-Id: I0de3250ed402b940dfb5991ea837edb98734529a
Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
This commit is contained in:
Harshdeep Dhatt 2020-06-02 14:42:09 -06:00
commit 9f96936918
10 changed files with 46 additions and 15 deletions

View file

@ -1034,13 +1034,11 @@ l3_pwrlevel_probe(struct kgsl_device *device, struct device_node *node)
&device->l3_freq[index]);
}
device->l3_clk = devm_clk_get(&device->pdev->dev, "l3_vote");
device->l3_icc = of_icc_get(&device->pdev->dev, "l3_path");
if (IS_ERR_OR_NULL(device->l3_clk)) {
if (IS_ERR(device->l3_icc))
dev_err(&device->pdev->dev,
"Unable to get the l3_vote clock\n");
device->l3_clk = NULL;
}
"Unable to get the l3 icc path\n");
}
static int adreno_of_get_power(struct adreno_device *adreno_dev,

View file

@ -3103,6 +3103,8 @@ no_gx_power:
kgsl_pwrscale_sleep(device);
kgsl_pwrctrl_clear_l3_vote(device);
trace_kgsl_pwr_set_state(device, KGSL_STATE_SLUMBER);
return ret;

View file

@ -654,6 +654,8 @@ no_gx_power:
kgsl_pwrscale_sleep(device);
kgsl_pwrctrl_clear_l3_vote(device);
trace_kgsl_pwr_set_state(device, KGSL_STATE_SLUMBER);
return ret;

View file

@ -711,6 +711,7 @@ static void a6xx_rgmu_power_off(struct adreno_device *adreno_dev)
a6xx_rgmu_disable_clks(adreno_dev);
a6xx_rgmu_disable_gdsc(adreno_dev);
kgsl_pwrctrl_clear_l3_vote(device);
}
static int a6xx_rgmu_clock_set(struct adreno_device *adreno_dev,

View file

@ -3,6 +3,7 @@
* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/interconnect.h>
#include <linux/sched/clock.h>
#include <linux/slab.h>
@ -753,9 +754,9 @@ static void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
((context->flags & KGSL_CONTEXT_PWR_CONSTRAINT) ||
(flags & KGSL_CONTEXT_PWR_CONSTRAINT))) {
if (device->l3_clk == NULL) {
if (IS_ERR(device->l3_icc)) {
dev_err_once(device->dev,
"l3_vote clk not available\n");
"l3_icc path not available\n");
return;
}
@ -776,15 +777,21 @@ static void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
new_l3 = min_t(unsigned int, new_l3,
device->num_l3_pwrlevels - 1);
ret = clk_set_rate(device->l3_clk,
if (device->cur_l3_pwrlevel == new_l3)
return;
ret = icc_set_bw(device->l3_icc, 0,
device->l3_freq[new_l3]);
if (!ret)
if (!ret) {
trace_kgsl_constraint(device,
KGSL_CONSTRAINT_L3_PWRLEVEL, new_l3, 1);
device->cur_l3_pwrlevel = new_l3;
else
} else {
dev_err_ratelimited(device->dev,
"Could not set l3_vote: %d\n",
ret);
}
break;
}
}

View file

@ -196,7 +196,7 @@ done:
validate_pwrlevels(device, pwr->ddr_table, pwr->ddr_table_count);
pwr->icc_path = of_icc_get(&pdev->dev, NULL);
pwr->icc_path = of_icc_get(&pdev->dev, "gpu_icc_path");
if (IS_ERR(pwr->icc_path) && !gmu_core_scales_bandwidth(device)) {
WARN(1, "The CPU has no way to set the GPU bus levels\n");

View file

@ -288,7 +288,8 @@ struct kgsl_device {
/* Number of active contexts seen globally for this device */
int active_context_count;
struct kobject gpu_sysfs_kobj;
struct clk *l3_clk;
/** @icc_path: Interconnect path for scaling l3 frequency */
struct icc_path *l3_icc;
unsigned int l3_freq[MAX_L3_LEVELS];
unsigned int num_l3_pwrlevels;
/* store current L3 vote to determine if we should change our vote */

View file

@ -3,6 +3,7 @@
* Copyright (c) 2010-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/interconnect.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@ -1617,6 +1618,8 @@ void kgsl_pwrctrl_close(struct kgsl_device *device)
kgsl_bus_close(device);
pm_runtime_disable(&device->pdev->dev);
icc_put(device->l3_icc);
}
void kgsl_idle_check(struct work_struct *work)
@ -1752,16 +1755,24 @@ static int kgsl_pwrctrl_enable(struct kgsl_device *device)
return device->ftbl->regulator_enable(device);
}
static void kgsl_pwrctrl_disable(struct kgsl_device *device)
void kgsl_pwrctrl_clear_l3_vote(struct kgsl_device *device)
{
int status;
status = clk_set_rate(device->l3_clk, device->l3_freq[0]);
if (IS_ERR(device->l3_icc))
return;
status = icc_set_bw(device->l3_icc, 0, device->l3_freq[0]);
if (!status)
device->cur_l3_pwrlevel = 0;
else
dev_err(device->dev, "Could not clear l3_vote: %d\n",
status);
}
static void kgsl_pwrctrl_disable(struct kgsl_device *device)
{
kgsl_pwrctrl_clear_l3_vote(device);
/* Order pwrrail/clk sequence based upon platform */
device->ftbl->regulator_disable(device);

View file

@ -253,4 +253,11 @@ void kgsl_idle_check(struct work_struct *work);
*
*/
void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
/**
* kgsl_pwrctrl_clear_l3_vote - Relinquish l3 vote
* @device: Handle to the kgsl device
*
* Clear the l3 vote when going into slumber
*/
void kgsl_pwrctrl_clear_l3_vote(struct kgsl_device *device);
#endif /* __KGSL_PWRCTRL_H */

View file

@ -28,7 +28,9 @@
#define show_constraint(type) \
__print_symbolic(type, \
{ KGSL_CONSTRAINT_NONE, "None" }, \
{ KGSL_CONSTRAINT_PWRLEVEL, "Pwrlevel" })
{ KGSL_CONSTRAINT_PWRLEVEL, "Pwrlevel" }, \
{ KGSL_CONSTRAINT_L3_NONE, "L3_none" }, \
{ KGSL_CONSTRAINT_L3_PWRLEVEL, "L3_pwrlevel" })
struct kgsl_ringbuffer_issueibcmds;
struct kgsl_device_waittimestamp;