arm: tegra: power: enable dynamic VDD_CPU EDP capping
Diwakar Tundlam [Fri, 21 Sep 2012 08:02:42 +0000 (01:02 -0700)]
Using the model used to enforce max frequency for a given VDD_CPU EDP.
Enabled for dalmore and pluto.

Initialised edp_reg_override to 6A and increased default per-platform
edp-limit higher by 6A to allow users to override the limit up by upto
6A when needed for specific use-cases.

Change-Id: I2741ba7316cebe0ae2836b84c4b3bbbe0afefe5e
Signed-off-by: Diwakar Tundlam <dtundlam@nvidia.com>
Reviewed-on: http://git-master/r/134306
(cherry picked from commit 9648d86f4a9a7b3b2557e98530e8265ea9f53467)
Signed-off-by: Gaurav Batra <gbatra@nvidia.com>
Reviewed-on: http://git-master/r/146677
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

Rebase-Id: R41ff83ba9a5dd4c1799961cc00dc6e796a93c8ba

13 files changed:
arch/arm/configs/tegra11_android_defconfig
arch/arm/mach-tegra/board-dalmore-power.c
arch/arm/mach-tegra/board-dalmore.c
arch/arm/mach-tegra/board-dalmore.h
arch/arm/mach-tegra/board-pluto-power.c
arch/arm/mach-tegra/board-pluto-sensors.c
arch/arm/mach-tegra/board-pluto.c
arch/arm/mach-tegra/board-pluto.h
arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/edp.c
arch/arm/mach-tegra/include/mach/edp.h
arch/arm/mach-tegra/tegra11_clocks.c
arch/arm/mach-tegra/tegra11_dvfs.c

index c7cbb19..f2fda51 100644 (file)
@@ -299,6 +299,7 @@ CONFIG_SENSORS_INA219=y
 CONFIG_MISC_DEVICES=y
 CONFIG_SENSORS_NCT1008=y
 CONFIG_THERMAL=y
+CONFIG_TEGRA_EDP_LIMITS=y
 CONFIG_MFD_TPS6586X=y
 CONFIG_MFD_TPS65910=y
 CONFIG_MFD_MAX8831=y
index 19ea860..2dff5ce 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
+#include <mach/edp.h>
 #include <mach/gpio-tegra.h>
 
 #include "pm.h"
@@ -1089,3 +1090,18 @@ int __init dalmore_suspend_init(void)
        return 0;
 }
 
+int __init dalmore_edp_init(void)
+{
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+       unsigned int regulator_mA;
+
+       regulator_mA = get_maximum_cpu_current_supported();
+       if (!regulator_mA)
+               regulator_mA = 15000;
+
+       pr_info("%s: CPU regulator %d mA\n", __func__, regulator_mA);
+
+       tegra_init_cpu_edp_limits(regulator_mA);
+#endif
+       return 0;
+}
index 53e2d1f..e6ac6df 100644 (file)
@@ -594,6 +594,7 @@ static void __init tegra_dalmore_init(void)
        dalmore_i2c_init();
        dalmore_spi_init();
        dalmore_usb_init();
+       dalmore_edp_init();
        dalmore_uart_init();
        dalmore_audio_init();
        platform_add_devices(dalmore_devices, ARRAY_SIZE(dalmore_devices));
index e64f95c..3875d4d 100644 (file)
@@ -102,6 +102,7 @@ int dalmore_sdhci_init(void);
 int dalmore_pinmux_init(void);
 int dalmore_sensors_init(void);
 int dalmore_emc_init(void);
+int dalmore_edp_init(void);
 int dalmore_panel_init(void);
 int dalmore_kbc_init(void);
 
index 41cd656..65f7418 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 
 #include <mach/iomap.h>
+#include <mach/edp.h>
 #include <mach/irqs.h>
 #include <linux/regulator/fixed.h>
 #include <linux/mfd/palmas.h>
