diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-07-15 03:44:28 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-07-15 03:44:28 -0700 |
commit | c5b0fe8f95c7eb18d6409caf765d02020f0893c7 (patch) | |
tree | 6843b492e1725b4d93b921d5b9c654954341a261 /drivers | |
parent | d487ef9aa9d94ff46708447ac76e929a9f1c23a0 (diff) | |
parent | fb1c6ee3acd0bb0dc802b1a0f4ec104e1d97de49 (diff) |
Merge "msm: kgsl: Disable GPU isense clock below nominal power level"
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/msm/kgsl_pwrctrl.c | 39 | ||||
-rw-r--r-- | drivers/gpu/msm/kgsl_pwrctrl.h | 6 |
2 files changed, 39 insertions, 6 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) diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 9d2c6ce0c269..0029c389484f 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -33,7 +33,8 @@ /* Only two supported levels, min & max */ #define KGSL_CONSTRAINT_PWR_MAXLEVELS 2 -#define KGSL_RBBMTIMER_CLK_FREQ 19200000 +#define KGSL_XO_CLK_FREQ 19200000 +#define KGSL_RBBMTIMER_CLK_FREQ KGSL_XO_CLK_FREQ #define KGSL_ISENSE_CLK_FREQ 200000000 /* Symbolic table for the constraint type */ @@ -154,6 +155,8 @@ struct kgsl_regulator { * @deep_nap_timer - Timer struct for entering deep nap * @deep_nap_timeout - Timeout for entering deep nap * @gx_retention - true if retention voltage is allowed + * isense_clk_indx - index of isense clock, 0 if no isense + * isense_clk_on_level - isense clock rate is XO rate below this level. */ struct kgsl_pwrctrl { @@ -162,6 +165,7 @@ struct kgsl_pwrctrl { struct clk *dummy_mx_clk; struct clk *gpu_bimc_int_clk; int isense_clk_indx; + int isense_clk_on_level; unsigned long power_flags; unsigned long ctrl_flags; struct kgsl_pwrlevel pwrlevels[KGSL_MAX_PWRLEVELS]; |