]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - arch/arm/mach-tegra/common.c
ARM: (merge fixup) Move declaration to appropriate ifdef
[linux-3.10.git] / arch / arm / mach-tegra / common.c
index 446132949fd84445439d8835398565101b7997fc..b52b471a5d1c505e53aaca28ea270d4c2e185bf6 100644 (file)
 #include <linux/pstore_ram.h>
 #include <linux/dma-mapping.h>
 #include <linux/sys_soc.h>
+#if defined(CONFIG_SMSC911X)
+#include <linux/smsc911x.h>
+#endif
 
 #include <linux/export.h>
 #include <linux/bootmem.h>
 #include <trace/events/nvsecurity.h>
 
-#include <asm/hardware/cache-l2x0.h>
+#ifdef CONFIG_ARM64
+#include <linux/irqchip/gic.h>
+#else
 #include <asm/system.h>
+#include <asm/hardware/cache-l2x0.h>
+#endif
 #include <asm/dma-mapping.h>
 
 #include <mach/hardware.h>
 #include <mach/powergate.h>
 #include <mach/tegra_smmu.h>
-#include <mach/gpio-tegra.h>
 #include <mach/nct.h>
 
 #include "apbio.h"
@@ -73,6 +79,8 @@
 #define AHB_GIZMO_AHB_MEM              0xc
 #define   ENB_FAST_REARBITRATE BIT(2)
 #define   DONT_SPLIT_AHB_WR     BIT(7)
+#define   WR_WAIT_COMMIT_ON_1K BIT(8)
+#define   EN_USB_WAIT_COMMIT_ON_1K_STALL       BIT(9)
 
 #define   RECOVERY_MODE        BIT(31)
 #define   BOOTLOADER_MODE      BIT(30)
 #define   ADDR_BNDRY(x)        (((x) & 0xf) << 21)
 #define   INACTIVITY_TIMEOUT(x)        (((x) & 0xffff) << 0)
 
-unsigned long tegra_avp_kernel_start;
-unsigned long tegra_avp_kernel_size;
-unsigned long tegra_bootloader_fb_start;
-unsigned long tegra_bootloader_fb_size;
-unsigned long tegra_bootloader_fb2_start;
-unsigned long tegra_bootloader_fb2_size;
-unsigned long tegra_fb_start;
-unsigned long tegra_fb_size;
-unsigned long tegra_fb2_start;
-unsigned long tegra_fb2_size;
-unsigned long tegra_carveout_start;
-unsigned long tegra_carveout_size;
-unsigned long tegra_vpr_start;
-unsigned long tegra_vpr_size;
-unsigned long tegra_tsec_start;
-unsigned long tegra_tsec_size;
-unsigned long tegra_lp0_vec_start;
-unsigned long tegra_lp0_vec_size;
+phys_addr_t tegra_avp_kernel_start;
+phys_addr_t tegra_avp_kernel_size;
+phys_addr_t tegra_bootloader_fb_start;
+phys_addr_t tegra_bootloader_fb_size;
+phys_addr_t tegra_bootloader_fb2_start;
+phys_addr_t tegra_bootloader_fb2_size;
+phys_addr_t tegra_fb_start;
+phys_addr_t tegra_fb_size;
+phys_addr_t tegra_fb2_start;
+phys_addr_t tegra_fb2_size;
+phys_addr_t tegra_carveout_start;
+phys_addr_t tegra_carveout_size;
+phys_addr_t tegra_vpr_start;
+phys_addr_t tegra_vpr_size;
+phys_addr_t tegra_tsec_start;
+phys_addr_t tegra_tsec_size;
+phys_addr_t tegra_lp0_vec_start;
+phys_addr_t tegra_lp0_vec_size;
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+phys_addr_t tegra_wb0_params_address;
+phys_addr_t tegra_wb0_params_instances;
+phys_addr_t tegra_wb0_params_block_size;
+#endif
+
 #ifdef CONFIG_TEGRA_NVDUMPER
 unsigned long nvdumper_reserved;
 #endif
@@ -133,7 +147,8 @@ static struct board_info pmu_board_info;
 static struct board_info display_board_info;
 static int panel_id;
 static struct board_info camera_board_info;
-static int touch_id;
+static int touch_vendor_id;
+static int touch_panel_id;
 static struct board_info io_board_info;
 static struct board_info button_board_info;
 static struct board_info joystick_board_info;
@@ -150,6 +165,11 @@ static enum power_supply_type pow_supply_type = POWER_SUPPLY_TYPE_MAINS;
 static int pwr_i2c_clk = 400;
 static u8 power_config;
 static u8 display_config;
+
+#ifdef CONFIG_TEGRA_SIMULATION_SPLIT_MEM
+static int tegra_split_mem_set;
+#endif
+
 /*
  * Storage for debug-macro.S's state.
  *
@@ -170,6 +190,7 @@ u32 tegra_uart_config[4] = {
 
 
 #define NEVER_RESET 0
+static DEFINE_SPINLOCK(ahb_lock);
 
 void ahb_gizmo_writel(unsigned long val, void __iomem *reg)
 {
@@ -179,6 +200,7 @@ void ahb_gizmo_writel(unsigned long val, void __iomem *reg)
        /* Read and check if write is successful,
         * if val doesn't match with read, retry write.
         */
