uboot/board/freescale/t4qds/ddr.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Freescale Semiconductor, Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License
   6 * Version 2 or later as published by the Free Software Foundation.
   7 */
   8
   9#include <common.h>
  10#include <i2c.h>
  11#include <hwconfig.h>
  12#include <asm/mmu.h>
  13#include <asm/fsl_ddr_sdram.h>
  14#include <asm/fsl_ddr_dimm_params.h>
  15#include <asm/fsl_law.h>
  16
  17DECLARE_GLOBAL_DATA_PTR;
  18
  19struct board_specific_parameters {
  20        u32 n_ranks;
  21        u32 datarate_mhz_high;
  22        u32 clk_adjust;
  23        u32 wrlvl_start;
  24        u32 wrlvl_ctl_2;
  25        u32 wrlvl_ctl_3;
  26        u32 cpo;
  27        u32 write_data_delay;
  28        u32 force_2T;
  29};
  30
  31/*
  32 * This table contains all valid speeds we want to override with board
  33 * specific parameters. datarate_mhz_high values need to be in ascending order
  34 * for each n_ranks group.
  35 */
  36static const struct board_specific_parameters udimm0[] = {
  37        /*
  38         * memory controller 0
  39         *   num|  hi|  clk| wrlvl |   wrlvl   |  wrlvl | cpo  |wrdata|2T
  40         * ranks| mhz|adjst| start |   ctl2    |  ctl3  |      |delay |
  41         */
  42        {2,  1350,    5,     7, 0x0809090b, 0x0c0c0d09,   0xff,    2,  0},
  43        {2,  1666,    5,     8, 0x080a0a0c, 0x0c0d0e0a,   0xff,    2,  0},
  44        {2,  2140,    5,     8, 0x090a0b0c, 0x0e0f100b,   0xff,    2,  0},
  45        {1,  1350,    5,     8, 0x0809090b, 0x0c0c0d0a,   0xff,    2,  0},
  46        {1,  1700,    5,     8, 0x080a0a0c, 0x0c0d0e0a,   0xff,    2,  0},
  47        {1,  1900,    4,     8, 0x080a0a0c, 0x0e0e0f0a,   0xff,    2,  0},
  48        {1,  2140,    4,     8, 0x090a0b0c, 0x0e0f100b,   0xff,    2,  0},
  49        {}
  50};
  51
  52/*
  53 * The three slots have slightly different timing. The center values are good
  54 * for all slots. We use identical speed tables for them. In future use, if
  55 * DIMMs require separated tables, make more entries as needed.
  56 */
  57static const struct board_specific_parameters *udimms[] = {
  58        udimm0,
  59};
  60
  61static const struct board_specific_parameters rdimm0[] = {
  62        /*
  63         * memory controller 0
  64         *   num|  hi|  clk| wrlvl |   wrlvl   |  wrlvl | cpo  |wrdata|2T
  65         * ranks| mhz|adjst| start |   ctl2    |  ctl3  |      |delay |
  66         */
  67        {4,  1350,    5,     9, 0x08070605, 0x07080805,   0xff,    2,  0},
  68        {4,  1666,    5,     8, 0x08070605, 0x07080805,   0xff,    2,  0},
  69        {4,  2140,    5,     8, 0x08070605, 0x07081805,   0xff,    2,  0},
  70        {2,  1350,    5,     7, 0x0809090b, 0x0c0c0d09,   0xff,    2,  0},
  71        {2,  1666,    5,     8, 0x080a0a0c, 0x0c0d0e0a,   0xff,    2,  0},
  72        {2,  2140,    5,     8, 0x090a0b0c, 0x0e0f100b,   0xff,    2,  0},
  73        {1,  1350,    5,     8, 0x0809090b, 0x0c0c0d0a,   0xff,    2,  0},
  74        {1,  1700,    5,     8, 0x080a0a0c, 0x0c0d0e0a,   0xff,    2,  0},
  75        {1,  1900,    4,     8, 0x080a0a0c, 0x0e0e0f0a,   0xff,    2,  0},
  76        {1,  2140,    4,     8, 0x090a0b0c, 0x0e0f100b,   0xff,    2,  0},
  77        {}
  78};
  79
  80/*
  81 * The three slots have slightly different timing. See comments above.
  82 */
  83static const struct board_specific_parameters *rdimms[] = {
  84        rdimm0,
  85};
  86
  87void fsl_ddr_board_options(memctl_options_t *popts,
  88                                dimm_params_t *pdimm,
  89                                unsigned int ctrl_num)
  90{
  91        const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
  92        ulong ddr_freq;
  93
  94        if (ctrl_num > 2) {
  95                printf("Not supported controller number %d\n", ctrl_num);
  96                return;
  97        }
  98        if (!pdimm->n_ranks)
  99                return;
 100
 101        /*
 102         * we use identical timing for all slots. If needed, change the code
 103         * to  pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num];
 104         */
 105        if (popts->registered_dimm_en)
 106                pbsp = rdimms[0];
 107        else
 108                pbsp = udimms[0];
 109
 110
 111        /* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
 112         * freqency and n_banks specified in board_specific_parameters table.
 113         */
 114        ddr_freq = get_ddr_freq(0) / 1000000;
 115        while (pbsp->datarate_mhz_high) {
 116                if (pbsp->n_ranks == pdimm->n_ranks) {
 117                        if (ddr_freq <= pbsp->datarate_mhz_high) {
 118                                popts->cpo_override = pbsp->cpo;
 119                                popts->write_data_delay =
 120                                        pbsp->write_data_delay;
 121                                popts->clk_adjust = pbsp->clk_adjust;
 122                                popts->wrlvl_start = pbsp->wrlvl_start;
 123                                popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
 124                                popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
 125                                popts->twoT_en = pbsp->force_2T;
 126                                goto found;
 127                        }
 128                        pbsp_highest = pbsp;
 129                }
 130                pbsp++;
 131        }
 132
 133        if (pbsp_highest) {
 134                printf("Error: board specific timing not found "
 135                        "for data rate %lu MT/s\n"
 136                        "Trying to use the highest speed (%u) parameters\n",
 137                        ddr_freq, pbsp_highest->datarate_mhz_high);
 138                popts->cpo_override = pbsp_highest->cpo;
 139                popts->write_data_delay = pbsp_highest->write_data_delay;
 140                popts->clk_adjust = pbsp_highest->clk_adjust;
 141                popts->wrlvl_start = pbsp_highest->wrlvl_start;
 142                popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
 143                popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
 144                popts->twoT_en = pbsp_highest->force_2T;
 145        } else {
 146                panic("DIMM is not supported by this board");
 147        }
 148found:
 149        /*
 150         * Factors to consider for half-strength driver enable:
 151         *      - number of DIMMs installed
 152         */
 153        popts->half_strength_driver_enable = 0;
 154        /*
 155         * Write leveling override
 156         */
 157        popts->wrlvl_override = 1;
 158        popts->wrlvl_sample = 0xf;
 159
 160        /*
 161         * Rtt and Rtt_WR override
 162         */
 163        popts->rtt_override = 0;
 164
 165        /* Enable ZQ calibration */
 166        popts->zq_en = 1;
 167
 168        /* DHC_EN =1, ODT = 75 Ohm */
 169        popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_75ohm);
 170        popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_75ohm);
 171}
 172
 173phys_size_t initdram(int board_type)
 174{
 175        phys_size_t dram_size;
 176
 177        puts("Initializing....using SPD\n");
 178
 179        dram_size = fsl_ddr_sdram();
 180
 181        dram_size = setup_ddr_tlbs(dram_size / 0x100000);
 182        dram_size *= 0x100000;
 183
 184        puts("    DDR: ");
 185        return dram_size;
 186}
 187