uboot/board/xes/xpedite550x/ddr.c
<<
>>
Prefs
   1/*
   2 * Copyright 2010 Extreme Engineering Solutions, Inc.
   3 * Copyright 2007-2008 Freescale Semiconductor, Inc.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <i2c.h>
  10
  11#include <fsl_ddr_sdram.h>
  12#include <fsl_ddr_dimm_params.h>
  13
  14void get_spd(ddr3_spd_eeprom_t *spd, u8 i2c_address)
  15{
  16        i2c_read(i2c_address, SPD_EEPROM_OFFSET, 2, (uchar *)spd,
  17                 sizeof(ddr3_spd_eeprom_t));
  18}
  19
  20/*
  21 *     There are traditionally three board-specific SDRAM timing parameters
  22 *     which must be calculated based on the particular PCB artwork.  These are:
  23 *     1.) CPO (Read Capture Delay)
  24 *             - TIMING_CFG_2 register
  25 *             Source: Calculation based on board trace lengths and
  26 *                     chip-specific internal delays.
  27 *     2.) CLK_ADJUST (Clock and Addr/Cmd alignment control)
  28 *             - DDR_SDRAM_CLK_CNTL register
  29 *             Source: Signal Integrity Simulations
  30 *     3.) 2T Timing on Addr/Ctl
  31 *             - TIMING_CFG_2 register
  32 *             Source: Signal Integrity Simulations
  33 *             Usually only needed with heavy load/very high speed (>DDR2-800)
  34 *
  35 *     ====== XPedite550x DDR3-800 read delay calculations ======
  36 *
  37 *     The P2020 processor provides an autoleveling option. Setting CPO to
  38 *     0x1f enables this auto configuration.
  39 */
  40
  41typedef struct {
  42        unsigned short datarate_mhz_low;
  43        unsigned short datarate_mhz_high;
  44        unsigned char clk_adjust;
  45        unsigned char cpo;
  46} board_specific_parameters_t;
  47
  48const board_specific_parameters_t board_specific_parameters[][20] = {
  49        {
  50                /* Controller 0 */
  51                {
  52                        /* DDR3-600/667 */
  53                        .datarate_mhz_low       = 500,
  54                        .datarate_mhz_high      = 750,
  55                        .clk_adjust             = 5,
  56                        .cpo                    = 31,
  57                },
  58                {
  59                        /* DDR3-800 */
  60                        .datarate_mhz_low       = 750,
  61                        .datarate_mhz_high      = 850,
  62                        .clk_adjust             = 5,
  63                        .cpo                    = 31,
  64                },
  65        },
  66};
  67
  68void fsl_ddr_board_options(memctl_options_t *popts,
  69                                dimm_params_t *pdimm,
  70                                unsigned int ctrl_num)
  71{
  72        const board_specific_parameters_t *pbsp =
  73                                &(board_specific_parameters[ctrl_num][0]);
  74        u32 num_params = sizeof(board_specific_parameters[ctrl_num]) /
  75                                sizeof(board_specific_parameters[0][0]);
  76        u32 i;
  77        ulong ddr_freq;
  78
  79        /*
  80         * Set odt_rd_cfg and odt_wr_cfg. If the there is only one dimm in
  81         * that controller, set odt_wr_cfg to 4 for CS0, and 0 to CS1. If
  82         * there are two dimms in the controller, set odt_rd_cfg to 3 and
  83         * odt_wr_cfg to 3 for the even CS, 0 for the odd CS.
  84         */
  85        for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
  86                if (i&1) {      /* odd CS */
  87                        popts->cs_local_opts[i].odt_rd_cfg = 0;
  88                        popts->cs_local_opts[i].odt_wr_cfg = 0;
  89                } else {        /* even CS */
  90                        if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
  91                                popts->cs_local_opts[i].odt_rd_cfg = 0;
  92                                popts->cs_local_opts[i].odt_wr_cfg = 4;
  93                        } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
  94                                popts->cs_local_opts[i].odt_rd_cfg = 3;
  95                                popts->cs_local_opts[i].odt_wr_cfg = 3;
  96                        }
  97                }
  98        }
  99
 100        /*
 101         * Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
 102         * freqency and n_banks specified in board_specific_parameters table.
 103         */
 104        ddr_freq = get_ddr_freq(0) / 1000000;
 105
 106        for (i = 0; i < num_params; i++) {
 107                if (ddr_freq >= pbsp->datarate_mhz_low &&
 108                    ddr_freq <= pbsp->datarate_mhz_high) {
 109                        popts->clk_adjust = pbsp->clk_adjust;
 110                        popts->cpo_override = pbsp->cpo;
 111                        popts->twot_en = 0;
 112                        break;
 113                }
 114                pbsp++;
 115        }
 116
 117        if (i == num_params) {
 118                printf("Warning: board specific timing not found "
 119                "for data rate %lu MT/s!\n", ddr_freq);
 120        }
 121
 122        /*
 123         * Factors to consider for half-strength driver enable:
 124         *      - number of DIMMs installed
 125         */
 126        popts->half_strength_driver_enable = 0;
 127
 128        /*
 129         * Enable on-die termination.
 130         * From the Micron Technical Node TN-41-04, RTT_Nom should typically
 131         * be 30 to 40 ohms, while RTT_WR should be 120 ohms.  Setting RTT_WR
 132         * is handled in the Freescale DDR3 driver.  Set RTT_Nom here.
 133         */
 134        popts->rtt_override = 1;
 135        popts->rtt_override_value = 3;
 136}
 137