|
@@ -16,10 +16,12 @@
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/clk-provider.h>
|
|
|
#include <linux/of_address.h>
|
|
|
+#include <linux/of_fdt.h>
|
|
|
#include <linux/of_platform.h>
|
|
|
#include <linux/io.h>
|
|
|
#include <linux/clocksource.h>
|
|
|
#include <linux/dma-mapping.h>
|
|
|
+#include <linux/memblock.h>
|
|
|
#include <linux/mbus.h>
|
|
|
#include <linux/signal.h>
|
|
|
#include <linux/slab.h>
|
|
@@ -56,6 +58,54 @@ void __iomem *mvebu_get_scu_base(void)
|
|
|
return scu_base;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * When returning from suspend, the platform goes through the
|
|
|
+ * bootloader, which executes its DDR3 training code. This code has
|
|
|
+ * the unfortunate idea of using the first 10 KB of each DRAM bank to
|
|
|
+ * exercise the RAM and calculate the optimal timings. Therefore, this
|
|
|
+ * area of RAM is overwritten, and shouldn't be used by the kernel if
|
|
|
+ * suspend/resume is supported.
|
|
|
+ */
|
|
|
+
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+#define MVEBU_DDR_TRAINING_AREA_SZ (10 * SZ_1K)
|
|
|
+static int __init mvebu_scan_mem(unsigned long node, const char *uname,
|
|
|
+ int depth, void *data)
|
|
|
+{
|
|
|
+ const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
|
|
+ const __be32 *reg, *endp;
|
|
|
+ int l;
|
|
|
+
|
|
|
+ if (type == NULL || strcmp(type, "memory"))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
|
|
|
+ if (reg == NULL)
|
|
|
+ reg = of_get_flat_dt_prop(node, "reg", &l);
|
|
|
+ if (reg == NULL)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ endp = reg + (l / sizeof(__be32));
|
|
|
+ while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
|
|
|
+ u64 base, size;
|
|
|
+
|
|
|
+ base = dt_mem_next_cell(dt_root_addr_cells, ®);
|
|
|
+ size = dt_mem_next_cell(dt_root_size_cells, ®);
|
|
|
+
|
|
|
+ memblock_reserve(base, MVEBU_DDR_TRAINING_AREA_SZ);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void __init mvebu_memblock_reserve(void)
|
|
|
+{
|
|
|
+ of_scan_flat_dt(mvebu_scan_mem, NULL);
|
|
|
+}
|
|
|
+#else
|
|
|
+static void __init mvebu_memblock_reserve(void) {}
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* Early versions of Armada 375 SoC have a bug where the BootROM
|
|
|
* leaves an external data abort pending. The kernel is hit by this
|
|
@@ -210,6 +260,7 @@ DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)")
|
|
|
.init_machine = mvebu_dt_init,
|
|
|
.init_irq = mvebu_init_irq,
|
|
|
.restart = mvebu_restart,
|
|
|
+ .reserve = mvebu_memblock_reserve,
|
|
|
.dt_compat = armada_370_xp_dt_compat,
|
|
|
MACHINE_END
|
|
|
|