+ return SZ_512M;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Determine the amount of usable RAM below 4GiB, taking into account any
+ * carve-out that may be assigned.
+ */
+static ulong usable_ram_size_below_4g(void)
+{
+ ulong total_size_below_4g;
+ ulong usable_size_below_4g;
+
+ /*
+ * The total size of RAM below 4GiB is the lesser address of:
+ * (a) 2GiB itself (RAM starts at 2GiB, and 4GiB - 2GiB == 2GiB).
+ * (b) The size RAM physically present in the system.
+ */
+ if (gd->ram_size < SZ_2G)
+ total_size_below_4g = gd->ram_size;
+ else
+ total_size_below_4g = SZ_2G;
+
+ /* Calculate usable RAM by subtracting out any carve-out size */
+ usable_size_below_4g = total_size_below_4g - carveout_size();
+
+ return usable_size_below_4g;
+}
+
+/*
+ * Represent all available RAM in either one or two banks.
+ *
+ * The first bank describes any usable RAM below 4GiB.
+ * The second bank describes any RAM above 4GiB.
+ *
+ * This split is driven by the following requirements:
+ * - The NVIDIA L4T kernel requires separate entries in the DT /memory/reg
+ * property for memory below and above the 4GiB boundary. The layout of that
+ * DT property is directly driven by the entries in the U-Boot bank array.
+ * - The potential existence of a carve-out at the end of RAM below 4GiB can
+ * only be represented using multiple banks.
+ *
+ * Explicitly removing the carve-out RAM from the bank entries makes the RAM
+ * layout a bit more obvious, e.g. when running "bdinfo" at the U-Boot
+ * command-line.
+ *
+ * This does mean that the DT U-Boot passes to the Linux kernel will not
+ * include this RAM in /memory/reg at all. An alternative would be to include
+ * all RAM in the U-Boot banks (and hence DT), and add a /memreserve/ node
+ * into DT to stop the kernel from using the RAM. IIUC, I don't /think/ the
+ * Linux kernel will ever need to access any RAM in* the carve-out via a CPU
+ * mapping, so either way is acceptable.
+ *
+ * On 32-bit systems, we never define a bank for RAM above 4GiB, since the
+ * start address of that bank cannot be represented in the 32-bit .size
+ * field.
+ */
+void dram_init_banksize(void)
+{
+ gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+ gd->bd->bi_dram[0].size = usable_ram_size_below_4g();
+
+#ifdef CONFIG_PHYS_64BIT
+ if (gd->ram_size > SZ_2G) {
+ gd->bd->bi_dram[1].start = 0x100000000;
+ gd->bd->bi_dram[1].size = gd->ram_size - SZ_2G;
+ } else
+#endif
+ {
+ gd->bd->bi_dram[1].start = 0;
+ gd->bd->bi_dram[1].size = 0;
+ }
+}
+