1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Memory Config Utility File: memconfig.c 5 * 6 * Author: Mitch Lichtenberg 7 * 8 * This host tool lets you enter DRAM parameters and run CFE's 9 * standard memory configuration to calculate the relevant timing 10 * parameters. It's a good way to see what CFE would have done, 11 * to find bogus timing calculations. 12 * 13 ********************************************************************* 14 * 15 * Copyright 2000,2001,2002,2003 16 * Broadcom Corporation. All rights reserved. 17 * 18 * This software is furnished under license and may be used and 19 * copied only in accordance with the following terms and 20 * conditions. Subject to these conditions, you may download, 21 * copy, install, use, modify and distribute modified or unmodified 22 * copies of this software in source and/or binary form. No title 23 * or ownership is transferred hereby. 24 * 25 * 1) Any source code used, modified or distributed must reproduce 26 * and retain this copyright notice and list of conditions 27 * as they appear in the source file. 28 * 29 * 2) No right is granted to use any trade name, trademark, or 30 * logo of Broadcom Corporation. The "Broadcom Corporation" 31 * name may not be used to endorse or promote products derived 32 * from this software without the prior written permission of 33 * Broadcom Corporation. 34 * 35 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 36 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 37 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 38 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 39 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 40 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 41 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 43 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 45 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 46 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 47 * THE POSSIBILITY OF SUCH DAMAGE. 48 ********************************************************************* */ 49 50#include <stdio.h> 51#include <string.h> 52#include <stdlib.h> 53 54/* ********************************************************************* 55 * Basic types 56 ********************************************************************* */ 57 58typedef unsigned char uint8_t; 59typedef unsigned short uint16_t; 60typedef unsigned int uint32_t; 61typedef unsigned long long uint64_t; 62 63/* ********************************************************************* 64 * SB1250 stuff 65 ********************************************************************* */ 66 67#include "sb1250_defs.h" 68#include "sb1250_mc.h" 69#include "sb1250_draminit.h" 70#include "sb1250_regs.h" 71#include "sb1250_scd.h" 72 73/* ********************************************************************* 74 * BCD macros 75 ********************************************************************* */ 76 77#define DECTO10THS(x) ((((x) >> 4)*10)+((x) & 0x0F)) 78 79/* ********************************************************************* 80 * Global defaults 81 ********************************************************************* */ 82 83#define MIN_tMEMCLK DRT10(8,0) 84#define tROUNDTRIP DRT10(2,5) 85 86/* ********************************************************************* 87 * Types 88 ********************************************************************* */ 89 90typedef struct encvalue_s { 91 char *name; 92 uint8_t val; 93} encvalue_t; 94 95typedef struct spdbyte_s { 96 char *name; 97 uint8_t *data; 98 int decimal; 99 encvalue_t *values; 100 char *units; 101 char *description; 102 char *deflt; 103} spdbyte_t; 104 105#define SPD_DEC_BCD 1 106#define SPD_DEC_QTR 2 107#define SPD_ENCODED 3 108#define SPD_ENCODED2 4 109 110#define SPD_SIZE 64 111 112/* ********************************************************************* 113 * Globals 114 ********************************************************************* */ 115 116 117uint8_t spd[SPD_SIZE] = {0}; /* SPD data */ 118uint8_t mintmemclk = MIN_tMEMCLK; /* Default value: 8.0ns */ 119uint8_t roundtrip = tROUNDTRIP; /* Default value: 2.5ns */ 120uint8_t dramtype = JEDEC; /* Regular DDR SDRAMs */ 121uint8_t plldiv = 16; /* 500 MHz using 100Mhz refclk */ 122uint8_t refclk = 100; /* 100Mhz reference clock */ 123uint8_t portintlv = 0; /* no port interleaving */ 124 125uint8_t addrskew = 0x8; 126uint8_t dqoskew = 0x8; 127uint8_t dqiskew = 0x8; 128uint8_t addrdrive = 0xF; 129uint8_t datadrive = 0xF; 130uint8_t clkdrive = 0xF; 131 132uint64_t mc0_mclkcfg; /* Value programmed by draminit */ 133uint64_t mc0_timing1; /* Value programmed by draminit */ 134uint64_t mc1_mclkcfg; /* Value programmed by draminit */ 135uint64_t mc1_timing1; /* Value programmed by draminit */ 136uint64_t mc0_config,mc1_config; 137uint64_t mc0_cs_start,mc0_cs_end; 138uint64_t mc1_cs_start,mc1_cs_end; 139uint64_t smbus0_start = 0; /* Rememberd SMBus register value */ 140uint64_t smbus0_cmd = 0; /* Rememberd SMBus register value */ 141 142extern int sb1250_refclk; /* from draminit - reference clock */ 143extern int dram_cas_latency; /* from draminit - calc'd cas latency */ 144extern int dram_tMemClk; /* from draminit - calc'd tMemClk */ 145 146draminittab_t inittab[16]; /* our init tab */ 147 148static uint8_t csels = 1; 149static uint8_t channels = 1; 150 151int debug = 0; 152int asmout = 0; 153FILE *asmoutfile = NULL; 154 155uint64_t sbreadcsr(uint64_t reg); 156void sbwritecsr(uint64_t reg,uint64_t val); 157void sbdelay(void); 158uint64_t sb1250_dram_init(draminittab_t *tab,void *data); 159 160/* ********************************************************************* 161 * Parameter and value tables 162 ********************************************************************* */ 163 164encvalue_t caslatencies[] = { 165 {"3.5",JEDEC_CASLAT_35}, 166 {"3.0",JEDEC_CASLAT_30}, 167 {"2.5",JEDEC_CASLAT_25}, 168 {"2.0",JEDEC_CASLAT_20}, 169 {"1.5",JEDEC_CASLAT_15}, 170 {"1.0",JEDEC_CASLAT_10}, 171 {NULL,0}}; 172 173encvalue_t refreshrates[] = { 174 {"64",JEDEC_RFSH_64khz}, 175 {"256",JEDEC_RFSH_256khz}, 176 {"128",JEDEC_RFSH_128khz}, 177 {"32",JEDEC_RFSH_32khz}, 178 {"16",JEDEC_RFSH_16khz}, 179 {"8",JEDEC_RFSH_8khz}, 180 {NULL,0}}; 181 182encvalue_t modattribs[] = { 183 {"none",0}, 184 {"reg",JEDEC_ATTRIB_REG}, 185 {"diffclk",0x20}, 186 {NULL,0}}; 187 188encvalue_t dramtypes[] = { 189 {"jedec",JEDEC}, 190 {"fcram",FCRAM}, 191 {"sgram",SGRAM}, 192 {NULL,0}}; 193 194spdbyte_t spdfields[] = { 195 {"plldiv", &plldiv, 0,NULL,"","PLL Ratio (System Config Register)","16"}, 196 {"refclk", &refclk, 0,NULL,"Mhz","Reference clock, usually 100Mhz","100"}, 197 {"mintmemclk",&mintmemclk,SPD_DEC_BCD,NULL,"ns","Minimum value for tMEMCLK","8.0"}, 198 {"roundtrip", &roundtrip, SPD_DEC_BCD,NULL,"ns","Round trip time from CLK to returned DQS","2.5"}, 199 {"chans", &channels, 0,NULL,"","Bitmask of enabled channels (bit0=chan0)","1"}, 200 {"csels", &csels, 0,NULL,"","Bitmask of enabled chipsels","1"}, 201 {"portintlv", &portintlv, 0,NULL,"","Port interleave (1=on)","0"}, 202 {"memtype", &dramtype, SPD_ENCODED,dramtypes,"","Memory type (jedec, fcram, sgram)","jedec"}, 203 {"rows", &spd[JEDEC_SPD_ROWS],0,NULL,"","[3 ] Number of row bits","13"}, 204 {"cols", &spd[JEDEC_SPD_COLS],0,NULL,"","[4 ] Number of column bits","9"}, 205 {"banks", &spd[JEDEC_SPD_BANKS],0,NULL,"","[17] Number of banks","4"}, 206 {"tCK25", &spd[JEDEC_SPD_tCK25],SPD_DEC_BCD,NULL,"ns","[9 ] tCK value for CAS Latency 2.5","7.5"}, 207 {"tCK20", &spd[JEDEC_SPD_tCK20],SPD_DEC_BCD,NULL,"ns","[23] tCK value for CAS Latency 2.0","0"}, 208 {"tCK10", &spd[JEDEC_SPD_tCK10],SPD_DEC_BCD,NULL,"ns","[25] tCK value for CAS Latency 1.0","0"}, 209 {"rfsh", &spd[JEDEC_SPD_RFSH],SPD_ENCODED,refreshrates,"","[12] Refresh rate (KHz)","8"}, 210 {"caslat", &spd[JEDEC_SPD_CASLATENCIES],SPD_ENCODED2,caslatencies,"","[18] CAS Latencies supported","2.5"}, 211 {"attrib", &spd[JEDEC_SPD_ATTRIBUTES],SPD_ENCODED,modattribs,"","[21] Module attributes","none"}, 212 {"tRAS", &spd[JEDEC_SPD_tRAS],0,NULL,"ns","[30]","45"}, 213 {"tRP", &spd[JEDEC_SPD_tRP],SPD_DEC_QTR,NULL,"ns","[27]","20.0"}, 214 {"tRRD", &spd[JEDEC_SPD_tRRD],SPD_DEC_QTR,NULL,"ns","[28]","15.0"}, 215 {"tRCD", &spd[JEDEC_SPD_tRCD],SPD_DEC_QTR,NULL,"ns","[29]","20.0"}, 216 {"tRFC", &spd[JEDEC_SPD_tRFC],0,NULL,"ns","[42]","0"}, 217 {"tRC", &spd[JEDEC_SPD_tRC],0,NULL,"ns","[41]","0"}, 218 219 {"addrskew", &addrskew, 0, NULL, "","Address Skew","0x0F"}, 220 {"dqoskew", &dqoskew, 0, NULL, "","DQO Skew","0x08"}, 221 {"dqikew", &dqiskew, 0, NULL, "","DQI Skew","0x08"}, 222 {"addrdrive", &addrdrive, 0, NULL, "","Address Drive","0x0F"}, 223 {"datadrive", &datadrive, 0, NULL, "","Data Drive","0x0F"}, 224 {"clkdrive", &clkdrive, 0, NULL, "","Clock Drive","0"}, 225 {NULL,0,0,NULL,NULL,NULL,NULL}}; 226 227static char *lookupstr(encvalue_t *ev,uint8_t val) 228{ 229 while (ev->name) { 230 if (ev->val == val) return ev->name; 231 ev++; 232 } 233 return "unknown"; 234} 235 236uint64_t sbreadcsr(uint64_t reg) 237{ 238 uint64_t val = 0; 239 240 if (debug) printf("READ %08X\n",(uint32_t) reg); 241 242 243 switch ((uint32_t) reg) { 244 case A_SCD_SYSTEM_REVISION: 245 val = V_SYS_PART(0x1250) | V_SYS_WID(0) | V_SYS_REVISION(K_SYS_REVISION_PASS2) | 0xFF; 246 break; 247 case A_SCD_SYSTEM_CFG: 248 val = V_SYS_PLL_DIV(plldiv); 249 break; 250 case A_SMB_STATUS_0: 251 val = 0; 252 break; 253 case A_SMB_CMD_0: 254 val = smbus0_cmd; 255 break; 256 case A_SMB_START_0: 257 val = smbus0_start; 258 break; 259 case A_SMB_DATA_0: 260 val = spd[smbus0_cmd & 0x3F]; 261 break; 262 case A_MC_REGISTER(0,R_MC_CS_START): 263 val = mc0_cs_start; 264 break; 265 case A_MC_REGISTER(0,R_MC_CS_END): 266 val = mc0_cs_end; 267 break; 268 case A_MC_REGISTER(0,R_MC_CONFIG): 269 val = mc0_config; 270 break; 271 case A_MC_REGISTER(1,R_MC_CS_START): 272 val = mc1_cs_start; 273 break; 274 case A_MC_REGISTER(1,R_MC_CS_END): 275 val = mc1_cs_end; 276 break; 277 case A_MC_REGISTER(1,R_MC_CONFIG): 278 val = mc1_config; 279 break; 280 default: 281 printf("Warning: CSR %08X not supported by emulated SBREADCSR\n",(uint32_t)reg); 282 } 283 return val; 284} 285 286void sbdelay(void) 287{ 288 if (asmoutfile) fprintf(asmoutfile,"\t.dword 0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFF /* Insert delay here */\n"); 289} 290 291void sbwritecsr(uint64_t reg,uint64_t val) 292{ 293 if (debug) printf("WRITE %08X %016llX\n",(uint32_t) reg,val); 294 295 if (asmoutfile) fprintf(asmoutfile,"\t.dword 0x%016llX,0x%016llX\n",reg,val); 296 297 switch ((uint32_t) reg) { 298 case A_MC_REGISTER(0,R_MC_MCLK_CFG): 299 mc0_mclkcfg = val; 300 break; 301 case A_MC_REGISTER(0,R_MC_TIMING1): 302 mc0_timing1 = val; 303 break; 304 case A_MC_REGISTER(1,R_MC_MCLK_CFG): 305 mc1_mclkcfg = val; 306 break; 307 case A_MC_REGISTER(1,R_MC_TIMING1): 308 mc1_timing1 = val; 309 break; 310 case A_SMB_CMD_0: 311 smbus0_cmd = val; 312 break; 313 case A_SMB_START_0: 314 smbus0_start = val; 315 break; 316 case A_MC_REGISTER(0,R_MC_CS_START): 317 mc0_cs_start = val; 318 break; 319 case A_MC_REGISTER(0,R_MC_CS_END): 320 mc0_cs_end = val; 321 break; 322 case A_MC_REGISTER(0,R_MC_CONFIG): 323 mc0_config = val; 324 break; 325 case A_MC_REGISTER(1,R_MC_CS_START): 326 mc1_cs_start = val; 327 break; 328 case A_MC_REGISTER(1,R_MC_CS_END): 329 mc1_cs_end = val; 330 break; 331 case A_MC_REGISTER(1,R_MC_CONFIG): 332 mc1_config = val; 333 break; 334 default: 335 break; 336 } 337} 338 339static int readspdfile(uint8_t *spd,char *fname) 340{ 341 FILE *str; 342 char line[500]; 343 char *x; 344 unsigned int addr,val; 345 int idx; 346 uint8_t ttl; 347 348 str = fopen(fname,"r"); 349 if (!str) { 350 perror(fname); 351 return -1; 352 } 353 354 memset(spd,0,SPD_SIZE); 355 356 while (!feof(str)) { 357 if (!fgets(line,sizeof(line),str)) break; 358 if ((x = strchr(line,'\r'))) *x = '\0'; 359 if (line[0] == '\0') continue; /* blank line */ 360 if (line[0] == '#') continue; /* comment */ 361 if (strchr(line,'=') == NULL) continue; 362 if (sscanf(line,"%u=%02x",&addr,&val) != 2) { 363 printf("Incorrect line format: %s\n",line); 364 continue; 365 } 366 if ((addr >= SPD_SIZE) || (val >= 0x100)) { 367 printf("Values out of range: %s\n",line); 368 continue; 369 } 370 371 spd[addr] = val; 372 } 373 374 ttl = 0; 375 for (idx = 0; idx < 63; idx++) ttl += spd[idx]; 376 377 if (ttl != spd[63]) printf("Warning: checksum mismatch on SPD file: %02X\n",ttl); 378 379 fclose(str); 380 return 0; 381} 382 383 384static int procfield(char *txt) 385{ 386 int num = 0; 387 int a,b; 388 spdbyte_t *sf; 389 encvalue_t *ev; 390 char *x; 391 char *tok; 392 393 x = strchr(txt,'='); 394 if (!x) { 395 printf("Fields must be specified as 'name=value'\n"); 396 exit(1); 397 } 398 *x++ = '\0'; 399 400 sf = spdfields; 401 while (sf->name) { 402 if (strcmp(sf->name,txt) == 0) break; 403 sf++; 404 } 405 406 if (sf->name == NULL) { 407 printf("Invalid field name: %s\n",txt); 408 return -1; 409 } 410 411 if (memcmp(x,"0x",2) == 0) { 412 sscanf(x+2,"%x",&num); 413 } 414 else { 415 if (strchr(x,'.')) { 416 if (sscanf(x,"%d.%d",&a,&b) != 2) { 417 printf("%s: invalid number: %s\n",sf->name,x); 418 return -1; 419 } 420 } 421 else { 422 a = atoi(x); 423 b = 0; 424 } 425 426 switch (sf->decimal) { 427 case SPD_DEC_BCD: 428 if ((b < 0) || (b > 9)) { 429 printf("%s: Invalid BCD number: %s\n",sf->name,x); 430 return -1; 431 } 432 num = (a*16)+b; 433 break; 434 case SPD_DEC_QTR: 435 if ((b != 0) && (b != 25) && (b != 50) && (b != 75)) { 436 printf("%s: Invalid 2-bit fraction number: %s\n",sf->name,x); 437 printf("(number after decimal should be 0,25,50,75)\n"); 438 exit(1); 439 } 440 num = (a*4)+(b/25); 441 break; 442 case SPD_ENCODED: 443 ev = sf->values; 444 while (ev->name) { 445 if (strcmp(ev->name,x) == 0) break; 446 ev++; 447 } 448 if (!ev->name) { 449 printf("%s: Invalid value. Valid values are: ",x); 450 ev = sf->values; 451 while (ev->name) { printf("%s ",ev->name); ev++; } 452 printf("\n"); 453 return -1; 454 } 455 num = ev->val; 456 break; 457 case SPD_ENCODED2: 458 tok = strtok(x," ,"); 459 num = 0; 460 while (tok) { 461 ev = sf->values; 462 while (ev->name) { 463 if (strcmp(ev->name,tok) == 0) break; 464 ev++; 465 } 466 if (!ev->name) { 467 printf("%s: Invalid value. Valid values are: ",tok); 468 ev = sf->values; 469 while (ev->name) { printf("%s ",ev->name); ev++; } 470 printf("\n"); 471 return -1; 472 } 473 num |= ev->val; 474 tok = strtok(NULL," ,"); 475 } 476 break; 477 default: 478 num = a; 479 break; 480 } 481 } 482 483 *(sf->data) = num; 484 485 return 0; 486} 487 488static void interactive(int spdfilemode) 489{ 490 spdbyte_t *sf; 491 char field[100]; 492 char ask[100]; 493 char prompt[100]; 494 char *x; 495 496 sf = spdfields; 497 498 printf("%-65.65s: Value\n","Parameter"); 499 printf("%-65.65s: -----\n","-----------------------------------------------------------------"); 500 501 while (sf->name) { 502 /* 503 * Gross hack: If in SPD file mode, skip parameters that will be placed 504 * in the SPD. 505 */ 506 507 if (spdfilemode && (sf->data >= &spd[0]) && (sf->data < &spd[SPD_SIZE])) { 508 sf++; 509 continue; 510 } 511 512 for (;;) { 513 x = prompt; 514 x += sprintf(x,"%s (%s", sf->name,sf->description); 515 if (sf->units && sf->units[0]) { 516 if (sf->description && sf->description[0]) x += sprintf(x,", "); 517 x += sprintf(x,"%s",sf->units); 518 } 519 x += sprintf(x,"): [%s]", sf->deflt); 520 printf("%-65.65s: ",prompt); 521 522 fgets(ask,sizeof(ask),stdin); 523 if ((x = strchr(ask,'\n'))) *x = '\0'; 524 if (ask[0] == 0) strcpy(ask,sf->deflt); 525 sprintf(field,"%s=%s",sf->name,ask); 526 if (procfield(field) < 0) continue; 527 break; 528 } 529 sf++; 530 } 531 532 printf("\n\n"); 533} 534 535int swcnt = 0; 536char *swnames[32]; 537 538static int proc_args(int argc,char *argv[]) 539{ 540 int inidx,outidx; 541 542 outidx = 1; 543 544 for (inidx = 1; inidx < argc; inidx++) { 545 if (argv[inidx][0] != '-') { 546 argv[outidx++] = argv[inidx]; 547 } 548 else { 549 swnames[swcnt] = argv[inidx]; 550 swcnt++; 551 } 552 } 553 554 return outidx; 555} 556 557static int swisset(char *x) 558{ 559 int idx; 560 char tempname[500]; 561 char *zz; 562 563 564 for (idx = 0; idx < swcnt; idx++) { 565 strcpy(tempname,swnames[idx]); 566 if ((zz = strchr(tempname,'='))) *zz = '\0'; 567 if (strcmp(x,tempname) == 0) return 1; 568 } 569 return 0; 570} 571 572static int swvalue(char *x,char **val) 573{ 574 int idx; 575 char tempname[500]; 576 char *zz; 577 578 for (idx = 0; idx < swcnt; idx++) { 579 strcpy(tempname,swnames[idx]); 580 if ((zz = strchr(tempname,'='))) *zz = '\0'; 581 if (strcmp(x,tempname) == 0) { 582 zz = strchr(swnames[idx],'='); /* should never return NULL*/ 583 *val = (zz+1); 584 return 1; 585 } 586 } 587 return 0; 588} 589 590static void dumpmclkcfg(uint64_t val) 591{ 592 printf("clk_ratio = %d\n",(int)G_MC_CLK_RATIO(val)); 593 printf("ref_rate = %d\n",(int)G_MC_REF_RATE(val)); 594 595} 596 597static void dumptiming1(uint64_t val) 598{ 599 printf("w2rIdle = %d\n",(val & M_MC_w2rIDLE_TWOCYCLES) ? 1 : 0); 600 printf("r2rIdle = %d\n",(val & M_MC_r2rIDLE_TWOCYCLES) ? 1 : 0); 601 printf("r2wIdle = %d\n",(val & M_MC_r2wIDLE_TWOCYCLES) ? 1 : 0); 602 printf("tCrD = %d\n",(int)G_MC_tCrD(val)); 603 printf("tCrDh = %d\n",(val & M_MC_tCrDh) ? 1 : 0); 604 printf("tFIFO = %d\n",(int)G_MC_tFIFO(val)); 605 printf("tCwD = %d\n",(int)G_MC_tCwD(val)); 606 607 printf("tRP = %d\n",(int)G_MC_tRP(val)); 608 printf("tRRD = %d\n",(int)G_MC_tRRD(val)); 609 printf("tRCD = %d\n",(int)G_MC_tRCD(val)); 610 611 printf("tRFC = %d\n",(int)G_MC_tRFC(val)); 612 printf("tRFC_PLUS16 = %d\n", ((val & M_MC_tRFC_PLUS16) != 0 ? 1 : 0)); 613 printf("tRCw = %d\n",(int)G_MC_tRCw(val)); 614 printf("tRCr = %d\n",(int)G_MC_tRCr(val)); 615 printf("tCwCr = %d\n",(int)G_MC_tCwCr(val)); 616} 617 618int main(int argc,char *argv[]) 619{ 620 spdbyte_t *sf; 621 uint8_t t; 622 int idx; 623 int csidx; 624 int chidx; 625 int mclk; 626 draminittab_t *init; 627 int spdmode = 0; 628 char *spdname = NULL; 629 630 spd[JEDEC_SPD_MEMTYPE] = JEDEC_MEMTYPE_DDRSDRAM2; 631 spd[JEDEC_SPD_ROWS] = 13; 632 spd[JEDEC_SPD_COLS] = 9; 633 spd[JEDEC_SPD_BANKS] = 2; 634 spd[JEDEC_SPD_SIDES] = 1; 635 spd[JEDEC_SPD_WIDTH] = 72; 636 637 argc = proc_args(argc,argv); 638 639 if (swvalue("-spd",&spdname)) { 640 printf("[Reading SPD file: %s]\n",spdname); 641 readspdfile(spd,spdname); 642 } 643 644 if ((argc == 1) && !swisset("-i")) { 645 printf("usage: memconfig name=value name=value ...\n"); 646 printf("\n"); 647 printf("Available fields: "); 648 sf = spdfields; 649 while (sf->name) { 650 printf("%s ",sf->name); 651 sf++; 652 } 653 printf("\n"); 654 exit(1); 655 } 656 657 if (swisset("-i")) { 658 interactive((spdname != NULL)); 659 } 660 else { 661 for (idx = 1; idx < argc; idx++) { 662 if (procfield(argv[idx]) < 0) exit(1); 663 } 664 } 665 666 debug = swisset("-d"); 667 668 spdmode = swisset("-spd"); 669 670 asmout = swisset("-a"); 671 if (asmout) { 672 char fname[100]; 673 sprintf(fname,"%s.inc",argv[0]); 674 asmoutfile = fopen(fname,"w"); 675 if (asmoutfile) printf("[Writing memory init sequence to file '%s']\n",fname); 676 } 677 678 printf("-------Memory Parameters---------\n"); 679 680 sf = spdfields; 681 while (sf->name) { 682 char buffer[64]; 683 char *p = buffer; 684 685 t = *(sf->data); 686 printf("%-10.10s = 0x%02X ",sf->name,t); 687 switch (sf->decimal) { 688 case SPD_DEC_BCD: 689 p += sprintf(p,"(%d.%d)", 690 t >> 4, t & 0x0F); 691 break; 692 case SPD_DEC_QTR: 693 p += sprintf(p,"(%d.%02d)", 694 t/4,(t&3)*25); 695 break; 696 case SPD_ENCODED: 697 p += sprintf(p,"(%s)",lookupstr(sf->values,t)); 698 break; 699 default: 700 p += sprintf(p,"(%d)",t); 701 break; 702 } 703 704 p += sprintf(p," %s",sf->units); 705 printf("%-16.16s %s\n",buffer,sf->description); 706 sf++; 707 } 708 709 printf("\n"); 710 711 init = &inittab[0]; 712 memset(inittab,0,sizeof(inittab)); 713 714 init->gbl.gbl_type = MCR_GLOBALS; 715 init->gbl.gbl_intlv_ch = portintlv; 716 init++; 717 718 for (chidx = 0; chidx < 2; chidx++) { 719 if (channels & (1<<chidx)) { 720 721 init->cfg.cfg_type = MCR_CHCFG; 722 init->cfg.cfg_chan = chidx; 723 init->cfg.cfg_mintmemclk = mintmemclk; 724 init->cfg.cfg_dramtype = dramtype; 725 init->cfg.cfg_pagepolicy = CASCHECK; 726 init->cfg.cfg_blksize = BLKSIZE32; 727 init->cfg.cfg_intlv_cs = NOCSINTLV; 728 init->cfg.cfg_ecc = 0; 729 init->cfg.cfg_roundtrip = roundtrip; 730 init++; 731 732 init->clk.clk_type = MCR_CLKCFG; 733 init->clk.clk_addrskew = addrskew; 734 init->clk.clk_dqoskew = dqoskew; 735 init->clk.clk_dqiskew = dqiskew; 736 init->clk.clk_addrdrive = addrdrive; 737 init->clk.clk_datadrive = datadrive; 738 init->clk.clk_clkdrive = clkdrive; 739 init++; 740 741 for (csidx = 0; csidx < 4; csidx++) { 742 743 if (spdmode) { 744 /* Assume double sided dimm support and dimms on even chip selects */ 745 if ((csels & (1<<csidx)) && ((csidx & 1) == 0)) { 746 init->spd.spd_type = MCR_SPD; 747 init->spd.spd_csel = csidx; 748 init->spd.spd_flags = 0; 749 init->spd.spd_smbuschan = 0; 750 init->spd.spd_smbusdev = 0x50; 751 init++; 752 } 753 } 754 else { 755 if (csels & (1<<csidx)) { 756 init->geom.geom_type = MCR_GEOM; 757 init->geom.geom_csel = csidx; 758 init->geom.geom_rows = spd[JEDEC_SPD_ROWS]; 759 init->geom.geom_cols = spd[JEDEC_SPD_COLS]; 760 init->geom.geom_banks = spd[JEDEC_SPD_BANKS]; 761 init++; 762 763 init->tmg.tmg_type = MCR_TIMING; 764 init->tmg.tmg_tCK = spd[JEDEC_SPD_tCK25]; 765 init->tmg.tmg_rfsh = spd[JEDEC_SPD_RFSH]; 766 init->tmg.tmg_caslatency = spd[JEDEC_SPD_CASLATENCIES]; 767 init->tmg.tmg_attributes = spd[JEDEC_SPD_ATTRIBUTES]; 768 init->tmg.tmg_tRAS = spd[JEDEC_SPD_tRAS]; 769 init->tmg.tmg_tRP = spd[JEDEC_SPD_tRP]; 770 init->tmg.tmg_tRRD = spd[JEDEC_SPD_tRRD]; 771 init->tmg.tmg_tRCD = spd[JEDEC_SPD_tRCD]; 772 init->tmg.tmg_tRFC = spd[JEDEC_SPD_tRFC]; 773 init->tmg.tmg_tRC = spd[JEDEC_SPD_tRC]; 774 init++; 775 } 776 } 777 } 778 } 779 } 780 781 init->mcr.mcr_type = MCR_EOT; 782 783 784 sb1250_refclk = (int) refclk; 785 786 sb1250_dram_init(inittab,NULL); 787 788 789 printf("-----Memory Timing Register Values-----\n"); 790 printf("System Clock %dMHz\n",plldiv*refclk/2); 791 printf("CAS latency %d.%d\n",dram_cas_latency>>1,(dram_cas_latency&1)?5:0); 792 printf("tMemClk %d.%d ns\n",dram_tMemClk/10,dram_tMemClk%10); 793 if (channels & 1) mclk = (plldiv*refclk)*10/2/((int)G_MC_CLK_RATIO(mc0_mclkcfg)); 794 else if (channels & 2) mclk = (plldiv*refclk)*10/2/((int)G_MC_CLK_RATIO(mc1_mclkcfg)); 795 else mclk = 0; 796 printf("MCLK Freq %d.%dMHz\n",mclk/10,mclk%10); 797 printf("\n"); 798 if (channels & 1) { 799 printf("MC_TIMING1 = %016llX\n",mc0_timing1); 800 printf("MCLK_CONFIG = %016llX\n",mc0_mclkcfg); 801 } 802 else if (channels & 2) { 803 printf("MC_TIMING1 = %016llX\n",mc1_timing1); 804 printf("MCLK_CONFIG = %016llX\n",mc1_mclkcfg); 805 } 806 printf("\n"); 807 808 printf("-----Memory Timing Register Fields-----\n"); 809 if (channels & 1) dumptiming1(mc0_timing1); 810 else if (channels & 2) dumptiming1(mc1_timing1); 811 812 printf("-----Memory Clock Config Register Fields-----\n"); 813 if (channels & 1) dumpmclkcfg(mc0_mclkcfg); 814 else if (channels & 2) dumpmclkcfg(mc1_mclkcfg); 815 816 printf("---Done!---\n"); 817 818 printf("%s ",argv[0]); 819 if (spdmode) { 820 if (spdname) printf("-spd=%s ",spdname); 821 else printf("-spd "); 822 } 823 sf = spdfields; 824 while (sf->name) { 825 char buffer[64]; 826 char *p = buffer; 827 828 if (spdname && (sf->data >= &spd[0]) && (sf->data < &spd[SPD_SIZE])) { 829 sf++; 830 continue; 831 } 832 833 t = *(sf->data); 834 835 p += sprintf(p,"%s=",sf->name); 836 switch (sf->decimal) { 837 case SPD_DEC_BCD: 838 p += sprintf(p,"%d.%d", 839 t >> 4, t & 0x0F); 840 break; 841 case SPD_DEC_QTR: 842 p += sprintf(p,"%d.%02d", 843 t/4,(t&3)*25); 844 break; 845 case SPD_ENCODED: 846 default: 847 p += sprintf(p,"0x%02X",t); 848 break; 849 } 850 851 printf("%s ",buffer); 852 sf++; 853 } 854 855 printf("\n"); 856 857 if (asmoutfile) { 858 fprintf(asmoutfile,"\t.dword 0,0 /* End of Table */\n"); 859 fclose(asmoutfile); 860 } 861 862 return 0; 863} 864