msm: kgsl: Dynamically create an OPP table at runtime

The other reason why we define a OPP table for each target is for devfreq.
This is equally as silly as the first reason because we already have a
frequency table and forcing the developer to define it twice only invites
a mistake.  Remove the need for the static OPP table and create it
dynamically, at run time, from the information we already have.

Change-Id: Ic0dedbada16ec0832c0d531f39460f14aadc1bdd
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
This commit is contained in:
Jordan Crouse 2019-10-14 10:41:09 -06:00
commit 3a2f09f384
3 changed files with 35 additions and 52 deletions

View file

@ -885,6 +885,40 @@ static void adreno_of_get_ca_aware_properties(struct adreno_device *adreno_dev,
}
}
/* Dynamically build the OPP table for the GPU device */
static void adreno_build_opp_table(struct device *dev, struct kgsl_pwrctrl *pwr)
{
unsigned long freq = 0;
int i;
/*
* First an annoying step: Some targets have clock drivers that
* "helpfully" builds a OPP table for us but usually it is wrong.
* Go through and filter out unsupported frequencies
*/
for (;;) {
struct dev_pm_opp *opp = dev_pm_opp_find_freq_ceil(dev, &freq);
if (IS_ERR(opp))
break;
for (i = 0; i < pwr->num_pwrlevels; i++) {
if (freq == pwr->pwrlevels[i].gpu_freq)
break;
}
if (i == pwr->num_pwrlevels)
dev_pm_opp_remove(dev, freq);
freq++;
}
/* Now add all of our supported frequencies into the tree */
for (i = 0; i < pwr->num_pwrlevels; i++)
dev_pm_opp_add(dev, pwr->pwrlevels[i].gpu_freq, 0);
}
static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
struct device_node *node)
{
@ -893,17 +927,6 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
struct device_node *child;
int ret;
/* ADD the GPU OPP table if we define it */
if (of_find_property(device->pdev->dev.of_node,
"operating-points-v2", NULL)) {
ret = dev_pm_opp_of_add_table(&device->pdev->dev);
if (ret) {
dev_err(device->dev,
"Unable to set the GPU OPP table: %d\n", ret);
return ret;
}
}
pwr->num_pwrlevels = 0;
for_each_child_of_node(node, child) {
@ -971,6 +994,7 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
"qcom,bus-max", &level->bus_max);
}
adreno_build_opp_table(&device->pdev->dev, pwr);
return 0;
out:
of_node_put(child);

View file

@ -1584,43 +1584,6 @@ static int kgsl_pwrctrl_clk_set_rate(struct clk *grp_clk, unsigned int freq,
return ret;
}
static bool _gpu_freq_supported(struct kgsl_pwrctrl *pwr, unsigned int freq)
{
int i;
for (i = pwr->num_pwrlevels - 1; i >= 0; i--) {
if (pwr->pwrlevels[i].gpu_freq == freq)
return true;
}
return false;
}
void kgsl_pwrctrl_disable_unused_opp(struct kgsl_device *device,
struct device *dev)
{
struct dev_pm_opp *opp;
unsigned long freq = 0;
int ret;
ret = dev_pm_opp_get_opp_count(dev);
/* Return early, If no OPP table or OPP count is zero */
if (ret <= 0)
return;
while (1) {
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
if (IS_ERR(opp))
break;
if (!_gpu_freq_supported(&device->pwrctrl, freq))
dev_pm_opp_disable(dev, freq);
dev_pm_opp_put(opp);
freq++;
}
}
static u32 *kgsl_bus_get_table(struct platform_device *pdev, int *count)
{
u32 *levels;
@ -1702,8 +1665,6 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
pwr->pwrlevels[i].gpu_freq = freq;
}
kgsl_pwrctrl_disable_unused_opp(device, &pdev->dev);
kgsl_clk_set_rate(device, pwr->num_pwrlevels - 1);
freq = clk_round_rate(pwr->grp_clks[6], KGSL_RBBMTIMER_CLK_FREQ);

View file

@ -198,7 +198,5 @@ void kgsl_pwrctrl_busy_time(struct kgsl_device *device, u64 time, u64 busy);
void kgsl_pwrctrl_set_constraint(struct kgsl_device *device,
struct kgsl_pwr_constraint *pwrc, uint32_t id);
int kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device);
void kgsl_pwrctrl_disable_unused_opp(struct kgsl_device *device,
struct device *dev);
#endif /* __KGSL_PWRCTRL_H */