+       spin_lock(&ahb_lock);
        do {
                writel(val, reg);
                check = readl(reg);
@@ -187,6 +209,7 @@ void ahb_gizmo_writel(unsigned long val, void __iomem *reg)
                else
                        pr_err("AHB register access fail for reg\n");
        } while (--retry);
+       spin_unlock(&ahb_lock);
 }
 
 void tegra_assert_system_reset(char mode, const char *cmd)
@@ -254,6 +277,8 @@ static __initdata struct tegra_clk_init_table tegra11x_clk_init_table[] = {
        { "host1x",     "pll_p",        102000000,      false },
        { "cl_dvfs_ref", "pll_p",       51000000,       true },
        { "cl_dvfs_soc", "pll_p",       51000000,       true },
+       { "dsialp", "pll_p",    70000000,       false },
+       { "dsiblp", "pll_p",    70000000,       false },
 #else
        { "pll_m_out1", "pll_m",        275000000,      true },
        { "pll_p_out2", "pll_p",        108000000,      false },
@@ -272,11 +297,11 @@ static __initdata struct tegra_clk_init_table tegra11x_clk_init_table[] = {
        { "csite",      NULL,           0,              true },
 #endif
        { "pll_u",      NULL,           480000000,      true },
-       { "pll_re_vco", NULL,           612000000,      true },
+       { "pll_re_vco", NULL,           612000000,      false },
        { "xusb_falcon_src",    "pll_p",        204000000,      false},
        { "xusb_host_src",      "pll_p",        102000000,      false},
-       { "xusb_ss_src",        "pll_re_vco",   122400000,      false},
-       { "xusb_hs_src",        "xusb_ss_div2", 61200000,       false},
+       { "xusb_ss_src",        "pll_u_480M",   120000000,      false},
+       { "xusb_hs_src",        "pll_u_60M",    60000000,       false},
        { "xusb_fs_src",        "pll_u_48M",    48000000,       false},
        { "sdmmc1",     "pll_p",        48000000,       false},
        { "sdmmc3",     "pll_p",        48000000,       false},
@@ -287,13 +312,22 @@ static __initdata struct tegra_clk_init_table tegra11x_clk_init_table[] = {
        { "sbc4.sclk",  NULL,           40000000,       false},
        { "sbc5.sclk",  NULL,           40000000,       false},
        { "sbc6.sclk",  NULL,           40000000,       false},
+#ifdef CONFIG_TEGRA_DUAL_CBUS
+       { "c2bus",      "pll_c2",       250000000,      false },
+       { "c3bus",      "pll_c3",       250000000,      false },
+       { "pll_c",      NULL,           624000000,      false },
+#else
+       { "cbus",       "pll_c",        250000000,      false },
+#endif
+       { "pll_c_out1", "pll_c",        150000000,      false },
 #ifdef CONFIG_TEGRA_PLLM_SCALED
        { "vi",         "pll_p",        0,              false},
 #endif
 #ifdef CONFIG_TEGRA_SOCTHERM
-       { "soc_therm",  "pll_p",        51000000,       false },
+       { "soc_therm",  "pll_p",        136000000,      false },
        { "tsensor",    "clk_m",        500000,         false },
 #endif
+       { "csite",      NULL,           0,              true },
        { NULL,         NULL,           0,              0},
 };
 static __initdata struct tegra_clk_init_table tegra11x_cbus_init_table[] = {
@@ -308,6 +342,76 @@ static __initdata struct tegra_clk_init_table tegra11x_cbus_init_table[] = {
        { NULL,         NULL,           0,              0},
 };
 #endif
+#ifdef CONFIG_ARCH_TEGRA_12x_SOC
+static __initdata struct tegra_clk_init_table tegra12x_clk_init_table[] = {
+       /* name         parent          rate            enabled */
+       { "clk_m",      NULL,           0,              true },
+       { "emc",        NULL,           0,              true },
+       { "cpu",        NULL,           0,              true },
+       { "kfuse",      NULL,           0,              true },
+       { "fuse",       NULL,           0,              true },
+       { "sclk",       NULL,           0,              true },
+#ifdef CONFIG_TEGRA_SILICON_PLATFORM
+       { "pll_p",      NULL,           0,              true },
+       { "pll_p_out1", "pll_p",        0,              false },
+       { "pll_p_out3", "pll_p",        0,              true },
+       { "pll_m_out1", "pll_m",        275000000,      false },
+       { "pll_p_out2", "pll_p",        102000000,      false },
+       { "sclk",       "pll_p_out2",   102000000,      true },
+       { "pll_p_out4", "pll_p",        204000000,      true },
+       { "host1x",     "pll_p",        102000000,      false },
+       { "cl_dvfs_ref", "pll_p",       54000000,       true },
+       { "cl_dvfs_soc", "pll_p",       54000000,       true },
+       { "hclk",       "sclk",         102000000,      true },
+       { "pclk",       "hclk",         51000000,       true },
+       { "wake.sclk",  NULL,           40000000,       true },
+       { "mselect",    "pll_p",        102000000,      true },
+#else
+       { "pll_m_out1", "pll_m",        275000000,      true },
+       { "pll_p_out2", "pll_p",        108000000,      false },
+       { "sclk",       "pll_p_out2",   108000000,      true },
+       { "pll_p_out4", "pll_p",        216000000,      true },
+       { "hclk",       "sclk",         108000000,      true },
+       { "pclk",       "hclk",         54000000,       true },
+       { "mselect",    "pll_p",        108000000,      true },
+       { "host1x",     "pll_p",        108000000,      false },
+       { "cl_dvfs_ref", "clk_m",       13000000,       false },
+       { "cl_dvfs_soc", "clk_m",       13000000,       false },
+#endif
+#ifdef CONFIG_TEGRA_SLOW_CSITE
+       { "csite",      "clk_m",        1000000,        true },
+#else
+       { "csite",      NULL,           0,              true },
+#endif
+       { "pll_u",      NULL,           480000000,      true },
+       { "pll_re_vco", NULL,           612000000,      true },
+       { "xusb_falcon_src",    "pll_p",        204000000,      false},
+       { "xusb_host_src",      "pll_p",        102000000,      false},
+       { "xusb_ss_src",        "pll_re_vco",   122400000,      false},
+       { "xusb_hs_src",        "xusb_ss_div2", 61200000,       false},
+       { "xusb_fs_src",        "pll_u_48M",    48000000,       false},
+       { "sdmmc1",     "pll_p",        48000000,       false},
+       { "sdmmc3",     "pll_p",        48000000,       false},
+       { "sdmmc4",     "pll_p",        48000000,       false},
+       { "sbc1.sclk",  NULL,           40000000,       false},
+       { "sbc2.sclk",  NULL,           40000000,       false},
+       { "sbc3.sclk",  NULL,           40000000,       false},
+       { "sbc4.sclk",  NULL,           40000000,       false},
+       { "sbc5.sclk",  NULL,           40000000,       false},
+       { "sbc6.sclk",  NULL,           40000000,       false},
+#ifdef CONFIG_TEGRA_PLLM_SCALED
+       { "vi",         "pll_p",        0,              false},
+#endif
+#ifdef CONFIG_TEGRA_SOCTHERM
+       { "soc_therm",  "pll_p",        51000000,       false },
+       { "tsensor",    "clk_m",        500000,         false },
+#endif
+#if defined(CONFIG_TEGRA_SIMULATION_PLATFORM)
+       { "vde",        "pll_c3",       48400000,       true},
+#endif
+       { NULL,         NULL,           0,              0},
+};
+#endif
 #ifdef CONFIG_ARCH_TEGRA_14x_SOC
 static __initdata struct tegra_clk_init_table tegra14x_clk_init_table[] = {
        /* name         parent          rate            enabled */
@@ -536,6 +640,15 @@ static void __init tegra_perf_init(void)
 {
        u32 reg;
 
+#ifdef CONFIG_ARM64
+       asm volatile("mrs %0, PMCR_EL0" : "=r"(reg));
+       reg >>= 11;
+       reg = (1 << (reg & 0x1f))-1;
+       reg |= 0x80000000;
+       asm volatile("msr PMINTENCLR_EL1, %0" : : "r"(reg));
+       reg = 1;
+       asm volatile("msr PMUSERENR_EL0, %0" : : "r"(reg));
+#else
        asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(reg));
        reg >>= 11;
        reg = (1 << (reg & 0x1f))-1;
@@ -543,9 +656,10 @@ static void __init tegra_perf_init(void)
        asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r"(reg));
        reg = 1;
        asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r"(reg));
+#endif
 }
 
-#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
 static void __init tegra_ramrepair_init(void)
 {
        if (tegra_spare_fuse(10)  | tegra_spare_fuse(11)) {
@@ -562,7 +676,8 @@ static void __init tegra_init_power(void)
 #ifdef CONFIG_ARCH_TEGRA_HAS_SATA
        tegra_powergate_partition_with_clk_off(TEGRA_POWERGATE_SATA);
 #endif
-#ifdef CONFIG_ARCH_TEGRA_HAS_PCIE
+#if defined(CONFIG_ARCH_TEGRA_HAS_PCIE) && \
+                       !defined(CONFIG_TEGRA_PCIE_SKIP_POWERGATING)
        tegra_powergate_partition_with_clk_off(TEGRA_POWERGATE_PCIE);
 #endif
 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
@@ -589,6 +704,13 @@ static void __init tegra_init_ahb_gizmo_settings(void)
 
        val = gizmo_readl(AHB_GIZMO_AHB_MEM);
        val |= ENB_FAST_REARBITRATE | IMMEDIATE | DONT_SPLIT_AHB_WR;
+
+       if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA11 &&
+               tegra_revision == TEGRA_REVISION_A02)
+               val |= WR_WAIT_COMMIT_ON_1K;
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+       val |= WR_WAIT_COMMIT_ON_1K | EN_USB_WAIT_COMMIT_ON_1K_STALL;
+#endif
        gizmo_writel(val, AHB_GIZMO_AHB_MEM);
 
        val = gizmo_readl(AHB_GIZMO_USB);
@@ -603,13 +725,6 @@ static void __init tegra_init_ahb_gizmo_settings(void)
        val |= IMMEDIATE;
        gizmo_writel(val, AHB_GIZMO_USB3);
 
-#if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
-       val = gizmo_readl(AHB_GIZMO_SE);
-       val |= IMMEDIATE;
-       gizmo_writel(val, AHB_GIZMO_SE);
-#endif
-
-
        val = gizmo_readl(AHB_ARBITRATION_PRIORITY_CTRL);
        val |= PRIORITY_SELECT_USB | PRIORITY_SELECT_USB2 | PRIORITY_SELECT_USB3
                                | AHB_PRIORITY_WEIGHT(7);
@@ -696,7 +811,6 @@ void __init tegra20_init_early(void)
        tegra_init_power();
        tegra_init_ahb_gizmo_settings();
        tegra_init_debug_uart_rate();
-       tegra_gpio_resume_init();
        tegra_ram_console_debug_reserve(SZ_1M);
 }
 #endif
@@ -743,7 +857,6 @@ void __init tegra30_init_early(void)
        tegra_init_power();
        tegra_init_ahb_gizmo_settings();
        tegra_init_debug_uart_rate();
-       tegra_gpio_resume_init();
        tegra_ram_console_debug_reserve(SZ_1M);
 
        init_dma_coherent_pool_size(SZ_1M);
@@ -774,11 +887,34 @@ void __init tegra11x_init_early(void)
        tegra_init_power();
        tegra_init_ahb_gizmo_settings();
        tegra_init_debug_uart_rate();
-       tegra_gpio_resume_init();
 
        init_dma_coherent_pool_size(SZ_2M);
 }
 #endif
+#ifdef CONFIG_ARCH_TEGRA_12x_SOC
+void __init tegra12x_init_early(void)
+{
+#ifndef CONFIG_SMP
+       /* For SMP system, initializing the reset handler here is too
+          late. For non-SMP systems, the function that calls the reset
+          handler initializer is not called, so do it here for non-SMP. */
+       tegra_cpu_reset_handler_init();
+#endif
+       tegra_apb_io_init();
+       tegra_init_fuse();
+       tegra_ramrepair_init();
+       tegra12x_init_clocks();
+       tegra12x_init_dvfs();
+       tegra_common_init_clock();
+       tegra_clk_init_from_table(tegra12x_clk_init_table);
+       tegra_init_cache(true);
+       tegra_pmc_init();
+       tegra_powergate_init();
+       tegra_init_power();
+       tegra_init_ahb_gizmo_settings();
+       tegra_init_debug_uart_rate();
+}
+#endif
 #ifdef CONFIG_ARCH_TEGRA_14x_SOC
 void __init tegra14x_init_early(void)
 {
@@ -812,7 +948,6 @@ void __init tegra14x_init_early(void)
        tegra_init_power();
        tegra_init_ahb_gizmo_settings();
        tegra_init_debug_uart_rate();
-       tegra_gpio_resume_init();
        tegra_ram_console_debug_reserve(SZ_1M);
 }
 #endif
@@ -832,6 +967,22 @@ static int __init tegra_lp0_vec_arg(char *options)
 }
 early_param("lp0_vec", tegra_lp0_vec_arg);
 
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+static int __init tegra_wb0_params_arg(char *options)
+{
+       char *p = options;
+
+       tegra_wb0_params_address = memparse(p, &p);
+       if (*p == ',')
+               tegra_wb0_params_instances = memparse(p+1, &p);
+       if (*p == ',')
+               tegra_wb0_params_block_size = memparse(p+1, &p);
+
+       return 0;
+}
+early_param("wb0_params", tegra_wb0_params_arg);
+#endif
+
 #ifdef CONFIG_TEGRA_NVDUMPER
 static int __init tegra_nvdumper_arg(char *options)
 {
@@ -851,8 +1002,8 @@ static int __init tegra_bootloader_fb_arg(char *options)
        if (*p == '@')
                tegra_bootloader_fb_start = memparse(p+1, &p);
 
-       pr_info("Found tegra_fbmem: %08lx@%08lx\n",
-               tegra_bootloader_fb_size, tegra_bootloader_fb_start);
+       pr_info("Found tegra_fbmem: %08llx@%08llx\n",
+               (u64)tegra_bootloader_fb_size, (u64)tegra_bootloader_fb_start);
 
        return 0;
 }
@@ -866,8 +1017,9 @@ static int __init tegra_bootloader_fb2_arg(char *options)
        if (*p == '@')
                tegra_bootloader_fb2_start = memparse(p+1, &p);
 
-       pr_info("Found tegra_fbmem2: %08lx@%08lx\n",
-               tegra_bootloader_fb2_size, tegra_bootloader_fb2_start);
+       pr_info("Found tegra_fbmem2: %08llx@%08llx\n",
+               (u64)tegra_bootloader_fb2_size,
+               (u64)tegra_bootloader_fb2_start);
 
        return 0;
 }
