diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 5b8614f934b8..e72a85b5985f 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -842,7 +842,7 @@ static void adreno_of_get_ca_target_pwrlevel(struct adreno_device *adreno_dev, of_property_read_u32(node, "qcom,ca-target-pwrlevel", &ca_target_pwrlevel); - if (ca_target_pwrlevel > device->pwrctrl.num_pwrlevels - 2) + if (ca_target_pwrlevel >= device->pwrctrl.num_pwrlevels) ca_target_pwrlevel = 1; device->pwrscale.ctxt_aware_target_pwrlevel = ca_target_pwrlevel; @@ -907,15 +907,27 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, pwr->num_pwrlevels = 0; for_each_child_of_node(node, child) { - unsigned int index; + unsigned int index, freq = 0; struct kgsl_pwrlevel *level; if (of_property_read_u32(child, "reg", &index)) { dev_err(device->dev, "%pOF: powerlevel index not found\n", child); + of_node_put(child); return -EINVAL; } + if (of_property_read_u32(child, "qcom,gpu-freq", &freq)) { + dev_err(device->dev, + "%pOF: Unable to read qcom,gpu-freq\n", child); + of_node_put(child); + return -EINVAL; + } + + /* Ignore "zero" powerlevels */ + if (!freq) + continue; + if (index >= KGSL_MAX_PWRLEVELS) { dev_err(device->dev, "%pOF: Pwrlevel index %d is out of range\n", @@ -928,12 +940,7 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, level = &pwr->pwrlevels[index]; - if (of_property_read_u32(child, "qcom,gpu-freq", - &level->gpu_freq)) { - dev_err(device->dev, - "%pOF: Unable to read qcom,gpu-freq\n", child); - return -EINVAL; - } + level->gpu_freq = freq; of_property_read_u32(child, "qcom,acd-level", &level->acd_level); @@ -944,6 +951,7 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, dev_err(device->dev, "%pOF: Couldn't read the bus frequency for power level %d\n", child, index); + of_node_put(child); return ret; } @@ -968,7 +976,7 @@ static void adreno_of_get_initial_pwrlevel(struct adreno_device *adreno_dev, of_property_read_u32(node, "qcom,initial-pwrlevel", &init_level); - if (init_level < 0 || init_level > pwr->num_pwrlevels) + if (init_level < 0 || init_level >= pwr->num_pwrlevels) init_level = 1; pwr->active_pwrlevel = init_level; diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 88819e06d886..30565b592d38 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -934,14 +934,13 @@ static uint32_t _write_voltage_table(struct adreno_device *adreno_dev, const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev); int i; struct dev_pm_opp *opp; - int levels = pwr->num_pwrlevels - 1; unsigned int mvolt = 0; kgsl_regwrite(device, addr++, a5xx_core->max_power); - kgsl_regwrite(device, addr++, levels); + kgsl_regwrite(device, addr++, pwr->num_pwrlevels); /* Write voltage in mV and frequency in MHz */ - for (i = 0; i < levels; i++) { + for (i = 0; i < pwr->num_pwrlevels; i++) { opp = dev_pm_opp_find_freq_exact(&device->pdev->dev, pwr->pwrlevels[i].gpu_freq, true); /* _opp_get returns uV, convert to mV */ @@ -953,7 +952,7 @@ static uint32_t _write_voltage_table(struct adreno_device *adreno_dev, kgsl_regwrite(device, addr++, pwr->pwrlevels[i].gpu_freq / 1000000); } - return (levels * 2 + 2); + return (pwr->num_pwrlevels * 2 + 2); } static uint32_t lm_limit(struct adreno_device *adreno_dev) diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index f874286fc487..0582544b401c 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -830,7 +830,8 @@ static int a6xx_gmu_gfx_rail_on(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - unsigned int perf_idx = pwr->num_pwrlevels - pwr->default_pwrlevel - 1; + unsigned int perf_idx = gmu->num_gpupwrlevels - + pwr->default_pwrlevel - 1; uint32_t default_opp = gmu->rpmh_votes.gx_votes[perf_idx]; gmu_core_regwrite(device, A6XX_GMU_BOOT_SLUMBER_OPTION, diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index 9d548623573f..f2914236fb21 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -486,7 +486,7 @@ static int gmu_memory_probe(struct kgsl_device *device) * to index being used by GMU/RPMh. */ static int gmu_dcvs_set(struct kgsl_device *device, - unsigned int gpu_pwrlevel, unsigned int bus_level) + int gpu_pwrlevel, int bus_level) { int ret = 0; struct gmu_device *gmu = KGSL_GMU_DEVICE(device); @@ -1193,7 +1193,7 @@ static void gmu_acd_probe(struct kgsl_device *device, struct gmu_device *gmu, cmd->enable_by_level = 0; for (i = 0, cmd_idx = 0; i < numlvl; i++) { - acd_level = pwr->pwrlevels[numlvl - i - 1].acd_level; + acd_level = pwr->pwrlevels[numlvl - i].acd_level; if (acd_level) { cmd->enable_by_level |= (1 << i); cmd->data[cmd_idx++] = acd_level; @@ -1218,7 +1218,7 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) struct kgsl_hfi *hfi; struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - int i = 0, ret = -ENXIO; + int i = 0, ret = -ENXIO, index = 0; gmu = kzalloc(sizeof(struct gmu_device), GFP_KERNEL); @@ -1288,13 +1288,14 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) tasklet_init(&hfi->tasklet, hfi_receiver, (unsigned long) gmu); hfi->kgsldev = device; - gmu->num_gpupwrlevels = pwr->num_pwrlevels; + /* Add a dummy level for "off" that the GMU expects */ + gmu->gpu_freqs[index++] = 0; - for (i = 0; i < gmu->num_gpupwrlevels; i++) { - int j = gmu->num_gpupwrlevels - 1 - i; + /* GMU power levels are in ascending order */ + for (i = pwr->num_pwrlevels - 1; i >= 0; i--) + gmu->gpu_freqs[index++] = pwr->pwrlevels[i].gpu_freq; - gmu->gpu_freqs[i] = pwr->pwrlevels[j].gpu_freq; - } + gmu->num_gpupwrlevels = pwr->num_pwrlevels + 1; gmu->icc_path = of_icc_get(&gmu->pdev->dev, NULL); diff --git a/drivers/gpu/msm/kgsl_gmu_core.c b/drivers/gpu/msm/kgsl_gmu_core.c index 2181a583fa29..5ff963e25740 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.c +++ b/drivers/gpu/msm/kgsl_gmu_core.c @@ -153,8 +153,8 @@ void gmu_core_snapshot(struct kgsl_device *device) gmu_core_ops->snapshot(device); } -int gmu_core_dcvs_set(struct kgsl_device *device, unsigned int gpu_pwrlevel, - unsigned int bus_level) +int gmu_core_dcvs_set(struct kgsl_device *device, int gpu_pwrlevel, + int bus_level) { struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index 0818e716db5e..cf1225a2c2e6 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -114,7 +114,7 @@ struct gmu_core_ops { int (*probe)(struct kgsl_device *device, struct device_node *node); void (*remove)(struct kgsl_device *device); int (*dcvs_set)(struct kgsl_device *device, - unsigned int gpu_pwrlevel, unsigned int bus_level); + int gpu_pwrlevel, int bus_level); int (*init)(struct kgsl_device *device); int (*start)(struct kgsl_device *device); void (*stop)(struct kgsl_device *device); @@ -187,8 +187,8 @@ void gmu_core_snapshot(struct kgsl_device *device); bool gmu_core_gpmu_isenabled(struct kgsl_device *device); bool gmu_core_scales_bandwidth(struct kgsl_device *device); bool gmu_core_isenabled(struct kgsl_device *device); -int gmu_core_dcvs_set(struct kgsl_device *device, unsigned int gpu_pwrlevel, - unsigned int bus_level); +int gmu_core_dcvs_set(struct kgsl_device *device, int gpu_pwrlevel, + int bus_level); int gmu_core_acd_set(struct kgsl_device *device, unsigned int val); bool gmu_core_regulator_isenabled(struct kgsl_device *device); bool gmu_core_is_register_offset(struct kgsl_device *device, diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index c9b06047512c..b35b9c49d0aa 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -443,8 +443,8 @@ static void kgsl_pwrctrl_set_thermal_pwrlevel(struct kgsl_device *device, mutex_lock(&device->mutex); - if (level > pwr->num_pwrlevels - 2) - level = pwr->num_pwrlevels - 2; + if (level >= pwr->num_pwrlevels) + level = pwr->num_pwrlevels - 1; pwr->thermal_pwrlevel = level; @@ -524,8 +524,8 @@ static void kgsl_pwrctrl_min_pwrlevel_set(struct kgsl_device *device, struct kgsl_pwrctrl *pwr = &device->pwrctrl; mutex_lock(&device->mutex); - if (level > pwr->num_pwrlevels - 2) - level = pwr->num_pwrlevels - 2; + if (level >= pwr->num_pwrlevels) + level = pwr->num_pwrlevels - 1; /* You can't set a minimum power level lower than the maximum */ if (level < pwr->max_pwrlevel) @@ -572,7 +572,7 @@ static ssize_t num_pwrlevels_show(struct device *dev, struct kgsl_device *device = dev_get_drvdata(dev); struct kgsl_pwrctrl *pwr = &device->pwrctrl; - return scnprintf(buf, PAGE_SIZE, "%d\n", pwr->num_pwrlevels - 1); + return scnprintf(buf, PAGE_SIZE, "%d\n", pwr->num_pwrlevels); } /* Given a GPU clock value, return the lowest matching powerlevel */ @@ -581,7 +581,7 @@ static int _get_nearest_pwrlevel(struct kgsl_pwrctrl *pwr, unsigned int clock) { int i; - for (i = pwr->num_pwrlevels - 2; i >= 0; i--) { + for (i = pwr->num_pwrlevels - 1; i >= 0; i--) { if (abs(pwr->pwrlevels[i].gpu_freq - clock) < 5000000) return i; } @@ -728,7 +728,7 @@ static ssize_t gpu_available_frequencies_show(struct device *dev, struct kgsl_pwrctrl *pwr = &device->pwrctrl; int index, num_chars = 0; - for (index = 0; index < pwr->num_pwrlevels - 1; index++) { + for (index = 0; index < pwr->num_pwrlevels; index++) { num_chars += scnprintf(buf + num_chars, PAGE_SIZE - num_chars - 1, "%d ", pwr->pwrlevels[index].gpu_freq); @@ -750,7 +750,7 @@ static ssize_t gpu_clock_stats_show(struct device *dev, mutex_lock(&device->mutex); kgsl_pwrscale_update_stats(device); mutex_unlock(&device->mutex); - for (index = 0; index < pwr->num_pwrlevels - 1; index++) + for (index = 0; index < pwr->num_pwrlevels; index++) num_chars += scnprintf(buf + num_chars, PAGE_SIZE - num_chars, "%llu ", pwr->clock_times[index]); @@ -925,8 +925,8 @@ static ssize_t default_pwrlevel_store(struct device *dev, if (ret) return ret; - if (level > pwr->num_pwrlevels - 2) - goto done; + if (level >= pwr->num_pwrlevels) + return count; mutex_lock(&device->mutex); pwr->default_pwrlevel = level; @@ -934,7 +934,6 @@ static ssize_t default_pwrlevel_store(struct device *dev, = pwr->pwrlevels[level].gpu_freq; mutex_unlock(&device->mutex); -done: return count; } @@ -1063,7 +1062,7 @@ static ssize_t freq_table_mhz_show(struct device *dev, struct kgsl_pwrctrl *pwr = &device->pwrctrl; int index, num_chars = 0; - for (index = 0; index < pwr->num_pwrlevels - 1; index++) { + for (index = 0; index < pwr->num_pwrlevels; index++) { num_chars += scnprintf(buf + num_chars, PAGE_SIZE - num_chars - 1, "%d ", pwr->pwrlevels[index].gpu_freq / 1000000); @@ -1589,7 +1588,7 @@ static bool _gpu_freq_supported(struct kgsl_pwrctrl *pwr, unsigned int freq) { int i; - for (i = pwr->num_pwrlevels - 2; i >= 0; i--) { + for (i = pwr->num_pwrlevels - 1; i >= 0; i--) { if (pwr->pwrlevels[i].gpu_freq == freq) return true; } @@ -1687,7 +1686,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) /* Initialize the user and thermal clock constraints */ pwr->max_pwrlevel = 0; - pwr->min_pwrlevel = pwr->num_pwrlevels - 2; + pwr->min_pwrlevel = pwr->num_pwrlevels - 1; pwr->thermal_pwrlevel = 0; pwr->thermal_pwrlevel_floor = pwr->min_pwrlevel; diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index e75e37008ed0..894b4de212b5 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -28,6 +28,8 @@ #define KGSL_RBBMTIMER_CLK_FREQ KGSL_XO_CLK_FREQ #define KGSL_ISENSE_CLK_FREQ 200000000 +#define KGSL_PWRLEVEL_OFF -1 + enum kgsl_pwrctrl_timer_type { KGSL_PWR_IDLE_TIMER, }; diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 671b7eae4974..850948c90421 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -644,7 +644,7 @@ static int opp_notify(struct notifier_block *nb, min_level = pwr->thermal_pwrlevel_floor; /* Thermal limit cannot be lower than lowest non-zero operating freq */ - for (level = 0; level < (pwr->num_pwrlevels - 1); level++) { + for (level = 0; level < pwr->num_pwrlevels; level++) { if (pwr->pwrlevels[level].gpu_freq == max_freq) max_level = level; if (pwr->pwrlevels[level].gpu_freq == min_freq) @@ -678,7 +678,7 @@ static void pwrscale_busmon_create(struct kgsl_device *device, bus_profile->profile.get_dev_status = kgsl_busmon_get_dev_status; bus_profile->profile.get_cur_freq = kgsl_busmon_get_cur_freq; - bus_profile->profile.max_state = pwr->num_pwrlevels - 1; + bus_profile->profile.max_state = pwr->num_pwrlevels; bus_profile->profile.freq_table = table; dev->parent = &pdev->dev; @@ -736,16 +736,14 @@ int kgsl_pwrscale_init(struct kgsl_device *device, struct platform_device *pdev, srcu_init_notifier_head(&pwrscale->nh); - - /* do not include the 'off' level or duplicate freq. levels */ - for (i = 0; i < (pwr->num_pwrlevels - 1); i++) + for (i = 0; i < pwr->num_pwrlevels; i++) pwrscale->freq_table[i] = pwr->pwrlevels[i].gpu_freq; /* * Max_state is the number of valid power levels. * The valid power levels range from 0 - (max_state - 1) */ - gpu_profile->profile.max_state = pwr->num_pwrlevels - 1; + gpu_profile->profile.max_state = pwr->num_pwrlevels; /* link storage array to the devfreq profile pointer */ gpu_profile->profile.freq_table = pwrscale->freq_table; diff --git a/drivers/gpu/msm/kgsl_rgmu.c b/drivers/gpu/msm/kgsl_rgmu.c index a4d96ce4cb65..4f43d8f1e688 100644 --- a/drivers/gpu/msm/kgsl_rgmu.c +++ b/drivers/gpu/msm/kgsl_rgmu.c @@ -410,16 +410,18 @@ error_rgmu: * to index being used by GMU/RPMh. */ static int rgmu_dcvs_set(struct kgsl_device *device, - unsigned int pwrlevel, unsigned int bus_level) + int pwrlevel, int bus_level) { struct rgmu_device *rgmu = KGSL_RGMU_DEVICE(device); int ret; + unsigned long rate; if (pwrlevel == INVALID_DCVS_IDX) return -EINVAL; - ret = clk_set_rate(rgmu->gpu_clk, - device->pwrctrl.pwrlevels[pwrlevel].gpu_freq); + rate = device->pwrctrl.pwrlevels[pwrlevel].gpu_freq; + + ret = clk_set_rate(rgmu->gpu_clk, rate); if (ret) dev_err(&rgmu->pdev->dev, "Couldn't set the GPU clock\n");