Hi,
I'm working on an OMAP L138 based product. We're facing a couple of issues related to ESD on the system very likely related to the issues discussed in Section 2.1.4 of the document linked below.
http://www.ti.com/lit/er/sprz301m/sprz301m.pdf
The document mentions a couple of suggestions for mitigation and possibly elimination of the problem but it's not clear how this should be done in code. I've tried to implement the recommendations in the Linux kernel and uboot and run into different issues in both cases. Details below:
Changes made to Linux kernel:
In the board specific init function I added the following lines of code to set the DLL REFCLK field.
#define DA8XX_DRYPC1R 0xe4
ddr_ctl_base = da8xx_get_mem_ctlr();
ddr_pcr = __raw_readl(ddr_ctl_base + DA8XX_DRPYC1R_REG);
pr_alert("### Default value of DRPYC1R: 0x%x\n", ddr_pcr);
ddr_pcr |= 0x00002000;
#if 1
__raw_writel((ddr_ctl_base + DA8XX_DRPYC1R_REG), ddr_pcr);
#endif
Without the write command, the kernel boots as expected and reads the value written to DRPYC1R by uBoot correctly. However, as soon as the write command is introduced the kernel does not boot, presumably because I'm writing to the DDR registers without unlocking them for write.
To get pass this I moved my changes over to uboot. Modified version of da850_ddr_setup() in
uboot-03.22.00.02/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c is shown below. The line of code I added is shown in bold text.
int da850_ddr_setup(void)
{
unsigned long tmp;
/* Enable the Clock to DDR2/mDDR */
lpsc_on(DAVINCI_LPSC_DDR_EMIF);
tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);
if ((tmp & VTP_POWERDWN) == VTP_POWERDWN) {
/* Begin VTP Calibration */
clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN);
clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK);
setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);
clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);
setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ);
/* Polling READY bit to see when VTP calibration is done */
tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);
while ((tmp & VTP_READY) != VTP_READY)
tmp = readl(&davinci_syscfg1_regs->vtpio_ctl);
setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK);
setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN);
setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_IOPWRDWN);
}
writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr);
clrbits_le32(&davinci_syscfg1_regs->ddr_slew,
(1 << DDR_SLEW_CMOSEN_BIT));
/*
* SDRAM Configuration Register (SDCR):
* First set the BOOTUNLOCK bit to make configuration bits
* writeable.
*/
setbits_le32(&dv_ddr2_regs_ctrl->sdbcr, DV_DDR_BOOTUNLOCK);
/*
* Write the new value of these bits and clear BOOTUNLOCK.
* At the same time, set the TIMUNLOCK bit to allow changing
* the timing registers
*/
tmp = CONFIG_SYS_DA850_DDR2_SDBCR;
tmp &= ~DV_DDR_BOOTUNLOCK;
tmp |= DV_DDR_TIMUNLOCK;
writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);
/* write memory configuration and timing */
writel(CONFIG_SYS_DA850_DDR2_SDBCR2, &dv_ddr2_regs_ctrl->sdbcr2);
writel(CONFIG_SYS_DA850_DDR2_SDTIMR, &dv_ddr2_regs_ctrl->sdtimr);
writel(CONFIG_SYS_DA850_DDR2_SDTIMR2, &dv_ddr2_regs_ctrl->sdtimr2);
/* clear the TIMUNLOCK bit and write the value of the CL field */
tmp &= ~DV_DDR_TIMUNLOCK;
writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);
/*
* LPMODEN and MCLKSTOPEN must be set!
* Without this bits set, PSC don;t switch states !!
*/
writel(CONFIG_SYS_DA850_DDR2_SDRCR |
DV_DDR_SDRCR_LPMODEN |
DV_DDR_SDRCR_MCLKSTOPEN,
&dv_ddr2_regs_ctrl->sdrcr);
/* Disable DLL REFCLK */
#if 1
setbits_le32(&dv_ddr2_regs_ctrl->ddrphycr, 0x2000 );
#endif
/* SyncReset the Clock to EMIF3A SDRAM */
lpsc_syncreset(DAVINCI_LPSC_DDR_EMIF);
/* Enable the Clock to EMIF3A SDRAM */
lpsc_on(DAVINCI_LPSC_DDR_EMIF);
/* disable self refresh */
clrbits_le32(&dv_ddr2_regs_ctrl->sdrcr, DV_DDR_SDRCR_LPMODEN | DV_DDR_SDRCR_MCLKSTOPEN);
writel(CONFIG_SYS_DA850_DDR2_PBBPR, &dv_ddr2_regs_ctrl->pbbpr);
return 0;
}
After flashing the version of uboot with the changes listed above the system fails to boot. In this case I'm assuming it's because the instruction setting the DLL Refclk bit is misplaced in the sequence.
What is the correct the way to make this change and where should this be done (kernel or uboot)? Any pointers of where this should be placed in the sequence?
Thanks,
Dinesh