[PATCH 1/1] sunxi: dram: Fix incorrect ram size detection for some H6 boards
Jernej Škrabec
jernej.skrabec at gmail.com
Sat Oct 21 07:48:27 CEST 2023
On Saturday, October 21, 2023 1:38:39 AM CEST Andre Przywara wrote:
> On Mon, 02 Oct 2023 20:59:34 +0200
> Jernej Škrabec <jernej.skrabec at gmail.com> wrote:
>
> Hi Jernej,
>
> > Dne ponedeljek, 02. oktober 2023 ob 14:42:40 CEST je Gunjan Gupta
napisal(a):
> > > > > bool mctl_mem_matches(u32 offset)
> > > > > {
> > > > >
> > > > > + dsb();
> > > >
> > > > This looks a bit odd, do you have an explanation for that? And are you
> > > > sure that is really needed?
> > > > I understand why we need the DSB after the writel's below, but before
> > > > that?
> > >
> > > I started with Ondrej Jirman's patch from LibreELEC's tree that had a
> > > dsb call added
> > > after the first writel call. That reduced the frequency of the errors
> > > but didn't removed
> > > it completely. My reason for moving it before the writel was to make
> > > sure any memory
> > > access is completed before starting the actual logic for the test.
> > > That reduced the
> > > frequency even further, but didn't resolve the issue. I did try
> > > removing it leaving only
> > > udelay added to the code, but that brings back the issue.
> > >
> > > > The only thing I could think of is that we are missing a barrier in
> > > > mctl_core_init() - which is the function called before
> > > > mctl_mem_matches().
> > > > Can you move that dsb(); into mctl_auto_detect_dram_size(), right
> > > > after
> > > > the mctl_core_init() call (where you add the udelay() below)? And I
> > > > wonder
> > > > if a dmb() would already be sufficient?
> > >
> > > Sure, I will try experimenting with it.
> > >
> > > > I noticed recently that the clr/setbit_le32() functions don't have a
> > > > barrier at all, maybe that should be fixed instead?
> > >
> > > I haven't done much of the low level programming myself. Mostly have
> > > done user space
> > > programming along with fixing minor kernel module compilation issues
> > > due to kernel api
> > > changes. So I wasn't sure what all places to debug. But if you point
> > > me to places with
> > > things to try, I surely can give time playing around testing the
> > > proposed fixes.> >
> > > > > @@ -623,6 +623,8 @@ static void mctl_auto_detect_dram_size(struct
> > > > > dram_para *para)> > > >
> > > > > para->cols = 11;
> > > > > mctl_core_init(para);
> > > > >
> > > > > + udelay(50);
> > > >
> > > > The location of that udelay() looks a bit odd, any chance that belongs
> > > > at
> > > > the end of mctl_channel_init() instead? And how did you come up with
> > > > that
> > > > and the value of 50? Just pure experimentation?
> > >
> > > Before adding the udelay, I added 7 print statements to print all the
> > > members of the para
> > > struct. That itself solved the issue along with the dsb added to the
> > > top of the mctl_mem_matches
> > > function. This is what gave me the clue that a delay is needed there.
> > > The value of 50 is
> > > indeed from pure experimentation
> >
> > Oh, I found one major difference between BSP and mainline driver. Please
> > test patch attached below. I don't know if this path is always taken when
> > wrong configuration is tested or not.
> >
> > Best regards,
> > Jernej
> >
> > --- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
> > +++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
> > @@ -420,6 +420,7 @@ static bool mctl_channel_init(struct dram_para *para)
> >
> > (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
> >
> > struct sunxi_mctl_phy_reg * const mctl_phy =
> >
> > (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
> >
> > + bool ret = true;
> >
> > int i;
> > u32 val;
> >
> > @@ -537,7 +538,7 @@ static bool mctl_channel_init(struct dram_para *para)
> >
> > debug("DRAM PHY DX%dRSR0 = %x\n", i,
> > readl(&mctl_phy->dx[i].rsr[0]));
> >
> > debug("Error while initializing DRAM PHY!\n");
>
> So those error messages (and the ones before them, not shown here) look
> odd: if I follow the code correctly, this here is the only place which
> makes mctl_core_init() return false. And we rely on it doing so up to
> three times, to detect the proper rank and bus width, in
> mctl_auto_detect_rank_width(). So we should not have dramatic error
> messages (even for debug), as they would occur during normal, eventually
> successful setup as well.
> So shall we tone those messages down? I'd suggest to change the
> "Oops!..." comment into something saying that we detected a wrong
> rank/bus-width setup. Also removing the pointless PLL debug print
> (since the failure is not DRAM clock related), and also the final error
> message (the last line shown here). I will make patch for that.
Those messages are remnants of old behaviour. In the past, code first
enabled dual rank and 32-bit lanes. If that failed, it analyzed error
messages and in second round only enabled supported features.
However, that proved unreliable, so I changed code so it simply tries
every combination and uses whatever works first.
In any case, I concur that these messages might not make sense anymore.
>
> But regardless I doubt that this patch is doing anything: when this
> function returns false, we set new rank/width parameters, and call
> mctl_core_init() again, which starts with mctl_sys_init() resetting all
> DRAM controller registers, which I actually wonder is really necessary.
> But surely any register setup after that point above is useless, with
> the current code.
>
> Does that make sense?
My concern is that code after failure might put controller or DRAM in
initial state which may gave more time for next round of attempts to
init DRAM properly. It may also be the reason why initial approach didn't
work reliably.
I'm fine with current approach if Gunjan confirms that initialization
works reliably.
Best regards,
Jernej
>
> Cheers,
> Andre
>
> > - return false;
> > + ret = false;
> >
> > }
> >
> > if (sunxi_dram_is_lpddr(para->type))
> >
> > @@ -553,7 +554,7 @@ static bool mctl_channel_init(struct dram_para *para)
> >
> > writel(0x7ff, &mctl_com->maer1);
> > writel(0xffff, &mctl_com->maer2);
> >
> > - return true;
> > + return ret;
> >
> > }
> >
> > static void mctl_auto_detect_rank_width(struct dram_para *para)
More information about the U-Boot
mailing list