Loading Documentation/devicetree/bindings/gpu/adreno.txt +2 −0 Original line number Diff line number Diff line Loading @@ -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. Loading arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading drivers/gpu/msm/kgsl_pwrctrl.c +34 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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, Loading @@ -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]); } Loading Loading @@ -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; Loading Loading @@ -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) Loading drivers/gpu/msm/kgsl_pwrctrl.h +5 −1 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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 { Loading @@ -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 Loading
Documentation/devicetree/bindings/gpu/adreno.txt +2 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
drivers/gpu/msm/kgsl_pwrctrl.c +34 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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, Loading @@ -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]); } Loading Loading @@ -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; Loading Loading @@ -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) Loading
drivers/gpu/msm/kgsl_pwrctrl.h +5 −1 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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 { Loading @@ -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