[PATCH] sunxi: dram: detect non-power-of-2 sized DRAM chips
    Jernej Škrabec 
    jernej.skrabec at gmail.com
       
    Thu Oct 23 23:04:52 CEST 2025
    
    
  
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 at 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 at 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;
> > > +}
> > >   
> > 
> > 
> > 
> > 
> > 
> 
> 
    
    
More information about the U-Boot
mailing list