arm: tegra12: add support for CD575M 24x7 Chip
Bibek Basu [Thu, 6 Nov 2014 11:04:09 +0000 (16:04 +0530)]
Added DVFS support for CD575M Always on behaviour.
With this personality configuration for the chip,the
lifetime of the chip increases to 5 Yrs
Operating Temp : -25 to 105 degC
CPU DVFS: Max Freq 1938Mhz. Max Voltage 1.12V
SOC DVFS: Max Voltage0 1.01V EMC dvfs max freq 792Mhz
GPU DVFS: Max Freq 804Mhz and Ma Voltage 1.09V

Bug 1563635

Change-Id: If7fec38b83ae4de8c5435006207fa3cf717384c0
Signed-off-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-on: http://git-master/r/594855
GVS: Gerrit_Virtual_Submit
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>

arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/dvfs.c
arch/arm/mach-tegra/tegra12_dvfs.c
arch/arm/mach-tegra/tegra12_edp.c
arch/arm/mach-tegra/tegra12_speedo.c
drivers/mmc/host/sdhci-tegra.c
include/linux/clk/tegra.h
include/linux/tegra-fuse.h

index 07f9c2b..3ae1d51 100644 (file)
@@ -244,6 +244,12 @@ enum image_type {
        rck_image,
 };
 
+/* Usage Model */
+enum chip_personality {
+       normal = 0,
+       always_on,
+};
+
 void tegra_get_board_info(struct board_info *);
 void tegra_get_pmu_board_info(struct board_info *bi);
 void tegra_get_display_board_info(struct board_info *bi);
index ab1cf8d..eb79acb 100644 (file)
@@ -150,6 +150,7 @@ unsigned long clk_get_max_rate(struct clk *c)
 {
                return c->max_rate;
 }
