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.

DDR PHY Comand 0/1/2 Invert Clockout Selection Register



Hi,

I have one question regarding DDR3 memory controller's regisgers.

According to the Figure 7-1 in TRM, the memory cotroller has two DDR interface 0 and 1. However, regarding CMDn_REG_xxxx register, n =0,1,2.

For examaple, there are three registers for INVERT_CLKOUT_0. CMD0_REG_PHY_INVERT_CLKOUT_0, CMD1_REG_PHY_INVERT_CLKOUT_0  and CMD2_REG_PHY_INVERT_CLKOUT2. 

I can understand CMD0 and CMD1 regsiter. Because, I think these are for DDR interface 0 and 1. But I don't understand CMD2. There is not DDRinterface2 in the controllers. What is CMD2?

Please let me know.

Best regards,

Michi

 

  • Michi,

    This CMD0 registers does not correspond only to the DDR interface 0. This CMD0 register is common for both DDR0 and DDR1. See DM814x datasheet, Table 8-49. DDR2/DDR3 PHY Registers:

    CMD0_REG_PHY_INVERT_CLKOUT_0  - DDR PHY Command 0 Invert Clockout Selection Register
    DDR0 HEX ADDRESS : 0x47C0_C42C
    DDR1 HEX ADDRESS : 0x47C0_C82C

    This CMD0/1/2 is common for both DDR0 and DDR1 PHYs. I mean DDR0 has CMD0/1/2 and DDR1 has CMD0/1/2.

    The DDR PHY I/Os are grouped into 5 different sets based on the I/O macro that controls them. Each macro controls 10 signals each. Three command macros (CMD0-2) contain 10 control/address signals each.

    The command macro acts as a unidirectional macro that transmits address and control bits from memory controller to the memory chip. The clocks DDR[x]_CLK and DDR[x]_CLKn are used by the memory to register the command and address transmitted on the transmit channels. All address and control signals are transmitted clock- centered with respect to DDR[x]_CLK and DDR[x]_CLKn. The memory, on the positive edge of DDR[x]_CLK and the negative edge of DDR[x]_CLKn, samples all address and control signals.

    The data and command macros are responsible for system level flight time compensation.

    Software leveling can be done independently for each data and command macro.

    BR
    Pavel


  • Dear Pavel-san,

    Thank you for your reply.

    I understood DDR PHY has 5 I/O macro, and each macro controls 10 signals.

    According to my customer,  Invert clkout settig is needed to only CMD0 register. It seems that CMD1 and CMD2 are not needed for Invert clkout.

    Why is it needed only CMD0 register for Invert clkout?

    Please adivise me.

    I appreciate your quick reply.

     

    Best regards,

    Michi

     

     

  • Michi,

    Michi Yama said:
    Why is it needed only CMD0 register for Invert clkout?

    According to the Linux based EZSDK/PSP that I am using, all three CMD (CMD0/1/2) are used for the Invert clkout. This is the extract of the u-boot source code:

    u-boot-2010.06-psp.04.04.00.01/board/ti/ti8148/evm.c

    /*
     * early system init of muxing and clocks.
     */
    void s_init(u32 in_ddr)
    {
        /* TODO: Revisit enabling of I/D-cache in 1st stage */
    #if 0
        icache_enable();
        dcache_enable();
    #endif

        /*
         * Disable Write Allocate on miss to avoid starvation of other masters
         * (than A8).
         *
         * Ref DM814x Erratum: TODO
         */
        l2_disable_wa();

        /* Can be removed as A8 comes up with L2 enabled */
        l2_cache_enable();
        unlock_pll_control_mmr();
        /* Setup the PLLs and the clocks for the peripherals */
        prcm_init(in_ddr);
    #if defined(CONFIG_TI814X_CONFIG_DDR)
        if (!in_ddr)
            config_ti814x_ddr();    /* Do DDR settings */
    #endif
    }

    #ifdef CONFIG_TI814X_CONFIG_DDR
    static void config_ti814x_ddr(void)
    {
        int macro, emif;

        /*Enable the Power Domain Transition of L3 Fast Domain Peripheral*/
        __raw_writel(0x2, CM_DEFAULT_FW_CLKCTRL);
        /*Enable the Power Domain Transition of L3 Fast Domain Peripheral*/
        __raw_writel(0x2, CM_DEFAULT_L3_FAST_CLKSTCTRL);
        __raw_writel(0x2, CM_DEFAULT_EMIF_0_CLKCTRL); /*Enable EMIF0 Clock*/
        __raw_writel(0x2, CM_DEFAULT_EMIF_1_CLKCTRL); /*Enable EMIF1 Clock*/
        __raw_writel(0x2, CM_DEFAULT_DMM_CLKCTRL);

        /*Poll for L3_FAST_GCLK  & DDR_GCLK  are active*/
        while ((__raw_readl(CM_DEFAULT_L3_FAST_CLKSTCTRL) & 0x300) != 0x300);
        /*Poll for Module is functional*/
        while ((__raw_readl(CM_DEFAULT_EMIF_0_CLKCTRL)) != 0x2);
        while ((__raw_readl(CM_DEFAULT_EMIF_1_CLKCTRL)) != 0x2);
        while ((__raw_readl(CM_DEFAULT_DMM_CLKCTRL)) != 0x2);

        if (is_ddr3()) {
            cmd_macro_config(DDR_PHY0, DDR3_PHY_INVERT_CLKOUT_OFF,
                    DDR3_PHY_CTRL_SLAVE_RATIO_CS0_DEFINE,
                    PHY_CMD0_DLL_LOCK_DIFF_DEFINE);
            cmd_macro_config(DDR_PHY1, DDR3_PHY_INVERT_CLKOUT_OFF,
                    DDR3_PHY_CTRL_SLAVE_RATIO_CS0_DEFINE,
                    PHY_CMD0_DLL_LOCK_DIFF_DEFINE);

            for (emif = 0; emif <= DDR_PHY1; emif++) {
                for (macro = 0; macro <= DATA_MACRO_3; macro++) {
                    data_macro_config(macro, emif,
                        DDR3_PHY_RD_DQS_CS0_DEFINE,
                        DDR3_PHY_WR_DQS_CS0_DEFINE,
                        DDR3_PHY_RD_DQS_GATE_CS0_DEFINE,
                        DDR3_PHY_WR_DATA_CS0_DEFINE);
                }
            }

    ................

    }


    #ifdef CONFIG_TI814X_CONFIG_DDR
    static void cmd_macro_config(u32 ddr_phy, u32 inv_clk_out,
                 u32 ctrl_slave_ratio_cs0, u32 cmd_dll_lock_diff)
    {
        u32 ddr_phy_base = (DDR_PHY0 == ddr_phy) ?
                 DDR0_PHY_BASE_ADDR : DDR1_PHY_BASE_ADDR;

        __raw_writel(inv_clk_out,
             ddr_phy_base + CMD1_REG_PHY_INVERT_CLKOUT_0);
        __raw_writel(inv_clk_out,
             ddr_phy_base + CMD0_REG_PHY_INVERT_CLKOUT_0);
        __raw_writel(inv_clk_out,
             ddr_phy_base + CMD2_REG_PHY_INVERT_CLKOUT_0);

    .........

    }

    As you can see from the above code, all 3 CMD registers are used for both DDR_PHY0 and DDR_PHY1.

    BR
    Pavel

  • Pavel-san,

    Thank you for your quick reply.

    If you modify the source code to use only CMD0 register for Invert clkout, what is happened in your system? Is your system still working correctly?

    Best regards,

    Michi

  • Michi,

    Michi Yama said:
    If you modify the source code to use only CMD0 register for Invert clkout, what is happened in your system? Is your system still working correctly?

    Yes, my DM814x/AM387x EVM is still working correctly.

    I even modify the source code to not use any CMD register for invert clkout (see below), and the DM814x/AM387x EVM is still working correctly.

    #ifdef CONFIG_TI814X_CONFIG_DDR
    static void cmd_macro_config(u32 ddr_phy, u32 inv_clk_out,
                 u32 ctrl_slave_ratio_cs0, u32 cmd_dll_lock_diff)
    {
        u32 ddr_phy_base = (DDR_PHY0 == ddr_phy) ?
                 DDR0_PHY_BASE_ADDR : DDR1_PHY_BASE_ADDR;

        /*__raw_writel(inv_clk_out,
             ddr_phy_base + CMD1_REG_PHY_INVERT_CLKOUT_0);*/
        /*__raw_writel(inv_clk_out,
             ddr_phy_base + CMD0_REG_PHY_INVERT_CLKOUT_0);*/
        /*__raw_writel(inv_clk_out,
             ddr_phy_base + CMD2_REG_PHY_INVERT_CLKOUT_0);*/

    BR
    Pavel