From e9b32d4342a9ee9308729ae0c725d421869a0538 Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Thu, 6 Nov 2014 16:34:09 +0530 Subject: arm: tegra12: add support for CD575M 24x7 Chip 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 Reviewed-on: http://git-master/r/594855 GVS: Gerrit_Virtual_Submit Reviewed-by: Venkat Moganty --- arch/arm/mach-tegra/board.h | 6 ++++++ arch/arm/mach-tegra/clock.c | 1 + arch/arm/mach-tegra/common.c | 16 ++++++++++++++++ arch/arm/mach-tegra/dvfs.c | 3 ++- arch/arm/mach-tegra/tegra12_dvfs.c | 36 ++++++++++++++++++------------------ arch/arm/mach-tegra/tegra12_edp.c | 5 +++++ arch/arm/mach-tegra/tegra12_speedo.c | 12 ++++++++++++ drivers/mmc/host/sdhci-tegra.c | 3 +++ include/linux/clk/tegra.h | 1 + include/linux/tegra-fuse.h | 1 + 10 files changed, 65 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 07f9c2b37d9e..3ae1d51876b3 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -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); diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index ab1cf8dab68a..eb79acb14187 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -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) { diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 271e8228a865..de7173b67cb0 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -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) { diff --git a/arch/arm/mach-tegra/dvfs.c b/arch/arm/mach-tegra/dvfs.c index 06596c51ee1a..429385118b64 100644 --- a/arch/arm/mach-tegra/dvfs.c +++ b/arch/arm/mach-tegra/dvfs.c @@ -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; diff --git a/arch/arm/mach-tegra/tegra12_dvfs.c b/arch/arm/mach-tegra/tegra12_dvfs.c index a5d37ddb73d9..ac59d2c0a4a2 100644 --- a/arch/arm/mach-tegra/tegra12_dvfs.c +++ b/arch/arm/mach-tegra/tegra12_dvfs.c @@ -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[] = { { diff --git a/arch/arm/mach-tegra/tegra12_edp.c b/arch/arm/mach-tegra/tegra12_edp.c index 2fcae97829d7..4e95abce381d 100644 --- a/arch/arm/mach-tegra/tegra12_edp.c +++ b/arch/arm/mach-tegra/tegra12_edp.c @@ -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( diff --git a/arch/arm/mach-tegra/tegra12_speedo.c b/arch/arm/mach-tegra/tegra12_speedo.c index 8341128c66ba..28dfac8c0baa 100644 --- a/arch/arm/mach-tegra/tegra12_speedo.c +++ b/arch/arm/mach-tegra/tegra12_speedo.c @@ -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(); } diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 485570c75a2d..52aeac80ca31 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -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); diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h index 2a374c56297d..8394de40787c 100644 --- a/include/linux/clk/tegra.h +++ b/include/linux/clk/tegra.h @@ -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 diff --git a/include/linux/tegra-fuse.h b/include/linux/tegra-fuse.h index c12770eafcf5..0d2b9c967bce 100644 --- a/include/linux/tegra-fuse.h +++ b/include/linux/tegra-fuse.h @@ -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); -- cgit v1.2.3