This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

OMAP L138, DDR2 PSC config before DEEPSLEEP failed

Other Parts Discussed in Thread: DA8XX

Hello,

on a custom OMAP L138 Board we run linux.
Using DEEPSLEEP with external wakeup is not working reliable.
Very often the transition to DEEPSLEEP is working fine.
But sometimes the system is unable to go to DEEPSLEEP.

Using the internal RTC to wake up from DEEPSLEEP is showing the same
error.

We found that the systems hangs in arch/arm/mach-davinci/sleep.S
in davinci_ddr_psc_config.

In case of error
the check for Transition Complete in PTSTAT register (ptstat_done) never returns
after enabling the Power Domain Transiton Command.

Code from arch/arm/mach-davinci/sleep.S:
[...]
/*
 * Disables or Enables DDR2 LPSC
 * Register Usage:
 *     r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
 *     r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
 *     r2: contains PSC number for DDR2
 */
ENTRY(davinci_ddr_psc_config)
    /* Set next state in mdctl for DDR2 */
    mov    r6, #MDCTL
    add    r6, r6, r2, lsl #2
    ldr    ip, [r1, r6]
    bic    ip, ip, #MDSTAT_STATE_MASK
    orr    ip, ip, r0
    str    ip, [r1, r6]

    /* Enable the Power Domain Transition Command */
    ldr    ip, [r1, #PTCMD]
    orr    ip, ip, #0x1
    str    ip, [r1, #PTCMD]

    /* Check for Transition Complete (PTSTAT) */
ptstat_done:
    ldr    ip, [r1, #PTSTAT]
    and    ip, ip, #0x1
    cmp     ip, #0x0
    bne    ptstat_done

    /* Check for DDR2 clock disable completion; */
    mov    r6, #MDSTAT
    add    r6, r6, r2, lsl #2
ddr2clk_stop_done:
    ldr    ip, [r1, r6]
    and    ip, ip, #MDSTAT_STATE_MASK
    cmp    ip, r0
    bne    ddr2clk_stop_done
[...]

In the Manual spruh77a: in 9.3.2 Module State Transitions,
the first step is: wait for the GOSTAT[x] bit in PTSTAT to clear to 0.
This step is not implemented in sleep.S so we tested this with the step added.
The problem is the same.

We also replaced the "Check for Transition Complete" with a delay.
The error occoured, but in this case the freeze seems to be in the next
step ("Check for DDR2 clock disable completion").

What can prenvent the Power Domain Transition Command from completion?

Regards,

Bastian.

  • Hi,

    Using DEEPSLEEP with external wakeup is not working reliable.
    Very often the transition to DEEPSLEEP is working fine.
    But sometimes the system is unable to go to DEEPSLEEP.

    I'm not understanding from your two terms.

    I presume that the DEEPSLEEP was not reliable while putting the s/m to DS and waking up from DS(DEEPSLEEP).

    Am I right ?

    Please correct me if I'm wrong.

    Which version of SDK are you using?

    Is this your own DEEPSLEEP implementation or provided by TI ?

    Please list steps that done by you.

    We also replaced the "Check for Transition Complete" with a delay.
    The error occoured, but in this case the freeze seems to be in the next
    step ("Check for DDR2 clock disable completion").

    Please refer the gel file for PSC configurations(enable or disable or syncrst).

    /*Enable Function for PSC1*/
    PSC1_LPSC_enable(unsigned int PD, unsigned int LPSC_num) {
        unsigned int j;
    
        if( (*(unsigned int*)(PSC1_MDSTAT+4 * LPSC_num) & 0x1F) != 0x3 ) {
          *(unsigned int*) (PSC1_MDCTL+4*LPSC_num) = (*(unsigned int*) (PSC1_MDCTL+4*LPSC_num) & 0xFFFFFFE0) | 0x0003;
          PSC1_PTCMD = 0x1<<PD;
    
          j = 0;
          /*Wait for power state transition to finish*/
          while( (PSC1_PTSTAT & (0x1<<PD) ) !=0) {
            if( j++ > PSC_TIMEOUT ) {
              GEL_TextOut("\tPSC1 Enable Transition Timeout on Domain %d, LPSC %d\n","Output",1,1,1,PD,LPSC_num);
              break;
            }
          }
    
          j = 0;
          while( (*(unsigned int*)(PSC1_MDSTAT+4 * LPSC_num) & 0x1F) !=0x3) {
            if( j++ > PSC_TIMEOUT ) {
              GEL_TextOut("\tPSC1 Enable Verify Timeout on Domain %d, LPSC %d\n","Output",1,1,1,PD,LPSC_num);
              break;
            }
          }
        }
    }


    We have also code to disable the PSC through 'C'

    static int __init lpsc_control_init(void)
    	{
    
    	u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
    
    	void __iomem *psc_base;
    
    	unsigned int tmp,id,ctlr,domain;
    
    //Provide your LPSC state here;
    
    //	u32 next_state = PSC_STATE_ENABLE;
    
    //	u32 next_state = PSC_STATE_DISABLE;
    
    /	u32 next_state = PSC_STATE_SYNCRST;
    
    #if 0 /* DSP */
    	id = DA8XX_LPSC0_GEM;//15;//LPSC no (DSP)
    	ctlr = 0;//LPSC controller (PSC = 0)
    	domain = 1;//LPSC power domain (PD = 1)
    #endif
    
    
    #if 0 /* USB1 (USB1.1) */
    	id = 2;//LPSC no (USB)
    	ctlr = 1;//LPSC controller (PSC = 1)
    	domain = 0;//LPSC power domain (PD = 0)
    #endif
    
    
    #if 1 /* DDR2/mDDR */
    	id = 6;//LPSC no (USB)
    	ctlr = 1;//LPSC controller (PSC = 1)
    	domain = 0;//LPSC power domain (PD = 0)
    #endif
    
    
    	struct davinci_soc_info *soc_info = &davinci_soc_info;
    
    	psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
    
    	mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
    
    	printk(KERN_ERR "################## DSP LPSC value before = %x PSC = %d LPSC No = %d PD = %d\n",mdstat,ctlr,id,domain);
    
    
    	mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
    	mdctl &= ~MDSTAT_STATE_MASK;
    	mdctl |= next_state;
    //	if (flags & PSC_FORCE)
    		mdctl |= MDCTL_FORCE;
    	__raw_writel(mdctl, psc_base + MDCTL + 4 * id);
    
    	pdstat = __raw_readl(psc_base + PDSTAT);
    	if ((pdstat & 0x00000001) == 0) {
    		pdctl1 = __raw_readl(psc_base + PDCTL1);
    		pdctl1 |= 0x1;
    		__raw_writel(pdctl1, psc_base + PDCTL1);
    
    		ptcmd = 1 << domain;
    		__raw_writel(ptcmd, psc_base + PTCMD);
    
    		do {
    			epcpr = __raw_readl(psc_base + EPCPR);
    		} while ((((epcpr >> domain) & 1) == 0));
    
    		pdctl1 = __raw_readl(psc_base + PDCTL1);
    		pdctl1 |= 0x100;
    		__raw_writel(pdctl1, psc_base + PDCTL1);
    	} else {
    		ptcmd = 1 << domain;
    		__raw_writel(ptcmd, psc_base + PTCMD);
    	}
    
    	do {
    		ptstat = __raw_readl(psc_base + PTSTAT);
    	} while (!(((ptstat >> domain) & 1) == 0));
    
    	do {
    		mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
    	} while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
    
    
    	mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
    
    	printk(KERN_ERR "################## DSP LPSC value after = %x PSC = %d LPSC No = %d PD = %d\n",mdstat,ctlr,id,domain);
    
    	iounmap(psc_base);
    
    	printk(KERN_INFO "lpsc_control module init.\n");
    	return 0;
    	}

  • Hello Titusrathinaraj Stalin,

    thank you for your response.

    I'm not understanding from your two terms.

    I presume that the DEEPSLEEP was not reliable while putting the s/m to DS and waking up from DS(DEEPSLEEP).

    Am I right ?

    Please correct me if I'm wrong.

    Which version of SDK are you using?

    Is this your own DEEPSLEEP implementation or provided by TI ?

    We are using a 3.6.7 mainline kernel.
    The DEEPSLEEP implemention is from TI.

    The code is working several times as expected.
    But sometimes the error occurs.

    The problem is to put the system to DEEPSLEEP.
    In case of error we never reach the code after
    "Check for Transition Complete (PTSTAT") in
    arch/arm/mach-davinci/sleep.S.

    In your code examples we see the same steps which are
    implemented by TIs kernel developers.

    I think the code is OK so far.
    But in our system there are sometimes special circumstances which
    cause the error.

    So, what can disturb such a Power Domain Transition?

    Regards,

    Bastian.

     

  • Hi,

    But in our system there are sometimes special circumstances which
    cause the error.


    Yes, I have also the same doubt on it.

    Could you reproduce the problem?

    Kindly check that whether you trying to process anything (DDR) while shutdown the DDR.

  • Hello,



    Could you reproduce the problem?



    I can reproduce this error by booting the system, the dsp is untouched. Then running a bash script putting

    the system in deepsleep in a loop. Sooner or later the error occurs.

    Regards,


    Bastian.

  • Hi,

    Could you please send me the script to my email ID (x0213399@ti.com) or attach which is used to put the processor to DS mode.

    Did you run any process/apps in background while you initiating the DS mode?

    Don't run any process/apps while you initiating the DS mode.

    Please try this and let us know the results.

  • Hello,

    i did some tests with a logicpd Zoom eXperimenter kit.
    -Kernel 3.6.7
    -make da8xx_omapl_defconfig
    -make menuconfig -> enable Omap RTC buildin
    -rootfs via nfs
    -run a script putting the system into deepsleep for 10 seconds in a loop

    This Test was running 30 hours without failure.
    In this time my own board shows the problem in all tests.




    Kindly check that whether you trying to process anything (DDR) while shutdown the DDR.



    To check this seems to be the challenge, now!

    Thank your so far

    Regads,

    Bastian.

  • Hi,

    This Test was running 30 hours without failure.
    In this time my own board shows the problem in all tests.

    What are the difference between your custom and EVM board while you are running these test cases (applcn level) ?

    In your custom : Are you running any app while DS mode ?

  • Hello,

    What are the difference between your custom and EVM board while you are running these test cases (applcn level) ?

    In your custom : Are you running any app while DS mode ?

    The test was running on a minimal system.

    There is a script running in a bash, nothing else.

    Our custom board is based on the SOM on the eXperimenter board.

    One difference is: On our board we are using a NAND flash (ubi / ubifs).

    Regards,


    Bastian.