arm: tegra: EDP: Allow enforcing max-freq caps based on tables
Diwakar Tundlam [Mon, 3 Jun 2013 21:40:06 +0000 (14:40 -0700)]
In addition solving for max-freq using leakage/dynamic formula, some
platforms require capping based on EDP tables published in the spec.
Adding support for this.

Added T114 fixed-capping table entries.

Bug 1281159

Change-Id: Ia159281db0ca72e74002b526b3b9e6f54b271646
Reviewed-on: http://git-master/r/239512
(cherry picked from commit d2ad4ba3de666f3fd299a8b95b1685e2f6da0d21)
Signed-off-by: Diwakar Tundlam <dtundlam@nvidia.com>
Reviewed-on: http://git-master/r/253751

arch/arm/mach-tegra/edp.c
arch/arm/mach-tegra/include/mach/edp.h
arch/arm/mach-tegra/tegra11_edp.c

index f2cd9bd..1c189f2 100644 (file)
@@ -91,6 +91,38 @@ static inline s64 edp_pow(s64 val, int pwr)
        return retval;
 }
 
+
+#ifdef CONFIG_TEGRA_CPU_EDP_FIXED_LIMITS
+static inline unsigned int edp_apply_fixed_limits(
+                               unsigned int in_freq_KHz,
+                               struct tegra_edp_cpu_leakage_params *params,
+                               unsigned int cur_effective,
+                               int temp_C, int n_cores_idx)
+{
+       unsigned int out_freq_KHz = in_freq_KHz;
+       unsigned int max_cur, max_temp, max_freq;
+       int i;
+
+       /* Apply any additional fixed limits */
+       for (i = 0; i < 8; i++) {
+               max_cur = params->max_current_cap[i].max_cur;
+               if (max_cur != 0 && cur_effective <= max_cur) {
+                       max_temp = params->max_current_cap[i].max_temp;
+                       if (max_temp != 0 && temp_C > max_temp) {
+                               max_freq = params->max_current_cap[i].
+                                       max_freq[n_cores_idx];
+                               if (max_freq && max_freq < out_freq_KHz)
+                                       out_freq_KHz = max_freq;
+                       }
+               }
+       }
+
+       return out_freq_KHz;
+}
+#else
+#define edp_apply_fixed_limits(freq, unused...)        (freq)
+#endif
+
 /*
  * Find the maximum frequency that results in dynamic and leakage current that
  * is less than the regulator current limit.
@@ -103,9 +135,9 @@ static unsigned int edp_calculate_maxf(
                                int iddq_mA,
                                int n_cores_idx)
 {
-       unsigned int voltage_mV, freq_KHz;
+       unsigned int voltage_mV, freq_KHz = 0;
        unsigned int cur_effective = regulator_cur - edp_reg_override_mA;
-       int f, i, j, k;
+       int f, i, j, k, r = 0;
        s64 leakage_mA, dyn_mA, leakage_calc_step;
        s64 leakage_mW, dyn_mW;
 
@@ -175,12 +207,19 @@ static unsigned int edp_calculate_maxf(
                        leakage_mW = leakage_mA * voltage_mV;
                        dyn_mW = dyn_mA * voltage_mV;
                        if (div64_s64(leakage_mW + dyn_mW, 1000) <= power_mW)
-                               return freq_KHz;
+                               goto end;
                } else if ((leakage_mA + dyn_mA) <= cur_effective) {
-                       return freq_KHz;
+                       goto end;
                }
+               freq_KHz = 0;
        }
-       return -EINVAL;
+
+ end:
+       if (r != 0)
+               return r;
+
+       return edp_apply_fixed_limits(freq_KHz, params,
+                                       cur_effective, temp_C, n_cores_idx);
 }
 
 static int edp_relate_freq_voltage(struct clk *clk_cpu_g,
index b2e60be..5b2dc5c 100644 (file)
@@ -42,6 +42,12 @@ struct tegra_edp_voltage_temp_constraint {
        unsigned int voltage_limit_mV;
 };
 
+struct tegra_edp_maximum_current_constraint {
+       unsigned int max_cur;
+       unsigned int max_temp;
+       unsigned int max_freq[4]; /* KHz */
+};
+
 struct tegra_edp_cpu_leakage_params {
        int cpu_speedo_id;
 
@@ -58,6 +64,7 @@ struct tegra_edp_cpu_leakage_params {
        unsigned int leakage_min;        /* minimum leakage current */
 
        unsigned int safety_cap[4];
+       struct tegra_edp_maximum_current_constraint max_current_cap[9];
        struct tegra_edp_voltage_temp_constraint volt_temp_cap;
 };
 
index 2fd3504..76b804f 100644 (file)
@@ -157,16 +157,76 @@ static struct core_edp_entry core_edp_table[] = {
 static struct tegra_edp_cpu_leakage_params t11x_leakage_params[] = {
        {
                .cpu_speedo_id      = 0, /* A01 CPU */
+               .max_current_cap = { /* values are from tegra4 datasheet */
+                       { .max_cur = 9000, .max_temp = 60,
+                               { 1900000, 1900000, 1600000, 1600000 }
+                       },
+                       { .max_cur = 9000, .max_temp = 75,
+                               { 1900000, 1900000, 1530000, 1530000 }
+                       },
+                       { .max_cur = 9000, .max_temp = 90,
+                               { 1900000, 1900000, 1500000, 1500000 }
+                       },
+                       { .max_cur = 12000, .max_temp = 90,
+                               { 1900000, 1900000, 1700000, 1700000 }
+                       },
+                       { .max_cur = 15000, .max_temp = 90,
+                               { 1900000, 1900000, 1900000, 1900000 }
+                       },
+               },
                LEAKAGE_PARAMS_COMMON_PART,
        },
        {
                .cpu_speedo_id      = 1, /* A01P+ CPU */
                .safety_cap         = { 1810500, 1810500, 1606500, 1606500 },
+               .max_current_cap = { /* values are from tegra4 datasheet */
+                       { .max_cur = 7500, .max_temp = 90,
+                               { 1800000, 1700000, 1320000, 1320000 }
+                       },
+                       { .max_cur = 7500, .max_temp = 75,
+                               { 1800000, 1700000, 1420000, 1420000 }
+                       },
+                       { .max_cur = 7500, .max_temp = 60,
+                               { 1800000, 1800000, 1420000, 1420000 }
+                       },
+                       { .max_cur = 7500, .max_temp = 45,
+                               { 1800000, 1800000, 1530000, 1530000 }
+                       },
+                       { .max_cur = 9000, .max_temp = 90,
+                               { 1800000, 1800000, 1500000, 1500000 }
+                       },
+                       { .max_cur = 9000, .max_temp = 75,
+                               { 1800000, 1800000, 1530000, 1530000 }
+                       },
+                       { .max_cur = 9000, .max_temp = 60,
+                               { 1800000, 1800000, 1600000, 1600000 }
+                       },
+                       { .max_cur = 12000, .max_temp = 45,
+                               { 1800000, 1800000, 1600000, 1600000 }
+                       },
+               },
                LEAKAGE_PARAMS_COMMON_PART,
        },
        {
                .cpu_speedo_id      = 2, /* A01P+ fast CPU */
                .safety_cap         = { 1912500, 1912500, 1912500, 1912500 },
+               .max_current_cap = { /* values are from tegra4 datasheet */
+                       { .max_cur = 9000, .max_temp = 90,
+                               { 1900000, 1900000, 1500000, 1500000 }
+                       },
+                       { .max_cur = 9000, .max_temp = 75,
+                               { 1900000, 1900000, 1530000, 1530000 }
+                       },
+                       { .max_cur = 9000, .max_temp = 60,
+                               { 1900000, 1900000, 1600000, 1600000 }
+                       },
+                       { .max_cur = 12000, .max_temp = 90,
+                               { 1900000, 1900000, 1700000, 1700000 }
+                       },
+                       { .max_cur = 15000, .max_temp = 90,
+                               { 1900000, 1900000, 1900000, 1900000 }
+                       },
+               },
                LEAKAGE_PARAMS_COMMON_PART,
        },
 };