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