diff options
author | Oleg Perelet <operelet@codeaurora.org> | 2016-07-07 09:41:20 -0700 |
---|---|---|
committer | Oleg Perelet <operelet@codeaurora.org> | 2016-07-13 10:04:55 -0700 |
commit | fb1c6ee3acd0bb0dc802b1a0f4ec104e1d97de49 (patch) | |
tree | 1a62f06761195c80cedb30ab32588f7526ef2081 /drivers/gpu/msm/kgsl_pwrctrl.c | |
parent | 400520a6e2f06cc7c45e386e769a85d4aded565b (diff) |
msm: kgsl: Disable GPU isense clock below nominal power level
By disabling isense clock below nominal level we'll remove
vote for CX rail and save power.
CRs-Fixed: 973565
Change-Id: If4a13b3eca117fc2ff9c32ca3a24eb8b8e70b4fe
Signed-off-by: Oleg Perelet <operelet@codeaurora.org>
Diffstat (limited to 'drivers/gpu/msm/kgsl_pwrctrl.c')
-rw-r--r-- | drivers/gpu/msm/kgsl_pwrctrl.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 830579d94bcf..51717373b821 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -81,6 +81,8 @@ static void kgsl_pwrctrl_set_state(struct kgsl_device *device, static void kgsl_pwrctrl_request_state(struct kgsl_device *device, unsigned int state); static void kgsl_pwrctrl_retention_clk(struct kgsl_device *device, int state); +static int _isense_clk_set_rate(struct kgsl_pwrctrl *pwr, int level); + /** * _record_pwrevent() - Record the history of the new event @@ -387,6 +389,8 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, /* Change register settings if any BEFORE pwrlevel change*/ kgsl_pwrctrl_pwrlevel_change_settings(device, 0); clk_set_rate(pwr->grp_clks[0], pwrlevel->gpu_freq); + _isense_clk_set_rate(pwr, pwr->active_pwrlevel); + trace_kgsl_pwrlevel(device, pwr->active_pwrlevel, pwrlevel->gpu_freq, pwr->previous_pwrlevel, @@ -1374,15 +1378,20 @@ static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, clk_set_rate(pwr->grp_clks[0], pwr->pwrlevels[pwr->num_pwrlevels - 1]. gpu_freq); + _isense_clk_set_rate(pwr, + pwr->num_pwrlevels - 1); } } else if (requested_state == KGSL_STATE_SLEEP) { /* High latency clock maintenance. */ for (i = KGSL_MAX_CLKS - 1; i > 0; i--) clk_unprepare(pwr->grp_clks[i]); - if ((pwr->pwrlevels[0].gpu_freq > 0)) + if ((pwr->pwrlevels[0].gpu_freq > 0)) { clk_set_rate(pwr->grp_clks[0], pwr->pwrlevels[pwr->num_pwrlevels - 1]. gpu_freq); + _isense_clk_set_rate(pwr, + pwr->num_pwrlevels - 1); + } } } else if (state == KGSL_PWRFLAGS_ON) { if (!test_and_set_bit(KGSL_PWRFLAGS_CLK_ON, @@ -1392,11 +1401,15 @@ static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, /* High latency clock maintenance. */ if ((device->state != KGSL_STATE_NAP) && (device->state != KGSL_STATE_DEEP_NAP)) { - if (pwr->pwrlevels[0].gpu_freq > 0) + if (pwr->pwrlevels[0].gpu_freq > 0) { clk_set_rate(pwr->grp_clks[0], pwr->pwrlevels [pwr->active_pwrlevel]. gpu_freq); + _isense_clk_set_rate(pwr, + pwr->active_pwrlevel); + } + for (i = KGSL_MAX_CLKS - 1; i > 0; i--) clk_prepare(pwr->grp_clks[i]); } @@ -1720,9 +1733,27 @@ static int _get_clocks(struct kgsl_device *device) } } + if (pwr->isense_clk_indx && of_property_read_u32(dev->of_node, + "qcom,isense-clk-on-level", &pwr->isense_clk_on_level)) { + KGSL_CORE_ERR("Couldn't get isense clock on level\n"); + return -ENXIO; + } return 0; } +static int _isense_clk_set_rate(struct kgsl_pwrctrl *pwr, int level) +{ + int rate; + + if (!pwr->isense_clk_indx) + return -EINVAL; + + rate = clk_round_rate(pwr->grp_clks[pwr->isense_clk_indx], + level > pwr->isense_clk_on_level ? + KGSL_XO_CLK_FREQ : KGSL_ISENSE_CLK_FREQ); + return clk_set_rate(pwr->grp_clks[pwr->isense_clk_indx], rate); +} + int kgsl_pwrctrl_init(struct kgsl_device *device) { int i, k, m, n = 0, result; @@ -1799,9 +1830,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) clk_set_rate(pwr->grp_clks[6], clk_round_rate(pwr->grp_clks[6], KGSL_RBBMTIMER_CLK_FREQ)); - if (pwr->isense_clk_indx) - clk_set_rate(pwr->grp_clks[pwr->isense_clk_indx], - KGSL_ISENSE_CLK_FREQ); + _isense_clk_set_rate(pwr, pwr->num_pwrlevels - 1); result = get_regulators(device); if (result) |