1 /***********************license start***************
2 * Copyright (c) 2003-2010 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 control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
26 * 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 TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
39
40
41
42
43
44
45
46 /**
47 * @file
48 *
49 * Configuration functions for low latency memory.
50 *
51 * <hr>$Revision: 70030 $<hr>
52 */
53 #include "cvmx-config.h"
54 #include "cvmx.h"
55 #include "cvmx-llm.h"
56 #include "cvmx-sysinfo.h"
57 #include "cvmx-csr-db.h"
58
59 #define MIN(a,b) (((a)<(b))?(a):(b))
60
61 typedef struct
62 {
63 uint32_t dfa_memcfg0_base;
64 uint32_t dfa_memcfg1_base;
65 uint32_t mrs_dat_p0bunk0;
66 uint32_t mrs_dat_p0bunk1;
67 uint32_t mrs_dat_p1bunk0;
68 uint32_t mrs_dat_p1bunk1;
69 uint8_t p0_ena;
70 uint8_t p1_ena;
71 uint8_t bunkport;
72 } rldram_csr_config_t;
73
74
75
76
77
78 int rld_csr_config_generate(llm_descriptor_t *llm_desc_ptr, rldram_csr_config_t *cfg_ptr);
79
80
81 void print_rld_cfg(rldram_csr_config_t *cfg_ptr);
82 void write_rld_cfg(rldram_csr_config_t *cfg_ptr);
83 static void cn31xx_dfa_memory_init(void);
84
85 static uint32_t process_address_map_str(uint32_t mrs_dat, char *addr_str);
86
87
88
89 #ifndef CVMX_LLM_NUM_PORTS
90 #warning WARNING: default CVMX_LLM_NUM_PORTS used. Defaults deprecated, please set in executive-config.h
91 #define CVMX_LLM_NUM_PORTS 1
92 #endif
93
94
95 #if (CVMX_LLM_NUM_PORTS != 1) && (CVMX_LLM_NUM_PORTS != 2)
96 #error "Invalid CVMX_LLM_NUM_PORTS value: must be 1 or 2\n"
97 #endif
98
cvmx_llm_initialize()99 int cvmx_llm_initialize()
100 {
101 if (cvmx_llm_initialize_desc(NULL) < 0)
102 return -1;
103
104 return 0;
105 }
106
107
cvmx_llm_get_default_descriptor(llm_descriptor_t * llm_desc_ptr)108 int cvmx_llm_get_default_descriptor(llm_descriptor_t *llm_desc_ptr)
109 {
110 cvmx_sysinfo_t *sys_ptr;
111 sys_ptr = cvmx_sysinfo_get();
112
113 if (!llm_desc_ptr)
114 return -1;
115
116 memset(llm_desc_ptr, 0, sizeof(llm_descriptor_t));
117
118 llm_desc_ptr->cpu_hz = cvmx_clock_get_rate(CVMX_CLOCK_CORE);
119
120 if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBT3000)
121 { // N3K->RLD0 Address Swizzle
122 strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
123 strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
124 // N3K->RLD1 Address Swizzle
125 strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
126 strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
127 /* NOTE: The ebt3000 has a strange RLDRAM configuration for validation purposes. It is not recommended to have
128 ** different amounts of memory on different ports as that renders some memory unusable */
129 llm_desc_ptr->rld0_bunks = 2;
130 llm_desc_ptr->rld1_bunks = 2;
131 llm_desc_ptr->rld0_mbytes = 128; // RLD0: 4x 32Mx9
132 llm_desc_ptr->rld1_mbytes = 64; // RLD1: 2x 16Mx18
133 }
134 else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBT5800)
135 {
136 strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
137 strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
138 strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
139 strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 00 08 07 06 05 04 13 02 01 03 09 18 17 16 15 14 10 12 11 19");
140 llm_desc_ptr->rld0_bunks = 2;
141 llm_desc_ptr->rld1_bunks = 2;
142 llm_desc_ptr->rld0_mbytes = 128;
143 llm_desc_ptr->rld1_mbytes = 128;
144 llm_desc_ptr->max_rld_clock_mhz = 400; /* CN58XX needs a max clock speed for selecting optimal divisor */
145 }
146 else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3000)
147 {
148 strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
149 strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
150 strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
151 strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
152 llm_desc_ptr->rld0_bunks = 2;
153 llm_desc_ptr->rld1_bunks = 2;
154 llm_desc_ptr->rld0_mbytes = 128;
155 llm_desc_ptr->rld1_mbytes = 128;
156 }
157 else if (sys_ptr->board_type == CVMX_BOARD_TYPE_THUNDER)
158 {
159
160 if (sys_ptr->board_rev_major >= 4)
161 {
162 strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 13 11 01 02 07 19 03 18 10 12 20 06 04 08 17 05 14 16 00 09 15");
163 strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 11 13 04 08 17 05 14 16 00 09 15 06 01 02 07 19 03 18 10 12 20");
164 strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 02 19 18 17 16 09 14 13 20 11 10 01 08 03 06 15 04 07 05 12 00");
165 strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 19 02 08 03 06 15 04 07 05 12 00 01 18 17 16 09 14 13 20 11 10");
166 }
167 else
168 {
169 strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
170 strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
171 strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
172 strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
173 }
174
175 llm_desc_ptr->rld0_bunks = 2;
176 llm_desc_ptr->rld1_bunks = 2;
177 llm_desc_ptr->rld0_mbytes = 128;
178 llm_desc_ptr->rld1_mbytes = 128;
179 }
180 else if (sys_ptr->board_type == CVMX_BOARD_TYPE_NICPRO2)
181 {
182 strcpy(llm_desc_ptr->addr_rld0_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
183 strcpy(llm_desc_ptr->addr_rld0_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
184 strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
185 strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 19 20 08 07 06 05 04 03 02 01 00 09 18 17 16 15 14 13 12 11 10");
186 llm_desc_ptr->rld0_bunks = 2;
187 llm_desc_ptr->rld1_bunks = 2;
188 llm_desc_ptr->rld0_mbytes = 256;
189 llm_desc_ptr->rld1_mbytes = 256;
190 llm_desc_ptr->max_rld_clock_mhz = 400; /* CN58XX needs a max clock speed for selecting optimal divisor */
191 }
192 else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3100)
193 {
194 /* CN31xx DFA memory is DDR based, so it is completely different from the CN38XX DFA memory */
195 llm_desc_ptr->rld0_bunks = 1;
196 llm_desc_ptr->rld0_mbytes = 256;
197 }
198 else if (sys_ptr->board_type == CVMX_BOARD_TYPE_KBP)
199 {
200 strcpy(llm_desc_ptr->addr_rld0_fb_str, "");
201 strcpy(llm_desc_ptr->addr_rld0_bb_str, "");
202 llm_desc_ptr->rld0_bunks = 0;
203 llm_desc_ptr->rld0_mbytes = 0;
204 strcpy(llm_desc_ptr->addr_rld1_fb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
205 strcpy(llm_desc_ptr->addr_rld1_bb_str, "22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00");
206 llm_desc_ptr->rld1_bunks = 2;
207 llm_desc_ptr->rld1_mbytes = 64;
208 }
209 else
210 {
211 cvmx_dprintf("No default LLM configuration available for board %s (%d)\n", cvmx_board_type_to_string(sys_ptr->board_type), sys_ptr->board_type);
212 return -1;
213 }
214
215 return(0);
216 }
217
cvmx_llm_initialize_desc(llm_descriptor_t * llm_desc_ptr)218 int cvmx_llm_initialize_desc(llm_descriptor_t *llm_desc_ptr)
219 {
220 cvmx_sysinfo_t *sys_ptr;
221 sys_ptr = cvmx_sysinfo_get();
222 llm_descriptor_t default_llm_desc;
223
224 memset(&default_llm_desc, 0, sizeof(default_llm_desc));
225 if (sys_ptr->board_type == CVMX_BOARD_TYPE_SIM)
226 {
227 cvmx_dprintf("Skipping llm configuration for simulator.\n");
228 return 0;
229 }
230
231 if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3100)
232 {
233 /* CN31xx DFA memory is DDR based, so it is completely different from the CN38XX DFA memory
234 ** config descriptors are not supported yet.*/
235 cvmx_dprintf("Warning: preliminary DFA memory configuration\n");
236 cn31xx_dfa_memory_init();
237 return(256*1024*1024);
238 }
239
240 /* If no descriptor passed, generate default descriptor based on board type.
241 ** Fail if no default available for given board type
242 */
243 if (!llm_desc_ptr)
244 {
245 /* Get default descriptor */
246 if (0 > cvmx_llm_get_default_descriptor(&default_llm_desc))
247 return -1;
248
249 /* Disable second port depending on CVMX config */
250 if (CVMX_LLM_NUM_PORTS == 1)
251 default_llm_desc.rld0_bunks = 0; // For single port: Force RLD0(P1) to appear EMPTY
252
253 cvmx_dprintf("Using default LLM configuration for board %s (%d)\n", cvmx_board_type_to_string(sys_ptr->board_type), sys_ptr->board_type);
254
255 llm_desc_ptr = &default_llm_desc;
256 }
257
258
259
260 rldram_csr_config_t ebt3000_rld_cfg;
261 if (!rld_csr_config_generate(llm_desc_ptr, &ebt3000_rld_cfg))
262 {
263 cvmx_dprintf("Configuring %d llm port(s).\n", !!llm_desc_ptr->rld0_bunks + !!llm_desc_ptr->rld1_bunks);
264 write_rld_cfg(&ebt3000_rld_cfg);
265 }
266 else
267 {
268 cvmx_dprintf("Error creating rldram configuration\n");
269 return(-1);
270 }
271
272 /* Compute how much memory is configured
273 ** Memory is interleaved, so if one port has more than the other some memory is not usable */
274
275 /* If both ports are enabled, handle the case where one port has more than the other.
276 ** This is an unusual and not recommended configuration that exists on the ebt3000 board */
277 if (!!llm_desc_ptr->rld0_bunks && !!llm_desc_ptr->rld1_bunks)
278 llm_desc_ptr->rld0_mbytes = llm_desc_ptr->rld1_mbytes = MIN(llm_desc_ptr->rld0_mbytes, llm_desc_ptr->rld1_mbytes);
279
280 return(((!!llm_desc_ptr->rld0_bunks) * llm_desc_ptr->rld0_mbytes
281 + (!!llm_desc_ptr->rld1_bunks) * llm_desc_ptr->rld1_mbytes) * 1024*1024);
282 }
283
284 //======================
285 // SUPPORT FUNCTIONS:
286 //======================
287 //======================================================================
288 // Extracts srcvec[srcbitpos] and places it in return int (bit[0])
bit_extract(int srcvec,int srcbitpos)289 int bit_extract ( int srcvec, // source word (to extract)
290 int srcbitpos // source bit position
291 )
292 {
293 return(((1 << srcbitpos) & srcvec) >> srcbitpos);
294 }
295 //======================================================================
296 // Inserts srcvec[0] into dstvec[dstbitpos] (without affecting other bits)
bit_insert(int srcvec,int dstbitpos,int dstvec)297 int bit_insert ( int srcvec, // srcvec[0] = bit to be inserted
298 int dstbitpos, // Bit position to insert into returned int
299 int dstvec // dstvec (destination vector)
300 )
301 {
302 return((srcvec << dstbitpos) | dstvec); // Shift bit to insert into bit position/OR with accumulated number
303 }
304 //======================================================================
305
rld_csr_config_generate(llm_descriptor_t * llm_desc_ptr,rldram_csr_config_t * cfg_ptr)306 int rld_csr_config_generate(llm_descriptor_t *llm_desc_ptr, rldram_csr_config_t *cfg_ptr)
307 {
308 char *addr_rld0_fb_str;
309 char *addr_rld0_bb_str;
310 char *addr_rld1_fb_str;
311 char *addr_rld1_bb_str;
312 int eclk_ps;
313 int mtype = 0; // MTYPE (0: RLDRAM/1: FCRAM
314 int trcmin = 20; // tRC(min) - from RLDRAM data sheet
315 int trc_cyc; // TRC(cyc)
316 int trc_mod;
317 int trl_cyc; // TRL(cyc)
318 int twl_cyc; // TWL(cyc)
319 int tmrsc_cyc = 6; // tMRSC(cyc) [2-7]
320 int mclk_ps; // DFA Memory Clock(in ps) = 2x eclk
321 int rldcfg = 99; // RLDRAM-II CFG (1,2,3)
322 int mrs_odt = 0; // RLDRAM MRS A[9]=ODT (default)
323 int mrs_impmatch = 0; // RLDRAM MRS A[8]=Impedance Matching (default)
324 int mrs_dllrst = 1; // RLDRAM MRS A[7]=DLL Reset (default)
325 uint32_t mrs_dat;
326 int mrs_dat_p0bunk0 = 0; // MRS Register Data After Address Map (for Port0 Bunk0)
327 int mrs_dat_p0bunk1 = 0; // MRS Register Data After Address Map (for Port0 Bunk1)
328 int mrs_dat_p1bunk0 = 0; // MRS Register Data After Address Map (for Port1 Bunk0)
329 int mrs_dat_p1bunk1 = 0; // MRS Register Data After Address Map (for Port1 Bunk1)
330 int p0_ena = 0; // DFA Port#0 Enabled
331 int p1_ena = 0; // DFA Port#1 Enabled
332 int memport = 0; // Memory(MB) per Port [MAX=512]
333 int membunk; // Memory(MB) per Bunk
334 int bunkport = 0; // Bunks/Port [1/2]
335 int pbunk = 0; // Physical Bunk(or Rank) encoding for address bit
336 int tref_ms = 32; // tREF(ms) (RLDRAM-II overall device refresh interval
337 int trefi_ns; // tREFI(ns) = tREF(ns)/#rows/bank
338 int rows = 8; // #rows/bank (K) typically 8K
339 int ref512int;
340 int ref512mod;
341 int tskw_cyc = 0;
342 int fprch = 1;
343 int bprch = 0;
344 int dfa_memcfg0_base = 0;
345 int dfa_memcfg1_base = 0;
346 int tbl = 1; // tBL (1: 2-burst /2: 4-burst)
347 int rw_dly;
348 int wr_dly;
349 int r2r = 1;
350 int sil_lat = 1;
351 int clkdiv = 2; /* CN38XX is fixed at 2, CN58XX supports 2,3,4 */
352 int clkdiv_enc = 0x0; /* Encoded clock divisor, only used for CN58XX */
353
354 if (!llm_desc_ptr)
355 return -1;
356
357 /* Setup variables from descriptor */
358
359 addr_rld0_fb_str = llm_desc_ptr->addr_rld0_fb_str;
360 addr_rld0_bb_str = llm_desc_ptr->addr_rld0_bb_str;
361 addr_rld1_fb_str = llm_desc_ptr->addr_rld1_fb_str;
362 addr_rld1_bb_str = llm_desc_ptr->addr_rld1_bb_str;
363
364 p0_ena = !!llm_desc_ptr->rld1_bunks; // NOTE: P0 == RLD1
365 p1_ena = !!llm_desc_ptr->rld0_bunks; // NOTE: P1 == RLD0
366
367 // Massage the code, so that if the user had imbalanced memory per-port (or imbalanced bunks/port), we
368 // at least try to configure 'workable' memory.
369 if (p0_ena && p1_ena) // IF BOTH PORTS Enabled (imbalanced memory), select smaller of BOTH
370 {
371 memport = MIN(llm_desc_ptr->rld0_mbytes, llm_desc_ptr->rld1_mbytes);
372 bunkport = MIN(llm_desc_ptr->rld0_bunks, llm_desc_ptr->rld1_bunks);
373 }
374 else if (p0_ena) // P0=RLD1 Enabled
375 {
376 memport = llm_desc_ptr->rld1_mbytes;
377 bunkport = llm_desc_ptr->rld1_bunks;
378 }
379 else if (p1_ena) // P1=RLD0 Enabled
380 {
381 memport = llm_desc_ptr->rld0_mbytes;
382 bunkport = llm_desc_ptr->rld0_bunks;
383 }
384 else
385 return -1;
386
387 uint32_t eclk_mhz = llm_desc_ptr->cpu_hz/1000000;
388
389
390
391 /* Tweak skew based on cpu clock */
392 if (eclk_mhz <= 367)
393 {
394 tskw_cyc = 0;
395 }
396 else
397 {
398 tskw_cyc = 1;
399 }
400
401 /* Determine clock divider ratio (only required for CN58XX) */
402 if (OCTEON_IS_MODEL(OCTEON_CN58XX))
403 {
404 uint32_t max_llm_clock_mhz = llm_desc_ptr->max_rld_clock_mhz;
405 if (!max_llm_clock_mhz)
406 {
407 max_llm_clock_mhz = 400; /* Default to 400 MHz */
408 cvmx_dprintf("Warning, using default max_rld_clock_mhz of: %lu MHz\n", (unsigned long)max_llm_clock_mhz);
409 }
410
411 /* Compute the divisor, and round up */
412 clkdiv = eclk_mhz/max_llm_clock_mhz;
413 if (clkdiv * max_llm_clock_mhz < eclk_mhz)
414 clkdiv++;
415
416 if (clkdiv > 4)
417 {
418 cvmx_dprintf("ERROR: CN58XX LLM clock divisor out of range\n");
419 goto TERMINATE;
420 }
421 if (clkdiv < 2)
422 clkdiv = 2;
423
424 cvmx_dprintf("Using llm clock divisor: %d, llm clock is: %lu MHz\n", clkdiv, (unsigned long)eclk_mhz/clkdiv);
425 /* Translate divisor into bit encoding for register */
426 /* 0 -> div 2
427 ** 1 -> reserved
428 ** 2 -> div 3
429 ** 3 -> div 4
430 */
431 if (clkdiv == 2)
432 clkdiv_enc = 0;
433 else
434 clkdiv_enc = clkdiv - 1;
435
436 /* Odd divisor needs sil_lat to be 2 */
437 if (clkdiv == 0x3)
438 sil_lat = 2;
439
440 /* Increment tskw for high clock speeds */
441 if ((unsigned long)eclk_mhz/clkdiv >= 375)
442 tskw_cyc += 1;
443 }
444
445 eclk_ps = (1000000+(eclk_mhz-1)) / eclk_mhz; // round up if nonzero remainder
446 //=======================================================================
447
448 //=======================================================================
449 // Now, Query User for DFA Memory Type
450 if (mtype != 0)
451 {
452 goto TERMINATE; // Complete this code for FCRAM usage on N3K-P2
453 }
454 //=======================================================================
455 // Query what the tRC(min) value is from the data sheets
456 //=======================================================================
457 // Now determine the Best CFG based on Memory clock(ps) and tRCmin(ns)
458 mclk_ps = eclk_ps * clkdiv;
459 trc_cyc = ((trcmin * 1000)/mclk_ps);
460 trc_mod = ((trcmin * 1000) % mclk_ps);
461 // If remainder exists, bump up to the next integer multiple
462 if (trc_mod != 0)
463 {
464 trc_cyc = trc_cyc + 1;
465 }
466 // If tRC is now ODD, then bump it to the next EVEN integer (RLDRAM-II does not support odd tRC values at this time).
467 if (trc_cyc & 1)
468 {
469 trc_cyc = trc_cyc + 1; // Bump it to an even #
470 }
471 // RLDRAM CFG Range Check: If the computed trc_cyc is less than 4, then set it to min CFG1 [tRC=4]
472 if (trc_cyc < 4)
473 {
474 trc_cyc = 4; // If computed trc_cyc < 4 then clamp to 4
475 }
476 else if (trc_cyc > 8)
477 { // If the computed trc_cyc > 8, then report an error (because RLDRAM cannot support a tRC>8
478 goto TERMINATE;
479 }
480 // Assuming all is ok(up to here)
481 // At this point the tRC_cyc has been clamped between 4 and 8 (and is even), So it can only be 4,6,8 which are
482 // the RLDRAM valid CFG range values.
483 trl_cyc = trc_cyc; // tRL = tRC (for RLDRAM=II)
484 twl_cyc = trl_cyc + 1; // tWL = tRL + 1 (for RLDRAM-II)
485 // NOTE: RLDRAM-II (as of 4/25/05) only have 3 supported CFG encodings:
486 if (trc_cyc == 4)
487 {
488 rldcfg = 1; // CFG #1 (tRL=4/tRC=4/tWL=5)
489 }
490 else if (trc_cyc == 6)
491 {
492 rldcfg = 2; // CFG #2 (tRL=6/tRC=6/tWL=7)
493 }
494 else if (trc_cyc == 8)
495 {
496 rldcfg = 3; // CFG #3 (tRL=8/tRC=8/tWL=9)
497 }
498 else
499 {
500 goto TERMINATE;
501 }
502 //=======================================================================
503 mrs_dat = ( (mrs_odt << 9) | (mrs_impmatch << 8) | (mrs_dllrst << 7) | rldcfg );
504 //=======================================================================
505 // If there is only a single bunk, then skip over address mapping queries (which are not required)
506 if (bunkport == 1)
507 {
508 goto CALC_PBUNK;
509 }
510
511 /* Process the address mappings */
512 /* Note that that RLD0 pins corresponds to Port#1, and
513 ** RLD1 pins corresponds to Port#0.
514 */
515 mrs_dat_p1bunk0 = process_address_map_str(mrs_dat, addr_rld0_fb_str);
516 mrs_dat_p1bunk1 = process_address_map_str(mrs_dat, addr_rld0_bb_str);
517 mrs_dat_p0bunk0 = process_address_map_str(mrs_dat, addr_rld1_fb_str);
518 mrs_dat_p0bunk1 = process_address_map_str(mrs_dat, addr_rld1_bb_str);
519
520
521 //=======================================================================
522 CALC_PBUNK:
523 // Determine the PBUNK field (based on Memory/Bunk)
524 // This determines the addr bit used to distinguish when crossing a bunk.
525 // NOTE: For RLDRAM, the bunk bit is extracted from 'a' programmably selected high
526 // order addr bit. [linear address per-bunk]
527 if (bunkport == 2)
528 {
529 membunk = (memport / 2);
530 }
531 else
532 {
533 membunk = memport;
534 }
535 if (membunk == 16)
536 { // 16MB/bunk MA[19]
537 pbunk = 0;
538 }
539 else if (membunk == 32)
540 { // 32MB/bunk MA[20]
541 pbunk = 1;
542 }
543 else if (membunk == 64)
544 { // 64MB/bunk MA[21]
545 pbunk = 2;
546 }
547 else if (membunk == 128)
548 { // 128MB/bunk MA[22]
549 pbunk = 3;
550 }
551 else if (membunk == 256)
552 { // 256MB/bunk MA[23]
553 pbunk = 4;
554 }
555 else if (membunk == 512)
556 { // 512MB/bunk
557 }
558 //=======================================================================
559 //=======================================================================
560 //=======================================================================
561 // Now determine N3K REFINT
562 trefi_ns = (tref_ms * 1000 * 1000) / (rows * 1024);
563 ref512int = ((trefi_ns * 1000) / (eclk_ps * 512));
564 ref512mod = ((trefi_ns * 1000) % (eclk_ps * 512));
565 //=======================================================================
566 // Ask about tSKW
567 #if 0
568 if (tskw_ps == 0)
569 {
570 tskw_cyc = 0;
571 }
572 else
573 { // CEILING function
574 tskw_cyc = (tskw_ps / eclk_ps);
575 tskw_mod = (tskw_ps % eclk_ps);
576 if (tskw_mod != 0)
577 { // If there's a remainder - then bump to next (+1)
578 tskw_cyc = tskw_cyc + 1;
579 }
580 }
581 #endif
582 if (tskw_cyc > 3)
583 {
584 goto TERMINATE;
585 }
586
587 tbl = 1; // BLEN=2 (ALWAYs for RLDRAM)
588 //=======================================================================
589 // RW_DLY = (ROUND_UP{[[(TRL+TBL)*2 + tSKW + BPRCH] + 1] / 2}) - tWL
590 rw_dly = ((((trl_cyc + tbl) * 2 + tskw_cyc + bprch) + 1) / 2);
591 if (rw_dly & 1)
592 { // If it's ODD then round up
593 rw_dly = rw_dly + 1;
594 }
595 rw_dly = rw_dly - twl_cyc +1 ;
596 if (rw_dly < 0)
597 { // range check - is it positive
598 goto TERMINATE;
599 }
600 //=======================================================================
601 // WR_DLY = (ROUND_UP[[(tWL + tBL)*2 - tSKW + FPRCH] / 2]) - tRL
602 wr_dly = (((twl_cyc + tbl) * 2 - tskw_cyc + fprch) / 2);
603 if (wr_dly & 1)
604 { // If it's ODD then round up
605 wr_dly = wr_dly + 1;
606 }
607 wr_dly = wr_dly - trl_cyc + 1;
608 if (wr_dly < 0)
609 { // range check - is it positive
610 goto TERMINATE;
611 }
612
613
614 dfa_memcfg0_base = 0;
615 dfa_memcfg0_base = ( p0_ena |
616 (p1_ena << 1) |
617 (mtype << 3) |
618 (sil_lat << 4) |
619 (rw_dly << 6) |
620 (wr_dly << 10) |
621 (fprch << 14) |
622 (bprch << 16) |
623 (0 << 18) | // BLEN=0(2-burst for RLDRAM)
624 (pbunk << 19) |
625 (r2r << 22) | // R2R=1
626 (clkdiv_enc << 28 )
627 );
628
629
630 dfa_memcfg1_base = 0;
631 dfa_memcfg1_base = ( ref512int |
632 (tskw_cyc << 4) |
633 (trl_cyc << 8) |
634 (twl_cyc << 12) |
635 (trc_cyc << 16) |
636 (tmrsc_cyc << 20)
637 );
638
639
640
641
642 cfg_ptr->dfa_memcfg0_base = dfa_memcfg0_base;
643 cfg_ptr->dfa_memcfg1_base = dfa_memcfg1_base;
644 cfg_ptr->mrs_dat_p0bunk0 = mrs_dat_p0bunk0;
645 cfg_ptr->mrs_dat_p1bunk0 = mrs_dat_p1bunk0;
646 cfg_ptr->mrs_dat_p0bunk1 = mrs_dat_p0bunk1;
647 cfg_ptr->mrs_dat_p1bunk1 = mrs_dat_p1bunk1;
648 cfg_ptr->p0_ena = p0_ena;
649 cfg_ptr->p1_ena = p1_ena;
650 cfg_ptr->bunkport = bunkport;
651 //=======================================================================
652
653 return(0);
654 TERMINATE:
655 return(-1);
656
657 }
658
659
660
process_address_map_str(uint32_t mrs_dat,char * addr_str)661 static uint32_t process_address_map_str(uint32_t mrs_dat, char *addr_str)
662 {
663 int count = 0;
664 int amap [23];
665 uint32_t new_mrs_dat = 0;
666
667 // cvmx_dprintf("mrs_dat: 0x%x, str: %x\n", mrs_dat, addr_str);
668 char *charptr = strtok(addr_str," ");
669 while ((charptr != NULL) & (count <= 22))
670 {
671 amap[22-count] = atoi(charptr); // Assign the AMAP Array
672 charptr = strtok(NULL," "); // Get Next char string (which represents next addr bit mapping)
673 count++;
674 }
675 // Now do the bit swap of MRSDAT (based on address mapping)
676 uint32_t mrsdat_bit;
677 for (count=0;count<=22;count++)
678 {
679 mrsdat_bit = bit_extract(mrs_dat, count);
680 new_mrs_dat = bit_insert(mrsdat_bit, amap[count], new_mrs_dat);
681 }
682
683 return new_mrs_dat;
684 }
685
686
687 //#define PRINT_LLM_CONFIG
688 #ifdef PRINT_LLM_CONFIG
689 #define ll_printf printf
690 #else
691 #define ll_printf(...)
692 #define cvmx_csr_db_decode(...)
693 #endif
694
cn31xx_dfa_memory_init(void)695 static void cn31xx_dfa_memory_init(void)
696 {
697 if (OCTEON_IS_MODEL(OCTEON_CN31XX))
698 {
699 cvmx_dfa_ddr2_cfg_t dfaCfg;
700 cvmx_dfa_eclkcfg_t dfaEcklCfg;
701 cvmx_dfa_ddr2_addr_t dfaAddr;
702 cvmx_dfa_ddr2_tmg_t dfaTmg;
703 cvmx_dfa_ddr2_pll_t dfaPll;
704 int mem_freq_hz = 533*1000000;
705 int ref_freq_hz = cvmx_sysinfo_get()->dfa_ref_clock_hz;
706 if (!ref_freq_hz)
707 ref_freq_hz = 33*1000000;
708
709 cvmx_dprintf ("Configuring DFA memory for %d MHz operation.\n",mem_freq_hz/1000000);
710
711 /* Turn on the DFA memory port. */
712 dfaCfg.u64 = cvmx_read_csr (CVMX_DFA_DDR2_CFG);
713 dfaCfg.s.prtena = 1;
714 cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64);
715
716 /* Start the PLL alignment sequence */
717 dfaPll.u64 = 0;
718 dfaPll.s.pll_ratio = mem_freq_hz/ref_freq_hz /*400Mhz / 33MHz*/;
719 dfaPll.s.pll_div2 = 1 /*400 - 1 */;
720 dfaPll.s.pll_bypass = 0;
721 cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64);
722
723 dfaPll.s.pll_init = 1;
724 cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64);
725
726 cvmx_wait (RLD_INIT_DELAY); //want 150uS
727 dfaPll.s.qdll_ena = 1;
728 cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64);
729
730 cvmx_wait (RLD_INIT_DELAY); //want 10us
731 dfaEcklCfg.u64 = 0;
732 dfaEcklCfg.s.dfa_frstn = 1;
733 cvmx_write_csr (CVMX_DFA_ECLKCFG, dfaEcklCfg.u64);
734
735 /* Configure the DFA Memory */
736 dfaCfg.s.silo_hc = 1 /*400 - 1 */;
737 dfaCfg.s.silo_qc = 0 /*400 - 0 */;
738 dfaCfg.s.tskw = 1 /*400 - 1 */;
739 dfaCfg.s.ref_int = 0x820 /*533 - 0x820 400 - 0x618*/;
740 dfaCfg.s.trfc = 0x1A /*533 - 0x23 400 - 0x1A*/;
741 dfaCfg.s.fprch = 0; /* 1 more conservative*/
742 dfaCfg.s.bprch = 0; /* 1 */
743 cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64);
744
745 dfaEcklCfg.u64 = cvmx_read_csr (CVMX_DFA_ECLKCFG);
746 dfaEcklCfg.s.maxbnk = 1;
747 cvmx_write_csr (CVMX_DFA_ECLKCFG, dfaEcklCfg.u64);
748
749 dfaAddr.u64 = cvmx_read_csr (CVMX_DFA_DDR2_ADDR);
750 dfaAddr.s.num_cols = 0x1;
751 dfaAddr.s.num_colrows = 0x2;
752 dfaAddr.s.num_rnks = 0x1;
753 cvmx_write_csr (CVMX_DFA_DDR2_ADDR, dfaAddr.u64);
754
755 dfaTmg.u64 = cvmx_read_csr (CVMX_DFA_DDR2_TMG);
756 dfaTmg.s.ddr2t = 0;
757 dfaTmg.s.tmrd = 0x2;
758 dfaTmg.s.caslat = 0x4 /*400 - 0x3, 500 - 0x4*/;
759 dfaTmg.s.pocas = 0;
760 dfaTmg.s.addlat = 0;
761 dfaTmg.s.trcd = 4 /*400 - 3, 500 - 4*/;
762 dfaTmg.s.trrd = 2;
763 dfaTmg.s.tras = 0xB /*400 - 8, 500 - 0xB*/;
764 dfaTmg.s.trp = 4 /*400 - 3, 500 - 4*/;
765 dfaTmg.s.twr = 4 /*400 - 3, 500 - 4*/;
766 dfaTmg.s.twtr = 2 /*400 - 2 */;
767 dfaTmg.s.tfaw = 0xE /*400 - 0xA, 500 - 0xE*/;
768 dfaTmg.s.r2r_slot = 0;
769 dfaTmg.s.dic = 0; /*400 - 0 */
770 dfaTmg.s.dqsn_ena = 0;
771 dfaTmg.s.odt_rtt = 0;
772 cvmx_write_csr (CVMX_DFA_DDR2_TMG, dfaTmg.u64);
773
774 /* Turn on the DDR2 interface and wait a bit for the hardware to setup. */
775 dfaCfg.s.init = 1;
776 cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64);
777 cvmx_wait(RLD_INIT_DELAY); // want at least 64K cycles
778 }
779 }
780
write_rld_cfg(rldram_csr_config_t * cfg_ptr)781 void write_rld_cfg(rldram_csr_config_t *cfg_ptr)
782 {
783 cvmx_dfa_memcfg0_t memcfg0;
784 cvmx_dfa_memcfg2_t memcfg2;
785
786 memcfg0.u64 = cfg_ptr->dfa_memcfg0_base;
787
788 if ((OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)))
789 {
790 uint32_t dfa_memcfg0;
791
792 if (OCTEON_IS_MODEL (OCTEON_CN58XX)) {
793 // Set RLDQK90_RST and RDLCK_RST to reset all three DLLs.
794 memcfg0.s.rldck_rst = 1;
795 memcfg0.s.rldqck90_rst = 1;
796 cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64);
797 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x clk/qk90 reset\n", (uint32_t) memcfg0.u64);
798 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64);
799
800 // Clear RDLCK_RST while asserting RLDQK90_RST to bring RLDCK DLL out of reset.
801 memcfg0.s.rldck_rst = 0;
802 memcfg0.s.rldqck90_rst = 1;
803 cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64);
804 cvmx_wait(4000000); /* Wait */
805 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x qk90 reset\n", (uint32_t) memcfg0.u64);
806 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64);
807
808 // Clear both RDLCK90_RST and RLDQK90_RST to bring the RLDQK90 DLL out of reset.
809 memcfg0.s.rldck_rst = 0;
810 memcfg0.s.rldqck90_rst = 0;
811 cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64);
812 cvmx_wait(4000000); /* Wait */
813 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x DLL out of reset\n", (uint32_t) memcfg0.u64);
814 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64);
815 }
816
817 //=======================================================================
818 // Now print out the sequence of events:
819 cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base);
820 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x port enables\n", cfg_ptr->dfa_memcfg0_base);
821 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base);
822 cvmx_wait(4000000); /* Wait */
823
824 cvmx_write_csr(CVMX_DFA_MEMCFG1, cfg_ptr->dfa_memcfg1_base);
825 ll_printf("CVMX_DFA_MEMCFG1: 0x%08x\n", cfg_ptr->dfa_memcfg1_base);
826 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG1 & ~(1ull<<63), cfg_ptr->dfa_memcfg1_base);
827
828 if (cfg_ptr->p0_ena ==1)
829 {
830 cvmx_write_csr(CVMX_DFA_MEMRLD, cfg_ptr->mrs_dat_p0bunk0);
831 ll_printf("CVMX_DFA_MEMRLD : 0x%08x p0_ena memrld\n", cfg_ptr->mrs_dat_p0bunk0);
832 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p0bunk0);
833
834 dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base |
835 (1 << 23) | // P0_INIT
836 (1 << 25) // BUNK_INIT[1:0]=Bunk#0
837 );
838
839 cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
840 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x p0_init/bunk_init\n", dfa_memcfg0);
841 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
842 cvmx_wait(RLD_INIT_DELAY);
843 ll_printf("Delay.....\n");
844 cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base);
845 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x back to base\n", cfg_ptr->dfa_memcfg0_base);
846 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base);
847 }
848
849 if (cfg_ptr->p1_ena ==1)
850 {
851 cvmx_write_csr(CVMX_DFA_MEMRLD, cfg_ptr->mrs_dat_p1bunk0);
852 ll_printf("CVMX_DFA_MEMRLD : 0x%08x p1_ena memrld\n", cfg_ptr->mrs_dat_p1bunk0);
853 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p1bunk0);
854
855 dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base |
856 (1 << 24) | // P1_INIT
857 (1 << 25) // BUNK_INIT[1:0]=Bunk#0
858 );
859 cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
860 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x p1_init/bunk_init\n", dfa_memcfg0);
861 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
862 cvmx_wait(RLD_INIT_DELAY);
863 ll_printf("Delay.....\n");
864 cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base);
865 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x back to base\n", cfg_ptr->dfa_memcfg0_base);
866 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base);
867 }
868
869 // P0 Bunk#1
870 if ((cfg_ptr->p0_ena ==1) && (cfg_ptr->bunkport == 2))
871 {
872 cvmx_write_csr(CVMX_DFA_MEMRLD, cfg_ptr->mrs_dat_p0bunk1);
873 ll_printf("CVMX_DFA_MEMRLD : 0x%08x p0_ena memrld\n", cfg_ptr->mrs_dat_p0bunk1);
874 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p0bunk1);
875
876 dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base |
877 (1 << 23) | // P0_INIT
878 (2 << 25) // BUNK_INIT[1:0]=Bunk#1
879 );
880 cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
881 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x p0_init/bunk_init\n", dfa_memcfg0);
882 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
883 cvmx_wait(RLD_INIT_DELAY);
884 ll_printf("Delay.....\n");
885
886 if (cfg_ptr->p1_ena == 1)
887 { // Re-arm Px_INIT if P1-B1 init is required
888 cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base);
889 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x px_init rearm\n", cfg_ptr->dfa_memcfg0_base);
890 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base);
891 }
892 }
893
894 if ((cfg_ptr->p1_ena == 1) && (cfg_ptr->bunkport == 2))
895 {
896 cvmx_write_csr(CVMX_DFA_MEMRLD, cfg_ptr->mrs_dat_p1bunk1);
897 ll_printf("CVMX_DFA_MEMRLD : 0x%08x p1_ena memrld\n", cfg_ptr->mrs_dat_p1bunk1);
898 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p1bunk1);
899
900 dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base |
901 (1 << 24) | // P1_INIT
902 (2 << 25) // BUNK_INIT[1:0]=10
903 );
904 cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
905 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x p1_init/bunk_init\n", dfa_memcfg0);
906 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
907 }
908 cvmx_wait(4000000); // 1/100S, 0.01S, 10mS
909 ll_printf("Delay.....\n");
910
911 /* Enable bunks */
912 dfa_memcfg0 = cfg_ptr->dfa_memcfg0_base |((cfg_ptr->bunkport >= 1) << 25) | ((cfg_ptr->bunkport == 2) << 26);
913 cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0);
914 ll_printf("CVMX_DFA_MEMCFG0: 0x%08x enable bunks\n", dfa_memcfg0);
915 cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0);
916 cvmx_wait(RLD_INIT_DELAY);
917 ll_printf("Delay.....\n");
918
919 /* Issue a Silo reset by toggling SILRST in memcfg2. */
920 memcfg2.u64 = cvmx_read_csr (CVMX_DFA_MEMCFG2);
921 memcfg2.s.silrst = 1;
922 cvmx_write_csr (CVMX_DFA_MEMCFG2, memcfg2.u64);
923 ll_printf("CVMX_DFA_MEMCFG2: 0x%08x silo reset start\n", (uint32_t) memcfg2.u64);
924 memcfg2.s.silrst = 0;
925 cvmx_write_csr (CVMX_DFA_MEMCFG2, memcfg2.u64);
926 ll_printf("CVMX_DFA_MEMCFG2: 0x%08x silo reset done\n", (uint32_t) memcfg2.u64);
927 }
928 }
929
930