hc
2023-06-12 22f2094bc421ab4159aec033f44a0aa239ac8e20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * Copyright 2009 Extreme Engineering Solutions, Inc.
 * Copyright 2007-2008 Freescale Semiconductor, Inc.
 *
 * SPDX-License-Identifier:    GPL-2.0+
 */
 
#include <common.h>
#include <i2c.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr_dimm_params.h>
 
void get_spd(ddr2_spd_eeprom_t *spd, u8 i2c_address)
{
   i2c_read(i2c_address, SPD_EEPROM_OFFSET, 2, (uchar *)spd,
       sizeof(ddr2_spd_eeprom_t));
}
 
/*
 * There are four board-specific SDRAM timing parameters which must be
 * calculated based on the particular PCB artwork.  These are:
 *   1.) CPO (Read Capture Delay)
 *           - TIMING_CFG_2 register
 *           Source: Calculation based on board trace lengths and
 *                   chip-specific internal delays.
 *   2.) WR_DATA_DELAY (Write Command to Data Strobe Delay)
 *           - TIMING_CFG_2 register
 *           Source: Calculation based on board trace lengths.
 *                   Unless clock and DQ lanes are very different
 *                   lengths (>2"), this should be set to the nominal value
 *                   of 1/2 clock delay.
 *   3.) CLK_ADJUST (Clock and Addr/Cmd alignment control)
 *           - DDR_SDRAM_CLK_CNTL register
 *           Source: Signal Integrity Simulations
 *   4.) 2T Timing on Addr/Ctl
 *           - TIMING_CFG_2 register
 *           Source: Signal Integrity Simulations
 *           Usually only needed with heavy load/very high speed (>DDR2-800)
 *
 *     PCB routing on the XPedite5170 is nearly identical to the XPedite5370
 *     so we use the XPedite5370 settings as a basis for the XPedite5170.
 */
 
typedef struct board_memctl_options {
   uint16_t datarate_mhz_low;
   uint16_t datarate_mhz_high;
   uint8_t clk_adjust;
   uint8_t cpo_override;
   uint8_t write_data_delay;
} board_memctl_options_t;
 
static struct board_memctl_options bopts_ctrl[][2] = {
   {
       /* Controller 0 */
       {
           /* DDR2 600/667 */
           .datarate_mhz_low    = 500,
           .datarate_mhz_high    = 750,
           .clk_adjust        = 5,
           .cpo_override        = 8,
           .write_data_delay    = 2,
       },
       {
           /* DDR2 800 */
           .datarate_mhz_low    = 750,
           .datarate_mhz_high    = 850,
           .clk_adjust        = 5,
           .cpo_override        = 9,
           .write_data_delay    = 2,
       },
   },
   {
       /* Controller 1 */
       {
           /* DDR2 600/667 */
           .datarate_mhz_low    = 500,
           .datarate_mhz_high    = 750,
           .clk_adjust        = 5,
           .cpo_override        = 7,
           .write_data_delay    = 2,
       },
       {
           /* DDR2 800 */
           .datarate_mhz_low    = 750,
           .datarate_mhz_high    = 850,
           .clk_adjust        = 5,
           .cpo_override        = 8,
           .write_data_delay    = 2,
       },
   },
};
 
void fsl_ddr_board_options(memctl_options_t *popts,
           dimm_params_t *pdimm,
           unsigned int ctrl_num)
{
   struct board_memctl_options *bopts = bopts_ctrl[ctrl_num];
   sys_info_t sysinfo;
   int i;
   unsigned int datarate;
 
   get_sys_info(&sysinfo);
   datarate = get_ddr_freq(0) / 1000000;
 
   for (i = 0; i < ARRAY_SIZE(bopts_ctrl[ctrl_num]); i++) {
       if ((bopts[i].datarate_mhz_low <= datarate) &&
           (bopts[i].datarate_mhz_high >= datarate)) {
           debug("controller %d:\n", ctrl_num);
           debug(" clk_adjust = %d\n", bopts[i].clk_adjust);
           debug(" cpo = %d\n", bopts[i].cpo_override);
           debug(" write_data_delay = %d\n",
               bopts[i].write_data_delay);
           popts->clk_adjust = bopts[i].clk_adjust;
           popts->cpo_override = bopts[i].cpo_override;
           popts->write_data_delay = bopts[i].write_data_delay;
       }
   }
 
   /*
    * Factors to consider for half-strength driver enable:
    *    - number of DIMMs installed
    */
   popts->half_strength_driver_enable = 0;
}