summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-07-15 03:44:28 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-07-15 03:44:28 -0700
commitc5b0fe8f95c7eb18d6409caf765d02020f0893c7 (patch)
tree6843b492e1725b4d93b921d5b9c654954341a261 /drivers
parentd487ef9aa9d94ff46708447ac76e929a9f1c23a0 (diff)
parentfb1c6ee3acd0bb0dc802b1a0f4ec104e1d97de49 (diff)
Merge "msm: kgsl: Disable GPU isense clock below nominal power level"
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c39
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.h6
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];