+EXPORT_SYMBOL(clk_get_max_rate);
 
 unsigned long clk_get_min_rate(struct clk *c)
 {
index 271e822..de7173b 100644 (file)
@@ -333,6 +333,7 @@ static int emc_max_dvfs;
 static unsigned int memory_type;
 static int usb_port_owner_info;
 static int lane_owner_info;
+static int chip_personality;
 
 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
 static __initdata struct tegra_clk_init_table tegra11x_clk_init_table[] = {
@@ -1157,6 +1158,21 @@ int tegra_get_sku_override(void)
        return sku_override;
 }
 
+static int __init tegra_chip_personality(char *id)
+{
+       char *p = id;
+
+       chip_personality = memparse(p, &p);
+
+       return 0;
+}
+early_param("chip_personality", tegra_chip_personality);
+
+int tegra_get_chip_personality(void)
+{
+       return chip_personality;
+}
+
 #ifndef CONFIG_NVMAP_USE_CMA_FOR_CARVEOUT
 static int __init tegra_vpr_arg(char *options)
 {
index 06596c5..4293851 100644 (file)
@@ -1146,7 +1146,8 @@ int __init tegra_enable_dvfs_on_clk(struct clk *c, struct dvfs *d)
        }
 
        for (i = 0; i < MAX_DVFS_FREQS; i++) {
-               if (d->millivolts[i] == 0)
+               if (d->millivolts[i] == 0 ||
+                               d->millivolts[i] > d->max_millivolts)
                        break;
 
                d->freqs[i] *= d->freqs_mult;
index a5d37dd..ac59d2c 100644 (file)
@@ -152,8 +152,8 @@ void __init tegra12x_vdd_cpu_align(int step_uv, int offset_uv)
 
 /* CPU DVFS tables */
 static unsigned long cpu_max_freq[] = {
-/* speedo_id   0        1        2        3        4        5       */
-               2014500, 2320500, 2116500, 2524500, 1811000, 2218500,
+/* speedo_id   0        1        2        3        4        5        6         */
+               2014500, 2320500, 2116500, 2524500, 1811000, 2218500, 1938000,
 };
 
 static struct cpu_cvb_dvfs cpu_cvb_dvfs_table[] = {
@@ -277,11 +277,24 @@ static const int core_millivolts[MAX_DVFS_FREQS] = {
                .dvfs_rail      = &tegra12_dvfs_rail_vdd_core,  \
        }
 
+#define DEFER_DVFS(_clk_name, _speedo_id, _process_id, _auto, _mult, _freqs...) \
+       {                                                       \
+               .clk_name       = _clk_name,                    \
+               .speedo_id      = _speedo_id,                   \
+               .process_id     = _process_id,                  \
+               .freqs          = {_freqs},                     \
+               .freqs_mult     = _mult,                        \
+               .millivolts     = core_millivolts,              \
+               .auto_dvfs      = _auto,                        \
+               .defer_override = true,                         \
+               .dvfs_rail      = &tegra12_dvfs_rail_vdd_core,  \
+       }
+
 static struct dvfs core_dvfs_table[] = {
        /* Core voltages (mV):                   800,    850,    900,    950,    1000,  1050,    1100,   1110,    1150 */
        /* Clock limits for internal blocks, PLLs */
 
-       CORE_DVFS("emc",        -1, -1, 1, KHZ, 264000, 348000, 384000, 384000, 528000, 528000, 1200000, 1200000, 1200000),
+       CORE_DVFS("emc",        -1, -1, 1, KHZ, 264000, 348000, 384000, 384000, 792000, 792000, 1200000, 1200000, 1200000),
 
         CORE_DVFS("cpu_lp",     0, 0, 1, KHZ,   312000, 528000, 660000, 804000, 912000, 1044000, 1044000, 1044000, 1044000),
         CORE_DVFS("cpu_lp",     0, 1, 1, KHZ,   312000, 564000, 696000, 828000, 960000, 1044000, 1044000, 1044000, 1044000),
@@ -440,19 +453,6 @@ static struct dvfs core_dvfs_table_automotive[] = {
  * clock capabilities specified in DVFS table.
  *
  */
-#define DEFER_DVFS(_clk_name, _speedo_id, _process_id, _auto, _mult, _freqs...) \
-       {                                                       \
-               .clk_name       = _clk_name,                    \
-               .speedo_id      = _speedo_id,                   \
-               .process_id     = _process_id,                  \
-               .freqs          = {_freqs},                     \
-               .freqs_mult     = _mult,                        \
-               .millivolts     = core_millivolts,              \
-               .auto_dvfs      = _auto,                        \
-               .defer_override = true,                         \
-               .dvfs_rail      = &tegra12_dvfs_rail_vdd_core,  \
-       }
-
 static struct dvfs disp_dvfs_table[] = {
        /*
         * The clock rate for the display controllers that determines the
@@ -478,8 +478,8 @@ static int resolve_core_override(int min_override_mv)
 
 /* GPU DVFS tables */
 static unsigned long gpu_max_freq[] = {
-/* speedo_id   0       1       2        3      */
-               648000, 852000, 1008000, 600000
+/* speedo_id   0       1       2        3       4      */
+               648000, 852000, 1008000, 600000, 804000
 };
 static struct gpu_cvb_dvfs gpu_cvb_dvfs_table[] = {
        {
index 2fcae97..4e95abc 100644 (file)
@@ -189,6 +189,7 @@ struct tegra_sysedp_corecap *tegra_get_sysedp_corecap(unsigned int *sz)
        gpu_speedo_id = tegra_gpu_speedo_id();
 
        switch (cpu_speedo_id) {
+       case 0x6:
        case 0x5:
        case 0x2:
                if (gpu_speedo_id == 1) {
@@ -332,6 +333,10 @@ static struct tegra_edp_cpu_powermodel_params t12x_cpu_powermodel_params[] = {
                .cpu_speedo_id = 5, /* Prod SKU */
                .common = EDP_PARAMS_COMMON_PART,
        },
+       {
+               .cpu_speedo_id = 6, /* Prod SKU */
+               .common = EDP_PARAMS_COMMON_PART,
+       },
 };
 
 struct tegra_edp_cpu_powermodel_params *tegra12x_get_cpu_powermodel_params(
index 8341128..28dfac8 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "iomap.h"
 #include "common.h"
+#include "board.h"
 
 #define TEGRA124_CPU_SPEEDO 2271 /* FIXME: Get Correct Value */
 
@@ -92,6 +93,7 @@ static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
 static void rev_sku_to_speedo_ids(int rev, int sku)
 {
        int can_boost = tegra_get_sku_override();
+       int chip_personality = tegra_get_chip_personality();
 
        switch (sku) {
        case 0x00: /* Engg sku */
@@ -111,6 +113,10 @@ static void rev_sku_to_speedo_ids(int rev, int sku)
                soc_speedo_id = 0;
                gpu_speedo_id = 1;
                threshold_index = 0;
+               if (sku == 0x87 && chip_personality == always_on) {
+                       cpu_speedo_id = 6;
+                       gpu_speedo_id = 4;
+               }
                break;
        case 0x07:
                if (can_boost) {
@@ -310,13 +316,19 @@ int tegra_cpu_speedo_mv(void)
 
 int tegra_core_speedo_mv(void)
 {
+       int chip_personality = tegra_get_chip_personality();
+
        switch (soc_speedo_id) {
        case 0:
+               if (chip_personality == always_on)
+                       return 1010;
                return 1150;
        case 1:
                return 1150;
        case 2:
                return 1110;
+       case 3:
+               return 1010;
        default:
                BUG();
        }
index 485570c..52aeac8 100644 (file)
@@ -1398,6 +1398,9 @@ static void tegra_sdhci_set_clk_rate(struct sdhci_host *sdhci,
                (clk_rate > tegra_host->max_clk_limit))
                clk_rate = tegra_host->max_clk_limit;
 
+       if (clk_rate > clk_get_max_rate(pltfm_host->clk))
+               clk_rate = clk_get_max_rate(pltfm_host->clk);
+
        tegra_sdhci_clock_set_parent(sdhci, clk_rate);
        clk_set_rate(pltfm_host->clk, clk_rate);
        sdhci->max_clk = clk_get_rate(pltfm_host->clk);
index 2a374c5..8394de4 100644 (file)
@@ -168,6 +168,7 @@ void tegra_unregister_clk_rate_notifier(
        struct clk *c, struct notifier_block *nb);
 int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting);
 int tegra_dvfs_use_alt_freqs_on_clk(struct clk *c, bool use_alt_freq);
+unsigned long clk_get_max_rate(struct clk *c);
 
 /**
  * tegra_is_clk_enabled - get info if the clk is enabled or not
index c12770e..0d2b9c9 100644 (file)
@@ -60,6 +60,7 @@ int tegra_core_speedo_mv(void);
 int tegra_gpu_speedo_id(void);
 int tegra_get_sku_override(void);
 int tegra_get_cpu_iddq_value(void);
+int tegra_get_chip_personality(void);
 
 #ifdef CONFIG_ARCH_TEGRA_12x_SOC
 int tegra_cpu_speedo_0_value(void);