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.

AM3352: Timing of CKE to RESET failed and tWPST failed

Part Number: AM3352

Hi

The timing of CKE to Reset failed. Result as below:

tWPST test failed as below:

thanks.

  • Hi Support Team,

    Is there a register that can be adjusted?

    Do other projects have similar problems?

    Looking forward to your reply.

  • Hello Ryan, 

    Thank you for the query.

    Can you please describe the setup for me to review and reply.

    I cam across the below thread. Not sure if this helps.

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/353205/about-the-cke-low-time-time-from-reset-going-high-to-cke-going-high-on-the-ddr3-required-by-jedec

    Based on the reply, i will have to assign to the expert.

    Regards,

    Sreenivasa

  • Hello Sreenivasa,

    Thank you for your reply.
    Issue CKE looks like it should be solvable, we'll try it。
    But we still need help with the tWPST issue.
    Below is the code to configure DDR.But we rewrote this code.
    The valid configuration is in lines 825-880. Then Uboot will call the ddr_config_commit() function to write to the register. The config_ddr() function is called internally.

    /************************************************************** -*- c -*- ******
    File name : ddr-config.c
    Create Date : 2016-10(October)-31 Monday 06:45:16 (+0000,UTC)
    Author : ZhengYi <yzheng@techyauld.com>

    License :
    Copyright(C) 2014, 2015
    Copyright(C) Techyauld Inc.
    All rights reserved

    ---------1---------2---------3---------4---------5---------6---------7---------8
    *******************************************************************************/
    #include <common.h>
    #include <asm/arch/ddr_defs.h>

    #include "ddr-common.h"

    static void init_ddr_param_ctrl_ioregs(const struct am335x_ddr_config* ddr_cfg, struct ctrl_ioregs* param)
    {
    u32 val;

    if(1){ /* 9.3.1.87 ddr_cmd0_ioctrl Register (offset = 1404h) [reset = 0h] */
    val = (ddr_cfg->slewrate_clk << 8) |
    (ddr_cfg->slewrate_cmdaddr << 3) |
    (ddr_cfg->output_imp_clk << 5) |
    (ddr_cfg->output_imp_cmdaddr << 0);

    param->cm0ioctl = val;
    param->cm1ioctl = val;
    param->cm2ioctl = val;
    }
    if(1){ /* 9.3.1.90ddr_data0_ioctrl Register (offset = 1440h) [reset = 0h] */
    val = (ddr_cfg->slewrate_dqs << 8) |
    (ddr_cfg->slewrate_dq << 3) |
    (ddr_cfg->output_imp_dqs << 5) |
    (ddr_cfg->output_imp_dq << 0);

    param->dt0ioctl = val;
    param->dt1ioctl = val;
    }

    /* not used by AM335x */
    param->dt2ioctrl = 0;
    param->dt3ioctrl = 0;
    param->emif_sdram_config_ext = 0;
    }
    static void init_ddr_param_data(const struct am335x_ddr_config* ddr_cfg, struct ddr_data* param)
    {
    /* 7.3.6.4 DDR PHY Data Macro 0/1 Read DQS Slave Ratio Register */
    /* (DATA0/1_REG_PHY_RD_DQS_SLAVE_RATIO_0) */
    /* offset 0xc8 / 0x16c */
    param->datardsratio0 = ddr_cfg->adjustable_params.phy_slave_ratio_rd_dqs;

    /* 7.3.6.5 DDR PHY Data Macro 0/1 Write DQS Slave Ratio Register */
    /* (DATA0/1_REG_PHY_WR_DQS_SLAVE_RATIO_0) */
    /* offset 0xdc / 0x180 */
    param->datawdsratio0 = ddr_cfg->adjustable_params.phy_slave_ratio_wr_dqs;

    /* 7.3.6.6 DDR PHY Data Macro 0/1 Write Leveling Init Ratio Register */
    /* (DATA0/1_REG_PHY_WRLVL_INIT_RATIO_0) */
    /* offset 0x0f0 / 0x194 */
    param->datawiratio0 = ddr_cfg->phy_wrlvl_init_ratio;

    /* 7.3.6.8 DDR PHY Data Macro 0 DQS Gate Training Init Ratio Register */
    /* (DATA0_REG_PHY_GATELVL_INIT_RATIO_0) */
    /* offset 0x0fc / 0x1a0 */
    param->datagiratio0 = ddr_cfg->phy_gatelvl_init_ratio;

    /* 7.3.6.10 DDR PHY Data Macro 0/1 DQS Gate Slave Ratio Register */
    /* (DATA0/1_REG_PHY_FIFO_WE_SLAVE_RATIO_0) */
    /* offset 0x108 / 0x1ac */
    param->datafwsratio0 = ddr_cfg->adjustable_params.phy_slave_ratio_fifo_we;

    /* 7.3.6.11 DDR PHY Data Macro 0/1 Write Data Slave Ratio Register */
    /* (DATA0/1_REG_PHY_WR_DATA_SLAVE_RATIO_0) */
    /* offset 0x120 / 0x1c4 */
    param->datawrsratio0 = ddr_cfg->adjustable_params.phy_slave_ratio_wr_data;
    }
    static void init_ddr_param_cmdctrl(const struct am335x_ddr_config* ddr_cfg, struct cmd_control* param)
    {
    /* all of the not used registers are kept as the default values */
    memset(param, 0, sizeof(*param));

    /* 7.3.6.1 DDR PHY Command 0/1/2 Address/Command Slave Ratio Register */
    /* (CMD0/1/2_REG_PHY_CTRL_SLAVE_RATIO_0) */
    param->cmd0csratio = ddr_cfg->adjustable_params.phy_slave_ratio_cmd;
    param->cmd1csratio = ddr_cfg->adjustable_params.phy_slave_ratio_cmd;
    param->cmd2csratio = ddr_cfg->adjustable_params.phy_slave_ratio_cmd;

    /* 7.3.6.3 DDR PHY Command 0/1/2 Invert Clockout Selection Register */
    /* (CMD0/1/2_REG_PHY_INVERT_CLKOUT_0) */
    param->cmd0iclkout = 0;
    param->cmd1iclkout = 0;
    param->cmd2iclkout = 0;
    }
    static void init_ddr_param_emif_reg(const struct am335x_ddr_config* ddr_cfg, struct emif_regs* param)
    {
    /* all of the not used registers are kept as the default values */
    memset(param, 0, sizeof(*param));

    /* 7.3.5.33 DDR_PHY_CTRL_1 Register (offset = E4h) [reset = 0h] */
    /* This field defines the latency for read data from DDR SDRAM in */
    /* number of DDR clock cycles. */
    /* The value applied should be equal to the required value minus one. */
    /* The maximum read latency supported by the DDR PHY is equal to */
    /* CAS latency plus 7 clock cycles. */
    /* The minimum read latency must be equal to CAS latency plus 2 */
    /* clock cycle. */

    param->emif_ddr_phy_ctlr_1 = ddr_cfg->tAL + ddr_cfg->tCL - 1;
    param->emif_ddr_phy_ctlr_1 |= 0x03 << 8; /* reg_phy_rd_local_odt */
    param->emif_ddr_phy_ctlr_1 |= 0x03 << 10; /* reg_phy_wr_local_odt */
    param->emif_ddr_phy_ctlr_1 |= 0x00 << 12; /* reg_phy_idle_local_odt */


    if(1){ /* SDRAM refresh settings */
    u32 val = 0;

    /* bit[31] Initialization and Refresh disable. */
    if(1){
    /* reg_initref_dis */
    /* When set to 1, EMIF will disable SDRAM initialization and refreshes, */
    /* but will carry out SDRAM write/read transactions. */
    val = 0;
    }

    /* bit[29] DDR2 and DDR3 self-refresh temperature range. */
    if(1){
    /* reg_srt */
    /* Set to 0 for normal operating temperature range. */
    /* Set to 1 for extended operating temperature range. */
    /* For DDR3, this bit must be set to 0 if the reg_asr field is set to 1. */
    /* A write to this field will cause the EMIF to start the SDRAM */
    /* initialization sequence. */
    val |= (0<<29);
    }

    /* bit[28] DDR3 Auto Self Refresh enable. */
    if(1){
    /* reg_asr */
    /* Set to 1 for auto Self Refresh enable. */
    /* Set to 0 for manual Self Refresh reference indicated by the reg_srt field. */
    /* A write to this field will cause the EMIF to start the SDRAM */
    /* initialization sequence. */

    val |= (1<<28); /* enable auto refresh */
    }

    /* bit[26-24] Partial Array Self Refresh. */
    if(1){
    /* reg_pasr */
    /* These bits get loaded into the Extended Mode Register of an */
    /* LPDDR1 or DDR3 during initialization. */

    /* For LPDDR1, */
    /* set to 0 for full array, */
    /* set to 1 for 1/2 array, */
    /* set to 2 for 1/4 array, */
    /* set to 5 for 1/8 array, */
    /* set to 6 for 1/16 array to be refreshed. */

    /* For DDR3, */
    /* set to 0 for full array, */
    /* set to 1 or 5 for 1/2 array, */
    /* set to 2 or 6 for 1/4 array, */
    /* set to 3 or 7 for 1/8 array, */
    /* set to 4 for 3/4 array to be refreshed. */

    /* All other values are reserved. */
    /* A write to this field will cause the EMIF to start the SDRAM */
    /* initialization sequence. */

    val |= (0<<24); /* full array self refresh */
    }

    /* bit[15-0] Refresh Rate. */
    if(1){
    /* reg_refresh_rate */
    /* Value in this field is used to define the rate at which connected */
    /* SDRAM devices will be refreshed. */

    /* SDRAM_refresh_rate = EMIF_rate / reg_refresh_rate; */
    /* where EMIF_rate is equal to DDR clock rate. */
    /* If reg_refresh_rate < (8*reg_t_rfc) + reg_t_rp + reg_t_rcd + 20; */
    /* then it will be loaded with (8*reg_t_rfc) + reg_t_rp + reg_t_rcd + 20. */

    /* This is done to avoid lock-up situations when illegal values are */
    /* programmed. */

    /* assuming refresh interval is 7.8us(128.2KHz), we should fill this field */
    /* to be (DDR_CLK_MHz * 7.8us) */
    val |= ddr_cfg->clk_MHz / 10 * 78;
    }

    param->ref_ctrl = val;
    }
    if(1){ /* SDRAM_TIM_{1,2,3} and their shadows */
    u32 val_1 = 0;
    u32 val_2 = 0;
    u32 val_3 = 0;

    /* bit[28-25] reg_t_rp */
    if(1){
    /* Minimum number of DDR clock cycles from Precharge to Activate or */
    /* Refresh, minus one. */
    val_1 |= (ddr_cfg->tRP - 1) << 25;
    }

    /* bit[24-21] reg_t_rcd */
    if(1){
    /* Minimum number of DDR clock cycles from Activate to Read or */
    /* Write, minus one. */
    val_1 |= (ddr_cfg->tRCD - 1) << 21;
    }

    /* bit[20-17] reg_t_wr */
    if(1){
    /* Minimum number of DDR clock cycles from last Write transfer to */
    /* Pre-charge, minus one. */
    /* The SDRAM initialization sequence will be started when the value of */
    /* this field is changed from the previous value and the EMIF is in */
    /* DDR2 mode. */
    val_1 |= (ddr_cfg->tWR - 1) << 17;
    }

    /* bit[16-12] reg_t_ras */
    if(1){
    /* Minimum number of DDR clock cycles from Activate to Pre-charge, */
    /* minus one. */
    /* reg_t_ras >= reg_t_rcd. */
    val_1 |= (ddr_cfg->tRAS - 1) << 12;
    }

    /* bit[11-6] reg_t_rc */
    if(1){
    /* Minimum number of DDR clock cycles from Activate to Activate, */
    /* minus one. */
    val_1 |= (ddr_cfg->tRC - 1) << 6;
    }

    /* bit[5-3] reg_t_rrd */
    if(1){
    /* Minimum number of DDR clock cycles from Activate to Activate for a */
    /* different bank, minus one. */
    /* For an 8 bank DDR2 and DDR3, this field must be equal to */
    /* ((tFAW/(4*tCK))-1). */
    val_1 |= (ddr_cfg->tRRD - 1) << 3;
    }

    /* bit[2-0] reg_t_wtr */
    if(1){
    /* Minimum number of DDR clock cycles from last Write to Read, */
    /* minus one. */
    val_1 |= (ddr_cfg->tWTR - 1);
    }

    param->sdram_tim1 = val_1;

    /* bit[30-28] reg_t_xp */
    if(1){
    /* Minimum number of DDR clock cycles from Powerdown exit to any */
    /* command other than a Read command, minus one. */
    /* For DDR2 and LPDDR1, this field must satisfy greater of tXP or */
    /* tCKE. */
    val_2 |= (ddr_cfg->tXP - 1) << 28;
    }

    /* bit[27-25] reg_t_odt */
    if(1){
    /* Minimum number of DDR clock cycles from ODT enable to write */
    /* data driven for DDR2 and DDR3. */
    /* reg_t_odt must be equal to tAOND. */
    val_2 |= ddr_cfg->tODT << 25;
    }

    /* bit[24-16] reg_t_xsnr */
    if(1){
    /* Minimum number of DDR clock cycles from Self-Refresh exit to any */
    /* command other than a Read command, minus one. */
    val_2 |= (ddr_cfg->tXSNR - 1) << 16;
    }

    /* bit[15-6] reg_t_xsrd */
    if(1){
    /* Minimum number of DDR clock cycles from Self-Refresh exit to a */
    /* Read command, minus one. */
    val_2 |= (ddr_cfg->tXSRD - 1) << 6;
    }

    /* bit[5-3] reg_t_rtp */
    if(1){
    /* Minimum number of DDR clock cycles from the last Read command */
    /* to a Pre-charge command for DDR2 and DDR3, minus one. */
    val_2 |= (ddr_cfg->tRTP - 1) << 3;
    }

    /* bit[2-0] reg_t_cke */
    if(1){
    /* Minimum number of DDR clock cycles between pad_cke_o changes, */
    /* minus one. */
    val_2 |= (ddr_cfg->tCKE - 1);
    }

    param->sdram_tim2 = val_2;

    /* bit[31-28] reg_t_pdll_ul */
    if(1){
    /* Minimum number of DDR clock cycles for PHY DLL to unlock. */
    /* A value of N will be equal to N x 128 clocks. */
    val_3 |= ddr_cfg->tPDLL_UL << 28;
    }

    /* bit[20-15] reg_zq_zqcs */
    if(1){
    /* Number of DDR clock clock cycles for a ZQCS command, minus one. */
    val_3 |= (ddr_cfg->tZQCS - 1) << 15;
    }

    /* bit[12-4] reg_t_rfc */
    if(1){
    /* Minimum number of DDR clock cycles from Refresh or Load Mode to */
    /* Refresh or Activate, minus one. */
    val_3 |= (ddr_cfg->tRFC - 1) << 4;
    }

    /* bit[3-0] reg_t_ras_max */
    if(1){
    /* Maximum number of reg_refresh_rate intervals from Activate to */
    /* Precharge command. */
    /* This field must be equal to ((tRASmax / tREFI)-1) rounded down to */
    /* the next lower integer. */
    /* This field is only applicable for mDDR. */
    /* This field must be programmed to 0xF for other SDRAM types. */
    val_3 |= 0x0f;
    }

    param->sdram_tim3 = val_3;
    }
    if(1){ /* SDRAM Config/Config_2 */
    u32 val = 0;

    /* bit[31:29] SDRAM Type selection. */
    switch(ddr_cfg->ddr_type){
    case DT_mDDR: val |= (1<<29); break;
    case DT_DDR1: val |= (0<<29); break;
    case DT_DDR2: val |= (2<<29); break;
    case DT_DDR3: val |= (3<<29); break;
    default: val |= (0<<29); break; /* suppose DDR3 */
    }

    /* bit[28:27] Internal bank position.*/
    if(1){
    /* Set to 0 to assign internal bank address bits from lower OCP */
    /* address bits, as shown in the tables for OCP Address to DDR2/3/mDDR Address Mapping. */

    /* Set to 1, 2, or 3 to assign internal bank address bits from higher */
    /* OCP address, as shown in the tables for OCP Address to DDR2/3/mDDR Address Mapping. */
    val |= (0<<27);
    }

    /* bit[26:24] */
    switch(ddr_cfg->odt_value){
    /* reg_ddr_term DDR2 and DDR3 termination resistor value. */
    /* |-------+----------+---------+---------+---------+----------+---------| */
    /* | Value | 0 | 1 | 2 | 3 | 4 | 5 | */
    /* |-------+----------+---------+---------+---------+----------+---------| */
    /* | DDR2 | disabled | 75 Ohm | 150 Ohm | 50 Ohm | NA | NA | */
    /* |-------+----------+---------+---------+---------+----------+---------| */
    /* | DDR3 | disabled | 1/4 Rzq | 1/2 Rzq | 1/6 Rzq | 1/12 Rzq | 1/8 Rzq | */
    /* |-------+----------+---------+---------+---------+----------+---------| */
    case ODT_DDR2_75_Ohm: val |= (1<<24); break;
    case ODT_DDR2_150_Ohm: val |= (2<<24); break;
    case ODT_DDR2_50_Ohm: val |= (3<<24); break;
    case ODT_DDR3_1_4_RZQ: val |= (1<<24); break;
    case ODT_DDR3_1_2_RZQ: val |= (2<<24); break;
    case ODT_DDR3_1_6_RZQ: val |= (3<<24); break;
    case ODT_DDR3_1_12_RZQ: val |= (4<<24); break;
    case ODT_DDR3_1_8_RZQ: val |= (5<<24); break;
    case ODT_DISBLED: val |= (0<<24); break;
    default : val |= (0<<24); break; /* default is disabled */
    }

    /* bit[23] DDR2 differential DQS enable */
    if(1){
    /* Set to 0 for single ended DQS. */
    /* Set to 1 for differential DQS. */
    if(ddr_cfg->differential_dqs)
    val |= 1<<23;
    else
    val |= 0<<23;
    }

    /* bit[22:21] */
    switch(ddr_cfg->odt_dynamic){
    /* DDR3 Dynamic ODT. */
    /* Set to 0 to turn off dynamic ODT. */
    /* Set to 1 for RZQ/4 and set to 2 for RZQ/2. */
    /* All other values are reserved. */

    case ODT_DYN_1_4_RZQ: val |= (1<<21); break;
    case ODT_DYN_1_2_RZQ: val |= (2<<21); break;
    case ODT_DYN_DISABLED: val |= (0<<21); break;
    default: val |= (0<<21); break; /* disabled DYN ODT */
    }

    /* bit[20] Disable DLL select */
    if(1){
    /* Set to 1 to disable DLL inside SDRAM. */

    /* hard code to enable the inside DLL */
    val &= ~(1<<20);
    }

    /* bit[19:18] */
    switch(ddr_cfg->ddr_type){
    /* SDRAM drive strength. */
    /* |---------+---------+---------+-----+-----| */
    /* | Value | 0 | 1 | 2 | 3 | */
    /* |---------+---------+---------+-----+-----| */
    /* | DDR 1/2 | normal | weak | NA | NA | */
    /* | LPDDR1 | full | 1/2 | 1/4 | 1/8 | */
    /* | DDR 3 | 1/6 RZQ | 1/7 RZQ | NA | NA | */
    /* |---------+---------+---------+-----+-----| */
    case DT_mDDR:
    switch(ddr_cfg->drv_strength){
    case DDR_DRV_STRENGTH_LPDDR_1_2: val |= (1<<18); break;
    case DDR_DRV_STRENGTH_LPDDR_1_4: val |= (2<<18); break;
    case DDR_DRV_STRENGTH_LPDDR_1_8: val |= (3<<18); break;
    case DDR_DRV_STRENGTH_LPDDR_FULL: val |= (0<<18); break;
    default: val |= (0<<18); break;
    }
    break;

    case DT_DDR1:
    case DT_DDR2:
    switch(ddr_cfg->drv_strength){
    case DDR_DRV_STRENGTH_DDR12_NORMAL: val |= (0<<18); break;
    case DDR_DRV_STRENGTH_DDR12_WEAK: val |= (1<<18); break;
    default: val |= (1<<18); break;
    }
    break;

    case DT_DDR3:
    switch(ddr_cfg->drv_strength){
    case DDR_DRV_STRENGTH_DDR3_1_6_RZQ: val |= (0<<18); break;
    case DDR_DRV_STRENGTH_DDR3_1_7_RZQ: val |= (1<<18); break;
    default: val |= (1<<18); break;
    }
    break;

    default:
    /* NOTE: */
    /* If we reach here, the DDR type is error. */
    break;
    }

    /* bit[17:16] DDR3 CAS Write latency.*/
    if(1){
    /* Value of 0, 1, 2, and 3 */
    /* (CAS write latency of 5, 6, 7, and 8) are supported. */
    /* Use the lowest value supported for best performance. */
    /* All other values are reserved. */

    val |= (ddr_cfg->tCWL-5)<<16;
    }

    /* bit[15:14] SDRAM data bus width. */
    if(1){
    /* Set to 0 for 32-bit; */
    /* Set to 1 for 16-bit. */
    /* All other values are reserved. */
    switch(ddr_cfg->data_width){
    case 16: val |= (1<<14); break;
    case 32: val |= (0<<14); break;
    default: val |= (0<<14); break;
    }
    }

    /* bit[13:10] CAS Latency. */
    switch(ddr_cfg->ddr_type){
    /* The value of this field defines the CAS latency to be used when */
    /* accessing connected SDRAM devices. */

    /* |------------+------+------+------+--------| */
    /* | Bits Value | DDR1 | DDR2 | DDR3 | LPDDR1 | */
    /* |------------+------+------+------+--------| */
    /* | 2 | 2 | 2 | 5 | 2 | */
    /* | 3 | 3 | 3 | - | 3 | */
    /* | 4 | - | 4 | 6 | - | */
    /* | 5 | 1.5 | 5 | - | - | */
    /* | 6 | 2.5 | - | 7 | - | */
    /* | 8 | - | - | 8 | - | */
    /* | 10 | - | - | 9 | - | */
    /* | 12 | - | - | 10 | - | */
    /* | 14 | - | - | 11 | - | */
    /* | Other | - | - | - | - | */
    /* |------------+------+------+------+--------| */

    case DT_mDDR:
    switch(ddr_cfg->tCL){
    case 2: val |= (2<<10); break;
    case 3: val |= (3<<10); break;
    default: val |= (3<<10); break;
    }
    break;

    case DT_DDR1:
    switch(ddr_cfg->tCL){
    case 2: val |= (2<<10); break;
    case 3: val |= (3<<10); break;
    case 15: val |= (5<<10); break; /* 1.5 */
    case 25: val |= (6<<10); break; /* 2.5 */
    default: val |= (6<<10); break;
    }
    break;

    case DT_DDR2:
    switch(ddr_cfg->tCL){
    case 2: val |= (2<<10); break;
    case 3: val |= (3<<10); break;
    case 4: val |= (4<<10); break;
    case 5: val |= (5<<10); break;
    default: val |= (5<<10); break;
    }
    break;

    case DT_DDR3:
    switch(ddr_cfg->tCL){
    case 5: val |= (2<<10); break;
    case 6: val |= (4<<10); break;
    case 7: val |= (6<<10); break;
    case 8: val |= (8<<10); break;
    case 9: val |= (10<<10); break;
    case 10: val |= (12<<10); break;
    case 11: val |= (14<<10); break;
    default: val |= (14<<10); break;
    }
    break;

    default:
    /* NOTE: */
    /* If we reach here, the DDR type is error. */
    break;
    }

    /* bit[9:7] Row Size */
    if(1){
    /* Defines the number of row address bits of connected SDRAM devices. */
    /* Set to 0 for 9 row bits, */
    /* set to 1 for 10 row bits, */
    /* set to 2 for 11 row bits, */
    /* set to 3 for 12 row bits, */
    /* set to 4 for 13 row bits, */
    /* set to 5 for 14 row bits, */
    /* set to 6 for 15 row bits, */
    /* set to 7 for 16 row bits. */
    /* This field is only used when reg_ibank_pos field in SDRAM Config */
    /* register is set to 1, 2, or 3, or reg_ebank_pos field in SDRAM */
    /* Config_2 register is set to 1. */
    val |= (ddr_cfg->row_bits-9) << 7;
    }

    /* bit[6:4] Internal Bank setup. */
    if(1){
    /* Internal Bank setup. */
    /* Defines number of banks inside connected SDRAM devices. */
    /* Set to 0 for 1 bank, */
    /* set to 1 for 2 banks, */
    /* set to 2 for 4 banks, */
    /* set to 3 for 8 banks. */
    /* All other values are reserved. */
    switch(ddr_cfg->nr_banks){
    case 1: val |= (0<<4); break;
    case 2: val |= (1<<4); break;
    case 4: val |= (2<<4); break;
    case 8: val |= (3<<4); break;
    default: val |= (3<<4); break; /* default is 8 banks */
    }
    }

    /* bit[3] External chip select setup. */
    if(1){
    /* Defines whether SDRAM accesses will use 1 or 2 chip select lines. */
    /* Set to 0 to use pad_cs_o_n[0] only. */
    /* All other values reserved. */

    val &= ~(1<<3);
    }

    /* bit[2:0] Page Size. */
    switch(ddr_cfg->col_bits){
    /* Defines the internal page size of connected SDRAM devices. */
    /* Set to 0 for 256-word page (8 column bits), */
    /* set to 1 for 512-word page (9 column bits), */
    /* set to 2 for 1024-word page (10 column bits), */
    /* set to 3 for 2048-word page (11 column bits). */
    /* All other values are reserved. */
    case 8: val |= 0; break;
    case 9: val |= 1; break;
    case 10: val |= 2; break;
    case 11: val |= 3; break;
    default: val |= 3; break; /* default 11 column bits */
    }

    param->sdram_config = val;
    }
    if(1){ /* 7.3.5.29 ZQ_CONFIG Register (offset = C8h) [reset = 0h] */
    u32 val = 0;

    /* 0x50074BE4; */
    /* 0x50070924 */
    /* 0101_0000 0000_0111 0100_1011 1110_0100 */

    /* bit[31] reg_zq_cs1en */
    if(1){ /* Writing a 1 enables ZQ calibration for CS1. */
    val |= 0 << 31; /* disable CS1 */
    }

    /* bit[30] reg_zq_cs0en */
    if(1){ /* Writing a 1 enables ZQ calibration for CS0. */
    val |= 1 << 30; /* disable CS1 */
    }

    /* bit[29] reg_zq_dualcalen */
    if(1){ /* ZQ Dual Calibration enable. */
    /* Allows both ranks to be ZQ calibrated simultaneously. */
    /* Setting this bit requires both chip selects to have a seerate */
    /* calibration resistor per device. */
    val |= 0 << 29;
    }

    /* bit[28] reg_zq_sfexiten */
    if(1){
    /* ZQCL on Self Refresh, Active Power-Down, and Precharge Power-Down exit enable. */
    /* Writing a 1 enables the issuing of ZQCL on Self-Refresh, Active */
    /* Power-Down, and Precharge Power-Down exit. */
    val |= 1 << 28;
    }

    /* bit[19-18] reg_zq_zqinit_mult */
    if(1){
    /* Indicates the number of ZQCL intervals that make up a ZQINIT */
    /* interval, minus one. */
    val |= 1 << 18;
    }

    /* bit[17-16] reg_zq_zqcl_mult */
    if(1){
    /* Indicates the number of ZQCS intervals that make up a ZQCL */
    /* interval, minus one. */
    /* ZQCS interval is defined by reg_zq_zqcs in SDRAM Timing 3 */
    /* Register. */
    val |= 3 << 16;
    }

    /* bit[15-0] reg_zq_refinterval */
    if(1){
    /* Number of refresh periods between ZQCS commans. */
    /* This field supports between one refresh period to 256 ms between */
    /* ZQCS calibration commands. */
    /* Refresh period is defined by reg_refresh_rate in SDRAM Refresh */
    /* Control register. */
    /* val |= ddr_cfg->clk_MHz / 10 * 78; */
    val |= 0x4be4; /* ??? */
    }
    param->zq_config = val;
    }
    }


    void dump_ddr_params(const struct ddr_params* p)
    {
    if(!p)
    return;

    printf(" cmd = %05d(0x%04x)\n", p->phy_slave_ratio_cmd, p->phy_slave_ratio_cmd );
    printf(" rd_dqs = %05d(0x%04x)\n", p->phy_slave_ratio_rd_dqs, p->phy_slave_ratio_rd_dqs );
    printf(" wr_dqs = %05d(0x%04x)\n", p->phy_slave_ratio_wr_dqs, p->phy_slave_ratio_wr_dqs );
    printf(" fifo_we = %05d(0x%04x)\n", p->phy_slave_ratio_fifo_we, p->phy_slave_ratio_fifo_we);
    printf(" wr_data = %05d(0x%04x)\n", p->phy_slave_ratio_wr_data, p->phy_slave_ratio_wr_data);
    }

    int ddr_config_load(struct am335x_ddr_config* cfg /* [output] */)
    {
    int res;
    uchar buf[16];


    /* disable loading DDR param from i2/eeprom temporarily */
    ddr_config_default(0, cfg);
    res = 0;
    goto finish;

    eeprom_init(1);

    if(0){ /* EEPROM write */
    #if 0
    unsigned int eeprom_wp = IMX_GPIO_NR(2, 12);

    gpio_request(eeprom_wp, NULL);

    gpio_direction_output(eeprom_wp, 0);
    mdelay(10);
    gpio_set_value(eeprom_wp, 0);
    mdelay(10);

    buf[0] = 0x0;
    buf[1] = 0x1;
    buf[2] = 0x2;
    buf[3] = 0x3;
    buf[4] = 0x4;
    buf[5] = 0x5;
    buf[6] = 0x6;
    buf[7] = 0x7;
    res = eeprom_write(0x50, 0, buf, 8);
    printf("EEPROM write, res = %d\n", res);
    mdelay(10);
    gpio_set_value(eeprom_wp, 1);
    gpio_free(eeprom_wp);
    #endif
    }

    memset(buf, 0, sizeof(buf));
    res = eeprom_read(0x50, 0, buf, sizeof(buf));
    if(!res){
    REPORT_INF(0, "EEPROM read OK:");
    printf(" %02x %02x %02x %02x %02x %02x %02x %02x\n"
    " %02x %02x %02x %02x %02x %02x %02x %02x\n",
    buf[0], buf[1], buf[2], buf[3],
    buf[4], buf[5], buf[6], buf[7],
    buf[8], buf[9], buf[10], buf[11],
    buf[12], buf[13], buf[14], buf[15]);
    }else{
    REPORT_ERR(0, "EEPROM read failed, res=%d", res);
    }

    finish:
    return res;
    }

    void ddr_config_commit(const struct am335x_ddr_config* ddr_cfg)
    {
    struct ctrl_ioregs ddr_ioregs;
    struct ddr_data ddr_data;
    struct cmd_control ddr_cmdctrl;
    struct emif_regs ddr_emif_regs;

    init_ddr_param_ctrl_ioregs(ddr_cfg, &ddr_ioregs);
    init_ddr_param_data (ddr_cfg, &ddr_data);
    init_ddr_param_cmdctrl (ddr_cfg, &ddr_cmdctrl);
    init_ddr_param_emif_reg (ddr_cfg, &ddr_emif_regs);

    config_ddr(0,
    &ddr_ioregs,
    &ddr_data,
    &ddr_cmdctrl,
    &ddr_emif_regs,
    0);
    }

    void ddr_config_default(unsigned int which, struct am335x_ddr_config* ddr_cfg /* [out] */)
    {
    static struct am335x_ddr_config s_ddr_cfgs[] = {
    #if defined CONFIG_TARGET_ZKTY_PA5304
    { /* MT41K256M16HA-125 IT:E */
    .clk_MHz = 399, /* 400 MHz */
    .ddr_type = DT_DDR3,
    .capacity = (512<<20), /* 512 MiB */

    .slewrate_clk = DSR_FASTEST,
    .slewrate_cmdaddr = DSR_FASTEST,
    .slewrate_dqs = DSR_FASTEST,
    .slewrate_dq = DSR_FASTEST,

    .output_imp_clk = D_OIM_0_88,
    .output_imp_cmdaddr = D_OIM_1_00,
    .output_imp_dqs = D_OIM_0_88,
    .output_imp_dq = D_OIM_1_00,

    .odt_value = ODT_DDR3_1_2_RZQ,
    .odt_dynamic = ODT_DYN_1_2_RZQ,

    .differential_dqs = 1,
    .drv_strength = DDR_DRV_STRENGTH_DDR3_1_6_RZQ,

    .data_width = 16,
    .row_bits = 15, /* A0-A14 */
    .col_bits = 10, /* A0-A9, page size is 2K bytes */
    .nr_banks = 8,

    .tCL = 6,
    .tCWL = 5,
    .tAL = 2,
    .tRP = 6,
    .tRCD = 6,
    .tWR = 6,
    .tRAS = 14,
    .tRC = 20,
    .tRRD = 4, /* for 8banks DDR2/3 must be (tFAW/(4*tCK)) */
    .tWTR = 4,
    .tXP = 3,
    .tODT = 6,

    .tXSNR = 4, /* 90, */ /* ??? */
    .tXSRD = 9, /* 511, */ /* ??? */
    .tRTP = 4,
    .tCKE = 2, /* ??? */
    .tPDLL_UL = 5, /* ??? */
    .tZQCS = 64,
    .tRFC = 104,

    .adjustable_params = {
    .phy_slave_ratio_cmd = 128,
    .phy_slave_ratio_rd_dqs = 66,
    .phy_slave_ratio_wr_dqs = 1,
    .phy_slave_ratio_fifo_we = 57,
    .phy_slave_ratio_wr_data = 60,
    },

    .phy_wrlvl_init_ratio = 0x20, /* no effect */
    .phy_gatelvl_init_ratio = 0x20, /* no effect */
    },
    #elif defined CONFIG_TARGET_ZKTY_CP5502
    { /* MT41K512M16VRN-107 IT:P */
    .clk_MHz = 399, /* 400 MHz */
    .ddr_type = DT_DDR3,
    .capacity = (1024<<20), /* 1204 MiB */

    .slewrate_clk = DSR_FASTEST,
    .slewrate_cmdaddr = DSR_FASTEST,
    .slewrate_dqs = DSR_FASTEST,
    .slewrate_dq = DSR_FASTEST,

    .output_imp_clk = D_OIM_0_88,
    .output_imp_cmdaddr = D_OIM_1_00,
    .output_imp_dqs = D_OIM_0_88,
    .output_imp_dq = D_OIM_1_00,

    .odt_value = ODT_DDR3_1_2_RZQ,
    .odt_dynamic = ODT_DYN_1_2_RZQ,

    .differential_dqs = 1,
    .drv_strength = DDR_DRV_STRENGTH_DDR3_1_7_RZQ,

    .data_width = 16,
    .row_bits = 16, /* A0-A15 */
    .col_bits = 10, /* A0-A9, page size is 2K bytes */
    .nr_banks = 8,

    .tCL = 6,
    .tCWL = 5,
    .tAL = 2,
    .tRP = 6,
    .tRCD = 6,
    .tWR = 6,
    .tRAS = 14,
    .tRC = 20,
    .tRRD = 4, /* for 8banks DDR2/3 must be (tFAW/(4*tCK)) */
    .tWTR = 4,
    .tXP = 3,
    .tODT = 6,

    .tXSNR = 107, /* 90, */ /* ??? */
    .tXSRD = 512, /* 511, */ /* ??? */
    .tRTP = 4,
    .tCKE = 3, /* ??? */
    .tPDLL_UL = 5, /* ??? */
    .tZQCS = 64,
    .tRFC = 104,

    .adjustable_params = {
    .phy_slave_ratio_cmd = 120,
    .phy_slave_ratio_rd_dqs = 57,
    .phy_slave_ratio_wr_dqs = 52,
    .phy_slave_ratio_fifo_we = 130,
    .phy_slave_ratio_wr_data = 108,
    },
    .phy_wrlvl_init_ratio = 0x20, /* no effect */
    .phy_gatelvl_init_ratio = 0x20, /* no effect */
    },

    { /* MT41K256M16TW-107 IT:P */
    .clk_MHz = 399, /* 400 MHz */
    .ddr_type = DT_DDR3,
    .capacity = (512<<20), /* 512 MiB */

    .slewrate_clk = DSR_FASTEST,
    .slewrate_cmdaddr = DSR_FASTEST,
    .slewrate_dqs = DSR_FASTEST,
    .slewrate_dq = DSR_FASTEST,

    .output_imp_clk = D_OIM_0_88,
    .output_imp_cmdaddr = D_OIM_1_00,
    .output_imp_dqs = D_OIM_0_88,
    .output_imp_dq = D_OIM_1_00,

    .odt_value = ODT_DDR3_1_2_RZQ,
    .odt_dynamic = ODT_DYN_1_2_RZQ,

    .differential_dqs = 1,
    .drv_strength = DDR_DRV_STRENGTH_DDR3_1_7_RZQ,

    .data_width = 16,
    .row_bits = 15, /* A0-A14 */
    .col_bits = 10, /* A0-A9, page size is 2K bytes */
    .nr_banks = 8,

    .tCL = 6,
    .tCWL = 5,
    .tAL = 2,
    .tRP = 6,
    .tRCD = 6,
    .tWR = 6,
    .tRAS = 14,
    .tRC = 20,
    .tRRD = 4, /* for 8banks DDR2/3 must be (tFAW/(4*tCK)) */
    .tWTR = 4,
    .tXP = 3,
    .tODT = 6,

    .tXSNR = 107, /* 90, */ /* ??? */
    .tXSRD = 512, /* 511, */ /* ??? */
    .tRTP = 4,
    .tCKE = 3, /* ??? */
    .tPDLL_UL = 5, /* ??? */
    .tZQCS = 64,
    .tRFC = 104,

    .adjustable_params = {
    .phy_slave_ratio_cmd = 120,
    .phy_slave_ratio_rd_dqs = 57,
    .phy_slave_ratio_wr_dqs = 52,
    .phy_slave_ratio_fifo_we = 130,
    .phy_slave_ratio_wr_data = 108,
    },
    .phy_wrlvl_init_ratio = 0x20, /* no effect */
    .phy_gatelvl_init_ratio = 0x20, /* no effect */
    },
    #endif
    };

    assert(which < ARRAY_SIZE(s_ddr_cfgs));
    *ddr_cfg = s_ddr_cfgs[which];
    return;
    }

    /******************************************************************************/
    /*--------------------------- The End of This File ---------------------------*/


  • Hello Ryan,

    Thank you.

    Issue CKE looks like it should be solvable, we'll try it。

    Ok.

    But we still need help with the tWPST issue.

    I will have to assign the query to the DDR expert.

    Regards,

    Sreenivasa

  • Ryan, please check here for patch on CKE issue: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1302074/am3354-delay-between-ddr_cke-and-ddr_reset-configuration-in-spl

    There isn't a specific register that adjusts tWPST.  Can you double check that all of the EMIF registers are programmed correctly.  Be sure to use the AM335x EMIF tool spreadsheet https://www.ti.com/lit/pdf/sprack4 to obtain the correct register configuration for your board.  We have not seen this issue with other customers.

    Regards,

    James

  • Thank you for your replay.


    The root cause of the tWPST problem is that the DQS/# signals were reversed during testing.