xref: /aosp_15_r20/external/coreboot/src/vendorcode/cavium/bdk/libdram/libdram-config-load.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /***********************license start***********************************
2 * Copyright (c) 2003-2017  Cavium Inc. ([email protected]). All rights
3 * reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *   * Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 *
13 *   * Redistributions in binary form must reproduce the above
14 *     copyright notice, this list of conditions and the following
15 *     disclaimer in the documentation and/or other materials provided
16 *     with the distribution.
17 *
18 *   * Neither the name of Cavium Inc. nor the names of
19 *     its contributors may be used to endorse or promote products
20 *     derived from this software without specific prior written
21 *     permission.
22 *
23 * This Software, including technical data, may be subject to U.S. export
24 * control laws, including the U.S. Export Administration Act and its
25 * associated regulations, and may be subject to export or import
26 * regulations in other countries.
27 *
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
31 * TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
32 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
33 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
34 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
35 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
36 * QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK
37 * ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
39 #include <bdk.h>
40 
41 /* FIXME(dhendrix): added */
42 #include <console/console.h>	/* for die() */
43 #include <string.h>
44 #include <libbdk-arch/bdk-model.h>
45 #include <libbdk-hal/bdk-config.h>
46 #include <soc/twsi.h>
47 #include <device/i2c_simple.h>
48 
49 /**
50  * Load a "odt_*rank_config" structure
51  *
52  * @param cfg    Config to fill
53  * @param ranks  Number of ranks we're loading (1,2,4)
54  * @param node   Node we're loading for
55  * @param dimm   Which DIMM this is for
56  * @param lmc    Which LMC this is for
57  */
load_rank_data(dram_config_t * cfg,int ranks,int num_dimms,int lmc,bdk_node_t node)58 static void load_rank_data(dram_config_t *cfg, int ranks, int num_dimms, int lmc, bdk_node_t node)
59 {
60     /* Get a pointer to the structure we are filling */
61     dimm_odt_config_t *c;
62     switch (ranks)
63     {
64         case 1:
65             c = &cfg->config[lmc].odt_1rank_config[num_dimms - 1];
66             break;
67         case 2:
68             c = &cfg->config[lmc].odt_2rank_config[num_dimms - 1];
69             break;
70         case 4:
71             c = &cfg->config[lmc].odt_4rank_config[num_dimms - 1];
72             break;
73         default:
74             bdk_fatal("Unexpected number of ranks\n");
75             break;
76     }
77 
78     /* Fill the global items */
79     c->odt_ena      = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_DQX_CTL,      ranks, num_dimms, lmc, node);
80     c->odt_mask     = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_WODT_MASK,    ranks, num_dimms, lmc, node);
81 
82     /* Fill the per rank items */
83     int rank = 0;
84     c->odt_mask1.s.pasr_00              = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_PASR,    ranks, num_dimms, rank, lmc, node);
85     c->odt_mask1.s.asr_00               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_ASR,     ranks, num_dimms, rank, lmc, node);
86     c->odt_mask1.s.srt_00               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_SRT,     ranks, num_dimms, rank, lmc, node);
87     c->odt_mask1.s.rtt_wr_00            = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR,  ranks, num_dimms, rank, lmc, node);
88     c->odt_mask1.s.rtt_wr_00_ext        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR,  ranks, num_dimms, rank, lmc, node) >> 2;
89     c->odt_mask1.s.dic_00               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DIC,     ranks, num_dimms, rank, lmc, node);
90     c->odt_mask1.s.rtt_nom_00           = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM, ranks, num_dimms, rank, lmc, node);
91     c->odt_mask1.s.db_output_impedance  = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DB_OUTPUT_IMPEDANCE, ranks, num_dimms, lmc, node);
92     rank = 1;
93     c->odt_mask1.s.pasr_01              = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_PASR,    ranks, num_dimms, rank, lmc, node);
94     c->odt_mask1.s.asr_01               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_ASR,     ranks, num_dimms, rank, lmc, node);
95     c->odt_mask1.s.srt_01               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_SRT,     ranks, num_dimms, rank, lmc, node);
96     c->odt_mask1.s.rtt_wr_01            = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR,  ranks, num_dimms, rank, lmc, node);
97     c->odt_mask1.s.rtt_wr_01_ext        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR,  ranks, num_dimms, rank, lmc, node) >> 2;
98     c->odt_mask1.s.dic_01               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DIC,     ranks, num_dimms, rank, lmc, node);
99     c->odt_mask1.s.rtt_nom_01           = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM, ranks, num_dimms, rank, lmc, node);
100     rank = 2;
101     c->odt_mask1.s.pasr_10              = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_PASR,    ranks, num_dimms, rank, lmc, node);
102     c->odt_mask1.s.asr_10               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_ASR,     ranks, num_dimms, rank, lmc, node);
103     c->odt_mask1.s.srt_10               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_SRT,     ranks, num_dimms, rank, lmc, node);
104     c->odt_mask1.s.rtt_wr_10            = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR,  ranks, num_dimms, rank, lmc, node);
105     c->odt_mask1.s.rtt_wr_10_ext        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR,  ranks, num_dimms, rank, lmc, node) >> 2;
106     c->odt_mask1.s.dic_10               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DIC,     ranks, num_dimms, rank, lmc, node);
107     c->odt_mask1.s.rtt_nom_10           = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM, ranks, num_dimms, rank, lmc, node);
108     rank = 3;
109     c->odt_mask1.s.pasr_11              = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_PASR,    ranks, num_dimms, rank, lmc, node);
110     c->odt_mask1.s.asr_11               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_ASR,     ranks, num_dimms, rank, lmc, node);
111     c->odt_mask1.s.srt_11               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_SRT,     ranks, num_dimms, rank, lmc, node);
112     c->odt_mask1.s.rtt_wr_11            = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR,  ranks, num_dimms, rank, lmc, node);
113     c->odt_mask1.s.rtt_wr_11_ext        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR,  ranks, num_dimms, rank, lmc, node) >> 2;
114     c->odt_mask1.s.dic_11               = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DIC,     ranks, num_dimms, rank, lmc, node);
115     c->odt_mask1.s.rtt_nom_11           = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM, ranks, num_dimms, rank, lmc, node);
116     rank = 0;
117     c->odt_mask2.s.rtt_park_00          = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK,   ranks, num_dimms, rank, lmc, node);
118     c->odt_mask2.s.vref_value_00        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE, ranks, num_dimms, rank, lmc, node);
119     c->odt_mask2.s.vref_range_00        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE, ranks, num_dimms, rank, lmc, node);
120     c->odt_mask2.s.vrefdq_train_en      = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREFDQ_TRAIN_EN, ranks, num_dimms, lmc, node);
121     rank = 1;
122     c->odt_mask2.s.rtt_park_01          = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK,   ranks, num_dimms, rank, lmc, node);
123     c->odt_mask2.s.vref_value_01        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE, ranks, num_dimms, rank, lmc, node);
124     c->odt_mask2.s.vref_range_01        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE, ranks, num_dimms, rank, lmc, node);
125     rank = 2;
126     c->odt_mask2.s.rtt_park_10          = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK,   ranks, num_dimms, rank, lmc, node);
127     c->odt_mask2.s.vref_value_10        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE, ranks, num_dimms, rank, lmc, node);
128     c->odt_mask2.s.vref_range_10        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE, ranks, num_dimms, rank, lmc, node);
129     rank = 3;
130     c->odt_mask2.s.rtt_park_11          = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK,   ranks, num_dimms, rank, lmc, node);
131     c->odt_mask2.s.vref_value_11        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE, ranks, num_dimms, rank, lmc, node);
132     c->odt_mask2.s.vref_range_11        = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE, ranks, num_dimms, rank, lmc, node);
133 
134     /* Fill more global items */
135     c->qs_dic       = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_RODT_CTL,     ranks, num_dimms, lmc, node);
136     c->rodt_ctl     = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_RODT_MASK,    ranks, num_dimms, lmc, node);
137 }
138 
139 /**
140  * Load a DRAM configuration based on the current bdk-config settings
141  *
142  * @param node   Node the DRAM config is for
143  *
144  * @return Pointer to __libdram_global_cfg, a global structure. Returns NULL if bdk-config
145  *         lacks information about DRAM.
146  */
libdram_config_load(bdk_node_t node)147 const dram_config_t *libdram_config_load(bdk_node_t node)
148 {
149     dram_config_t *cfg = &__libdram_global_cfg;
150     const int MAX_LMCS = ARRAY_SIZE(cfg->config);
151 
152     /* Make all fields for the node default to zero */
153     memset(cfg, 0, sizeof(*cfg));
154 
155     /* Fill the SPD data first as some parameters need to know the DRAM type
156        to lookup the correct values */
157     for (int lmc = 0; lmc < MAX_LMCS; lmc++)
158     {
159         for (int dimm = 0; dimm < DDR_CFG_T_MAX_DIMMS; dimm++)
160         {
161             int spd_addr = bdk_config_get_int(BDK_CONFIG_DDR_SPD_ADDR, dimm, lmc, node);
162             if (spd_addr)
163             {
164                 cfg->config[lmc].dimm_config_table[dimm].spd_addr = spd_addr;
165             }
166             else
167             {
168 #if 0
169                 int spd_size;
170                 const void *spd_data = bdk_config_get_blob(&spd_size, BDK_CONFIG_DDR_SPD_DATA, dimm, lmc, node);
171                 if (spd_data && spd_size)
172                     cfg->config[lmc].dimm_config_table[dimm].spd_ptr = spd_data;
173 #endif
174             }
175         }
176     }
177 
178     /* Check that we know how to get DIMM inofmration. If not, return failure */
179     if (!cfg->config[0].dimm_config_table[0].spd_addr && !cfg->config[0].dimm_config_table[0].spd_ptr)
180         return NULL;
181 
182     cfg->name = "Loaded from bdk-config";
183     for (int lmc = 0; lmc < MAX_LMCS; lmc++)
184     {
185         for (int num_dimms = 1; num_dimms <= DDR_CFG_T_MAX_DIMMS; num_dimms++)
186         {
187             load_rank_data(cfg, 1, num_dimms, lmc, node);
188             load_rank_data(cfg, 2, num_dimms, lmc, node);
189             load_rank_data(cfg, 4, num_dimms, lmc, node);
190         }
191 
192         ddr_configuration_t *c = &cfg->config[lmc];
193         ddr3_custom_config_t *custom = &c->custom_lmc_config;
194         custom->min_rtt_nom_idx                 = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MIN_RTT_NOM_IDX,     lmc, node);
195         custom->max_rtt_nom_idx                 = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MAX_RTT_NOM_IDX,     lmc, node);
196         custom->min_rodt_ctl                    = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MIN_RODT_CTL,        lmc, node);
197         custom->max_rodt_ctl                    = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MAX_RODT_CTL,        lmc, node);
198         custom->ck_ctl                          = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_CK_CTL,              lmc, node);
199         custom->cmd_ctl                         = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_CMD_CTL,             lmc, node);
200         custom->ctl_ctl                         = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_CTL_CTL,             lmc, node);
201         custom->min_cas_latency                 = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MIN_CAS_LATENCY,     lmc, node);
202         custom->offset_en                       = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_OFFSET_EN,           lmc, node);
203         custom->offset_udimm                    = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_OFFSET,              "UDIMM", lmc, node);
204         custom->offset_rdimm                    = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_OFFSET,              "RDIMM", lmc, node);
205         custom->rlevel_compute                  = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_RLEVEL_COMPUTE,      lmc, node);
206         custom->rlevel_comp_offset_udimm        = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_RLEVEL_COMP_OFFSET,  "UDIMM", lmc, node);
207         custom->rlevel_comp_offset_rdimm        = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_RLEVEL_COMP_OFFSET,  "RDIMM", lmc, node);
208         custom->ddr2t_udimm                     = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DDR2T,               "UDIMM", lmc, node);
209         custom->ddr2t_rdimm                     = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DDR2T,               "RDIMM", lmc, node);
210         custom->disable_sequential_delay_check  = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DISABLE_SEQUENTIAL_DELAY_CHECK, lmc, node);
211         custom->maximum_adjacent_rlevel_delay_increment
212                                                 = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MAXIMUM_ADJACENT_RLEVEL_DELAY_INCREMENT, lmc, node);
213         custom->parity                          = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_PARITY,          lmc, node);
214         custom->fprch2                          = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_FPRCH2,          lmc, node);
215         custom->mode32b                         = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MODE32B,         lmc, node);
216         custom->measured_vref                   = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MEASURED_VREF,   lmc, node);
217 
218         /* CN80XX only supports 32bit mode */
219         if (cavium_is_altpkg(CAVIUM_CN81XX))
220             custom->mode32b = 1;
221 
222         /* Loop through 8 bytes, plus ecc byte */
223         #define NUM_BYTES 9 /* Max bytes on LMC (8 plus ECC) */
224         static int8_t dll_write_offset[NUM_BYTES];
225         static int8_t dll_read_offset[NUM_BYTES];
226         for (int b = 0; b < NUM_BYTES; b++)
227         {
228             dll_write_offset[b] = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DLL_WRITE_OFFSET, b, lmc, node);
229             dll_read_offset[b] = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DLL_READ_OFFSET,   b, lmc, node);
230         }
231         custom->dll_write_offset = dll_write_offset;
232         custom->dll_read_offset = dll_read_offset;
233     }
234 
235     int is_ddr4 = (cfg->config[0].odt_1rank_config[0].odt_mask2.u != 0);
236     int speed = bdk_config_get_int(BDK_CONFIG_DDR_SPEED, node);
237     switch (speed)
238     {
239     	case 0: // AUTO
240             cfg->ddr_clock_hertz = 0;
241             break;
242         case 800:
243         case 1600:
244         case 2400:
245             cfg->ddr_clock_hertz = (uint64_t)speed * 1000000 / 2;
246             break;
247         case 666:
248             cfg->ddr_clock_hertz = 333333333;
249             break;
250         case 1066:
251             cfg->ddr_clock_hertz = 533333333;
252             break;
253         case 1333:
254             cfg->ddr_clock_hertz = 666666666;
255             break;
256         case 1866:
257             if (is_ddr4)
258                 cfg->ddr_clock_hertz = 940000000;
259             else
260                 cfg->ddr_clock_hertz = 933333333;
261             break;
262         case 2133:
263             cfg->ddr_clock_hertz = 1050000000;
264             break;
265         default:
266             bdk_warn("Unsupported DRAM speed of %d MT/s\n", speed);
267             cfg->ddr_clock_hertz = speed * 1000000 / 2;
268             break;
269     }
270 
271     return cfg;
272 };
273