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