aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2014-11-21 11:00:07 -0500
committerJason Cooper <jason@lakedaemon.net>2014-11-30 11:40:13 -0500
commit8da2b2f7ceeed931af0fc1d4fca800650bb41826 (patch)
treede3b9aa7e621117cd1c52f5b406cd2fe8167cfc5
parent8446be5d030c0d986cf90e0b395764f2c6ca443d (diff)
ARM: mvebu: reserve the first 10 KB of each memory bank for suspend/resume
When going out of suspend to RAM, the Marvell EBU platforms go through the bootloader, which re-configures the DRAM controller. To achieve this, the bootloader executes a piece of code called the "DDR3 training code". It does some reads/writes to the memory to find out the optimal timings for the memory chip being used. This has the nasty side effect that the first 10 KB of each DRAM chip-select are overwritten by the bootloader when exiting the suspend to RAM state. Therefore, this commit implements the ->reserve() hook for the 'struct machine_desc' used on Armada XP, to reserve the 10 KB of each DRAM chip-select using the memblock API. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Link: https://lkml.kernel.org/r/1416585613-2113-11-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--arch/arm/mach-mvebu/board-v7.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index 6478626e3ff6..bc52231dfd1c 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -16,10 +16,12 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/clk-provider.h> 17#include <linux/clk-provider.h>
18#include <linux/of_address.h> 18#include <linux/of_address.h>
19#include <linux/of_fdt.h>
19#include <linux/of_platform.h> 20#include <linux/of_platform.h>
20#include <linux/io.h> 21#include <linux/io.h>
21#include <linux/clocksource.h> 22#include <linux/clocksource.h>
22#include <linux/dma-mapping.h> 23#include <linux/dma-mapping.h>
24#include <linux/memblock.h>
23#include <linux/mbus.h> 25#include <linux/mbus.h>
24#include <linux/signal.h> 26#include <linux/signal.h>
25#include <linux/slab.h> 27#include <linux/slab.h>
@@ -57,6 +59,54 @@ void __iomem *mvebu_get_scu_base(void)
57} 59}
58 60
59/* 61/*
62 * When returning from suspend, the platform goes through the
63 * bootloader, which executes its DDR3 training code. This code has
64 * the unfortunate idea of using the first 10 KB of each DRAM bank to
65 * exercise the RAM and calculate the optimal timings. Therefore, this
66 * area of RAM is overwritten, and shouldn't be used by the kernel if
67 * suspend/resume is supported.
68 */
69
70#ifdef CONFIG_SUSPEND
71#define MVEBU_DDR_TRAINING_AREA_SZ (10 * SZ_1K)
72static int __init mvebu_scan_mem(unsigned long node, const char *uname,
73 int depth, void *data)
74{
75 const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
76 const __be32 *reg, *endp;
77 int l;
78
79 if (type == NULL || strcmp(type, "memory"))
80 return 0;
81
82 reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
83 if (reg == NULL)
84 reg = of_get_flat_dt_prop(node, "reg", &l);
85 if (reg == NULL)
86 return 0;
87
88 endp = reg + (l / sizeof(__be32));
89 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
90 u64 base, size;
91
92 base = dt_mem_next_cell(dt_root_addr_cells, &reg);
93 size = dt_mem_next_cell(dt_root_size_cells, &reg);
94
95 memblock_reserve(base, MVEBU_DDR_TRAINING_AREA_SZ);
96 }
97
98 return 0;
99}
100
101static void __init mvebu_memblock_reserve(void)
102{
103 of_scan_flat_dt(mvebu_scan_mem, NULL);
104}
105#else
106static void __init mvebu_memblock_reserve(void) {}
107#endif
108
109/*
60 * Early versions of Armada 375 SoC have a bug where the BootROM 110 * Early versions of Armada 375 SoC have a bug where the BootROM
61 * leaves an external data abort pending. The kernel is hit by this 111 * leaves an external data abort pending. The kernel is hit by this
62 * data abort as soon as it enters userspace, because it unmasks the 112 * data abort as soon as it enters userspace, because it unmasks the
@@ -210,6 +260,7 @@ DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)")
210 .init_machine = mvebu_dt_init, 260 .init_machine = mvebu_dt_init,
211 .init_irq = mvebu_init_irq, 261 .init_irq = mvebu_init_irq,
212 .restart = mvebu_restart, 262 .restart = mvebu_restart,
263 .reserve = mvebu_memblock_reserve,
213 .dt_compat = armada_370_xp_dt_compat, 264 .dt_compat = armada_370_xp_dt_compat,
214MACHINE_END 265MACHINE_END
215 266