1210284Sjmallett/***********************license start*************** 2215990Sjmallett * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18215990Sjmallett * * Neither the name of Cavium Networks nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29215990Sjmallett * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett 45215990Sjmallett 46210284Sjmallett/** 47210284Sjmallett * @file 48210284Sjmallett * 49210284Sjmallett * Configuration functions for low latency memory. 50210284Sjmallett * 51215990Sjmallett * <hr>$Revision: 52372 $<hr> 52210284Sjmallett */ 53210284Sjmallett#include "cvmx-config.h" 54210284Sjmallett#include "cvmx.h" 55210284Sjmallett#include "cvmx-llm.h" 56210284Sjmallett#include "cvmx-sysinfo.h" 57210284Sjmallett#include "cvmx-csr-db.h" 58210284Sjmallett 59210284Sjmallett#define MIN(a,b) (((a)<(b))?(a):(b)) 60210284Sjmallett 61210284Sjmalletttypedef struct 62210284Sjmallett{ 63210284Sjmallett uint32_t dfa_memcfg0_base; 64210284Sjmallett uint32_t dfa_memcfg1_base; 65210284Sjmallett uint32_t mrs_dat_p0bunk0; 66210284Sjmallett uint32_t mrs_dat_p0bunk1; 67210284Sjmallett uint32_t mrs_dat_p1bunk0; 68210284Sjmallett uint32_t mrs_dat_p1bunk1; 69210284Sjmallett uint8_t p0_ena; 70210284Sjmallett uint8_t p1_ena; 71210284Sjmallett uint8_t bunkport; 72210284Sjmallett} rldram_csr_config_t; 73210284Sjmallett 74210284Sjmallett 75210284Sjmallett 76210284Sjmallett 77210284Sjmallett 78210284Sjmallettint rld_csr_config_generate(llm_descriptor_t *llm_desc_ptr, rldram_csr_config_t *cfg_ptr); 79210284Sjmallett 80210284Sjmallett 81210284Sjmallettvoid print_rld_cfg(rldram_csr_config_t *cfg_ptr); 82210284Sjmallettvoid write_rld_cfg(rldram_csr_config_t *cfg_ptr); 83210284Sjmallettstatic void cn31xx_dfa_memory_init(void); 84210284Sjmallett 85210284Sjmallettstatic uint32_t process_address_map_str(uint32_t mrs_dat, char *addr_str); 86210284Sjmallett 87210284Sjmallett 88210284Sjmallett 89210284Sjmallett#ifndef CVMX_LLM_NUM_PORTS 90210284Sjmallett#warning WARNING: default CVMX_LLM_NUM_PORTS used. Defaults deprecated, please set in executive-config.h 91210284Sjmallett#define CVMX_LLM_NUM_PORTS 1 92210284Sjmallett#endif 93210284Sjmallett 94210284Sjmallett 95210284Sjmallett#if (CVMX_LLM_NUM_PORTS != 1) && (CVMX_LLM_NUM_PORTS != 2) 96210284Sjmallett#error "Invalid CVMX_LLM_NUM_PORTS value: must be 1 or 2\n" 97210284Sjmallett#endif 98210284Sjmallett 99210284Sjmallettint cvmx_llm_initialize() 100210284Sjmallett{ 101210284Sjmallett if (cvmx_llm_initialize_desc(NULL) < 0) 102210284Sjmallett return -1; 103210284Sjmallett 104210284Sjmallett return 0; 105210284Sjmallett} 106210284Sjmallett 107210284Sjmallett 108210284Sjmallettint cvmx_llm_get_default_descriptor(llm_descriptor_t *llm_desc_ptr) 109210284Sjmallett{ 110210284Sjmallett cvmx_sysinfo_t *sys_ptr; 111210284Sjmallett sys_ptr = cvmx_sysinfo_get(); 112210284Sjmallett 113210284Sjmallett if (!llm_desc_ptr) 114210284Sjmallett return -1; 115210284Sjmallett 116210284Sjmallett memset(llm_desc_ptr, 0, sizeof(llm_descriptor_t)); 117210284Sjmallett 118215990Sjmallett llm_desc_ptr->cpu_hz = cvmx_clock_get_rate(CVMX_CLOCK_CORE); 119210284Sjmallett 120210284Sjmallett if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBT3000) 121210284Sjmallett { // N3K->RLD0 Address Swizzle 122210284Sjmallett 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"); 123210284Sjmallett 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"); 124210284Sjmallett // N3K->RLD1 Address Swizzle 125210284Sjmallett 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"); 126210284Sjmallett 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"); 127210284Sjmallett /* NOTE: The ebt3000 has a strange RLDRAM configuration for validation purposes. It is not recommended to have 128210284Sjmallett ** different amounts of memory on different ports as that renders some memory unusable */ 129210284Sjmallett llm_desc_ptr->rld0_bunks = 2; 130210284Sjmallett llm_desc_ptr->rld1_bunks = 2; 131210284Sjmallett llm_desc_ptr->rld0_mbytes = 128; // RLD0: 4x 32Mx9 132210284Sjmallett llm_desc_ptr->rld1_mbytes = 64; // RLD1: 2x 16Mx18 133210284Sjmallett } 134210284Sjmallett else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBT5800) 135210284Sjmallett { 136210284Sjmallett 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"); 137210284Sjmallett 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"); 138210284Sjmallett 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"); 139210284Sjmallett 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"); 140210284Sjmallett llm_desc_ptr->rld0_bunks = 2; 141210284Sjmallett llm_desc_ptr->rld1_bunks = 2; 142210284Sjmallett llm_desc_ptr->rld0_mbytes = 128; 143210284Sjmallett llm_desc_ptr->rld1_mbytes = 128; 144210284Sjmallett llm_desc_ptr->max_rld_clock_mhz = 400; /* CN58XX needs a max clock speed for selecting optimal divisor */ 145210284Sjmallett } 146210284Sjmallett else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3000) 147210284Sjmallett { 148210284Sjmallett 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"); 149210284Sjmallett 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"); 150210284Sjmallett 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"); 151210284Sjmallett 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"); 152210284Sjmallett llm_desc_ptr->rld0_bunks = 2; 153210284Sjmallett llm_desc_ptr->rld1_bunks = 2; 154210284Sjmallett llm_desc_ptr->rld0_mbytes = 128; 155210284Sjmallett llm_desc_ptr->rld1_mbytes = 128; 156210284Sjmallett } 157210284Sjmallett else if (sys_ptr->board_type == CVMX_BOARD_TYPE_NAC38) 158210284Sjmallett { 159210284Sjmallett if (sys_ptr->board_rev_major == 1 && sys_ptr->board_rev_minor == 0) 160210284Sjmallett { 161210284Sjmallett 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"); 162210284Sjmallett 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"); 163210284Sjmallett 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"); 164210284Sjmallett 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"); 165210284Sjmallett llm_desc_ptr->rld0_bunks = 2; 166210284Sjmallett llm_desc_ptr->rld1_bunks = 2; 167210284Sjmallett llm_desc_ptr->rld0_mbytes = 128; 168210284Sjmallett llm_desc_ptr->rld1_mbytes = 128; 169210284Sjmallett } 170210284Sjmallett else 171210284Sjmallett { /* Asus new recommendation */ 172210284Sjmallett 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"); 173210284Sjmallett 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"); 174210284Sjmallett 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"); 175210284Sjmallett 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"); 176210284Sjmallett llm_desc_ptr->rld0_bunks = 2; 177210284Sjmallett llm_desc_ptr->rld1_bunks = 2; 178210284Sjmallett llm_desc_ptr->rld0_mbytes = 128; 179210284Sjmallett llm_desc_ptr->rld1_mbytes = 128; 180210284Sjmallett } 181210284Sjmallett } 182210284Sjmallett else if (sys_ptr->board_type == CVMX_BOARD_TYPE_THUNDER) 183210284Sjmallett { 184210284Sjmallett 185210284Sjmallett if (sys_ptr->board_rev_major >= 4) 186210284Sjmallett { 187210284Sjmallett 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"); 188210284Sjmallett 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"); 189210284Sjmallett 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"); 190210284Sjmallett 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"); 191210284Sjmallett } 192210284Sjmallett else 193210284Sjmallett { 194210284Sjmallett 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"); 195210284Sjmallett 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"); 196210284Sjmallett 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"); 197210284Sjmallett 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"); 198210284Sjmallett } 199210284Sjmallett 200210284Sjmallett llm_desc_ptr->rld0_bunks = 2; 201210284Sjmallett llm_desc_ptr->rld1_bunks = 2; 202210284Sjmallett llm_desc_ptr->rld0_mbytes = 128; 203210284Sjmallett llm_desc_ptr->rld1_mbytes = 128; 204210284Sjmallett } 205210284Sjmallett else if (sys_ptr->board_type == CVMX_BOARD_TYPE_NICPRO2) 206210284Sjmallett { 207210284Sjmallett 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"); 208210284Sjmallett 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"); 209210284Sjmallett 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"); 210210284Sjmallett 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"); 211210284Sjmallett llm_desc_ptr->rld0_bunks = 2; 212210284Sjmallett llm_desc_ptr->rld1_bunks = 2; 213210284Sjmallett llm_desc_ptr->rld0_mbytes = 256; 214210284Sjmallett llm_desc_ptr->rld1_mbytes = 256; 215210284Sjmallett llm_desc_ptr->max_rld_clock_mhz = 400; /* CN58XX needs a max clock speed for selecting optimal divisor */ 216210284Sjmallett } 217210284Sjmallett else if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3100) 218210284Sjmallett { 219210284Sjmallett /* CN31xx DFA memory is DDR based, so it is completely different from the CN38XX DFA memory */ 220210284Sjmallett llm_desc_ptr->rld0_bunks = 1; 221210284Sjmallett llm_desc_ptr->rld0_mbytes = 256; 222210284Sjmallett } 223210284Sjmallett else if (sys_ptr->board_type == CVMX_BOARD_TYPE_KBP) 224210284Sjmallett { 225210284Sjmallett strcpy(llm_desc_ptr->addr_rld0_fb_str, ""); 226210284Sjmallett strcpy(llm_desc_ptr->addr_rld0_bb_str, ""); 227210284Sjmallett llm_desc_ptr->rld0_bunks = 0; 228210284Sjmallett llm_desc_ptr->rld0_mbytes = 0; 229210284Sjmallett 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"); 230210284Sjmallett 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"); 231210284Sjmallett llm_desc_ptr->rld1_bunks = 2; 232210284Sjmallett llm_desc_ptr->rld1_mbytes = 64; 233210284Sjmallett } 234210284Sjmallett else 235210284Sjmallett { 236210284Sjmallett 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); 237210284Sjmallett return -1; 238210284Sjmallett } 239210284Sjmallett 240210284Sjmallett return(0); 241210284Sjmallett} 242210284Sjmallett 243210284Sjmallettint cvmx_llm_initialize_desc(llm_descriptor_t *llm_desc_ptr) 244210284Sjmallett{ 245210284Sjmallett cvmx_sysinfo_t *sys_ptr; 246210284Sjmallett sys_ptr = cvmx_sysinfo_get(); 247210284Sjmallett llm_descriptor_t default_llm_desc; 248210284Sjmallett 249210284Sjmallett memset(&default_llm_desc, 0, sizeof(default_llm_desc)); 250210284Sjmallett if (sys_ptr->board_type == CVMX_BOARD_TYPE_SIM) 251210284Sjmallett { 252210284Sjmallett cvmx_dprintf("Skipping llm configuration for simulator.\n"); 253210284Sjmallett return 0; 254210284Sjmallett } 255210284Sjmallett 256210284Sjmallett if (sys_ptr->board_type == CVMX_BOARD_TYPE_EBH3100) 257210284Sjmallett { 258210284Sjmallett /* CN31xx DFA memory is DDR based, so it is completely different from the CN38XX DFA memory 259210284Sjmallett ** config descriptors are not supported yet.*/ 260210284Sjmallett cvmx_dprintf("Warning: preliminary DFA memory configuration\n"); 261210284Sjmallett cn31xx_dfa_memory_init(); 262210284Sjmallett return(256*1024*1024); 263210284Sjmallett } 264210284Sjmallett 265210284Sjmallett /* If no descriptor passed, generate default descriptor based on board type. 266210284Sjmallett ** Fail if no default available for given board type 267210284Sjmallett */ 268210284Sjmallett if (!llm_desc_ptr) 269210284Sjmallett { 270210284Sjmallett /* Get default descriptor */ 271210284Sjmallett if (0 > cvmx_llm_get_default_descriptor(&default_llm_desc)) 272210284Sjmallett return -1; 273210284Sjmallett 274210284Sjmallett /* Disable second port depending on CVMX config */ 275210284Sjmallett if (CVMX_LLM_NUM_PORTS == 1) 276210284Sjmallett default_llm_desc.rld0_bunks = 0; // For single port: Force RLD0(P1) to appear EMPTY 277210284Sjmallett 278210284Sjmallett cvmx_dprintf("Using default LLM configuration for board %s (%d)\n", cvmx_board_type_to_string(sys_ptr->board_type), sys_ptr->board_type); 279210284Sjmallett 280210284Sjmallett llm_desc_ptr = &default_llm_desc; 281210284Sjmallett } 282210284Sjmallett 283210284Sjmallett 284210284Sjmallett 285210284Sjmallett rldram_csr_config_t ebt3000_rld_cfg; 286210284Sjmallett if (!rld_csr_config_generate(llm_desc_ptr, &ebt3000_rld_cfg)) 287210284Sjmallett { 288210284Sjmallett cvmx_dprintf("Configuring %d llm port(s).\n", !!llm_desc_ptr->rld0_bunks + !!llm_desc_ptr->rld1_bunks); 289210284Sjmallett write_rld_cfg(&ebt3000_rld_cfg); 290210284Sjmallett } 291210284Sjmallett else 292210284Sjmallett { 293210284Sjmallett cvmx_dprintf("Error creating rldram configuration\n"); 294210284Sjmallett return(-1); 295210284Sjmallett } 296210284Sjmallett 297210284Sjmallett /* Compute how much memory is configured 298210284Sjmallett ** Memory is interleaved, so if one port has more than the other some memory is not usable */ 299210284Sjmallett 300210284Sjmallett /* If both ports are enabled, handle the case where one port has more than the other. 301210284Sjmallett ** This is an unusual and not recommended configuration that exists on the ebt3000 board */ 302210284Sjmallett if (!!llm_desc_ptr->rld0_bunks && !!llm_desc_ptr->rld1_bunks) 303210284Sjmallett llm_desc_ptr->rld0_mbytes = llm_desc_ptr->rld1_mbytes = MIN(llm_desc_ptr->rld0_mbytes, llm_desc_ptr->rld1_mbytes); 304210284Sjmallett 305210284Sjmallett return(((!!llm_desc_ptr->rld0_bunks) * llm_desc_ptr->rld0_mbytes 306210284Sjmallett + (!!llm_desc_ptr->rld1_bunks) * llm_desc_ptr->rld1_mbytes) * 1024*1024); 307210284Sjmallett} 308210284Sjmallett 309210284Sjmallett//====================== 310210284Sjmallett// SUPPORT FUNCTIONS: 311210284Sjmallett//====================== 312210284Sjmallett//====================================================================== 313210284Sjmallett// Extracts srcvec[srcbitpos] and places it in return int (bit[0]) 314210284Sjmallettint bit_extract ( int srcvec, // source word (to extract) 315210284Sjmallett int srcbitpos // source bit position 316210284Sjmallett ) 317210284Sjmallett{ 318210284Sjmallett return(((1 << srcbitpos) & srcvec) >> srcbitpos); 319210284Sjmallett} 320210284Sjmallett//====================================================================== 321210284Sjmallett// Inserts srcvec[0] into dstvec[dstbitpos] (without affecting other bits) 322210284Sjmallettint bit_insert ( int srcvec, // srcvec[0] = bit to be inserted 323210284Sjmallett int dstbitpos, // Bit position to insert into returned int 324210284Sjmallett int dstvec // dstvec (destination vector) 325210284Sjmallett ) 326210284Sjmallett{ 327210284Sjmallett return((srcvec << dstbitpos) | dstvec); // Shift bit to insert into bit position/OR with accumulated number 328210284Sjmallett} 329210284Sjmallett//====================================================================== 330210284Sjmallett 331210284Sjmallettint rld_csr_config_generate(llm_descriptor_t *llm_desc_ptr, rldram_csr_config_t *cfg_ptr) 332210284Sjmallett{ 333210284Sjmallett char *addr_rld0_fb_str; 334210284Sjmallett char *addr_rld0_bb_str; 335210284Sjmallett char *addr_rld1_fb_str; 336210284Sjmallett char *addr_rld1_bb_str; 337210284Sjmallett int eclk_ps; 338210284Sjmallett int mtype = 0; // MTYPE (0: RLDRAM/1: FCRAM 339210284Sjmallett int trcmin = 20; // tRC(min) - from RLDRAM data sheet 340210284Sjmallett int trc_cyc; // TRC(cyc) 341210284Sjmallett int trc_mod; 342210284Sjmallett int trl_cyc; // TRL(cyc) 343210284Sjmallett int twl_cyc; // TWL(cyc) 344210284Sjmallett int tmrsc_cyc = 6; // tMRSC(cyc) [2-7] 345210284Sjmallett int mclk_ps; // DFA Memory Clock(in ps) = 2x eclk 346210284Sjmallett int rldcfg = 99; // RLDRAM-II CFG (1,2,3) 347210284Sjmallett int mrs_odt = 0; // RLDRAM MRS A[9]=ODT (default) 348210284Sjmallett int mrs_impmatch = 0; // RLDRAM MRS A[8]=Impedance Matching (default) 349210284Sjmallett int mrs_dllrst = 1; // RLDRAM MRS A[7]=DLL Reset (default) 350210284Sjmallett uint32_t mrs_dat; 351210284Sjmallett int mrs_dat_p0bunk0 = 0; // MRS Register Data After Address Map (for Port0 Bunk0) 352210284Sjmallett int mrs_dat_p0bunk1 = 0; // MRS Register Data After Address Map (for Port0 Bunk1) 353210284Sjmallett int mrs_dat_p1bunk0 = 0; // MRS Register Data After Address Map (for Port1 Bunk0) 354210284Sjmallett int mrs_dat_p1bunk1 = 0; // MRS Register Data After Address Map (for Port1 Bunk1) 355210284Sjmallett int p0_ena = 0; // DFA Port#0 Enabled 356210284Sjmallett int p1_ena = 0; // DFA Port#1 Enabled 357210284Sjmallett int memport = 0; // Memory(MB) per Port [MAX=512] 358210284Sjmallett int membunk; // Memory(MB) per Bunk 359210284Sjmallett int bunkport = 0; // Bunks/Port [1/2] 360210284Sjmallett int pbunk = 0; // Physical Bunk(or Rank) encoding for address bit 361210284Sjmallett int tref_ms = 32; // tREF(ms) (RLDRAM-II overall device refresh interval 362210284Sjmallett int trefi_ns; // tREFI(ns) = tREF(ns)/#rows/bank 363210284Sjmallett int rows = 8; // #rows/bank (K) typically 8K 364210284Sjmallett int ref512int; 365210284Sjmallett int ref512mod; 366210284Sjmallett int tskw_cyc = 0; 367210284Sjmallett int fprch = 1; 368210284Sjmallett int bprch = 0; 369210284Sjmallett int dfa_memcfg0_base = 0; 370210284Sjmallett int dfa_memcfg1_base = 0; 371210284Sjmallett int tbl = 1; // tBL (1: 2-burst /2: 4-burst) 372210284Sjmallett int rw_dly; 373210284Sjmallett int wr_dly; 374210284Sjmallett int r2r = 1; 375210284Sjmallett int sil_lat = 1; 376210284Sjmallett int clkdiv = 2; /* CN38XX is fixed at 2, CN58XX supports 2,3,4 */ 377210284Sjmallett int clkdiv_enc = 0x0; /* Encoded clock divisor, only used for CN58XX */ 378210284Sjmallett 379210284Sjmallett if (!llm_desc_ptr) 380210284Sjmallett return -1; 381210284Sjmallett 382210284Sjmallett /* Setup variables from descriptor */ 383210284Sjmallett 384210284Sjmallett addr_rld0_fb_str = llm_desc_ptr->addr_rld0_fb_str; 385210284Sjmallett addr_rld0_bb_str = llm_desc_ptr->addr_rld0_bb_str; 386210284Sjmallett addr_rld1_fb_str = llm_desc_ptr->addr_rld1_fb_str; 387210284Sjmallett addr_rld1_bb_str = llm_desc_ptr->addr_rld1_bb_str; 388210284Sjmallett 389210284Sjmallett p0_ena = !!llm_desc_ptr->rld1_bunks; // NOTE: P0 == RLD1 390210284Sjmallett p1_ena = !!llm_desc_ptr->rld0_bunks; // NOTE: P1 == RLD0 391210284Sjmallett 392210284Sjmallett // Massage the code, so that if the user had imbalanced memory per-port (or imbalanced bunks/port), we 393210284Sjmallett // at least try to configure 'workable' memory. 394210284Sjmallett if (p0_ena && p1_ena) // IF BOTH PORTS Enabled (imbalanced memory), select smaller of BOTH 395210284Sjmallett { 396210284Sjmallett memport = MIN(llm_desc_ptr->rld0_mbytes, llm_desc_ptr->rld1_mbytes); 397210284Sjmallett bunkport = MIN(llm_desc_ptr->rld0_bunks, llm_desc_ptr->rld1_bunks); 398210284Sjmallett } 399210284Sjmallett else if (p0_ena) // P0=RLD1 Enabled 400210284Sjmallett { 401210284Sjmallett memport = llm_desc_ptr->rld1_mbytes; 402210284Sjmallett bunkport = llm_desc_ptr->rld1_bunks; 403210284Sjmallett } 404210284Sjmallett else if (p1_ena) // P1=RLD0 Enabled 405210284Sjmallett { 406210284Sjmallett memport = llm_desc_ptr->rld0_mbytes; 407210284Sjmallett bunkport = llm_desc_ptr->rld0_bunks; 408210284Sjmallett } 409210284Sjmallett else 410210284Sjmallett return -1; 411210284Sjmallett 412210284Sjmallett uint32_t eclk_mhz = llm_desc_ptr->cpu_hz/1000000; 413210284Sjmallett 414210284Sjmallett 415210284Sjmallett 416210284Sjmallett /* Tweak skew based on cpu clock */ 417210284Sjmallett if (eclk_mhz <= 367) 418210284Sjmallett { 419210284Sjmallett tskw_cyc = 0; 420210284Sjmallett } 421210284Sjmallett else 422210284Sjmallett { 423210284Sjmallett tskw_cyc = 1; 424210284Sjmallett } 425210284Sjmallett 426210284Sjmallett /* Determine clock divider ratio (only required for CN58XX) */ 427210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN58XX)) 428210284Sjmallett { 429210284Sjmallett uint32_t max_llm_clock_mhz = llm_desc_ptr->max_rld_clock_mhz; 430210284Sjmallett if (!max_llm_clock_mhz) 431210284Sjmallett { 432210284Sjmallett max_llm_clock_mhz = 400; /* Default to 400 MHz */ 433210284Sjmallett cvmx_dprintf("Warning, using default max_rld_clock_mhz of: %lu MHz\n", (unsigned long)max_llm_clock_mhz); 434210284Sjmallett } 435210284Sjmallett 436210284Sjmallett /* Compute the divisor, and round up */ 437210284Sjmallett clkdiv = eclk_mhz/max_llm_clock_mhz; 438210284Sjmallett if (clkdiv * max_llm_clock_mhz < eclk_mhz) 439210284Sjmallett clkdiv++; 440210284Sjmallett 441210284Sjmallett if (clkdiv > 4) 442210284Sjmallett { 443210284Sjmallett cvmx_dprintf("ERROR: CN58XX LLM clock divisor out of range\n"); 444210284Sjmallett goto TERMINATE; 445210284Sjmallett } 446210284Sjmallett if (clkdiv < 2) 447210284Sjmallett clkdiv = 2; 448210284Sjmallett 449210284Sjmallett cvmx_dprintf("Using llm clock divisor: %d, llm clock is: %lu MHz\n", clkdiv, (unsigned long)eclk_mhz/clkdiv); 450210284Sjmallett /* Translate divisor into bit encoding for register */ 451210284Sjmallett /* 0 -> div 2 452210284Sjmallett ** 1 -> reserved 453210284Sjmallett ** 2 -> div 3 454210284Sjmallett ** 3 -> div 4 455210284Sjmallett */ 456210284Sjmallett if (clkdiv == 2) 457210284Sjmallett clkdiv_enc = 0; 458210284Sjmallett else 459210284Sjmallett clkdiv_enc = clkdiv - 1; 460210284Sjmallett 461210284Sjmallett /* Odd divisor needs sil_lat to be 2 */ 462210284Sjmallett if (clkdiv == 0x3) 463210284Sjmallett sil_lat = 2; 464210284Sjmallett 465210284Sjmallett /* Increment tskw for high clock speeds */ 466215990Sjmallett if ((unsigned long)eclk_mhz/clkdiv >= 375) 467210284Sjmallett tskw_cyc += 1; 468210284Sjmallett } 469210284Sjmallett 470210284Sjmallett eclk_ps = (1000000+(eclk_mhz-1)) / eclk_mhz; // round up if nonzero remainder 471210284Sjmallett //======================================================================= 472210284Sjmallett 473210284Sjmallett //======================================================================= 474210284Sjmallett // Now, Query User for DFA Memory Type 475210284Sjmallett if (mtype != 0) 476210284Sjmallett { 477210284Sjmallett goto TERMINATE; // Complete this code for FCRAM usage on N3K-P2 478210284Sjmallett } 479210284Sjmallett //======================================================================= 480210284Sjmallett // Query what the tRC(min) value is from the data sheets 481210284Sjmallett //======================================================================= 482210284Sjmallett // Now determine the Best CFG based on Memory clock(ps) and tRCmin(ns) 483210284Sjmallett mclk_ps = eclk_ps * clkdiv; 484210284Sjmallett trc_cyc = ((trcmin * 1000)/mclk_ps); 485210284Sjmallett trc_mod = ((trcmin * 1000) % mclk_ps); 486210284Sjmallett // If remainder exists, bump up to the next integer multiple 487210284Sjmallett if (trc_mod != 0) 488210284Sjmallett { 489210284Sjmallett trc_cyc = trc_cyc + 1; 490210284Sjmallett } 491210284Sjmallett // If tRC is now ODD, then bump it to the next EVEN integer (RLDRAM-II does not support odd tRC values at this time). 492210284Sjmallett if (trc_cyc & 1) 493210284Sjmallett { 494210284Sjmallett trc_cyc = trc_cyc + 1; // Bump it to an even # 495210284Sjmallett } 496210284Sjmallett // RLDRAM CFG Range Check: If the computed trc_cyc is less than 4, then set it to min CFG1 [tRC=4] 497210284Sjmallett if (trc_cyc < 4) 498210284Sjmallett { 499210284Sjmallett trc_cyc = 4; // If computed trc_cyc < 4 then clamp to 4 500210284Sjmallett } 501210284Sjmallett else if (trc_cyc > 8) 502210284Sjmallett { // If the computed trc_cyc > 8, then report an error (because RLDRAM cannot support a tRC>8 503210284Sjmallett goto TERMINATE; 504210284Sjmallett } 505210284Sjmallett // Assuming all is ok(up to here) 506210284Sjmallett // 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 507210284Sjmallett // the RLDRAM valid CFG range values. 508210284Sjmallett trl_cyc = trc_cyc; // tRL = tRC (for RLDRAM=II) 509210284Sjmallett twl_cyc = trl_cyc + 1; // tWL = tRL + 1 (for RLDRAM-II) 510210284Sjmallett // NOTE: RLDRAM-II (as of 4/25/05) only have 3 supported CFG encodings: 511210284Sjmallett if (trc_cyc == 4) 512210284Sjmallett { 513210284Sjmallett rldcfg = 1; // CFG #1 (tRL=4/tRC=4/tWL=5) 514210284Sjmallett } 515210284Sjmallett else if (trc_cyc == 6) 516210284Sjmallett { 517210284Sjmallett rldcfg = 2; // CFG #2 (tRL=6/tRC=6/tWL=7) 518210284Sjmallett } 519210284Sjmallett else if (trc_cyc == 8) 520210284Sjmallett { 521210284Sjmallett rldcfg = 3; // CFG #3 (tRL=8/tRC=8/tWL=9) 522210284Sjmallett } 523210284Sjmallett else 524210284Sjmallett { 525210284Sjmallett goto TERMINATE; 526210284Sjmallett } 527210284Sjmallett //======================================================================= 528210284Sjmallett mrs_dat = ( (mrs_odt << 9) | (mrs_impmatch << 8) | (mrs_dllrst << 7) | rldcfg ); 529210284Sjmallett //======================================================================= 530210284Sjmallett // If there is only a single bunk, then skip over address mapping queries (which are not required) 531210284Sjmallett if (bunkport == 1) 532210284Sjmallett { 533210284Sjmallett goto CALC_PBUNK; 534210284Sjmallett } 535210284Sjmallett 536210284Sjmallett /* Process the address mappings */ 537210284Sjmallett /* Note that that RLD0 pins corresponds to Port#1, and 538210284Sjmallett ** RLD1 pins corresponds to Port#0. 539210284Sjmallett */ 540210284Sjmallett mrs_dat_p1bunk0 = process_address_map_str(mrs_dat, addr_rld0_fb_str); 541210284Sjmallett mrs_dat_p1bunk1 = process_address_map_str(mrs_dat, addr_rld0_bb_str); 542210284Sjmallett mrs_dat_p0bunk0 = process_address_map_str(mrs_dat, addr_rld1_fb_str); 543210284Sjmallett mrs_dat_p0bunk1 = process_address_map_str(mrs_dat, addr_rld1_bb_str); 544210284Sjmallett 545210284Sjmallett 546210284Sjmallett //======================================================================= 547210284Sjmallett CALC_PBUNK: 548210284Sjmallett // Determine the PBUNK field (based on Memory/Bunk) 549210284Sjmallett // This determines the addr bit used to distinguish when crossing a bunk. 550210284Sjmallett // NOTE: For RLDRAM, the bunk bit is extracted from 'a' programmably selected high 551210284Sjmallett // order addr bit. [linear address per-bunk] 552210284Sjmallett if (bunkport == 2) 553210284Sjmallett { 554210284Sjmallett membunk = (memport / 2); 555210284Sjmallett } 556210284Sjmallett else 557210284Sjmallett { 558210284Sjmallett membunk = memport; 559210284Sjmallett } 560210284Sjmallett if (membunk == 16) 561210284Sjmallett { // 16MB/bunk MA[19] 562210284Sjmallett pbunk = 0; 563210284Sjmallett } 564210284Sjmallett else if (membunk == 32) 565210284Sjmallett { // 32MB/bunk MA[20] 566210284Sjmallett pbunk = 1; 567210284Sjmallett } 568210284Sjmallett else if (membunk == 64) 569210284Sjmallett { // 64MB/bunk MA[21] 570210284Sjmallett pbunk = 2; 571210284Sjmallett } 572210284Sjmallett else if (membunk == 128) 573210284Sjmallett { // 128MB/bunk MA[22] 574210284Sjmallett pbunk = 3; 575210284Sjmallett } 576210284Sjmallett else if (membunk == 256) 577210284Sjmallett { // 256MB/bunk MA[23] 578210284Sjmallett pbunk = 4; 579210284Sjmallett } 580210284Sjmallett else if (membunk == 512) 581210284Sjmallett { // 512MB/bunk 582210284Sjmallett } 583210284Sjmallett //======================================================================= 584210284Sjmallett //======================================================================= 585210284Sjmallett //======================================================================= 586210284Sjmallett // Now determine N3K REFINT 587210284Sjmallett trefi_ns = (tref_ms * 1000 * 1000) / (rows * 1024); 588210284Sjmallett ref512int = ((trefi_ns * 1000) / (eclk_ps * 512)); 589210284Sjmallett ref512mod = ((trefi_ns * 1000) % (eclk_ps * 512)); 590210284Sjmallett //======================================================================= 591210284Sjmallett // Ask about tSKW 592210284Sjmallett#if 0 593210284Sjmallett if (tskw_ps == 0) 594210284Sjmallett { 595210284Sjmallett tskw_cyc = 0; 596210284Sjmallett } 597210284Sjmallett else 598210284Sjmallett { // CEILING function 599210284Sjmallett tskw_cyc = (tskw_ps / eclk_ps); 600210284Sjmallett tskw_mod = (tskw_ps % eclk_ps); 601210284Sjmallett if (tskw_mod != 0) 602210284Sjmallett { // If there's a remainder - then bump to next (+1) 603210284Sjmallett tskw_cyc = tskw_cyc + 1; 604210284Sjmallett } 605210284Sjmallett } 606210284Sjmallett#endif 607210284Sjmallett if (tskw_cyc > 3) 608210284Sjmallett { 609210284Sjmallett goto TERMINATE; 610210284Sjmallett } 611210284Sjmallett 612210284Sjmallett tbl = 1; // BLEN=2 (ALWAYs for RLDRAM) 613210284Sjmallett //======================================================================= 614210284Sjmallett // RW_DLY = (ROUND_UP{[[(TRL+TBL)*2 + tSKW + BPRCH] + 1] / 2}) - tWL 615210284Sjmallett rw_dly = ((((trl_cyc + tbl) * 2 + tskw_cyc + bprch) + 1) / 2); 616210284Sjmallett if (rw_dly & 1) 617210284Sjmallett { // If it's ODD then round up 618210284Sjmallett rw_dly = rw_dly + 1; 619210284Sjmallett } 620210284Sjmallett rw_dly = rw_dly - twl_cyc +1 ; 621210284Sjmallett if (rw_dly < 0) 622210284Sjmallett { // range check - is it positive 623210284Sjmallett goto TERMINATE; 624210284Sjmallett } 625210284Sjmallett //======================================================================= 626210284Sjmallett // WR_DLY = (ROUND_UP[[(tWL + tBL)*2 - tSKW + FPRCH] / 2]) - tRL 627210284Sjmallett wr_dly = (((twl_cyc + tbl) * 2 - tskw_cyc + fprch) / 2); 628210284Sjmallett if (wr_dly & 1) 629210284Sjmallett { // If it's ODD then round up 630210284Sjmallett wr_dly = wr_dly + 1; 631210284Sjmallett } 632210284Sjmallett wr_dly = wr_dly - trl_cyc + 1; 633210284Sjmallett if (wr_dly < 0) 634210284Sjmallett { // range check - is it positive 635210284Sjmallett goto TERMINATE; 636210284Sjmallett } 637210284Sjmallett 638210284Sjmallett 639210284Sjmallett dfa_memcfg0_base = 0; 640210284Sjmallett dfa_memcfg0_base = ( p0_ena | 641210284Sjmallett (p1_ena << 1) | 642210284Sjmallett (mtype << 3) | 643210284Sjmallett (sil_lat << 4) | 644210284Sjmallett (rw_dly << 6) | 645210284Sjmallett (wr_dly << 10) | 646210284Sjmallett (fprch << 14) | 647210284Sjmallett (bprch << 16) | 648210284Sjmallett (0 << 18) | // BLEN=0(2-burst for RLDRAM) 649210284Sjmallett (pbunk << 19) | 650210284Sjmallett (r2r << 22) | // R2R=1 651210284Sjmallett (clkdiv_enc << 28 ) 652210284Sjmallett ); 653210284Sjmallett 654210284Sjmallett 655210284Sjmallett dfa_memcfg1_base = 0; 656210284Sjmallett dfa_memcfg1_base = ( ref512int | 657210284Sjmallett (tskw_cyc << 4) | 658210284Sjmallett (trl_cyc << 8) | 659210284Sjmallett (twl_cyc << 12) | 660210284Sjmallett (trc_cyc << 16) | 661210284Sjmallett (tmrsc_cyc << 20) 662210284Sjmallett ); 663210284Sjmallett 664210284Sjmallett 665210284Sjmallett 666210284Sjmallett 667210284Sjmallett cfg_ptr->dfa_memcfg0_base = dfa_memcfg0_base; 668210284Sjmallett cfg_ptr->dfa_memcfg1_base = dfa_memcfg1_base; 669210284Sjmallett cfg_ptr->mrs_dat_p0bunk0 = mrs_dat_p0bunk0; 670210284Sjmallett cfg_ptr->mrs_dat_p1bunk0 = mrs_dat_p1bunk0; 671210284Sjmallett cfg_ptr->mrs_dat_p0bunk1 = mrs_dat_p0bunk1; 672210284Sjmallett cfg_ptr->mrs_dat_p1bunk1 = mrs_dat_p1bunk1; 673210284Sjmallett cfg_ptr->p0_ena = p0_ena; 674210284Sjmallett cfg_ptr->p1_ena = p1_ena; 675210284Sjmallett cfg_ptr->bunkport = bunkport; 676210284Sjmallett //======================================================================= 677210284Sjmallett 678210284Sjmallett return(0); 679210284Sjmallett TERMINATE: 680210284Sjmallett return(-1); 681210284Sjmallett 682210284Sjmallett} 683210284Sjmallett 684210284Sjmallett 685210284Sjmallett 686210284Sjmallettstatic uint32_t process_address_map_str(uint32_t mrs_dat, char *addr_str) 687210284Sjmallett{ 688210284Sjmallett int count = 0; 689210284Sjmallett int amap [23]; 690210284Sjmallett uint32_t new_mrs_dat = 0; 691210284Sjmallett 692210284Sjmallett// cvmx_dprintf("mrs_dat: 0x%x, str: %x\n", mrs_dat, addr_str); 693210284Sjmallett char *charptr = strtok(addr_str," "); 694210284Sjmallett while ((charptr != NULL) & (count <= 22)) 695210284Sjmallett { 696210284Sjmallett amap[22-count] = atoi(charptr); // Assign the AMAP Array 697210284Sjmallett charptr = strtok(NULL," "); // Get Next char string (which represents next addr bit mapping) 698210284Sjmallett count++; 699210284Sjmallett } 700210284Sjmallett // Now do the bit swap of MRSDAT (based on address mapping) 701210284Sjmallett uint32_t mrsdat_bit; 702210284Sjmallett for (count=0;count<=22;count++) 703210284Sjmallett { 704210284Sjmallett mrsdat_bit = bit_extract(mrs_dat, count); 705210284Sjmallett new_mrs_dat = bit_insert(mrsdat_bit, amap[count], new_mrs_dat); 706210284Sjmallett } 707210284Sjmallett 708210284Sjmallett return new_mrs_dat; 709210284Sjmallett} 710210284Sjmallett 711210284Sjmallett 712210284Sjmallett//#define PRINT_LLM_CONFIG 713210284Sjmallett#ifdef PRINT_LLM_CONFIG 714210284Sjmallett#define ll_printf printf 715210284Sjmallett#else 716210284Sjmallett#define ll_printf(...) 717210284Sjmallett#define cvmx_csr_db_decode(...) 718210284Sjmallett#endif 719210284Sjmallett 720210284Sjmallettstatic void cn31xx_dfa_memory_init(void) 721210284Sjmallett{ 722210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN31XX)) 723210284Sjmallett { 724210284Sjmallett cvmx_dfa_ddr2_cfg_t dfaCfg; 725210284Sjmallett cvmx_dfa_eclkcfg_t dfaEcklCfg; 726210284Sjmallett cvmx_dfa_ddr2_addr_t dfaAddr; 727210284Sjmallett cvmx_dfa_ddr2_tmg_t dfaTmg; 728210284Sjmallett cvmx_dfa_ddr2_pll_t dfaPll; 729210284Sjmallett int mem_freq_hz = 533*1000000; 730210284Sjmallett int ref_freq_hz = cvmx_sysinfo_get()->dfa_ref_clock_hz; 731210284Sjmallett if (!ref_freq_hz) 732210284Sjmallett ref_freq_hz = 33*1000000; 733210284Sjmallett 734210284Sjmallett cvmx_dprintf ("Configuring DFA memory for %d MHz operation.\n",mem_freq_hz/1000000); 735210284Sjmallett 736210284Sjmallett /* Turn on the DFA memory port. */ 737210284Sjmallett dfaCfg.u64 = cvmx_read_csr (CVMX_DFA_DDR2_CFG); 738210284Sjmallett dfaCfg.s.prtena = 1; 739210284Sjmallett cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64); 740210284Sjmallett 741210284Sjmallett /* Start the PLL alignment sequence */ 742210284Sjmallett dfaPll.u64 = 0; 743210284Sjmallett dfaPll.s.pll_ratio = mem_freq_hz/ref_freq_hz /*400Mhz / 33MHz*/; 744210284Sjmallett dfaPll.s.pll_div2 = 1 /*400 - 1 */; 745210284Sjmallett dfaPll.s.pll_bypass = 0; 746210284Sjmallett cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64); 747210284Sjmallett 748210284Sjmallett dfaPll.s.pll_init = 1; 749210284Sjmallett cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64); 750210284Sjmallett 751210284Sjmallett cvmx_wait (RLD_INIT_DELAY); //want 150uS 752210284Sjmallett dfaPll.s.qdll_ena = 1; 753210284Sjmallett cvmx_write_csr (CVMX_DFA_DDR2_PLL, dfaPll.u64); 754210284Sjmallett 755210284Sjmallett cvmx_wait (RLD_INIT_DELAY); //want 10us 756210284Sjmallett dfaEcklCfg.u64 = 0; 757210284Sjmallett dfaEcklCfg.s.dfa_frstn = 1; 758210284Sjmallett cvmx_write_csr (CVMX_DFA_ECLKCFG, dfaEcklCfg.u64); 759210284Sjmallett 760210284Sjmallett /* Configure the DFA Memory */ 761210284Sjmallett dfaCfg.s.silo_hc = 1 /*400 - 1 */; 762210284Sjmallett dfaCfg.s.silo_qc = 0 /*400 - 0 */; 763210284Sjmallett dfaCfg.s.tskw = 1 /*400 - 1 */; 764210284Sjmallett dfaCfg.s.ref_int = 0x820 /*533 - 0x820 400 - 0x618*/; 765210284Sjmallett dfaCfg.s.trfc = 0x1A /*533 - 0x23 400 - 0x1A*/; 766210284Sjmallett dfaCfg.s.fprch = 0; /* 1 more conservative*/ 767210284Sjmallett dfaCfg.s.bprch = 0; /* 1 */ 768210284Sjmallett cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64); 769210284Sjmallett 770210284Sjmallett dfaEcklCfg.u64 = cvmx_read_csr (CVMX_DFA_ECLKCFG); 771210284Sjmallett dfaEcklCfg.s.maxbnk = 1; 772210284Sjmallett cvmx_write_csr (CVMX_DFA_ECLKCFG, dfaEcklCfg.u64); 773210284Sjmallett 774210284Sjmallett dfaAddr.u64 = cvmx_read_csr (CVMX_DFA_DDR2_ADDR); 775210284Sjmallett dfaAddr.s.num_cols = 0x1; 776210284Sjmallett dfaAddr.s.num_colrows = 0x2; 777210284Sjmallett dfaAddr.s.num_rnks = 0x1; 778210284Sjmallett cvmx_write_csr (CVMX_DFA_DDR2_ADDR, dfaAddr.u64); 779210284Sjmallett 780210284Sjmallett dfaTmg.u64 = cvmx_read_csr (CVMX_DFA_DDR2_TMG); 781210284Sjmallett dfaTmg.s.ddr2t = 0; 782210284Sjmallett dfaTmg.s.tmrd = 0x2; 783210284Sjmallett dfaTmg.s.caslat = 0x4 /*400 - 0x3, 500 - 0x4*/; 784210284Sjmallett dfaTmg.s.pocas = 0; 785210284Sjmallett dfaTmg.s.addlat = 0; 786210284Sjmallett dfaTmg.s.trcd = 4 /*400 - 3, 500 - 4*/; 787210284Sjmallett dfaTmg.s.trrd = 2; 788210284Sjmallett dfaTmg.s.tras = 0xB /*400 - 8, 500 - 0xB*/; 789210284Sjmallett dfaTmg.s.trp = 4 /*400 - 3, 500 - 4*/; 790210284Sjmallett dfaTmg.s.twr = 4 /*400 - 3, 500 - 4*/; 791210284Sjmallett dfaTmg.s.twtr = 2 /*400 - 2 */; 792210284Sjmallett dfaTmg.s.tfaw = 0xE /*400 - 0xA, 500 - 0xE*/; 793210284Sjmallett dfaTmg.s.r2r_slot = 0; 794210284Sjmallett dfaTmg.s.dic = 0; /*400 - 0 */ 795210284Sjmallett dfaTmg.s.dqsn_ena = 0; 796210284Sjmallett dfaTmg.s.odt_rtt = 0; 797210284Sjmallett cvmx_write_csr (CVMX_DFA_DDR2_TMG, dfaTmg.u64); 798210284Sjmallett 799210284Sjmallett /* Turn on the DDR2 interface and wait a bit for the hardware to setup. */ 800210284Sjmallett dfaCfg.s.init = 1; 801210284Sjmallett cvmx_write_csr (CVMX_DFA_DDR2_CFG, dfaCfg.u64); 802210284Sjmallett cvmx_wait(RLD_INIT_DELAY); // want at least 64K cycles 803210284Sjmallett } 804210284Sjmallett} 805210284Sjmallett 806210284Sjmallettvoid write_rld_cfg(rldram_csr_config_t *cfg_ptr) 807210284Sjmallett{ 808210284Sjmallett cvmx_dfa_memcfg0_t memcfg0; 809210284Sjmallett cvmx_dfa_memcfg2_t memcfg2; 810210284Sjmallett 811210284Sjmallett memcfg0.u64 = cfg_ptr->dfa_memcfg0_base; 812210284Sjmallett 813210284Sjmallett if ((OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))) 814210284Sjmallett { 815210284Sjmallett uint32_t dfa_memcfg0; 816210284Sjmallett 817210284Sjmallett if (OCTEON_IS_MODEL (OCTEON_CN58XX)) { 818210284Sjmallett // Set RLDQK90_RST and RDLCK_RST to reset all three DLLs. 819210284Sjmallett memcfg0.s.rldck_rst = 1; 820210284Sjmallett memcfg0.s.rldqck90_rst = 1; 821210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64); 822210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x clk/qk90 reset\n", (uint32_t) memcfg0.u64); 823210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64); 824210284Sjmallett 825210284Sjmallett // Clear RDLCK_RST while asserting RLDQK90_RST to bring RLDCK DLL out of reset. 826210284Sjmallett memcfg0.s.rldck_rst = 0; 827210284Sjmallett memcfg0.s.rldqck90_rst = 1; 828210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64); 829210284Sjmallett cvmx_wait(4000000); /* Wait */ 830210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x qk90 reset\n", (uint32_t) memcfg0.u64); 831210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64); 832210284Sjmallett 833210284Sjmallett // Clear both RDLCK90_RST and RLDQK90_RST to bring the RLDQK90 DLL out of reset. 834210284Sjmallett memcfg0.s.rldck_rst = 0; 835210284Sjmallett memcfg0.s.rldqck90_rst = 0; 836210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, memcfg0.u64); 837210284Sjmallett cvmx_wait(4000000); /* Wait */ 838210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x DLL out of reset\n", (uint32_t) memcfg0.u64); 839210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), memcfg0.u64); 840210284Sjmallett } 841210284Sjmallett 842210284Sjmallett //======================================================================= 843210284Sjmallett // Now print out the sequence of events: 844210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base); 845210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x port enables\n", cfg_ptr->dfa_memcfg0_base); 846210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base); 847210284Sjmallett cvmx_wait(4000000); /* Wait */ 848210284Sjmallett 849210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG1, cfg_ptr->dfa_memcfg1_base); 850210284Sjmallett ll_printf("CVMX_DFA_MEMCFG1: 0x%08x\n", cfg_ptr->dfa_memcfg1_base); 851210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG1 & ~(1ull<<63), cfg_ptr->dfa_memcfg1_base); 852210284Sjmallett 853210284Sjmallett if (cfg_ptr->p0_ena ==1) 854210284Sjmallett { 855210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMRLD, cfg_ptr->mrs_dat_p0bunk0); 856210284Sjmallett ll_printf("CVMX_DFA_MEMRLD : 0x%08x p0_ena memrld\n", cfg_ptr->mrs_dat_p0bunk0); 857210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p0bunk0); 858210284Sjmallett 859210284Sjmallett dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base | 860210284Sjmallett (1 << 23) | // P0_INIT 861210284Sjmallett (1 << 25) // BUNK_INIT[1:0]=Bunk#0 862210284Sjmallett ); 863210284Sjmallett 864210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0); 865210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x p0_init/bunk_init\n", dfa_memcfg0); 866210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0); 867210284Sjmallett cvmx_wait(RLD_INIT_DELAY); 868210284Sjmallett ll_printf("Delay.....\n"); 869210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base); 870210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x back to base\n", cfg_ptr->dfa_memcfg0_base); 871210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base); 872210284Sjmallett } 873210284Sjmallett 874210284Sjmallett if (cfg_ptr->p1_ena ==1) 875210284Sjmallett { 876210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMRLD, cfg_ptr->mrs_dat_p1bunk0); 877210284Sjmallett ll_printf("CVMX_DFA_MEMRLD : 0x%08x p1_ena memrld\n", cfg_ptr->mrs_dat_p1bunk0); 878210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p1bunk0); 879210284Sjmallett 880210284Sjmallett dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base | 881210284Sjmallett (1 << 24) | // P1_INIT 882210284Sjmallett (1 << 25) // BUNK_INIT[1:0]=Bunk#0 883210284Sjmallett ); 884210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0); 885210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x p1_init/bunk_init\n", dfa_memcfg0); 886210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0); 887210284Sjmallett cvmx_wait(RLD_INIT_DELAY); 888210284Sjmallett ll_printf("Delay.....\n"); 889210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base); 890210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x back to base\n", cfg_ptr->dfa_memcfg0_base); 891210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base); 892210284Sjmallett } 893210284Sjmallett 894210284Sjmallett // P0 Bunk#1 895210284Sjmallett if ((cfg_ptr->p0_ena ==1) && (cfg_ptr->bunkport == 2)) 896210284Sjmallett { 897210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMRLD, cfg_ptr->mrs_dat_p0bunk1); 898210284Sjmallett ll_printf("CVMX_DFA_MEMRLD : 0x%08x p0_ena memrld\n", cfg_ptr->mrs_dat_p0bunk1); 899210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p0bunk1); 900210284Sjmallett 901210284Sjmallett dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base | 902210284Sjmallett (1 << 23) | // P0_INIT 903210284Sjmallett (2 << 25) // BUNK_INIT[1:0]=Bunk#1 904210284Sjmallett ); 905210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0); 906210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x p0_init/bunk_init\n", dfa_memcfg0); 907210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0); 908210284Sjmallett cvmx_wait(RLD_INIT_DELAY); 909210284Sjmallett ll_printf("Delay.....\n"); 910210284Sjmallett 911210284Sjmallett if (cfg_ptr->p1_ena == 1) 912210284Sjmallett { // Re-arm Px_INIT if P1-B1 init is required 913210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, cfg_ptr->dfa_memcfg0_base); 914210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x px_init rearm\n", cfg_ptr->dfa_memcfg0_base); 915210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), cfg_ptr->dfa_memcfg0_base); 916210284Sjmallett } 917210284Sjmallett } 918210284Sjmallett 919210284Sjmallett if ((cfg_ptr->p1_ena == 1) && (cfg_ptr->bunkport == 2)) 920210284Sjmallett { 921210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMRLD, cfg_ptr->mrs_dat_p1bunk1); 922210284Sjmallett ll_printf("CVMX_DFA_MEMRLD : 0x%08x p1_ena memrld\n", cfg_ptr->mrs_dat_p1bunk1); 923210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMRLD & ~(1ull<<63), cfg_ptr->mrs_dat_p1bunk1); 924210284Sjmallett 925210284Sjmallett dfa_memcfg0 = ( cfg_ptr->dfa_memcfg0_base | 926210284Sjmallett (1 << 24) | // P1_INIT 927210284Sjmallett (2 << 25) // BUNK_INIT[1:0]=10 928210284Sjmallett ); 929210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0); 930210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x p1_init/bunk_init\n", dfa_memcfg0); 931210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0); 932210284Sjmallett } 933210284Sjmallett cvmx_wait(4000000); // 1/100S, 0.01S, 10mS 934210284Sjmallett ll_printf("Delay.....\n"); 935210284Sjmallett 936210284Sjmallett /* Enable bunks */ 937210284Sjmallett dfa_memcfg0 = cfg_ptr->dfa_memcfg0_base |((cfg_ptr->bunkport >= 1) << 25) | ((cfg_ptr->bunkport == 2) << 26); 938210284Sjmallett cvmx_write_csr(CVMX_DFA_MEMCFG0, dfa_memcfg0); 939210284Sjmallett ll_printf("CVMX_DFA_MEMCFG0: 0x%08x enable bunks\n", dfa_memcfg0); 940210284Sjmallett cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_DFA_MEMCFG0 & ~(1ull<<63), dfa_memcfg0); 941210284Sjmallett cvmx_wait(RLD_INIT_DELAY); 942210284Sjmallett ll_printf("Delay.....\n"); 943210284Sjmallett 944210284Sjmallett /* Issue a Silo reset by toggling SILRST in memcfg2. */ 945210284Sjmallett memcfg2.u64 = cvmx_read_csr (CVMX_DFA_MEMCFG2); 946210284Sjmallett memcfg2.s.silrst = 1; 947210284Sjmallett cvmx_write_csr (CVMX_DFA_MEMCFG2, memcfg2.u64); 948210284Sjmallett ll_printf("CVMX_DFA_MEMCFG2: 0x%08x silo reset start\n", (uint32_t) memcfg2.u64); 949210284Sjmallett memcfg2.s.silrst = 0; 950210284Sjmallett cvmx_write_csr (CVMX_DFA_MEMCFG2, memcfg2.u64); 951210284Sjmallett ll_printf("CVMX_DFA_MEMCFG2: 0x%08x silo reset done\n", (uint32_t) memcfg2.u64); 952210284Sjmallett } 953210284Sjmallett} 954210284Sjmallett 955