summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/gpu/adreno.txt2
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi1
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c39
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.h6
4 files changed, 42 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 5097e994f483..0d9427b3e1b8 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -31,6 +31,8 @@ Required properties:
- qcom,base-leakage-coefficient: Dynamic leakage coefficient.
- qcom,lm-limit: Current limit for GPU limit management.
+- qcom,isense-clk-on-level: below or equal this power level isense clock is at XO rate,
+ above this powerlevel isense clock is at working frequency.
Bus Scaling Data:
- qcom,msm-bus,name: String property to describe the name of the 3D graphics processor.
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
index 4b5956049bab..2128261d9bf2 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
@@ -91,6 +91,7 @@
"mem_clk", "mem_iface_clk", "isense_clk", "rbcpr_clk",
"iref_clk";
+ qcom,isense-clk-on-level = <1>;
/* Bus Scale Settings */
qcom,gpubw-dev = <&gpubw>;
qcom,bus-control;
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];