@@ -895,8 +1047,8 @@ static int __init tegra_vpr_arg(char *options)
        tegra_vpr_size = memparse(p, &p);
        if (*p == '@')
                tegra_vpr_start = memparse(p+1, &p);
-       pr_info("Found vpr, start=0x%lx size=%lx",
-               tegra_vpr_start, tegra_vpr_size);
+       pr_info("Found vpr, start=0x%llx size=%llx",
+               (u64)tegra_vpr_start, (u64)tegra_vpr_size);
        return 0;
 }
 early_param("vpr", tegra_vpr_arg);
@@ -908,8 +1060,8 @@ static int __init tegra_tsec_arg(char *options)
        tegra_tsec_size = memparse(p, &p);
        if (*p == '@')
                tegra_tsec_start = memparse(p+1, &p);
-       pr_info("Found tsec, start=0x%lx size=%lx",
-               tegra_tsec_start, tegra_tsec_size);
+       pr_info("Found tsec, start=0x%llx size=%llx",
+               (u64)tegra_tsec_start, (u64)tegra_tsec_size);
        return 0;
 }
 early_param("tsec", tegra_tsec_arg);
@@ -973,18 +1125,23 @@ static int __init tegra_board_panel_id(char *options)
 }
 __setup("display_panel=", tegra_board_panel_id);
 
-int tegra_get_touch_id(void)
+int tegra_get_touch_vendor_id(void)
+{
+       return touch_vendor_id;
+}
+int tegra_get_touch_panel_id(void)
 {
-       return touch_id;
+       return touch_panel_id;
 }
 static int __init tegra_touch_id(char *options)
 {
        char *p = options;
-       touch_id = memparse(p, &p);
-       return touch_id;
+       touch_vendor_id = memparse(p, &p);
+       if (*p == '@')
+               touch_panel_id = memparse(p+1, &p);
+       return 1;
 }
-__setup("touch_type=", tegra_touch_id);
-
+__setup("touch_id=", tegra_touch_id);
 
 u8 get_power_config(void)
 {
@@ -1222,16 +1379,30 @@ void tegra_get_board_info(struct board_info *bi)
                        pr_err("failed to read /chosen/board_info/minor_revision\n");
                else
                        bi->minor_revision = prop_val;
+#ifndef CONFIG_ARM64
                system_serial_high = (bi->board_id << 16) | bi->sku;
                system_serial_low = (bi->fab << 24) |
                        (bi->major_revision << 16) | (bi->minor_revision << 8);
+#endif
        } else {
 #endif
+#ifdef CONFIG_ARM64
+               /* FIXME:
+                * use dummy values for now as system_serial_high/low
+                * are gone in arm64.
+                */
+               bi->board_id = 0xDEAD;
+               bi->sku = 0xDEAD;
+               bi->fab = 0xDD;
+               bi->major_revision = 0xDD;
+               bi->minor_revision = 0xDD;
+#else
                bi->board_id = (system_serial_high >> 16) & 0xFFFF;
                bi->sku = (system_serial_high) & 0xFFFF;
                bi->fab = (system_serial_low >> 24) & 0xFF;
                bi->major_revision = (system_serial_low >> 16) & 0xFF;
                bi->minor_revision = (system_serial_low >> 8) & 0xFF;
+#endif
 #ifdef CONFIG_OF
        }
 #endif
@@ -1448,13 +1619,14 @@ void __init tegra_protected_aperture_init(unsigned long aperture)
  * the memory map.
  */
 void __tegra_move_framebuffer(struct platform_device *pdev,
-       unsigned long to, unsigned long from,
-       unsigned long size)
+       phys_addr_t to, phys_addr_t from,
+       size_t size)
 {
        struct page *page;
        void __iomem *to_io;
        void *from_virt;
-       unsigned long i, addr[] = { to, from, };
+       unsigned long i;
+       phys_addr_t addr[] = { to, from, };
 
        BUG_ON(PAGE_ALIGN((unsigned long)to) != (unsigned long)to);
        BUG_ON(PAGE_ALIGN(from) != from);
@@ -1466,14 +1638,14 @@ void __tegra_move_framebuffer(struct platform_device *pdev,
                return;
        }
 
-       if (pfn_valid(page_to_pfn(phys_to_page(from)))) {
+       if (from && pfn_valid(page_to_pfn(phys_to_page(from)))) {
                for (i = 0 ; i < size; i += PAGE_SIZE) {
                        page = phys_to_page(from + i);
                        from_virt = kmap(page);
                        memcpy(to_io + i, from_virt, PAGE_SIZE);
                        kunmap(page);
                }
-       } else {
+       } else if (from) {
                void __iomem *from_io = ioremap(from, size);
                if (!from_io) {
                        pr_err("%s: Failed to map source framebuffer\n",
@@ -1490,8 +1662,12 @@ void __tegra_move_framebuffer(struct platform_device *pdev,
        if (!pdev)
                goto out;
 
+#ifdef CONFIG_ARM64
+       BUG(); /* ARM64 doesn't support dma_map_linear yet!!! */
+#else
        for (i = 0; i < ARRAY_SIZE(addr); i++)
                dma_map_linear(&pdev->dev, addr[i], size, DMA_TO_DEVICE);
+#endif
 out:
        iounmap(to_io);
 }
@@ -1522,7 +1698,9 @@ void __tegra_clear_framebuffer(struct platform_device *pdev,
        if (!pdev)
                goto out;
 
+#ifndef CONFIG_ARM64 /* FIXME */
        dma_map_linear(&pdev->dev, to, size, DMA_TO_DEVICE);
+#endif
 out:
        iounmap(to_io);
 }
@@ -1531,16 +1709,45 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
        unsigned long fb2_size)
 {
        const size_t avp_kernel_reserve = SZ_32M;
+       int i = 0;
 #if !defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */ && \
        !defined(CONFIG_TEGRA_AVP_KERNEL_ON_SMMU) /* Tegra3 & up with SMMU */
        /* Reserve hardcoded AVP kernel load area starting at 0xXe000000*/
-       tegra_avp_kernel_size = SZ_1M;
-       tegra_avp_kernel_start = memblock_end_of_DRAM() - avp_kernel_reserve;
+       tegra_avp_kernel_size = SECTION_SIZE;
+
+       /*
+        * Choose a DRAM region in which to allocate the AVP kernel, using the
+        * following guidelines:
+        *     - Choose a DRAM region which exists below the 4 GB physical
+        *       address limit. This is necessary because AVP is a 32 bit
+        *       processor and it cannot access physical addresses above 4 GB.
+        *     - Out of the applicable DRAM regions (i.e. those which exist
+        *       below 4 GB), choose the region with the highest starting
+        *       physical address.
+        */
+       for (i = memblock.memory.cnt - 1; i >= 0; i--) {
+               if ((u64)(memblock.memory.regions[i].base) +
+                       (u64)(memblock.memory.regions[i].size) <
+                       (u64)(SZ_2G)*(u64)(2)) {
+                       tegra_avp_kernel_start =
+                               memblock.memory.regions[i].base +
+                               memblock.memory.regions[i].size -
+                               avp_kernel_reserve;
+                       break;
+               }
+       }
+       /*
+        * If tegra_avp_kernel_start is still 0, that means we didn't find any
+        * DRAM region below the 4 GB physical address limit. This is a problem
+        * because the AVP kernel must reside below 4 GB.
+        */
+       BUG_ON(tegra_avp_kernel_start == 0);
+
        if (memblock_remove(tegra_avp_kernel_start, avp_kernel_reserve)) {
-               pr_err("Failed to remove AVP kernel load area %08lx@%08lx "
+               pr_err("Failed to remove AVP kernel load area %08lx@%08llx "
                                "from memory map\n",
                        (unsigned long)avp_kernel_reserve,
-                       tegra_avp_kernel_start);
+                       (u64)tegra_avp_kernel_start);
                tegra_avp_kernel_size = 0;
        }
 #endif
@@ -1548,9 +1755,9 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
        if (carveout_size) {
                tegra_carveout_start = memblock_end_of_DRAM() - carveout_size;
                if (memblock_remove(tegra_carveout_start, carveout_size)) {
-                       pr_err("Failed to remove carveout %08lx@%08lx "
+                       pr_err("Failed to remove carveout %08lx@%08llx "
                                "from memory map\n",
-                               carveout_size, tegra_carveout_start);
+                               carveout_size, (u64)tegra_carveout_start);
                        tegra_carveout_start = 0;
                        tegra_carveout_size = 0;
                } else
@@ -1561,8 +1768,8 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
                tegra_fb2_start = memblock_end_of_DRAM() - fb2_size;
                if (memblock_remove(tegra_fb2_start, fb2_size)) {
                        pr_err("Failed to remove second framebuffer "
-                               "%08lx@%08lx from memory map\n",
-                               fb2_size, tegra_fb2_start);
+                               "%08lx@%08llx from memory map\n",
+                               fb2_size, (u64)tegra_fb2_start);
                        tegra_fb2_start = 0;
                        tegra_fb2_size = 0;
                } else
@@ -1572,15 +1779,91 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
        if (fb_size) {
                tegra_fb_start = memblock_end_of_DRAM() - fb_size;
                if (memblock_remove(tegra_fb_start, fb_size)) {
-                       pr_err("Failed to remove framebuffer %08lx@%08lx "
+                       pr_err("Failed to remove framebuffer %08lx@%08llx "
                                "from memory map\n",
-                               fb_size, tegra_fb_start);
+                               fb_size, (u64)tegra_fb_start);
                        tegra_fb_start = 0;
                        tegra_fb_size = 0;
                } else
                        tegra_fb_size = fb_size;
        }
 
+#ifdef CONFIG_TEGRA_SIMULATION_SPLIT_MEM
+       if (tegra_split_mem_active()) {
+               tegra_fb_start = TEGRA_ASIM_QT_FB_START;
+               tegra_fb_size = TEGRA_ASIM_QT_FB_SIZE;
+
+               if (tegra_vpr_size == 0) {
+                       tegra_carveout_start =
+                               TEGRA_ASIM_QT_CARVEOUT_VPR_DISABLED_START;
+                       tegra_carveout_size =
+                               TEGRA_ASIM_QT_CARVEOUT_VPR_DISABLED_SIZE;
+               } else if (
+                       (tegra_vpr_start <
+                               TEGRA_ASIM_QT_FB_START +
+                               TEGRA_ASIM_QT_FB_SIZE) ||
+                       (tegra_vpr_start + tegra_vpr_size - 1 >
+                               TEGRA_ASIM_QT_FRONT_DOOR_MEM_START +
+                               TEGRA_ASIM_QT_FRONT_DOOR_MEM_SIZE - 1)) {
+                       /*
+                        * On ASIM/ASIM + QT with
+                        * CONFIG_TEGRA_SIMULATION_SPLIT_MEM enabled, the VPR
+                        * region needs to be within the front door memory
+                        * region. Moreover, the VPR region can't exist where
+                        * the framebuffer resides.
+                        */
+                       BUG();
+               } else if (
+                       (tegra_vpr_start -
+                       (TEGRA_ASIM_QT_FB_START +
+                       TEGRA_ASIM_QT_FB_SIZE) <
+                               TEGRA_ASIM_QT_CARVEOUT_MIN_SIZE) &&
+                       (TEGRA_ASIM_QT_FRONT_DOOR_MEM_START +
+                       TEGRA_ASIM_QT_FRONT_DOOR_MEM_SIZE -
+                       (tegra_vpr_start + tegra_vpr_size) <
+                               TEGRA_ASIM_QT_CARVEOUT_MIN_SIZE)) {
+                       /*
+                        * The tegra ASIM/QT carveout has a min size:-
+                        * TEGRA_ASIM_QT_CARVEOUT_MIN_SIZE. All free regions in
+                        * front door mem are smaller than the min carveout
+                        * size. Therefore, we can't fit the carveout in front
+                        * door mem.
+                        */
+                       BUG();
+               } else if (
+                       (tegra_vpr_start -
+                       (TEGRA_ASIM_QT_FB_START + TEGRA_ASIM_QT_FB_SIZE)) >=
+                       (TEGRA_ASIM_QT_FRONT_DOOR_MEM_START +
+                       TEGRA_ASIM_QT_FRONT_DOOR_MEM_SIZE -
+                       (tegra_vpr_start + tegra_vpr_size))) {
+                       /*
+                        * Place the tegra ASIM/QT carveout between the
+                        * framebuffer and VPR.
+                        */
+                       tegra_carveout_start =
+                               TEGRA_ASIM_QT_CARVEOUT_VPR_DISABLED_START;
+                       tegra_carveout_size = tegra_vpr_start -
+                                               (TEGRA_ASIM_QT_FB_START +
+                                               TEGRA_ASIM_QT_FB_SIZE);
+               } else {
+                       /*
+                        * Place the tegra ASIM/QT carveout after VPR.
+                        */
+                       tegra_carveout_start = tegra_vpr_start + tegra_vpr_size;
+                       tegra_carveout_size =
+                                       TEGRA_ASIM_QT_FRONT_DOOR_MEM_START +
+                                       TEGRA_ASIM_QT_FRONT_DOOR_MEM_SIZE -
+                                       (tegra_vpr_start + tegra_vpr_size);
+               }
+       } else if (tegra_vpr_size != 0) {
+               /*
+                * VPR cannot work on ASIM/ASIM + QT if split mem is not
+                * enabled.
+                */
+               BUG();
+       }
+#endif
+
        if (tegra_fb_size)
                tegra_grhost_aperture = tegra_fb_start;
 
@@ -1593,8 +1876,9 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
        if (tegra_lp0_vec_size &&
           (tegra_lp0_vec_start < memblock_end_of_DRAM())) {
                if (memblock_reserve(tegra_lp0_vec_start, tegra_lp0_vec_size)) {
-                       pr_err("Failed to reserve lp0_vec %08lx@%08lx\n",
-                               tegra_lp0_vec_size, tegra_lp0_vec_start);
+                       pr_err("Failed to reserve lp0_vec %08llx@%08llx\n",
+                               (u64)tegra_lp0_vec_size,
+                               (u64)tegra_lp0_vec_start);
                        tegra_lp0_vec_start = 0;
                        tegra_lp0_vec_size = 0;
                }
@@ -1633,8 +1917,9 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
                if (memblock_reserve(tegra_bootloader_fb_start,
                                tegra_bootloader_fb_size)) {
                        pr_err("Failed to reserve bootloader frame buffer "
-                               "%08lx@%08lx\n", tegra_bootloader_fb_size,
-                               tegra_bootloader_fb_start);
+                               "%08llx@%08llx\n",
+                               (u64)tegra_bootloader_fb_size,
+                               (u64)tegra_bootloader_fb_start);
                        tegra_bootloader_fb_start = 0;
                        tegra_bootloader_fb_size = 0;
                }
@@ -1645,47 +1930,49 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
                                PAGE_ALIGN(tegra_bootloader_fb2_size);
                if (memblock_reserve(tegra_bootloader_fb2_start,
                                tegra_bootloader_fb2_size)) {
-                       pr_err("Failed to reserve bootloader fb2 %08lx@%08lx\n",
-                               tegra_bootloader_fb2_size,
-                               tegra_bootloader_fb2_start);
+                       pr_err("Failed to reserve bootloader fb2 %08llx@%08llx\n",
+                               (u64)tegra_bootloader_fb2_size,
+                               (u64)tegra_bootloader_fb2_start);
                        tegra_bootloader_fb2_start = 0;
                        tegra_bootloader_fb2_size = 0;
                }
        }
 
        pr_info("Tegra reserved memory:\n"
-               "LP0:                    %08lx - %08lx\n"
-               "Bootloader framebuffer: %08lx - %08lx\n"
-               "Bootloader framebuffer2: %08lx - %08lx\n"
-               "Framebuffer:            %08lx - %08lx\n"
-               "2nd Framebuffer:        %08lx - %08lx\n"
-               "Carveout:               %08lx - %08lx\n"
-               "Vpr:                    %08lx - %08lx\n"
-               "Tsec:                   %08lx - %08lx\n",
-               tegra_lp0_vec_start,
-               tegra_lp0_vec_size ?
-                       tegra_lp0_vec_start + tegra_lp0_vec_size - 1 : 0,
-               tegra_bootloader_fb_start,
-               tegra_bootloader_fb_size ?
-                tegra_bootloader_fb_start + tegra_bootloader_fb_size - 1 : 0,
-               tegra_bootloader_fb2_start,
-               tegra_bootloader_fb2_size ?
-                tegra_bootloader_fb2_start + tegra_bootloader_fb2_size - 1 : 0,
-               tegra_fb_start,
-               tegra_fb_size ?
-                       tegra_fb_start + tegra_fb_size - 1 : 0,
-               tegra_fb2_start,
-               tegra_fb2_size ?
-                       tegra_fb2_start + tegra_fb2_size - 1 : 0,
-               tegra_carveout_start,
-               tegra_carveout_size ?
-                       tegra_carveout_start + tegra_carveout_size - 1 : 0,
-               tegra_vpr_start,
-               tegra_vpr_size ?
-                       tegra_vpr_start + tegra_vpr_size - 1 : 0,
-               tegra_tsec_start,
-               tegra_tsec_size ?
-               tegra_tsec_start + tegra_tsec_size - 1 : 0);
+               "LP0:                    %08llx - %08llx\n"
+               "Bootloader framebuffer: %08llx - %08llx\n"
+               "Bootloader framebuffer2: %08llx - %08llx\n"
+               "Framebuffer:            %08llx - %08llx\n"
+               "2nd Framebuffer:        %08llx - %08llx\n"
+               "Carveout:               %08llx - %08llx\n"
+               "Vpr:                    %08llx - %08llx\n"
+               "Tsec:                   %08llx - %08llx\n",
+               (u64)tegra_lp0_vec_start,
+               (u64)(tegra_lp0_vec_size ?
+                       tegra_lp0_vec_start + tegra_lp0_vec_size - 1 : 0),
+               (u64)tegra_bootloader_fb_start,
+               (u64)(tegra_bootloader_fb_size ?
+                       tegra_bootloader_fb_start +
+                       tegra_bootloader_fb_size - 1 : 0),
+               (u64)tegra_bootloader_fb2_start,
+               (u64)(tegra_bootloader_fb2_size ?
+                       tegra_bootloader_fb2_start +
+                       tegra_bootloader_fb2_size - 1 : 0),
+               (u64)tegra_fb_start,
+               (u64)(tegra_fb_size ?
+                       tegra_fb_start + tegra_fb_size - 1 : 0),
+               (u64)tegra_fb2_start,
+               (u64)(tegra_fb2_size ?
+                       tegra_fb2_start + tegra_fb2_size - 1 : 0),
+               (u64)tegra_carveout_start,
+               (u64)(tegra_carveout_size ?
+                       tegra_carveout_start + tegra_carveout_size - 1 : 0),
+               (u64)tegra_vpr_start,
+               (u64)(tegra_vpr_size ?
+                       tegra_vpr_start + tegra_vpr_size - 1 : 0),
+               (u64)tegra_tsec_start,
+               (u64)(tegra_tsec_size ?
+                       tegra_tsec_start + tegra_tsec_size - 1 : 0));
 
        if (tegra_avp_kernel_size) {
                /* Return excessive memory reserved for AVP kernel */
@@ -1693,10 +1980,16 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
                        memblock_add(
                                tegra_avp_kernel_start + tegra_avp_kernel_size,
                                avp_kernel_reserve - tegra_avp_kernel_size);
+               /* The AVP kernel should be loaded below the 4 GB physical
+                  address limit. */
+               BUG_ON((u64)(tegra_avp_kernel_start) +
+                       (u64)(tegra_avp_kernel_size) - (u64)(1) >=
+                       (u64)(SZ_2G)*(u64)(2));
                pr_info(
-               "AVP kernel: %08lx - %08lx\n",
-                       tegra_avp_kernel_start,
-                       tegra_avp_kernel_start + tegra_avp_kernel_size - 1);
+               "AVP kernel: %08llx - %08llx\n",
+                       (u64)tegra_avp_kernel_start,
+                       (u64)(tegra_avp_kernel_start +
+                               tegra_avp_kernel_size - 1));
        }
 
 #ifdef CONFIG_TEGRA_NVDUMPER
@@ -1918,14 +2211,66 @@ static struct platform_device tegra_asim_smc91x_device = {
        .resource       = tegra_asim_smc91x_resources,
 };
 
-static int __init asim_enet_init(void)
+static int __init asim_enet_smc91x_init(void)
 {
-       if (tegra_cpu_is_asim())
+       if (tegra_cpu_is_asim() && !tegra_cpu_is_dsim())
                platform_device_register(&tegra_asim_smc91x_device);
        return 0;
 }
 
-rootfs_initcall(asim_enet_init);
+rootfs_initcall(asim_enet_smc91x_init);
 #endif
 
+#if defined(CONFIG_SMSC911X)
+static struct resource tegra_smsc911x_resources[] = {
+       [0] = {
+               .start          = 0x4E000000,
+               .end            = 0x4E000000 + SZ_64K - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start          = IRQ_ETH,
+               .end            = IRQ_ETH,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct smsc911x_platform_config tegra_smsc911x_config = {
+       .flags          = SMSC911X_USE_32BIT,
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+       .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
+       .phy_interface  = PHY_INTERFACE_MODE_MII,
+};
+
+static struct platform_device tegra_smsc911x_device = {
+       .name              = "smsc911x",
+       .id                = 0,
+       .resource          = tegra_smsc911x_resources,
+       .num_resources     = ARRAY_SIZE(tegra_smsc911x_resources),
+       .dev.platform_data = &tegra_smsc911x_config,
+};
+
+static int __init enet_smsc911x_init(void)
+{
+       if (!tegra_cpu_is_dsim())
+               platform_device_register(&tegra_smsc911x_device);
+       return 0;
+}
+
+rootfs_initcall(enet_smsc911x_init);
+#endif
+
+#ifdef CONFIG_TEGRA_SIMULATION_SPLIT_MEM
+int tegra_split_mem_active(void)
+{
+       return tegra_split_mem_set;
+}
+
+static int __init set_tegra_split_mem(char *options)
+{
+       tegra_split_mem_set = 1;
+       return 0;
+}
+early_param("tegra_split_mem", set_tegra_split_mem);
+#endif
 #endif