msm: dcvs: rearrange platform data.
This change
-removes the use of group id and instead introduces core type
-rearranges platform data, adds energy curve coefficients and power
parameters
-allow for the energy params to be -ve numbers
The change also mandates updates to the msm8974-gpu.dtsi and the
associated binding documentation.
Also take this opportunity to remove devices for unsupported platform
- 8930 and 8960
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
(cherry picked from commit 4445166ad16be0c45b077bfb10487de355ed2e05)
Signed-off-by: Ram Kumar Chakravarthy Chebathini <rcheba@codeaurora.org>
(cherry picked from commit 24d2351f6a5e7069e5d554dbc999280a69288c5d)
Change-Id: I5c65c0e65cc7652eee72c525f0db10e128061cf9
Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt b/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
index a39356c..5b4d3cf 100644
--- a/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
+++ b/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
@@ -5,74 +5,135 @@
Required properties:
-- qcom,core-max-time-us: Maximum time limit in micorseconds for switching clock rate.
- Limited to this value if switching time takes longer than this limit. Typical value is 100000.
-- qcom,algo-slack-time-us: Time in microseconds after which the QoS guarantee will kick in
- and the clock rate will increased as necessary. Typical value is about 30000.
-- qcom,algo-disable-pc-threshold: If core frequency (kHz) is higher than this value, power collapse is disallowed. Set to 0 for GPU.
-- qcom,algo-ss-window-size: Steady state window size in microseconds.
-- qcom,algo-ss-util-pct: When determining the steady state level, this percentage value is used to provide headroom
- from the utilized cpu to the selected level.
-- qcom,algo-ee-max-util-pct: When determining the level with the lowest energy, any level that exceeds this busy
- percentage, for the measured work in the last window, is disqualified for performance reasons.
-- qcom,algo-ss-iobusy-conv: Used to convert correlation time into assumed IO Busy time, which is removed
- from measured elapsed time when computing cpu utilization.
+- qcom,core-core-type: indicates whether this core is a CPU(0) or a GPU(1)
+- qcom,algo-disable-pc-threshold: sets highest frequency at which DCVS
+ will allow the CPU to power collapse.
+- qcom,algo-em-win-size-min-us: sets minimum Energy Minimization(EM)
+ window size.
+- qcom,algo-em-win-size-max-us: sets maximum EM window size.
+- qcom,algo-em-max-util-pct: sets maximum CPU utilization that will
+ not be exceeded by any core when
+ MP-decision decides the number of
+ online cores.
+- qcom,algo-group-id: specifies a group index of a core.
+- qcom,algo-max-freq-chg-time-us: shows time taken for the most recent
+ frequency change.
+- qcom,algo-slack-mode-dynamic: specifies if dynamic slack mode is
+ enabled or not.
+- qcom,algo-slack-weight-thresh-pct: sets occurrence percentage of CPU
+ activity that will make slack timer
+ triggered.
+- qcom,algo-slack-time-min-us: specifies the slack time that slack
+ timer would be set if the current clock
+ frequency is zero.
+- qcom,algo-slack-time-max-us: sets maximum slack timer value to be
+ used by slack timer.
+- qcom,algo-ss-win-size-min-us: sets minimum steady state window size.
+- qcom,algo-ss-win-size-max-us: sets maximum steady state window size.
+- qcom,algo-ss-util-pct: sets target CPU utilization during
+ steady-state.
+- qcom,algo-ss-iobusy-conv: specifies how wait time (i/o busy time)
+ is incorporated into the steady-state
+ algorithm.
+
+- qcom,energy-active-coeff-a: sets active power equation coefficient a.
+- qcom,energy-active-coeff-b: sets active power equation coefficient b.
+- qcom,energy-active-coeff-c: sets active power equation coefficient c.
+- qcom,energy-leakage-coeff-a: sets leakage power equation coefficient a.
+- qcom,energy-leakage-coeff-b: sets leakage power equation coefficient b.
+- qcom,energy-leakage-coeff-c: sets leakage power equation coefficient c.
+- qcom,energy-leakage-coeff-d: sets leakage power equation coefficient d.
+
+- qcom,power-current-temp: the current temperature in degCelcius.
+- qcom,power-num-freq: the number of freq this core supports.
A number of frequency levels are represented as sub-nodes:
required properties:
- reg: The index of the frequency entry
- qcom,freq The frequency of the DVS entry (in kHZ)
-- qcom,idle-energy: The idle energy cost of the entry (in micro watts)
-- qcom,active-energy: The active energy cost of the entry (in micro watts)
+- qcom,is_trans_level This frequency is transient step for DCVS
+- qcom,active-energy-offset: The active energy cost of the entry
+- qcom,leakage-energy-offset: The leakage energy cost of the entry
Sample:
qcom,kgsl-3d0@fdb00000 {
...
- qcom,dcvs-core-info {
- #address-cells = <1>;
- #size-cells = <0>;
+ qcom,dcvs-core-info {
+ #address-cells = <1>;
+ #size-cells = <0>;
- compatible = "qcom,dcvs-core-info";
+ compatible = "qcom,dcvs-core-info";
- qcom,core-max-time-us = <100000>;
- qcom,algo-slack-time-us = <39000>;
- qcom,algo-disable-pc-threshold = <86000>;
- qcom,algo-ss-window-size = <1000000>;
- qcom,algo-ss-util-pct = <95>;
- qcom,algo-em-max-util-pct = <97>;
- qcom,algo-ss-iobusy-conv = <100>;
+ qcom,num_cores = <1>;
+ qcom,sensors = <0>;
- qcom,dcvs-freq@0 {
- reg = <0>;
- qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <333932>;
+ qcom,core-core-type = <1>;
+
+ qcom,algo-disable-pc-threshold = <0>;
+ qcom,algo-em-win-size-min-us = <100000>;
+ qcom,algo-em-win-size-max-us = <300000>;
+ qcom,algo-em-max-util-pct = <97>;
+ qcom,algo-group-id = <95>;
+ qcom,algo-max-freq-chg-time-us = <100000>;
+ qcom,algo-slack-mode-dynamic = <100000>;
+ qcom,algo-slack-weight-thresh-pct = <0>;
+ qcom,algo-slack-time-min-us = <39000>;
+ qcom,algo-slack-time-max-us = <39000>;
+ qcom,algo-ss-win-size-min-us = <1000000>;
+ qcom,algo-ss-win-size-max-us = <1000000>;
+ qcom,algo-ss-util-pct = <95>;
+ qcom,algo-ss-iobusy-conv = <100>;
+
+ qcom,energy-active-coeff-a = <2492>;
+ qcom,energy-active-coeff-b = <0>;
+ qcom,energy-active-coeff-c = <0>;
+ qcom,energy-leakage-coeff-a = <11>;
+ qcom,energy-leakage-coeff-b = <157150>;
+ qcom,energy-leakage-coeff-c = <0>;
+ qcom,energy-leakage-coeff-d = <0>;
+
+ qcom,power-current-temp = <25>;
+ qcom,power-num-freq = <4>;
+
+ qcom,dcvs-freq@0 {
+ reg = <0>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@1 {
+ reg = <1>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@2 {
+ reg = <2>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@3 {
+ reg = <3>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <844545>;
+ qcom,leakage-energy-offset = <0>;
+ };
};
-
- qcom,dcvs-freq@1 {
- reg = <1>;
- qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <497532>;
- };
-
- qcom,dcvs-freq@2 {
- reg = <2>;
- qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <707610>;
- };
-
- qcom,dcvs-freq@3 {
- reg = <3>;
- qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <844545>;
- };
- };
...
};
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index a972d7f..88eeb33 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -85,40 +85,68 @@
compatible = "qcom,dcvs-core-info";
- qcom,core-max-time-us = <100000>;
- qcom,algo-slack-time-us = <39000>;
- qcom,algo-disable-pc-threshold = <86000>;
- qcom,algo-ss-window-size = <1000000>;
- qcom,algo-ss-util-pct = <95>;
+ qcom,core-core-type = <1>;
+
+ qcom,algo-disable-pc-threshold = <0>;
+ qcom,algo-em-win-size-min-us = <100000>;
+ qcom,algo-em-win-size-max-us = <300000>;
qcom,algo-em-max-util-pct = <97>;
+ qcom,algo-group-id = <95>;
+ qcom,algo-max-freq-chg-time-us = <100000>;
+ qcom,algo-slack-mode-dynamic = <100000>;
+ qcom,algo-slack-weight-thresh-pct = <0>;
+ qcom,algo-slack-time-min-us = <39000>;
+ qcom,algo-slack-time-max-us = <39000>;
+ qcom,algo-ss-win-size-min-us = <1000000>;
+ qcom,algo-ss-win-size-max-us = <1000000>;
+ qcom,algo-ss-util-pct = <95>;
qcom,algo-ss-iobusy-conv = <100>;
+ qcom,energy-active-coeff-a = <2492>;
+ qcom,energy-active-coeff-b = <0>;
+ qcom,energy-active-coeff-c = <0>;
+ qcom,energy-leakage-coeff-a = <11>;
+ qcom,energy-leakage-coeff-b = <157150>;
+ qcom,energy-leakage-coeff-c = <0>;
+ qcom,energy-leakage-coeff-d = <0>;
+
+ qcom,power-current-temp = <25>;
+ qcom,power-num-freq = <4>;
+
qcom,dcvs-freq@0 {
reg = <0>;
qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <333932>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
};
qcom,dcvs-freq@1 {
reg = <1>;
qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <497532>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
};
qcom,dcvs-freq@2 {
reg = <2>;
qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <707610>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
};
qcom,dcvs-freq@3 {
reg = <3>;
qcom,freq = <0>;
- qcom,idle-energy = <0>;
- qcom,active-energy = <844545>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <844545>;
+ qcom,leakage-energy-offset = <0>;
};
};
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 122505e..26d4c27 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,26 +24,49 @@
#ifdef CONFIG_MSM_DCVS
static struct msm_dcvs_freq_entry grp3d_freq[] = {
- {0, 0, 333932},
- {0, 0, 497532},
- {0, 0, 707610},
- {0, 0, 844545},
+ {0, 900, 0, 0, 0},
+ {0, 950, 0, 0, 0},
+ {0, 950, 0, 0, 0},
+ {0, 1200, 1, 100, 100},
};
static struct msm_dcvs_core_info grp3d_core_info = {
- .freq_tbl = &grp3d_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(grp3d_freq),
+ .freq_tbl = &grp3d_freq[0],
+ .core_param = {
+ .core_type = MSM_DCVS_CORE_TYPE_GPU,
},
- .algo_param = {
- .slack_time_us = 39000,
- .disable_pc_threshold = 86000,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .em_max_util_pct = 97,
- .ss_iobusy_conv = 100,
+ .algo_param = {
+ .disable_pc_threshold = 0,
+ .em_win_size_min_us = 100000,
+ .em_win_size_max_us = 300000,
+ .em_max_util_pct = 97,
+ .group_id = 0,
+ .max_freq_chg_time_us = 100000,
+ .slack_mode_dynamic = 0,
+ .slack_time_min_us = 39000,
+ .slack_time_max_us = 39000,
+ .ss_win_size_min_us = 1000000,
+ .ss_win_size_max_us = 1000000,
+ .ss_util_pct = 95,
+ .ss_iobusy_conv = 100,
},
+
+
+ .energy_coeffs = {
+ .leakage_coeff_a = -17720,
+ .leakage_coeff_b = 37,
+ .leakage_coeff_c = 3329,
+ .leakage_coeff_d = -277,
+
+ .active_coeff_a = 2492,
+ .active_coeff_b = 0,
+ .active_coeff_c = 0
+ },
+
+ .power_param = {
+ .current_temp = 25,
+ .num_freq = ARRAY_SIZE(grp3d_freq),
+ }
};
#endif /* CONFIG_MSM_DCVS */
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index a7147b5..ab2fbaf 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2251,7 +2251,6 @@
#endif
&msm8930_rtb_device,
&msm8930_cpu_idle_device,
- &msm8930_msm_gov_device,
&msm_bus_8930_apps_fabric,
&msm_bus_8930_sys_fabric,
&msm_bus_8930_mm_fabric,
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index e9a034e..a46c93e 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2671,7 +2671,6 @@
&msm8960_device_watchdog,
&msm8960_rtb_device,
&msm8960_cpu_idle_device,
- &msm8960_msm_gov_device,
&msm8960_device_cache_erp,
&msm8960_device_ebi1_ch0_erp,
&msm8960_device_ebi1_ch1_erp,
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index d2d05b1..4032af6 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2599,32 +2599,50 @@
};
static struct msm_dcvs_freq_entry apq8064_freq[] = {
- { 384000, 166981, 345600},
- { 702000, 213049, 632502},
- {1026000, 285712, 925613},
- {1242000, 383945, 1176550},
- {1458000, 419729, 1465478},
- {1512000, 434116, 1546674},
-
+ { 384000, 900, 0, 0, 0},
+ { 594000, 950, 0, 0, 0},
+ { 702000, 975, 0, 0, 0},
+ {1026000, 1075, 0, 0, 0},
+ {1242000, 1150, 0, 100, 100},
+ {1458000, 1188, 0, 100, 100},
+ {1512000, 1200, 1, 100, 100},
};
static struct msm_dcvs_core_info apq8064_core_info = {
- .freq_tbl = &apq8064_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(apq8064_freq),
+ .freq_tbl = &apq8064_freq[0],
+ .core_param = {
+ .core_type = MSM_DCVS_CORE_TYPE_CPU,
},
- .algo_param = {
- .slack_time_us = 58000,
- .scale_slack_time = 0,
- .scale_slack_time_pct = 0,
- .disable_pc_threshold = 1458000,
- .em_window_size = 100000,
- .em_max_util_pct = 97,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .ss_iobusy_conv = 100,
+ .algo_param = {
+ .disable_pc_threshold = 1458000,
+ .em_win_size_min_us = 100000,
+ .em_win_size_max_us = 300000,
+ .em_max_util_pct = 97,
+ .group_id = 1,
+ .max_freq_chg_time_us = 100000,
+ .slack_mode_dynamic = 0,
+ .slack_weight_thresh_pct = 3,
+ .slack_time_min_us = 45000,
+ .slack_time_max_us = 45000,
+ .ss_iobusy_conv = 100,
+ .ss_win_size_min_us = 1000000,
+ .ss_win_size_max_us = 1000000,
+ .ss_util_pct = 95,
},
+ .energy_coeffs = {
+ .active_coeff_a = 336,
+ .active_coeff_b = 0,
+ .active_coeff_c = 0,
+
+ .leakage_coeff_a = -17720,
+ .leakage_coeff_b = 37,
+ .leakage_coeff_c = 3329,
+ .leakage_coeff_d = -277,
+ },
+ .power_param = {
+ .current_temp = 25,
+ .num_freq = ARRAY_SIZE(apq8064_freq),
+ }
};
struct platform_device apq8064_msm_gov_device = {
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index eac2140..0fbf856 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,7 +18,6 @@
#include <mach/msm_iomap.h>
#include <mach/irqs-8930.h>
#include <mach/rpm.h>
-#include <mach/msm_dcvs.h>
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
#include <mach/board.h>
@@ -323,43 +322,6 @@
},
};
-static struct msm_dcvs_freq_entry msm8930_freq[] = {
- { 384000, 166981, 345600},
- { 702000, 213049, 632502},
- {1026000, 285712, 925613},
- {1242000, 383945, 1176550},
- {1458000, 419729, 1465478},
- {1512000, 434116, 1546674},
-
-};
-
-static struct msm_dcvs_core_info msm8930_core_info = {
- .freq_tbl = &msm8930_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(msm8930_freq),
- },
- .algo_param = {
- .slack_time_us = 58000,
- .scale_slack_time = 0,
- .scale_slack_time_pct = 0,
- .disable_pc_threshold = 1458000,
- .em_window_size = 100000,
- .em_max_util_pct = 97,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .ss_iobusy_conv = 100,
- },
-};
-
-struct platform_device msm8930_msm_gov_device = {
- .name = "msm_dcvs_gov",
- .id = -1,
- .dev = {
- .platform_data = &msm8930_core_info,
- },
-};
-
struct platform_device msm_bus_8930_sys_fabric = {
.name = "msm_bus_fabric",
.id = MSM_BUS_FAB_SYSTEM,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 29edf1b..d0491a9 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2916,46 +2916,89 @@
};
static struct msm_dcvs_freq_entry grp3d_freq[] = {
- {0, 0, 333932},
- {0, 0, 497532},
- {0, 0, 707610},
- {0, 0, 844545},
+ {0, 900, 0, 0, 0},
+ {0, 950, 0, 0, 0},
+ {0, 950, 0, 0, 0},
+ {0, 1200, 1, 100, 100},
};
static struct msm_dcvs_freq_entry grp2d_freq[] = {
- {0, 0, 86000},
- {0, 0, 200000},
+ {0, 900, 0, 0, 0},
+ {0, 950, 1, 100, 100},
};
static struct msm_dcvs_core_info grp3d_core_info = {
- .freq_tbl = &grp3d_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(grp3d_freq),
+ .freq_tbl = &grp3d_freq[0],
+ .core_param = {
+ .core_type = MSM_DCVS_CORE_TYPE_GPU,
},
- .algo_param = {
- .slack_time_us = 39000,
- .disable_pc_threshold = 86000,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .em_max_util_pct = 97,
- .ss_iobusy_conv = 100,
+ .algo_param = {
+ .disable_pc_threshold = 0,
+ .em_win_size_min_us = 100000,
+ .em_win_size_max_us = 300000,
+ .em_max_util_pct = 97,
+ .group_id = 0,
+ .max_freq_chg_time_us = 100000,
+ .slack_mode_dynamic = 0,
+ .slack_weight_thresh_pct = 0,
+ .slack_time_min_us = 39000,
+ .slack_time_max_us = 39000,
+ .ss_win_size_min_us = 1000000,
+ .ss_win_size_max_us = 1000000,
+ .ss_util_pct = 95,
+ .ss_iobusy_conv = 100,
},
+ .energy_coeffs = {
+ .active_coeff_a = 2492,
+ .active_coeff_b = 0,
+ .active_coeff_c = 0,
+
+ .leakage_coeff_a = -17720,
+ .leakage_coeff_b = 37,
+ .leakage_coeff_c = 2729,
+ .leakage_coeff_d = -277,
+ },
+ .power_param = {
+ .current_temp = 25,
+ .num_freq = ARRAY_SIZE(grp3d_freq),
+ }
};
static struct msm_dcvs_core_info grp2d_core_info = {
- .freq_tbl = &grp2d_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(grp2d_freq),
+ .freq_tbl = &grp2d_freq[0],
+ .core_param = {
+ .core_type = MSM_DCVS_CORE_TYPE_GPU,
},
- .algo_param = {
- .slack_time_us = 39000,
- .disable_pc_threshold = 90000,
- .ss_window_size = 1000000,
- .ss_util_pct = 90,
- .em_max_util_pct = 95,
+ .algo_param = {
+ .disable_pc_threshold = 0,
+ .em_win_size_min_us = 100000,
+ .em_win_size_max_us = 300000,
+ .em_max_util_pct = 97,
+ .group_id = 0,
+ .max_freq_chg_time_us = 100000,
+ .slack_mode_dynamic = 0,
+ .slack_weight_thresh_pct = 0,
+ .slack_time_min_us = 39000,
+ .slack_time_max_us = 39000,
+ .ss_win_size_min_us = 1000000,
+ .ss_win_size_max_us = 1000000,
+ .ss_util_pct = 95,
+ .ss_iobusy_conv = 100,
},
+ .energy_coeffs = {
+ .active_coeff_a = 2492,
+ .active_coeff_b = 0,
+ .active_coeff_c = 0,
+
+ .leakage_coeff_a = -17720,
+ .leakage_coeff_b = 37,
+ .leakage_coeff_c = 2729,
+ .leakage_coeff_d = -277,
+ },
+ .power_param = {
+ .current_temp = 25,
+ .num_freq = ARRAY_SIZE(grp2d_freq),
+ }
};
#ifdef CONFIG_MSM_BUS_SCALING
@@ -4001,43 +4044,6 @@
},
};
-static struct msm_dcvs_freq_entry msm8960_freq[] = {
- { 384000, 166981, 345600},
- { 702000, 213049, 632502},
- {1026000, 285712, 925613},
- {1242000, 383945, 1176550},
- {1458000, 419729, 1465478},
- {1512000, 434116, 1546674},
-
-};
-
-static struct msm_dcvs_core_info msm8960_core_info = {
- .freq_tbl = &msm8960_freq[0],
- .core_param = {
- .max_time_us = 100000,
- .num_freq = ARRAY_SIZE(msm8960_freq),
- },
- .algo_param = {
- .slack_time_us = 58000,
- .scale_slack_time = 0,
- .scale_slack_time_pct = 0,
- .disable_pc_threshold = 1458000,
- .em_window_size = 100000,
- .em_max_util_pct = 97,
- .ss_window_size = 1000000,
- .ss_util_pct = 95,
- .ss_iobusy_conv = 100,
- },
-};
-
-struct platform_device msm8960_msm_gov_device = {
- .name = "msm_dcvs_gov",
- .id = -1,
- .dev = {
- .platform_data = &msm8960_core_info,
- },
-};
-
static struct resource msm_cache_erp_resources[] = {
{
.name = "l1_irq",
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 8ee7891..f659831 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -393,8 +393,6 @@
extern struct platform_device msm8930_cpu_idle_device;
extern struct platform_device apq8064_cpu_idle_device;
-extern struct platform_device msm8960_msm_gov_device;
-extern struct platform_device msm8930_msm_gov_device;
extern struct platform_device apq8064_msm_gov_device;
extern struct platform_device msm_bus_8930_apps_fabric;
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs.h b/arch/arm/mach-msm/include/mach/msm_dcvs.h
index 78d0d4a..490a34b 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs.h
@@ -90,15 +90,16 @@
* before the sink driver can be registered.
*/
struct msm_dcvs_core_info {
- struct msm_dcvs_freq_entry *freq_tbl;
- struct msm_dcvs_core_param core_param;
- struct msm_dcvs_algo_param algo_param;
+ struct msm_dcvs_freq_entry *freq_tbl;
+ struct msm_dcvs_core_param core_param;
+ struct msm_dcvs_algo_param algo_param;
+ struct msm_dcvs_energy_curve_coeffs energy_coeffs;
+ struct msm_dcvs_power_params power_param;
};
/**
* msm_dcvs_register_core
* @core_name: Unique name identifier for the core.
- * @group_id: Cores that are to be grouped for synchronized frequency scaling
* @info: The core specific algorithm parameters.
* @return :
* 0 on success,
@@ -108,9 +109,8 @@
* Register the core with msm_dcvs driver. Done once at init before calling
* msm_dcvs_freq_sink_register
* Cores that need to run synchronously must share the same group id.
- * If a core doesnt care to be in any group, the group_id should be 0.
*/
-extern int msm_dcvs_register_core(const char *core_name, uint32_t group_id,
+extern int msm_dcvs_register_core(const char *core_name,
struct msm_dcvs_core_info *info);
/**
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
index d97cd32..597fdc0 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
@@ -13,6 +13,11 @@
#ifndef _ARCH_ARM_MACH_MSM_MSM_DCVS_SCM_H
#define _ARCH_ARM_MACH_MSM_MSM_DCVS_SCM_H
+enum msm_dcvs_core_type {
+ MSM_DCVS_CORE_TYPE_CPU = 0,
+ MSM_DCVS_CORE_TYPE_GPU = 1,
+};
+
enum msm_dcvs_algo_param_type {
MSM_DCVS_ALGO_DCVS_PARAM = 0,
MSM_DCVS_ALGO_MPD_PARAM = 1,
@@ -33,28 +38,50 @@
};
struct msm_dcvs_algo_param {
- uint32_t slack_time_us;
- uint32_t scale_slack_time;
- uint32_t scale_slack_time_pct;
uint32_t disable_pc_threshold;
- uint32_t em_window_size;
+ uint32_t em_win_size_min_us;
+ uint32_t em_win_size_max_us;
uint32_t em_max_util_pct;
- uint32_t ss_window_size;
- uint32_t ss_util_pct;
+ uint32_t group_id;
+ uint32_t max_freq_chg_time_us;
+ uint32_t slack_mode_dynamic;
+ uint32_t slack_time_min_us;
+ uint32_t slack_time_max_us;
+ uint32_t slack_weight_thresh_pct;
uint32_t ss_iobusy_conv;
+ uint32_t ss_win_size_min_us;
+ uint32_t ss_win_size_max_us;
+ uint32_t ss_util_pct;
};
struct msm_dcvs_freq_entry {
- uint32_t freq; /* Core freq in MHz */
- uint32_t idle_energy;
- uint32_t active_energy;
+ uint32_t freq;
+ uint32_t voltage;
+ uint32_t is_trans_level;
+ uint32_t active_energy_offset;
+ uint32_t leakage_energy_offset;
};
-struct msm_dcvs_core_param {
- uint32_t max_time_us;
+struct msm_dcvs_energy_curve_coeffs {
+ int32_t active_coeff_a;
+ int32_t active_coeff_b;
+ int32_t active_coeff_c;
+
+ int32_t leakage_coeff_a;
+ int32_t leakage_coeff_b;
+ int32_t leakage_coeff_c;
+ int32_t leakage_coeff_d;
+};
+
+struct msm_dcvs_power_params {
+ uint32_t current_temp;
uint32_t num_freq; /* number of msm_dcvs_freq_entry passed */
};
+struct msm_dcvs_core_param {
+ uint32_t core_type;
+ uint32_t core_bitmask_id;
+};
struct msm_mpd_algo_param {
uint32_t em_win_size_min_us;
@@ -83,20 +110,9 @@
extern int msm_dcvs_scm_init(size_t size);
/**
- * Create an empty core group
- *
- * @return:
- * 0 on success.
- * -ENOMEM: Insufficient memory.
- * -EINVAL: Invalid args.
- */
-extern int msm_dcvs_scm_create_group(uint32_t id);
-
-/**
- * Registers cores as part of a group
+ * Registers cores with the DCVS algo.
*
* @core_id: The core identifier that will be used for communication with DCVS
- * @group_id: The group to which this core will be added to.
* @param: The core parameters
* @freq: Array of frequency and energy values
*
@@ -105,9 +121,8 @@
* -ENOMEM: Insufficient memory.
* -EINVAL: Invalid args.
*/
-extern int msm_dcvs_scm_register_core(uint32_t core_id, uint32_t group_id,
- struct msm_dcvs_core_param *param,
- struct msm_dcvs_freq_entry *freq);
+extern int msm_dcvs_scm_register_core(uint32_t core_id,
+ struct msm_dcvs_core_param *param);
/**
* Set DCVS algorithm parameters
@@ -132,6 +147,24 @@
extern int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param);
/**
+ * Set frequency and power characteristics for the core.
+ *
+ * @param core_id: The core identifier that will be used to interace with the
+ * DCVS algo.
+ * @param pwr_param: power params
+ * @param freq_entry: frequency characteristics desired
+ * @param coeffs: Coefficients that will describe the power curve
+ *
+ * @return int
+ * 0 on success.
+ * -EINVAL: Invalid args.
+ */
+extern int msm_dcvs_scm_set_power_params(uint32_t core_id,
+ struct msm_dcvs_power_params *pwr_param,
+ struct msm_dcvs_freq_entry *freq_entry,
+ struct msm_dcvs_energy_curve_coeffs *coeffs);
+
+/**
* Do an SCM call.
*
* @core_id: The core identifier.
@@ -157,19 +190,44 @@
* @param1: time taken in usec to switch to the frequency
* @ret0: New QoS timer value for the core in usec
* @ret1: unused
- * MSM_DCVS_SCM_ENABLE_CORE
- * @param0: enable(1) or disable(0) core
- * @param1: active clock frequency of the core in KHz
- * @ret0: New clock frequency for the core in KHz
- * @ret1: unused
- * MSM_DCVS_SCM_RESET_CORE
+ * MSM_DCVS_SCM_CORE_ONLINE
* @param0: active clock frequency of the core in KHz
+ * @param1: time taken to online the core
+ * @ret0: unused
+ * @ret1: unused
+ * MSM_DCVS_SCM_CORE_OFFLINE
+ * @param0: time taken to offline the core
+ * @param1: unused
+ * @ret0: unused
+ * @ret1: unused
+ * MSM_DCVS_SCM_CORE_UNAVAILABLE
+ * @param0: TODO:bitmask
+ * @param1: unused
+ * @ret0: Bitmask of cores to bring online/offline.
+ * @ret1: Mp Decision slack time. Common to all cores.
+ * MSM_DCVS_SCM_DCVS_ENABLE
+ * @param0: 1 to enable; 0 to disable DCVS
* @param1: unused
* @ret0: New clock frequency for the core in KHz
* @ret1: unused
- * @return:
- * 0 on success,
- * SCM return values
+ * MSM_DCVS_SCM_MPD_ENABLE
+ * @param0: 1 to enable; 0 to disable MP Decision
+ * @param1: unused
+ * @ret0: unused
+ * @ret1: unused
+ * MSM_DCVS_SCM_RUNQ_UPDATE
+ * @param0: run q value
+ * @param1: unused
+ * @ret0: Bitmask of cores online
+ * @ret1: New QoS timer for MP Decision (usec)
+ * MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED
+ * @param0: unused
+ * @param1: unused
+ * @ret0: Bitmask of cores online
+ * @ret1: New QoS timer for MP Decision (usec)
+ * @return:
+ * 0 on success,
+ * SCM return values
*/
extern int msm_dcvs_scm_event(uint32_t core_id,
enum msm_dcvs_scm_event event_id,
@@ -179,10 +237,7 @@
#else
static inline int msm_dcvs_scm_init(uint32_t phy, size_t bytes)
{ return -ENOSYS; }
-static inline int msm_dcvs_scm_create_group(uint32_t id)
-{ return -ENOSYS; }
static inline int msm_dcvs_scm_register_core(uint32_t core_id,
- uint32_t group_id,
struct msm_dcvs_core_param *param,
struct msm_dcvs_freq_entry *freq)
{ return -ENOSYS; }
@@ -192,6 +247,11 @@
static inline int msm_mpd_scm_set_algo_params(
struct msm_mpd_algo_param *param)
{ return -ENOSYS; }
+static inline int msm_dcvs_set_power_params(uint32_t core_id,
+ struct msm_dcvs_power_params *pwr_param,
+ struct msm_dcvs_freq_entry *freq_entry,
+ struct msm_dcvs_energy_curve_coeffs *coeffs)
+{ return -ENOSYS; }
static inline int msm_dcvs_scm_event(uint32_t core_id,
enum msm_dcvs_scm_event event_id,
uint32_t param0, uint32_t param1,
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index 890e450..9601b7e 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -39,22 +39,34 @@
};
struct core_attribs {
+ struct kobj_attribute core_id;
struct kobj_attribute idle_enabled;
struct kobj_attribute freq_change_enabled;
struct kobj_attribute actual_freq;
struct kobj_attribute freq_change_us;
- struct kobj_attribute max_time_us;
-
- struct kobj_attribute slack_time_us;
- struct kobj_attribute scale_slack_time;
- struct kobj_attribute scale_slack_time_pct;
struct kobj_attribute disable_pc_threshold;
- struct kobj_attribute em_window_size;
+ struct kobj_attribute em_win_size_min_us;
+ struct kobj_attribute em_win_size_max_us;
struct kobj_attribute em_max_util_pct;
- struct kobj_attribute ss_window_size;
- struct kobj_attribute ss_util_pct;
+ struct kobj_attribute group_id;
+ struct kobj_attribute max_freq_chg_time_us;
+ struct kobj_attribute slack_mode_dynamic;
+ struct kobj_attribute slack_time_min_us;
+ struct kobj_attribute slack_time_max_us;
+ struct kobj_attribute slack_weight_thresh_pct;
struct kobj_attribute ss_iobusy_conv;
+ struct kobj_attribute ss_win_size_min_us;
+ struct kobj_attribute ss_win_size_max_us;
+ struct kobj_attribute ss_util_pct;
+
+ struct kobj_attribute active_coeff_a;
+ struct kobj_attribute active_coeff_b;
+ struct kobj_attribute active_coeff_c;
+ struct kobj_attribute leakage_coeff_a;
+ struct kobj_attribute leakage_coeff_b;
+ struct kobj_attribute leakage_coeff_c;
+ struct kobj_attribute leakage_coeff_d;
struct attribute_group attrib_group;
};
@@ -68,6 +80,7 @@
uint32_t max_time_us; /* core param */
struct msm_dcvs_algo_param algo_param;
+ struct msm_dcvs_energy_curve_coeffs coeffs;
struct msm_dcvs_idle *idle_driver;
struct msm_dcvs_freq *freq_driver;
@@ -78,12 +91,12 @@
struct task_struct *task;
struct core_attribs attrib;
uint32_t handle;
- uint32_t group_id;
uint32_t freq_pending;
struct hrtimer timer;
int32_t timer_disabled;
/* track if kthread for change_freq is active */
int32_t change_freq_activated;
+ struct msm_dcvs_core_info *info;
};
static int msm_dcvs_debug;
@@ -365,6 +378,39 @@
return count; \
}
+#define DCVS_ENERGY_PARAM(_name) \
+static ssize_t msm_dcvs_attr_##_name##_show(struct kobject *kobj,\
+ struct kobj_attribute *attr, char *buf) \
+{ \
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \
+ return snprintf(buf, PAGE_SIZE, "%d\n", core->coeffs._name); \
+} \
+static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, const char *buf, size_t count) \
+{ \
+ int ret = 0; \
+ int32_t val = 0; \
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \
+ mutex_lock(&core->lock); \
+ ret = kstrtoint(buf, 10, &val); \
+ if (ret) { \
+ __err("Invalid input %s for %s\n", buf, __stringify(_name));\
+ } else { \
+ int32_t old_val = core->coeffs._name; \
+ core->coeffs._name = val; \
+ ret = msm_dcvs_scm_set_power_params(core->handle, \
+ &core->info->power_param, &core->info->freq_tbl[0], \
+ &core->coeffs); \
+ if (ret) { \
+ core->coeffs._name = old_val; \
+ __err("Error(%d) in setting %d for coeffs param %s\n",\
+ ret, val, __stringify(_name)); \
+ } \
+ } \
+ mutex_unlock(&core->lock); \
+ return count; \
+}
+
#define DCVS_RO_ATTRIB(i, _name) \
core->attrib._name.attr.name = __stringify(_name); \
core->attrib._name.attr.mode = S_IRUGO; \
@@ -383,27 +429,40 @@
* Function declarations for different attributes.
* Gets used when setting the attribute show and store parameters.
*/
+DCVS_PARAM_SHOW(core_id, core->handle)
DCVS_PARAM_SHOW(idle_enabled, (core->idle_driver != NULL))
DCVS_PARAM_SHOW(freq_change_enabled, (core->freq_driver != NULL))
DCVS_PARAM_SHOW(actual_freq, (core->actual_freq))
DCVS_PARAM_SHOW(freq_change_us, (core->freq_change_us))
-DCVS_PARAM_SHOW(max_time_us, (core->max_time_us))
-DCVS_ALGO_PARAM(slack_time_us)
-DCVS_ALGO_PARAM(scale_slack_time)
-DCVS_ALGO_PARAM(scale_slack_time_pct)
DCVS_ALGO_PARAM(disable_pc_threshold)
-DCVS_ALGO_PARAM(em_window_size)
+DCVS_ALGO_PARAM(em_win_size_min_us)
+DCVS_ALGO_PARAM(em_win_size_max_us)
DCVS_ALGO_PARAM(em_max_util_pct)
-DCVS_ALGO_PARAM(ss_window_size)
-DCVS_ALGO_PARAM(ss_util_pct)
+DCVS_ALGO_PARAM(group_id)
+DCVS_ALGO_PARAM(max_freq_chg_time_us)
+DCVS_ALGO_PARAM(slack_mode_dynamic)
+DCVS_ALGO_PARAM(slack_time_min_us)
+DCVS_ALGO_PARAM(slack_time_max_us)
+DCVS_ALGO_PARAM(slack_weight_thresh_pct)
DCVS_ALGO_PARAM(ss_iobusy_conv)
+DCVS_ALGO_PARAM(ss_win_size_min_us)
+DCVS_ALGO_PARAM(ss_win_size_max_us)
+DCVS_ALGO_PARAM(ss_util_pct)
+
+DCVS_ENERGY_PARAM(active_coeff_a)
+DCVS_ENERGY_PARAM(active_coeff_b)
+DCVS_ENERGY_PARAM(active_coeff_c)
+DCVS_ENERGY_PARAM(leakage_coeff_a)
+DCVS_ENERGY_PARAM(leakage_coeff_b)
+DCVS_ENERGY_PARAM(leakage_coeff_c)
+DCVS_ENERGY_PARAM(leakage_coeff_d)
static int msm_dcvs_setup_core_sysfs(struct dcvs_core *core)
{
int ret = 0;
struct kobject *core_kobj = NULL;
- const int attr_count = 15;
+ const int attr_count = 27;
BUG_ON(!cores_kobj);
@@ -415,23 +474,37 @@
goto done;
}
- DCVS_RO_ATTRIB(0, idle_enabled);
- DCVS_RO_ATTRIB(1, freq_change_enabled);
- DCVS_RO_ATTRIB(2, actual_freq);
- DCVS_RO_ATTRIB(3, freq_change_us);
- DCVS_RO_ATTRIB(4, max_time_us);
- DCVS_RW_ATTRIB(5, slack_time_us);
- DCVS_RW_ATTRIB(6, scale_slack_time);
- DCVS_RW_ATTRIB(7, scale_slack_time_pct);
- DCVS_RW_ATTRIB(8, disable_pc_threshold);
- DCVS_RW_ATTRIB(9, em_window_size);
- DCVS_RW_ATTRIB(10, em_max_util_pct);
- DCVS_RW_ATTRIB(11, ss_window_size);
- DCVS_RW_ATTRIB(12, ss_util_pct);
- DCVS_RW_ATTRIB(13, ss_iobusy_conv);
+ DCVS_RO_ATTRIB(0, core_id);
+ DCVS_RO_ATTRIB(1, idle_enabled);
+ DCVS_RO_ATTRIB(2, freq_change_enabled);
+ DCVS_RO_ATTRIB(3, actual_freq);
+ DCVS_RO_ATTRIB(4, freq_change_us);
- core->attrib.attrib_group.attrs[14] = NULL;
+ DCVS_RW_ATTRIB(5, disable_pc_threshold);
+ DCVS_RW_ATTRIB(6, em_win_size_min_us);
+ DCVS_RW_ATTRIB(7, em_win_size_max_us);
+ DCVS_RW_ATTRIB(8, em_max_util_pct);
+ DCVS_RW_ATTRIB(9, group_id);
+ DCVS_RW_ATTRIB(10, max_freq_chg_time_us);
+ DCVS_RW_ATTRIB(11, slack_mode_dynamic);
+ DCVS_RW_ATTRIB(12, slack_time_min_us);
+ DCVS_RW_ATTRIB(13, slack_time_max_us);
+ DCVS_RW_ATTRIB(14, slack_weight_thresh_pct);
+ DCVS_RW_ATTRIB(15, ss_iobusy_conv);
+ DCVS_RW_ATTRIB(16, ss_win_size_min_us);
+ DCVS_RW_ATTRIB(17, ss_win_size_max_us);
+ DCVS_RW_ATTRIB(18, ss_util_pct);
+
+ DCVS_RW_ATTRIB(19, active_coeff_a);
+ DCVS_RW_ATTRIB(20, active_coeff_b);
+ DCVS_RW_ATTRIB(21, active_coeff_c);
+ DCVS_RW_ATTRIB(22, leakage_coeff_a);
+ DCVS_RW_ATTRIB(23, leakage_coeff_b);
+ DCVS_RW_ATTRIB(24, leakage_coeff_c);
+ DCVS_RW_ATTRIB(25, leakage_coeff_d);
+
+ core->attrib.attrib_group.attrs[26] = NULL;
core_kobj = kobject_create_and_add(core->core_name, cores_kobj);
if (!core_kobj) {
@@ -497,11 +570,13 @@
return core;
}
-int msm_dcvs_register_core(const char *core_name, uint32_t group_id,
+int msm_dcvs_register_core(const char *core_name,
struct msm_dcvs_core_info *info)
{
int ret = -EINVAL;
struct dcvs_core *core = NULL;
+ uint32_t ret1;
+ uint32_t ret2;
if (!core_name || !core_name[0])
return ret;
@@ -511,25 +586,15 @@
return ret;
mutex_lock(&core->lock);
- if (group_id) {
- /**
- * Create a group for cores, if this core is part of a group
- * if the group_id is 0, the core is not part of a group.
- * If the group_id already exits, it will through an error
- * which we will ignore.
- */
- ret = msm_dcvs_scm_create_group(group_id);
- if (ret == -ENOMEM)
- goto bail;
- }
- core->group_id = group_id;
- core->max_time_us = info->core_param.max_time_us;
+ core->info = info;
memcpy(&core->algo_param, &info->algo_param,
sizeof(struct msm_dcvs_algo_param));
- ret = msm_dcvs_scm_register_core(core->handle, group_id,
- &info->core_param, info->freq_tbl);
+ memcpy(&core->coeffs, &info->energy_coeffs,
+ sizeof(struct msm_dcvs_energy_curve_coeffs));
+
+ ret = msm_dcvs_scm_register_core(core->handle, &info->core_param);
if (ret)
goto bail;
@@ -537,6 +602,16 @@
if (ret)
goto bail;
+ ret = msm_dcvs_scm_set_power_params(core->handle, &info->power_param,
+ &info->freq_tbl[0], &core->coeffs);
+ if (ret)
+ goto bail;
+
+ ret = msm_dcvs_scm_event(core->handle, MSM_DCVS_SCM_CORE_ONLINE,
+ core->actual_freq, 0, &ret1, &ret2);
+ if (ret)
+ goto bail;
+
ret = msm_dcvs_setup_core_sysfs(core);
if (ret) {
__err("Unable to setup core %s sysfs\n", core->core_name);
diff --git a/arch/arm/mach-msm/msm_dcvs_scm.c b/arch/arm/mach-msm/msm_dcvs_scm.c
index bf623df..df6c44f 100644
--- a/arch/arm/mach-msm/msm_dcvs_scm.c
+++ b/arch/arm/mach-msm/msm_dcvs_scm.c
@@ -21,17 +21,15 @@
#include <mach/scm.h>
#include <mach/msm_dcvs_scm.h>
-#define DCVS_CMD_CREATE_GROUP 1
#define DCVS_CMD_REGISTER_CORE 2
#define DCVS_CMD_SET_ALGO_PARAM 3
#define DCVS_CMD_EVENT 4
#define DCVS_CMD_INIT 5
+#define DCVS_CMD_SET_POWER_PARAM 6
struct scm_register_core {
uint32_t core_id;
- uint32_t group_id;
phys_addr_t core_param_phy;
- phys_addr_t freq_phy;
};
struct scm_algo {
@@ -44,6 +42,13 @@
uint32_t size;
};
+struct scm_pwr_param {
+ uint32_t core_id;
+ phys_addr_t pwr_param_phy;
+ phys_addr_t freq_phy;
+ phys_addr_t coeffs_phy;
+};
+
struct msm_algo_param {
enum msm_dcvs_algo_param_type type;
union {
@@ -77,49 +82,25 @@
}
EXPORT_SYMBOL(msm_dcvs_scm_init);
-int msm_dcvs_scm_create_group(uint32_t id)
-{
- int ret = 0;
-
- ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_CREATE_GROUP,
- &id, sizeof(uint32_t), NULL, 0);
-
- return ret;
-}
-EXPORT_SYMBOL(msm_dcvs_scm_create_group);
-
-int msm_dcvs_scm_register_core(uint32_t core_id, uint32_t group_id,
- struct msm_dcvs_core_param *param,
- struct msm_dcvs_freq_entry *freq)
+int msm_dcvs_scm_register_core(uint32_t core_id,
+ struct msm_dcvs_core_param *param)
{
int ret = 0;
struct scm_register_core reg_data;
struct msm_dcvs_core_param *p = NULL;
- struct msm_dcvs_freq_entry *f = NULL;
p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_core_param)), GFP_KERNEL);
if (!p)
return -ENOMEM;
- f = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_freq_entry) *
- param->num_freq), GFP_KERNEL);
- if (!f) {
- kfree(p);
- return -ENOMEM;
- }
-
memcpy(p, param, sizeof(struct msm_dcvs_core_param));
- memcpy(f, freq, sizeof(struct msm_dcvs_freq_entry) * param->num_freq);
reg_data.core_id = core_id;
- reg_data.group_id = group_id;
reg_data.core_param_phy = virt_to_phys(p);
- reg_data.freq_phy = virt_to_phys(f);
ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_REGISTER_CORE,
®_data, sizeof(reg_data), NULL, 0);
- kfree(f);
kfree(p);
return ret;
@@ -137,7 +118,6 @@
if (!p)
return -ENOMEM;
-
p->type = MSM_DCVS_ALGO_DCVS_PARAM;
memcpy(&p->u.dcvs_param, param, sizeof(struct msm_dcvs_algo_param));
@@ -178,6 +158,60 @@
}
EXPORT_SYMBOL(msm_mpd_scm_set_algo_params);
+int msm_dcvs_scm_set_power_params(uint32_t core_id,
+ struct msm_dcvs_power_params *pwr_param,
+ struct msm_dcvs_freq_entry *freq_entry,
+ struct msm_dcvs_energy_curve_coeffs *coeffs)
+{
+ int ret = 0;
+ struct scm_pwr_param pwr;
+ struct msm_dcvs_power_params *pwrt = NULL;
+ struct msm_dcvs_freq_entry *freqt = NULL;
+ struct msm_dcvs_energy_curve_coeffs *coefft = NULL;
+
+ pwrt = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_power_params)),
+ GFP_KERNEL);
+ if (!pwrt)
+ return -ENOMEM;
+
+ freqt = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_freq_entry)
+ * pwr_param->num_freq),
+ GFP_KERNEL);
+ if (!freqt) {
+ kfree(pwrt);
+ return -ENOMEM;
+ }
+
+ coefft = kzalloc(PAGE_ALIGN(
+ sizeof(struct msm_dcvs_energy_curve_coeffs)),
+ GFP_KERNEL);
+ if (!coefft) {
+ kfree(pwrt);
+ kfree(freqt);
+ return -ENOMEM;
+ }
+
+ memcpy(pwrt, pwr_param, sizeof(struct msm_dcvs_power_params));
+ memcpy(freqt, freq_entry,
+ sizeof(struct msm_dcvs_freq_entry)*pwr_param->num_freq);
+ memcpy(coefft, coeffs, sizeof(struct msm_dcvs_energy_curve_coeffs));
+
+ pwr.core_id = core_id;
+ pwr.pwr_param_phy = virt_to_phys(pwrt);
+ pwr.freq_phy = virt_to_phys(freqt);
+ pwr.coeffs_phy = virt_to_phys(coefft);
+
+ ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_POWER_PARAM,
+ &pwr, sizeof(pwr), NULL, 0);
+
+ kfree(pwrt);
+ kfree(freqt);
+ kfree(coefft);
+
+ return ret;
+}
+EXPORT_SYMBOL(msm_dcvs_scm_set_power_params);
+
int msm_dcvs_scm_event(uint32_t core_id,
enum msm_dcvs_scm_event event_id,
uint32_t param0, uint32_t param1,
diff --git a/drivers/cpufreq/cpufreq_gov_msm.c b/drivers/cpufreq/cpufreq_gov_msm.c
index 9c49f80..4eeff35 100644
--- a/drivers/cpufreq/cpufreq_gov_msm.c
+++ b/drivers/cpufreq/cpufreq_gov_msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -138,7 +138,6 @@
{
int ret = 0;
int cpu;
- uint32_t group_id = 0x43505530; /* CPU0 */
struct msm_dcvs_core_info *core = NULL;
core = pdev->dev.platform_data;
@@ -146,7 +145,7 @@
for_each_possible_cpu(cpu) {
mutex_init(&per_cpu(gov_mutex, cpu));
snprintf(core_name[cpu], 10, "cpu%d", cpu);
- ret = msm_dcvs_register_core(core_name[cpu], group_id, core);
+ ret = msm_dcvs_register_core(core_name[cpu], core);
if (ret)
pr_err("Unable to register core for %d\n", cpu);
}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 3d1fbc8..8361430 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -865,15 +865,15 @@
for_each_child_of_node(node, child)
count++;
- info->core_param.num_freq = count;
+ info->power_param.num_freq = count;
- info->freq_tbl = kzalloc(info->core_param.num_freq *
+ info->freq_tbl = kzalloc(info->power_param.num_freq *
sizeof(struct msm_dcvs_freq_entry),
GFP_KERNEL);
if (info->freq_tbl == NULL) {
KGSL_CORE_ERR("kzalloc(%d) failed\n",
- info->core_param.num_freq *
+ info->power_param.num_freq *
sizeof(struct msm_dcvs_freq_entry));
ret = -ENOMEM;
goto err;
@@ -885,7 +885,7 @@
if (adreno_of_read_property(child, "reg", &index))
goto err;
- if (index >= info->core_param.num_freq) {
+ if (index >= info->power_param.num_freq) {
KGSL_CORE_ERR("DCVS freq entry %d is out of range\n",
index);
continue;
@@ -895,43 +895,96 @@
&info->freq_tbl[index].freq))
goto err;
- if (adreno_of_read_property(child, "qcom,idle-energy",
- &info->freq_tbl[index].idle_energy))
- info->freq_tbl[index].idle_energy = 0;
+ if (adreno_of_read_property(child, "qcom,voltage",
+ &info->freq_tbl[index].voltage))
+ info->freq_tbl[index].voltage = 0;
- if (adreno_of_read_property(child, "qcom,active-energy",
- &info->freq_tbl[index].active_energy))
- info->freq_tbl[index].active_energy = 0;
+ if (adreno_of_read_property(child, "qcom,is_trans_level",
+ &info->freq_tbl[index].is_trans_level))
+ info->freq_tbl[index].is_trans_level = 0;
+
+ if (adreno_of_read_property(child, "qcom,active-energy-offset",
+ &info->freq_tbl[index].active_energy_offset))
+ info->freq_tbl[index].active_energy_offset = 0;
+
+ if (adreno_of_read_property(child, "qcom,leakage-energy-offset",
+ &info->freq_tbl[index].leakage_energy_offset))
+ info->freq_tbl[index].leakage_energy_offset = 0;
}
- if (adreno_of_read_property(node, "qcom,core-max-time-us",
- &info->core_param.max_time_us))
- goto err;
-
- if (adreno_of_read_property(node, "qcom,algo-slack-time-us",
- &info->algo_param.slack_time_us))
+ if (adreno_of_read_property(node, "qcom,core-core-type",
+ &info->core_param.core_type))
goto err;
if (adreno_of_read_property(node, "qcom,algo-disable-pc-threshold",
&info->algo_param.disable_pc_threshold))
goto err;
-
- if (adreno_of_read_property(node, "qcom,algo-ss-window-size",
- &info->algo_param.ss_window_size))
+ if (adreno_of_read_property(node, "qcom,algo-em-win-size-min-us",
+ &info->algo_param.em_win_size_min_us))
goto err;
-
- if (adreno_of_read_property(node, "qcom,algo-ss-util-pct",
- &info->algo_param.ss_util_pct))
+ if (adreno_of_read_property(node, "qcom,algo-em-win-size-max-us",
+ &info->algo_param.em_win_size_max_us))
goto err;
-
if (adreno_of_read_property(node, "qcom,algo-em-max-util-pct",
&info->algo_param.em_max_util_pct))
goto err;
-
+ if (adreno_of_read_property(node, "qcom,algo-group-id",
+ &info->algo_param.group_id))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-max-freq-chg-time-us",
+ &info->algo_param.max_freq_chg_time_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-slack-mode-dynamic",
+ &info->algo_param.slack_mode_dynamic))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-slack-weight-thresh-pct",
+ &info->algo_param.slack_weight_thresh_pct))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-slack-time-min-us",
+ &info->algo_param.slack_time_min_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-slack-time-max-us",
+ &info->algo_param.slack_time_max_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-ss-win-size-min-us",
+ &info->algo_param.ss_win_size_min_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-ss-win-size-max-us",
+ &info->algo_param.ss_win_size_max_us))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,algo-ss-util-pct",
+ &info->algo_param.ss_util_pct))
+ goto err;
if (adreno_of_read_property(node, "qcom,algo-ss-iobusy-conv",
&info->algo_param.ss_iobusy_conv))
goto err;
+ if (adreno_of_read_property(node, "qcom,energy-active-coeff-a",
+ &info->energy_coeffs.active_coeff_a))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-active-coeff-b",
+ &info->energy_coeffs.active_coeff_b))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-active-coeff-c",
+ &info->energy_coeffs.active_coeff_c))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-a",
+ &info->energy_coeffs.leakage_coeff_a))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-b",
+ &info->energy_coeffs.leakage_coeff_b))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-c",
+ &info->energy_coeffs.leakage_coeff_c))
+ goto err;
+ if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-d",
+ &info->energy_coeffs.leakage_coeff_d))
+ goto err;
+
+ if (adreno_of_read_property(node, "qcom,power-current-temp",
+ &info->power_param.current_temp))
+ goto err;
+
return info;
err:
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index c6f8b1b..4b08e52 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -148,9 +148,8 @@
/* Fill in frequency table from low to high, reversing order. */
low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
for (i = 0; i <= low_level; i++)
- tbl[i].freq =
- pwr->pwrlevels[low_level - i].gpu_freq / 1000;
- ret = msm_dcvs_register_core(device->name, 0, priv->core_info);
+ tbl[i].freq = pwr->pwrlevels[low_level - i].gpu_freq / 1000;
+ ret = msm_dcvs_register_core(device->name, priv->core_info);
if (ret) {
KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
goto err;