
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");
- 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)