diff --git a/README b/README
index 4fee7066d5d2fa249b0657c3d4f42f8e28b3e8b0..6ea1af2678e656c9ec43c193ff797ce7c04f0686 100644
--- a/README
+++ b/README
@@ -3869,6 +3869,14 @@ Configuration Settings:
 		Scratch address used by the alternate memory test
 		You only need to set this if address zero isn't writeable
 
+- CONFIG_SYS_MEM_RESERVE_SECURE
+		If defined, the size of CONFIG_SYS_MEM_RESERVE_SECURE memory
+		is substracted from total RAM and won't be reported to OS.
+		This memory can be used as secure memory. A variable
+		gd->secure_ram is used to track the location. In systems
+		the RAM base is not zero, or RAM is divided into banks,
+		this variable needs to be recalcuated to get the address.
+
 - CONFIG_SYS_MEM_TOP_HIDE (PPC only):
 		If CONFIG_SYS_MEM_TOP_HIDE is defined in the board config header,
 		this specified memory area will get subtracted from the top
diff --git a/common/board_f.c b/common/board_f.c
index b40735438b3d9898bee90c16e1c07b12830e917e..bd5a4862480e655dc31c863141e411cf8d03fa3a 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -324,6 +324,15 @@ static int setup_dest_addr(void)
 	 * Ram is setup, size stored in gd !!
 	 */
 	debug("Ram size: %08lX\n", (ulong)gd->ram_size);
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	/* Reserve memory for secure MMU tables, and/or security monitor */
+	gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE;
+	/*
+	 * Record secure memory location. Need recalcuate if memory splits
+	 * into banks, or the ram base is not zero.
+	 */
+	gd->secure_ram = gd->ram_size;
+#endif
 #if defined(CONFIG_SYS_MEM_TOP_HIDE)
 	/*
 	 * Subtract specified amount of memory to hide so that it won't
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index adda55a26307d1620ab0e2471b46683e5eeab5c8..deed6d825558e561f90a62d0859cc8fefd21aa31 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -382,6 +382,12 @@ static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc,
 		print_num("-> size",	bd->bi_dram[i].size);
 	}
 
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+	if (gd->secure_ram & MEM_RESERVE_SECURE_SECURED) {
+		print_num("Secure ram",
+			  gd->secure_ram & MEM_RESERVE_SECURE_ADDR_MASK);
+	}
+#endif
 #if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH)
 	print_eths();
 #endif
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 1abdcaa6b7cd3f9f21affd12e941a82b7b135bbf..5d8b043f1441ed93fad348fc099c65385578a404 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -59,6 +59,20 @@ typedef struct global_data {
 
 	unsigned long relocaddr;	/* Start address of U-Boot in RAM */
 	phys_size_t ram_size;	/* RAM size */
+#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
+#define MEM_RESERVE_SECURE_SECURED	0x1
+#define MEM_RESERVE_SECURE_MAINTAINED	0x2
+#define MEM_RESERVE_SECURE_ADDR_MASK	(~0x3)
+	/*
+	 * Secure memory addr
+	 * This variable needs maintenance if the RAM base is not zero,
+	 * or if RAM splits into non-consecutive banks. It also has a
+	 * flag indicating the secure memory is marked as secure by MMU.
+	 * Flags used: 0x1 secured
+	 *             0x2 maintained
+	 */
+	phys_addr_t secure_ram;
+#endif
 	unsigned long mon_len;	/* monitor len */
 	unsigned long irq_sp;		/* irq stack pointer */
 	unsigned long start_addr_sp;	/* start_addr_stackpointer */