[PATCH v3 0/2] sunxi: restore modified memory

Changes in v3: - reorder patches - remove casts - change commit message for 'sunxi: restore modified memory' patch
Changes in v2: - rename temporary variables - fix types for temporary variables
Andrey Skvortsov (2): sunxi: reorganize mctl_mem_matches_* functions sunxi: restore modified memory
arch/arm/include/asm/arch-sunxi/dram.h | 1 + arch/arm/mach-sunxi/dram_helpers.c | 32 +++++++++++++++++++++----- arch/arm/mach-sunxi/dram_sunxi_dw.c | 13 ----------- 3 files changed, 27 insertions(+), 19 deletions(-)

mctl_mem_matches and mctl_mem_matches_base identical functions. To avoid code duplication move them to dram_helpers and make mctl_mem_matches use generic mctl_mem_matches_base.
Signed-off-by: Andrey Skvortsov andrej.skvortzov@gmail.com --- arch/arm/include/asm/arch-sunxi/dram.h | 1 + arch/arm/mach-sunxi/dram_helpers.c | 20 ++++++++++++++------ arch/arm/mach-sunxi/dram_sunxi_dw.c | 13 ------------- 3 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h index 682daae6b1..9d21b49241 100644 --- a/arch/arm/include/asm/arch-sunxi/dram.h +++ b/arch/arm/include/asm/arch-sunxi/dram.h @@ -40,5 +40,6 @@ unsigned long sunxi_dram_init(void); void mctl_await_completion(u32 *reg, u32 mask, u32 val); bool mctl_mem_matches(u32 offset); +bool mctl_mem_matches_base(u32 offset, ulong base);
#endif /* _SUNXI_DRAM_H */ diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c index cdf2750f1c..661186b648 100644 --- a/arch/arm/mach-sunxi/dram_helpers.c +++ b/arch/arm/mach-sunxi/dram_helpers.c @@ -25,19 +25,27 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val) }
/* - * Test if memory at offset offset matches memory at begin of DRAM + * Test if memory at offset matches memory at a certain base * * Note: dsb() is not available on ARMv5 in Thumb mode */ #ifndef CONFIG_MACH_SUNIV -bool mctl_mem_matches(u32 offset) +bool mctl_mem_matches_base(u32 offset, ulong base) { /* Try to write different values to RAM at two addresses */ - writel(0, CFG_SYS_SDRAM_BASE); - writel(0xaa55aa55, (ulong)CFG_SYS_SDRAM_BASE + offset); + writel(0, base); + writel(0xaa55aa55, base + offset); dsb(); /* Check if the same value is actually observed when reading back */ - return readl(CFG_SYS_SDRAM_BASE) == - readl((ulong)CFG_SYS_SDRAM_BASE + offset); + return readl(base) == + readl(base + offset); +} + +/* + * Test if memory at offset matches memory at begin of DRAM + */ +bool mctl_mem_matches(u32 offset) +{ + return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE); } #endif diff --git a/arch/arm/mach-sunxi/dram_sunxi_dw.c b/arch/arm/mach-sunxi/dram_sunxi_dw.c index 9382d3d0be..2e8dd40b97 100644 --- a/arch/arm/mach-sunxi/dram_sunxi_dw.c +++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c @@ -652,19 +652,6 @@ static int mctl_channel_init(uint16_t socid, struct dram_para *para) return 0; }
-/* - * Test if memory at offset offset matches memory at a certain base - */ -static bool mctl_mem_matches_base(u32 offset, ulong base) -{ - /* Try to write different values to RAM at two addresses */ - writel(0, base); - writel(0xaa55aa55, base + offset); - dsb(); - /* Check if the same value is actually observed when reading back */ - return readl(base) == - readl(base + offset); -}
static void mctl_auto_detect_dram_size_rank(uint16_t socid, struct dram_para *para, ulong base, struct rank_para *rank) {

On Thu, 28 Dec 2023 00:28:42 +0300 Andrey Skvortsov andrej.skvortzov@gmail.com wrote:
Hi,
mctl_mem_matches and mctl_mem_matches_base identical functions. To avoid code duplication move them to dram_helpers and make mctl_mem_matches use generic mctl_mem_matches_base.
Signed-off-by: Andrey Skvortsov andrej.skvortzov@gmail.com
thanks for the changes, that looks good now!
Reviewed-by: Andre Przywara andre.przywara@arm.com
Merged to sunxi/master.
Cheers, Andre
arch/arm/include/asm/arch-sunxi/dram.h | 1 + arch/arm/mach-sunxi/dram_helpers.c | 20 ++++++++++++++------ arch/arm/mach-sunxi/dram_sunxi_dw.c | 13 ------------- 3 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h index 682daae6b1..9d21b49241 100644 --- a/arch/arm/include/asm/arch-sunxi/dram.h +++ b/arch/arm/include/asm/arch-sunxi/dram.h @@ -40,5 +40,6 @@ unsigned long sunxi_dram_init(void); void mctl_await_completion(u32 *reg, u32 mask, u32 val); bool mctl_mem_matches(u32 offset); +bool mctl_mem_matches_base(u32 offset, ulong base);
#endif /* _SUNXI_DRAM_H */ diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c index cdf2750f1c..661186b648 100644 --- a/arch/arm/mach-sunxi/dram_helpers.c +++ b/arch/arm/mach-sunxi/dram_helpers.c @@ -25,19 +25,27 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val) }
/*
- Test if memory at offset offset matches memory at begin of DRAM
*/
- Test if memory at offset matches memory at a certain base
- Note: dsb() is not available on ARMv5 in Thumb mode
#ifndef CONFIG_MACH_SUNIV -bool mctl_mem_matches(u32 offset) +bool mctl_mem_matches_base(u32 offset, ulong base) { /* Try to write different values to RAM at two addresses */
- writel(0, CFG_SYS_SDRAM_BASE);
- writel(0xaa55aa55, (ulong)CFG_SYS_SDRAM_BASE + offset);
- writel(0, base);
- writel(0xaa55aa55, base + offset); dsb(); /* Check if the same value is actually observed when reading back */
- return readl(CFG_SYS_SDRAM_BASE) ==
readl((ulong)CFG_SYS_SDRAM_BASE + offset);
- return readl(base) ==
readl(base + offset);
+}
+/*
- Test if memory at offset matches memory at begin of DRAM
- */
+bool mctl_mem_matches(u32 offset) +{
- return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE);
} #endif diff --git a/arch/arm/mach-sunxi/dram_sunxi_dw.c b/arch/arm/mach-sunxi/dram_sunxi_dw.c index 9382d3d0be..2e8dd40b97 100644 --- a/arch/arm/mach-sunxi/dram_sunxi_dw.c +++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c @@ -652,19 +652,6 @@ static int mctl_channel_init(uint16_t socid, struct dram_para *para) return 0; }
-/*
- Test if memory at offset offset matches memory at a certain base
- */
-static bool mctl_mem_matches_base(u32 offset, ulong base) -{
- /* Try to write different values to RAM at two addresses */
- writel(0, base);
- writel(0xaa55aa55, base + offset);
- dsb();
- /* Check if the same value is actually observed when reading back */
- return readl(base) ==
readl(base + offset);
-}
static void mctl_auto_detect_dram_size_rank(uint16_t socid, struct dram_para *para, ulong base, struct rank_para *rank) {

Current sunxi DRAM initialisation code does several test accesses to the DRAM array to detect aliasing effects and so determine the correct row/column configuration. This changes the DRAM content, which breaks use cases like soft reset and Linux's ramoops mechanism.
Fix this problem by saving and restoring the content of the DRAM cells that is used for the test writes.
Signed-off-by: Andrey Skvortsov andrej.skvortzov@gmail.com --- arch/arm/mach-sunxi/dram_helpers.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c index 661186b648..e487f87bf3 100644 --- a/arch/arm/mach-sunxi/dram_helpers.c +++ b/arch/arm/mach-sunxi/dram_helpers.c @@ -32,13 +32,25 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val) #ifndef CONFIG_MACH_SUNIV bool mctl_mem_matches_base(u32 offset, ulong base) { + u32 val_base; + u32 val_offset; + bool ret; + + /* Save original values */ + val_base = readl(base); + val_offset = readl(base + offset); + /* Try to write different values to RAM at two addresses */ writel(0, base); writel(0xaa55aa55, base + offset); dsb(); /* Check if the same value is actually observed when reading back */ - return readl(base) == - readl(base + offset); + ret = readl(base) == readl(base + offset); + + /* Restore original values */ + writel(val_base, base); + writel(val_offset, base + offset); + return ret; }
/*

On Thu, 28 Dec 2023 00:28:43 +0300 Andrey Skvortsov andrej.skvortzov@gmail.com wrote:
Current sunxi DRAM initialisation code does several test accesses to the DRAM array to detect aliasing effects and so determine the correct row/column configuration. This changes the DRAM content, which breaks use cases like soft reset and Linux's ramoops mechanism.
Fix this problem by saving and restoring the content of the DRAM cells that is used for the test writes.
Signed-off-by: Andrey Skvortsov andrej.skvortzov@gmail.com
Reviewed-by: Andre Przywara andre.przywara@arm.com
Merged to sunxi/master.
Cheers, Andre
arch/arm/mach-sunxi/dram_helpers.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c index 661186b648..e487f87bf3 100644 --- a/arch/arm/mach-sunxi/dram_helpers.c +++ b/arch/arm/mach-sunxi/dram_helpers.c @@ -32,13 +32,25 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val) #ifndef CONFIG_MACH_SUNIV bool mctl_mem_matches_base(u32 offset, ulong base) {
- u32 val_base;
- u32 val_offset;
- bool ret;
- /* Save original values */
- val_base = readl(base);
- val_offset = readl(base + offset);
- /* Try to write different values to RAM at two addresses */ writel(0, base); writel(0xaa55aa55, base + offset); dsb(); /* Check if the same value is actually observed when reading back */
- return readl(base) ==
readl(base + offset);
- ret = readl(base) == readl(base + offset);
- /* Restore original values */
- writel(val_base, base);
- writel(val_offset, base + offset);
- return ret;
}
/*
participants (2)
-
Andre Przywara
-
Andrey Skvortsov