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.

Am335x io pads settings for the DDR in Control Module conflict with CM3 settings after suspend/resume cycle

Hello,

This topic concerns DDR settings changes after the first suspend / resume cycle. Could be interesting to anyone experiencing memory issues after suspend / resume.

I made a custom design based on am335x-evmsk using the same ddr3 form micron. The differences between both design are that the routing and board stackup are different, from the DDR standpoint.

I have noticed unstabilities, more specifically memory-related kernel crashes after the first suspend / resume cycle (either in "mem" or "standby").

After days of investigation I discovered that the DDR io ctrl / pads settings are changed by the suspend / resume cycle (Using the latest CM3 firmware version) :

Before suspend those registers are (values programmed by the uboot bootloader in sdram_init of board/ti/am335x/board.c):

ddr_cmd0_ioctrl    : 0x0000018b
ddr_cmd1_ioctrl    : 0x0000018b
ddr_cmd2_ioctrl    : 0x0000018b
ddr_data0_ioctrl   : 0x0000018b
ddr_data1_ioctrl   : 0x0000018b

After resume those registers are:

ddr_cmd0_ioctrl    : 0x0000018b
ddr_cmd1_ioctrl    : 0x00000000
ddr_cmd2_ioctrl    : 0x00000000
ddr_data0_ioctrl   : 0x00000084
ddr_data1_ioctrl   : 0x00000084

I realized those changes were done by the CM3 firmware, see below an extract of the resume routine for ddr of the CM3 source code (pm_services/ddr.c, function ddr_io_resume)

if (mem_type == MEM_TYPE_DDR3) {
        /* Disable the pull for CMD2/1/0 */
        __raw_writel(RESUME_IO_PULL_CMD_DDR3, DDR_CMD2_IOCTRL);
        __raw_writel(RESUME_IO_PULL_CMD_DDR3, DDR_CMD1_IOCTRL);
        /* Disable the pull for DATA1/0 */
        __raw_writel(RESUME_IO_PULL_DATA_DDR3, DDR_DATA0_IOCTRL);
        __raw_writel(RESUME_IO_PULL_DATA_DDR3, DDR_DATA1_IOCTRL);

        if (soc_id == AM43XX_SOC_ID) {
            __raw_writel(RESUME_IO_PULL_DATA_DDR3, DDR_DATA2_IOCTRL);
            __raw_writel(RESUME_IO_PULL_DATA_DDR3, DDR_DATA3_IOCTRL);
        }

Changing this code to have the same values (ie 0x18b) programmed by the bootloader solved all my issues.

Those changes are also observed on the EVMSK but do not lead to any type of memory corruption issue. But on my custom design they do.

1) Is this the best place to fine-tune hw settings for the DDR, and should not those be programmed in the bootloader ?

To me, the suspend/resume cycle functions in the CM3 firmware should not be used to "tune" hw settings for normal operation, but only to :

- program hw settings while the platform is in low power,

- revert back to pre-suspend configuration.

Please let me know your thoughts. Anyone seeking to fine tune their hw settings for their design will take some time before discovering they are reprogrammed by the CM3 firmware.

2) I am not even sure those settings changes are relevant since they disagree with the rule

"Values for DDR_CMDx_IOCTRL.io_config_sr_clk should be programmed to the same value"

in section 9.2.5 DDR PHY of the TRM.

In the code excerpt above, the changes concern only CMD2 and CMD1 but not CMD0 leading to inconsistencies betweem them after the resume cycle :

ddr_cmd0_ioctrl    : 0x0000018b
ddr_cmd1_ioctrl    : 0x00000000
ddr_cmd2_ioctrl    : 0x00000000

Please advise,

Best Regards,

Gregoire

  • Hi Biser,

    I am seeing this on different SW versions, including ti-processor-sdk-linux-am335x-evm-02.00.01.07 which i just tested (see below register dump).

    I only need to use an updated version of the am335x-pm-firmware.elf to make the issue disappear.

    My point is not about how to to tune the ddr settings but rather to say that whatever settings you will put in the bootloader, some of those will be erased after a suspend/resume cycle for the reason i gave previously (erased by the CM3 firmware).

    Yes I already went on those sites ... But found no clue about CM3 reprogramming ddr settings.
    Also please note I am specifically referring to Control Module settings, not EMIF.

    Regarding Control Modules, the recommended settings from processors.wiki.ti.com/.../AM335x_EMIF_Configuration_tips
    are to set
    DDR_CMD0_IOCTRL (@0x44E11404) - set to 0x18B
    DDR_CMD1_IOCTRL (@0x44E11408) - set to 0x18B
    DDR_CMD2_IOCTRL (@0x44E1140C) - set to 0x18B
    DDR_DATA0_IOCTRL (@0x44E11440) - set to 0x18B
    DDR_DATA1_IOCTRL (@0x44E11444) - set to 0x18B

    which are indeed programmed in the bootloader (board/ti/am335x/board.c).

    BUT ...

    Those settings are partially erased by the ddr resume function of the CM3, leading to following values after first resume :
    ddr_cmd0_ioctrl : 0x0000018b
    ddr_cmd1_ioctrl : 0x00000000
    ddr_cmd2_ioctrl : 0x00000000
    ddr_data0_ioctrl : 0x00000084
    ddr_data1_ioctrl : 0x00000084

    Which seem to cause my kernel memory crashes. In my patched firmware (see below) I am forcing those registers to 0x18b, which correspond to the settings of the bootloader.
    ==> With this patched firmware, my stability issues disappear.

    So anyone seeking to tune their ioctrl settings for ddr must do it not only in the bootloader but also in the CM3 firmware. I haven't seen any clear indication from TI on this .

    An alternative would be to save/restore the settings in the CM3 firmware code.

    As of today there is no save/restore mechanism. Data are hardcoded in the source code, leading to potentially corrupted settings after the first suspend/resume cycle. Here is the excerpt of the ddr code of the CM3 (patched by myself -- see commented lines // original file would be the same with 0x84 and 0x0 values instead of 0x18b) :

    /*
    * Values recommended by the HW team. These change the pulls
    * on certain IOs of DATA and CMD macros
    */
    #define SUSP_IO_PULL_DATA 0x3FF00003
    #define SUSP_IO_PULL_CMD1_DDR3 0x08000000
    #define SUSP_IO_PULL_CMD2_DDR3 0xF7FFFFFF
    #define SUSP_IO_PULL_CMD1_LPDDR2 0x00000000
    #define SUSP_IO_PULL_CMD2_LPDDR2 0xFFFFFFFF

    //#define RESUME_IO_PULL_DATA_DDR3 0x84
    //#define RESUME_IO_PULL_CMD_DDR3 0x0

    #define RESUME_IO_PULL_DATA_DDR3 0x18b
    #define RESUME_IO_PULL_CMD_DDR3 0x18b

    #define RESUME_IO_PULL_DATA_LPDDR2 0x20000294
    #define RESUME_IO_PULL_CMD_LPDDR2 0x0





    Below the register dump done on ti-processor-sdk-linux-am335x-evm-02.00.01.07 running on my design, and using the am335x-pm-firmare.elf from the release.

    root@am335x-evm:~# echo standby > /sys/power/state
    [ 23.953720] PM: Syncing filesystems ... done.
    [ 24.069184] Freezing user space processes ... (elapsed 0.001 seconds) done.
    [ 24.079687] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done.
    [ 24.088684] Suspending console(s) (use no_console_suspend to debug)
    [ 24.099991] PM: suspend of devices complete after 3.753 msecs
    [ 24.101509] PM: late suspend of devices complete after 1.485 msecs
    [ 24.103707] PM: noirq suspend of devices complete after 2.158 msecs

    [ 24.103722] Control registers before suspend:
    [ 24.103722] conf_rtc_pwronrstn : 0x00000030
    [ 24.103722] conf_pmic_power_en : 0x00000028
    [ 24.103722] conf_ext_wakeup : 0x00000028
    [ 24.103722] conf_rtc_kaldo_enn : 0x00000020
    [ 24.103722] conf_usb0_drvvbus : 0x00000020
    [ 24.103722] conf_usb1_drvvbus : 0x00000020
    [ 24.103722] cqdetect_status : 0x00003f3f
    [ 24.103722] ddr_io_ctrl : 0x00000000
    [ 24.103722] vtp_ctrl : 0x00010167
    [ 24.103722] vref_ctrl : 0x00000000
    [ 24.103722] ddr_cmd0_ioctrl : 0x0000018b
    [ 24.103722] ddr_cmd1_ioctrl : 0x0000018b
    [ 24.103722] ddr_cmd2_ioctrl : 0x0000018b
    [ 24.103722] ddr_data0_ioctrl : 0x0000018b
    [ 24.103722] ddr_data1_ioctrl : 0x0000018b

    [ 24.103722] Control registers after suspend:
    [ 24.103722] conf_rtc_pwronrstn : 0x00000030
    [ 24.103722] conf_pmic_power_en : 0x00000028
    [ 24.103722] conf_ext_wakeup : 0x00000028
    [ 24.103722] conf_rtc_kaldo_enn : 0x00000020
    [ 24.103722] conf_usb0_drvvbus : 0x00000020
    [ 24.103722] conf_usb1_drvvbus : 0x00000020
    [ 24.103722] cqdetect_status : 0x00003f3f
    [ 24.103722] ddr_io_ctrl : 0x00000000
    [ 24.103722] vtp_ctrl : 0x00000067
    [ 24.103722] vref_ctrl : 0x00000000
    [ 24.103722] ddr_cmd0_ioctrl : 0x0000018b
    [ 24.103722] ddr_cmd1_ioctrl : 0x00000000
    [ 24.103722] ddr_cmd2_ioctrl : 0x00000000
    [ 24.103722] ddr_data0_ioctrl : 0x00000084
    [ 24.103722] ddr_data1_ioctrl : 0x00000084

    [ 24.103722] PM: Successfully put all powerdomains to target state
    [ 24.103722] PM: Wakeup source UART
    [ 24.105573] PM: noirq resume of devices complete after 1.683 msecs
    [ 24.106816] PM: early resume of devices complete after 1.010 msecs
    [ 24.211074] PM: resume of devices complete after 104.218 msecs
    [ 24.401271] Restarting tasks ... done.





    Please let me know your thoughts,

    Best,

    Gregoire
  • OK, thanks for the clarification. I will notify the factory team to check this.