@@ -675,3 +676,18 @@ int __init pluto_suspend_init(void)
        return 0;
 }
 
+int __init pluto_edp_init(void)
+{
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+       unsigned int regulator_mA;
+
+       regulator_mA = get_maximum_cpu_current_supported();
+       if (!regulator_mA)
+               regulator_mA = 9000;
+
+       pr_info("%s: CPU regulator %d mA\n", __func__, regulator_mA);
+
+       tegra_init_cpu_edp_limits(regulator_mA);
+#endif
+       return 0;
+}
index 9b3150f..e7a24ab 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
+#include <mach/edp.h>
 #include <linux/gpio.h>
 #include <linux/mpu.h>
 #include <media/imx091.h>
index 1a08c67..1f1bb59 100644 (file)
@@ -675,6 +675,7 @@ static void __init tegra_pluto_init(void)
        pluto_i2c_init();
        pluto_spi_init();
        pluto_usb_init();
+       pluto_edp_init();
        pluto_uart_init();
        pluto_audio_init();
        platform_add_devices(pluto_devices, ARRAY_SIZE(pluto_devices));
index 01b042b..dd7b42a 100644 (file)
@@ -87,6 +87,7 @@ int pluto_sdhci_init(void);
 int pluto_pinmux_init(void);
 int pluto_sensors_init(void);
 int pluto_emc_init(void);
+int pluto_edp_init(void);
 int pluto_panel_init(void);
 int pluto_kbc_init(void);
 
index abb0674..21fea48 100644 (file)
@@ -188,8 +188,10 @@ static int edp_thermal_index;
 static cpumask_t edp_cpumask;
 static unsigned int edp_limit;
 
-unsigned int tegra_get_edp_limit(void)
+unsigned int tegra_get_edp_limit(int *get_edp_thermal_index)
 {
+       if (get_edp_thermal_index)
+               *get_edp_thermal_index = edp_thermal_index;
        return edp_limit;
 }
 
index 9d779e8..99bddd3 100644 (file)
 #include "cpu-tegra.h"
 
 #define FREQ_STEP 10000000
-#define TEMP_LUT_MAX 68
-#define EDP_CALCULATED_LIMITS_SIZE TEMP_LUT_MAX
+#define OVERRIDE_DEFAULT 6000
 
 static struct tegra_edp_limits *edp_limits;
 static int edp_limits_size;
 static unsigned int regulator_cur;
 /* Value to subtract from regulator current limit */
-static unsigned int edp_reg_override_mA = 0;
+static unsigned int edp_reg_override_mA = OVERRIDE_DEFAULT;
 
 static const unsigned int *system_edp_limits;
 
