Merge "msm: kgsl: Disable GPU isense clock below nominal power level"
This commit is contained in:
commit
c5b0fe8f95
4 changed files with 42 additions and 6 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Add table
Reference in a new issue