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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
|
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#ifndef __LIBDRAM_CONFIG_H__
#define __LIBDRAM_CONFIG_H__
#include <libbdk-arch/bdk-csrs-lmc.h>
#define DDR_CFG_T_MAX_DIMMS 2 /* ThunderX supports a max of two DIMMs per LMC */
/* Structure that provides DIMM information, either in the form of an SPD TWSI
address, or a pointer to an array that contains SPD data. One of the two
fields must be valid. Note that these fields historically were dimension 2, left
over from CN38XX/CN58XX. These chips supported a 128 bit wide LMC, requiring
two DIMMs. All other chips use a 64bit wide LMC with multiple LMCs. All
Thunder chips use one DIMM for 64bits, so we no longer use an index */
typedef struct {
uint16_t spd_addr; /* TWSI address of SPD, 0 if not used */
const uint8_t *spd_ptr; /* pointer to SPD data array, NULL if not used */
} dimm_config_t;
typedef struct {
uint8_t odt_ena; /* FIX: dqx_ctl for Octeon 3 DDR4 */
uint64_t odt_mask; /* FIX: wodt_mask for Octeon 3 */
bdk_lmcx_modereg_params1_t odt_mask1;
bdk_lmcx_modereg_params2_t odt_mask2; /* FIX: needed for DDR4 */
uint8_t qs_dic; /* FIX: rodt_ctl for Octeon 3 */
uint64_t rodt_ctl; /* FIX: rodt_mask for Octeon 3 */
} dimm_odt_config_t;
/*
The parameters below make up the custom_lmc_config data structure.
This structure is used to customize the way that the LMC DRAM
Controller is configured for a particular board design.
The HRM describes LMC Read Leveling which supports automatic
selection of per byte-lane delays. When measuring the read delays
the LMC configuration software sweeps through a range of settings
for LMC0_COMP_CTL2[RODT_CTL], the Octeon II on-die-termination
resistance and LMC0_MODEREG_PARAMS1[RTT_NOM_XX], the DRAM
on-die-termination resistance. The minimum and maximum parameters
for rtt_nom_idx and rodt_ctl listed below determine the ranges of
ODT settings used for the measurements. Note that for rtt_nom an
index is used into a sorted table rather than the direct csr setting
in order to optimize the sweep.
.min_rtt_nom_idx: 1=120ohms, 2=60ohms, 3=40ohms, 4=30ohms, 5=20ohms
.max_rtt_nom_idx: 1=120ohms, 2=60ohms, 3=40ohms, 4=30ohms, 5=20ohms
.min_rodt_ctl: 1=20ohms, 2=30ohms, 3=40ohms, 4=60ohms, 5=120ohms
.max_rodt_ctl: 1=20ohms, 2=30ohms, 3=40ohms, 4=60ohms, 5=120ohms
The settings below control the Octeon II drive strength for the CK,
ADD/CMD, and DQ/DQS signals. 1=24ohms, 2=26.67ohms, 3=30ohms,
4=34.3ohms, 5=40ohms, 6=48ohms, 6=60ohms.
.dqx_ctl: Drive strength control for DDR_DQX/DDR_DQS_X_P/N drivers.
.ck_ctl: Drive strength control for DDR_CK_X_P/DDR_DIMMX_CSX_L/DDR_DIMMX_ODT_X drivers.
.cmd_ctl: Drive strength control for CMD/A/RESET_L/CKEX drivers.
The LMC controller software selects the most optimal CAS Latency
that complies with the appropriate SPD values and the frequency
that the DRAMS are being operated. When operating the DRAMs at
frequencies substantially lower than their rated frequencies it
might be necessary to limit the minimum CAS Latency the LMC
controller software is allowed to select in order to make the DRAM
work reliably.
.min_cas_latency: Minimum allowed CAS Latency
The value used for LMC0_RLEVEL_CTL[OFFSET_EN] determine how the
read-leveling information that the Octeon II gathers is interpreted
to determine the per-byte read delays.
.offset_en: Value used for LMC0_RLEVEL_CTL[OFFSET_EN].
.offset_udimm: Value used for LMC0_RLEVEL_CTL[OFFSET] for UDIMMS.
.offset_rdimm: Value used for LMC0_RLEVEL_CTL[OFFSET] for RDIMMS.
The LMC configuration software sweeps through a range of ODT
settings while measuring the per-byte read delays. During those
measurements the software makes an assessment of the quality of the
measurements in order to determine which measurements provide the
most accurate delays. The automatic settings provide the option to
allow that same assessment to determine the most optimal RODT_CTL
and/or RTT_NOM settings.
The automatic approach might provide the best means to determine
the settings used for initial poweron of a new design. However,
the final settings should be determined by board analysis, testing,
and experience.
.ddr_rtt_nom_auto: 1 means automatically set RTT_NOM value.
.ddr_rodt_ctl_auto: 1 means automatically set RODT_CTL value.
.rlevel_compute: Enables software interpretation of per-byte read
delays using the measurements collected by the
Octeon II rather than completely relying on the
Octeon II to determine the delays. 1=software
computation is recommended since a more complete
analysis is implemented in software.
.rlevel_comp_offset: Set to 2 unless instructed differently by Cavium.
.rlevel_average_loops: Determines the number of times the read-leveling
sequence is run for each rank. The results is
then averaged across the number of loops. The
default setting is 1.
.ddr2t_udimm:
.ddr2t_rdimm: Turn on the DDR 2T mode. 2-cycle window for CMD and
address. This mode helps relieve setup time pressure
on the address and command bus. Please refer to
Micron's tech note tn_47_01 titled DDR2-533 Memory
Design Guide for Two Dimm Unbuffered Systems for
physical details.
.disable_sequential_delay_check: As result of the flyby topology
prescribed in the JEDEC specifications the byte delays should
maintain a consistent increasing or decreasing trend across
the bytes on standard dimms. This setting can be used disable
that check for unusual circumstances where the check is not
useful.
.maximum_adjacent_rlevel_delay_increment: An additional sequential
delay check for the delays that result from the flyby
topology. This value specifies the maximum difference between
the delays of adjacent bytes. A value of 0 disables this
check.
.fprch2 Front Porch Enable: When set, the turn-off
time for the default DDR_DQ/DQS drivers is FPRCH2 CKs earlier.
00 = 0 CKs
01 = 1 CKs
10 = 2 CKs
.parity: The parity input signal PAR_IN on each dimm must be
strapped high or low on the board. This bit is programmed
into LMC0_DIMM_CTL[PARITY] and it must be set to match the
board strapping. This signal is typically strapped low.
.mode32b: Enable 32-bit datapath mode. Set to 1 if only 32 DQ pins
are used. (cn61xx, cn71xx)
.dll_write_offset: FIXME: Add description
.dll_read_offset: FIXME: Add description
*/
typedef struct {
const char *part;
int speed;
uint64_t rlevel_rank[4][4];
} rlevel_table_t;
typedef struct {
uint8_t min_rtt_nom_idx;
uint8_t max_rtt_nom_idx;
uint8_t min_rodt_ctl;
uint8_t max_rodt_ctl;
//uint8_t dqx_ctl;
uint8_t ck_ctl;
uint8_t cmd_ctl;
uint8_t ctl_ctl;
uint8_t min_cas_latency;
uint8_t offset_en;
uint8_t offset_udimm;
uint8_t offset_rdimm;
uint8_t rlevel_compute;
uint8_t ddr_rtt_nom_auto;
uint8_t ddr_rodt_ctl_auto;
uint8_t rlevel_comp_offset_udimm;
uint8_t rlevel_comp_offset_rdimm;
uint8_t rlevel_average_loops;
uint8_t ddr2t_udimm;
uint8_t ddr2t_rdimm;
uint8_t disable_sequential_delay_check;
uint8_t maximum_adjacent_rlevel_delay_increment;
uint8_t parity;
uint8_t fprch2;
uint8_t mode32b;
uint8_t measured_vref;
const int8_t *dll_write_offset; /* Indexed by byte number (0-8, includes ecc byte) */
const int8_t *dll_read_offset; /* Indexed by byte number (0-8, includes ecc byte) */
const rlevel_table_t *rlevel_table; /* Only used if ENABLE_CUSTOM_RLEVEL_TABLE. List of DIMMs to check */
} ddr3_custom_config_t;
typedef struct {
dimm_config_t dimm_config_table[DDR_CFG_T_MAX_DIMMS]; /* Indexed by DIMM */
dimm_odt_config_t odt_1rank_config[DDR_CFG_T_MAX_DIMMS]; /* Indexed by number of DIMMs minus 1 */
dimm_odt_config_t odt_2rank_config[DDR_CFG_T_MAX_DIMMS]; /* Indexed by number of DIMMs minus 1 */
dimm_odt_config_t odt_4rank_config[DDR_CFG_T_MAX_DIMMS]; /* Indexed by number of DIMMs minus 1 */
ddr3_custom_config_t custom_lmc_config;
} ddr_configuration_t;
typedef struct {
const char *name;
ddr_configuration_t config[4]; /* Indexed by LMC */
int ddr_clock_hertz;
} dram_config_t;
extern int libdram_config(int node, const dram_config_t *dram_config, int ddr_clock_override);
extern int libdram_tune(int node);
//extern int libdram_margin_write_voltage(int node);
//extern int libdram_margin_read_voltage(int node);
//extern int libdram_margin_read_timing(int node);
//extern int libdram_margin_write_timing(int node);
extern int libdram_margin(int node);
extern uint32_t libdram_get_freq(int node);
extern uint32_t libdram_get_freq_from_pll(int node, int lmc);
/**
* Load a DRAM configuration based on the current bdk-config settings
*
* @param node Node the DRAM config is for
*
* @return Pointer to __libdram_global_cfg, a global structure. Returns NULL if bdk-config
* lacks information about DRAM.
*/
extern const dram_config_t* libdram_config_load(bdk_node_t node);
/* The various DRAM configs in the libdram/configs directory need space
to store the DRAM config. Since only one config is ever in active use
at a time, store the configs in __libdram_global_cfg. In a multi-node
setup, independent calls to get the DRAM config will load first node 0's
config, then node 1's */
extern dram_config_t __libdram_global_cfg;
#endif /* __LIBDRAM_CONFIG_H__ */
|