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.

Change DDR clock speed while running?

Our board has an OMAP L138 with mDDR.  For a number of reasons, we'd like to be able to lower the clock speed of the mDDR while running (and hence while potentially accessing the memory).  This will involve changing the speed of PLL1 and PLL1_SYSCLK1, as well as the timing parameters in SDRCR, SDTIMR1, and SDTIMR2.  Here is the procedure I believe I should follow:

1. Adjust SDRCR for the PLL bypass clock rate

2. Adjust PLL1 and PLL1_SYSCLK1 speed

4. Adjust SDTIMR1 and SDTIMR2

5. Adjust SDRCR for the lower mDDR clock speed

My question is, will the changes I make to SDTIMR1 and SDTIMR2 take effect without resetting the DDR controller?  Because since the board is running, there may be accesses to memory, which I assume means that I can't reset the DDR controller. 

Thanks,

Brian

  • Hi,

    My question is, will the changes I make to SDTIMR1 and SDTIMR2 take effect without resetting the DDR controller?  Because since the board is running, there may be accesses to memory, which I assume means that I can't reset the DDR controller.

    In my understanding,

    DDR controller reset is not required while changing the DDR frequency.

    To confirm this again, I have to do some experiments that the DDR freq need to be modify through gel file hotmenu (script option) options while running any DSP/ARM app.

    Let me update once I done.

    I referred the gel files which has the configuring the DDR frequencies through hotmenu options.

    In that, They have not resetting DDR controller but As you said, We need to modify the PLL1 sysclk for MCLK and SDTIMR1 and SDRCR register.

    I think that SDTIMR2 register changes not required since we didn't change new DDR part spec (for new timings).

    Set_mDDR_126MHz() {
        GEL_TextOut("\tmDDR initialization is in progress....\n","Output",1,1,1);
        Set_DDRPLL_126MHz();
        DEVICE_DDRConfig(MDDR, 126);
        GEL_TextOut("\tmDDR init for 126 MHz is done\n","Output",1,1,1);
    }
    Set_DDRPLL_126MHz() {
        device_PLL1(20,1,0,1,2);
        GEL_TextOut("\tPLL1 init done for DDR:126MHz\n","Output",1,1,1);
    }

    DEVICE_DDRConfig(unsigned int ddr_type, unsigned int freq)
    {
        unsigned int j;
        unsigned int tmp_SDCR;
        
        // Enable the Clock to EMIFDDR SDRAM
        PSC1_LPSC_enable(PD0, LPSC_DDR);

        // Begin VTP Calibration
        VTPIO_CTL &= ~0x00000040;       // Clear POWERDN
        VTPIO_CTL &= ~0x00000080;       // Clear LOCK
        VTPIO_CTL |=  0x00002000;       // Set CLKRZ in case it was cleared before (VTP looks for CLKRZ edge transition)
        VTPIO_CTL &= ~0x00002000;       // Clear CLKRZ (Use read-modify-write to ensure 1 VTP cycle wait for previous instruction)
        VTPIO_CTL |=  0x00002000;       // Set CLKRZ (Use read-modify-write to ensure 1 VTP cycle wait for previous instruction)

        j = 0;
        // Polling READY bit to see when VTP calibration is done
        while((VTPIO_CTL & 0x00008000) == 0) {
          if( j++ > VTP_TIMEOUT ) {
            GEL_TextOut("\tVTP Ready timeout\n","Output",1,1,1);           
            break;
          }
        }

        VTPIO_CTL |= 0x00000080;       // Set LOCK bit for static calibration mode
        VTPIO_CTL |= 0x00000040;       // Set POWERDN bit to power down VTP module
        // End VTP Calibration

        VTPIO_CTL |= 0x00004000;       // Set IOPWRDN to allow powerdown of input receivers when PWRDNEN is set

        // **********************************************************************************************
        // Setting based on the looser of 512Mb mDDR MT46H32M16LFBF-6,
        //                                  1Gb mDDR MT46H64M16LF-6, or
        //                                  1Gb mDDR MT46H64M16LFBF-6 on EVM
        // Config DDR timings
        DRPYC1R     = (0x0               << 8)   |  // Reserved
                      (0x1               << 7)   |  // EXT_STRBEN
                      (0x1               << 6)   |  // PWRDNEN
                      (0x0               << 3)   |  // Reserved
                      (0x4               << 0);     // RL
        // DRPYC1R Value = 0x000000C4

        if( DDR_DEBUG ) {
          // Configure EMIF with max timings for more slack
          // Try this if memory is not stable
          DRPYC1R  |=  0x7; // RL
        }

        EMIFDDR_SDCR |= 0x00800000; // Set BOOTUNLOCK

        // Settings that change depending on DDR2 or MDDR
        if( ddr_type == DDR2 ) {
          tmp_SDCR = (0x0               << 25)  |  // MSDRAMEN
                     (0x1               << 20);    // DDR2EN
          GEL_TextOut("\tUsing DDR2 settings\n","Output",1,1,1);
        }
        else if( ddr_type == MDDR ) {
          tmp_SDCR = (0x1               << 25)  |  // MSDRAMEN
                     (0x0               << 20);    // DDR2EN
          GEL_TextOut("\tUsing mDDR settings\n","Output",1,1,1);
        }
        else {
          tmp_SDCR = (0x1               << 25)  |  // MSDRAMEN
                     (0x0               << 20);    // DDR2EN
          GEL_TextOut("\tUnknown DDR Type!  Using MDDR settings\n","Output",1,1,1);
        }

        EMIFDDR_SDCR = tmp_SDCR                    |  // Settings that change depending on DDR2 or MDDR
                       (EMIFDDR_SDCR & 0xF0000000) |  // Reserved
                       (0x0               << 27)   |  // DDR2TERM1
                       (0x0               << 26)   |  // IBANK_POS
                       (0x0               << 24)   |  // DDRDRIVE1
                       (0x0               << 23)   |  // BOOTUNLOCK
                       (0x0               << 22)   |  // DDR2DDQS
                       (0x0               << 21)   |  // DDR2TERM0
                       (0x0               << 19)   |  // DDRDLL_DIS
                       (0x0               << 18)   |  // DDRDRIVE0
                       (0x1               << 17)   |  // DDREN
                       (0x1               << 16)   |  // SDRAMEN
                       (0x1               << 15)   |  // TIMUNLOCK
                       (0x1               << 14)   |  // NM
                       (0x0               << 12)   |  // Reserved
                       (0x3               << 9)    |  // CL
                       (0x0               << 7)    |  // Reserved
                       (0x2               << 4)    |  // IBANK
                       (0x0               << 3)    |  // Reserved
                       (0x2               << 0);      // PAGESIZE
        // mDDR SDCR Value = 0x02034622

        if( ddr_type == MDDR ) {
          EMIFDDR_SDCR2   = 0x00000000; // IBANK_POS set to 0 so this register does not apply
        }

        if( DDR_DEBUG ) {
          // Configure EMIF with max timings for more slack
          // Try this if memory is not stable

          EMIFDDR_SDTIMR1 = (0x7F << 25)             |  // tRFC
                            (0x07 << 22)             |  // tRP
                            (0x07 << 19)             |  // tRCD
                            (0x07 << 16)             |  // tWR
                            (0x1F << 11)             |  // tRAS
                            (0x1F << 6)              |  // tRC
                            (0x07 << 3)              |  // tRRD
                            (EMIFDDR_SDTIMR1 & 0x4)  |  // Reserved
                            (0x03 << 0);                // tWTR

          EMIFDDR_SDTIMR2 = (EMIFDDR_SDTIMR2 & 0x80000000)                       |  // Reserved
                            (((unsigned int) ((70000 / 7812.5) - 0.5))  << 27)   |  // tRASMAX
                            (0x3                                        << 25)   |  // tXP
                            (0x0                                        << 23)   |  // tODT (Not supported)
                            (0x7F                                       << 16)   |  // tXSNR
                            (0xFF                                       << 8)    |  // tXSRD
                            (0x07                                       << 5)    |  // tRTP (1 Cycle)
                            (0x1F                                       << 0);      // tCKE

          // SDTIMR1 Value = 0xFFFFFFFB
          // SDTIMR2 Value = 0x467FFFFF

          GEL_TextOut("\tDDR Timings Configured for Debug\n","Output",1,1,1);
        }
        else {
          // Let float -> integer truncate handle minus 1; Safer to round up for timings
          EMIFDDR_SDTIMR1 = (((unsigned int) (110.0 * freq / 1000))  << 25)  |  // tRFC
                            (((unsigned int) ( 18.0 * freq / 1000))  << 22)  |  // tRP
                            (((unsigned int) ( 18.0 * freq / 1000))  << 19)  |  // tRCD
                            (((unsigned int) ( 15.0 * freq / 1000))  << 16)  |  // tWR
                            (((unsigned int) ( 42.0 * freq / 1000))  << 11)  |  // tRAS
                            (((unsigned int) ( 60.0 * freq / 1000))  << 6)   |  // tRC
                            (((unsigned int) ( 12.0 * freq / 1000))  << 3)   |  // tRRD
                            (EMIFDDR_SDTIMR1 & 0x4)                          |  // Reserved
                            ((2 - 1)                                 << 0);     // tWTR

          EMIFDDR_SDTIMR2 = (EMIFDDR_SDTIMR2 & 0x80000000)                    |  // Reserved
                            (((unsigned int) ((70000 / 7812.5) - 1)) << 27)   |  // tRASMAX
                            (0x3                                     << 25)   |  // tXP (Should be 6-1 per MT46H64M16LFBF-6 datasheet, but field only goes up to 0b11)
                            (0x0                                     << 23)   |  // tODT (Not supported)
                            (((unsigned int) (138.0 * freq / 1000))  << 16)   |  // tXSNR (tXSR for mDDR)
                            (((unsigned int) (138.0 * freq / 1000))  << 8)    |  // tXSRD (tXSR for mDDR)
                            ((2 - 1)                                 << 5)    |  // tRTP
                            ((1 - 1)                                 << 0);      // tCKE

          // SDTIMR1 Value @ 150MHz = 0x20923249
          // SDTIMR2 Value @ 150MHz = 0x3E141420
        }
     
        EMIFDDR_SDCR    &= ~0x00008000; // Clear TIMUNLOCK

        // Let float -> integer truncate handle RR round-down; Safer to round down for refresh rate
        EMIFDDR_SDRCR   = (0x1                                  << 31)  |  // LPMODEN (Required for LPSC SyncReset/Enable)
                          (0x1                                  << 30)  |  // MCLKSTOPEN (Required for LPSC SyncReset/Enable)
                          (0x0                                  << 24)  |  // Reserved
                          (0x0                                  << 23)  |  // SR_PD
                          (0x0                                  << 16)  |  // Reserved
                          (((unsigned int) (7.8125 * freq))     << 0);     // RR

        // SyncReset the Clock to EMIFDDR SDRAM
        PSC1_LPSC_SyncReset(PD0, LPSC_DDR);

        // Enable the Clock to EMIFDDR SDRAM
        PSC1_LPSC_enable(PD0, LPSC_DDR);

        // Disable self-refresh
        EMIFDDR_SDRCR &= ~0xC0000000;
        // SDRCR Value @ 150MHz = 0x00000493
        
        // Set PBBPR to a value lower than default to prevent blocking
        EMIFDDR_PBBPR = 0x30;
    }

  • These scripts do the full initialization sequence as specified in the user guide.  However I was assuming that I wouldn't have to redo VTP calibration, set DRPYC1R, or set SDCR (other than to set TIMUNLOCK).  But the part I'm most concerned about is whether or not I have to do the clock reset that is shown at the end of this script.  It also appears that this script assumes that the mDDR is in self-refresh since it disables self-refresh after reconfiguring DDR.  Since the user guide only discusses post-reset configuration, it's hard to know if the timing can be reconfigured without doing all of the steps shown in that script.

  • Hi,

    Understood.

    I can't answer directly, I will try some experiments on this and will come back.

    Mean while, You may get answers from our experts too.

  • Brian,

    Brian Niebuhr said:
    Since the user guide only discusses post-reset configuration, it's hard to know if the timing can be reconfigured without doing all of the steps shown in that script.

    Post-reset configuration is all we can support; we have to be in a known state and do this initialization in a controlled sequence. Dynamically changing any of the parameters while trying to use the DDR Controller for data access is a sure way to get corruption in your data flow. Even if the SDTIMR1/2 registers will allow changes without a reset (which I suspect they will), doing this while the DDR Controller is actively accessing the DDR device has the chance for disaster.

    In the DDR Controller User Guide's section x.1.2 on Clock Configuration, there is the following Note:

    This is written for normal use, of course. The corollary of this is that any time the PLLC1 is being configured or the clock is not stable, the DDR Controller must be held in reset.

    Regards,
    RandyP