summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Thomas <james.thomas@codethink.co.uk>2014-08-18 16:33:06 +0100
committerJames Thomas <james.thomas@codethink.co.uk>2014-08-18 16:33:06 +0100
commitde3664efca390a8d2fe525a583d17772deee8500 (patch)
tree8e036ae4a4120ed011cd2fb1faf9e81ad5655697
parent1f12d2a9854d101f23cce77f6fe8e53814c8a896 (diff)
parent123cc68c33ff537748a244f4932640083b4b6825 (diff)
downloadlinux-de3664efca390a8d2fe525a583d17772deee8500.tar.gz
Merge branch 'baserock/james/tegra-3.10' into baserock/arm/tegra-3.10baserock/arm/tegra-3.10
Reviewed by : Paul Sherwood <paul.sherwood@codethink.co.uk> Reviewed by : Richard Maw <richard.maw@codethink.co.uk> Merged by : James Thomas <james.thomas@codethink.co.uk>
-rw-r--r--arch/arm/boot/dts/tegra124-pm375.dts9
-rw-r--r--arch/arm/configs/tegra12_defconfig3
-rw-r--r--arch/arm/mach-tegra/Kconfig7
-rw-r--r--arch/arm/mach-tegra/board-ardbeg-memory.c410
-rw-r--r--arch/arm/mach-tegra/board-ardbeg-sdhci.c29
-rw-r--r--arch/arm/mach-tegra/board-ardbeg.c26
-rw-r--r--arch/arm/mach-tegra/board-dalmore.c9
-rw-r--r--arch/arm/mach-tegra/board-laguna-power.c3
-rw-r--r--arch/arm/mach-tegra/board-loki-sdhci.c14
-rw-r--r--arch/arm/mach-tegra/board-loki.c9
-rw-r--r--arch/arm/mach-tegra/board-macallan.c9
-rw-r--r--arch/arm/mach-tegra/board-pismo.c9
-rw-r--r--arch/arm/mach-tegra/board-pluto.c8
-rw-r--r--arch/arm/mach-tegra/board-roth.c9
-rw-r--r--arch/arm/mach-tegra/board-vcm30_t124.c6
-rw-r--r--arch/arm/mach-tegra/board.h9
-rw-r--r--arch/arm/mach-tegra/clock.c38
-rw-r--r--arch/arm/mach-tegra/common.c74
-rw-r--r--arch/arm/mach-tegra/dvfs.c73
-rw-r--r--arch/arm/mach-tegra/dvfs.h1
-rw-r--r--arch/arm/mach-tegra/pm.c2
-rw-r--r--arch/arm/mach-tegra/powergate-t12x.c18
-rw-r--r--arch/arm/mach-tegra/tegra12_clocks.c226
-rw-r--r--arch/arm/mach-tegra/tegra12_dvfs.c83
-rw-r--r--arch/arm/mach-tegra/tegra12_edp.c4
-rw-r--r--arch/arm/mach-tegra/tegra12_speedo.c2
-rw-r--r--drivers/cpufreq/cpufreq_governor.c7
-rw-r--r--drivers/misc/tegra-fuse/tegra_fuse.c1
-rw-r--r--drivers/mmc/host/sdhci-tegra.c1732
-rw-r--r--drivers/pci/host/pci-tegra.c2
-rw-r--r--drivers/tty/serial/8250/8250_core.c21
-rw-r--r--drivers/tty/serial/of_serial.c22
-rw-r--r--drivers/usb/phy/tegra11x_usb_phy.c4
-rw-r--r--drivers/video/tegra/dc/bandwidth.c8
-rw-r--r--drivers/video/tegra/dc/dc_reg.h12
-rw-r--r--drivers/video/tegra/dc/hdmi_state_machine.c2
-rw-r--r--drivers/video/tegra/host/gk20a/channel_gk20a.c33
-rw-r--r--drivers/video/tegra/host/gk20a/gr_gk20a.c18
-rw-r--r--drivers/video/tegra/host/msenc/msenc.c2
-rw-r--r--drivers/video/tegra/host/tsec/tsec.c2
-rw-r--r--drivers/video/tegra/host/vic03/vic03.c2
-rw-r--r--fs/eventpoll.c6
-rw-r--r--include/linux/clk/tegra.h2
-rw-r--r--include/linux/platform_data/mmc-sdhci-tegra.h4
-rw-r--r--include/linux/serial_8250.h7
-rw-r--r--sound/soc/codecs/max98090.c25
-rw-r--r--sound/soc/tegra/tegra30_ahub.c16
47 files changed, 2034 insertions, 984 deletions
diff --git a/arch/arm/boot/dts/tegra124-pm375.dts b/arch/arm/boot/dts/tegra124-pm375.dts
index 43dbf9231186..83f314cd3563 100644
--- a/arch/arm/boot/dts/tegra124-pm375.dts
+++ b/arch/arm/boot/dts/tegra124-pm375.dts
@@ -7,15 +7,13 @@
/ {
model = "NVIDIA Tegra124 PM375";
- compatible = "nvidia,jetson-tk1", "nvidia,laguna", "nvidia,tegra124";
+ compatible = "nvidia,jetson-tk1", "nvidia,tegra124";
nvidia,dtsfilename = __FILE__;
#address-cells = <1>;
#size-cells = <1>;
chosen {
bootargs = "tegraid=40.0.0.00.00 vmalloc=256M video=tegrafb console=ttyS0,115200n8 earlyprintk";
- linux,initrd-start = <0x85000000>;
- linux,initrd-end = <0x851bc400>;
};
pinmux {
@@ -107,10 +105,11 @@
status = "okay";
nvidia,invert-interrupt;
nvidia,suspend-mode = <0>;
- nvidia,cpu-pwr-good-time = <2000>;
- nvidia,cpu-pwr-off-time = <2000>;
+ nvidia,cpu-pwr-good-time = <500>;
+ nvidia,cpu-pwr-off-time = <300>;
nvidia,core-pwr-good-time = <3845 3845>;
nvidia,core-pwr-off-time = <2000>;
+ nvidia,lp0-vec = <0xf46ff000 2064>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
};
diff --git a/arch/arm/configs/tegra12_defconfig b/arch/arm/configs/tegra12_defconfig
index a2bafc4cf2d9..9dfa0c29eeff 100644
--- a/arch/arm/configs/tegra12_defconfig
+++ b/arch/arm/configs/tegra12_defconfig
@@ -31,6 +31,7 @@ CONFIG_MACH_LOKI=y
CONFIG_MACH_LAGUNA=y
CONFIG_TEGRA_EMC_SCALING_ENABLE=y
CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y
+CONFIG_TEGRA_PREINIT_CLOCKS=y
CONFIG_TEGRA_EDP_LIMITS=y
CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ=1400
CONFIG_TEGRA_DYNAMIC_PWRDET=y
@@ -186,7 +187,6 @@ CONFIG_THERM_EST=y
CONFIG_FAN_THERM_EST=y
CONFIG_EEPROM_AT24=y
CONFIG_TEGRA_BB_SUPPORT=y
-CONFIG_TEGRA_USB_MODEM_POWER=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
@@ -444,7 +444,6 @@ CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_PL2303=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_SERIAL_BASEBAND=m
-CONFIG_USB_RENESAS_MODEM=y
CONFIG_USB_TEGRA_OTG=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 53e9b66e45ae..cc9913b6264b 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -753,6 +753,13 @@ config TEGRA_SLOW_CSITE
When enabled, csite will be running at 1 Mhz and the performance of
jtag, lauterbach and other debugger will be extremely slow.
+config TEGRA_PREINIT_CLOCKS
+ bool "Preinitialize Tegra clocks to known states"
+ default n
+ help
+ Preinitialize Tegra clocks to known states before actual full-
+ scale clock initialization starts.
+
config TEGRA_PREPOWER_WIFI
bool "Pre-power up WiFi "
default n
diff --git a/arch/arm/mach-tegra/board-ardbeg-memory.c b/arch/arm/mach-tegra/board-ardbeg-memory.c
index eae25e79cebf..99f04e2657ff 100644
--- a/arch/arm/mach-tegra/board-ardbeg-memory.c
+++ b/arch/arm/mach-tegra/board-ardbeg-memory.c
@@ -11523,8 +11523,8 @@ static struct tegra12_emc_table ardbeg_lpddr3_emc_table_E1781[] = {
static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
{
- 0x19, /* V5.0.14 */
- "04_12750_03_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_12750_01_V5.0.17_V1.1", /* DVFS table version */
12750, /* SDRAM frequency */
800, /* min voltage */
800, /* gpu min voltage */
@@ -11540,7 +11540,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* EMC_RP */
0x00000004, /* EMC_R2W */
0x0000000a, /* EMC_W2R */
- 0x00000003, /* EMC_R2P */
+ 0x00000005, /* EMC_R2P */
0x0000000b, /* EMC_W2P */
0x00000000, /* EMC_RD_RCD */
0x00000000, /* EMC_WR_RCD */
@@ -11589,22 +11589,22 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x106aa298, /* EMC_FBIO_CFG5 */
0x002c00a0, /* EMC_CFG_DIG_DLL */
0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
- 0x00064000, /* EMC_DLL_XFORM_DQS0 */
- 0x00064000, /* EMC_DLL_XFORM_DQS1 */
- 0x00064000, /* EMC_DLL_XFORM_DQS2 */
- 0x00064000, /* EMC_DLL_XFORM_DQS3 */
- 0x00064000, /* EMC_DLL_XFORM_DQS4 */
- 0x00064000, /* EMC_DLL_XFORM_DQS5 */
- 0x00064000, /* EMC_DLL_XFORM_DQS6 */
- 0x00064000, /* EMC_DLL_XFORM_DQS7 */
- 0x00064000, /* EMC_DLL_XFORM_DQS8 */
- 0x00064000, /* EMC_DLL_XFORM_DQS9 */
- 0x00064000, /* EMC_DLL_XFORM_DQS10 */
- 0x00064000, /* EMC_DLL_XFORM_DQS11 */
- 0x00064000, /* EMC_DLL_XFORM_DQS12 */
- 0x00064000, /* EMC_DLL_XFORM_DQS13 */
- 0x00064000, /* EMC_DLL_XFORM_DQS14 */
- 0x00064000, /* EMC_DLL_XFORM_DQS15 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS8 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS9 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS10 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS11 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS12 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS13 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS14 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS15 */
0x00000000, /* EMC_DLL_XFORM_QUSE0 */
0x00000000, /* EMC_DLL_XFORM_QUSE1 */
0x00000000, /* EMC_DLL_XFORM_QUSE2 */
@@ -11687,14 +11687,14 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* MC_EMEM_ARB_TIMING_RAS */
0x00000002, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
- 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
0x00000003, /* MC_EMEM_ARB_TIMING_R2R */
0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
0x06030203, /* MC_EMEM_ARB_DA_TURNS */
- 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x000a0502, /* MC_EMEM_ARB_DA_COVERS */
0x77e30303, /* MC_EMEM_ARB_MISC0 */
0x70000f03, /* MC_EMEM_ARB_MISC1 */
0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
@@ -11750,8 +11750,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
57820, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_20400_03_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_20400_01_V5.0.17_V1.1", /* DVFS table version */
20400, /* SDRAM frequency */
800, /* min voltage */
800, /* gpu min voltage */
@@ -11767,7 +11767,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* EMC_RP */
0x00000004, /* EMC_R2W */
0x0000000a, /* EMC_W2R */
- 0x00000003, /* EMC_R2P */
+ 0x00000005, /* EMC_R2P */
0x0000000b, /* EMC_W2P */
0x00000000, /* EMC_RD_RCD */
0x00000000, /* EMC_WR_RCD */
@@ -11816,22 +11816,22 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x106aa298, /* EMC_FBIO_CFG5 */
0x002c00a0, /* EMC_CFG_DIG_DLL */
0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
- 0x00064000, /* EMC_DLL_XFORM_DQS0 */
- 0x00064000, /* EMC_DLL_XFORM_DQS1 */
- 0x00064000, /* EMC_DLL_XFORM_DQS2 */
- 0x00064000, /* EMC_DLL_XFORM_DQS3 */
- 0x00064000, /* EMC_DLL_XFORM_DQS4 */
- 0x00064000, /* EMC_DLL_XFORM_DQS5 */
- 0x00064000, /* EMC_DLL_XFORM_DQS6 */
- 0x00064000, /* EMC_DLL_XFORM_DQS7 */
- 0x00064000, /* EMC_DLL_XFORM_DQS8 */
- 0x00064000, /* EMC_DLL_XFORM_DQS9 */
- 0x00064000, /* EMC_DLL_XFORM_DQS10 */
- 0x00064000, /* EMC_DLL_XFORM_DQS11 */
- 0x00064000, /* EMC_DLL_XFORM_DQS12 */
- 0x00064000, /* EMC_DLL_XFORM_DQS13 */
- 0x00064000, /* EMC_DLL_XFORM_DQS14 */
- 0x00064000, /* EMC_DLL_XFORM_DQS15 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS8 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS9 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS10 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS11 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS12 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS13 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS14 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS15 */
0x00000000, /* EMC_DLL_XFORM_QUSE0 */
0x00000000, /* EMC_DLL_XFORM_QUSE1 */
0x00000000, /* EMC_DLL_XFORM_QUSE2 */
@@ -11914,14 +11914,14 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* MC_EMEM_ARB_TIMING_RAS */
0x00000002, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
- 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
0x00000003, /* MC_EMEM_ARB_TIMING_R2R */
0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
0x06030203, /* MC_EMEM_ARB_DA_TURNS */
- 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x000a0502, /* MC_EMEM_ARB_DA_COVERS */
0x76230303, /* MC_EMEM_ARB_MISC0 */
0x70000f03, /* MC_EMEM_ARB_MISC1 */
0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
@@ -11977,8 +11977,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
35610, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_40800_03_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_40800_01_V5.0.17_V1.1", /* DVFS table version */
40800, /* SDRAM frequency */
800, /* min voltage */
800, /* gpu min voltage */
@@ -11994,7 +11994,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* EMC_RP */
0x00000004, /* EMC_R2W */
0x0000000a, /* EMC_W2R */
- 0x00000003, /* EMC_R2P */
+ 0x00000005, /* EMC_R2P */
0x0000000b, /* EMC_W2P */
0x00000000, /* EMC_RD_RCD */
0x00000000, /* EMC_WR_RCD */
@@ -12043,22 +12043,22 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x106aa298, /* EMC_FBIO_CFG5 */
0x002c00a0, /* EMC_CFG_DIG_DLL */
0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
- 0x00064000, /* EMC_DLL_XFORM_DQS0 */
- 0x00064000, /* EMC_DLL_XFORM_DQS1 */
- 0x00064000, /* EMC_DLL_XFORM_DQS2 */
- 0x00064000, /* EMC_DLL_XFORM_DQS3 */
- 0x00064000, /* EMC_DLL_XFORM_DQS4 */
- 0x00064000, /* EMC_DLL_XFORM_DQS5 */
- 0x00064000, /* EMC_DLL_XFORM_DQS6 */
- 0x00064000, /* EMC_DLL_XFORM_DQS7 */
- 0x00064000, /* EMC_DLL_XFORM_DQS8 */
- 0x00064000, /* EMC_DLL_XFORM_DQS9 */
- 0x00064000, /* EMC_DLL_XFORM_DQS10 */
- 0x00064000, /* EMC_DLL_XFORM_DQS11 */
- 0x00064000, /* EMC_DLL_XFORM_DQS12 */
- 0x00064000, /* EMC_DLL_XFORM_DQS13 */
- 0x00064000, /* EMC_DLL_XFORM_DQS14 */
- 0x00064000, /* EMC_DLL_XFORM_DQS15 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS8 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS9 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS10 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS11 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS12 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS13 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS14 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS15 */
0x00000000, /* EMC_DLL_XFORM_QUSE0 */
0x00000000, /* EMC_DLL_XFORM_QUSE1 */
0x00000000, /* EMC_DLL_XFORM_QUSE2 */
@@ -12141,14 +12141,14 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* MC_EMEM_ARB_TIMING_RAS */
0x00000002, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
- 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
0x00000003, /* MC_EMEM_ARB_TIMING_R2R */
0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
0x06030203, /* MC_EMEM_ARB_DA_TURNS */
- 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x000a0502, /* MC_EMEM_ARB_DA_COVERS */
0x74a30303, /* MC_EMEM_ARB_MISC0 */
0x70000f03, /* MC_EMEM_ARB_MISC1 */
0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
@@ -12204,8 +12204,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
20850, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_68000_03_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_68000_01_V5.0.17_V1.1", /* DVFS table version */
68000, /* SDRAM frequency */
800, /* min voltage */
800, /* gpu min voltage */
@@ -12221,7 +12221,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* EMC_RP */
0x00000004, /* EMC_R2W */
0x0000000a, /* EMC_W2R */
- 0x00000003, /* EMC_R2P */
+ 0x00000005, /* EMC_R2P */
0x0000000b, /* EMC_W2P */
0x00000000, /* EMC_RD_RCD */
0x00000000, /* EMC_WR_RCD */
@@ -12270,22 +12270,22 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x106aa298, /* EMC_FBIO_CFG5 */
0x002c00a0, /* EMC_CFG_DIG_DLL */
0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
- 0x00064000, /* EMC_DLL_XFORM_DQS0 */
- 0x00064000, /* EMC_DLL_XFORM_DQS1 */
- 0x00064000, /* EMC_DLL_XFORM_DQS2 */
- 0x00064000, /* EMC_DLL_XFORM_DQS3 */
- 0x00064000, /* EMC_DLL_XFORM_DQS4 */
- 0x00064000, /* EMC_DLL_XFORM_DQS5 */
- 0x00064000, /* EMC_DLL_XFORM_DQS6 */
- 0x00064000, /* EMC_DLL_XFORM_DQS7 */
- 0x00064000, /* EMC_DLL_XFORM_DQS8 */
- 0x00064000, /* EMC_DLL_XFORM_DQS9 */
- 0x00064000, /* EMC_DLL_XFORM_DQS10 */
- 0x00064000, /* EMC_DLL_XFORM_DQS11 */
- 0x00064000, /* EMC_DLL_XFORM_DQS12 */
- 0x00064000, /* EMC_DLL_XFORM_DQS13 */
- 0x00064000, /* EMC_DLL_XFORM_DQS14 */
- 0x00064000, /* EMC_DLL_XFORM_DQS15 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS8 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS9 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS10 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS11 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS12 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS13 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS14 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS15 */
0x00000000, /* EMC_DLL_XFORM_QUSE0 */
0x00000000, /* EMC_DLL_XFORM_QUSE1 */
0x00000000, /* EMC_DLL_XFORM_QUSE2 */
@@ -12368,14 +12368,14 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* MC_EMEM_ARB_TIMING_RAS */
0x00000002, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
- 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
0x00000003, /* MC_EMEM_ARB_TIMING_R2R */
0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
0x06030203, /* MC_EMEM_ARB_DA_TURNS */
- 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x000a0502, /* MC_EMEM_ARB_DA_COVERS */
0x74230403, /* MC_EMEM_ARB_MISC0 */
0x70000f03, /* MC_EMEM_ARB_MISC1 */
0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
@@ -12431,8 +12431,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
10720, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_102000_03_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_102000_01_V5.0.17_V1.1", /* DVFS table version */
102000, /* SDRAM frequency */
800, /* min voltage */
800, /* gpu min voltage */
@@ -12448,7 +12448,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000001, /* EMC_RP */
0x00000004, /* EMC_R2W */
0x0000000a, /* EMC_W2R */
- 0x00000003, /* EMC_R2P */
+ 0x00000005, /* EMC_R2P */
0x0000000b, /* EMC_W2P */
0x00000001, /* EMC_RD_RCD */
0x00000001, /* EMC_WR_RCD */
@@ -12486,7 +12486,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000004, /* EMC_TCKE */
0x00000005, /* EMC_TCKESR */
0x00000004, /* EMC_TPD */
- 0x00000003, /* EMC_TFAW */
+ 0x00000002, /* EMC_TFAW */
0x00000000, /* EMC_TRPAB */
0x00000005, /* EMC_TCLKSTABLE */
0x00000005, /* EMC_TCLKSTOP */
@@ -12497,22 +12497,22 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x106aa298, /* EMC_FBIO_CFG5 */
0x002c00a0, /* EMC_CFG_DIG_DLL */
0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
- 0x00064000, /* EMC_DLL_XFORM_DQS0 */
- 0x00064000, /* EMC_DLL_XFORM_DQS1 */
- 0x00064000, /* EMC_DLL_XFORM_DQS2 */
- 0x00064000, /* EMC_DLL_XFORM_DQS3 */
- 0x00064000, /* EMC_DLL_XFORM_DQS4 */
- 0x00064000, /* EMC_DLL_XFORM_DQS5 */
- 0x00064000, /* EMC_DLL_XFORM_DQS6 */
- 0x00064000, /* EMC_DLL_XFORM_DQS7 */
- 0x00064000, /* EMC_DLL_XFORM_DQS8 */
- 0x00064000, /* EMC_DLL_XFORM_DQS9 */
- 0x00064000, /* EMC_DLL_XFORM_DQS10 */
- 0x00064000, /* EMC_DLL_XFORM_DQS11 */
- 0x00064000, /* EMC_DLL_XFORM_DQS12 */
- 0x00064000, /* EMC_DLL_XFORM_DQS13 */
- 0x00064000, /* EMC_DLL_XFORM_DQS14 */
- 0x00064000, /* EMC_DLL_XFORM_DQS15 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS8 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS9 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS10 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS11 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS12 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS13 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS14 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS15 */
0x00000000, /* EMC_DLL_XFORM_QUSE0 */
0x00000000, /* EMC_DLL_XFORM_QUSE1 */
0x00000000, /* EMC_DLL_XFORM_QUSE2 */
@@ -12595,14 +12595,14 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* MC_EMEM_ARB_TIMING_RAS */
0x00000002, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
- 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
0x00000003, /* MC_EMEM_ARB_TIMING_R2R */
0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
0x06030203, /* MC_EMEM_ARB_DA_TURNS */
- 0x000a0403, /* MC_EMEM_ARB_DA_COVERS */
+ 0x000a0503, /* MC_EMEM_ARB_DA_COVERS */
0x73c30504, /* MC_EMEM_ARB_MISC0 */
0x70000f03, /* MC_EMEM_ARB_MISC1 */
0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
@@ -12658,8 +12658,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
6890, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_204000_04_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_204000_01_V5.0.17_V1.1", /* DVFS table version */
204000, /* SDRAM frequency */
800, /* min voltage */
800, /* gpu min voltage */
@@ -12675,7 +12675,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000002, /* EMC_RP */
0x00000005, /* EMC_R2W */
0x0000000a, /* EMC_W2R */
- 0x00000003, /* EMC_R2P */
+ 0x00000005, /* EMC_R2P */
0x0000000b, /* EMC_W2P */
0x00000002, /* EMC_RD_RCD */
0x00000002, /* EMC_WR_RCD */
@@ -12713,7 +12713,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000004, /* EMC_TCKE */
0x00000005, /* EMC_TCKESR */
0x00000004, /* EMC_TPD */
- 0x00000007, /* EMC_TFAW */
+ 0x00000006, /* EMC_TFAW */
0x00000000, /* EMC_TRPAB */
0x00000005, /* EMC_TCLKSTABLE */
0x00000005, /* EMC_TCLKSTOP */
@@ -12724,22 +12724,22 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x106aa298, /* EMC_FBIO_CFG5 */
0x002c00a0, /* EMC_CFG_DIG_DLL */
0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
- 0x00064000, /* EMC_DLL_XFORM_DQS0 */
- 0x00064000, /* EMC_DLL_XFORM_DQS1 */
- 0x00064000, /* EMC_DLL_XFORM_DQS2 */
- 0x00064000, /* EMC_DLL_XFORM_DQS3 */
- 0x00064000, /* EMC_DLL_XFORM_DQS4 */
- 0x00064000, /* EMC_DLL_XFORM_DQS5 */
- 0x00064000, /* EMC_DLL_XFORM_DQS6 */
- 0x00064000, /* EMC_DLL_XFORM_DQS7 */
- 0x00064000, /* EMC_DLL_XFORM_DQS8 */
- 0x00064000, /* EMC_DLL_XFORM_DQS9 */
- 0x00064000, /* EMC_DLL_XFORM_DQS10 */
- 0x00064000, /* EMC_DLL_XFORM_DQS11 */
- 0x00064000, /* EMC_DLL_XFORM_DQS12 */
- 0x00064000, /* EMC_DLL_XFORM_DQS13 */
- 0x00064000, /* EMC_DLL_XFORM_DQS14 */
- 0x00064000, /* EMC_DLL_XFORM_DQS15 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS8 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS9 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS10 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS11 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS12 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS13 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS14 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS15 */
0x00000000, /* EMC_DLL_XFORM_QUSE0 */
0x00000000, /* EMC_DLL_XFORM_QUSE1 */
0x00000000, /* EMC_DLL_XFORM_QUSE2 */
@@ -12820,16 +12820,16 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000001, /* MC_EMEM_ARB_TIMING_RP */
0x00000004, /* MC_EMEM_ARB_TIMING_RC */
0x00000002, /* MC_EMEM_ARB_TIMING_RAS */
- 0x00000004, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
- 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
0x00000003, /* MC_EMEM_ARB_TIMING_R2R */
0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
0x00000004, /* MC_EMEM_ARB_TIMING_R2W */
0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
0x06040203, /* MC_EMEM_ARB_DA_TURNS */
- 0x000a0404, /* MC_EMEM_ARB_DA_COVERS */
+ 0x000a0504, /* MC_EMEM_ARB_DA_COVERS */
0x73840a05, /* MC_EMEM_ARB_MISC0 */
0x70000f03, /* MC_EMEM_ARB_MISC1 */
0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
@@ -12871,8 +12871,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
0x00000802, /* EMC_CTT_TERM_CTRL */
0x73240000, /* EMC_CFG */
- 0x0000088d, /* EMC_CFG_2 */
- 0x00040008, /* EMC_SEL_DPD_CTRL */
+ 0x000008cd, /* EMC_CFG_2 */
+ 0x00040128, /* EMC_SEL_DPD_CTRL */
0x002c0068, /* EMC_CFG_DIG_DLL */
0x00000008, /* EMC_BGBIAS_CTL0 */
0x00000000, /* EMC_AUTO_CAL_CONFIG2 */
@@ -12885,8 +12885,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
3420, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_300000_04_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_300000_01_V5.0.17_V1.1", /* DVFS table version */
300000, /* SDRAM frequency */
820, /* min voltage */
820, /* gpu min voltage */
@@ -12940,7 +12940,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000004, /* EMC_TCKE */
0x00000005, /* EMC_TCKESR */
0x00000004, /* EMC_TPD */
- 0x00000009, /* EMC_TFAW */
+ 0x00000008, /* EMC_TFAW */
0x00000000, /* EMC_TRPAB */
0x00000005, /* EMC_TCLKSTABLE */
0x00000005, /* EMC_TCLKSTOP */
@@ -13005,14 +13005,14 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* EMC_DLI_TRIM_TXDQS13 */
0x00000000, /* EMC_DLI_TRIM_TXDQS14 */
0x00000000, /* EMC_DLI_TRIM_TXDQS15 */
- 0x00060000, /* EMC_DLL_XFORM_DQ0 */
- 0x00060000, /* EMC_DLL_XFORM_DQ1 */
- 0x00060000, /* EMC_DLL_XFORM_DQ2 */
- 0x00060000, /* EMC_DLL_XFORM_DQ3 */
- 0x00006000, /* EMC_DLL_XFORM_DQ4 */
- 0x00006000, /* EMC_DLL_XFORM_DQ5 */
- 0x00006000, /* EMC_DLL_XFORM_DQ6 */
- 0x00006000, /* EMC_DLL_XFORM_DQ7 */
+ 0x00050000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00050000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00050000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00050000, /* EMC_DLL_XFORM_DQ3 */
+ 0x00005000, /* EMC_DLL_XFORM_DQ4 */
+ 0x00005000, /* EMC_DLL_XFORM_DQ5 */
+ 0x00005000, /* EMC_DLL_XFORM_DQ6 */
+ 0x00005000, /* EMC_DLL_XFORM_DQ7 */
0x10000280, /* EMC_XM2CMDPADCTRL */
0x00000000, /* EMC_XM2CMDPADCTRL4 */
0x00111111, /* EMC_XM2CMDPADCTRL5 */
@@ -13047,7 +13047,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000002, /* MC_EMEM_ARB_TIMING_RP */
0x00000007, /* MC_EMEM_ARB_TIMING_RC */
0x00000004, /* MC_EMEM_ARB_TIMING_RAS */
- 0x00000005, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000007, /* MC_EMEM_ARB_TIMING_WAP2PRE */
@@ -13112,8 +13112,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
2680, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_396000_05_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_396000_01_V5.0.17_V1.1", /* DVFS table version */
396000, /* SDRAM frequency */
850, /* min voltage */
850, /* gpu min voltage */
@@ -13167,7 +13167,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000004, /* EMC_TCKE */
0x00000005, /* EMC_TCKESR */
0x00000004, /* EMC_TPD */
- 0x0000000d, /* EMC_TFAW */
+ 0x0000000b, /* EMC_TFAW */
0x00000000, /* EMC_TRPAB */
0x00000005, /* EMC_TCLKSTABLE */
0x00000005, /* EMC_TCLKSTOP */
@@ -13274,7 +13274,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000002, /* MC_EMEM_ARB_TIMING_RP */
0x00000009, /* MC_EMEM_ARB_TIMING_RC */
0x00000005, /* MC_EMEM_ARB_TIMING_RAS */
- 0x00000007, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
@@ -13339,8 +13339,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
2180, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_528000_05_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_528000_01_V5.0.17_V1.1", /* DVFS table version */
528000, /* SDRAM frequency */
880, /* min voltage */
870, /* gpu min voltage */
@@ -13394,7 +13394,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000004, /* EMC_TCKE */
0x00000005, /* EMC_TCKESR */
0x00000004, /* EMC_TPD */
- 0x00000013, /* EMC_TFAW */
+ 0x00000010, /* EMC_TFAW */
0x00000000, /* EMC_TRPAB */
0x00000006, /* EMC_TCLKSTABLE */
0x00000006, /* EMC_TCLKSTOP */
@@ -13459,14 +13459,14 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* EMC_DLI_TRIM_TXDQS13 */
0x00000000, /* EMC_DLI_TRIM_TXDQS14 */
0x00000000, /* EMC_DLI_TRIM_TXDQS15 */
- 0x0000000e, /* EMC_DLL_XFORM_DQ0 */
- 0x0000000e, /* EMC_DLL_XFORM_DQ1 */
- 0x0000000e, /* EMC_DLL_XFORM_DQ2 */
- 0x0000000e, /* EMC_DLL_XFORM_DQ3 */
- 0x0000000e, /* EMC_DLL_XFORM_DQ4 */
- 0x0000000e, /* EMC_DLL_XFORM_DQ5 */
- 0x0000000e, /* EMC_DLL_XFORM_DQ6 */
- 0x0000000e, /* EMC_DLL_XFORM_DQ7 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ0 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ1 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ2 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ3 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ4 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ5 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ6 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ7 */
0x100002a0, /* EMC_XM2CMDPADCTRL */
0x00000000, /* EMC_XM2CMDPADCTRL4 */
0x00111111, /* EMC_XM2CMDPADCTRL5 */
@@ -13501,7 +13501,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000003, /* MC_EMEM_ARB_TIMING_RP */
0x0000000c, /* MC_EMEM_ARB_TIMING_RC */
0x00000007, /* MC_EMEM_ARB_TIMING_RAS */
- 0x0000000a, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x00000009, /* MC_EMEM_ARB_TIMING_WAP2PRE */
@@ -13566,8 +13566,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
1440, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_600000_03_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_600000_01_V5.0.17_V1.1", /* DVFS table version */
600000, /* SDRAM frequency */
910, /* min voltage */
910, /* gpu min voltage */
@@ -13621,7 +13621,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000004, /* EMC_TCKE */
0x00000005, /* EMC_TCKESR */
0x00000004, /* EMC_TPD */
- 0x00000015, /* EMC_TFAW */
+ 0x00000013, /* EMC_TFAW */
0x00000000, /* EMC_TRPAB */
0x00000006, /* EMC_TCLKSTABLE */
0x00000006, /* EMC_TCLKSTOP */
@@ -13720,7 +13720,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* EMC_CTT */
0x00000003, /* EMC_CTT_DURATION */
0x000040a0, /* EMC_CFG_PIPE */
- 0x800024a9, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x800024aa, /* EMC_DYN_SELF_REF_CONTROL */
0x0000000e, /* EMC_QPOP */
0x00000009, /* MC_EMEM_ARB_CFG */
0x80000040, /* MC_EMEM_ARB_OUTSTANDING_REQ */
@@ -13728,7 +13728,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000004, /* MC_EMEM_ARB_TIMING_RP */
0x0000000e, /* MC_EMEM_ARB_TIMING_RC */
0x00000009, /* MC_EMEM_ARB_TIMING_RAS */
- 0x0000000b, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x0000000a, /* MC_EMEM_ARB_TIMING_FAW */
0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x0000000b, /* MC_EMEM_ARB_TIMING_WAP2PRE */
@@ -13793,8 +13793,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
1440, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_792000_06_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_792000_01_V5.0.17_V1.1", /* DVFS table version */
792000, /* SDRAM frequency */
980, /* min voltage */
980, /* gpu min voltage */
@@ -13814,7 +13814,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000013, /* EMC_W2P */
0x0000000a, /* EMC_RD_RCD */
0x0000000a, /* EMC_WR_RCD */
- 0x00000003, /* EMC_RRD */
+ 0x00000004, /* EMC_RRD */
0x00000002, /* EMC_REXT */
0x00000000, /* EMC_WEXT */
0x00000006, /* EMC_WDV */
@@ -13848,7 +13848,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000005, /* EMC_TCKE */
0x00000006, /* EMC_TCKESR */
0x00000005, /* EMC_TPD */
- 0x0000001d, /* EMC_TFAW */
+ 0x00000019, /* EMC_TFAW */
0x00000000, /* EMC_TRPAB */
0x00000008, /* EMC_TCLKSTABLE */
0x00000008, /* EMC_TCLKSTOP */
@@ -13859,22 +13859,22 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x104ab098, /* EMC_FBIO_CFG5 */
0xe00700b1, /* EMC_CFG_DIG_DLL */
0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
- 0x00000008, /* EMC_DLL_XFORM_DQS0 */
- 0x00000008, /* EMC_DLL_XFORM_DQS1 */
- 0x00000008, /* EMC_DLL_XFORM_DQS2 */
- 0x00000008, /* EMC_DLL_XFORM_DQS3 */
- 0x00000008, /* EMC_DLL_XFORM_DQS4 */
- 0x00000008, /* EMC_DLL_XFORM_DQS5 */
- 0x00000008, /* EMC_DLL_XFORM_DQS6 */
- 0x00000008, /* EMC_DLL_XFORM_DQS7 */
- 0x00000008, /* EMC_DLL_XFORM_DQS8 */
- 0x00000008, /* EMC_DLL_XFORM_DQS9 */
- 0x00000008, /* EMC_DLL_XFORM_DQS10 */
- 0x00000008, /* EMC_DLL_XFORM_DQS11 */
- 0x00000008, /* EMC_DLL_XFORM_DQS12 */
- 0x00000008, /* EMC_DLL_XFORM_DQS13 */
- 0x00000008, /* EMC_DLL_XFORM_DQS14 */
- 0x00000008, /* EMC_DLL_XFORM_DQS15 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS0 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS1 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS2 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS3 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS4 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS5 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS6 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS7 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS8 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS9 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS10 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS11 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS12 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS13 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS14 */
+ 0x007fc008, /* EMC_DLL_XFORM_DQS15 */
0x00000000, /* EMC_DLL_XFORM_QUSE0 */
0x00000000, /* EMC_DLL_XFORM_QUSE1 */
0x00000000, /* EMC_DLL_XFORM_QUSE2 */
@@ -13955,7 +13955,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000005, /* MC_EMEM_ARB_TIMING_RP */
0x00000013, /* MC_EMEM_ARB_TIMING_RC */
0x0000000c, /* MC_EMEM_ARB_TIMING_RAS */
- 0x0000000f, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x0000000d, /* MC_EMEM_ARB_TIMING_FAW */
0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x0000000c, /* MC_EMEM_ARB_TIMING_WAP2PRE */
@@ -14020,8 +14020,8 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
1200, /* expected dvfs latency (ns) */
},
{
- 0x19, /* V5.0.14 */
- "04_924000_06_V5.0.14_V1.1", /* DVFS table version */
+ 0x19, /* V5.0.17 */
+ "01_924000_01_V5.0.17_V1.1", /* DVFS table version */
924000, /* SDRAM frequency */
1010, /* min voltage */
1010, /* gpu min voltage */
@@ -14075,7 +14075,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000006, /* EMC_TCKE */
0x00000007, /* EMC_TCKESR */
0x00000006, /* EMC_TPD */
- 0x00000022, /* EMC_TFAW */
+ 0x0000001e, /* EMC_TFAW */
0x00000000, /* EMC_TRPAB */
0x0000000a, /* EMC_TCLKSTABLE */
0x0000000a, /* EMC_TCLKSTOP */
@@ -14124,22 +14124,22 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000000, /* EMC_DLL_XFORM_QUSE13 */
0x00000000, /* EMC_DLL_XFORM_QUSE14 */
0x00000000, /* EMC_DLL_XFORM_QUSE15 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS0 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS1 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS2 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS3 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS4 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS5 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS6 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS7 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS8 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS9 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS10 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS11 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS12 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS13 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS14 */
- 0x00000005, /* EMC_DLI_TRIM_TXDQS15 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS8 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS9 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS10 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS11 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS12 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS13 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS14 */
+ 0x00000004, /* EMC_DLI_TRIM_TXDQS15 */
0x00000008, /* EMC_DLL_XFORM_DQ0 */
0x00000008, /* EMC_DLL_XFORM_DQ1 */
0x00000008, /* EMC_DLL_XFORM_DQ2 */
@@ -14182,7 +14182,7 @@ static struct tegra12_emc_table jetson_tk1_ddr3_emc_table[] = {
0x00000006, /* MC_EMEM_ARB_TIMING_RP */
0x00000016, /* MC_EMEM_ARB_TIMING_RC */
0x0000000e, /* MC_EMEM_ARB_TIMING_RAS */
- 0x00000011, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x0000000f, /* MC_EMEM_ARB_TIMING_FAW */
0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
0x00000004, /* MC_EMEM_ARB_TIMING_RAP2PRE */
0x0000000e, /* MC_EMEM_ARB_TIMING_WAP2PRE */
diff --git a/arch/arm/mach-tegra/board-ardbeg-sdhci.c b/arch/arm/mach-tegra/board-ardbeg-sdhci.c
index 5d7d2fbde651..80ea1e8b2055 100644
--- a/arch/arm/mach-tegra/board-ardbeg-sdhci.c
+++ b/arch/arm/mach-tegra/board-ardbeg-sdhci.c
@@ -27,6 +27,7 @@
#include <linux/wl12xx.h>
#include <linux/platform_data/mmc-sdhci-tegra.h>
#include <linux/mfd/max77660/max77660-core.h>
+#include <linux/tegra-fuse.h>
#include <asm/mach-types.h>
#include <mach/irqs.h>
@@ -50,6 +51,7 @@ static unsigned int wifi_states[] = {ON, OFF};
#define ARDBEG_SD_CD TEGRA_GPIO_PV2
#define ARDBEG_SD_WP TEGRA_GPIO_PQ4
+#define FUSE_SOC_SPEEDO_0 0x134
static void (*wifi_status_cb)(int card_present, void *dev_id);
static void *wifi_status_cb_devid;
@@ -206,7 +208,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
.power_gpio = -1,
.is_8bit = 1,
.tap_delay = 0x4,
- .trim_delay = 0x4,
+ .trim_delay = 0x3,
.ddr_trim_delay = 0x0,
.mmc_data = {
.built_in = 1,
@@ -384,7 +386,8 @@ static int __init ardbeg_wifi_prepower(void)
!of_machine_is_compatible("nvidia,laguna") &&
!of_machine_is_compatible("nvidia,ardbeg_sata") &&
!of_machine_is_compatible("nvidia,tn8") &&
- !of_machine_is_compatible("nvidia,norrin"))
+ !of_machine_is_compatible("nvidia,norrin") &&
+ !of_machine_is_compatible("nvidia,jetson-tk1"))
return 0;
ardbeg_wifi_power(1);
@@ -399,6 +402,7 @@ int __init ardbeg_sdhci_init(void)
int nominal_core_mv;
int min_vcore_override_mv;
int boot_vcore_mv;
+ u32 speedo;
struct board_info board_info;
nominal_core_mv =
@@ -425,7 +429,8 @@ int __init ardbeg_sdhci_init(void)
tegra_sdhci_platform_data3.boot_vcore_mv = boot_vcore_mv;
}
- if (of_machine_is_compatible("nvidia,laguna"))
+ if (of_machine_is_compatible("nvidia,laguna") ||
+ of_machine_is_compatible("nvidia,jetson-tk1"))
tegra_sdhci_platform_data2.wp_gpio = ARDBEG_SD_WP;
tegra_get_board_info(&board_info);
@@ -443,6 +448,24 @@ int __init ardbeg_sdhci_init(void)
board_info.board_id == BOARD_PM359)
tegra_sdhci_platform_data0.disable_clock_gate = 1;
+ /*
+ * FIXME: Set max clk limit to 200MHz for SDMMC3 for PM375.
+ * Requesting 208MHz results in getting 204MHz from PLL_P
+ * and CRC errors are seen with same.
+ */
+ if (board_info.board_id == BOARD_PM375)
+ tegra_sdhci_platform_data2.max_clk_limit = 200000000;
+
+ speedo = tegra_fuse_readl(FUSE_SOC_SPEEDO_0);
+ tegra_sdhci_platform_data0.cpu_speedo = speedo;
+ tegra_sdhci_platform_data2.cpu_speedo = speedo;
+ tegra_sdhci_platform_data3.cpu_speedo = speedo;
+
+ speedo = tegra_fuse_readl(FUSE_SOC_SPEEDO_0);
+ tegra_sdhci_platform_data0.cpu_speedo = speedo;
+ tegra_sdhci_platform_data2.cpu_speedo = speedo;
+ tegra_sdhci_platform_data3.cpu_speedo = speedo;
+
platform_device_register(&tegra_sdhci_device3);
platform_device_register(&tegra_sdhci_device2);
if (board_info.board_id != BOARD_PM359 &&
diff --git a/arch/arm/mach-tegra/board-ardbeg.c b/arch/arm/mach-tegra/board-ardbeg.c
index 2b7e726bc772..28e7fefa4207 100644
--- a/arch/arm/mach-tegra/board-ardbeg.c
+++ b/arch/arm/mach-tegra/board-ardbeg.c
@@ -1299,7 +1299,6 @@ static void __init tegra_ardbeg_late_init(void)
else
platform_device_register(&ardbeg_audio_device_rt5639);
- //tegra_ram_console_debug_init();
tegra_io_dpd_init();
ardbeg_sdhci_init();
if (board_info.board_id == BOARD_PM359 ||
@@ -1373,11 +1372,6 @@ static void __init tegra_ardbeg_late_init(void)
ardbeg_sysedp_batmon_init();
}
-static void __init ardbeg_ramconsole_reserve(unsigned long size)
-{
- tegra_ram_console_debug_reserve(SZ_1M);
-}
-
static void __init tegra_ardbeg_init_early(void)
{
ardbeg_rail_alignment_init();
@@ -1419,7 +1413,6 @@ static void __init tegra_ardbeg_reserve(void)
#endif
tegra_reserve(carveout_size, fb1_size, fb2_size);
- ardbeg_ramconsole_reserve(SZ_1M);
}
static const char * const ardbeg_dt_board_compat[] = {
@@ -1447,6 +1440,11 @@ static const char * const norrin_dt_board_compat[] = {
NULL
};
+static const char * const jetson_dt_board_compat[] = {
+ "nvidia,jetson-tk1",
+ NULL
+};
+
DT_MACHINE_START(LAGUNA, "laguna")
.atag_offset = 0x100,
.smp = smp_ops(tegra_smp_ops),
@@ -1517,3 +1515,17 @@ DT_MACHINE_START(ARDBEG_SATA, "ardbeg_sata")
.init_late = tegra_init_late
MACHINE_END
+
+DT_MACHINE_START(JETSON_TK1, "jetson-tk1")
+ .atag_offset = 0x100,
+ .smp = smp_ops(tegra_smp_ops),
+ .map_io = tegra_map_common_io,
+ .reserve = tegra_ardbeg_reserve,
+ .init_early = tegra_ardbeg_init_early,
+ .init_irq = irqchip_init,
+ .init_time = clocksource_of_init,
+ .init_machine = tegra_ardbeg_dt_init,
+ .restart = tegra_assert_system_reset,
+ .dt_compat = jetson_dt_board_compat,
+ .init_late = tegra_init_late
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-dalmore.c b/arch/arm/mach-tegra/board-dalmore.c
index 43460f9db428..9cadf4b77b03 100644
--- a/arch/arm/mach-tegra/board-dalmore.c
+++ b/arch/arm/mach-tegra/board-dalmore.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-dalmore.c
*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -671,7 +671,6 @@ static void __init tegra_dalmore_late_init(void)
dalmore_uart_init();
dalmore_audio_init();
platform_add_devices(dalmore_devices, ARRAY_SIZE(dalmore_devices));
- //tegra_ram_console_debug_init();
tegra_io_dpd_init();
dalmore_regulator_init();
dalmore_sdhci_init();
@@ -702,11 +701,6 @@ static void __init tegra_dalmore_late_init(void)
tegra_register_fuse();
}
-static void __init dalmore_ramconsole_reserve(unsigned long size)
-{
- tegra_ram_console_debug_reserve(SZ_1M);
-}
-
static void __init tegra_dalmore_dt_init(void)
{
tegra_get_board_info(&board_info);
@@ -729,7 +723,6 @@ static void __init tegra_dalmore_reserve(void)
#else
tegra_reserve(SZ_512M, SZ_16M + SZ_2M, SZ_4M);
#endif
- dalmore_ramconsole_reserve(SZ_1M);
}
static const char * const dalmore_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/board-laguna-power.c b/arch/arm/mach-tegra/board-laguna-power.c
index f2e0de9a5ed0..c34f6b42f39a 100644
--- a/arch/arm/mach-tegra/board-laguna-power.c
+++ b/arch/arm/mach-tegra/board-laguna-power.c
@@ -852,7 +852,8 @@ static int __init laguna_fixed_regulator_init(void)
{
struct board_info board_info;
- if (!of_machine_is_compatible("nvidia,laguna"))
+ if (!of_machine_is_compatible("nvidia,laguna") &&
+ !of_machine_is_compatible("nvidia,jetson-tk1"))
return 0;
tegra_get_board_info(&board_info);
diff --git a/arch/arm/mach-tegra/board-loki-sdhci.c b/arch/arm/mach-tegra/board-loki-sdhci.c
index 86504670dd43..42e2ab6fe188 100644
--- a/arch/arm/mach-tegra/board-loki-sdhci.c
+++ b/arch/arm/mach-tegra/board-loki-sdhci.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-loki-sdhci.c
*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -28,6 +28,7 @@
#include <linux/wl12xx.h>
#include <linux/platform_data/mmc-sdhci-tegra.h>
#include <linux/mfd/max77660/max77660-core.h>
+#include <linux/tegra-fuse.h>
#include <asm/mach-types.h>
#include <mach/irqs.h>
@@ -46,6 +47,8 @@
#define LOKI_SD_CD TEGRA_GPIO_PV2
+#define FUSE_SOC_SPEEDO_0 0x134
+
static void (*wifi_status_cb)(int card_present, void *dev_id);
static void *wifi_status_cb_devid;
static int loki_wifi_status_register(void (*callback)(int , void *), void *);
@@ -174,7 +177,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
.power_gpio = -1,
.is_8bit = 1,
.tap_delay = 0x4,
- .trim_delay = 0x4,
+ .trim_delay = 0x3,
.ddr_trim_delay = 0x0,
.mmc_data = {
.built_in = 1,
@@ -453,6 +456,7 @@ int __init loki_sdhci_init(void)
int nominal_core_mv;
int min_vcore_override_mv;
int boot_vcore_mv;
+ u32 speedo;
struct board_info bi;
tegra_get_board_info(&bi);
@@ -488,6 +492,12 @@ int __init loki_sdhci_init(void)
tegra_sdhci_platform_data0.max_clk_limit = 204000000;
+ speedo = tegra_fuse_readl(FUSE_SOC_SPEEDO_0);
+ tegra_sdhci_platform_data0.cpu_speedo = speedo;
+ tegra_sdhci_platform_data2.cpu_speedo = speedo;
+ tegra_sdhci_platform_data3.cpu_speedo = speedo;
+
+
platform_device_register(&tegra_sdhci_device3);
if (!is_uart_over_sd_enabled())
diff --git a/arch/arm/mach-tegra/board-loki.c b/arch/arm/mach-tegra/board-loki.c
index 570e001e7eed..b730466ef577 100644
--- a/arch/arm/mach-tegra/board-loki.c
+++ b/arch/arm/mach-tegra/board-loki.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-loki.c
*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -799,7 +799,6 @@ static void __init tegra_loki_late_init(void)
loki_uart_init();
loki_audio_init();
platform_add_devices(loki_devices, ARRAY_SIZE(loki_devices));
- //tegra_ram_console_debug_init();
tegra_io_dpd_init();
loki_sdhci_init();
loki_regulator_init();
@@ -827,11 +826,6 @@ static void __init tegra_loki_late_init(void)
#endif
}
-static void __init loki_ramconsole_reserve(unsigned long size)
-{
- tegra_ram_console_debug_reserve(SZ_1M);
-}
-
static void __init tegra_loki_dt_init(void)
{
tegra_get_board_info(&board_info);
@@ -856,7 +850,6 @@ static void __init tegra_loki_reserve(void)
#else
tegra_reserve(SZ_1G, SZ_16M + SZ_2M, SZ_4M);
#endif
- loki_ramconsole_reserve(SZ_1M);
}
static const char * const loki_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/board-macallan.c b/arch/arm/mach-tegra/board-macallan.c
index 2f0a50256477..47d320bc7076 100644
--- a/arch/arm/mach-tegra/board-macallan.c
+++ b/arch/arm/mach-tegra/board-macallan.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-macallan.c
*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -546,7 +546,6 @@ static void __init tegra_macallan_late_init(void)
macallan_uart_init();
macallan_audio_init();
platform_add_devices(macallan_devices, ARRAY_SIZE(macallan_devices));
- //tegra_ram_console_debug_init();
tegra_io_dpd_init();
macallan_regulator_init();
macallan_sdhci_init();
@@ -572,11 +571,6 @@ static void __init tegra_macallan_late_init(void)
tegra_register_fuse();
}
-static void __init macallan_ramconsole_reserve(unsigned long size)
-{
- tegra_ram_console_debug_reserve(SZ_1M);
-}
-
static void __init tegra_macallan_dt_init(void)
{
tegra_get_board_info(&board_info);
@@ -603,7 +597,6 @@ static void __init tegra_macallan_reserve(void)
#else
tegra_reserve(SZ_128M, SZ_16M + SZ_2M, SZ_16M + SZ_2M);
#endif
- macallan_ramconsole_reserve(SZ_1M);
}
static const char * const macallan_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/board-pismo.c b/arch/arm/mach-tegra/board-pismo.c
index 2577b12e5426..7dd931c4cff5 100644
--- a/arch/arm/mach-tegra/board-pismo.c
+++ b/arch/arm/mach-tegra/board-pismo.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-pismo.c
*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -595,7 +595,6 @@ static void __init tegra_pismo_init(void)
pismo_uart_init();
pismo_audio_init();
platform_add_devices(pismo_devices, ARRAY_SIZE(pismo_devices));
- //tegra_ram_console_debug_init();
tegra_io_dpd_init();
pismo_regulator_init();
pismo_sdhci_init();
@@ -619,11 +618,6 @@ static void __init tegra_pismo_init(void)
pismo_soctherm_init();
}
-static void __init pismo_ramconsole_reserve(unsigned long size)
-{
- tegra_ram_console_debug_reserve(SZ_1M);
-}
-
#ifdef CONFIG_USE_OF
struct of_dev_auxdata pismo_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("nvidia,tegra114-host1x", TEGRA_HOST1X_BASE, "host1x",
@@ -661,7 +655,6 @@ static void __init tegra_pismo_reserve(void)
#else
tegra_reserve(SZ_128M, SZ_16M + SZ_2M, SZ_4M);
#endif
- pismo_ramconsole_reserve(SZ_1M);
}
static const char * const pismo_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/board-pluto.c b/arch/arm/mach-tegra/board-pluto.c
index 68b162873e21..0735f5878281 100644
--- a/arch/arm/mach-tegra/board-pluto.c
+++ b/arch/arm/mach-tegra/board-pluto.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-pluto.c
*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -1229,7 +1229,6 @@ static void __init tegra_pluto_late_init(void)
pluto_uart_init();
pluto_audio_init();
platform_add_devices(pluto_devices, ARRAY_SIZE(pluto_devices));
- //tegra_ram_console_debug_init();
tegra_io_dpd_init();
pluto_sdhci_init();
pluto_regulator_init();
@@ -1258,10 +1257,6 @@ static void __init tegra_pluto_late_init(void)
tegra_register_fuse();
}
-static void __init pluto_ramconsole_reserve(unsigned long size)
-{
- tegra_ram_console_debug_reserve(SZ_1M);
-}
static void __init tegra_pluto_dt_init(void)
{
@@ -1282,7 +1277,6 @@ static void __init tegra_pluto_reserve(void)
#else
tegra_reserve(SZ_128M, SZ_16M, SZ_4M);
#endif
- pluto_ramconsole_reserve(SZ_1M);
}
static const char * const pluto_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/board-roth.c b/arch/arm/mach-tegra/board-roth.c
index b2518795227f..64e45e9fa8a5 100644
--- a/arch/arm/mach-tegra/board-roth.c
+++ b/arch/arm/mach-tegra/board-roth.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-roth.c
*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -571,7 +571,6 @@ static void __init tegra_roth_init(void)
roth_led_init();
roth_audio_init();
platform_add_devices(roth_devices, ARRAY_SIZE(roth_devices));
- //tegra_ram_console_debug_init();
tegra_io_dpd_init();
roth_regulator_init();
roth_sdhci_init();
@@ -601,11 +600,6 @@ static void __init tegra_roth_init(void)
roth_issp_init();
}
-static void __init roth_ramconsole_reserve(unsigned long size)
-{
- tegra_ram_console_debug_reserve(SZ_1M);
-}
-
#ifdef CONFIG_USE_OF
struct of_dev_auxdata roth_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("nvidia,tegra114-host1x", TEGRA_HOST1X_BASE, "host1x",
@@ -643,7 +637,6 @@ static void __init tegra_roth_reserve(void)
#else
tegra_reserve(SZ_128M, SZ_16M + SZ_2M, SZ_4M);
#endif
- roth_ramconsole_reserve(SZ_1M);
}
static const char * const roth_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/board-vcm30_t124.c b/arch/arm/mach-tegra/board-vcm30_t124.c
index bf76143776e6..eebf65a56561 100644
--- a/arch/arm/mach-tegra/board-vcm30_t124.c
+++ b/arch/arm/mach-tegra/board-vcm30_t124.c
@@ -487,11 +487,6 @@ static void __init tegra_vcm30_t124_late_init(void)
vcm30_t124_panel_init();
}
-static void __init vcm30_t124_ramconsole_reserve(unsigned long size)
-{
- tegra_ram_console_debug_reserve(SZ_1M);
-}
-
static void __init tegra_vcm30_t124_dt_init(void)
{
tegra_get_board_info(&board_info);
@@ -515,7 +510,6 @@ static void __init tegra_vcm30_t124_reserve(void)
#else
tegra_reserve(SZ_128M, SZ_16M + SZ_2M, SZ_4M);
#endif
- vcm30_t124_ramconsole_reserve(SZ_1M);
}
static const char * const vcm30_t124_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 6fd8cfe3f7cf..1db0118b0961 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -2,7 +2,7 @@
* arch/arm/mach-tegra/board.h
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2011-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
*
* Author:
* Colin Cross <ccross@google.com>
@@ -122,13 +122,6 @@ int get_sd_uart_port_id(void);
void set_sd_uart_port_id(int);
int __init tegra_register_fuse(void);
-#ifdef CONFIG_PSTORE_RAM
-void __init tegra_ram_console_debug_reserve(unsigned long ram_console_size);
-#else
-static inline void __init tegra_ram_console_debug_reserve(unsigned long ram_console_size)
-{}
-#endif
-
extern phys_addr_t tegra_bootloader_fb_start;
extern phys_addr_t tegra_bootloader_fb_size;
extern phys_addr_t tegra_bootloader_fb2_start;
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index c9941f2ebaee..4b21c8aa3974 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -1712,6 +1712,37 @@ static int use_alt_freq_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(use_alt_freq_fops,
use_alt_freq_get, use_alt_freq_set, "%llu\n");
+static ssize_t fmax_at_vmin_write(struct file *file,
+ const char __user *userbuf, size_t count, loff_t *ppos)
+{
+ struct clk *c = file->f_path.dentry->d_inode->i_private;
+ unsigned long f_max;
+ int v_min;
+ char buf[32];
+
+ if (sizeof(buf) <= count)
+ return -EINVAL;
+
+ if (copy_from_user(buf, userbuf, count))
+ return -EFAULT;
+
+ /* terminate buffer and trim - white spaces may be appended
+ * at the end when invoked from shell command line */
+ buf[count] = '\0';
+ strim(buf);
+
+ if (sscanf(buf, "%lu_at_%d", &f_max, &v_min) != 2)
+ return -EINVAL;
+
+ tegra_dvfs_set_fmax_at_vmin(c, f_max, v_min);
+
+ return count;
+}
+
+static const struct file_operations fmax_at_vmin_fops = {
+ .write = fmax_at_vmin_write,
+};
+
static int clk_debugfs_register_one(struct clk *c)
{
struct dentry *d;
@@ -1787,6 +1818,13 @@ static int clk_debugfs_register_one(struct clk *c)
goto err_out;
}
+ if (c->dvfs && c->dvfs->can_override) {
+ d = debugfs_create_file("fmax_at_vmin", S_IWUSR, c->dent,
+ c, &fmax_at_vmin_fops);
+ if (!d)
+ goto err_out;
+ }
+
return 0;
err_out:
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 1b76f7ecd804..f4961dd48308 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -113,6 +113,11 @@
#define ADDR_BNDRY(x) (((x) & 0xf) << 21)
#define INACTIVITY_TIMEOUT(x) (((x) & 0xffff) << 0)
+#ifdef CONFIG_PSTORE_RAM
+#define RAMOOPS_MEM_SIZE SZ_2M
+#define FTRACE_MEM_SIZE SZ_1M
+#endif
+
phys_addr_t tegra_bootloader_fb_start;
phys_addr_t tegra_bootloader_fb_size;
phys_addr_t tegra_bootloader_fb2_start;
@@ -881,7 +886,6 @@ void __init tegra20_init_early(void)
tegra_init_power();
tegra_init_ahb_gizmo_settings();
tegra_init_debug_uart_rate();
- tegra_ram_console_debug_reserve(SZ_1M);
}
#endif
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
@@ -928,7 +932,6 @@ void __init tegra30_init_early(void)
tegra_init_power();
tegra_init_ahb_gizmo_settings();
tegra_init_debug_uart_rate();
- tegra_ram_console_debug_reserve(SZ_1M);
init_dma_coherent_pool_size(SZ_1M);
}
@@ -1024,7 +1027,6 @@ void __init tegra14x_init_early(void)
tegra_init_power();
tegra_init_ahb_gizmo_settings();
tegra_init_debug_uart_rate();
- tegra_ram_console_debug_reserve(SZ_1M);
}
#endif
static int __init tegra_lp0_vec_arg(char *options)
@@ -1835,6 +1837,38 @@ void __tegra_clear_framebuffer(struct platform_device *pdev,
iounmap(to_io);
}
+#ifdef CONFIG_PSTORE_RAM
+static struct ramoops_platform_data ramoops_data;
+
+static struct platform_device ramoops_dev = {
+ .name = "ramoops",
+ .dev = {
+ .platform_data = &ramoops_data,
+ },
+};
+
+static void __init tegra_reserve_ramoops_memory(unsigned long reserve_size)
+{
+ ramoops_data.mem_size = reserve_size;
+ ramoops_data.mem_address = memblock_end_of_4G() - reserve_size;
+ ramoops_data.console_size = reserve_size - FTRACE_MEM_SIZE;
+ ramoops_data.ftrace_size = FTRACE_MEM_SIZE;
+ ramoops_data.dump_oops = 1;
+ memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size);
+}
+
+static int __init tegra_register_ramoops_device(void)
+{
+ int ret = platform_device_register(&ramoops_dev);
+ if (ret) {
+ pr_info("Unable to register ramoops platform device\n");
+ return ret;
+ }
+ return ret;
+}
+core_initcall(tegra_register_ramoops_device);
+#endif
+
void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
unsigned long fb2_size)
{
@@ -2126,6 +2160,9 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
#endif
tegra_fb_linear_set(map);
+#ifdef CONFIG_PSTORE_RAM
+ tegra_reserve_ramoops_memory(RAMOOPS_MEM_SIZE);
+#endif
}
void tegra_get_fb_resource(struct resource *fb_res)
@@ -2142,37 +2179,6 @@ void tegra_get_fb2_resource(struct resource *fb2_res)
(resource_size_t) tegra_fb2_size - 1;
}
-#ifdef CONFIG_PSTORE_RAM
-static struct persistent_ram_descriptor desc = {
- .name = "ramoops",
-};
-
-static struct persistent_ram ram = {
- .descs = &desc,
- .num_descs = 1,
-};
-
-void __init tegra_ram_console_debug_reserve(unsigned long ram_console_size)
-{
- int ret;
-
- ram.start = memblock_end_of_DRAM() - ram_console_size;
- ram.size = ram_console_size;
- ram.descs->size = ram_console_size;
-
- INIT_LIST_HEAD(&ram.node);
-
- ret = persistent_ram_early_init(&ram);
- if (ret)
- goto fail;
-
- return;
-
-fail:
- pr_err("Failed to reserve memory block for ram console\n");
-}
-#endif
-
int __init tegra_register_fuse(void)
{
return platform_device_register(&tegra_fuse_device);
diff --git a/arch/arm/mach-tegra/dvfs.c b/arch/arm/mach-tegra/dvfs.c
index 47c38be2dfd4..b1414a100350 100644
--- a/arch/arm/mach-tegra/dvfs.c
+++ b/arch/arm/mach-tegra/dvfs.c
@@ -830,6 +830,7 @@ int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate)
tegra_dvfs_get_millivolts_pll(c->dvfs);
return predict_millivolts(c, millivolts, rate);
}
+EXPORT_SYMBOL(tegra_dvfs_predict_millivolts);
int tegra_dvfs_predict_peak_millivolts(struct clk *c, unsigned long rate)
{
@@ -1004,12 +1005,74 @@ int tegra_dvfs_rail_get_override_floor(struct dvfs_rail *rail)
}
return -ENOENT;
}
+
+static int dvfs_set_fmax_at_vmin(struct clk *c, unsigned long f_max, int v_min)
+{
+ int i, ret = 0;
+ struct dvfs *d = c->dvfs;
+ unsigned long f_min = 1000; /* 1kHz min rate in DVFS tables */
+
+ mutex_lock(&rail_override_lock);
+ mutex_lock(&dvfs_lock);
+
+ if (v_min > d->dvfs_rail->override_millivolts) {
+ pr_err("%s: new %s vmin %dmV is above override voltage %dmV\n",
+ __func__, c->name, v_min,
+ d->dvfs_rail->override_millivolts);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (v_min >= d->max_millivolts) {
+ pr_err("%s: new %s vmin %dmV is at/above max voltage %dmV\n",
+ __func__, c->name, v_min, d->max_millivolts);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * dvfs table update:
+ * - for voltages below new v_min the respective frequencies are shifted
+ * below new f_max to the levels already present in the table; if the
+ * 1st table entry has frequency above new fmax, all entries below v_min
+ * are filled in with 1kHz (min rate used in DVFS tables).
+ * - for voltages above new v_min, the respective frequencies are
+ * increased to at least new f_max
+ * - if new v_min is already in the table set the respective frequency
+ * to new f_max
+ */
+ for (i = 0; i < d->num_freqs; i++) {
+ int mv = d->millivolts[i];
+ unsigned long f = d->freqs[i];
+
+ if (mv < v_min) {
+ if (d->freqs[i] >= f_max)
+ d->freqs[i] = i ? d->freqs[i-1] : f_min;
+ } else if (mv > v_min) {
+ d->freqs[i] = max(f, f_max);
+ } else {
+ d->freqs[i] = f_max;
+ }
+ ret = __tegra_dvfs_set_rate(d, d->cur_rate);
+ }
+out:
+ mutex_unlock(&dvfs_lock);
+ mutex_unlock(&rail_override_lock);
+
+ return ret;
+}
#else
static int dvfs_override_core_voltage(int override_mv)
{
pr_err("%s: vdd core override is not supported\n", __func__);
return -ENOSYS;
}
+
+static int dvfs_set_fmax_at_vmin(struct clk *c, unsigned long f_max, int v_min)
+{
+ pr_err("%s: vdd core override is not supported\n", __func__);
+ return -ENOSYS;
+}
#endif
int tegra_dvfs_override_core_voltage(struct clk *c, int override_mv)
@@ -1022,6 +1085,16 @@ int tegra_dvfs_override_core_voltage(struct clk *c, int override_mv)
}
EXPORT_SYMBOL(tegra_dvfs_override_core_voltage);
+int tegra_dvfs_set_fmax_at_vmin(struct clk *c, unsigned long f_max, int v_min)
+{
+ if (!c->dvfs || !c->dvfs->can_override) {
+ pr_err("%s: %s cannot set fmax_at_vmin)\n", __func__, c->name);
+ return -EPERM;
+ }
+ return dvfs_set_fmax_at_vmin(c, f_max, v_min);
+}
+EXPORT_SYMBOL(tegra_dvfs_set_fmax_at_vmin);
+
/* May only be called during clock init, does not take any locks on clock c. */
int __init tegra_enable_dvfs_on_clk(struct clk *c, struct dvfs *d)
{
diff --git a/arch/arm/mach-tegra/dvfs.h b/arch/arm/mach-tegra/dvfs.h
index 4565529b01bc..cc9ef7a315a1 100644
--- a/arch/arm/mach-tegra/dvfs.h
+++ b/arch/arm/mach-tegra/dvfs.h
@@ -250,7 +250,6 @@ void tegra_dvfs_rail_pause(struct dvfs_rail *rail, ktime_t delta, bool on);
int tegra_dvfs_rail_set_mode(struct dvfs_rail *rail, unsigned int mode);
struct dvfs_rail *tegra_dvfs_get_rail_by_name(const char *reg_id);
-int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate);
int tegra_dvfs_predict_peak_millivolts(struct clk *c, unsigned long rate);
const int *tegra_dvfs_get_millivolts_pll(struct dvfs *d);
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 51cc64fcfaaa..525f575d4e6c 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -1660,7 +1660,7 @@ void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat)
/* create the pdata from DT information */
pm_dat = tegra_get_pm_data();
if (pm_dat) {
- pr_err("PMC dt information non-NULL %s\n", __func__);
+ pr_debug("PMC dt information non-NULL %s\n", __func__);
is_board_pdata = false;
pdata = kzalloc(sizeof(struct tegra_suspend_platform_data),
GFP_KERNEL);
diff --git a/arch/arm/mach-tegra/powergate-t12x.c b/arch/arm/mach-tegra/powergate-t12x.c
index 05933a731a91..14bd096be15e 100644
--- a/arch/arm/mach-tegra/powergate-t12x.c
+++ b/arch/arm/mach-tegra/powergate-t12x.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -286,6 +286,7 @@ static struct powergate_partition_info tegra12x_powergate_partition_info[] = {
#define MC_CLIENT_HOTRESET_STAT 0x204
#define MC_CLIENT_HOTRESET_CTRL_1 0x970
#define MC_CLIENT_HOTRESET_STAT_1 0x974
+#define MC_VIDEO_PROTECT_REG_CTRL 0x650
#define PMC_GPU_RG_CNTRL_0 0x2d4
@@ -444,12 +445,27 @@ err_power_off:
return ret;
}
+static int mc_check_vpr(void)
+{
+ int ret = 0;
+ u32 val = mc_read(MC_VIDEO_PROTECT_REG_CTRL);
+ if ((val & 1) == 0) {
+ pr_err("VPR configuration not locked down\n");
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
static int tegra12x_gpu_unpowergate(int id,
struct powergate_partition_info *pg_info)
{
int ret = 0;
bool first = false;
+ ret = mc_check_vpr();
+ if (ret)
+ return ret;
+
if (!gpu_rail) {
gpu_rail = tegra_dvfs_get_rail_by_name("vdd_gpu");
if (IS_ERR_OR_NULL(gpu_rail)) {
diff --git a/arch/arm/mach-tegra/tegra12_clocks.c b/arch/arm/mach-tegra/tegra12_clocks.c
index c686b43d5bc5..c9a085bf70a2 100644
--- a/arch/arm/mach-tegra/tegra12_clocks.c
+++ b/arch/arm/mach-tegra/tegra12_clocks.c
@@ -8355,6 +8355,16 @@ struct clk_duplicate tegra_clk_duplicates[] = {
CLK_DUPLICATE("dam2", NULL, "dam2"),
CLK_DUPLICATE("spdif_in", NULL, "spdif_in"),
CLK_DUPLICATE("mclk", NULL, "default_mclk"),
+ CLK_DUPLICATE("amx", NULL, "amx"),
+ CLK_DUPLICATE("amx1", NULL, "amx1"),
+ CLK_DUPLICATE("adx", NULL, "adx"),
+ CLK_DUPLICATE("adx1", NULL, "adx1"),
+ CLK_DUPLICATE("afc0", NULL, "afc0"),
+ CLK_DUPLICATE("afc1", NULL, "afc1"),
+ CLK_DUPLICATE("afc2", NULL, "afc2"),
+ CLK_DUPLICATE("afc3", NULL, "afc3"),
+ CLK_DUPLICATE("afc4", NULL, "afc4"),
+ CLK_DUPLICATE("afc5", NULL, "afc5"),
CLK_DUPLICATE("amx", "tegra124-amx.0", NULL),
CLK_DUPLICATE("amx1", "tegra124-amx.1", NULL),
CLK_DUPLICATE("adx", "tegra124-adx.0", NULL),
@@ -9219,11 +9229,227 @@ static void tegra12_init_xusb_clocks(void)
tegra12_init_one_clock(&tegra_xusb_coupled_clks[i]);
}
+#ifdef CONFIG_TEGRA_PREINIT_CLOCKS
+
+#define CLK_RSTENB_DEV_V_0_AUDIO_BIT (1 << 10)
+#define CLK_RSTENB_DEV_V_0_3D2_BIT (1 << 2)
+
+#define CLK_RSTENB_DEV_L_0_HOST1X_BIT (1 << 28)
+#define CLK_RSTENB_DEV_L_0_DISP1_BIT (1 << 27)
+#define CLK_RSTENB_DEV_L_0_3D_BIT (1 << 24)
+#define CLK_RSTENB_DEV_L_0_ISP_BIT (1 << 23)
+#define CLK_RSTENB_DEV_L_0_2D_BIT (1 << 21)
+#define CLK_RSTENB_DEV_L_0_VI_BIT (1 << 20)
+#define CLK_RSTENB_DEV_L_0_EPP_BIT (1 << 19)
+
+#define CLK_RSTENB_DEV_H_0_VDE_BIT (1 << 29)
+#define CLK_RSTENB_DEV_H_0_MPE_BIT (1 << 28)
+
+#define CLK_RSTENB_DEV_U_0_CSITE_BIT (1 << 9)
+
+#define CLK_RSTENB_DEV_X_0_HDMI_AUDIO_BIT (1 << 16)
+
+#define HOST1X_CLK_REG_OFFSET 0x180
+#define HOST1X_CLK_SRC_SHIFT 30
+#define HOST1X_CLK_SRC_MASK (0x3 << HOST1X_CLK_SRC_SHIFT)
+#define HOST1X_CLK_SRC_PLLM_OUT0 0
+#define HOST1X_CLK_SRC_PLLC_OUT0 1
+#define HOST1X_CLK_SRC_PLLP_OUT0 2
+#define HOST1X_CLK_SRC_PLLA_OUT0 3
+#define HOST1X_CLK_SRC_DEFAULT (\
+ HOST1X_CLK_SRC_PLLP_OUT0 << HOST1X_CLK_SRC_SHIFT)
+#define HOST1X_CLK_IDLE_DIV_SHIFT 8
+#define HOST1X_CLK_IDLE_DIV_MASK (0xff << HOST1X_CLK_IDLE_DIV_SHIFT)
+#define HOST1X_CLK_IDLE_DIV_DEFAULT (0 << HOST1X_CLK_IDLE_DIV_SHIFT)
+#define HOST1X_CLK_DIV_SHIFT 0
+#define HOST1X_CLK_DIV_MASK (0xff << HOST1X_CLK_DIV_SHIFT)
+#define HOST1X_CLK_DIV_DEFAULT (3 << HOST1X_CLK_DIV_SHIFT)
+
+#define VCLK_SRC_SHIFT 30
+#define VCLK_SRC_MASK (0x3 << VCLK_SRC_SHIFT)
+#define VCLK_SRC_PLLM_OUT0 0
+#define VCLK_SRC_PLLC_OUT0 1
+#define VCLK_SRC_PLLP_OUT0 2
+#define VCLK_SRC_PLLA_OUT0 3
+#define VCLK_SRC_DEFAULT (VCLK_SRC_PLLM_OUT0 << VCLK_SRC_SHIFT)
+#define VCLK_IDLE_DIV_SHIFT 8
+#define VCLK_IDLE_DIV_MASK (0xff << VCLK_IDLE_DIV_SHIFT)
+#define VCLK_IDLE_DIV_DEFAULT (0 << VCLK_IDLE_DIV_SHIFT)
+#define VCLK_DIV_SHIFT 0
+#define VCLK_DIV_MASK (0xff << VCLK_DIV_SHIFT)
+#define VCLK_DIV_DEFAULT (0xa << VCLK_DIV_SHIFT)
+
+#define ISP_CLK_REG_OFFSET 0x144
+#define VI_CLK_REG_OFFSET 0x148
+#define VI_SENSOR_CLK_REG_OFFSET 0x1a8
+#define VI_SENSOR2_CLK_REG_OFFSET 0x658
+#define VI_CLK_DIV_DEFAULT (0x12 << VCLK_DIV_SHIFT)
+#define G3D_CLK_REG_OFFSET 0x158
+#define G2D_CLK_REG_OFFSET 0x15c
+#define EPP_CLK_REG_OFFSET 0x16c
+#define MPE_CLK_REG_OFFSET 0x170
+#define VDE_CLK_REG_OFFSET 0x170
+#define G3D2_CLK_REG_OFFSET 0x3b0
+#define HDMI_AUDIO_CLK_REG_OFFSET 0x668
+#define HDMI_AUDIO_CLK_DIV_DEFAULT (0x12 << VCLK_DIV_SHIFT)
+#define CSITE_CLK_REG_OFFSET 0x1d4
+#define CSITE_CLK_DIV_DEFAULT (0x4 << VCLK_DIV_SHIFT)
+
+static void __init clk_setbit(u32 reg, u32 bit)
+{
+ u32 val = clk_readl(reg);
+
+ if ((val & bit) == bit)
+ return;
+ val |= bit;
+ clk_writel(val, reg);
+ udelay(2);
+}
+
+static void __init clk_clrbit(u32 reg, u32 bit)
+{
+ u32 val = clk_readl(reg);
+
+ if ((val & bit) == 0)
+ return;
+ val &= ~bit;
+ clk_writel(val, reg);
+ udelay(2);
+}
+
+static void __init clk_setbits(u32 reg, u32 bits, u32 mask)
+{
+ u32 val = clk_readl(reg);
+
+ if ((val & mask) == bits)
+ return;
+ val &= ~mask;
+ val |= bits;
+ clk_writel(val, reg);
+ udelay(2);
+}
+
+static void __init vclk_init(int tag, u32 src, u32 rebit)
+{
+ u32 rst, enb;
+
+ switch (tag) {
+ case 'L':
+ rst = RST_DEVICES_L;
+ enb = CLK_OUT_ENB_L;
+ break;
+ case 'H':
+ rst = RST_DEVICES_H;
+ enb = CLK_OUT_ENB_H;
+ break;
+ case 'U':
+ rst = RST_DEVICES_U;
+ enb = CLK_OUT_ENB_U;
+ break;
+ case 'V':
+ rst = RST_DEVICES_V;
+ enb = CLK_OUT_ENB_V;
+ break;
+ case 'W':
+ rst = RST_DEVICES_W;
+ enb = CLK_OUT_ENB_W;
+ break;
+ case 'X':
+ rst = RST_DEVICES_X;
+ enb = CLK_OUT_ENB_X;
+ break;
+ default:
+ /* Quietly ignore. */
+ return;
+ }
+
+ clk_setbit(rst, rebit);
+ clk_clrbit(enb, rebit);
+
+ clk_setbits(src, VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(src, VCLK_DIV_DEFAULT, VCLK_DIV_MASK);
+
+ clk_clrbit(rst, rebit);
+}
+
+static int __init tegra_soc_preinit_clocks(void)
+{
+ /*
+ * Make sure host1x clock configuration has:
+ * HOST1X_CLK_SRC : PLLP_OUT0.
+ * HOST1X_CLK_DIVISOR: >2 to start from safe enough frequency.
+ */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_DEV_L_0_HOST1X_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_DEV_L_0_HOST1X_BIT);
+ clk_setbits(HOST1X_CLK_REG_OFFSET,
+ HOST1X_CLK_DIV_DEFAULT, HOST1X_CLK_DIV_MASK);
+ clk_setbits(HOST1X_CLK_REG_OFFSET,
+ HOST1X_CLK_IDLE_DIV_DEFAULT, HOST1X_CLK_IDLE_DIV_MASK);
+ clk_setbits(HOST1X_CLK_REG_OFFSET,
+ HOST1X_CLK_SRC_DEFAULT, HOST1X_CLK_SRC_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_DEV_L_0_HOST1X_BIT);
+
+ /*
+ * Make sure vi clock configuration has:
+ * VI_CLK_DIVISOR: 0x12
+ * VI_SENSOR_CLK_DIVISOR: 0x12
+ * VI_SENSOR2_CLK_DIVISOR: 0x12
+ */
+ clk_setbit(RST_DEVICES_L, CLK_RSTENB_DEV_L_0_VI_BIT);
+ clk_setbit(CLK_OUT_ENB_L, CLK_RSTENB_DEV_L_0_VI_BIT);
+ clk_setbits(VI_CLK_REG_OFFSET,
+ VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(VI_CLK_REG_OFFSET, VI_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_setbits(VI_SENSOR_CLK_REG_OFFSET, VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(VI_SENSOR_CLK_REG_OFFSET,
+ VI_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_setbits(VI_SENSOR2_CLK_REG_OFFSET, VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(VI_SENSOR2_CLK_REG_OFFSET,
+ VI_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_L, CLK_RSTENB_DEV_L_0_VI_BIT);
+
+ /*
+ * Make sure hdmi_audio clock configuration has:
+ * HDMI_AUDIO_CLK_DIVISOR: 0x12
+ */
+ clk_setbit(RST_DEVICES_X, CLK_RSTENB_DEV_X_0_HDMI_AUDIO_BIT);
+ clk_setbit(CLK_OUT_ENB_X, CLK_RSTENB_DEV_X_0_HDMI_AUDIO_BIT);
+ clk_setbits(HDMI_AUDIO_CLK_REG_OFFSET,
+ HDMI_AUDIO_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_X, CLK_RSTENB_DEV_X_0_HDMI_AUDIO_BIT);
+
+ /*
+ * Make sure csite clock configuration has:
+ * CSITE_CLK_DIVISOR: 0x4
+ */
+ clk_setbit(RST_DEVICES_U, CLK_RSTENB_DEV_U_0_CSITE_BIT);
+ clk_setbit(CLK_OUT_ENB_U, CLK_RSTENB_DEV_U_0_CSITE_BIT);
+ clk_setbits(CSITE_CLK_REG_OFFSET, CSITE_CLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_clrbit(RST_DEVICES_U, CLK_RSTENB_DEV_U_0_CSITE_BIT);
+
+ /* Pre-initialize Video clocks. */
+ vclk_init('L', G3D_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_3D_BIT);
+ vclk_init('L', G2D_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_2D_BIT);
+ vclk_init('L', ISP_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_ISP_BIT);
+ vclk_init('L', EPP_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_EPP_BIT);
+ vclk_init('H', VDE_CLK_REG_OFFSET, CLK_RSTENB_DEV_H_0_VDE_BIT);
+ vclk_init('H', MPE_CLK_REG_OFFSET, CLK_RSTENB_DEV_H_0_MPE_BIT);
+ vclk_init('V', G3D2_CLK_REG_OFFSET, CLK_RSTENB_DEV_V_0_3D2_BIT);
+
+ return 0;
+}
+#endif /* CONFIG_TEGRA_PREINIT_CLOCKS */
+
void __init tegra12x_init_clocks(void)
{
int i;
struct clk *c;
+
+#ifdef CONFIG_TEGRA_PREINIT_CLOCKS
+ tegra_soc_preinit_clocks();
+#endif /* CONFIG_TEGRA_PREINIT_CLOCKS */
+
for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
tegra12_init_one_clock(tegra_ptr_clks[i]);
diff --git a/arch/arm/mach-tegra/tegra12_dvfs.c b/arch/arm/mach-tegra/tegra12_dvfs.c
index 2a03b7165bc5..d2fbb8de3c52 100644
--- a/arch/arm/mach-tegra/tegra12_dvfs.c
+++ b/arch/arm/mach-tegra/tegra12_dvfs.c
@@ -141,8 +141,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 */
- 2014500, 2320500, 2116500, 2524500,
+/* speedo_id 0 1 2 3 4 5 */
+ 2014500, 2320500, 2116500, 2524500, 1500000, 2218500,
};
static struct cpu_cvb_dvfs cpu_cvb_dvfs_table[] = {
@@ -221,6 +221,19 @@ static const int core_millivolts[MAX_DVFS_FREQS] = {
.dvfs_rail = &tegra12_dvfs_rail_vdd_core, \
}
+#define OVRRD_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, \
+ .can_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, 1150 */
/* Clock limits for internal blocks, PLLs */
@@ -315,41 +328,19 @@ static struct dvfs core_dvfs_table[] = {
CORE_DVFS("hda", -1, -1, 1, KHZ, 1, 108000, 108000, 108000, 108000, 108000 , 108000, 108000),
CORE_DVFS("hda2codec_2x", -1, -1, 1, KHZ, 1, 48000, 48000, 48000, 48000, 48000 , 48000, 48000),
+
+ OVRRD_DVFS("sdmmc1", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 204000),
+ OVRRD_DVFS("sdmmc3", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 204000),
+ OVRRD_DVFS("sdmmc4", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 200000),
};
/*
- * Separate sdmmc and display dvfs table to handle dependency of sdmmc tuning
- * on display maximum rate.
- *
* Display peak voltage aggregation into override range floor is deferred until
* actual pixel clock for the particular platform is known. This would allow to
- * extend sdmmc tuning range on the platforms that do not excercise maximum
- * display clock capabilities specified in DVFS table.
+ * extend override range on the platforms that do not excercise maximum display
+ * clock capabilities specified in DVFS table.
*
- * Two SDMMC tables:
- * - "1-point tuning" table is applicable when override floor is equal to
- * nominal voltage (override range is zero). It is installed by default, while
- * display peak voltage is unknown. It is overwritten when display peak voltage
- * is aggregated, provided final override floor is below nominal.
- *
- * - "2-point tuning" table is applicable when override floor is below nominal
- * voltage (i.e., at least 2 tuning points in override range). It is installed
- * when display peak voltage is aggregated, provided final override floor is
- * below nominal.
*/
-#define OVRRD_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, \
- .can_override = true, \
- .dvfs_rail = &tegra12_dvfs_rail_vdd_core, \
- }
-
#define DEFER_DVFS(_clk_name, _speedo_id, _process_id, _auto, _mult, _freqs...) \
{ \
.clk_name = _clk_name, \
@@ -363,19 +354,6 @@ static struct dvfs core_dvfs_table[] = {
.dvfs_rail = &tegra12_dvfs_rail_vdd_core, \
}
- /* Core voltages (mV): 800, 850, 900, 950, 1000, 1050, 1100, 1150 */
-static struct dvfs sdmmc_dvfs_table[] = {
- OVRRD_DVFS("sdmmc1", -1, -1, 1, KHZ, 1, 1, 50000, 50000, 50000, 50000, 50000, 204000),
- OVRRD_DVFS("sdmmc3", -1, -1, 1, KHZ, 1, 1, 50000, 50000, 50000, 50000, 50000, 204000),
- OVRRD_DVFS("sdmmc4", -1, -1, 1, KHZ, 1, 1, 50000, 50000, 50000, 50000, 50000, 200000),
-};
-
-static struct dvfs sdmmc_tune2_dvfs_table[] = {
- OVRRD_DVFS("sdmmc1", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 204000),
- OVRRD_DVFS("sdmmc3", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 204000),
- OVRRD_DVFS("sdmmc4", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 200000),
-};
-
static struct dvfs disp_dvfs_table[] = {
/*
* The clock rate for the display controllers that determines the
@@ -407,22 +385,7 @@ static struct dvfs disp_alt_dvfs_table[] = {
static int resolve_core_override(int min_override_mv)
{
- int i, j;
- struct dvfs *d = sdmmc_dvfs_table;
- struct dvfs *d_tune = sdmmc_tune2_dvfs_table;
-
- BUILD_BUG_ON(ARRAY_SIZE(sdmmc_dvfs_table) !=
- ARRAY_SIZE(sdmmc_tune2_dvfs_table));
-
- if (min_override_mv >=
- tegra12_dvfs_rail_vdd_core.nominal_millivolts)
- return 0;
-
- /* Override range is not 0: 2+ points for SDMMC tuning are available */
- for (i = 0; i < ARRAY_SIZE(sdmmc_dvfs_table); i++, d++, d_tune++) {
- for (j = 0; j < d->num_freqs; j++)
- d->freqs[j] = d_tune->freqs[j] * d_tune->freqs_mult;
- }
+ /* nothing to do -- always resolved */
return 0;
}
@@ -1173,8 +1136,6 @@ void __init tegra12x_init_dvfs(void)
if (!tegra_platform_is_linsim()) {
INIT_CORE_DVFS_TABLE(core_dvfs_table,
ARRAY_SIZE(core_dvfs_table));
- INIT_CORE_DVFS_TABLE(sdmmc_dvfs_table,
- ARRAY_SIZE(sdmmc_dvfs_table));
INIT_CORE_DVFS_TABLE(disp_dvfs_table,
ARRAY_SIZE(disp_dvfs_table));
diff --git a/arch/arm/mach-tegra/tegra12_edp.c b/arch/arm/mach-tegra/tegra12_edp.c
index 91570e0102ed..10d6ec9e6484 100644
--- a/arch/arm/mach-tegra/tegra12_edp.c
+++ b/arch/arm/mach-tegra/tegra12_edp.c
@@ -272,6 +272,10 @@ static struct tegra_edp_cpu_leakage_params t12x_leakage_params[] = {
.cpu_speedo_id = 3, /* Prod SKU */
EDP_PARAMS_COMMON_PART,
},
+ {
+ .cpu_speedo_id = 5, /* Prod SKU */
+ EDP_PARAMS_COMMON_PART,
+ },
};
#ifdef CONFIG_TEGRA_GPU_EDP
diff --git a/arch/arm/mach-tegra/tegra12_speedo.c b/arch/arm/mach-tegra/tegra12_speedo.c
index 92244be7cf20..9ce142e5354a 100644
--- a/arch/arm/mach-tegra/tegra12_speedo.c
+++ b/arch/arm/mach-tegra/tegra12_speedo.c
@@ -106,7 +106,7 @@ static void rev_sku_to_speedo_ids(int rev, int sku)
case 0x1F:
case 0x87:
case 0x27:
- cpu_speedo_id = 2;
+ cpu_speedo_id = 5;
soc_speedo_id = 0;
gpu_speedo_id = 1;
threshold_index = 0;
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index a7272676b230..3a87379674d5 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -8,6 +8,7 @@
* (C) 2003 Jun Nakajima <jun.nakajima@intel.com>
* (C) 2009 Alexander Clouter <alex@digriz.org.uk>
* (c) 2012 Viresh Kumar <viresh.kumar@linaro.org>
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -364,6 +365,11 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
break;
case CPUFREQ_GOV_LIMITS:
+ mutex_lock(&dbs_data->mutex);
+ if (!cpu_cdbs->cur_policy) {
+ mutex_unlock(&dbs_data->mutex);
+ break;
+ }
mutex_lock(&cpu_cdbs->timer_mutex);
if (policy->max < cpu_cdbs->cur_policy->cur)
__cpufreq_driver_target(cpu_cdbs->cur_policy,
@@ -373,6 +379,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
policy->min, CPUFREQ_RELATION_L);
dbs_check_cpu(dbs_data, cpu);
mutex_unlock(&cpu_cdbs->timer_mutex);
+ mutex_unlock(&dbs_data->mutex);
break;
}
return 0;
diff --git a/drivers/misc/tegra-fuse/tegra_fuse.c b/drivers/misc/tegra-fuse/tegra_fuse.c
index 5ad209ecd5f6..e8c65f520ffa 100644
--- a/drivers/misc/tegra-fuse/tegra_fuse.c
+++ b/drivers/misc/tegra-fuse/tegra_fuse.c
@@ -322,6 +322,7 @@ static struct chip_revision tegra_chip_revisions[] = {
CHIP_REVISION(TEGRA11, 1, 2, 0, A02),
CHIP_REVISION(TEGRA14, 1, 1, 0, A01),
CHIP_REVISION(TEGRA14, 1, 2, 0, A02),
+ CHIP_REVISION(TEGRA12, 1, 1, 0, A01),
};
static enum tegra_revision tegra_decode_revision(const struct tegra_id *id)
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index fdda83afe1f6..abcc0e5f5020 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -146,6 +146,7 @@
#define NVQUIRK_HIGH_FREQ_TAP_PROCEDURE BIT(22)
/* Disable SDMMC3 external loopback */
#define NVQUIRK_DISABLE_EXTERNAL_LOOPBACK BIT(23)
+#define NVQUIRK_TMP_VAR_1_5_TAP_MARGIN BIT(24)
/* Common subset of quirks for Tegra3 and later sdmmc controllers */
#define TEGRA_SDHCI_NVQUIRKS (NVQUIRK_ENABLE_PADPIPE_CLKEN | \
@@ -196,7 +197,7 @@
#define TUNING_VOLTAGES_COUNT 3
#define TUNING_RETRIES 1
#define DFS_FREQ_COUNT 2
-
+#define NEG_MAR_CHK_WIN_COUNT 2
/* Tuning core voltage requirements */
#define NOMINAL_VCORE_TUN BIT(0)
#define BOOT_VCORE_TUN BIT(1)
@@ -221,7 +222,10 @@ struct sdhci_tegra_soc_data {
u32 nvquirks;
const char *parent_clk_list[2];
unsigned int tuning_freq_list[TUNING_FREQ_COUNT];
- unsigned int tuning_min_volt_list[TUNING_FREQ_COUNT];
+ u8 t2t_coeffs_count;
+ u8 tap_hole_coeffs_count;
+ struct tuning_t2t_coeffs *t2t_coeffs;
+ struct tap_hole_coeffs *tap_hole_coeffs;
};
@@ -231,18 +235,137 @@ enum tegra_regulator_config_ops {
CONFIG_REG_SET_VOLT,
};
-static unsigned int uhs_max_freq_MHz[] = {
- [MMC_TIMING_UHS_SDR50] = 100,
- [MMC_TIMING_UHS_SDR104] = 208,
- [MMC_TIMING_MMC_HS200] = 200,
-};
-
enum tegra_tuning_freq {
TUNING_LOW_FREQ,
TUNING_HIGH_FREQ,
TUNING_MAX_FREQ,
};
+struct tuning_t2t_coeffs {
+ const char *dev_id;
+ int vmax;
+ int vmin;
+ unsigned int t2t_vnom_slope;
+ unsigned int t2t_vnom_int;
+ unsigned int t2t_vmax_slope;
+ unsigned int t2t_vmax_int;
+ unsigned int t2t_vmin_slope;
+ unsigned int t2t_vmin_int;
+};
+
+#define SET_TUNING_COEFFS(_device_id, _vmax, _vmin, _t2t_vnom_slope, \
+ _t2t_vnom_int, _t2t_vmax_slope, _t2t_vmax_int, _t2t_vmin_slope, \
+ _t2t_vmin_int) \
+ { \
+ .dev_id = _device_id, \
+ .vmax = _vmax, \
+ .vmin = _vmin, \
+ .t2t_vnom_slope = _t2t_vnom_slope, \
+ .t2t_vnom_int = _t2t_vnom_int, \
+ .t2t_vmax_slope = _t2t_vmax_slope, \
+ .t2t_vmax_int = _t2t_vmax_int, \
+ .t2t_vmin_slope = _t2t_vmin_slope, \
+ .t2t_vmin_int = _t2t_vmin_int, \
+ }
+
+struct tuning_t2t_coeffs t11x_tuning_coeffs[] = {
+ SET_TUNING_COEFFS("sdhci-tegra.3", 1250, 950, 55, 135434,
+ 73, 170493, 243, 455948),
+ SET_TUNING_COEFFS("sdhci-tegra.2", 1250, 950, 50, 129738,
+ 73, 168898, 241, 453050),
+ SET_TUNING_COEFFS("sdhci-tegra.0", 1250, 950, 62, 143469,
+ 82, 180096, 238, 444285),
+};
+
+struct tuning_t2t_coeffs t12x_tuning_coeffs[] = {
+ SET_TUNING_COEFFS("sdhci-tegra.3", 1150, 950, 27, 118295,
+ 27, 118295, 48, 188148),
+ SET_TUNING_COEFFS("sdhci-tegra.2", 1150, 950, 29, 124427,
+ 29, 124427, 54, 203707),
+ SET_TUNING_COEFFS("sdhci-tegra.0", 1150, 950, 25, 115933,
+ 25, 115933, 47, 187224),
+};
+
+struct tap_hole_coeffs {
+ const char *dev_id;
+ unsigned int freq_khz;
+ unsigned int thole_vnom_slope;
+ unsigned int thole_vnom_int;
+ unsigned int thole_vmax_slope;
+ unsigned int thole_vmax_int;
+ unsigned int thole_vmin_slope;
+ unsigned int thole_vmin_int;
+};
+
+#define SET_TAP_HOLE_COEFFS(_device_id, _freq_khz, _thole_vnom_slope, \
+ _thole_vnom_int, _thole_vmax_slope, _thole_vmax_int, \
+ _thole_vmin_slope, _thole_vmin_int) \
+ { \
+ .dev_id = _device_id, \
+ .freq_khz = _freq_khz, \
+ .thole_vnom_slope = _thole_vnom_slope, \
+ .thole_vnom_int = _thole_vnom_int, \
+ .thole_vmax_slope = _thole_vmax_slope, \
+ .thole_vmax_int = _thole_vmax_int, \
+ .thole_vmin_slope = _thole_vmin_slope, \
+ .thole_vmin_int = _thole_vmin_int, \
+ }
+
+struct tap_hole_coeffs t11x_tap_hole_coeffs[] = {
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.3", 200000, 765, 102357, 507,
+ 81144, 131, 36346),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.3", 156000, 1042, 142044, 776,
+ 121659, 152, 48728),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.3", 136000, 1215, 167702, 905,
+ 143825, 207, 63477),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.3", 81600, 1925, 284516, 1528,
+ 253188, 366, 120001),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 204000, 472, 53312, 318,
+ 41756, 84, 15496),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 156000, 765, 95512, 526,
+ 77404, 134, 33032),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 136000, 949, 121887, 656,
+ 99684, 165, 43992),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 81600, 1901, 259035, 1334,
+ 215539, 326, 100986),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.0", 204000, 411, 54495, 305,
+ 46415, 91, 20366),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.0", 156000, 715, 97623, 516,
+ 82375, 145, 38278),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.0", 136000, 905, 124579, 648,
+ 104850, 179, 50204),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.0", 81600, 1893, 264746, 1333,
+ 221722, 354, 109880),
+};
+
+struct tap_hole_coeffs t12x_tap_hole_coeffs[] = {
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.3", 200000, 1037, 106934, 1037,
+ 106934, 558, 74315),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.3", 136000, 1703, 186307, 1703,
+ 186307, 890, 130617),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.3", 100000, 2452, 275601, 2452,
+ 275601, 1264, 193957),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.3", 81600, 3090, 351666, 3090,
+ 351666, 1583, 247913),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 204000, 468, 36031, 468,
+ 36031, 253, 21264),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 200000, 468, 36031, 468,
+ 36031, 253, 21264),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 136000, 1146, 117841, 1146,
+ 117841, 589, 78993),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 100000, 1879, 206195, 1879,
+ 206195, 953, 141341),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.2", 81600, 2504, 281460, 2504,
+ 281460, 1262, 194452),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.0", 204000, 874, 85243, 874,
+ 85243, 449, 57321),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.0", 136000, 1554, 167210, 1554,
+ 167210, 793, 115672),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.0", 100000, 2290, 255734, 2290,
+ 255734, 1164, 178691),
+ SET_TAP_HOLE_COEFFS("sdhci-tegra.0", 81600, 2916, 331143, 2916,
+ 331143, 1480, 232373),
+};
struct freq_tuning_constraints {
unsigned int vcore_mask;
@@ -253,35 +376,57 @@ static struct freq_tuning_constraints tuning_vcore_constraints[3] = {
.vcore_mask = BOOT_VCORE_TUN,
},
[1] = {
- .vcore_mask = BOOT_VCORE_TUN | MIN_OVERRIDE_VCORE_TUN |
- NOMINAL_VCORE_TUN,
+ .vcore_mask = BOOT_VCORE_TUN,
},
[2] = {
- .vcore_mask = BOOT_VCORE_TUN | NOMINAL_VCORE_TUN,
+ .vcore_mask = BOOT_VCORE_TUN,
},
};
+struct tuning_ui {
+ int ui;
+ bool is_valid_ui;
+};
+
+enum tap_win_edge_attr {
+ WIN_EDGE_BOUN_START,
+ WIN_EDGE_BOUN_END,
+ WIN_EDGE_HOLE,
+};
+
struct tap_window_data {
- bool abandon_partial_win;
- bool abandon_full_win;
- unsigned int voltage;
- u8 partial_win;
- u8 full_win_begin;
- u8 full_win_end;
- u8 vcore_set_status;
- u8 found_tuning_window;
- u8 tuning_done;
+ int win_start;
+ int win_end;
+ enum tap_win_edge_attr win_start_attr;
+ enum tap_win_edge_attr win_end_attr;
+ u8 win_size;
+ u8 hole_pos;
};
+struct tuning_values {
+ int t2t_vmax;
+ int t2t_vmin;
+ int ui;
+ int ui_vmin;
+ int vmax_thole;
+ int vmin_thole;
+};
struct tegra_tuning_data {
unsigned int freq_hz;
- unsigned int best_tap_value;
- unsigned int nom_best_tap_value;
+ int best_tap_value;
+ int nom_best_tap_value;
struct freq_tuning_constraints constraints;
- struct tap_window_data *tap_data[TUNING_VOLTAGES_COUNT];
+ struct tap_hole_coeffs *thole_coeffs;
+ struct tuning_t2t_coeffs *t2t_coeffs;
+ struct tuning_values est_values;
+ struct tuning_values calc_values;
+ struct tap_window_data *tap_data;
+ struct tap_window_data *final_tap_data;
+ u8 num_of_valid_tap_wins;
u8 nr_voltages;
u8 freq_band;
bool tuning_done;
+ bool is_partial_win_valid;
};
#ifdef CONFIG_MMC_FREQ_SCALING
@@ -372,7 +517,7 @@ struct sdhci_tegra {
/* Tuning packet size */
unsigned int tuning_bsize;
/* Num of tuning freqs selected */
- unsigned int tuning_freq_count;
+ int tuning_freq_count;
unsigned int tap_cmd;
/* Tuning status */
unsigned int tuning_status;
@@ -382,6 +527,7 @@ struct sdhci_tegra {
/* Freq tuning information for each sampling clock freq */
struct tegra_tuning_data tuning_data[DFS_FREQ_COUNT];
struct tegra_freq_gov_data *gov_data;
+ u32 speedo;
};
static struct clk *pll_c;
@@ -802,9 +948,11 @@ static int tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- /* Select Bus Speed Mode for host */
- /* For HS200 we need to set UHS_MODE_SEL to SDR104.
+ /* Select Bus Speed Mode for host
+ * For HS200 we need to set UHS_MODE_SEL to SDR104.
* It works as SDR 104 in SD 4-bit mode and HS200 in eMMC 8-bit mode.
+ * SDR50 mode timing seems to have issues. Programming SDR104
+ * mode for SDR50 mode for reliable transfers over interface.
*/
ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
switch (uhs) {
@@ -815,7 +963,7 @@ static int tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
break;
case MMC_TIMING_UHS_SDR50:
- ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
break;
case MMC_TIMING_UHS_SDR104:
case MMC_TIMING_MMC_HS200:
@@ -1016,8 +1164,17 @@ static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
/* External loopback is valid for sdmmc3 only */
if ((soc_data->nvquirks & NVQUIRK_DISABLE_EXTERNAL_LOOPBACK) &&
- (tegra_host->instance == 2))
- misc_ctrl &= ~(1 << SDHCI_VNDR_MISC_CTRL_EN_EXT_LOOPBACK_SHIFT);
+ (tegra_host->instance == 2)) {
+ if ((tegra_host->tuning_status == TUNING_STATUS_DONE)
+ && (host->mmc->pm_flags &
+ MMC_PM_KEEP_POWER)) {
+ misc_ctrl &= ~(1 <<
+ SDHCI_VNDR_MISC_CTRL_EN_EXT_LOOPBACK_SHIFT);
+ } else {
+ misc_ctrl |= (1 <<
+ SDHCI_VNDR_MISC_CTRL_EN_EXT_LOOPBACK_SHIFT);
+ }
+ }
sdhci_writel(host, misc_ctrl, SDHCI_VNDR_MISC_CTRL);
if (soc_data->nvquirks & NVQUIRK_DISABLE_AUTO_CMD23)
@@ -1144,13 +1301,12 @@ static void tegra_sdhci_clock_set_parent(struct sdhci_host *host,
if ((pll_c_freq > desired_rate) && (pll_p_freq > desired_rate)) {
if (pll_p_freq <= pll_c_freq) {
desired_rate = pll_p_freq;
- parent_clk = pll_p;
+ pll_c_freq = 0;
} else {
desired_rate = pll_c_freq;
- parent_clk = pll_c;
+ pll_p_freq = 0;
}
rc = clk_set_rate(pltfm_host->clk, desired_rate);
- goto set_clk_parent;
}
if (pll_c_freq > pll_p_freq) {
@@ -1166,7 +1322,6 @@ static void tegra_sdhci_clock_set_parent(struct sdhci_host *host,
} else
return;
-set_clk_parent:
rc = clk_set_parent(pltfm_host->clk, parent_clk);
if (rc)
pr_err("%s: failed to set pll parent clock %d\n",
@@ -1512,7 +1667,13 @@ static void sdhci_tegra_set_tap_delay(struct sdhci_host *sdhci,
u32 vendor_ctrl;
/* Max tap delay value is 255 */
- BUG_ON(tap_delay > MAX_TAP_VALUES);
+ if (tap_delay > MAX_TAP_VALUES) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "Valid tap range (0-255). Setting tap value %d\n",
+ tap_delay);
+ dump_stack();
+ return;
+ }
vendor_ctrl = sdhci_readl(sdhci, SDHCI_VNDR_CLK_CTRL);
vendor_ctrl &= ~(0xFF << SDHCI_VNDR_CLK_CTRL_TAP_VALUE_SHIFT);
@@ -1567,266 +1728,296 @@ out:
return tuning_data;
}
-static void sdhci_tegra_dump_tuning_data(struct sdhci_host *sdhci)
+static void calculate_vmin_values(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data, int vmin, int boot_mv)
{
- struct tegra_tuning_data *tuning_data;
- struct tap_window_data *tap_data;
- u8 i;
+ struct tuning_values *est_values = &tuning_data->est_values;
+ struct tuning_values *calc_values = &tuning_data->calc_values;
+ struct tuning_t2t_coeffs *t2t_coeffs = tuning_data->t2t_coeffs;
+ struct tap_hole_coeffs *thole_coeffs = tuning_data->thole_coeffs;
+ int vmin_slope, vmin_int, temp_calc_vmin;
+ int t2t_vmax, t2t_vmin;
+ int vmax_thole, vmin_thole;
- pr_info("********%s: Tuning window data********\n",
- mmc_hostname(sdhci->mmc));
- tuning_data = sdhci_tegra_get_tuning_data(sdhci, sdhci->max_clk);
- for (i = 0; i < tuning_data->nr_voltages; i++) {
- tap_data = tuning_data->tap_data[i];
- pr_info("%dHz: voltage %dmv:\n", sdhci->max_clk,
- tap_data->voltage);
- pr_info("Partial Win %d, Full win start %d, full win end %d\n",
- tap_data->partial_win,
- tap_data->full_win_begin,
- tap_data->full_win_end);
+ /*
+ * If current vmin is equal to vmin or vmax of tuning data, use the
+ * previously calculated estimated T2T values directly. Note that the
+ * estimated T2T_vmax is not at Vmax specified in tuning data. It is
+ * the T2T at the boot or max voltage for the current SKU. Hence,
+ * boot_mv is used in place of t2t_coeffs->vmax.
+ */
+ if (vmin == t2t_coeffs->vmin) {
+ t2t_vmin = est_values->t2t_vmin;
+ } else if (vmin == boot_mv) {
+ t2t_vmin = est_values->t2t_vmax;
+ } else {
+ /*
+ * For any intermediate voltage between boot voltage and vmin
+ * of tuning data, calculate the slope and intercept from the
+ * t2t at boot_mv and vmin and calculate the actual values.
+ */
+ t2t_vmax = 1000 / est_values->t2t_vmax;
+ t2t_vmin = 1000 / est_values->t2t_vmin;
+ vmin_slope = ((t2t_vmax - t2t_vmin) * 1000) /
+ (boot_mv - t2t_coeffs->vmin);
+ vmin_int = (t2t_vmax * 1000 - (vmin_slope * boot_mv)) / 1000;
+ t2t_vmin = (vmin_slope * vmin) / 1000 + vmin_int;
+ t2t_vmin = (1000 / t2t_vmin);
}
- pr_info("Best tap value %d, best nom voltage tap value %d\n",
- tuning_data->best_tap_value,
- tuning_data->nom_best_tap_value);
- pr_info("*****************************\n");
+
+ calc_values->t2t_vmin = (t2t_vmin * calc_values->t2t_vmax) /
+ est_values->t2t_vmax;
+
+ calc_values->ui_vmin = (1000000 / (tuning_data->freq_hz / 1000000)) /
+ calc_values->t2t_vmin;
+
+ /* Calculate the vmin tap hole at vmin of tuning data */
+ temp_calc_vmin = (est_values->t2t_vmin * calc_values->t2t_vmax) /
+ est_values->t2t_vmax;
+ vmin_thole = (thole_coeffs->thole_vmin_int -
+ (thole_coeffs->thole_vmin_slope * temp_calc_vmin)) /
+ 1000;
+ vmax_thole = calc_values->vmax_thole;
+
+ if (vmin == t2t_coeffs->vmin) {
+ calc_values->vmin_thole = vmin_thole;
+ } else if (vmin == boot_mv) {
+ calc_values->vmin_thole = vmax_thole;
+ } else {
+ /*
+ * Interpolate the tap hole for any intermediate voltage.
+ * Calculate the slope and intercept from the available data
+ * and use them to calculate the actual values.
+ */
+ vmin_slope = ((vmax_thole - vmin_thole) * 1000) /
+ (boot_mv - t2t_coeffs->vmin);
+ vmin_int = (vmax_thole * 1000 - (vmin_slope * boot_mv)) / 1000;
+ calc_values->vmin_thole = (vmin_slope * vmin) / 1000 + vmin_int;
+ }
+
+ /* Adjust the partial win start for Vmin boundary */
+ if (tuning_data->is_partial_win_valid)
+ tuning_data->final_tap_data[0].win_start =
+ (tuning_data->final_tap_data[0].win_start *
+ tuning_data->calc_values.t2t_vmax) /
+ tuning_data->calc_values.t2t_vmin;
+
+ pr_info("**********Tuning values*********\n");
+ pr_info("**estimated values**\n");
+ pr_info("T2T_Vmax %d, T2T_Vmin %d, 1'st_hole_Vmax %d, UI_Vmax %d\n",
+ est_values->t2t_vmax, est_values->t2t_vmin,
+ est_values->vmax_thole, est_values->ui);
+ pr_info("**Calculated values**\n");
+ pr_info("T2T_Vmax %d, 1'st_hole_Vmax %d, UI_Vmax %d\n",
+ calc_values->t2t_vmax, calc_values->vmax_thole,
+ calc_values->ui);
+ pr_info("T2T_Vmin %d, 1'st_hole_Vmin %d, UI_Vmin %d\n",
+ calc_values->t2t_vmin, calc_values->vmin_thole,
+ calc_values->ui_vmin);
+ pr_info("***********************************\n");
}
-/*
- * Calculation of best tap value for low frequencies(82MHz).
- * X = Partial win, Y = Full win start, Z = Full win end.
- * UI = Z - X.
- * Full Window = Z - Y.
- * Taps margin = mid-point of 1/2*(curr_freq/max_frequency)*UI
- * = (1/2)*(1/2)*(82/200)*UI
- * = (0.1025)*UI
- * if Partial win<(0.22)*UI
- * best tap = Y+(0.1025*UI)
- * else
- * best tap = (X-(Z-Y))+(0.1025*UI)
- * If best tap<0, best tap = 0
- */
-static unsigned int calculate_low_freq_tap_value(struct sdhci_host *sdhci,
- struct tap_window_data *tap_data)
+static int slide_window_start(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data,
+ int tap_value, enum tap_win_edge_attr edge_attr, int tap_hole)
{
- unsigned int curr_clock;
- unsigned int max_clock;
- int best_tap_value;
- unsigned int tuning_ui;
- unsigned int sampling_point = 0;
- bool select_partial_win = false;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+ struct sdhci_tegra *tegra_host = pltfm_host->priv;
+ const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
- tuning_ui = tap_data->full_win_end - tap_data->partial_win;
+ if (edge_attr == WIN_EDGE_BOUN_START) {
+ if (tap_value < 0)
+ tap_value += (1000 / tuning_data->calc_values.t2t_vmin);
+ else
+ tap_value += (1000 / tuning_data->calc_values.t2t_vmax);
+ } else if (edge_attr == WIN_EDGE_HOLE) {
+ if (soc_data->nvquirks & NVQUIRK_TMP_VAR_1_5_TAP_MARGIN)
+ tap_value += ((7 * tap_hole) / 100) + 2;
+ else
+ tap_value += ((7 * tap_hole) / 100) +
+ (((2 * (450 / tuning_data->calc_values.t2t_vmax))
+ + 1) / 2);
+ }
- /* Calculate the sampling point */
- curr_clock = sdhci->max_clk / 1000000;
- max_clock = uhs_max_freq_MHz[sdhci->mmc->ios.timing];
- sampling_point = ((tuning_ui * curr_clock) / (max_clock << 2));
+ if (tap_value > MAX_TAP_VALUES)
+ tap_value = MAX_TAP_VALUES;
- /*
- * Check whether partial window should be used. Use partial window
- * if partial window > 0.22(UI).
- */
- if ((!tap_data->abandon_partial_win) &&
- (tap_data->partial_win > ((22 * tuning_ui) / 100)))
- select_partial_win = true;
-
- if (select_partial_win)
- best_tap_value = (tap_data->partial_win -
- (tap_data->full_win_end - tap_data->full_win_begin)) +
- sampling_point;
- else
- best_tap_value = tap_data->full_win_begin +
- sampling_point;
+ return tap_value;
+}
+
+static int slide_window_end(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data,
+ int tap_value, enum tap_win_edge_attr edge_attr, int tap_hole)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+ struct sdhci_tegra *tegra_host = pltfm_host->priv;
+ const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
- if (best_tap_value < 0)
- best_tap_value = 0;
+ if (edge_attr == WIN_EDGE_BOUN_END) {
+ tap_value = (tap_value * tuning_data->calc_values.t2t_vmax) /
+ tuning_data->calc_values.t2t_vmin;
+ tap_value -= (1000 / tuning_data->calc_values.t2t_vmin);
+ } else if (edge_attr == WIN_EDGE_HOLE) {
+ if (tap_hole > 0)
+ tap_value = tap_hole;
+ if (soc_data->nvquirks & NVQUIRK_TMP_VAR_1_5_TAP_MARGIN)
+ tap_value -= ((7 * tap_hole) / 100) + 2;
+ else
+ tap_value -= ((7 * tap_hole) / 100) +
+ (((2 * (450 / tuning_data->calc_values.t2t_vmin))
+ + 1) / 2);
+ }
- return best_tap_value;
+ return tap_value;
}
-/*
- * Calculation of best tap value for high frequencies(156MHz).
- * Tap window data at 1.25V core voltage
- * X = Partial win, Y = Full win start, Z = Full win end.
- * Full Window = Z-Y.
- * UI = Z-X.
- * Tap_margin = (0.20375)UI
- *
- * Tap window data at 1.1V core voltage
- * X' = Partial win, Y' = Full win start, Z' = Full win end.
- * UI' = Z'-X'.
- * Full Window' = Z'-Y'.
- * Tap_margin' = (0.20375)UI'
- *
- * Full_window_tap=[(Z'-0.20375UI')+(Y+0.20375UI)]/2
- * Partial_window_tap=[(X'-0.20375UI')+(X-(Z-Y)+0x20375UI)]/2
- * if(Partial_window_tap < 0), Partial_window_tap=0
- *
- * Full_window_quality=[(Z'-0.20375UI')-(Y+0.20375UI)]/2
- * Partial_window_quality=(X'-0.20375UI')-Partial_window_tap
- * if(Full_window_quality>Partial_window_quality) choose full window,
- * else choose partial window.
- * If there is no margin window for both cases,
- * best tap=(Y+Z')/2.
- */
-static unsigned int calculate_high_freq_tap_value(struct sdhci_host *sdhci,
- struct tap_window_data *vmax_tap_data,
- struct tap_window_data *vmid_tap_data)
-{
- unsigned int curr_clock;
- unsigned int max_clock;
- unsigned int vmax_tuning_ui;
- unsigned int vmax_sampling_point;
- unsigned int vmid_tuning_ui;
- unsigned int vmid_sampling_point;
- unsigned int full_win_tap;
- int partial_win_start;
- int partial_win_tap;
- int full_win_quality;
- int partial_win_quality;
- int best_tap_value;
+static int adjust_window_boundaries(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data,
+ struct tap_window_data *temp_tap_data)
+{
+ struct tap_window_data *tap_data;
+ int vmin_tap_hole;
+ int vmax_tap_hole;
+ u8 i = 0;
- curr_clock = sdhci->max_clk / 1000000;
- max_clock = uhs_max_freq_MHz[sdhci->mmc->ios.timing];
+ for (i = 0; i < tuning_data->num_of_valid_tap_wins; i++) {
+ tap_data = &temp_tap_data[i];
+ /* Update with next hole if first hole is taken care of */
+ if (tap_data->win_start_attr == WIN_EDGE_HOLE)
+ vmax_tap_hole = tuning_data->calc_values.vmax_thole +
+ (tap_data->hole_pos - 1) *
+ tuning_data->calc_values.ui;
+ tap_data->win_start = slide_window_start(sdhci, tuning_data,
+ tap_data->win_start, tap_data->win_start_attr,
+ vmax_tap_hole);
+
+ /* Update with next hole if first hole is taken care of */
+ if (tap_data->win_end_attr == WIN_EDGE_HOLE)
+ vmin_tap_hole = tuning_data->calc_values.vmin_thole +
+ (tap_data->hole_pos - 1) *
+ tuning_data->calc_values.ui_vmin;
+ tap_data->win_end = slide_window_end(sdhci, tuning_data,
+ tap_data->win_end, tap_data->win_end_attr,
+ vmin_tap_hole);
+ }
- /*
- * Calculate the tuning_ui and sampling points for tap windows found
- * at all core voltages.
- */
- vmax_tuning_ui = vmax_tap_data->full_win_end -
- vmax_tap_data->partial_win;
- vmax_sampling_point = (vmax_tuning_ui * curr_clock) / (max_clock << 2);
-
- vmid_tuning_ui = vmid_tap_data->full_win_end -
- vmid_tap_data->partial_win;
- vmid_sampling_point = (vmid_tuning_ui * curr_clock) / (max_clock << 2);
-
- full_win_tap = ((vmid_tap_data->full_win_end - vmid_sampling_point) +
- (vmax_tap_data->full_win_begin + vmax_sampling_point));
- full_win_tap >>= 1;
- full_win_quality = (vmid_tap_data->full_win_end -
- vmid_sampling_point) - (vmax_tap_data->full_win_begin +
- vmax_sampling_point);
- full_win_quality >>= 1;
-
- partial_win_start = (vmax_tap_data->partial_win -
- (vmax_tap_data->full_win_end -
- vmax_tap_data->full_win_begin));
- partial_win_tap = ((vmid_tap_data->partial_win - vmid_sampling_point) +
- (partial_win_start + vmax_sampling_point));
- partial_win_tap >>= 1;
-
- if (partial_win_tap < 0)
- partial_win_tap = 0;
- partial_win_quality = (vmid_tap_data->partial_win -
- vmid_sampling_point) - partial_win_tap;
-
- if ((full_win_quality <= 0) && (partial_win_quality <= 0)) {
- dev_warn(mmc_dev(sdhci->mmc),
- "No margin window for both windows\n");
- best_tap_value = vmax_tap_data->full_win_begin +
- vmid_tap_data->full_win_end;
- best_tap_value >>= 1;
+ pr_info("***********final tuning windows**********\n");
+ for (i = 0; i < tuning_data->num_of_valid_tap_wins; i++) {
+ tap_data = &temp_tap_data[i];
+ pr_info("win[%d]: %d - %d\n", i, tap_data->win_start,
+ tap_data->win_end);
+ }
+ pr_info("********************************\n");
+ return 0;
+}
+
+static int find_best_tap_value(struct tegra_tuning_data *tuning_data,
+ struct tap_window_data *temp_tap_data, int vmin)
+{
+ struct tap_window_data *tap_data;
+ u8 i = 0, sel_win = 0;
+ int pref_win = 0, curr_win_size = 0;
+ int best_tap_value = 0;
+
+ for (i = 0; i < tuning_data->num_of_valid_tap_wins; i++) {
+ tap_data = &temp_tap_data[i];
+ if (!i && tuning_data->is_partial_win_valid) {
+ pref_win = tap_data->win_end - tap_data->win_start;
+ if ((tap_data->win_end * 2) < pref_win)
+ pref_win = tap_data->win_end * 2;
+ sel_win = 0;
+ } else {
+ curr_win_size = tap_data->win_end - tap_data->win_start;
+ if ((curr_win_size > 0) && (curr_win_size > pref_win)) {
+ pref_win = curr_win_size;
+ sel_win = i;
+ }
+ }
+ }
+
+ if (pref_win <= 0) {
+ pr_err("No window opening for %d vmin\n", vmin);
+ return -1;
+ }
+
+ tap_data = &temp_tap_data[sel_win];
+ if (!sel_win && tuning_data->is_partial_win_valid) {
+ i = sel_win;
+ best_tap_value = tap_data->win_end - (pref_win / 2);
+ if (best_tap_value < 0)
+ best_tap_value = 0;
} else {
- if (full_win_quality > partial_win_quality)
- best_tap_value = full_win_tap;
- else
- best_tap_value = partial_win_tap;
+ best_tap_value = tap_data->win_start +
+ ((tap_data->win_end - tap_data->win_start) *
+ tuning_data->calc_values.t2t_vmin) /
+ (tuning_data->calc_values.t2t_vmin +
+ tuning_data->calc_values.t2t_vmax);
}
- if (best_tap_value < 0)
- best_tap_value = 0;
+ pr_info("best tap win - (%d-%d), best tap value %d\n",
+ tap_data->win_start, tap_data->win_end, best_tap_value);
return best_tap_value;
}
-static void sdhci_tegra_calculate_best_tap(struct sdhci_host *sdhci,
- u8 freq_band)
+static int sdhci_tegra_calculate_best_tap(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
- struct tegra_tuning_data *tuning_data;
- unsigned int vdd_core;
- int delta_vdd;
- unsigned int voltage = 0;
+ struct tap_window_data *temp_tap_data = NULL;
+ int vmin, curr_vmin, best_tap_value = 0;
+ int err = 0;
- SDHCI_TEGRA_DBG("%s: calculating best tap for freq band %d\n",
- mmc_hostname(sdhci->mmc), freq_band);
- SDHCI_TEGRA_DBG("%s: Best tap %s nom best tap\n",
- mmc_hostname(sdhci->mmc),
- (tegra_host->plat->en_nominal_vcore_tuning) ? "different from" :
- "same as");
+ curr_vmin = tegra_dvfs_predict_millivolts(pltfm_host->clk,
+ tuning_data->freq_hz);
+ vmin = curr_vmin;
- tuning_data = sdhci_tegra_get_tuning_data(sdhci, sdhci->max_clk);
+ do {
+ SDHCI_TEGRA_DBG("%s: checking for win opening with vmin %d\n",
+ mmc_hostname(sdhci->mmc), vmin);
+ if ((best_tap_value < 0) &&
+ (vmin > tegra_host->boot_vcore_mv)) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "No best tap for any vcore range\n");
+ return -EINVAL;
+ }
- if (tuning_data->tap_data[0] && tuning_data->tap_data[1] &&
- (tegra_host->soc_data->nvquirks &
- NVQUIRK_HIGH_FREQ_TAP_PROCEDURE)) {
- voltage = tuning_data->tap_data[0]->voltage -
- tuning_data->tap_data[1]->voltage;
-
- if (voltage > 0 && (freq_band == TUNING_LOW_FREQ ||
- freq_band == TUNING_HIGH_FREQ)) {
- vdd_core =
- tegra_host->soc_data->tuning_min_volt_list[freq_band];
- delta_vdd = tuning_data->tap_data[1]->voltage -
- vdd_core;
- tuning_data->tap_data[1]->partial_win =
- ((tuning_data->tap_data[0]->partial_win -
- tuning_data->tap_data[1]->partial_win) *
- delta_vdd) / voltage +
- tuning_data->tap_data[1]->partial_win;
- tuning_data->tap_data[1]->full_win_begin =
- ((tuning_data->tap_data[0]->full_win_begin -
- tuning_data->tap_data[1]->full_win_begin) *
- delta_vdd) / voltage +
- tuning_data->tap_data[1]->full_win_begin;
- tuning_data->tap_data[1]->full_win_end =
- -((tuning_data->tap_data[0]->full_win_end -
- tuning_data->tap_data[1]->full_win_end) *
- (delta_vdd / voltage)) +
- tuning_data->tap_data[1]->full_win_end;
- }
- }
-
- if (freq_band == TUNING_LOW_FREQ) {
- if (tegra_host->soc_data->nvquirks &
- NVQUIRK_HIGH_FREQ_TAP_PROCEDURE)
- tuning_data->nom_best_tap_value =
- calculate_high_freq_tap_value(sdhci,
- tuning_data->tap_data[0],
- tuning_data->tap_data[1]);
- else
- tuning_data->nom_best_tap_value =
- calculate_low_freq_tap_value(sdhci,
- tuning_data->tap_data[0]);
- tuning_data->best_tap_value = tuning_data->nom_best_tap_value;
- } else if (freq_band == TUNING_HIGH_FREQ) {
- tuning_data->nom_best_tap_value =
- calculate_high_freq_tap_value(sdhci,
- tuning_data->tap_data[0], tuning_data->tap_data[1]);
- if (!tegra_host->plat->en_nominal_vcore_tuning) {
- tuning_data->best_tap_value =
- tuning_data->nom_best_tap_value;
- } else {
- tuning_data->best_tap_value =
- calculate_high_freq_tap_value(sdhci,
- tuning_data->tap_data[1],
- tuning_data->tap_data[2]);
- }
- } else if (freq_band == TUNING_MAX_FREQ) {
- tuning_data->nom_best_tap_value = calculate_high_freq_tap_value(
- sdhci, tuning_data->tap_data[0],
- tuning_data->tap_data[0]);
- if (!tegra_host->plat->en_nominal_vcore_tuning) {
- tuning_data->best_tap_value =
- tuning_data->nom_best_tap_value;
- } else {
- tuning_data->best_tap_value =
- calculate_high_freq_tap_value(sdhci,
- tuning_data->tap_data[1],
- tuning_data->tap_data[1]);
+ calculate_vmin_values(sdhci, tuning_data, vmin,
+ tegra_host->boot_vcore_mv);
+
+ if (temp_tap_data == NULL) {
+ temp_tap_data = kzalloc(sizeof(struct tap_window_data) *
+ tuning_data->num_of_valid_tap_wins, GFP_KERNEL);
+ if (IS_ERR_OR_NULL(temp_tap_data)) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "No memory for final tap value calculation\n");
+ return -ENOMEM;
+ }
}
- }
+
+ memcpy(temp_tap_data, tuning_data->final_tap_data,
+ sizeof(struct tap_window_data) *
+ tuning_data->num_of_valid_tap_wins);
+
+ adjust_window_boundaries(sdhci, tuning_data, temp_tap_data);
+
+ best_tap_value = find_best_tap_value(tuning_data,
+ temp_tap_data, vmin);
+
+ if (best_tap_value < 0)
+ vmin += 50;
+ } while (best_tap_value < 0);
+
+ tuning_data->best_tap_value = best_tap_value;
+ tuning_data->nom_best_tap_value = best_tap_value;
+
+ /* Set the new vmin if there is any change. */
+ if ((tuning_data->best_tap_value >= 0) && (curr_vmin != vmin))
+ err = tegra_dvfs_set_fmax_at_vmin(pltfm_host->clk,
+ tuning_data->freq_hz, vmin);
+
+ kfree(temp_tap_data);
+ return err;
}
static int sdhci_tegra_issue_tuning_cmd(struct sdhci_host *sdhci)
@@ -1946,89 +2137,545 @@ static int sdhci_tegra_scan_tap_values(struct sdhci_host *sdhci,
return tap_value;
}
-/*
- * While scanning for tap values, first get the partial window followed by the
- * full window. Note that, when scanning for full win start, tuning has to be
- * run until a passing tap value is found. Hence, failure is expected during
- * this process and ignored.
- */
-static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci,
- struct tap_window_data *tap_data)
+static int calculate_actual_tuning_values(int speedo,
+ struct tegra_tuning_data *tuning_data, int voltage_mv)
{
- unsigned int tap_value;
- unsigned int full_win_percentage = 0;
- int err = 0;
+ struct tuning_t2t_coeffs *t2t_coeffs = tuning_data->t2t_coeffs;
+ struct tap_hole_coeffs *thole_coeffs = tuning_data->thole_coeffs;
+ struct tuning_values *calc_values = &tuning_data->calc_values;
+ int slope, inpt;
+ int vmax_thole, vmin_thole;
+
+ /* T2T_Vmax = (1000000/freq_MHz)/Calc_UI */
+ calc_values->t2t_vmax = (1000000 / (tuning_data->freq_hz / 1000000)) /
+ calc_values->ui;
- if (!tap_data) {
- dev_err(mmc_dev(sdhci->mmc), "Invalid tap data\n");
- return -ENODATA;
+ /*
+ * Interpolate the tap hole.
+ * Vmax_1'st_hole = (Calc_T2T_Vmax*(-thole_slope)+thole_tint.
+ */
+ vmax_thole = (thole_coeffs->thole_vmax_int -
+ (thole_coeffs->thole_vmax_slope * calc_values->t2t_vmax)) /
+ 1000;
+ vmin_thole = (thole_coeffs->thole_vmin_int -
+ (thole_coeffs->thole_vmin_slope * calc_values->t2t_vmax)) /
+ 1000;
+ if (voltage_mv == t2t_coeffs->vmin) {
+ calc_values->vmax_thole = vmin_thole;
+ } else if (voltage_mv == t2t_coeffs->vmax) {
+ calc_values->vmax_thole = vmax_thole;
+ } else {
+ slope = (vmax_thole - vmin_thole) /
+ (t2t_coeffs->vmax - t2t_coeffs->vmin);
+ inpt = ((vmax_thole * 1000) - (slope * 1250)) / 1000;
+ calc_values->vmax_thole = slope * voltage_mv + inpt;
}
- /* Get the partial window data */
- tap_value = 0;
- tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, false);
- if (!tap_value) {
- tap_data->abandon_partial_win = true;
- tap_data->partial_win = 0;
- } else if (tap_value > MAX_TAP_VALUES) {
+ return 0;
+}
+
+/*
+ * All coeffs are filled up in the table after multiplying by 1000. So, all
+ * calculations should have a divide by 1000 at the end.
+ */
+static int calculate_estimated_tuning_values(int speedo,
+ struct tegra_tuning_data *tuning_data, int voltage_mv)
+{
+ struct tuning_t2t_coeffs *t2t_coeffs = tuning_data->t2t_coeffs;
+ struct tap_hole_coeffs *thole_coeffs = tuning_data->thole_coeffs;
+ struct tuning_values *est_values = &tuning_data->est_values;
+ int slope, inpt;
+ int vmax_t2t, vmin_t2t;
+ int vmax_thole, vmin_thole;
+
+ /* Est_T2T_Vmax = (speedo*(-t2t_slope)+t2t_int */
+ vmax_t2t = (t2t_coeffs->t2t_vmax_int - (speedo *
+ t2t_coeffs->t2t_vmax_slope)) / 1000;
+ vmin_t2t = (t2t_coeffs->t2t_vmin_int - (speedo *
+ t2t_coeffs->t2t_vmin_slope)) / 1000;
+ est_values->t2t_vmin = vmin_t2t;
+
+ if (voltage_mv == t2t_coeffs->vmin) {
+ est_values->t2t_vmax = vmin_t2t;
+ } else if (voltage_mv == t2t_coeffs->vmax) {
+ est_values->t2t_vmax = vmax_t2t;
+ } else {
+ vmax_t2t = 1000 / vmax_t2t;
+ vmin_t2t = 1000 / vmin_t2t;
/*
- * If tap value is more than 0xFF, we have hit the miracle case
- * of all tap values passing. Discard full window as passing
- * window has covered all taps.
+ * For any intermediate voltage between 0.95V and 1.25V,
+ * calculate the slope and intercept from the T2T and tap hole
+ * values of 0.95V and 1.25V and use them to calculate the
+ * actual values. 1/T2T is a linear function of voltage.
*/
- tap_data->partial_win = MAX_TAP_VALUES;
- tap_data->abandon_full_win = true;
- goto out;
+ slope = ((vmax_t2t - vmin_t2t) * 1000) /
+ (t2t_coeffs->vmax - t2t_coeffs->vmin);
+ inpt = (vmax_t2t * 1000 - (slope * t2t_coeffs->vmax)) / 1000;
+ est_values->t2t_vmax = (slope * voltage_mv) / 1000 + inpt;
+ est_values->t2t_vmax = (1000 / est_values->t2t_vmax);
+ }
+
+ /* Est_UI = (1000000/freq_MHz)/Est_T2T_Vmax */
+ est_values->ui = (1000000 / (thole_coeffs->freq_khz / 1000)) /
+ est_values->t2t_vmax;
+
+ /*
+ * Est_1'st_hole = (Est_T2T_Vmax*(-thole_slope)) + thole_int.
+ */
+ vmax_thole = (thole_coeffs->thole_vmax_int -
+ (thole_coeffs->thole_vmax_slope * est_values->t2t_vmax)) / 1000;
+ vmin_thole = (thole_coeffs->thole_vmin_int -
+ (thole_coeffs->thole_vmin_slope * est_values->t2t_vmax)) / 1000;
+
+ if (voltage_mv == t2t_coeffs->vmin) {
+ est_values->vmax_thole = vmin_thole;
+ } else if (voltage_mv == t2t_coeffs->vmax) {
+ est_values->vmax_thole = vmax_thole;
} else {
- tap_data->partial_win = tap_value - 1;
- if (tap_value == MAX_TAP_VALUES) {
- /* All tap values exhausted. No full window */
- tap_data->abandon_full_win = true;
- goto out;
+ /*
+ * For any intermediate voltage between 0.95V and 1.25V,
+ * calculate the slope and intercept from the t2t and tap hole
+ * values of 0.95V and 1.25V and use them to calculate the
+ * actual values. Tap hole is a linear function of voltage.
+ */
+ slope = ((vmax_thole - vmin_thole) * 1000) /
+ (t2t_coeffs->vmax - t2t_coeffs->vmin);
+ inpt = (vmax_thole * 1000 - (slope * t2t_coeffs->vmax)) / 1000;
+ est_values->vmax_thole = (slope * voltage_mv) / 1000 + inpt;
+ }
+ est_values->vmin_thole = vmin_thole;
+
+ return 0;
+}
+
+/*
+ * Insert the calculated holes and get the final tap windows
+ * with the boundaries and holes set.
+ */
+static int adjust_holes_in_tap_windows(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data)
+{
+ struct tap_window_data *tap_data;
+ struct tap_window_data *final_tap_data;
+ struct tuning_values *calc_values = &tuning_data->calc_values;
+ int tap_hole, size = 0;
+ u8 i = 0, j = 0, num_of_wins, hole_pos = 0;
+
+ tuning_data->final_tap_data =
+ devm_kzalloc(mmc_dev(sdhci->mmc),
+ sizeof(struct tap_window_data) * 42, GFP_KERNEL);
+ if (IS_ERR_OR_NULL(tuning_data->final_tap_data)) {
+ dev_err(mmc_dev(sdhci->mmc), "No mem for final tap wins\n");
+ return -ENOMEM;
+ }
+
+ num_of_wins = tuning_data->num_of_valid_tap_wins;
+ tap_hole = calc_values->vmax_thole;
+ hole_pos++;
+ do {
+ tap_data = &tuning_data->tap_data[i];
+ final_tap_data = &tuning_data->final_tap_data[j];
+ if (tap_hole < tap_data->win_start) {
+ tap_hole += calc_values->ui;
+ hole_pos++;
+ continue;
+ } else if (tap_hole > tap_data->win_end) {
+ memcpy(final_tap_data, tap_data,
+ sizeof(struct tap_window_data));
+ i++;
+ j++;
+ num_of_wins--;
+ continue;
+ } else if ((tap_hole >= tap_data->win_start) &&
+ (tap_hole <= tap_data->win_end)) {
+ size = tap_data->win_end - tap_data->win_start;
+ do {
+ final_tap_data =
+ &tuning_data->final_tap_data[j];
+ if (tap_hole == tap_data->win_start) {
+ final_tap_data->win_start =
+ tap_hole + 1;
+ final_tap_data->win_start_attr =
+ WIN_EDGE_HOLE;
+ final_tap_data->hole_pos = hole_pos;
+ tap_hole += calc_values->ui;
+ hole_pos++;
+ } else {
+ final_tap_data->win_start =
+ tap_data->win_start;
+ final_tap_data->win_start_attr =
+ WIN_EDGE_BOUN_START;
+ }
+ if (tap_hole <= tap_data->win_end) {
+ final_tap_data->win_end = tap_hole - 1;
+ final_tap_data->win_end_attr =
+ WIN_EDGE_HOLE;
+ final_tap_data->hole_pos = hole_pos;
+ tap_data->win_start = tap_hole;
+ } else if (tap_hole > tap_data->win_end) {
+ final_tap_data->win_end =
+ tap_data->win_end;
+ final_tap_data->win_end_attr =
+ WIN_EDGE_BOUN_END;
+ tap_data->win_start =
+ tap_data->win_end;
+ }
+ size = tap_data->win_end - tap_data->win_start;
+ j++;
+ } while (size > 0);
+ i++;
+ num_of_wins--;
}
+ } while (num_of_wins > 0);
+
+ /* Update the num of valid wins count after tap holes insertion */
+ tuning_data->num_of_valid_tap_wins = j;
+
+ pr_info("********tuning windows after inserting holes*****\n");
+ pr_info("WIN_ATTR legend: 0-BOUN_ST, 1-BOUN_END, 2-HOLE\n");
+ for (i = 0; i < tuning_data->num_of_valid_tap_wins; i++) {
+ final_tap_data = &tuning_data->final_tap_data[i];
+ pr_info("win[%d]:%d(%d) - %d(%d)\n", i,
+ final_tap_data->win_start,
+ final_tap_data->win_start_attr,
+ final_tap_data->win_end, final_tap_data->win_end_attr);
}
+ pr_info("***********************************************\n");
+ return 0;
+}
+
+/*
+ * Insert the boundaries from negative margin calculations into the windows
+ * from auto tuning.
+ */
+static int insert_boundaries_in_tap_windows(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data, u8 boun_end)
+{
+ struct tap_window_data *tap_data;
+ struct tap_window_data *new_tap_data;
+ struct tap_window_data *temp_tap_data;
+ struct tuning_values *calc_values = &tuning_data->calc_values;
+ int curr_boun;
+ u8 i = 0, j = 0, num_of_wins;
+ bool get_next_boun = false;
+
+ temp_tap_data = devm_kzalloc(mmc_dev(sdhci->mmc),
+ sizeof(struct tap_window_data) * 42, GFP_KERNEL);
+ if (IS_ERR_OR_NULL(temp_tap_data)) {
+ dev_err(mmc_dev(sdhci->mmc), "No mem for final tap wins\n");
+ return -ENOMEM;
+ }
+
+ num_of_wins = tuning_data->num_of_valid_tap_wins;
+ curr_boun = boun_end % calc_values->ui;
do {
- /* Get the full window start */
- tap_value++;
- tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, true);
- if (tap_value > MAX_TAP_VALUES) {
- /* All tap values exhausted. No full window */
- tap_data->abandon_full_win = true;
- goto out;
- } else {
- tap_data->full_win_begin = tap_value;
+ if (get_next_boun) {
+ curr_boun += calc_values->ui;
/*
- * If full win start is 0xFF, then set that as
- * full win end and exit.
+ * If the boun_end exceeds the intial boundary end,
+ * just copy remaining windows and return.
*/
- if (tap_value == MAX_TAP_VALUES) {
- tap_data->full_win_end = tap_value;
- goto out;
- }
+ if (curr_boun >= boun_end)
+ curr_boun += MAX_TAP_VALUES;
+ }
+
+ tap_data = &tuning_data->tap_data[i];
+ new_tap_data = &temp_tap_data[j];
+ if (curr_boun <= tap_data->win_start) {
+ get_next_boun = true;
+ continue;
+ } else if (curr_boun >= tap_data->win_end) {
+ memcpy(new_tap_data, tap_data,
+ sizeof(struct tap_window_data));
+ i++;
+ j++;
+ num_of_wins--;
+ get_next_boun = false;
+ continue;
+ } else if ((curr_boun >= tap_data->win_start) &&
+ (curr_boun <= tap_data->win_end)) {
+ new_tap_data->win_start = tap_data->win_start;
+ new_tap_data->win_start_attr =
+ tap_data->win_start_attr;
+ new_tap_data->win_end = curr_boun - 1;
+ new_tap_data->win_end_attr =
+ tap_data->win_end_attr;
+ j++;
+ new_tap_data = &temp_tap_data[j];
+ new_tap_data->win_start = curr_boun;
+ new_tap_data->win_end = curr_boun;
+ new_tap_data->win_start_attr =
+ WIN_EDGE_BOUN_START;
+ new_tap_data->win_end_attr =
+ WIN_EDGE_BOUN_END;
+ j++;
+ new_tap_data = &temp_tap_data[j];
+ new_tap_data->win_start = curr_boun + 1;
+ new_tap_data->win_start_attr = WIN_EDGE_BOUN_START;
+ new_tap_data->win_end = tap_data->win_end;
+ new_tap_data->win_end_attr =
+ tap_data->win_end_attr;
+ i++;
+ j++;
+ num_of_wins--;
+ get_next_boun = true;
}
+ } while (num_of_wins > 0);
+
+ /* Update the num of valid wins count after tap holes insertion */
+ tuning_data->num_of_valid_tap_wins = j;
+
+ memcpy(tuning_data->tap_data, temp_tap_data,
+ j * sizeof(struct tap_window_data));
+ SDHCI_TEGRA_DBG("***tuning windows after inserting boundaries***\n");
+ SDHCI_TEGRA_DBG("WIN_ATTR legend: 0-BOUN_ST, 1-BOUN_END, 2-HOLE\n");
+ for (i = 0; i < tuning_data->num_of_valid_tap_wins; i++) {
+ new_tap_data = &tuning_data->tap_data[i];
+ SDHCI_TEGRA_DBG("win[%d]:%d(%d) - %d(%d)\n", i,
+ new_tap_data->win_start,
+ new_tap_data->win_start_attr,
+ new_tap_data->win_end, new_tap_data->win_end_attr);
+ }
+ SDHCI_TEGRA_DBG("***********************************************\n");
+
+ return 0;
+}
- /* Get the full window end */
+/*
+ * Scan for all tap values and get all passing tap windows.
+ */
+static int sdhci_tegra_get_tap_window_data(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+ struct sdhci_tegra *tegra_host = pltfm_host->priv;
+ struct tap_window_data *tap_data;
+ struct tuning_ui tuning_ui[10];
+ int err = 0, partial_win_start = 0, temp_margin = 0;
+ unsigned int tap_value, calc_ui = 0;
+ u8 prev_boundary_end = 0, num_of_wins = 0;
+ u8 num_of_uis = 0, valid_num_uis = 0;
+ u8 ref_ui, first_valid_full_win = 0;
+ u8 boun_end = 0, next_boun_end = 0;
+ u8 j = 0;
+ bool valid_ui_found = false;
+
+ /*
+ * Assume there are a max of 10 windows and allocate tap window
+ * structures for the same. If there are more windows, the array
+ * size can be adjusted later using realloc.
+ */
+ tuning_data->tap_data = devm_kzalloc(mmc_dev(sdhci->mmc),
+ sizeof(struct tap_window_data) * 42, GFP_KERNEL);
+ if (IS_ERR_OR_NULL(tuning_data->tap_data)) {
+ dev_err(mmc_dev(sdhci->mmc), "No memory for tap data\n");
+ return -ENOMEM;
+ }
+
+ spin_lock(&sdhci->lock);
+ tap_value = 0;
+ do {
+ tap_data = &tuning_data->tap_data[num_of_wins];
+ /* Get the window start */
+ tap_value = sdhci_tegra_scan_tap_values(sdhci, tap_value, true);
+ tap_data->win_start = min_t(u8, tap_value, MAX_TAP_VALUES);
tap_value++;
+ if (tap_value >= MAX_TAP_VALUES) {
+ /* If it's first iteration, then all taps failed */
+ if (!num_of_wins) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "All tap values(0-255) failed\n");
+ spin_unlock(&sdhci->lock);
+ return -EINVAL;
+ } else {
+ /* All windows obtained */
+ break;
+ }
+ }
+
+ /* Get the window end */
tap_value = sdhci_tegra_scan_tap_values(sdhci,
tap_value, false);
- tap_data->full_win_end = tap_value - 1;
- if (tap_value > MAX_TAP_VALUES)
- tap_data->full_win_end = MAX_TAP_VALUES;
- full_win_percentage = ((tap_data->full_win_end -
- tap_data->full_win_begin) * 100) /
- (tap_data->partial_win + 1);
- } while (full_win_percentage < 50 && tap_value < MAX_TAP_VALUES);
-
- if (full_win_percentage < 50)
- tap_data->abandon_full_win = true;
-out:
+ tap_data->win_end = min_t(u8, (tap_value - 1), MAX_TAP_VALUES);
+ tap_data->win_size = tap_data->win_end - tap_data->win_start;
+ tap_value++;
+
+ /*
+ * If the size of window is more than 4 taps wide, then it is a
+ * valid window. If tap value 0 has passed, then a partial
+ * window exists. Mark all the window edges as boundary edges.
+ */
+ if (tap_data->win_size > 4) {
+ if (tap_data->win_start == 0)
+ tuning_data->is_partial_win_valid = true;
+ tap_data->win_start_attr = WIN_EDGE_BOUN_START;
+ tap_data->win_end_attr = WIN_EDGE_BOUN_END;
+ } else {
+ /* Invalid window as size is less than 5 taps */
+ SDHCI_TEGRA_DBG("Invalid tuning win (%d-%d) ignored\n",
+ tap_data->win_start, tap_data->win_end);
+ continue;
+ }
+
+ /* Ignore first and last partial UIs */
+ if (tap_data->win_end_attr == WIN_EDGE_BOUN_END) {
+ tuning_ui[num_of_uis].ui = tap_data->win_end -
+ prev_boundary_end;
+ tuning_ui[num_of_uis].is_valid_ui = true;
+ num_of_uis++;
+ prev_boundary_end = tap_data->win_end;
+ }
+ num_of_wins++;
+ } while (tap_value < MAX_TAP_VALUES);
+ spin_unlock(&sdhci->lock);
+
+ tuning_data->num_of_valid_tap_wins = num_of_wins;
+ valid_num_uis = num_of_uis;
+
+ /* Print info of all tap windows */
+ pr_info("**********Auto tuning windows*************\n");
+ pr_info("WIN_ATTR legend: 0-BOUN_ST, 1-BOUN_END, 2-HOLE\n");
+ for (j = 0; j < tuning_data->num_of_valid_tap_wins; j++) {
+ tap_data = &tuning_data->tap_data[j];
+ pr_info("win[%d]: %d(%d) - %d(%d)\n",
+ j, tap_data->win_start, tap_data->win_start_attr,
+ tap_data->win_end, tap_data->win_end_attr);
+ }
+ pr_info("***************************************\n");
+
+ /* Mark the first last partial UIs as invalid */
+ tuning_ui[0].is_valid_ui = false;
+ tuning_ui[num_of_uis - 1].is_valid_ui = false;
+ valid_num_uis -= 2;
+
+ /* Discredit all uis at either end with size less than 30% of est ui */
+ ref_ui = (30 * tuning_data->est_values.ui) / 100;
+ for (j = 0; j < num_of_uis; j++) {
+ if (tuning_ui[j].is_valid_ui) {
+ tuning_ui[j].is_valid_ui = false;
+ valid_num_uis--;
+ }
+ if (tuning_ui[j].ui > ref_ui)
+ break;
+ }
+
+ for (j = num_of_uis; j > 0; j--) {
+ if (tuning_ui[j - 1].ui < ref_ui) {
+ if (tuning_ui[j - 1].is_valid_ui) {
+ tuning_ui[j - 1].is_valid_ui = false;
+ valid_num_uis--;
+ }
+ } else
+ break;
+ }
+
+ /* Calculate 0.75*est_UI */
+ ref_ui = (75 * tuning_data->est_values.ui) / 100;
+
/*
- * Mark tuning as failed if both partial and full windows are
- * abandoned.
+ * Check for valid UIs and discredit invalid UIs. A UI is considered
+ * valid if it's greater than (0.75*est_UI). If an invalid UI is found,
+ * also discredit the smaller of the two adjacent windows.
*/
- if (tap_data->abandon_partial_win && tap_data->abandon_full_win)
- err = -EIO;
+ for (j = 1; j < (num_of_uis - 1); j++) {
+ if (tuning_ui[j].ui > ref_ui && tuning_ui[j].is_valid_ui) {
+ tuning_ui[j].is_valid_ui = true;
+ } else {
+ if (tuning_ui[j].is_valid_ui) {
+ tuning_ui[j].is_valid_ui = false;
+ valid_num_uis--;
+ }
+ if (!tuning_ui[j + 1].is_valid_ui ||
+ !tuning_ui[j - 1].is_valid_ui) {
+ if (tuning_ui[j - 1].is_valid_ui) {
+ tuning_ui[j - 1].is_valid_ui = false;
+ valid_num_uis--;
+ } else if (tuning_ui[j + 1].is_valid_ui) {
+ tuning_ui[j + 1].is_valid_ui = false;
+ valid_num_uis--;
+ }
+ } else {
+
+ if (tuning_ui[j - 1].ui > tuning_ui[j + 1].ui)
+ tuning_ui[j + 1].is_valid_ui = false;
+ else
+ tuning_ui[j - 1].is_valid_ui = false;
+ valid_num_uis--;
+ }
+ }
+ }
+
+ /* Calculate the cumulative UI if there are valid UIs left */
+ if (valid_num_uis) {
+ for (j = 0; j < num_of_uis; j++)
+ if (tuning_ui[j].is_valid_ui) {
+ calc_ui += tuning_ui[j].ui;
+ if (!first_valid_full_win)
+ first_valid_full_win = j;
+ }
+ }
+
+ if (calc_ui) {
+ tuning_data->calc_values.ui = (calc_ui / valid_num_uis);
+ valid_ui_found = true;
+ } else {
+ tuning_data->calc_values.ui = tuning_data->est_values.ui;
+ valid_ui_found = false;
+ }
+
+ SDHCI_TEGRA_DBG("****Tuning UIs***********\n");
+ for (j = 0; j < num_of_uis; j++)
+ SDHCI_TEGRA_DBG("Tuning UI[%d] : %d, Is valid[%d]\n",
+ j, tuning_ui[j].ui, tuning_ui[j].is_valid_ui);
+ SDHCI_TEGRA_DBG("*************************\n");
+
+ /* Get the calculated tuning values */
+ err = calculate_actual_tuning_values(tegra_host->speedo, tuning_data,
+ tegra_host->boot_vcore_mv);
+
+ /*
+ * Calculate negative margin if partial win is valid. There are two
+ * cases here.
+ * Case 1: If Avg_UI is found, then keep subtracting avg_ui from start
+ * of first valid full window until a value <=0 is obtained.
+ * Case 2: If Avg_UI is not found, subtract avg_ui from all boundary
+ * starts until a value <=0 is found.
+ */
+ if (tuning_data->is_partial_win_valid && (num_of_wins > 1)) {
+ if (valid_ui_found) {
+ partial_win_start =
+ tuning_data->tap_data[first_valid_full_win].win_start;
+ boun_end = partial_win_start;
+ partial_win_start %= tuning_data->calc_values.ui;
+ partial_win_start -= tuning_data->calc_values.ui;
+ } else {
+ for (j = 0; j < NEG_MAR_CHK_WIN_COUNT; j++) {
+ temp_margin =
+ tuning_data->tap_data[j + 1].win_start;
+ if (!boun_end)
+ boun_end = temp_margin;
+ else if (!next_boun_end)
+ next_boun_end = temp_margin;
+ temp_margin %= tuning_data->calc_values.ui;
+ temp_margin -= tuning_data->calc_values.ui;
+ if (!partial_win_start ||
+ (temp_margin > partial_win_start))
+ partial_win_start = temp_margin;
+ }
+ }
+ if (partial_win_start <= 0)
+ tuning_data->tap_data[0].win_start = partial_win_start;
+ }
+
+ if (boun_end)
+ insert_boundaries_in_tap_windows(sdhci, tuning_data, boun_end);
+ if (next_boun_end)
+ insert_boundaries_in_tap_windows(sdhci, tuning_data, next_boun_end);
+
+ /* Insert calculated holes into the windows */
+ err = adjust_holes_in_tap_windows(sdhci, tuning_data);
+
return err;
}
@@ -2037,8 +2684,7 @@ static void sdhci_tegra_dump_tuning_constraints(struct sdhci_host *sdhci)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
struct tegra_tuning_data *tuning_data;
- struct tap_window_data *tap_data;
- u8 i, j;
+ u8 i;
SDHCI_TEGRA_DBG("%s: Num of tuning frequencies%d\n",
mmc_hostname(sdhci->mmc), tegra_host->tuning_freq_count);
@@ -2047,12 +2693,6 @@ static void sdhci_tegra_dump_tuning_constraints(struct sdhci_host *sdhci)
SDHCI_TEGRA_DBG("%s: Tuning freq[%d]: %d, freq band %d\n",
mmc_hostname(sdhci->mmc), i,
tuning_data->freq_hz, tuning_data->freq_band);
- SDHCI_TEGRA_DBG("%s: Supported voltages:",
- mmc_hostname(sdhci->mmc));
- for (j = 0; j < tuning_data->nr_voltages; ++j) {
- tap_data = tuning_data->tap_data[j];
- SDHCI_TEGRA_DBG("%d,", tap_data->voltage);
- }
}
}
@@ -2074,40 +2714,6 @@ static unsigned int get_tuning_voltage(struct sdhci_tegra *tegra_host, u8 *mask)
return tegra_host->boot_vcore_mv;
}
-static int sdhci_tegra_setup_vcore_constraints(struct sdhci_host *sdhci)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
- struct sdhci_tegra *tegra_host = pltfm_host->priv;
- struct freq_tuning_constraints *constraints;
- struct tegra_tuning_data *tuning_data;
- struct tap_window_data *tap_data;
- u8 freq_count = tegra_host->tuning_freq_count;
- u8 nr_voltages, i, j, vcore_mask;
-
- for (i = 0; i < freq_count; i++) {
- tuning_data = &tegra_host->tuning_data[i];
- constraints = &tuning_data->constraints;
- nr_voltages = hweight32(constraints->vcore_mask);
- SDHCI_TEGRA_DBG("%s: %dHz: vcore mask %#x, nr voltages %d\n",
- mmc_hostname(sdhci->mmc), tuning_data->freq_hz,
- constraints->vcore_mask, nr_voltages);
- vcore_mask = constraints->vcore_mask;
- for (j = 0; j < nr_voltages; j++) {
- tap_data = devm_kzalloc(
- mmc_dev(sdhci->mmc),
- sizeof(struct tap_window_data),
- GFP_KERNEL);
- if (!tap_data)
- return -ENOMEM;
- tap_data->voltage = get_tuning_voltage(tegra_host,
- &vcore_mask);
- tuning_data->tap_data[j] = tap_data;
- }
- tuning_data->nr_voltages = nr_voltages;
- }
- return 0;
-}
-
static u8 sdhci_tegra_get_freq_point(struct sdhci_host *sdhci)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
@@ -2127,19 +2733,96 @@ static u8 sdhci_tegra_get_freq_point(struct sdhci_host *sdhci)
}
/*
+ * The frequency tuning algorithm tries to calculate the tap-to-tap delay
+ * UI and estimate holes using equations and predetermined coefficients from
+ * the characterization data. The algorithm will not work without this data.
+ */
+static int find_tuning_coeffs_data(struct sdhci_host *sdhci,
+ bool force_retuning)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+ struct sdhci_tegra *tegra_host = pltfm_host->priv;
+ const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
+ struct tegra_tuning_data *tuning_data;
+ struct tuning_t2t_coeffs *t2t_coeffs;
+ struct tap_hole_coeffs *thole_coeffs;
+ const char *dev_id;
+ unsigned int freq_khz;
+ u8 i, j;
+ bool coeffs_set = false;
+
+ dev_id = dev_name(mmc_dev(sdhci->mmc));
+ /* Find the coeffs data for all supported frequencies */
+ for (i = 0; i < tegra_host->tuning_freq_count; i++) {
+ tuning_data = &tegra_host->tuning_data[i];
+
+ /* Skip if T2T coeffs are already found */
+ if (tuning_data->t2t_coeffs == NULL || force_retuning) {
+ t2t_coeffs = soc_data->t2t_coeffs;
+ for (j = 0; j < soc_data->t2t_coeffs_count; j++) {
+ if (!strcmp(dev_id, t2t_coeffs->dev_id)) {
+ tuning_data->t2t_coeffs = t2t_coeffs;
+ coeffs_set = true;
+ dev_info(mmc_dev(sdhci->mmc),
+ "Found T2T coeffs data\n");
+ break;
+ }
+ t2t_coeffs++;
+ }
+ if (!coeffs_set) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "T2T coeffs data missing\n");
+ tuning_data->t2t_coeffs = NULL;
+ return -ENODATA;
+ }
+ }
+
+ coeffs_set = false;
+ /* Skip if tap hole coeffs are already found */
+ if (tuning_data->thole_coeffs == NULL || force_retuning) {
+ thole_coeffs = soc_data->tap_hole_coeffs;
+ freq_khz = tuning_data->freq_hz / 1000;
+ for (j = 0; j < soc_data->tap_hole_coeffs_count; j++) {
+ if (!strcmp(dev_id, thole_coeffs->dev_id) &&
+ (freq_khz == thole_coeffs->freq_khz)) {
+ tuning_data->thole_coeffs =
+ thole_coeffs;
+ coeffs_set = true;
+ dev_info(mmc_dev(sdhci->mmc),
+ "%dMHz tap hole coeffs found\n",
+ (freq_khz / 1000));
+ break;
+ }
+ thole_coeffs++;
+ }
+
+ if (!coeffs_set) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "%dMHz Tap hole coeffs data missing\n",
+ (freq_khz / 1000));
+ tuning_data->thole_coeffs = NULL;
+ return -ENODATA;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
* Determines the numbers of frequencies required and then fills up the tuning
* constraints for each of the frequencies. The data of lower frequency is
- * filled first and then the higher frequency data. Currently fills constraints
- * for number of frequencies 1 and 2.
+ * filled first and then the higher frequency data. Max supported frequencies
+ * is currently two.
*/
-static u8 sdhci_tegra_setup_freq_constraints(struct sdhci_host *sdhci,
+static int setup_freq_constraints(struct sdhci_host *sdhci,
const unsigned int *freq_list)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
struct tegra_tuning_data *tuning_data;
- int i;
- u8 freq_count, freq_band;
+ int i, freq_count;
+ u8 freq_band;
if ((sdhci->mmc->ios.timing != MMC_TIMING_UHS_SDR50) &&
(sdhci->mmc->caps2 & MMC_CAP2_FREQ_SCALING))
@@ -2154,27 +2837,19 @@ static u8 sdhci_tegra_setup_freq_constraints(struct sdhci_host *sdhci,
tuning_data = &tegra_host->tuning_data[0];
tuning_data->freq_hz = sdhci->max_clk;
tuning_data->freq_band = freq_band;
- tuning_data->constraints =
- tuning_vcore_constraints[freq_band];
- if (tegra_host->soc_data->nvquirks &
- NVQUIRK_HIGH_FREQ_TAP_PROCEDURE) {
- if (tuning_data->freq_band == TUNING_LOW_FREQ)
- tuning_data->constraints.vcore_mask |=
- MIN_OVERRIDE_VCORE_TUN;
- }
- if (!tegra_host->plat->en_nominal_vcore_tuning)
- tuning_data->constraints.vcore_mask &=
- ~NOMINAL_VCORE_TUN;
+ tuning_data->constraints.vcore_mask =
+ tuning_vcore_constraints[freq_band].vcore_mask;
+ tuning_data->nr_voltages =
+ hweight32(tuning_data->constraints.vcore_mask);
break;
case 2:
tuning_data = &tegra_host->tuning_data[1];
tuning_data->freq_hz = sdhci->max_clk;
tuning_data->freq_band = freq_band;
- tuning_data->constraints =
- tuning_vcore_constraints[freq_band];
- if (!tegra_host->plat->en_nominal_vcore_tuning)
- tuning_data->constraints.vcore_mask &=
- ~NOMINAL_VCORE_TUN;
+ tuning_data->constraints.vcore_mask =
+ tuning_vcore_constraints[freq_band].vcore_mask;
+ tuning_data->nr_voltages =
+ hweight32(tuning_data->constraints.vcore_mask);
tuning_data = &tegra_host->tuning_data[0];
for (i = (freq_band - 1); i >= 0; i--) {
@@ -2182,51 +2857,51 @@ static u8 sdhci_tegra_setup_freq_constraints(struct sdhci_host *sdhci,
continue;
tuning_data->freq_hz = freq_list[i];
tuning_data->freq_band = i;
- tuning_data->constraints =
- tuning_vcore_constraints[i];
- if (tegra_host->soc_data->nvquirks &
- NVQUIRK_HIGH_FREQ_TAP_PROCEDURE) {
- if (i == TUNING_LOW_FREQ)
- tuning_data->constraints.vcore_mask |=
- MIN_OVERRIDE_VCORE_TUN;
- }
- if (!tegra_host->plat->en_nominal_vcore_tuning)
- tuning_data->constraints.vcore_mask &=
- ~NOMINAL_VCORE_TUN;
+ tuning_data->nr_voltages = 1;
+ tuning_data->constraints.vcore_mask =
+ tuning_vcore_constraints[i].vcore_mask;
+ tuning_data->nr_voltages =
+ hweight32(tuning_data->constraints.vcore_mask);
}
break;
default:
dev_err(mmc_dev(sdhci->mmc), "Unsupported freq count\n");
+ freq_count = -1;
}
+
return freq_count;
}
/*
- * Get the supported frequencies, core voltage levels for each frequency and
- * other tuning related constraints.
- * The supported frequencies should be determined from the list of frequencies
- * in the soc data and also consider the platform clock limits as well as any
- * DFS related restrictions.
- * Check if tuning at nominal core voltage is required.
+ * Get the supported frequencies and other tuning related constraints for each
+ * frequency. The supported frequencies should be determined from the list of
+ * frequencies in the soc data and also consider the platform clock limits as
+ * well as any DFS related restrictions.
*/
-static int sdhci_tegra_get_tuning_constraints(struct sdhci_host *sdhci)
+static int sdhci_tegra_get_tuning_constraints(struct sdhci_host *sdhci,
+ bool force_retuning)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
const unsigned int *freq_list;
int err = 0;
+ /* A valid freq count means freq constraints are already set up */
+ if (!tegra_host->tuning_freq_count || force_retuning) {
+ freq_list = tegra_host->soc_data->tuning_freq_list;
+ tegra_host->tuning_freq_count =
+ setup_freq_constraints(sdhci, freq_list);
+ if (tegra_host->tuning_freq_count < 0) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "Invalid tuning freq count\n");
+ return -EINVAL;
+ }
+ }
- /* Check if the constraints are already filled up */
- if (tegra_host->tuning_freq_count)
+ err = find_tuning_coeffs_data(sdhci, force_retuning);
+ if (err)
return err;
- freq_list = tegra_host->soc_data->tuning_freq_list;
- tegra_host->tuning_freq_count =
- sdhci_tegra_setup_freq_constraints(sdhci, freq_list);
-
- err = sdhci_tegra_setup_vcore_constraints(sdhci);
-
sdhci_tegra_dump_tuning_constraints(sdhci);
return err;
@@ -2288,63 +2963,59 @@ static int sdhci_tegra_set_tuning_voltage(struct sdhci_host *sdhci,
return err;
}
-static u8 get_curr_voltage_tuning_status(struct tap_window_data *tap_data)
-{
- if (!tap_data->vcore_set_status)
- maintain_boot_voltage = true;
-
- if (!tap_data->vcore_set_status || !tap_data->found_tuning_window)
- return 1;
-
- return 0;
-}
-
-static u8 sdhci_tegra_run_tuning(struct sdhci_host *sdhci,
- struct tegra_tuning_data *tuning_data, bool force_retuning)
+static int sdhci_tegra_run_tuning(struct sdhci_host *sdhci,
+ struct tegra_tuning_data *tuning_data)
{
- struct tap_window_data *tap_data;
- int err;
- u8 i, retuning_req = 0;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+ struct sdhci_tegra *tegra_host = pltfm_host->priv;
+ int err = 0;
+ int voltage = 0;
+ u8 i, vcore_mask = 0;
+ vcore_mask = tuning_data->constraints.vcore_mask;
for (i = 0; i < tuning_data->nr_voltages; i++) {
- tap_data = tuning_data->tap_data[i];
- /* Skip if tuning is already completed successfully */
- if (tap_data->vcore_set_status &&
- tap_data->found_tuning_window && !force_retuning)
- continue;
- err = sdhci_tegra_set_tuning_voltage(sdhci,
- tap_data->voltage);
- tap_data->vcore_set_status = !err;
+ voltage = get_tuning_voltage(tegra_host, &vcore_mask);
+ err = sdhci_tegra_set_tuning_voltage(sdhci, voltage);
+ if (err) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "Unable to set override voltage.\n");
+ return err;
+ }
+
/* Get the tuning window info */
- spin_lock(&sdhci->lock);
- err = sdhci_tegra_get_tap_window_data(sdhci, tap_data);
- spin_unlock(&sdhci->lock);
- SDHCI_TEGRA_DBG("%s: Tap data[%d] obtained\n",
- mmc_hostname(sdhci->mmc), i);
- tap_data->found_tuning_window = !err;
- if (err)
+ SDHCI_TEGRA_DBG("Getting tuning windows...\n");
+ err = sdhci_tegra_get_tap_window_data(sdhci, tuning_data);
+ if (err) {
dev_err(mmc_dev(sdhci->mmc),
- "Invalid tap win. Retuning req\n");
- retuning_req |= get_curr_voltage_tuning_status(tap_data);
- SDHCI_TEGRA_DBG("%s: Retuning req %s\n",
- mmc_hostname(sdhci->mmc), retuning_req ? "set" :
- "not set");
+ "Failed to get tap win %d\n", err);
+ return err;
+ }
+ SDHCI_TEGRA_DBG("%s: %d tuning window data obtained\n",
+ mmc_hostname(sdhci->mmc), tuning_data->freq_hz);
}
- return retuning_req;
+ return err;
}
-static int sdhci_tegra_verify_best_tap(struct sdhci_host *sdhci,
- u8 freq_band)
+static int sdhci_tegra_verify_best_tap(struct sdhci_host *sdhci)
{
struct tegra_tuning_data *tuning_data;
- unsigned int best_tap_value = 0;
- int err;
+ int err = 0;
tuning_data = sdhci_tegra_get_tuning_data(sdhci, sdhci->max_clk);
- best_tap_value = tuning_data->best_tap_value;
+ if ((tuning_data->best_tap_value < 0) ||
+ (tuning_data->best_tap_value > MAX_TAP_VALUES)) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "Trying to verify invalid best tap value\n");
+ return -EINVAL;
+ } else {
+ dev_info(mmc_dev(sdhci->mmc),
+ "%s: tuning freq %dhz, best tap %d\n",
+ __func__, tuning_data->freq_hz,
+ tuning_data->best_tap_value);
+ }
/* Set the best tap value */
- sdhci_tegra_set_tap_delay(sdhci, best_tap_value);
+ sdhci_tegra_set_tap_delay(sdhci, tuning_data->best_tap_value);
/* Run tuning after setting the best tap value */
err = sdhci_tegra_issue_tuning_cmd(sdhci);
@@ -2360,13 +3031,14 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci, u32 opcode)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
struct tegra_tuning_data *tuning_data;
- unsigned int freq_band;
+ const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
int err;
u16 ctrl_2;
+ u32 misc_ctrl;
u32 ier;
u8 i, set_retuning = 0;
- bool is_retuning_req = false;
bool force_retuning = false;
+ bool enable_lb_clk;
/* Tuning is valid only in SDR104 and SDR50 modes */
ctrl_2 = sdhci_readw(sdhci, SDHCI_HOST_CONTROL2);
@@ -2384,10 +3056,16 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci, u32 opcode)
return -EINVAL;
SDHCI_TEGRA_DBG("%s: Starting freq tuning\n", mmc_hostname(sdhci->mmc));
+ enable_lb_clk = (soc_data->nvquirks &
+ NVQUIRK_DISABLE_EXTERNAL_LOOPBACK) &&
+ (tegra_host->instance == 2);
+ if (enable_lb_clk) {
+ misc_ctrl = sdhci_readl(sdhci, SDHCI_VNDR_MISC_CTRL);
+ misc_ctrl &= ~(1 <<
+ SDHCI_VNDR_MISC_CTRL_EN_EXT_LOOPBACK_SHIFT);
+ sdhci_writel(sdhci, misc_ctrl, SDHCI_VNDR_MISC_CTRL);
+ }
mutex_lock(&tuning_mutex);
- if (sdhci->flags & SDHCI_NEEDS_RETUNING)
- is_retuning_req = true;
- sdhci->flags &= ~SDHCI_NEEDS_RETUNING;
/* Set the tuning command to be used */
tegra_host->tuning_opcode = opcode;
@@ -2408,15 +3086,14 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci, u32 opcode)
* previous best tap value verification failed, force retuning.
*/
if (tegra_host->tuning_status == TUNING_STATUS_DONE) {
- freq_band = sdhci_tegra_get_freq_point(sdhci);
- dev_info(mmc_dev(sdhci->mmc),
- "Tuning already done. Setting tuned tap value %d\n",
- tegra_host->tuning_data[freq_band].best_tap_value);
- err = sdhci_tegra_verify_best_tap(sdhci, freq_band);
- if (err)
+ err = sdhci_tegra_verify_best_tap(sdhci);
+ if (err) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "Prev best tap failed. Re-running tuning\n");
force_retuning = true;
- else
+ } else {
goto out;
+ }
}
if (tegra_host->force_retune == true) {
@@ -2425,9 +3102,10 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci, u32 opcode)
}
tegra_host->tuning_status = 0;
- err = sdhci_tegra_get_tuning_constraints(sdhci);
+ err = sdhci_tegra_get_tuning_constraints(sdhci, force_retuning);
if (err) {
- dev_err(mmc_dev(sdhci->mmc), "Failed to get tuning constraints\n");
+ dev_err(mmc_dev(sdhci->mmc),
+ "Failed to get tuning constraints\n");
goto out;
}
@@ -2440,16 +3118,24 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci, u32 opcode)
mmc_hostname(sdhci->mmc), tuning_data->freq_hz);
tegra_sdhci_set_clock(sdhci, tuning_data->freq_hz);
- set_retuning = sdhci_tegra_run_tuning(sdhci, tuning_data,
- force_retuning);
+ SDHCI_TEGRA_DBG("%s: Calculating estimated tuning values\n",
+ mmc_hostname(sdhci->mmc));
+ err = calculate_estimated_tuning_values(tegra_host->speedo,
+ tuning_data, tegra_host->boot_vcore_mv);
+ if (err)
+ goto out;
- sdhci_tegra_calculate_best_tap(sdhci, tuning_data->freq_band);
+ SDHCI_TEGRA_DBG("Running tuning...\n");
+ err = sdhci_tegra_run_tuning(sdhci, tuning_data);
+ if (err)
+ goto out;
- /* Dump the tuning data */
- sdhci_tegra_dump_tuning_data(sdhci);
+ SDHCI_TEGRA_DBG("calculating best tap value\n");
+ err = sdhci_tegra_calculate_best_tap(sdhci, tuning_data);
+ if (err)
+ goto out;
- err = sdhci_tegra_verify_best_tap(sdhci,
- tuning_data->freq_band);
+ err = sdhci_tegra_verify_best_tap(sdhci);
if (!err && !set_retuning) {
tuning_data->tuning_done = true;
tegra_host->tuning_status |= TUNING_STATUS_DONE;
@@ -2457,29 +3143,9 @@ static int sdhci_tegra_execute_tuning(struct sdhci_host *sdhci, u32 opcode)
tegra_host->tuning_status |= TUNING_STATUS_RETUNE;
}
}
- if (tegra_host->tuning_status & TUNING_STATUS_RETUNE)
- mod_timer(&sdhci->tuning_timer, jiffies + 10 * HZ);
out:
- if (maintain_boot_voltage) {
- ++boot_volt_req_refcount;
- maintain_boot_voltage = false;
- SDHCI_TEGRA_DBG("%s: Need fixed core volt %d, refcount %d\n",
- mmc_hostname(sdhci->mmc), tegra_host->boot_vcore_mv,
- boot_volt_req_refcount);
-
- } else {
- if (boot_volt_req_refcount && is_retuning_req)
- --boot_volt_req_refcount;
- SDHCI_TEGRA_DBG("%s: Relax core volt constraint. refcount %d\n",
- mmc_hostname(sdhci->mmc), boot_volt_req_refcount);
- }
-
- if (boot_volt_req_refcount)
- sdhci_tegra_set_tuning_voltage(sdhci,
- tegra_host->boot_vcore_mv);
- else
- sdhci_tegra_set_tuning_voltage(sdhci, 0);
-
+ /* Release any override core voltages set */
+ sdhci_tegra_set_tuning_voltage(sdhci, 0);
/* Enable interrupts. Enable full range for core voltage */
sdhci_writel(sdhci, ier, SDHCI_INT_ENABLE);
@@ -2487,6 +3153,21 @@ out:
mutex_unlock(&tuning_mutex);
SDHCI_TEGRA_DBG("%s: Freq tuning done\n", mmc_hostname(sdhci->mmc));
+ if (enable_lb_clk) {
+ misc_ctrl = sdhci_readl(sdhci, SDHCI_VNDR_MISC_CTRL);
+ if (err) {
+ /* Tuning is failed and card will try to enumerate in
+ * Legacy High Speed mode. So, Enable External Loopback
+ * for SDMMC3.
+ */
+ misc_ctrl |= (1 <<
+ SDHCI_VNDR_MISC_CTRL_EN_EXT_LOOPBACK_SHIFT);
+ } else {
+ misc_ctrl &= ~(1 <<
+ SDHCI_VNDR_MISC_CTRL_EN_EXT_LOOPBACK_SHIFT);
+ }
+ sdhci_writel(sdhci, misc_ctrl, SDHCI_VNDR_MISC_CTRL);
+ }
return err;
}
@@ -2580,22 +3261,26 @@ static void tegra_sdhci_post_resume(struct sdhci_host *sdhci)
/*
* For tegra specific tuning, core voltage has to be fixed at different
* voltages to get the tap values. Fixing the core voltage during tuning for one
- * device might affect transfers of other SDMMC devices. To handle this, lock
- * tuning_mutex to prevent any transfers during tuning execution. This is not
- * required once tuning is done.
+ * device might affect transfers of other SDMMC devices. Check if tuning mutex
+ * is locked before starting a data transfer. The new tuning procedure might
+ * take at max 1.5s for completion for a single run. Taking DFS into count,
+ * setting the max timeout for tuning mutex check a 3 secs. Since tuning is
+ * run only during boot or the first time device is inserted, there wouldn't
+ * be any delays in cmd/xfer execution once devices enumeration is done.
*/
static void tegra_sdhci_get_bus(struct sdhci_host *sdhci)
{
- int timeout = 100;
- while (mutex_is_locked(&tuning_mutex)) {
- if (!timeout) {
- dev_err(mmc_dev(sdhci->mmc),
- "Tuning timer not released\n");
- return;
- }
- msleep(10);
- timeout--;
- };
+ unsigned int timeout = 300;
+
+ while (mutex_is_locked(&tuning_mutex)) {
+ msleep(10);
+ --timeout;
+ if (!timeout) {
+ dev_err(mmc_dev(sdhci->mmc),
+ "Tuning mutex locked for long time\n");
+ return;
+ }
+ };
}
/*
@@ -2953,9 +3638,14 @@ static struct sdhci_tegra_soc_data soc_data_tegra11 = {
NVQUIRK_ENABLE_DDR50 |
NVQUIRK_ENABLE_HS200 |
NVQUIRK_INFINITE_ERASE_TIMEOUT |
+ NVQUIRK_DISABLE_EXTERNAL_LOOPBACK |
NVQUIRK_DISABLE_SDMMC4_CALIB,
.parent_clk_list = {"pll_p", "pll_c"},
.tuning_freq_list = {81600000, 156000000, 200000000},
+ .t2t_coeffs = t11x_tuning_coeffs,
+ .t2t_coeffs_count = 3,
+ .tap_hole_coeffs = t11x_tap_hole_coeffs,
+ .tap_hole_coeffs_count = 12,
};
static struct sdhci_pltfm_data sdhci_tegra12_pdata = {
@@ -2978,7 +3668,10 @@ static struct sdhci_tegra_soc_data soc_data_tegra12 = {
NVQUIRK_DISABLE_EXTERNAL_LOOPBACK,
.parent_clk_list = {"pll_p", "pll_c"},
.tuning_freq_list = {81600000, 136000000, 200000000},
- .tuning_min_volt_list = {950, 1000, 0},
+ .t2t_coeffs = t12x_tuning_coeffs,
+ .t2t_coeffs_count = 3,
+ .tap_hole_coeffs = t12x_tap_hole_coeffs,
+ .tap_hole_coeffs_count = 13,
};
static const struct of_device_id sdhci_tegra_dt_match[] = {
@@ -3308,7 +4001,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
tegra_host->ddr_clk_limit = plat->ddr_clk_limit;
tegra_host->instance = pdev->id;
tegra_host->tap_cmd = TAP_CMD_TRIM_DEFAULT_VOLTAGE;
-
+ tegra_host->speedo = plat->cpu_speedo;
+ dev_info(mmc_dev(host->mmc), "Speedo value %d\n", tegra_host->speedo);
host->mmc->pm_caps |= plat->pm_caps;
host->mmc->pm_flags |= plat->pm_flags;
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 9e003f2957a4..fe7329ec0150 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -1888,6 +1888,8 @@ static int tegra_pcie_resume_noirq(struct device *dev)
return ret;
}
}
+ /* give 100ms for 1.05v to come up */
+ msleep(100);
ret = tegra_pcie_power_on();
if (ret) {
pr_err("PCIE: Failed to power on: %d\n", ret);
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 264054fe8a66..5914e7a9ed5a 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1601,6 +1601,24 @@ static int serial8250_tegra_handle_irq(struct uart_port *port)
return 1;
}
+#ifdef CONFIG_ARCH_TEGRA
+void tegra_serial_handle_break(struct uart_port *p)
+{
+ unsigned int status, tmout = 10000;
+
+ do {
+ status = p->serial_in(p, UART_LSR);
+ if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
+ status = p->serial_in(p, UART_RX);
+ else
+ break;
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ } while (1);
+}
+#endif
+
/*
* These Exar UARTs have an extra interrupt indicator that could
* fire for a few unimplemented interrupts. One of which is a
@@ -2761,6 +2779,9 @@ static void serial8250_config_port(struct uart_port *port, int flags)
if (port->type == PORT_TEGRA) {
up->bugs |= UART_BUG_NOMSR;
port->handle_irq = serial8250_tegra_handle_irq;
+#if defined CONFIG_ARCH_TEGRA
+ port->handle_break = tegra_serial_handle_break;
+#endif
}
if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 39c7ea4cb14f..261c0ad164ec 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -29,28 +29,6 @@ struct of_serial_info {
int line;
};
-#ifdef CONFIG_ARCH_TEGRA
-void tegra_serial_handle_break(struct uart_port *p)
-{
- unsigned int status, tmout = 10000;
-
- do {
- status = p->serial_in(p, UART_LSR);
- if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
- status = p->serial_in(p, UART_RX);
- else
- break;
- if (--tmout == 0)
- break;
- udelay(1);
- } while (1);
-}
-#else
-static inline void tegra_serial_handle_break(struct uart_port *port)
-{
-}
-#endif
-
/*
* Fill a struct uart_port for a given device node
*/
diff --git a/drivers/usb/phy/tegra11x_usb_phy.c b/drivers/usb/phy/tegra11x_usb_phy.c
index 426a2e69682b..f690691e3fa1 100644
--- a/drivers/usb/phy/tegra11x_usb_phy.c
+++ b/drivers/usb/phy/tegra11x_usb_phy.c
@@ -1,7 +1,7 @@
/*
* drivers/usb/phy/tegra11x_usb_phy.c
*
- * Copyright (c) 2012-2013 NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2012-2014 NVIDIA Corporation. All rights reserved.
*
*
* This software is licensed under the terms of the GNU General Public
@@ -1023,7 +1023,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
utmi_phy_iddq_override(false);
if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL,
- USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500))
+ USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2600))
pr_warn("%s: timeout waiting for phy to stabilize\n", __func__);
val = readl(base + HOSTPC1_DEVLC);
diff --git a/drivers/video/tegra/dc/bandwidth.c b/drivers/video/tegra/dc/bandwidth.c
index b98ced801f7c..45558450403d 100644
--- a/drivers/video/tegra/dc/bandwidth.c
+++ b/drivers/video/tegra/dc/bandwidth.c
@@ -617,12 +617,12 @@ static unsigned long tegra_dc_calc_win_bandwidth(struct tegra_dc *dc,
* is of the luma plane's size only. */
bpp = tegra_dc_is_yuv_planar(w->fmt) ?
2 * tegra_dc_fmt_bpp(w->fmt) : tegra_dc_fmt_bpp(w->fmt);
- ret = dc->mode.pclk / 1000UL * bpp / 8 *
+ ret = dc->mode.pclk / 1000UL * bpp / 8
#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
- (win_use_v_filter(dc, w) ? 2 : 1) *
+ * (win_use_v_filter(dc, w) ? 2 : 1)
#endif
- in_w / w->out_w * (WIN_IS_TILED(w) ?
- tiled_windows_bw_multiplier : 1);
+ / w->out_w * in_w
+ / (WIN_IS_TILED(w) ? tiled_windows_bw_multiplier : 1);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
/*
* Assuming 60% efficiency: i.e. if we calculate we need 70MBps, we
diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h
index 8586d32a37ec..3580153ef5d2 100644
--- a/drivers/video/tegra/dc/dc_reg.h
+++ b/drivers/video/tegra/dc/dc_reg.h
@@ -503,16 +503,16 @@
#define DC_WIN_COLOR_DEPTH 0x703
#define DC_WIN_POSITION 0x704
-#define H_POSITION(x) (((x) & 0xfff) << 0)
-#define V_POSITION(x) (((x) & 0xfff) << 16)
+#define H_POSITION(x) (((x) & 0x1fff) << 0)
+#define V_POSITION(x) (((x) & 0x1fff) << 16)
#define DC_WIN_SIZE 0x705
-#define H_SIZE(x) (((x) & 0xfff) << 0)
-#define V_SIZE(x) (((x) & 0xfff) << 16)
+#define H_SIZE(x) (((x) & 0x1fff) << 0)
+#define V_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_PRESCALED_SIZE 0x706
-#define H_PRESCALED_SIZE(x) (((x) & 0x3fff) << 0)
-#define V_PRESCALED_SIZE(x) (((x) & 0xfff) << 16)
+#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0)
+#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
#define DC_WIN_H_INITIAL_DDA 0x707
#define DC_WIN_V_INITIAL_DDA 0x708
diff --git a/drivers/video/tegra/dc/hdmi_state_machine.c b/drivers/video/tegra/dc/hdmi_state_machine.c
index 3707a0a00a40..2312a98b3fff 100644
--- a/drivers/video/tegra/dc/hdmi_state_machine.c
+++ b/drivers/video/tegra/dc/hdmi_state_machine.c
@@ -151,7 +151,7 @@ static int emulate_hotplug = 1;
static void handle_enable_l(struct tegra_dc_hdmi_data *hdmi)
{
tegra_dc_enable(hdmi->dc);
- if (emulate_hotplug) {
+ if (emulate_hotplug && hdmi->dvi) {
emulate_hotplug = 0;
hdmi_reread_edid(hdmi->dc);
}
diff --git a/drivers/video/tegra/host/gk20a/channel_gk20a.c b/drivers/video/tegra/host/gk20a/channel_gk20a.c
index efb1c698faa0..bf15be94af9b 100644
--- a/drivers/video/tegra/host/gk20a/channel_gk20a.c
+++ b/drivers/video/tegra/host/gk20a/channel_gk20a.c
@@ -1528,8 +1528,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
* sure the fence represents work completion. In that case
* issue a wait-for-idle before the syncpoint increment.
*/
- wfi_cmd = !!(flags & NVHOST_SUBMIT_GPFIFO_FLAGS_FENCE_GET)
- && c->obj_class != KEPLER_C;
+ wfi_cmd = !!(flags & NVHOST_SUBMIT_GPFIFO_FLAGS_FENCE_GET);
/* Invalidate tlb if it's dirty... */
/* TBD: this should be done in the cmd stream, not with PRIs. */
@@ -1671,26 +1670,16 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
c->last_submit_fence.wfi = wfi_cmd;
trace_nvhost_ioctl_ctrl_syncpt_incr(fence->syncpt_id);
- if (c->obj_class == KEPLER_C) {
- /* setobject KEPLER_C */
- incr_cmd->ptr[j++] = 0x20010000;
- incr_cmd->ptr[j++] = KEPLER_C;
- /* syncpt incr */
- incr_cmd->ptr[j++] = 0x200100B2;
- incr_cmd->ptr[j++] = fence->syncpt_id | (0x1 << 20)
- | (0x1 << 16);
- } else {
- if (wfi_cmd)
- add_wfi_cmd(incr_cmd, &j);
- /* syncpoint_a */
- incr_cmd->ptr[j++] = 0x2001001C;
- /* payload, ignored */
- incr_cmd->ptr[j++] = 0;
- /* syncpoint_b */
- incr_cmd->ptr[j++] = 0x2001001D;
- /* syncpt_id, incr */
- incr_cmd->ptr[j++] = (fence->syncpt_id << 8) | 0x1;
- }
+ if (wfi_cmd)
+ add_wfi_cmd(incr_cmd, &j);
+ /* syncpoint_a */
+ incr_cmd->ptr[j++] = 0x2001001C;
+ /* payload, ignored */
+ incr_cmd->ptr[j++] = 0;
+ /* syncpoint_b */
+ incr_cmd->ptr[j++] = 0x2001001D;
+ /* syncpt_id, incr */
+ incr_cmd->ptr[j++] = (fence->syncpt_id << 8) | 0x1;
c->gpfifo.cpu_va[c->gpfifo.put].entry0 =
u64_lo32(incr_cmd->gva);
diff --git a/drivers/video/tegra/host/gk20a/gr_gk20a.c b/drivers/video/tegra/host/gk20a/gr_gk20a.c
index 4caaa51ab1aa..b4da945ee2a3 100644
--- a/drivers/video/tegra/host/gk20a/gr_gk20a.c
+++ b/drivers/video/tegra/host/gk20a/gr_gk20a.c
@@ -1887,10 +1887,9 @@ static int gr_gk20a_init_ctxsw_ucode(struct gk20a *g)
p_buf = (u8 *)p_ucode_info->surface_desc.cpuva;
if (!p_buf) {
- release_firmware(fecs_fw);
- release_firmware(gpccs_fw);
nvhost_err(d, "failed to map surface desc buffer");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto clean_up;
}
gr_gk20a_copy_ctxsw_ucode_inst(p_buf, &p_ucode_info->fecs,
@@ -1898,11 +1897,17 @@ static int gr_gk20a_init_ctxsw_ucode(struct gk20a *g)
g->gr.ctx_vars.ucode.fecs.inst.l,
g->gr.ctx_vars.ucode.fecs.data.l);
+ release_firmware(fecs_fw);
+ fecs_fw = NULL;
+
gr_gk20a_copy_ctxsw_ucode_inst(p_buf, &p_ucode_info->gpcs,
p_gpcs_boot_desc, p_gpcs_boot_image,
g->gr.ctx_vars.ucode.gpccs.inst.l,
g->gr.ctx_vars.ucode.gpccs.data.l);
+ release_firmware(gpccs_fw);
+ gpccs_fw = NULL;
+
err = gr_gk20a_init_ctxsw_ucode_vaspace(g);
if (err)
goto clean_up;
@@ -1925,6 +1930,11 @@ static int gr_gk20a_init_ctxsw_ucode(struct gk20a *g)
p_ucode_info->surface_desc.cpuva = NULL;
p_ucode_info->surface_desc.iova = 0;
+ release_firmware(gpccs_fw);
+ gpccs_fw = NULL;
+ release_firmware(fecs_fw);
+ fecs_fw = NULL;
+
return err;
}
@@ -5422,7 +5432,7 @@ int gk20a_gr_isr(struct gk20a *g)
}
if (need_reset)
- gk20a_set_error_notifier(ch,
+ gk20a_set_error_notifier(ch->hwctx,
NVHOST_CHANNEL_GR_ERROR_SW_NOTIFY);
}
diff --git a/drivers/video/tegra/host/msenc/msenc.c b/drivers/video/tegra/host/msenc/msenc.c
index 4a71de312978..c260ec1740d3 100644
--- a/drivers/video/tegra/host/msenc/msenc.c
+++ b/drivers/video/tegra/host/msenc/msenc.c
@@ -76,7 +76,7 @@ static char *msenc_get_fw_name(struct platform_device *dev)
return NULL;
}
- dev_info(&dev->dev, "fw name:%s\n", fw_name);
+ dev_dbg(&dev->dev, "fw name:%s\n", fw_name);
return fw_name;
}
diff --git a/drivers/video/tegra/host/tsec/tsec.c b/drivers/video/tegra/host/tsec/tsec.c
index 9316ab5bc9cc..eba08a1aec4e 100644
--- a/drivers/video/tegra/host/tsec/tsec.c
+++ b/drivers/video/tegra/host/tsec/tsec.c
@@ -80,7 +80,7 @@ static char *tsec_get_fw_name(struct platform_device *dev)
return NULL;
}
- dev_info(&dev->dev, "fw name:%s\n", fw_name);
+ dev_dbg(&dev->dev, "fw name:%s\n", fw_name);
return fw_name;
}
diff --git a/drivers/video/tegra/host/vic03/vic03.c b/drivers/video/tegra/host/vic03/vic03.c
index 35816243e0b5..b58f938eae09 100644
--- a/drivers/video/tegra/host/vic03/vic03.c
+++ b/drivers/video/tegra/host/vic03/vic03.c
@@ -73,7 +73,7 @@ static char *vic_get_fw_name(struct platform_device *dev)
decode_vic_ver(pdata->version, &maj, &min);
sprintf(fw_name, "vic%02d_ucode.bin", maj);
- dev_info(&dev->dev, "fw name:%s\n", fw_name);
+ dev_dbg(&dev->dev, "fw name:%s\n", fw_name);
return fw_name;
}
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index ab2157896d1d..047accde593d 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -9,7 +9,7 @@
*
* Davide Libenzi <davidel@xmailserver.org>
*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
*/
@@ -1290,7 +1290,9 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
spin_lock(&tfile->f_lock);
list_add_tail(&epi->fllink, &tfile->f_ep_links);
spin_unlock(&tfile->f_lock);
- tfile->f_path.dentry->d_inode->i_private = get_thread_process(current);
+ if (tfile->f_path.dentry->d_inode->i_private == NULL)
+ tfile->f_path.dentry->d_inode->i_private =
+ get_thread_process(current);
/*
* Add the current item to the RB tree. All RB tree operations are
diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h
index 59ea8e6a9587..2a374c56297d 100644
--- a/include/linux/clk/tegra.h
+++ b/include/linux/clk/tegra.h
@@ -159,6 +159,8 @@ struct notifier_block;
int tegra_dvfs_get_freqs(struct clk *c, unsigned long **freqs, int *num_freqs);
int tegra_dvfs_set_rate(struct clk *c, unsigned long rate);
int tegra_dvfs_override_core_voltage(struct clk *c, int override_mv);
+int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate);
+int tegra_dvfs_set_fmax_at_vmin(struct clk *c, unsigned long f_max, int v_min);
unsigned long clk_get_rate_all_locked(struct clk *c);
int tegra_dvfs_rail_disable_by_name(const char *reg_id);
int tegra_register_clk_rate_notifier(struct clk *c, struct notifier_block *nb);
diff --git a/include/linux/platform_data/mmc-sdhci-tegra.h b/include/linux/platform_data/mmc-sdhci-tegra.h
index 32de3cc5f1b6..0d5f862f66aa 100644
--- a/include/linux/platform_data/mmc-sdhci-tegra.h
+++ b/include/linux/platform_data/mmc-sdhci-tegra.h
@@ -1,9 +1,8 @@
/*
* Copyright (C) 2009 Palm, Inc.
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
* Author: Yvonne Yip <y@palm.com>
*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -64,6 +63,7 @@ struct tegra_sdhci_platform_data {
unsigned int calib_3v3_offsets; /* Format to be filled: 0xXXXXPDPU */
unsigned int calib_1v8_offsets; /* Format to be filled: 0xXXXXPDPU */
bool disable_clock_gate; /* no clock gate when true */
+ u32 cpu_speedo;
};
#endif
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index af47a8af6024..b4ddb420405c 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -125,5 +125,12 @@ unsigned int serial8250_modem_status(struct uart_8250_port *up);
extern void serial8250_set_isa_configurator(void (*v)
(int port, struct uart_port *up,
unsigned short *capabilities));
+#ifdef CONFIG_ARCH_TEGRA
+extern void tegra_serial_handle_break(struct uart_port *p);
+#else
+static inline void tegra_serial_handle_break(struct uart_port *port)
+{
+}
+#endif
#endif
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 611fed829ff6..2b79879684c8 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -3715,17 +3715,6 @@ static int max98090_probe(struct snd_soc_codec *codec)
INIT_DELAYED_WORK(&max98090->jack_work, max98090_jack_work);
- /* Enable jack detection */
- snd_soc_write(codec, M98090_REG_3D_CFG_JACK,
- M98090_JDETEN_MASK | M98090_JDEB_25MS);
-
- /* Register for interrupts */
- if ((request_threaded_irq(pdata->irq, NULL,
- max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "max98090_interrupt", codec)) < 0) {
- dev_info(codec->dev, "request_irq failed\n");
- }
-
#ifdef MAX98090_HIGH_PERFORMANCE
/* High Performance */
snd_soc_update_bits(codec, M98090_REG_43_DAC_CFG,
@@ -3758,6 +3747,20 @@ static int max98090_probe(struct snd_soc_codec *codec)
max98090_add_widgets(codec);
+ /* Clear existing interrupts */
+ snd_soc_read(codec, M98090_REG_01_IRQ_STATUS);
+
+ /* Register for interrupts */
+ if ((request_threaded_irq(pdata->irq, NULL,
+ max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "max98090_interrupt", codec)) < 0) {
+ dev_info(codec->dev, "request_irq failed\n");
+ }
+
+ /* Enable jack detection */
+ snd_soc_write(codec, M98090_REG_3D_CFG_JACK,
+ M98090_JDETEN_MASK | M98090_JDEB_25MS);
+
err_access:
return ret;
}
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index d57280e23318..c6e1d653f8e8 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -1,7 +1,7 @@
/*
* tegra30_ahub.c - Tegra30 AHUB driver
*
- * Copyright (c) 2011-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -618,6 +618,20 @@ static const char * const configlink_clocks[] = {
#ifndef CONFIG_ARCH_TEGRA_14x_SOC
"spdif_in",
#endif
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_12x_SOC)
+ "amx",
+ "adx",
+#endif
+#ifdef CONFIG_ARCH_TEGRA_12x_SOC
+ "amx1",
+ "adx1",
+ "afc0",
+ "afc1",
+ "afc2",
+ "afc3",
+ "afc4",
+ "afc5",
+#endif
};
struct of_dev_auxdata ahub_auxdata[] = {