ARM: tegra: power: Add voltage to freq convertion interface.
Amit Kamath [Mon, 17 Dec 2012 07:22:30 +0000 (12:22 +0530)]
Use EDP generated tables to calculate the frequency supported at
a specified voltage

bug 1042409

Change-Id: Id2aa6ac61023b9c9de1810fe6a46e4a1bc70eed0
Signed-off-by: Amit Kamath <akamath@nvidia.com>
Reviewed-on: http://git-master/r/171819
Reviewed-by: Mandar Padmawar <mpadmawar@nvidia.com>
Tested-by: Mandar Padmawar <mpadmawar@nvidia.com>

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

index ff6d134..033bb81 100644 (file)
@@ -422,6 +422,8 @@ static struct tegra_edp_cpu_leakage_params leakage_params[] = {
        },
 };
 
+static struct tegra_edp_freq_voltage_table *freq_voltage_lut_saved;
+static unsigned int freq_voltage_lut_size_saved;
 static struct tegra_edp_freq_voltage_table *freq_voltage_lut;
 static unsigned int freq_voltage_lut_size;
 
@@ -505,13 +507,15 @@ unsigned int edp_calculate_maxf(struct tegra_edp_cpu_leakage_params *params,
 }
 
 static int edp_relate_freq_voltage(struct clk *clk_cpu_g,
-                               unsigned int cpu_speedo_idx)
+                       unsigned int cpu_speedo_idx,
+                       unsigned int freq_volt_lut_size,
+                       struct tegra_edp_freq_voltage_table *freq_volt_lut)
 {
        unsigned int i, j, freq;
        int voltage_mV;
 
        for (i = 0, j = 0, freq = 0;
-                i < freq_voltage_lut_size;
+                i < freq_volt_lut_size;
                 i++, freq += FREQ_STEP) {
 
                /* Predict voltages */
@@ -523,12 +527,24 @@ static int edp_relate_freq_voltage(struct clk *clk_cpu_g,
                }
 
                /* Cache frequency / voltage / voltage constant relationship */
-               freq_voltage_lut[i].freq = freq;
-               freq_voltage_lut[i].voltage_mV = voltage_mV;
+               freq_volt_lut[i].freq = freq;
+               freq_volt_lut[i].voltage_mV = voltage_mV;
        }
        return 0;
 }
 
+unsigned int tegra_edp_find_maxf(int volt)
+{
+       unsigned int i;
+
+       for (i = 0; i < freq_voltage_lut_size_saved; i++) {
+               if (freq_voltage_lut_saved[i].voltage_mV > volt)
+                       break;
+       }
+       return freq_voltage_lut[i - 1].freq;
+}
+
+
 int edp_find_speedo_idx(int cpu_speedo_id, unsigned int *cpu_speedo_idx)
 {
        int i;
@@ -578,12 +594,33 @@ static int init_cpu_edp_limits_calculated(void)
                return -ENOMEM;
        }
 
-       ret = edp_relate_freq_voltage(clk_cpu_g, cpu_speedo_idx);
+       ret = edp_relate_freq_voltage(clk_cpu_g, cpu_speedo_idx,
+                               freq_voltage_lut_size, freq_voltage_lut);
        if (ret) {
                kfree(freq_voltage_lut);
                return ret;
        }
 
+       if (freq_voltage_lut_size != freq_voltage_lut_size_saved) {
+               /* release previous table if present */
+               kfree(freq_voltage_lut_saved);
+               /* create table to save */
+               freq_voltage_lut_saved =
+                       kmalloc(sizeof(struct tegra_edp_freq_voltage_table) *
+                       freq_voltage_lut_size, GFP_KERNEL);
+               if (!freq_voltage_lut_saved) {
+                       pr_err("%s: failed alloc mem for freq/voltage LUT\n",
+                               __func__);
+                       kfree(freq_voltage_lut);
+                       return -ENOMEM;
+               }
+               freq_voltage_lut_size_saved = freq_voltage_lut_size;
+       }
+       memcpy(freq_voltage_lut_saved,
+               freq_voltage_lut,
+               sizeof(struct tegra_edp_freq_voltage_table) *
+                       freq_voltage_lut_size);
+
        /* Calculate EDP table */
        for (temp_idx = 0; temp_idx < ARRAY_SIZE(temperatures); temp_idx++) {
                edp_calculated_limits[temp_idx].
index 7dfea8d..2304a4a 100644 (file)
@@ -83,7 +83,7 @@ void tegra_get_cpu_edp_limits(const struct tegra_edp_limits **limits, int *size)
 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);
-
+unsigned int tegra_edp_find_maxf(int volt);
 #else
 static inline struct thermal_cooling_device *edp_cooling_device_create(
        int index)
@@ -103,6 +103,8 @@ static inline void tegra_get_system_edp_limits(unsigned int **limits)
 {}
 static inline int tegra_system_edp_alarm(bool alarm)
 { return -1; }
+static inline unsigned int tegra_edp_find_maxf(int volt)
+{ return -1; }
 #endif
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC