diff --git a/arch/arm/cpu/tegra-common/board.c b/arch/arm/cpu/tegra-common/board.c
index 433da09..a313061 100644
--- a/arch/arm/cpu/tegra-common/board.c
+++ b/arch/arm/cpu/tegra-common/board.c
@@ -9,6 +9,7 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/funcmux.h>
+#include <asm/arch/mc.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/board.h>
 #include <asm/arch-tegra/pmc.h>
@@ -27,55 +28,6 @@ enum {
 	UART_COUNT = 5,
 };
 
-#if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30) || \
-	defined(CONFIG_TEGRA114)
-/*
- * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0,
- * so we are using this value to identify memory size.
- */
-unsigned int query_sdram_size(void)
-{
-	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-	u32 reg;
-
-	reg = readl(&pmc->pmc_scratch20);
-	debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg);
-
-#if defined(CONFIG_TEGRA20)
-	/* bits 30:28 in OdmData are used for RAM size on T20  */
-	reg &= 0x70000000;
-
-	switch ((reg) >> 28) {
-	case 1:
-		return 0x10000000;	/* 256 MB */
-	case 0:
-	case 2:
-	default:
-		return 0x20000000;	/* 512 MB */
-	case 3:
-		return 0x40000000;	/* 1GB */
-	}
-#else	/* Tegra30/Tegra114 */
-	/* bits 31:28 in OdmData are used for RAM size on T30  */
-	switch ((reg) >> 28) {
-	case 0:
-	case 1:
-	default:
-		return 0x10000000;	/* 256 MB */
-	case 2:
-		return 0x20000000;	/* 512 MB */
-	case 3:
-		return 0x30000000;	/* 768 MB */
-	case 4:
-		return 0x40000000;	/* 1GB */
-	case 8:
-		return 0x7ff00000;	/* 2GB - 1MB */
-	}
-#endif
-}
-#else
-#include <asm/arch/mc.h>
-
 /* Read the RAM size directly from the memory controller */
 unsigned int query_sdram_size(void)
 {
@@ -83,12 +35,22 @@ unsigned int query_sdram_size(void)
 	u32 size_mb;
 
 	size_mb = readl(&mc->mc_emem_cfg);
+#if defined(CONFIG_TEGRA20)
+	debug("mc->mc_emem_cfg (MEM_SIZE_KB) = 0x%08x\n", size_mb);
+	size_mb = get_ram_size((void *)PHYS_SDRAM_1, size_mb * 1024);
+#else
 	debug("mc->mc_emem_cfg (MEM_SIZE_MB) = 0x%08x\n", size_mb);
+	size_mb = get_ram_size((void *)PHYS_SDRAM_1, size_mb * 1024 * 1024);
+#endif
 
-	return size_mb * 1024 * 1024;
-}
+#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114)
+	/* External memory limited to 2047 MB due to IROM/HI-VEC */
+	if (size_mb == 0x80000000) size_mb -= 0x100000;
 #endif
 
+	return size_mb;
+}
+
 int dram_init(void)
 {
 	/* We do not initialise DRAM here. We just query the size */
diff --git a/arch/arm/include/asm/arch-tegra114/mc.h b/arch/arm/include/asm/arch-tegra114/mc.h
new file mode 100644
index 0000000..044b1e0
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra114/mc.h
@@ -0,0 +1,37 @@
+/*
+ *  (C) Copyright 2014
+ *  NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _TEGRA114_MC_H_
+#define _TEGRA114_MC_H_
+
+/**
+ * Defines the memory controller registers we need/care about
+ */
+struct mc_ctlr {
+	u32 reserved0[4];			/* offset 0x00 - 0x0C */
+	u32 mc_smmu_config;			/* offset 0x10 */
+	u32 mc_smmu_tlb_config;			/* offset 0x14 */
+	u32 mc_smmu_ptc_config;			/* offset 0x18 */
+	u32 mc_smmu_ptb_asid;			/* offset 0x1C */
+	u32 mc_smmu_ptb_data;			/* offset 0x20 */
+	u32 reserved1[3];			/* offset 0x24 - 0x2C */
+	u32 mc_smmu_tlb_flush;			/* offset 0x30 */
+	u32 mc_smmu_ptc_flush;			/* offset 0x34 */
+	u32 reserved2[6];			/* offset 0x38 - 0x4C */
+	u32 mc_emem_cfg;			/* offset 0x50 */
+	u32 mc_emem_adr_cfg;			/* offset 0x54 */
+	u32 mc_emem_adr_cfg_dev0;		/* offset 0x58 */
+	u32 mc_emem_adr_cfg_dev1;		/* offset 0x5C */
+	u32 reserved3[12];			/* offset 0x60 - 0x8C */
+	u32 mc_emem_arb_reserved[28];		/* offset 0x90 - 0xFC */
+	u32 reserved4[338];			/* offset 0x100 - 0x644 */
+	u32 mc_video_protect_bom;		/* offset 0x648 */
+	u32 mc_video_protect_size_mb;		/* offset 0x64c */
+	u32 mc_video_protect_reg_ctrl;		/* offset 0x650 */
+};
+
+#endif	/* _TEGRA114_MC_H_ */
diff --git a/arch/arm/include/asm/arch-tegra114/tegra.h b/arch/arm/include/asm/arch-tegra114/tegra.h
index 5d426b5..c3d061e 100644
--- a/arch/arm/include/asm/arch-tegra114/tegra.h
+++ b/arch/arm/include/asm/arch-tegra114/tegra.h
@@ -19,6 +19,7 @@
 
 #define NV_PA_SDRAM_BASE	0x80000000	/* 0x80000000 for real T114 */
 #define NV_PA_TSC_BASE		0x700F0000	/* System Counter TSC regs */
+#define NV_PA_MC_BASE		0x70019000
 
 #include <asm/arch-tegra/tegra.h>
 
diff --git a/arch/arm/include/asm/arch-tegra20/mc.h b/arch/arm/include/asm/arch-tegra20/mc.h
new file mode 100644
index 0000000..9c6e3ff
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra20/mc.h
@@ -0,0 +1,36 @@
+/*
+ *  (C) Copyright 2014
+ *  NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _TEGRA20_MC_H_
+#define _TEGRA20_MC_H_
+
+/**
+ * Defines the memory controller registers we need/care about
+ */
+struct mc_ctlr {
+	u32 reserved0[3];			/* offset 0x00 - 0x08 */
+	u32 mc_emem_cfg;			/* offset 0x0C */
+	u32 mc_emem_adr_cfg;			/* offset 0x10 */
+	u32 mc_emem_arb_cfg0;			/* offset 0x14 */
+	u32 mc_emem_arb_cfg1;			/* offset 0x18 */
+	u32 mc_emem_arb_cfg2;			/* offset 0x1C */
+	u32 reserved1;				/* offset 0x20 */
+	u32 mc_gart_cfg;			/* offset 0x24 */
+	u32 mc_gart_entry_addr;			/* offset 0x28 */
+	u32 mc_gart_entry_data;			/* offset 0x2C */
+	u32 mc_gart_error_req;			/* offset 0x30 */
+	u32 mc_gart_error_addr;			/* offset 0x34 */
+	u32 reserved2;				/* offset 0x38 */
+	u32 mc_timeout_ctrl;			/* offset 0x3C */
+	u32 reserved3[6];			/* offset 0x40 - 0x54 */
+	u32 mc_decerr_emem_others_status;	/* offset 0x58 */
+	u32 mc_decerr_emem_others_adr;		/* offset 0x5C */
+	u32 reserved4[40];			/* offset 0x60 - 0xFC */
+	u32 reserved5[93];			/* offset 0x100 - 0x270 */
+};
+
+#endif	/* _TEGRA20_MC_H_ */
diff --git a/arch/arm/include/asm/arch-tegra20/tegra.h b/arch/arm/include/asm/arch-tegra20/tegra.h
index 18856ac..22774ab 100644
--- a/arch/arm/include/asm/arch-tegra20/tegra.h
+++ b/arch/arm/include/asm/arch-tegra20/tegra.h
@@ -9,6 +9,7 @@
 #define _TEGRA20_H_
 
 #define NV_PA_SDRAM_BASE	0x00000000
+#define NV_PA_MC_BASE		0x7000F000
 
 #include <asm/arch-tegra/tegra.h>
 
diff --git a/arch/arm/include/asm/arch-tegra30/mc.h b/arch/arm/include/asm/arch-tegra30/mc.h
new file mode 100644
index 0000000..242a1fc
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra30/mc.h
@@ -0,0 +1,38 @@
+/*
+ *  (C) Copyright 2014
+ *  NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _TEGRA30_MC_H_
+#define _TEGRA30_MC_H_
+
+/**
+ * Defines the memory controller registers we need/care about
+ */
+struct mc_ctlr {
+	u32 reserved0[4];			/* offset 0x00 - 0x0C */
+	u32 mc_smmu_config;			/* offset 0x10 */
+	u32 mc_smmu_tlb_config;			/* offset 0x14 */
+	u32 mc_smmu_ptc_config;			/* offset 0x18 */
+	u32 mc_smmu_ptb_asid;			/* offset 0x1C */
+	u32 mc_smmu_ptb_data;			/* offset 0x20 */
+	u32 reserved1[3];			/* offset 0x24 - 0x2C */
+	u32 mc_smmu_tlb_flush;			/* offset 0x30 */
+	u32 mc_smmu_ptc_flush;			/* offset 0x34 */
+	u32 mc_smmu_asid_security;		/* offset 0x38 */
+	u32 reserved2[5];			/* offset 0x3C - 0x4C */
+	u32 mc_emem_cfg;			/* offset 0x50 */
+	u32 mc_emem_adr_cfg;			/* offset 0x54 */
+	u32 mc_emem_adr_cfg_dev0;		/* offset 0x58 */
+	u32 mc_emem_adr_cfg_dev1;		/* offset 0x5C */
+	u32 reserved3[12];			/* offset 0x60 - 0x8C */
+	u32 mc_emem_arb_reserved[28];		/* offset 0x90 - 0xFC */
+	u32 reserved4[338];			/* offset 0x100 - 0x644 */
+	u32 mc_video_protect_bom;		/* offset 0x648 */
+	u32 mc_video_protect_size_mb;		/* offset 0x64c */
+	u32 mc_video_protect_reg_ctrl;		/* offset 0x650 */
+};
+
+#endif	/* _TEGRA30_MC_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/tegra.h b/arch/arm/include/asm/arch-tegra30/tegra.h
index c02c5d8..9367179 100644
--- a/arch/arm/include/asm/arch-tegra30/tegra.h
+++ b/arch/arm/include/asm/arch-tegra30/tegra.h
@@ -17,6 +17,7 @@
 #ifndef _TEGRA30_H_
 #define _TEGRA30_H_
 
+#define NV_PA_MC_BASE		0x7000F000
 #define NV_PA_SDRAM_BASE	0x80000000	/* 0x80000000 for real T30 */
 
 #include <asm/arch-tegra/tegra.h>