@@ -328,16 +327,7 @@ static struct tegra_edp_limits edp_default_limits[] = {
 /*
  * Constants for EDP calculations
  */
-int temps_lut[TEMP_LUT_MAX] = {
-       23, 24, 25, 26, 27, 28, 29,
-       30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
-       40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
-       50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
-       60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
-       70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-       80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
-       90,
-};
+int temps_lut[] = { 23, 40, 50, 60, 70, 75, 80, 85, 90, 95 };
 
 /* TODO: This struct will get large for 13 speedo IDs... relocate. */
 struct edp_constants_lut_t {
@@ -439,13 +429,17 @@ struct freq_voltage_lut_t {
 } *freq_voltage_lut = 0;
 unsigned int freq_voltage_lut_size;
 
-static s64 edp_pwr(s64 val, int pwr)
+static inline s64 edp_pow(s64 val, int pwr)
 {
-       int i;
        s64 retval = 1;
 
-       for (i = 0; i < pwr; i++)
-               retval *= val;
+       while (pwr) {
+               if (pwr & 1)
+                       retval *= val;
+               pwr >>= 1;
+               if (pwr)
+                       val *= val;
+       }
 
        return retval;
 }
@@ -483,25 +477,26 @@ unsigned int edp_calculate_maxf(struct edp_constants_lut_t  *edp_constants,
                                for (k = 0; k <= 3; k++) {
                                        leakage_calc_step =
                                             leakage_consts_ijk[i*16 + j*4 + k]
-                                               * edp_pwr(iddq_mA, i);
+                                               * edp_pow(iddq_mA, i);
                                        /* Convert (mA)^i to (A)^i */
                                        leakage_calc_step =
                                                div64_s64(leakage_calc_step,
-                                                         edp_pwr(1000, i));
+                                                         edp_pow(1000, i));
                                        leakage_calc_step *=
-                                               edp_pwr(voltage_mV, j);
+                                               edp_pow(voltage_mV, j);
                                        /* Convert (mV)^i to (V)^i */
                                        leakage_calc_step =
                                                div64_s64(leakage_calc_step,
-                                                         edp_pwr(1000, j));
+                                                         edp_pow(1000, j));
                                        leakage_calc_step *=
-                                               edp_pwr(temp_C, k);
+                                               edp_pow(temp_C, k);
                                        /* const_ijk was X 1,000,000 */
                                        leakage_calc_step =
                                                div64_s64(leakage_calc_step,
                                                          1000000);
                                        leakage_mA += leakage_calc_step;
                                }
+
                leakage_mA *= leakage_const_n;
                /* leakage_const_n was pre-multiplied by 1,000,000 */
                leakage_mA = div64_s64(leakage_mA, 1000000);
@@ -544,7 +539,6 @@ static int edp_relate_freq_voltage(struct clk *clk_cpu_g,
                freq_voltage_lut[i].freq = freq;
                freq_voltage_lut[i].voltage_mV = voltage_mV;
        }
-
        return 0;
 }
 
@@ -562,6 +556,7 @@ int edp_find_speedo_idx(int cpu_speedo_id, unsigned int *cpu_speedo_idx)
               __func__, cpu_speedo_id);
        return -EINVAL;
 }
+
 int init_cpu_edp_limits_calculated(int cpu_speedo_id)
 {
        unsigned int temp_idx, n_cores_idx;
@@ -574,8 +569,7 @@ int init_cpu_edp_limits_calculated(int cpu_speedo_id)
        struct clk *clk_cpu_g = tegra_get_clock_by_name("cpu_g");
 
        /* Determine all inputs to EDP formula */
-       tegra_fuse_get_cpu_iddq_mA(&iddq_mA);
-
+       iddq_mA = tegra_get_cpu_iddq_value();
        ret = edp_find_speedo_idx(cpu_speedo_id, &cpu_speedo_idx);
        if (ret)
                return ret;
@@ -583,7 +577,7 @@ int init_cpu_edp_limits_calculated(int cpu_speedo_id)
        edp_constants = &edp_constants_lut[cpu_speedo_idx];
 
        edp_calculated_limits =
-               kmalloc(sizeof(struct tegra_edp_limits) * EDP_CALCULATED_LIMITS_SIZE,
+               kmalloc(sizeof(struct tegra_edp_limits) * ARRAY_SIZE(temps_lut),
                                GFP_KERNEL);
        BUG_ON(!edp_calculated_limits);
 
@@ -623,12 +617,12 @@ int init_cpu_edp_limits_calculated(int cpu_speedo_id)
         */
        if (edp_limits != edp_default_limits) {
                memcpy(edp_limits, edp_calculated_limits,
-                       sizeof(struct tegra_edp_limits) * EDP_CALCULATED_LIMITS_SIZE);
+                      sizeof(struct tegra_edp_limits) * ARRAY_SIZE(temps_lut));
                kfree(edp_calculated_limits);
        }
        else {
                edp_limits = edp_calculated_limits;
-               edp_limits_size = EDP_CALCULATED_LIMITS_SIZE;
+               edp_limits_size = ARRAY_SIZE(temps_lut);
        }
 
        kfree(freq_voltage_lut);
@@ -692,7 +686,7 @@ void __init tegra_init_cpu_edp_limits(unsigned int regulator_mA)
                edp_limits_size = ARRAY_SIZE(edp_default_limits);
                return;
        }
-       regulator_cur = regulator_mA;
+       regulator_cur = regulator_mA + OVERRIDE_DEFAULT;
 
        if (init_cpu_edp_limits_lookup(cpu_speedo_id) == 0)
                return;
@@ -803,21 +797,24 @@ err_ret:
 
 static int edp_limit_debugfs_show(struct seq_file *s, void *data)
 {
-       seq_printf(s, "%u\n", tegra_get_edp_limit());
+       seq_printf(s, "%u\n", tegra_get_edp_limit(NULL));
        return 0;
 }
 
 static int edp_debugfs_show(struct seq_file *s, void *data)
 {
-       int i;
+       int i, th_idx;
 
-       seq_printf(s, "-- VDD_CPU %sEDP table (%umA) --\n",
+       tegra_get_edp_limit(&th_idx);
+       seq_printf(s, "-- VDD_CPU %sEDP table (%umA = %umA - %umA) --\n",
                   edp_limits == edp_default_limits ? "default " : "",
-                  regulator_cur);
+                  regulator_cur - edp_reg_override_mA,
+                  regulator_cur, edp_reg_override_mA);
        seq_printf(s, "%6s %10s %10s %10s %10s\n",
                   " Temp.", "1-core", "2-cores", "3-cores", "4-cores");
        for (i = 0; i < edp_limits_size; i++) {
-               seq_printf(s, "%4dC: %10u %10u %10u %10u\n",
+               seq_printf(s, "%c%3dC: %10u %10u %10u %10u\n",
+                          i == th_idx ? '>' : ' ',
                           edp_limits[i].temperature,
                           edp_limits[i].freq_limits[0],
                           edp_limits[i].freq_limits[1],
index a074309..34914d4 100644 (file)
@@ -48,7 +48,7 @@ struct thermal_cooling_device *edp_cooling_device_create(int index);
 void tegra_init_cpu_edp_limits(unsigned int regulator_mA);
 void tegra_init_system_edp_limits(unsigned int power_limit_mW);
 void tegra_get_cpu_edp_limits(const struct tegra_edp_limits **limits, int *size);
-unsigned int tegra_get_edp_limit(void);
+unsigned int tegra_get_edp_limit(int *get_edp_thermal_index);
 void tegra_get_system_edp_limits(const unsigned int **limits);
 int tegra_system_edp_alarm(bool alarm);
 
@@ -63,7 +63,7 @@ static inline void tegra_init_system_edp_limits(int power_limit_mW)
 static inline void tegra_get_cpu_edp_limits(struct tegra_edp_limits **limits,
                                            int *size)
 {}
-static inline unsigned int tegra_get_edp_limit(void)
+static inline unsigned int tegra_get_edp_limit(int *get_edp_thermal_index)
 { return -1; }
 static inline void tegra_get_system_edp_limits(unsigned int **limits)
 {}
index 28b2f69..6aa4fe3 100644 (file)
@@ -6657,6 +6657,12 @@ static void tegra11_init_one_clock(struct clk *c)
        clkdev_add(&c->lookup);
 }
 
+void tegra_edp_throttle_cpu_now(u8 factor)
+{
+       /* empty definition for tegra11 */
+       return;
+}
+
 bool tegra_clk_is_parent_allowed(struct clk *c, struct clk *p)
 {
        /*
index 0d94bb8..8114dc6 100644 (file)
@@ -501,6 +501,13 @@ static int __init get_core_nominal_mv_index(int speedo_id)
        return i - 1;
 }
 
+int tegra_cpu_dvfs_alter(int edp_thermal_index, const cpumask_t *cpus,
+                        bool before_clk_update, int cpu_event)
+{
+       /* empty definition for tegra11 */
+       return 0;
+}
+
 void __init tegra11x_init_dvfs(void)
 {
        int cpu_speedo_id = tegra_cpu_speedo_id();