On Fri, 13 Nov 2015 18:22:10 +0100 Jens Kuske <jensku...@gmail.com> wrote:
> On 13/11/15 13:36, Siarhei Siamashka wrote: > > On Wed, 11 Nov 2015 18:26:54 +0100 > > Jens Kuske <jensku...@gmail.com> wrote: > > > >> Based on some guessing and comparing with the parts I initially started > >> disassembling (before this SDK appeared), I think it's I20. The I20 dram > >> init code matched the disassembled parts exactly, except the ZQ > >> calibration part... > >> So, looks like it might not be correct to assume I20 == H3. > > > > The magic constants in mctl_set_master_priority() seem to be a bit > > different too. This explains why I could not find the matching code > > in the SDK. > > Indeed, didn't remember that. > > > > >> This is the ZQ calibration function I got by disassembling, but I dropped > >> it since the SDK version worked well too. Maybe I should have done the > >> opposite and drop the SDK... > > > > Agreed, it's safer to prefer the variant of code that is actually > > used in production on real devices. > > > >> It looks a bit strange, like if they are always calibrating the > >> first channel and then copying to the others, maybe there is some > >> hardware bug they work around. > >> > >> static void mctl_zq_calibration(struct dram_para *para) > >> { > >> struct sunxi_mctl_ctl_reg * const mctl_ctl = > >> (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; > >> > >> int i; > >> u16 zq_val[6]; > >> u32 reg_val, val; > >> > >> mctl_dbg("ZQ calibration... "); > >> > >> writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]); > >> > >> for (i = 0; i < 6; i++) > >> { > >> u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf; > >> > >> writel((zq << 20) | (zq << 16) | (zq << 12) | > >> (zq << 8) | (zq << 4) | (zq << 0), > >> &mctl_ctl->zqcr); > >> > >> writel(PIR_CLRSR, &mctl_ctl->pir); > >> mctl_phy_init(PIR_ZCAL); > >> > >> val = readl(&mctl_ctl->zqdr[0]) & 0xff; > >> writel((val << 24) | (val << 16) | (val << 8) | (val << 0), > >> &mctl_ctl->zqdr[2]); > >> > >> writel(PIR_CLRSR, &mctl_ctl->pir); > >> mctl_phy_init(PIR_ZCAL); > >> > >> zq_val[i] = val | > >> (bin_to_mgray(mgray_to_bin(readl(&mctl_ctl->zqdr[0]) >> 24) - 1) << 8); > >> } > >> > >> writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]); > >> writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]); > >> writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]); > >> > >> mctl_dbg((mctl_ctl->zqsr & (1 << 30)) ? "ERROR\n" : "DONE\n"); > >> } > > > > Thanks, using this implementation fixes the reliability problems at > > 672MHz on my Orange Pi PC board. > > Ok, I'll replace the SDK version then. > > > > >> And while trying to figure out what's the reason for this I used the > >> following debug function, it might help you if you want to debug ZQ cal: > >> > >> static void dump_zq(void) > >> { > >> struct sunxi_mctl_ctl_reg * const mctl_ctl = > >> (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; > >> > >> int i; > >> static const char *mod[3] = { "control", "DX0/DX1", "DX2/DX3" }; > >> static const char *error[4] = { "\t", "overflow", > >> "underflow", "in progress" }; > >> > >> printf("== ZQ calibration %s %s ==\n", > >> (mctl_ctl->zqsr & (1 << 31)) ? "DONE" : "", > >> (mctl_ctl->zqsr & (1 << 30)) ? "ERROR" : ""); > >> > >> printf("\tODT pull-up\tODT pull-down\tDRV pull-up\tDRV pull-down\n"); > >> > >> for (i = 0; i < 3; i++) > >> printf("%s\t%2u %s\t%2u %s\t%2u %s\t%2u %s\n", mod[i], > >> mgray_to_bin((mctl_ctl->zqdr[i] >> 24) & 0x1f), > >> error[(mctl_ctl->zqsr >> (i * 8 + 6)) & 0x3], > >> mgray_to_bin((mctl_ctl->zqdr[i] >> 16) & 0x1f), > >> error[(mctl_ctl->zqsr >> (i * 8 + 4)) & 0x3], > >> mgray_to_bin((mctl_ctl->zqdr[i] >> 8) & 0x1f), > >> error[(mctl_ctl->zqsr >> (i * 8 + 2)) & 0x3], > >> mgray_to_bin((mctl_ctl->zqdr[i] >> 0) & 0x1f), > >> error[(mctl_ctl->zqsr >> (i * 8 + 0)) & 0x3]); > >> } > > > > With your original code from github I get: > > > > == ZQ calibration DONE ERROR == > > ODT pull-up ODT pull-down DRV pull-up DRV pull-down > > control 16 underflow 16 12 underflow 12 > > DX0/DX1 12 underflow 12 12 underflow 12 > > DX2/DX3 12 12 12 underflow 12 > > > > With the implementation from your e-mail I get: > > > > == ZQ calibration DONE == > > ODT pull-up ODT pull-down DRV pull-up DRV pull-down > > control 20 17 15 13 > > DX0/DX1 6 5 15 13 > > DX2/DX3 6 5 15 13 > > > > That looks *much* better :) > > > > > I'm going to try running lima-memtester on the device and also will > > do a detailed review of your code by the end of the weekend. BTW, which > > boot0 binary did you use as a reference? It might help to make sure > > that we are actually looking at exactly the same thing. > > If I remember correctly the libdram came from the SDK offered at the > orange pi downloads. I roughly compared it to the preinstalled android > boot0, it looked the same but had some symbols. > But I dropped most unused codepaths and tried to cleaned up a lot of magic. Thanks for the explanations. I finally got lima-memtester up and running on H3 hardware (not that it was difficult, but just the amount of unnecessary compatibility breaks in the H3 SDK kernel was a bit unexpected and really discouraging, they are really doing almost *everything* in a different way compared to A10/A20 SDK kernel just for the sake of making things different): https://github.com/ssvb/lima-memtester/releases/tag/20151207-orange-pi-pc-fel-test Currently U-Boot v2016.01-rc2 fails the lima-memtester check unless the DRAM clock speed is reduced to 456 MHz on my Orange Pi PC. But if I use the boot0 bootloader to boot the same kernel image (uImage-3.4-sun8i-h3-lima-memtester), then the test works fine. This means that there must be still something wrong with the H3 DRAM init code in U-Boot, or maybe some clocks are wrong While the investigation is ongoing, it might be a good idea to temporarily reduce the DRAM clock speed in U-Boot as a workaround. So that people are less likely to encounter reliability problems when using U-Boot instead of boot0. There is a lot of time before the U-boot v2016.01 release, so everything should be fine. And I still owe you a review for the H3 DRAM code. -- Best regards, Siarhei Siamashka -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.