* [PATCH] sunxi: dram: detect non-power-of-2 sized DRAM chips
@ 2025-10-21 23:53 Andre Przywara
2025-10-22 15:48 ` Jernej Škrabec
0 siblings, 1 reply; 4+ messages in thread
From: Andre Przywara @ 2025-10-21 23:53 UTC (permalink / raw)
To: u-boot; +Cc: Jernej Skrabec, Rudi Horn, linux-sunxi
Some boards feature an "odd" DRAM size, where the total RAM is 1.5GB or
3GB. Our existing DRAM size detection routines can only detect power-of-2
sized configuration, and on those boards the DRAM size is overestimated,
so this typically breaks the boot quite early.
There doesn't seem to be an easy explicit way to detect those odd-sized
chips, but we can test whether the later part of the memory behaves like
memory, by verifying that a written pattern can be read back.
Experiments show that there is no aliasing effect here, as all locations
in the unimplemented range always return some fixed pattern, and cannot
be changed.
Also so far all those boards use a factor of 3 of some lower power-of-2
number, or 3/4th of some higher number. The size detection routine
discovers the higher number, so we can check for some memory cells beyond
75% of the detected size to be legit.
Add a routine the inverts all bits at a given location in memory, and
reads that back to prove that the new value was stored.
Then test the memory cell at exactly 3/4th of the detected size, and cap
the size of the memory to 75% when this test fails.
This enables boards which ship with such odd memory sizes.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
Hi,
I don't really have a board with such an odd size to test that, though the
function worked on a 12GB A733 board. But that's not supporting the SPL
or any kind of DRAM init yet, so was tested out of context.
I would be grateful if anyone with a 1.5GB or 3GB board could test this.
Thanks,
Andre
arch/arm/include/asm/arch-sunxi/dram.h | 1 +
arch/arm/mach-sunxi/dram_dw_helpers.c | 16 +++++++++++++++-
arch/arm/mach-sunxi/dram_helpers.c | 12 ++++++++++++
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 0eccb1e6c28..59e2e980bfa 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -45,5 +45,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);
+bool mctl_check_memory(phys_addr_t addr);
#endif /* _SUNXI_DRAM_H */
diff --git a/arch/arm/mach-sunxi/dram_dw_helpers.c b/arch/arm/mach-sunxi/dram_dw_helpers.c
index 24767354935..14f6b24c30f 100644
--- a/arch/arm/mach-sunxi/dram_dw_helpers.c
+++ b/arch/arm/mach-sunxi/dram_dw_helpers.c
@@ -143,8 +143,22 @@ void mctl_auto_detect_dram_size(const struct dram_para *para,
unsigned long mctl_calc_size(const struct dram_config *config)
{
+ unsigned long size;
u8 width = config->bus_full_width ? 4 : 2;
/* 8 banks */
- return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
+ size = (1ULL << (config->cols + config->rows + 3)) * width *
+ config->ranks;
+
+ /*
+ * There are boards with non-power-of-2 sized DRAM chips, like 1.5GB
+ * or 3GB. They are detected as the larger power-of-2 (2GB and 4GB),
+ * so test the last quarter for being able to store values.
+ */
+ if (!mctl_check_memory(CFG_SYS_SDRAM_BASE + size / 4 * 3)) {
+ size = (size / 4) * 3;
+ debug("capping memory at %ld MB\n", size >> 20);
+ }
+
+ return size;
}
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
index 83dbe4ca98f..376b7d14f86 100644
--- a/arch/arm/mach-sunxi/dram_helpers.c
+++ b/arch/arm/mach-sunxi/dram_helpers.c
@@ -62,3 +62,15 @@ bool mctl_mem_matches(u32 offset)
return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE);
}
#endif
+
+bool mctl_check_memory(phys_addr_t addr)
+{
+ uint32_t orig, val;
+
+ orig = readl(addr);
+ writel(~orig, addr);
+ val = readl(addr);
+ writel(orig, addr);
+
+ return ~orig == val;
+}
--
2.46.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] sunxi: dram: detect non-power-of-2 sized DRAM chips
2025-10-21 23:53 [PATCH] sunxi: dram: detect non-power-of-2 sized DRAM chips Andre Przywara
@ 2025-10-22 15:48 ` Jernej Škrabec
2025-10-22 20:33 ` Andre Przywara
0 siblings, 1 reply; 4+ messages in thread
From: Jernej Škrabec @ 2025-10-22 15:48 UTC (permalink / raw)
To: u-boot, Andre Przywara; +Cc: Rudi Horn, linux-sunxi
Dne sreda, 22. oktober 2025 ob 01:53:34 Srednjeevropski poletni čas je Andre Przywara napisal(a):
> Some boards feature an "odd" DRAM size, where the total RAM is 1.5GB or
> 3GB. Our existing DRAM size detection routines can only detect power-of-2
> sized configuration, and on those boards the DRAM size is overestimated,
> so this typically breaks the boot quite early.
>
> There doesn't seem to be an easy explicit way to detect those odd-sized
> chips, but we can test whether the later part of the memory behaves like
> memory, by verifying that a written pattern can be read back.
> Experiments show that there is no aliasing effect here, as all locations
> in the unimplemented range always return some fixed pattern, and cannot
> be changed.
>
> Also so far all those boards use a factor of 3 of some lower power-of-2
> number, or 3/4th of some higher number. The size detection routine
> discovers the higher number, so we can check for some memory cells beyond
> 75% of the detected size to be legit.
>
> Add a routine the inverts all bits at a given location in memory, and
> reads that back to prove that the new value was stored.
> Then test the memory cell at exactly 3/4th of the detected size, and cap
> the size of the memory to 75% when this test fails.
>
> This enables boards which ship with such odd memory sizes.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> Hi,
>
> I don't really have a board with such an odd size to test that, though the
> function worked on a 12GB A733 board. But that's not supporting the SPL
> or any kind of DRAM init yet, so was tested out of context.
> I would be grateful if anyone with a 1.5GB or 3GB board could test this.
>
> Thanks,
> Andre
>
> arch/arm/include/asm/arch-sunxi/dram.h | 1 +
> arch/arm/mach-sunxi/dram_dw_helpers.c | 16 +++++++++++++++-
> arch/arm/mach-sunxi/dram_helpers.c | 12 ++++++++++++
> 3 files changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> index 0eccb1e6c28..59e2e980bfa 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> @@ -45,5 +45,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);
> +bool mctl_check_memory(phys_addr_t addr);
>
> #endif /* _SUNXI_DRAM_H */
> diff --git a/arch/arm/mach-sunxi/dram_dw_helpers.c b/arch/arm/mach-sunxi/dram_dw_helpers.c
> index 24767354935..14f6b24c30f 100644
> --- a/arch/arm/mach-sunxi/dram_dw_helpers.c
> +++ b/arch/arm/mach-sunxi/dram_dw_helpers.c
> @@ -143,8 +143,22 @@ void mctl_auto_detect_dram_size(const struct dram_para *para,
>
> unsigned long mctl_calc_size(const struct dram_config *config)
> {
> + unsigned long size;
> u8 width = config->bus_full_width ? 4 : 2;
>
> /* 8 banks */
> - return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
> + size = (1ULL << (config->cols + config->rows + 3)) * width *
> + config->ranks;
> +
> + /*
> + * There are boards with non-power-of-2 sized DRAM chips, like 1.5GB
> + * or 3GB. They are detected as the larger power-of-2 (2GB and 4GB),
> + * so test the last quarter for being able to store values.
> + */
> + if (!mctl_check_memory(CFG_SYS_SDRAM_BASE + size / 4 * 3)) {
> + size = (size / 4) * 3;
> + debug("capping memory at %ld MB\n", size >> 20);
As I already commented in first version of this change, wouldn't it be good to
add additional check here, just to be sure there is no misconfiguration? In such
case it would be better to panic than continue with unstable system.
Best regards,
Jernej
> + }
> +
> + return size;
> }
> diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
> index 83dbe4ca98f..376b7d14f86 100644
> --- a/arch/arm/mach-sunxi/dram_helpers.c
> +++ b/arch/arm/mach-sunxi/dram_helpers.c
> @@ -62,3 +62,15 @@ bool mctl_mem_matches(u32 offset)
> return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE);
> }
> #endif
> +
> +bool mctl_check_memory(phys_addr_t addr)
> +{
> + uint32_t orig, val;
> +
> + orig = readl(addr);
> + writel(~orig, addr);
> + val = readl(addr);
> + writel(orig, addr);
> +
> + return ~orig == val;
> +}
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] sunxi: dram: detect non-power-of-2 sized DRAM chips
2025-10-22 15:48 ` Jernej Škrabec
@ 2025-10-22 20:33 ` Andre Przywara
2025-10-23 21:04 ` Jernej Škrabec
0 siblings, 1 reply; 4+ messages in thread
From: Andre Przywara @ 2025-10-22 20:33 UTC (permalink / raw)
To: Jernej Škrabec; +Cc: u-boot, Rudi Horn, linux-sunxi
On Wed, 22 Oct 2025 17:48:27 +0200
Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
Hi Jernej,
> Dne sreda, 22. oktober 2025 ob 01:53:34 Srednjeevropski poletni čas je Andre Przywara napisal(a):
> > Some boards feature an "odd" DRAM size, where the total RAM is 1.5GB or
> > 3GB. Our existing DRAM size detection routines can only detect power-of-2
> > sized configuration, and on those boards the DRAM size is overestimated,
> > so this typically breaks the boot quite early.
> >
> > There doesn't seem to be an easy explicit way to detect those odd-sized
> > chips, but we can test whether the later part of the memory behaves like
> > memory, by verifying that a written pattern can be read back.
> > Experiments show that there is no aliasing effect here, as all locations
> > in the unimplemented range always return some fixed pattern, and cannot
> > be changed.
> >
> > Also so far all those boards use a factor of 3 of some lower power-of-2
> > number, or 3/4th of some higher number. The size detection routine
> > discovers the higher number, so we can check for some memory cells beyond
> > 75% of the detected size to be legit.
> >
> > Add a routine the inverts all bits at a given location in memory, and
> > reads that back to prove that the new value was stored.
> > Then test the memory cell at exactly 3/4th of the detected size, and cap
> > the size of the memory to 75% when this test fails.
> >
> > This enables boards which ship with such odd memory sizes.
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > Hi,
> >
> > I don't really have a board with such an odd size to test that, though the
> > function worked on a 12GB A733 board. But that's not supporting the SPL
> > or any kind of DRAM init yet, so was tested out of context.
> > I would be grateful if anyone with a 1.5GB or 3GB board could test this.
> >
> > Thanks,
> > Andre
> >
> > arch/arm/include/asm/arch-sunxi/dram.h | 1 +
> > arch/arm/mach-sunxi/dram_dw_helpers.c | 16 +++++++++++++++-
> > arch/arm/mach-sunxi/dram_helpers.c | 12 ++++++++++++
> > 3 files changed, 28 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> > index 0eccb1e6c28..59e2e980bfa 100644
> > --- a/arch/arm/include/asm/arch-sunxi/dram.h
> > +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> > @@ -45,5 +45,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);
> > +bool mctl_check_memory(phys_addr_t addr);
> >
> > #endif /* _SUNXI_DRAM_H */
> > diff --git a/arch/arm/mach-sunxi/dram_dw_helpers.c b/arch/arm/mach-sunxi/dram_dw_helpers.c
> > index 24767354935..14f6b24c30f 100644
> > --- a/arch/arm/mach-sunxi/dram_dw_helpers.c
> > +++ b/arch/arm/mach-sunxi/dram_dw_helpers.c
> > @@ -143,8 +143,22 @@ void mctl_auto_detect_dram_size(const struct dram_para *para,
> >
> > unsigned long mctl_calc_size(const struct dram_config *config)
> > {
> > + unsigned long size;
> > u8 width = config->bus_full_width ? 4 : 2;
> >
> > /* 8 banks */
> > - return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
> > + size = (1ULL << (config->cols + config->rows + 3)) * width *
> > + config->ranks;
> > +
> > + /*
> > + * There are boards with non-power-of-2 sized DRAM chips, like 1.5GB
> > + * or 3GB. They are detected as the larger power-of-2 (2GB and 4GB),
> > + * so test the last quarter for being able to store values.
> > + */
> > + if (!mctl_check_memory(CFG_SYS_SDRAM_BASE + size / 4 * 3)) {
> > + size = (size / 4) * 3;
> > + debug("capping memory at %ld MB\n", size >> 20);
>
> As I already commented in first version of this change, wouldn't it be good to
> add additional check here, just to be sure there is no misconfiguration? In such
> case it would be better to panic than continue with unstable system.
Mmmh, but what check would that be? I mean this is mctl_calc_size(),
which is only called once, just at the end, before we return from
sunxi_dram_init(). And it just calculates the size, there is no probing
anymore, this has been done earlier, elsewhere.
At this point we assume everything is fine and properly setup, so I
don't understand what additional check we should do here. If we cannot
read back what we have written, we are in deeper trouble anyway, but we
would have missed that before anyway here, and it would have crashed
sooner or later, so I don't see a problem.
Cheers,
Andre
>
> Best regards,
> Jernej
>
> > + }
> > +
> > + return size;
> > }
> > diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
> > index 83dbe4ca98f..376b7d14f86 100644
> > --- a/arch/arm/mach-sunxi/dram_helpers.c
> > +++ b/arch/arm/mach-sunxi/dram_helpers.c
> > @@ -62,3 +62,15 @@ bool mctl_mem_matches(u32 offset)
> > return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE);
> > }
> > #endif
> > +
> > +bool mctl_check_memory(phys_addr_t addr)
> > +{
> > + uint32_t orig, val;
> > +
> > + orig = readl(addr);
> > + writel(~orig, addr);
> > + val = readl(addr);
> > + writel(orig, addr);
> > +
> > + return ~orig == val;
> > +}
> >
>
>
>
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] sunxi: dram: detect non-power-of-2 sized DRAM chips
2025-10-22 20:33 ` Andre Przywara
@ 2025-10-23 21:04 ` Jernej Škrabec
0 siblings, 0 replies; 4+ messages in thread
From: Jernej Škrabec @ 2025-10-23 21:04 UTC (permalink / raw)
To: Andre Przywara; +Cc: u-boot, Rudi Horn, linux-sunxi
Dne sreda, 22. oktober 2025 ob 22:33:39 Srednjeevropski poletni čas je Andre Przywara napisal(a):
> On Wed, 22 Oct 2025 17:48:27 +0200
> Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
>
> Hi Jernej,
>
> > Dne sreda, 22. oktober 2025 ob 01:53:34 Srednjeevropski poletni čas je Andre Przywara napisal(a):
> > > Some boards feature an "odd" DRAM size, where the total RAM is 1.5GB or
> > > 3GB. Our existing DRAM size detection routines can only detect power-of-2
> > > sized configuration, and on those boards the DRAM size is overestimated,
> > > so this typically breaks the boot quite early.
> > >
> > > There doesn't seem to be an easy explicit way to detect those odd-sized
> > > chips, but we can test whether the later part of the memory behaves like
> > > memory, by verifying that a written pattern can be read back.
> > > Experiments show that there is no aliasing effect here, as all locations
> > > in the unimplemented range always return some fixed pattern, and cannot
> > > be changed.
> > >
> > > Also so far all those boards use a factor of 3 of some lower power-of-2
> > > number, or 3/4th of some higher number. The size detection routine
> > > discovers the higher number, so we can check for some memory cells beyond
> > > 75% of the detected size to be legit.
> > >
> > > Add a routine the inverts all bits at a given location in memory, and
> > > reads that back to prove that the new value was stored.
> > > Then test the memory cell at exactly 3/4th of the detected size, and cap
> > > the size of the memory to 75% when this test fails.
> > >
> > > This enables boards which ship with such odd memory sizes.
> > >
> > > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > > ---
> > > Hi,
> > >
> > > I don't really have a board with such an odd size to test that, though the
> > > function worked on a 12GB A733 board. But that's not supporting the SPL
> > > or any kind of DRAM init yet, so was tested out of context.
> > > I would be grateful if anyone with a 1.5GB or 3GB board could test this.
> > >
> > > Thanks,
> > > Andre
> > >
> > > arch/arm/include/asm/arch-sunxi/dram.h | 1 +
> > > arch/arm/mach-sunxi/dram_dw_helpers.c | 16 +++++++++++++++-
> > > arch/arm/mach-sunxi/dram_helpers.c | 12 ++++++++++++
> > > 3 files changed, 28 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> > > index 0eccb1e6c28..59e2e980bfa 100644
> > > --- a/arch/arm/include/asm/arch-sunxi/dram.h
> > > +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> > > @@ -45,5 +45,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);
> > > +bool mctl_check_memory(phys_addr_t addr);
> > >
> > > #endif /* _SUNXI_DRAM_H */
> > > diff --git a/arch/arm/mach-sunxi/dram_dw_helpers.c b/arch/arm/mach-sunxi/dram_dw_helpers.c
> > > index 24767354935..14f6b24c30f 100644
> > > --- a/arch/arm/mach-sunxi/dram_dw_helpers.c
> > > +++ b/arch/arm/mach-sunxi/dram_dw_helpers.c
> > > @@ -143,8 +143,22 @@ void mctl_auto_detect_dram_size(const struct dram_para *para,
> > >
> > > unsigned long mctl_calc_size(const struct dram_config *config)
> > > {
> > > + unsigned long size;
> > > u8 width = config->bus_full_width ? 4 : 2;
> > >
> > > /* 8 banks */
> > > - return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
> > > + size = (1ULL << (config->cols + config->rows + 3)) * width *
> > > + config->ranks;
> > > +
> > > + /*
> > > + * There are boards with non-power-of-2 sized DRAM chips, like 1.5GB
> > > + * or 3GB. They are detected as the larger power-of-2 (2GB and 4GB),
> > > + * so test the last quarter for being able to store values.
> > > + */
> > > + if (!mctl_check_memory(CFG_SYS_SDRAM_BASE + size / 4 * 3)) {
> > > + size = (size / 4) * 3;
> > > + debug("capping memory at %ld MB\n", size >> 20);
> >
> > As I already commented in first version of this change, wouldn't it be good to
> > add additional check here, just to be sure there is no misconfiguration? In such
> > case it would be better to panic than continue with unstable system.
>
> Mmmh, but what check would that be? I mean this is mctl_calc_size(),
> which is only called once, just at the end, before we return from
> sunxi_dram_init(). And it just calculates the size, there is no probing
> anymore, this has been done earlier, elsewhere.
> At this point we assume everything is fine and properly setup, so I
> don't understand what additional check we should do here. If we cannot
> read back what we have written, we are in deeper trouble anyway, but we
> would have missed that before anyway here, and it would have crashed
> sooner or later, so I don't see a problem.
My suggestion is to additionally check memory location size / 4 * 3 - 4,
which should be valid in case everything is configured properly.
Best regards,
Jernej
>
> Cheers,
> Andre
>
>
> >
> > Best regards,
> > Jernej
> >
> > > + }
> > > +
> > > + return size;
> > > }
> > > diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
> > > index 83dbe4ca98f..376b7d14f86 100644
> > > --- a/arch/arm/mach-sunxi/dram_helpers.c
> > > +++ b/arch/arm/mach-sunxi/dram_helpers.c
> > > @@ -62,3 +62,15 @@ bool mctl_mem_matches(u32 offset)
> > > return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE);
> > > }
> > > #endif
> > > +
> > > +bool mctl_check_memory(phys_addr_t addr)
> > > +{
> > > + uint32_t orig, val;
> > > +
> > > + orig = readl(addr);
> > > + writel(~orig, addr);
> > > + val = readl(addr);
> > > + writel(orig, addr);
> > > +
> > > + return ~orig == val;
> > > +}
> > >
> >
> >
> >
> >
> >
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-10-23 21:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-21 23:53 [PATCH] sunxi: dram: detect non-power-of-2 sized DRAM chips Andre Przywara
2025-10-22 15:48 ` Jernej Škrabec
2025-10-22 20:33 ` Andre Przywara
2025-10-23 21:04 ` Jernej Škrabec
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox