|
|
1.1 ! root 1: /****************************************************************************** ! 2: * Copyright (c) 2004, 2008 IBM Corporation ! 3: * All rights reserved. ! 4: * This program and the accompanying materials ! 5: * are made available under the terms of the BSD License ! 6: * which accompanies this distribution, and is available at ! 7: * http://www.opensource.org/licenses/bsd-license.php ! 8: * ! 9: * Contributors: ! 10: * IBM Corporation - initial implementation ! 11: *****************************************************************************/ ! 12: #include <stdint.h> ! 13: #include <hw.h> ! 14: #include <stdio.h> ! 15: #include "stage2.h" ! 16: #include <cpu.h> ! 17: #include <string.h> ! 18: ! 19: /* ! 20: * compiler switches ! 21: ******************************************************************************* ! 22: */ ! 23: #define U4_DEBUG ! 24: #define U4_INFO ! 25: //#define U4_SHOW_REGS ! 26: ! 27: int io_getchar(char *); ! 28: ! 29: /* ! 30: * version info ! 31: */ ! 32: static const uint32_t VER = 2; ! 33: static const uint32_t SUBVER = 1; ! 34: ! 35: /* ! 36: * local macros ! 37: ******************************************************************************* ! 38: */ ! 39: // bit shifting in Motorola/IBM bit enumeration format (yaks...) ! 40: #define IBIT( nr ) ( (uint32_t) 0x80000000 >> (nr) ) ! 41: #define BIT( nr ) ( (uint32_t) 0x1 << (nr) ) ! 42: ! 43: /* ! 44: * macros to detect the current board layout ! 45: */ ! 46: #define IS_MAUI ( ( load8_ci( 0xf4000682 ) >> 4 ) == 0 ) ! 47: #define IS_BIMINI ( ( load8_ci( 0xf4000682 ) >> 4 ) == 1 ) ! 48: #define IS_KAUAI ( ( load8_ci( 0xf4000682 ) >> 4 ) == 2 ) ! 49: ! 50: /* ! 51: * local constants ! 52: ******************************************************************************* ! 53: */ ! 54: ! 55: /* ! 56: * u4 base address ! 57: */ ! 58: #define U4_BASE_ADDR ((uint64_t) 0xf8000000 ) ! 59: #define u4reg( reg ) (U4_BASE_ADDR + (uint64_t) (reg)) ! 60: ! 61: /* ! 62: * I2C registers ! 63: */ ! 64: #define I2C_MODE_R u4reg(0x1000) ! 65: #define I2C_CTRL_R u4reg(0x1010) ! 66: #define I2C_STAT_R u4reg(0x1020) ! 67: #define I2C_ISR_R u4reg(0x1030) ! 68: #define I2C_ADDR_R u4reg(0x1050) ! 69: #define I2C_SUBA_R u4reg(0x1060) ! 70: #define I2C_DATA_R u4reg(0x1070) ! 71: ! 72: /* ! 73: * clock control registers & needed bits/masks ! 74: */ ! 75: #define ClkCntl_R u4reg(0x0800) ! 76: #define PLL2Cntl_R u4reg(0x0860) ! 77: ! 78: /* ! 79: * clock control bits & masks ! 80: */ ! 81: #define CLK_DDR_CLK_MSK (IBIT(11) | IBIT(12) | IBIT(13)) ! 82: ! 83: /* ! 84: * memory controler registers ! 85: */ ! 86: #define RASTimer0_R u4reg(0x2030) ! 87: #define RASTimer1_R u4reg(0x2040) ! 88: #define CASTimer0_R u4reg(0x2050) ! 89: #define CASTimer1_R u4reg(0x2060) ! 90: #define MemRfshCntl_R u4reg(0x2070) ! 91: #define MemProgCntl_R u4reg(0x20b0) ! 92: #define Dm0Cnfg_R u4reg(0x2200) ! 93: #define Dm1Cnfg_R u4reg(0x2210) ! 94: #define Dm2Cnfg_R u4reg(0x2220) ! 95: #define Dm3Cnfg_R u4reg(0x2230) ! 96: #define MemWrQCnfg_R u4reg(0x2270) ! 97: #define MemArbWt_R u4reg(0x2280) ! 98: #define UsrCnfg_R u4reg(0x2290) ! 99: #define MemRdQCnfg_R u4reg(0x22a0) ! 100: #define MemQArb_R u4reg(0x22b0) ! 101: #define MemRWArb_R u4reg(0x22c0) ! 102: #define MemBusCnfg_R u4reg(0x22d0) ! 103: #define MemBusCnfg2_R u4reg(0x22e0) ! 104: #define ODTCntl_R u4reg(0x23a0) ! 105: #define MemModeCntl_R u4reg(0x2500) ! 106: #define MemPhyModeCntl_R u4reg(0x2880) ! 107: #define CKDelayL_R u4reg(0x2890) ! 108: #define CKDelayU_R u4reg(0x28a0) ! 109: #define IOPadCntl_R u4reg(0x29a0) ! 110: #define ByteWrClkDelC0B00_R u4reg(0x2800) ! 111: #define ByteWrClkDelC0B01_R u4reg(0x2810) ! 112: #define ByteWrClkDelC0B02_R u4reg(0x2820) ! 113: #define ByteWrClkDelC0B03_R u4reg(0x2830) ! 114: #define ByteWrClkDelC0B04_R u4reg(0x2900) ! 115: #define ByteWrClkDelC0B05_R u4reg(0x2910) ! 116: #define ByteWrClkDelC0B06_R u4reg(0x2920) ! 117: #define ByteWrClkDelC0B07_R u4reg(0x2930) ! 118: #define ByteWrClkDelC0B16_R u4reg(0x2980) ! 119: #define ByteWrClkDelC0B08_R u4reg(0x2a00) ! 120: #define ByteWrClkDelC0B09_R u4reg(0x2a10) ! 121: #define ByteWrClkDelC0B10_R u4reg(0x2a20) ! 122: #define ByteWrClkDelC0B11_R u4reg(0x2a30) ! 123: #define ByteWrClkDelC0B12_R u4reg(0x2b00) ! 124: #define ByteWrClkDelC0B13_R u4reg(0x2b10) ! 125: #define ByteWrClkDelC0B14_R u4reg(0x2b20) ! 126: #define ByteWrClkDelC0B15_R u4reg(0x2b30) ! 127: #define ByteWrClkDelC0B17_R u4reg(0x2b80) ! 128: #define ReadStrobeDelC0B00_R u4reg(0x2840) ! 129: #define ReadStrobeDelC0B01_R u4reg(0x2850) ! 130: #define ReadStrobeDelC0B02_R u4reg(0x2860) ! 131: #define ReadStrobeDelC0B03_R u4reg(0x2870) ! 132: #define ReadStrobeDelC0B04_R u4reg(0x2940) ! 133: #define ReadStrobeDelC0B05_R u4reg(0x2950) ! 134: #define ReadStrobeDelC0B06_R u4reg(0x2960) ! 135: #define ReadStrobeDelC0B07_R u4reg(0x2970) ! 136: #define ReadStrobeDelC0B16_R u4reg(0x2990) ! 137: #define ReadStrobeDelC0B08_R u4reg(0x2a40) ! 138: #define ReadStrobeDelC0B09_R u4reg(0x2a50) ! 139: #define ReadStrobeDelC0B10_R u4reg(0x2a60) ! 140: #define ReadStrobeDelC0B11_R u4reg(0x2a70) ! 141: #define ReadStrobeDelC0B12_R u4reg(0x2b40) ! 142: #define ReadStrobeDelC0B13_R u4reg(0x2b50) ! 143: #define ReadStrobeDelC0B14_R u4reg(0x2b60) ! 144: #define ReadStrobeDelC0B15_R u4reg(0x2b70) ! 145: #define ReadStrobeDelC0B17_R u4reg(0x2b90) ! 146: #define MemInit00_R u4reg(0x2100) ! 147: #define MemInit01_R u4reg(0x2110) ! 148: #define MemInit02_R u4reg(0x2120) ! 149: #define MemInit03_R u4reg(0x2130) ! 150: #define MemInit04_R u4reg(0x2140) ! 151: #define MemInit05_R u4reg(0x2150) ! 152: #define MemInit06_R u4reg(0x2160) ! 153: #define MemInit07_R u4reg(0x2170) ! 154: #define MemInit08_R u4reg(0x2180) ! 155: #define MemInit09_R u4reg(0x2190) ! 156: #define MemInit10_R u4reg(0x21a0) ! 157: #define MemInit11_R u4reg(0x21b0) ! 158: #define MemInit12_R u4reg(0x21c0) ! 159: #define MemInit13_R u4reg(0x21d0) ! 160: #define MemInit14_R u4reg(0x21e0) ! 161: #define MemInit15_R u4reg(0x21f0) ! 162: #define CalConf0_R u4reg(0x29b0) ! 163: #define CalConf1_R u4reg(0x29c0) ! 164: #define MeasStatusC0_R u4reg(0x28f0) ! 165: #define MeasStatusC1_R u4reg(0x29f0) ! 166: #define MeasStatusC2_R u4reg(0x2af0) ! 167: #define MeasStatusC3_R u4reg(0x2bf0) ! 168: #define CalC0_R u4reg(0x28e0) ! 169: #define CalC1_R u4reg(0x29e0) ! 170: #define CalC2_R u4reg(0x2ae0) ! 171: #define CalC3_R u4reg(0x2be0) ! 172: #define RstLdEnVerniersC0_R u4reg(0x28d0) ! 173: #define RstLdEnVerniersC1_R u4reg(0x29d0) ! 174: #define RstLdEnVerniersC2_R u4reg(0x2ad0) ! 175: #define RstLdEnVerniersC3_R u4reg(0x2bd0) ! 176: #define ExtMuxVernier0_R u4reg(0x28b0) ! 177: #define ExtMuxVernier1_R u4reg(0x28c0) ! 178: #define OCDCalCmd_R u4reg(0x2300) ! 179: #define OCDCalCntl_R u4reg(0x2310) ! 180: #define MCCR_R u4reg(0x2440) ! 181: #define MSRSR_R u4reg(0x2410) ! 182: #define MSRER_R u4reg(0x2420) ! 183: #define MSPR_R u4reg(0x2430) ! 184: #define MSCR_R u4reg(0x2400) ! 185: #define MEAR0_R u4reg(0x2460) ! 186: #define MEAR1_R u4reg(0x2470) ! 187: #define MESR_R u4reg(0x2480) ! 188: #define MRSRegCntl_R u4reg(0x20c0) ! 189: #define EMRSRegCntl_R u4reg(0x20d0) ! 190: #define APIMemRdCfg_R u4reg(0x30090) ! 191: #define APIExcp_R u4reg(0x300a0) ! 192: ! 193: /* ! 194: * common return values ! 195: */ ! 196: #define RET_OK 0 ! 197: #define RET_ERR -1 ! 198: #define RET_ACERR_CE -1 ! 199: #define RET_ACERR_UEWT -2 ! 200: #define RET_ACERR_UE -3 ! 201: ! 202: /* ! 203: * 'DIMM slot populated' indicator ! 204: */ ! 205: #define SL_POP 1 ! 206: ! 207: /* ! 208: * spd buffer size ! 209: */ ! 210: #define SPD_BUF_SIZE 0x40 ! 211: ! 212: /* ! 213: * maximum number of DIMM banks & DIMM groups ! 214: */ ! 215: #define NUM_SLOTS 8 ! 216: #define NUM_BANKS ( NUM_SLOTS / 2 ) ! 217: #define MAX_DGROUPS ( NUM_SLOTS / 2 ) ! 218: #define SLOT_ADJ() ( ( IS_MAUI ) ? NUM_SLOTS / 4 : NUM_SLOTS / 2 ) ! 219: ! 220: /* ! 221: * values needed for auto calibration ! 222: */ ! 223: #define MAX_DRANKS NUM_SLOTS ! 224: #define MAX_BLANE 18 ! 225: #define MAX_RMD 0xf ! 226: ! 227: /* ! 228: * maximum number of supported CAS latencies ! 229: */ ! 230: #define NUM_CL 3 ! 231: ! 232: /* ! 233: * min/max supported CL values by U4 ! 234: */ ! 235: #define U4_MIN_CL 3 ! 236: #define U4_MAX_CL 5 ! 237: ! 238: /* ! 239: * DIMM constants ! 240: */ ! 241: #define DIMM_TYPE_MSK BIT(0) ! 242: #define DIMM_ORG_x4 BIT(0) ! 243: #define DIMM_ORG_x8 BIT(1) ! 244: #define DIMM_ORG_x16 BIT(2) ! 245: #define DIMM_ORG_MIXx8x16 BIT(30) ! 246: #define DIMM_ORG_UNKNOWN 0 ! 247: #define DIMM_WIDTH 72 ! 248: #define DIMM_BURSTLEN_4 BIT(2) ! 249: ! 250: /* ! 251: * L2 cache size ! 252: */ ! 253: #define L2_CACHE_SIZE (uint32_t) 0x100000 ! 254: ! 255: /* ! 256: * scrub types ! 257: */ ! 258: #define IMMEDIATE_SCRUB IBIT(0) ! 259: #define IMMEDIATE_SCRUB_WITH_FILL ( IBIT(0) | IBIT(1) ) ! 260: #define BACKGROUND_SCRUB ( IBIT(1) | ( 0x29 << 16 ) ) ! 261: ! 262: /* ! 263: * I2C starting slave addresses of the DIMM banks ! 264: */ ! 265: #define I2C_START 0x50 ! 266: ! 267: /* ! 268: * Index to the speed dependend DIMM settings ! 269: */ ! 270: enum ! 271: { ! 272: SPEED_IDX_400 = 0, ! 273: SPEED_IDX_533, ! 274: SPEED_IDX_667, ! 275: NUM_SPEED_IDX ! 276: }; ! 277: ! 278: /* ! 279: * number of read/write strobes of the U4 ! 280: */ ! 281: #define NUM_STROBES 18 ! 282: ! 283: /* ! 284: * 2GB hole definition ! 285: */ ! 286: static const uint64_t _2GB = (uint64_t) 0x80000000; ! 287: ! 288: /* ! 289: * local types ! 290: ******************************************************************************* ! 291: */ ! 292: /* ! 293: * DIMM definition ! 294: */ ! 295: typedef struct ! 296: { ! 297: uint32_t m_pop_u32; // set if bank is populated ! 298: uint32_t m_bank_u32; // bank number ! 299: uint32_t m_clmsk_u32; // mask of supported CAS latencies ! 300: uint32_t m_clcnt_u32; // number of supporetd CAS latencies ! 301: uint32_t m_clval_pu32[NUM_CL]; // values of supporeted CAS latencies ! 302: uint32_t m_speed_pu32[NUM_CL]; // speed (Mhz) at CAS latency of same index ! 303: uint32_t m_size_u32; // chip size in Mb ! 304: uint32_t m_rank_u32; // # of ranks, total size = chip size*rank ! 305: uint32_t m_orgmsk_u32; // data organisation (x4, x8, x16) (mask) ! 306: uint32_t m_orgval_u32; // data organisation (value) ! 307: uint32_t m_width_u32; // data width ! 308: uint32_t m_ecc_u32; // set if ecc ! 309: uint32_t m_type_u32; // rdimm or udimm ! 310: uint32_t m_burst_u32; // supported burst lengths ! 311: uint32_t m_bankcnt_u32; // number of banks ! 312: ! 313: /* ! 314: * the following timing values are all in 1/100ns ! 315: */ ! 316: uint32_t m_tCK_pu32[NUM_CL]; ! 317: uint32_t m_tRAS_u32; ! 318: uint32_t m_tRTP_u32; ! 319: uint32_t m_tRP_u32; ! 320: uint32_t m_tWR_u32; ! 321: uint32_t m_tRRD_u32; ! 322: uint32_t m_tRC_u32; ! 323: uint32_t m_tRCD_u32; ! 324: uint32_t m_tWTR_u32; ! 325: uint32_t m_tREF_u32; ! 326: uint32_t m_tRFC_u32; ! 327: } dimm_t; ! 328: ! 329: /* ! 330: * DIMM group definition ! 331: */ ! 332: typedef struct ! 333: { ! 334: uint32_t m_size_u32; // group size in MB ! 335: uint32_t m_start_u32; // in 128Mb granularity ! 336: uint32_t m_end_u32; // in 128Mb granularity ! 337: uint32_t m_ss_u32; // single sided/double sided ! 338: uint32_t m_csmode_u32; // selected CS mode for this group ! 339: uint32_t m_add2g_u32; ! 340: uint32_t m_sub2g_u32; ! 341: uint32_t m_memmd_u32; // selected mem mode for this group ! 342: uint32_t m_dcnt_u32; // number of DIMMs in group ! 343: dimm_t *m_dptr[NUM_SLOTS]; ! 344: } dgroup_t; ! 345: ! 346: /* ! 347: * auto calibration result structure ! 348: */ ! 349: typedef struct ! 350: { ! 351: uint32_t m_MemBusCnfg_u32; ! 352: uint32_t m_MemBusCnfg2_u32; ! 353: uint32_t m_RstLdEnVerniers_pu32[4]; ! 354: } auto_calib_t; ! 355: ! 356: /* ! 357: * ECC error structure ! 358: */ ! 359: typedef struct ! 360: { ! 361: int32_t m_err_i32; ! 362: uint32_t m_uecnt_u32; // number of uncorrectable errors ! 363: uint32_t m_cecnt_u32; // number of correctable errors ! 364: uint32_t m_rank_u32; // erroneous rank ! 365: uint32_t m_col_u32; // erroneous column ! 366: uint32_t m_row_u32; // erroneous row ! 367: uint32_t m_bank_u32; // erroneous bank ! 368: } eccerror_t; ! 369: ! 370: /* ! 371: * U4 register setup structure ! 372: */ ! 373: typedef struct ! 374: { ! 375: /* ! 376: * external MUX delays ! 377: */ ! 378: uint32_t RRMux; ! 379: uint32_t WRMux; ! 380: uint32_t WWMux; ! 381: uint32_t RWMux; ! 382: ! 383: /* ! 384: * default Wr/Rd Queue & Arbiter register settings ! 385: */ ! 386: uint32_t MemRdQCnfg; ! 387: uint32_t MemWrQCnfg; ! 388: uint32_t MemQArb; ! 389: uint32_t MemRWArb; ! 390: ! 391: /* ! 392: * misc fixed register values ! 393: */ ! 394: uint32_t ODTCntl; ! 395: uint32_t IOPadCntl; ! 396: uint32_t MemPhyModeCntl; ! 397: uint32_t OCDCalCntl; ! 398: uint32_t OCDCalCmd; ! 399: uint32_t CKDelayL; ! 400: uint32_t CKDelayU; ! 401: uint32_t MemBusCnfg; ! 402: uint32_t CAS1Dly0; ! 403: uint32_t CAS1Dly1; ! 404: uint32_t ByteWrClkDel[NUM_STROBES]; ! 405: uint32_t ReadStrobeDel[NUM_STROBES]; ! 406: } reg_statics_t; ! 407: ! 408: /* ! 409: * local variables ! 410: ******************************************************************************* ! 411: */ ! 412: static dimm_t m_dimm[NUM_SLOTS]; ! 413: static dimm_t m_gendimm; ! 414: static uint32_t m_dcnt_u32; ! 415: static dimm_t *m_dptr[NUM_SLOTS]; ! 416: static uint32_t m_bankoff_u32; ! 417: static uint32_t m_bankpop_u32[NUM_BANKS]; ! 418: static uint32_t m_dclidx_u32; ! 419: static uint32_t m_dgrcnt_u32; ! 420: static dgroup_t m_dgroup[MAX_DGROUPS]; ! 421: static dgroup_t *m_dgrptr[MAX_DGROUPS]; ! 422: static uint64_t m_memsize_u64; // memsize in bytes ! 423: ! 424: /* ! 425: * local functions ! 426: ******************************************************************************* ! 427: */ ! 428: static void ! 429: progbar( void ) ! 430: { ! 431: static uint8_t bar[] = ! 432: { '|', '/', '-', '\\', 0 }; ! 433: static uint32_t idx = 0; ! 434: ! 435: printf( "\b%c", bar[idx] ); ! 436: ! 437: if( bar[++idx] == 0 ) { ! 438: idx = 0; ! 439: } ! 440: ! 441: } ! 442: ! 443: static void ! 444: or32_ci( uint64_t r, uint32_t m ) ! 445: { ! 446: uint32_t v; ! 447: ! 448: v = load32_ci( r ); ! 449: v |= m; ! 450: store32_ci( r, v ); ! 451: } ! 452: ! 453: static void ! 454: and32_ci( uint64_t r, uint32_t m ) ! 455: { ! 456: uint32_t v; ! 457: ! 458: v = load32_ci( r ); ! 459: v &= m; ! 460: store32_ci( r, v ); ! 461: } ! 462: ! 463: static void ! 464: dly( uint64_t volatile f_wait_u64 ) \ ! 465: { ! 466: while( f_wait_u64 ) { ! 467: f_wait_u64--; ! 468: } ! 469: } ! 470: ! 471: /* ! 472: * local i2c access functions ! 473: */ ! 474: static void ! 475: i2c_term( void ) ! 476: { ! 477: uint32_t l_stat_u32; ! 478: ! 479: /* ! 480: * clear out all pending int's and wait ! 481: * for the stop condition to occur ! 482: */ ! 483: do { ! 484: l_stat_u32 = load32_ci( I2C_ISR_R ); ! 485: store32_ci( I2C_ISR_R, l_stat_u32 ); ! 486: } while( ( l_stat_u32 & IBIT(29) ) == 0 ); ! 487: ! 488: } ! 489: ! 490: static int32_t ! 491: i2c_read( uint32_t f_addr_u32, uint32_t f_suba_u32, uint8_t *f_buf_pu08, uint32_t f_len_u32 ) ! 492: { ! 493: uint32_t l_val_u32; ! 494: int32_t l_ret_i32 = 1; ! 495: ! 496: /* ! 497: * parameter check ! 498: */ ! 499: if( ( f_addr_u32 > (uint32_t) 0x7f ) || ! 500: ( f_suba_u32 > (uint32_t) 0xff ) || ! 501: ( f_len_u32 == (uint32_t) 0x00 ) ) { ! 502: return RET_ERR; ! 503: } ! 504: ! 505: /* ! 506: * set I2C Interface to combined mode ! 507: */ ! 508: store32_ci( I2C_MODE_R, IBIT(28) | IBIT(29) ); ! 509: ! 510: /* ! 511: * set address, subaddress & read mode ! 512: */ ! 513: store32_ci( I2C_ADDR_R, ( f_addr_u32 << 1 ) | (uint32_t) 0x1 ); ! 514: store32_ci( I2C_SUBA_R, f_suba_u32 ); ! 515: ! 516: /* ! 517: * start address transmission phase ! 518: */ ! 519: store32_ci( I2C_CTRL_R, IBIT(30) ); ! 520: ! 521: /* ! 522: * wait for address transmission to finish ! 523: */ ! 524: do { ! 525: l_val_u32 = load32_ci( I2C_ISR_R ); ! 526: } while( ( l_val_u32 & IBIT(30) ) == 0 ); ! 527: ! 528: /* ! 529: * check for success ! 530: */ ! 531: if( ( load32_ci( I2C_STAT_R ) & IBIT(30) ) == 0 ) { ! 532: i2c_term(); ! 533: return RET_ERR; ! 534: } else { ! 535: // send ack ! 536: store32_ci( I2C_CTRL_R, IBIT(31) ); ! 537: // clear int ! 538: store32_ci( I2C_ISR_R, IBIT(30) ); ! 539: } ! 540: ! 541: /* ! 542: * read data ! 543: */ ! 544: while( l_ret_i32 > 0 ) { ! 545: l_val_u32 = load32_ci( I2C_ISR_R ); ! 546: ! 547: if( ( l_val_u32 & IBIT(31) ) != 0 ) { ! 548: // data was received ! 549: *f_buf_pu08 = ( uint8_t ) load32_ci( I2C_DATA_R ); ! 550: ! 551: f_buf_pu08++; ! 552: f_len_u32--; ! 553: ! 554: /* ! 555: * continue when there is more data to read or ! 556: * exit if not ! 557: */ ! 558: if( f_len_u32 != 0 ) { ! 559: // send ack ! 560: store32_ci( I2C_CTRL_R, IBIT(31) ); ! 561: // clear int ! 562: store32_ci( I2C_ISR_R, IBIT(31) ); ! 563: } else { ! 564: // send nack ! 565: store32_ci( I2C_CTRL_R, 0 ); ! 566: // set exit flag ! 567: l_ret_i32 = RET_OK; ! 568: } ! 569: ! 570: } else if( ( l_val_u32 & IBIT(29) ) != 0 ) { ! 571: // early stop condition ! 572: // set exit flag ! 573: l_ret_i32 = RET_ERR; ! 574: } ! 575: ! 576: }; ! 577: ! 578: i2c_term(); ! 579: ! 580: return( l_ret_i32 ); ! 581: } ! 582: ! 583: static uint32_t ! 584: i2c_get_slot( uint32_t i2c_addr ) ! 585: { ! 586: uint32_t slot; ! 587: ! 588: slot = ( i2c_addr - I2C_START ) / 2; ! 589: ! 590: if( ( i2c_addr & 0x1 ) != 0 ) { ! 591: slot += SLOT_ADJ(); ! 592: } ! 593: ! 594: return slot; ! 595: } ! 596: ! 597: /* ! 598: * 'serial presence detect' interpretation functions ! 599: */ ! 600: static uint32_t ! 601: ddr2_get_dimm_rank( uint8_t *f_spd_pu08 ) ! 602: { ! 603: static const int RANK_IDX = (int) 5; ! 604: ! 605: return (uint32_t) ( f_spd_pu08[RANK_IDX] & 0x3 ) + 1; ! 606: } ! 607: ! 608: static uint32_t ! 609: ddr2_get_dimm_size( uint8_t *f_spd_pu08 ) ! 610: { ! 611: static const int SIZE_IDX = (int) 31; ! 612: uint8_t l_smsk_u08; ! 613: uint32_t i; ! 614: ! 615: l_smsk_u08 = ( f_spd_pu08[SIZE_IDX] << 3 ) | ! 616: ( f_spd_pu08[SIZE_IDX] >> 5 ); ! 617: ! 618: for( i = 0; ( ( l_smsk_u08 & ( (uint8_t) 0x1 << i ) ) == 0 ) ; i++ ); ! 619: ! 620: return (uint32_t) 0x80 << i; ! 621: } ! 622: ! 623: static uint32_t ! 624: ddr2_get_dimm_type( uint8_t *f_spd_pu08 ) ! 625: { ! 626: static const int TYPE_IDX = (int) 20; ! 627: ! 628: return (uint32_t) f_spd_pu08[TYPE_IDX] & DIMM_TYPE_MSK; ! 629: } ! 630: ! 631: static uint32_t ! 632: ddr2_get_dimm_org( uint8_t *f_spd_pu08, uint32_t /*out*/ *f_omsk_pu32 ) ! 633: { ! 634: static const int ORG_IDX = (int) 13; ! 635: uint32_t l_ret_u32 = (uint32_t) f_spd_pu08[ORG_IDX]; ! 636: ! 637: if( l_ret_u32 == 4 ) { ! 638: *f_omsk_pu32 = DIMM_ORG_x4; ! 639: } else if( l_ret_u32 == 8 ) { ! 640: *f_omsk_pu32 = DIMM_ORG_x8; ! 641: *f_omsk_pu32 |= DIMM_ORG_MIXx8x16; ! 642: } else if( l_ret_u32 == 16 ) { ! 643: *f_omsk_pu32 = DIMM_ORG_x16; ! 644: *f_omsk_pu32 |= DIMM_ORG_MIXx8x16; ! 645: } else { ! 646: *f_omsk_pu32 = DIMM_ORG_UNKNOWN; ! 647: l_ret_u32 = (uint32_t) ~0; ! 648: } ! 649: ! 650: return l_ret_u32; ! 651: } ! 652: ! 653: static uint32_t ! 654: ddr2_get_dimm_width( uint8_t *f_spd_pu08 ) ! 655: { ! 656: static const int WIDTH_IDX = (int) 6; ! 657: ! 658: return (uint32_t) f_spd_pu08[WIDTH_IDX]; ! 659: } ! 660: ! 661: static uint32_t ! 662: ddr2_get_dimm_ecc( uint8_t *f_spd_pu08 ) ! 663: { ! 664: static const int ECC_IDX = (int) 11; ! 665: ! 666: return ( f_spd_pu08[ECC_IDX] & BIT(1) ) != 0; ! 667: } ! 668: ! 669: static uint32_t ! 670: ddr2_get_dimm_burstlen( uint8_t *f_spd_pu08 ) ! 671: { ! 672: static const int BURST_IDX = (int) 16; ! 673: ! 674: return (uint32_t) f_spd_pu08[BURST_IDX]; ! 675: } ! 676: ! 677: static void ! 678: ddr2_get_dimm_speed( dimm_t *f_dimm, uint8_t *f_spd_pu08 ) ! 679: { ! 680: static const int SPEED_IDX[] = { 25, 23, 9 }; ! 681: static const uint32_t NS[] = { 25, 33, 66, 75 }; ! 682: uint8_t l_tmp_u08; ! 683: uint32_t l_dspeed_u32; ! 684: uint32_t idx = 0; ! 685: uint32_t i; ! 686: ! 687: for( i = NUM_CL - f_dimm->m_clcnt_u32; i < NUM_CL; i++ ) { ! 688: l_tmp_u08 = f_spd_pu08[SPEED_IDX[i]]; ! 689: l_dspeed_u32 = (uint32_t) ( l_tmp_u08 >> 4 ) * 100; ! 690: l_tmp_u08 &= (uint8_t) 0xf; ! 691: ! 692: if( l_tmp_u08 >= (uint8_t) 10 ) { ! 693: l_dspeed_u32 += NS[l_tmp_u08 - 10]; ! 694: } else { ! 695: l_dspeed_u32 += (uint32_t) l_tmp_u08 * 10; ! 696: } ! 697: ! 698: f_dimm->m_tCK_pu32[idx] = l_dspeed_u32; ! 699: f_dimm->m_speed_pu32[idx] = (uint32_t) 2000000 / l_dspeed_u32; ! 700: f_dimm->m_speed_pu32[idx] += (uint32_t) 5; ! 701: f_dimm->m_speed_pu32[idx] /= (uint32_t) 10; ! 702: idx++; ! 703: } ! 704: ! 705: } ! 706: ! 707: static void ! 708: ddr2_get_dimm_timings( dimm_t *f_dimm, uint8_t *f_spd_pu08 ) ! 709: { ! 710: static const uint32_t NS[] = { 00, 25, 33, 50, 66, 75, 00, 00 }; ! 711: static const uint32_t USMUL = (uint32_t) 390625; ! 712: static const int tREF_IDX = (int) 12; ! 713: static const int tRP_IDX = (int) 27; ! 714: static const int tRRD_IDX = (int) 28; ! 715: static const int tRCD_IDX = (int) 29; ! 716: static const int tRAS_IDX = (int) 30; ! 717: static const int tWR_IDX = (int) 36; ! 718: static const int tWTR_IDX = (int) 37; ! 719: static const int tRTP_IDX = (int) 38; ! 720: static const int tRC_IDX = (int) 41; // & 40 ! 721: static const int tRFC_IDX = (int) 42; // & 40 ! 722: ! 723: uint32_t l_tmp_u32; ! 724: ! 725: f_dimm->m_tRP_u32 = (uint32_t) f_spd_pu08[tRP_IDX] * 25; ! 726: f_dimm->m_tRRD_u32 = (uint32_t) f_spd_pu08[tRRD_IDX] * 25; ! 727: f_dimm->m_tRCD_u32 = (uint32_t) f_spd_pu08[tRCD_IDX] * 25; ! 728: f_dimm->m_tWR_u32 = (uint32_t) f_spd_pu08[tWR_IDX] * 25; ! 729: f_dimm->m_tWTR_u32 = (uint32_t) f_spd_pu08[tWTR_IDX] * 25; ! 730: f_dimm->m_tRTP_u32 = (uint32_t) f_spd_pu08[tRTP_IDX] * 25; ! 731: f_dimm->m_tRAS_u32 = (uint32_t) f_spd_pu08[tRAS_IDX] * 100; ! 732: ! 733: l_tmp_u32 = (uint32_t) ( f_spd_pu08[tRC_IDX - 1] >> 4 ); ! 734: l_tmp_u32 &= (uint32_t) 0x7; ! 735: f_dimm->m_tRC_u32 = (uint32_t) f_spd_pu08[tRC_IDX] * 100 + ! 736: NS[l_tmp_u32]; ! 737: ! 738: l_tmp_u32 = (uint32_t) f_spd_pu08[tRFC_IDX - 2]; ! 739: l_tmp_u32 &= (uint32_t) 0xf; ! 740: f_dimm->m_tRFC_u32 = (uint32_t) 256 * ( l_tmp_u32 & (uint32_t) 0x1 ); ! 741: f_dimm->m_tRFC_u32 += (uint32_t) f_spd_pu08[tRFC_IDX]; ! 742: f_dimm->m_tRFC_u32 *= 100; ! 743: l_tmp_u32 >>= 1; ! 744: f_dimm->m_tRFC_u32 += NS[l_tmp_u32]; ! 745: ! 746: l_tmp_u32 = (uint32_t) f_spd_pu08[tREF_IDX]; ! 747: l_tmp_u32 &= (uint32_t) 0x7f; ! 748: ! 749: if( l_tmp_u32 == 0 ) { ! 750: l_tmp_u32 = (uint32_t) 2; ! 751: } else if( l_tmp_u32 <= (uint32_t) 2 ) { ! 752: l_tmp_u32--; ! 753: } ! 754: ! 755: f_dimm->m_tREF_u32 = ( l_tmp_u32 + 1 ) * USMUL; ! 756: } ! 757: ! 758: static uint32_t ! 759: ddr2_get_banks( uint8_t *f_spd_pu08 ) ! 760: { ! 761: static const int BANK_IDX = (int) 17; ! 762: ! 763: return (uint32_t) f_spd_pu08[BANK_IDX]; ! 764: } ! 765: ! 766: static uint32_t ! 767: ddr2_get_cl_mask( uint8_t *f_spd_pu08 ) ! 768: { ! 769: static const int CL_IDX = (int) 18; ! 770: ! 771: return (uint32_t) f_spd_pu08[CL_IDX]; ! 772: } ! 773: ! 774: static void ! 775: ddr2_get_cl( dimm_t *f_dimm ) ! 776: { ! 777: uint32_t l_clcnt_u32 = 0; ! 778: uint32_t i; ! 779: ! 780: for( i = 0; ( i < 8 ) && ( l_clcnt_u32 < NUM_CL ) ; i++ ) { ! 781: ! 782: if( ( f_dimm->m_clmsk_u32 & ( (uint32_t) 0x1 << i ) ) != 0 ) { ! 783: f_dimm->m_clval_pu32[l_clcnt_u32] = i; ! 784: l_clcnt_u32++; ! 785: } ! 786: ! 787: } ! 788: ! 789: f_dimm->m_clcnt_u32 = l_clcnt_u32; ! 790: } ! 791: ! 792: static uint32_t ! 793: ddr2_cl2speed( dimm_t *f_dimm, uint32_t f_cl_u32, uint32_t *f_tCK_pu32 ) ! 794: { ! 795: uint32_t i; ! 796: ! 797: for(i = 0; (i < NUM_CL) && (f_dimm->m_clval_pu32[i] != f_cl_u32); i++); ! 798: ! 799: if( i == NUM_CL ) { ! 800: return (uint32_t) ~0; ! 801: } ! 802: ! 803: *f_tCK_pu32 = f_dimm->m_tCK_pu32[i]; ! 804: ! 805: return f_dimm->m_speed_pu32[i]; ! 806: } ! 807: ! 808: static void ! 809: ddr2_setupDIMM( dimm_t *f_dimm, uint32_t f_bank_u32, uint8_t *f_spd_pu08 ) ! 810: { ! 811: f_dimm->m_pop_u32 = SL_POP; ! 812: f_dimm->m_bank_u32 = f_bank_u32; ! 813: f_dimm->m_size_u32 = ddr2_get_dimm_size( f_spd_pu08 ); ! 814: f_dimm->m_rank_u32 = ddr2_get_dimm_rank( f_spd_pu08 ); ! 815: f_dimm->m_type_u32 = ddr2_get_dimm_type( f_spd_pu08 ); ! 816: f_dimm->m_orgval_u32 = ddr2_get_dimm_org( f_spd_pu08, &f_dimm->m_orgmsk_u32 ); ! 817: f_dimm->m_width_u32 = ddr2_get_dimm_width( f_spd_pu08 ); ! 818: f_dimm->m_ecc_u32 = ddr2_get_dimm_ecc( f_spd_pu08 ); ! 819: f_dimm->m_burst_u32 = ddr2_get_dimm_burstlen( f_spd_pu08 ); ! 820: f_dimm->m_clmsk_u32 = ddr2_get_cl_mask( f_spd_pu08 ); ! 821: f_dimm->m_bankcnt_u32 = ddr2_get_banks( f_spd_pu08 ); ! 822: ! 823: ddr2_get_cl( f_dimm ); ! 824: ddr2_get_dimm_speed( f_dimm, f_spd_pu08 ); ! 825: ddr2_get_dimm_timings( f_dimm, f_spd_pu08 ); ! 826: } ! 827: ! 828: static int32_t ! 829: ddr2_checkSPD( uint8_t *f_spd_pu08 ) ! 830: { ! 831: uint8_t crc = 0; ! 832: uint32_t i; ! 833: ! 834: for( i = 0; i < SPD_BUF_SIZE - 1; i++ ) { ! 835: crc += f_spd_pu08[i]; ! 836: } ! 837: ! 838: if( crc != f_spd_pu08[i] ) { ! 839: return RET_ERR; ! 840: } ! 841: ! 842: return RET_OK; ! 843: } ! 844: ! 845: static int32_t ! 846: ddr2_readSPDs( void ) ! 847: { ! 848: static const uint32_t MAX_SPD_FAIL = 3; ! 849: uint8_t l_spdbuf_pu08[SPD_BUF_SIZE]; ! 850: uint32_t l_bankfail_u32 = 0; ! 851: uint32_t l_spdfail_u32 = 0; ! 852: int32_t l_i2c_i32 = RET_OK; ! 853: int32_t l_spd_i32 = RET_OK; ! 854: int32_t ret = RET_OK; ! 855: uint32_t i; ! 856: ! 857: /* ! 858: * read spd's and detect populated slots ! 859: */ ! 860: for( i = 0; i < NUM_SLOTS; i++ ) { ! 861: /* ! 862: * indicate slot as empty ! 863: */ ! 864: m_dimm[i].m_pop_u32 = 0; ! 865: ! 866: /* ! 867: * check whether bank is switched off ! 868: */ ! 869: if( ( m_bankoff_u32 & ( 0x1 << ( i / 2 ) ) ) != 0 ) { ! 870: continue; ! 871: } ! 872: ! 873: /* ! 874: * read SPD data ! 875: */ ! 876: ! 877: /* ! 878: * reset SPD fail counter ! 879: */ ! 880: l_spdfail_u32 = MAX_SPD_FAIL; ! 881: l_spd_i32 = RET_OK; ! 882: ! 883: while( l_spdfail_u32 != 0 ) { ! 884: l_i2c_i32 = i2c_read( I2C_START + i, 0x0, l_spdbuf_pu08, SPD_BUF_SIZE ); ! 885: ! 886: if( l_i2c_i32 == RET_OK ) { ! 887: l_spd_i32 = ddr2_checkSPD( l_spdbuf_pu08 ); ! 888: ! 889: if( l_spd_i32 == RET_OK ) { ! 890: l_spdfail_u32 = 0; ! 891: } else { ! 892: l_spdfail_u32--; ! 893: } ! 894: ! 895: } else { ! 896: l_spdfail_u32--; ! 897: } ! 898: ! 899: } ! 900: ! 901: if( l_spd_i32 != RET_OK ) { ! 902: #ifdef U4_INFO ! 903: printf( "\r\n [ERROR -> SPD read failure in slot %u]", ! 904: i2c_get_slot( I2C_START + i ) ); ! 905: #endif ! 906: ! 907: l_bankfail_u32 |= ( 0x1 << ( i / 2 ) ); ! 908: ret = RET_ERR; ! 909: } else if( l_i2c_i32 == RET_OK ) { ! 910: /* ! 911: * slot is populated ! 912: */ ! 913: ddr2_setupDIMM( &m_dimm[i], i / 2, l_spdbuf_pu08 ); ! 914: ! 915: m_dptr[m_dcnt_u32] = &m_dimm[i]; ! 916: m_dcnt_u32++; ! 917: } ! 918: ! 919: } ! 920: ! 921: if( ret != RET_OK ) { ! 922: m_bankoff_u32 |= l_bankfail_u32; ! 923: #ifdef U4_INFO ! 924: printf( "\r\n" ); ! 925: #endif ! 926: } ! 927: ! 928: return ret; ! 929: } ! 930: ! 931: static int32_t ! 932: ddr2_setupDIMMcfg( void ) ! 933: { ! 934: uint32_t l_tmp_u32; ! 935: uint32_t l_tmp0_u32; ! 936: uint32_t l_tmp1_u32; ! 937: uint32_t i, j, e, b; ! 938: ! 939: /* ! 940: * check wether on board DIMM slot population is valid ! 941: */ ! 942: e = 0; ! 943: b = 0; ! 944: for( i = 0; i < NUM_SLOTS; i += 2 ) { ! 945: ! 946: switch( m_dimm[i].m_pop_u32 + m_dimm[i+1].m_pop_u32 ) { ! 947: case 0: { ! 948: m_bankpop_u32[i/2] = 0; ! 949: break; ! 950: } ! 951: ! 952: case 2 * SL_POP: { ! 953: m_bankpop_u32[i/2] = !0; ! 954: b++; ! 955: break; ! 956: } ! 957: ! 958: default: { ! 959: #ifdef U4_DEBUG ! 960: printf( "\r\n [ERROR -> only 1 DIMM installed in bank %u]", i/2 ); ! 961: #endif ! 962: e++; ! 963: } ! 964: ! 965: } ! 966: ! 967: } ! 968: ! 969: /* ! 970: * return on error ! 971: */ ! 972: if( e != 0 ) { ! 973: #ifdef U4_DEBUG ! 974: printf( "\r\n" ); ! 975: #endif ! 976: return RET_ERR; ! 977: } ! 978: ! 979: if( b == 0 ) { ! 980: #ifdef U4_DEBUG ! 981: printf( "\r\n [ERROR -> no (functional) memory installed]\r\n" ); ! 982: #endif ! 983: return RET_ERR; ! 984: } ! 985: ! 986: /* ! 987: * check DIMM compatibility ! 988: * configuration is 128 bit data/128 bit bus ! 989: * -all DIMMs must be organized as x4 ! 990: * -all DIMMs must be 72 bit wide with ECC ! 991: * -all DIMMs must be registered DIMMs (RDIMMs) ! 992: * -paired DIMMs must have the same # of ranks, size & organization ! 993: */ ! 994: ! 995: /* ! 996: * check DIMM ranks & sizes ! 997: */ ! 998: e = 0; ! 999: for( i = 0; i < NUM_SLOTS; i += 2 ) { ! 1000: ! 1001: if( ( m_bankpop_u32[i/2] != 0 ) && ! 1002: ( ( m_dimm[i].m_rank_u32 != m_dimm[i+1].m_rank_u32 ) || ! 1003: ( m_dimm[i].m_size_u32 != m_dimm[i+1].m_size_u32 ) ) ) { ! 1004: #ifdef U4_DEBUG ! 1005: printf( "\r\n [ERROR -> installed DIMMs in bank %u have different ranks/sizes]", i/2 ); ! 1006: #endif ! 1007: e++; ! 1008: } ! 1009: ! 1010: } ! 1011: ! 1012: /* ! 1013: * return on error ! 1014: */ ! 1015: if( e != 0 ) { ! 1016: #ifdef U4_DEBUG ! 1017: printf( "\r\n" ); ! 1018: #endif ! 1019: return RET_ERR; ! 1020: } ! 1021: ! 1022: /* ! 1023: * check valid DIMM organisation (must be x4) ! 1024: */ ! 1025: e = 0; ! 1026: for( i = 0; i < m_dcnt_u32; i++ ) { ! 1027: ! 1028: if( ( m_dptr[i]->m_orgmsk_u32 & DIMM_ORG_x4 ) == 0 ) { ! 1029: #ifdef U4_DEBUG ! 1030: printf( "\r\n [ERROR -> wrong DIMM organisation in bank %u]", ! 1031: m_dptr[i]->m_bank_u32 ); ! 1032: #endif ! 1033: e++; ! 1034: } ! 1035: ! 1036: } ! 1037: ! 1038: /* ! 1039: * return on error ! 1040: */ ! 1041: if( e != 0 ) { ! 1042: #ifdef U4_DEBUG ! 1043: printf( "\r\n" ); ! 1044: #endif ! 1045: return RET_ERR; ! 1046: } ! 1047: ! 1048: e = (uint32_t) ~0; ! 1049: for( i = 0; i < m_dcnt_u32; i++ ) { ! 1050: e &= m_dptr[i]->m_type_u32; ! 1051: } ! 1052: ! 1053: /* ! 1054: * return on error ! 1055: */ ! 1056: if( e == 0 ) { ! 1057: #ifdef U4_DEBUG ! 1058: printf( "\r\n [ERROR -> installed DIMMs are of different type]\r\n" ); ! 1059: #endif ! 1060: return RET_ERR; ! 1061: } ! 1062: ! 1063: /* ! 1064: * setup generic dimm ! 1065: */ ! 1066: m_gendimm.m_type_u32 = e; ! 1067: ! 1068: /* ! 1069: * check valid width, ecc & burst length ! 1070: */ ! 1071: e = 0; ! 1072: for( i = 0; i < m_dcnt_u32; i++ ) { ! 1073: ! 1074: if( m_dptr[i]->m_width_u32 != DIMM_WIDTH ) { ! 1075: #ifdef U4_DEBUG ! 1076: printf( "\r\n [ERROR -> invalid DIMM width in bank %u]", ! 1077: m_dptr[i]->m_bank_u32 ); ! 1078: #endif ! 1079: e++; ! 1080: } ! 1081: ! 1082: if( m_dptr[i]->m_ecc_u32 == 0 ) { ! 1083: #ifdef U4_DEBUG ! 1084: printf( "\r\n [ERROR -> DIMM(s) do not support ECC in bank %u]", ! 1085: m_dptr[i]->m_bank_u32 ); ! 1086: #endif ! 1087: e++; ! 1088: } ! 1089: ! 1090: if( ( m_dptr[i]->m_burst_u32 & DIMM_BURSTLEN_4 ) == 0 ) { ! 1091: #ifdef U4_DEBUG ! 1092: printf( "\r\n [ERROR -> DIMM(s) have invalid burst length in bank %u]", ! 1093: m_dptr[i]->m_bank_u32 ); ! 1094: #endif ! 1095: e++; ! 1096: } ! 1097: ! 1098: } ! 1099: ! 1100: /* ! 1101: * return on error ! 1102: */ ! 1103: if( e != 0 ) { ! 1104: #ifdef U4_DEBUG ! 1105: printf( "\r\n" ); ! 1106: #endif ! 1107: return RET_ERR; ! 1108: } ! 1109: ! 1110: /* ! 1111: * setup generic dimm ! 1112: */ ! 1113: m_gendimm.m_width_u32 = m_dptr[0]->m_width_u32; ! 1114: m_gendimm.m_ecc_u32 = m_dptr[0]->m_ecc_u32; ! 1115: m_gendimm.m_burst_u32 = m_dptr[0]->m_burst_u32; ! 1116: ! 1117: /* ! 1118: * success ! 1119: */ ! 1120: m_gendimm.m_pop_u32 = SL_POP; ! 1121: ! 1122: /* ! 1123: * setup timing parameters ! 1124: */ ! 1125: ! 1126: /* ! 1127: * find smallest common CL value ! 1128: */ ! 1129: l_tmp_u32 = (uint32_t) ~0; ! 1130: for( i = 0; i < m_dcnt_u32; i++ ) { ! 1131: l_tmp_u32 &= m_dptr[i]->m_clmsk_u32; ! 1132: } ! 1133: ! 1134: m_gendimm.m_clmsk_u32 = l_tmp_u32; ! 1135: ddr2_get_cl( &m_gendimm ); ! 1136: ! 1137: /* ! 1138: * find fastest common DIMM speed for all common CL values ! 1139: */ ! 1140: for( i = 0; i < m_gendimm.m_clcnt_u32; i++ ) { ! 1141: m_gendimm.m_speed_pu32[i] = (uint32_t) ~0; ! 1142: ! 1143: for( j = 0; j < m_dcnt_u32; j++ ) { ! 1144: l_tmp0_u32 = ! 1145: ddr2_cl2speed( m_dptr[j], ! 1146: m_gendimm.m_clval_pu32[i], ! 1147: &l_tmp1_u32 ); ! 1148: ! 1149: if( m_gendimm.m_speed_pu32[i] > l_tmp0_u32 ) { ! 1150: m_gendimm.m_speed_pu32[i] = l_tmp0_u32; ! 1151: m_gendimm.m_tCK_pu32[i] = l_tmp1_u32; ! 1152: } ! 1153: ! 1154: } ! 1155: ! 1156: } ! 1157: ! 1158: /* ! 1159: * check wether cl values are supported by U4 ! 1160: */ ! 1161: for( i = 0; i < m_gendimm.m_clcnt_u32; i++ ) { ! 1162: ! 1163: if( ( m_gendimm.m_clval_pu32[i] >= U4_MIN_CL ) && ! 1164: ( m_gendimm.m_clval_pu32[i] <= U4_MAX_CL ) ) { ! 1165: break; ! 1166: } ! 1167: ! 1168: } ! 1169: ! 1170: if( i == m_gendimm.m_clcnt_u32 ) { ! 1171: #ifdef U4_DEBUG ! 1172: printf( "\r\n [ERROR -> DIMM's CL values not supported]\r\n" ); ! 1173: #endif ! 1174: return RET_ERR; ! 1175: } ! 1176: ! 1177: /* ! 1178: * choose cl/speed values to use: prefer speed over CL ! 1179: * i holds smallest supported cl value of u4 already ! 1180: */ ! 1181: l_tmp_u32 = 0; ! 1182: while( i < m_gendimm.m_clcnt_u32 ) { ! 1183: ! 1184: if( l_tmp_u32 < m_gendimm.m_speed_pu32[i] ) { ! 1185: l_tmp_u32 = m_gendimm.m_speed_pu32[i]; ! 1186: m_dclidx_u32 = i; ! 1187: } ! 1188: ! 1189: i++; ! 1190: } ! 1191: ! 1192: /* ! 1193: * choose largest number of banks ! 1194: */ ! 1195: m_gendimm.m_bankcnt_u32 = 0; ! 1196: ! 1197: for( i = 0; i < m_dcnt_u32; i++ ) { ! 1198: ! 1199: if( m_gendimm.m_bankcnt_u32 < m_dptr[i]->m_bankcnt_u32 ) { ! 1200: m_gendimm.m_bankcnt_u32 = m_dptr[i]->m_bankcnt_u32; ! 1201: } ! 1202: ! 1203: } ! 1204: ! 1205: /* ! 1206: * setup fastest possible timing parameters for all DIMMs ! 1207: */ ! 1208: m_gendimm.m_tRP_u32 = 0; ! 1209: m_gendimm.m_tRRD_u32 = 0; ! 1210: m_gendimm.m_tRCD_u32 = 0; ! 1211: m_gendimm.m_tWR_u32 = 0; ! 1212: m_gendimm.m_tWTR_u32 = 0; ! 1213: m_gendimm.m_tRTP_u32 = 0; ! 1214: m_gendimm.m_tRAS_u32 = 0; ! 1215: m_gendimm.m_tRC_u32 = 0; ! 1216: m_gendimm.m_tRFC_u32 = 0; ! 1217: m_gendimm.m_tREF_u32 = (uint32_t) ~0; ! 1218: ! 1219: for( i = 0; i < m_dcnt_u32; i++ ) { ! 1220: ! 1221: if( m_gendimm.m_tRP_u32 < m_dptr[i]->m_tRP_u32 ) { ! 1222: m_gendimm.m_tRP_u32 = m_dptr[i]->m_tRP_u32; ! 1223: } ! 1224: ! 1225: if( m_gendimm.m_tRRD_u32 < m_dptr[i]->m_tRRD_u32 ) { ! 1226: m_gendimm.m_tRRD_u32 = m_dptr[i]->m_tRRD_u32; ! 1227: } ! 1228: ! 1229: if( m_gendimm.m_tRCD_u32 < m_dptr[i]->m_tRCD_u32 ) { ! 1230: m_gendimm.m_tRCD_u32 = m_dptr[i]->m_tRCD_u32; ! 1231: } ! 1232: ! 1233: if( m_gendimm.m_tWR_u32 < m_dptr[i]->m_tWR_u32 ) { ! 1234: m_gendimm.m_tWR_u32 = m_dptr[i]->m_tWR_u32; ! 1235: } ! 1236: ! 1237: if( m_gendimm.m_tWTR_u32 < m_dptr[i]->m_tWTR_u32 ) { ! 1238: m_gendimm.m_tWTR_u32 = m_dptr[i]->m_tWTR_u32; ! 1239: } ! 1240: ! 1241: if( m_gendimm.m_tRTP_u32 < m_dptr[i]->m_tRTP_u32 ) { ! 1242: m_gendimm.m_tRTP_u32 = m_dptr[i]->m_tRTP_u32; ! 1243: } ! 1244: ! 1245: if( m_gendimm.m_tRAS_u32 < m_dptr[i]->m_tRAS_u32 ) { ! 1246: m_gendimm.m_tRAS_u32 = m_dptr[i]->m_tRAS_u32; ! 1247: } ! 1248: ! 1249: if( m_gendimm.m_tRC_u32 < m_dptr[i]->m_tRC_u32 ) { ! 1250: m_gendimm.m_tRC_u32 = m_dptr[i]->m_tRC_u32; ! 1251: } ! 1252: ! 1253: if( m_gendimm.m_tRFC_u32 < m_dptr[i]->m_tRFC_u32 ) { ! 1254: m_gendimm.m_tRFC_u32 = m_dptr[i]->m_tRFC_u32; ! 1255: } ! 1256: ! 1257: if( m_gendimm.m_tREF_u32 > m_dptr[i]->m_tREF_u32 ) { ! 1258: m_gendimm.m_tREF_u32 = m_dptr[i]->m_tREF_u32; ! 1259: } ! 1260: ! 1261: } ! 1262: ! 1263: return RET_OK; ! 1264: } ! 1265: ! 1266: static void ! 1267: u4_group2dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1 ) ! 1268: { ! 1269: dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; ! 1270: ! 1271: /* ! 1272: * known conditions at this point: ! 1273: * -at least 2 slots are populated ! 1274: * -the 2 DIMMs are equal ! 1275: * -DIMMs are double sided (2 ranks) ! 1276: * ! 1277: * RESULT: ! 1278: * 1 group of 2 ranks (2 ranks/2 DIMMs) ! 1279: * -> CS mode 1 (one double sided DIMM pair) ! 1280: */ ! 1281: l_dgr->m_size_u32 = 2 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); ! 1282: l_dgr->m_ss_u32 = 0; ! 1283: l_dgr->m_csmode_u32 = 1; ! 1284: l_dgr->m_dcnt_u32 = 2; ! 1285: l_dgr->m_dptr[0] = f_dimm0; ! 1286: l_dgr->m_dptr[1] = f_dimm1; ! 1287: ! 1288: m_dgrcnt_u32++; ! 1289: } ! 1290: ! 1291: static void ! 1292: u4_group2dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1 ) ! 1293: { ! 1294: dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; ! 1295: ! 1296: /* ! 1297: * known conditions at this point: ! 1298: * -at least 2 slots are populated ! 1299: * -the 2 DIMMs are equal ! 1300: * -DIMMs are single sided (1 rank) ! 1301: * ! 1302: * RESULT: ! 1303: * 1 group of 1 rank (1 rank/2 DIMMs) ! 1304: * -> CS mode 0 (one single sided DIMM pair) ! 1305: */ ! 1306: l_dgr->m_size_u32 = 2 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); ! 1307: l_dgr->m_ss_u32 = 1; ! 1308: l_dgr->m_csmode_u32 = 0; ! 1309: l_dgr->m_dcnt_u32 = 2; ! 1310: l_dgr->m_dptr[0] = f_dimm0; ! 1311: l_dgr->m_dptr[1] = f_dimm1; ! 1312: ! 1313: m_dgrcnt_u32++; ! 1314: } ! 1315: ! 1316: static void ! 1317: u4_group4dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1, ! 1318: dimm_t *f_dimm2, dimm_t *f_dimm3 ) ! 1319: { ! 1320: dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; ! 1321: ! 1322: /* ! 1323: * known conditions at this point: ! 1324: * -4 slots are populated ! 1325: * -all 4 DIMMs are equal ! 1326: * -DIMMs are double sided (2 ranks) ! 1327: * ! 1328: * RESULT: ! 1329: * 1 group of 4 ranks (2 ranks/2 DIMMs) ! 1330: * -> CS mode 2 (two double sided DIMM pairs) ! 1331: */ ! 1332: l_dgr->m_size_u32 = 4 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); ! 1333: l_dgr->m_ss_u32 = 0; ! 1334: l_dgr->m_csmode_u32 = 2; ! 1335: l_dgr->m_dcnt_u32 = 4; ! 1336: l_dgr->m_dptr[0] = f_dimm0; ! 1337: l_dgr->m_dptr[1] = f_dimm1; ! 1338: l_dgr->m_dptr[2] = f_dimm2; ! 1339: l_dgr->m_dptr[3] = f_dimm3; ! 1340: ! 1341: m_dgrcnt_u32++; ! 1342: } ! 1343: ! 1344: static void ! 1345: u4_group4dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1, ! 1346: dimm_t *f_dimm2, dimm_t *f_dimm3 ) ! 1347: { ! 1348: dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; ! 1349: ! 1350: /* ! 1351: * known conditions at this point: ! 1352: * -4 slots are populated ! 1353: * -all 4 DIMMs are equal ! 1354: * -DIMMs are single sided (1 rank) ! 1355: * ! 1356: * RESULT: ! 1357: * 1 group of 2 ranks (1 rank/2 DIMMs) ! 1358: * -> CS mode 1 (two single sided DIMM pairs) ! 1359: */ ! 1360: l_dgr->m_size_u32 = 4 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); ! 1361: l_dgr->m_ss_u32 = 1; ! 1362: l_dgr->m_csmode_u32 = 1; ! 1363: l_dgr->m_dcnt_u32 = 4; ! 1364: l_dgr->m_dptr[0] = f_dimm0; ! 1365: l_dgr->m_dptr[1] = f_dimm1; ! 1366: l_dgr->m_dptr[2] = f_dimm2; ! 1367: l_dgr->m_dptr[3] = f_dimm3; ! 1368: ! 1369: m_dgrcnt_u32++; ! 1370: } ! 1371: ! 1372: static void ! 1373: u4_group8dimmsDS( dimm_t *f_dimm0, dimm_t *f_dimm1, ! 1374: dimm_t *f_dimm2, dimm_t *f_dimm3, ! 1375: dimm_t *f_dimm4, dimm_t *f_dimm5, ! 1376: dimm_t *f_dimm6, dimm_t *f_dimm7 ) ! 1377: { ! 1378: dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; ! 1379: ! 1380: /* ! 1381: * known conditions at this point: ! 1382: * -8 slots are populated ! 1383: * -all 8 DIMMs are equal ! 1384: * -DIMMs are double sided (2 ranks) ! 1385: * ! 1386: * RESULT: ! 1387: * 1 group of 8 ranks (2 ranks/2 DIMMs) ! 1388: * -> CS mode 3 (four double sided DIMM pairs) ! 1389: */ ! 1390: l_dgr->m_size_u32 = 8 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); ! 1391: l_dgr->m_ss_u32 = 0; ! 1392: l_dgr->m_csmode_u32 = 3; ! 1393: l_dgr->m_dcnt_u32 = 8; ! 1394: l_dgr->m_dptr[0] = f_dimm0; ! 1395: l_dgr->m_dptr[1] = f_dimm1; ! 1396: l_dgr->m_dptr[2] = f_dimm2; ! 1397: l_dgr->m_dptr[3] = f_dimm3; ! 1398: l_dgr->m_dptr[4] = f_dimm4; ! 1399: l_dgr->m_dptr[5] = f_dimm5; ! 1400: l_dgr->m_dptr[6] = f_dimm6; ! 1401: l_dgr->m_dptr[7] = f_dimm7; ! 1402: ! 1403: m_dgrcnt_u32++; ! 1404: } ! 1405: ! 1406: static void ! 1407: u4_group8dimmsSS( dimm_t *f_dimm0, dimm_t *f_dimm1, ! 1408: dimm_t *f_dimm2, dimm_t *f_dimm3, ! 1409: dimm_t *f_dimm4, dimm_t *f_dimm5, ! 1410: dimm_t *f_dimm6, dimm_t *f_dimm7 ) ! 1411: { ! 1412: dgroup_t *l_dgr = &m_dgroup[m_dgrcnt_u32]; ! 1413: ! 1414: /* ! 1415: * known conditions at this point: ! 1416: * -8 slots are populated ! 1417: * -all 8 DIMMs are equal ! 1418: * -DIMMs are single sided (1 rank) ! 1419: * ! 1420: * RESULT: ! 1421: * 1 group of 4 ranks (1 rank/2 DIMMs) ! 1422: * -> CS mode 2 (four single sided DIMM pairs) ! 1423: */ ! 1424: l_dgr->m_size_u32 = 8 * ( f_dimm0->m_size_u32 * f_dimm0->m_rank_u32 ); ! 1425: l_dgr->m_ss_u32 = 1; ! 1426: l_dgr->m_csmode_u32 = 2; ! 1427: l_dgr->m_dcnt_u32 = 8; ! 1428: l_dgr->m_dptr[0] = f_dimm0; ! 1429: l_dgr->m_dptr[1] = f_dimm1; ! 1430: l_dgr->m_dptr[2] = f_dimm2; ! 1431: l_dgr->m_dptr[3] = f_dimm3; ! 1432: l_dgr->m_dptr[4] = f_dimm4; ! 1433: l_dgr->m_dptr[5] = f_dimm5; ! 1434: l_dgr->m_dptr[6] = f_dimm6; ! 1435: l_dgr->m_dptr[7] = f_dimm7; ! 1436: ! 1437: m_dgrcnt_u32++; ! 1438: } ! 1439: ! 1440: static int32_t ! 1441: u4_Dcmp( dimm_t *f_dimm0, dimm_t *f_dimm1 ) ! 1442: { ! 1443: ! 1444: if( ( f_dimm0->m_size_u32 == f_dimm1->m_size_u32 ) && ! 1445: ( f_dimm0->m_rank_u32 == f_dimm1->m_rank_u32 ) ) { ! 1446: return RET_OK; ! 1447: } ! 1448: ! 1449: return RET_ERR; ! 1450: } ! 1451: ! 1452: static void ! 1453: u4_group1banks( uint32_t *bidx ) ! 1454: { ! 1455: uint32_t didx = 2 * bidx[0]; ! 1456: ! 1457: /* ! 1458: * known conditions at this point: ! 1459: * -either DIMMs 0 & 4 or ! 1460: * DIMMs 1 & 5 or ! 1461: * DIMMs 2 & 6 or ! 1462: * DIMMs 3 & 7 are populated ! 1463: * -3 (bimini)/1 (maui) pair of slots is empty ! 1464: * -installed DIMMs are equal ! 1465: */ ! 1466: ! 1467: /* ! 1468: * double/single sided setup ! 1469: */ ! 1470: if( m_dimm[didx].m_rank_u32 == 1 ) { ! 1471: u4_group2dimmsSS( &m_dimm[didx], &m_dimm[didx+1] ); ! 1472: } else { ! 1473: u4_group2dimmsDS( &m_dimm[didx], &m_dimm[didx+1] ); ! 1474: } ! 1475: ! 1476: } ! 1477: ! 1478: static void ! 1479: u4_group2banks( uint32_t *bidx ) ! 1480: { ! 1481: uint32_t didx0 = 2 * bidx[0]; ! 1482: uint32_t didx1 = 2 * bidx[1]; ! 1483: ! 1484: /* ! 1485: * known conditions at this point: ! 1486: * -4 slots are populated ! 1487: */ ! 1488: ! 1489: /* ! 1490: * check wether DIMM banks may be grouped ! 1491: */ ! 1492: if( ( ( ( bidx[0] + bidx[1] ) & 0x1 ) != 0 ) && ! 1493: ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx1] ) == 0 ) ) { ! 1494: /* ! 1495: * double/single sided setup ! 1496: * NOTE: at this point all DIMMs have the same amount ! 1497: * of ranks, therefore only the # of ranks on DIMM 0 is checked ! 1498: */ ! 1499: if( m_dimm[didx0].m_rank_u32 == 1 ) { ! 1500: u4_group4dimmsSS( &m_dimm[didx0], &m_dimm[didx0+1], ! 1501: &m_dimm[didx1], &m_dimm[didx1+1]); ! 1502: } else { ! 1503: u4_group4dimmsDS( &m_dimm[didx0], &m_dimm[didx0+1], ! 1504: &m_dimm[didx1], &m_dimm[didx1+1]); ! 1505: } ! 1506: ! 1507: } else { ! 1508: u4_group1banks( &bidx[0] ); ! 1509: u4_group1banks( &bidx[1] ); ! 1510: } ! 1511: ! 1512: } ! 1513: ! 1514: static void ! 1515: u4_group3banks( uint32_t *bidx ) ! 1516: { ! 1517: ! 1518: if( ( bidx[0] == 0 ) && ( bidx[1] == 1 ) ) { ! 1519: u4_group2banks( &bidx[0] ); ! 1520: u4_group1banks( &bidx[2] ); ! 1521: } else if( ( bidx[1] == 2 ) && ( bidx[2] == 3 ) ) { ! 1522: u4_group2banks( &bidx[1] ); ! 1523: u4_group1banks( &bidx[0] ); ! 1524: } ! 1525: ! 1526: } ! 1527: ! 1528: static void ! 1529: u4_group4banks( uint32_t *bidx ) ! 1530: { ! 1531: uint32_t didx0 = 2 * bidx[0]; ! 1532: uint32_t didx1 = 2 * bidx[1]; ! 1533: uint32_t didx2 = 2 * bidx[2]; ! 1534: uint32_t didx3 = 2 * bidx[3]; ! 1535: ! 1536: if( ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx1] ) == RET_OK ) && ! 1537: ( u4_Dcmp( &m_dimm[didx2], &m_dimm[didx3] ) == RET_OK ) && ! 1538: ( u4_Dcmp( &m_dimm[didx0], &m_dimm[didx2] ) == RET_OK ) ) { ! 1539: ! 1540: if( m_dimm[didx0].m_rank_u32 == 1 ) { ! 1541: u4_group8dimmsSS( &m_dimm[didx0], &m_dimm[didx0+1], ! 1542: &m_dimm[didx1], &m_dimm[didx1+1], ! 1543: &m_dimm[didx2], &m_dimm[didx2+1], ! 1544: &m_dimm[didx3], &m_dimm[didx3+1] ); ! 1545: } else { ! 1546: u4_group8dimmsDS( &m_dimm[didx0], &m_dimm[didx0+1], ! 1547: &m_dimm[didx1], &m_dimm[didx1+1], ! 1548: &m_dimm[didx2], &m_dimm[didx2+1], ! 1549: &m_dimm[didx3], &m_dimm[didx3+1] ); ! 1550: } ! 1551: ! 1552: } else { ! 1553: u4_group2banks( &bidx[0] ); ! 1554: u4_group2banks( &bidx[2] ); ! 1555: } ! 1556: ! 1557: } ! 1558: ! 1559: static void ! 1560: u4_sortDIMMgroups( void ) ! 1561: { ! 1562: uint32_t i, j; ! 1563: ! 1564: /* ! 1565: * setup global group pointers ! 1566: */ ! 1567: for( i = 0; i < m_dgrcnt_u32; i++ ) { ! 1568: m_dgrptr[i] = &m_dgroup[i]; ! 1569: } ! 1570: ! 1571: /* ! 1572: * use a simple bubble sort to sort groups by size (descending) ! 1573: */ ! 1574: for( i = 0; i < ( m_dgrcnt_u32 - 1 ); i++ ) { ! 1575: ! 1576: for( j = i + 1; j < m_dgrcnt_u32; j++ ) { ! 1577: ! 1578: if( m_dgrptr[i]->m_size_u32 < m_dgrptr[j]->m_size_u32 ) { ! 1579: dgroup_t *l_sgr; ! 1580: ! 1581: l_sgr = m_dgrptr[i]; ! 1582: m_dgrptr[i] = m_dgrptr[j]; ! 1583: m_dgrptr[j] = l_sgr; ! 1584: } ! 1585: ! 1586: } ! 1587: ! 1588: } ! 1589: ! 1590: } ! 1591: ! 1592: static void ! 1593: u4_calcDIMMcnfg( void ) ! 1594: { ! 1595: static const uint32_t _2GB = (uint32_t) 0x00800; ! 1596: static const uint32_t _4GB = (uint32_t) 0x01000; ! 1597: static const uint32_t _64GB = (uint32_t) 0x10000; ! 1598: uint32_t l_start_u32 = (uint32_t) 0; ! 1599: uint32_t l_end_u32 = (uint32_t) 0; ! 1600: uint32_t l_add2g_u32 = (uint32_t) 1; ! 1601: uint32_t l_sub2g_u32 = (uint32_t) 1; ! 1602: uint32_t i; ! 1603: ! 1604: /* ! 1605: * setup DIMM group parameters ! 1606: */ ! 1607: for( i = 0; i < m_dgrcnt_u32; i++ ) { ! 1608: l_end_u32 = l_start_u32 + m_dgrptr[i]->m_size_u32; ! 1609: ! 1610: if( m_dgrptr[i]->m_size_u32 > _2GB ) { ! 1611: ! 1612: if( l_end_u32 < _64GB ) { ! 1613: l_add2g_u32 = ( l_end_u32 >> 11 ); ! 1614: } else { ! 1615: l_add2g_u32 = 1; ! 1616: } ! 1617: ! 1618: if( l_start_u32 == 0 ) { ! 1619: l_sub2g_u32 = 1; ! 1620: } else { ! 1621: l_sub2g_u32 = ( l_start_u32 >> 11 ); ! 1622: } ! 1623: ! 1624: } else if( l_add2g_u32 != 1 ) { ! 1625: l_start_u32 += _2GB; ! 1626: l_end_u32 += _2GB; ! 1627: l_add2g_u32 = 1; ! 1628: l_sub2g_u32 = 1; ! 1629: } ! 1630: ! 1631: /* ! 1632: * save values for the group ! 1633: */ ! 1634: m_dgrptr[i]->m_start_u32 = ( l_start_u32 >> 7 ); // = /128 ! 1635: m_dgrptr[i]->m_end_u32 = ( l_end_u32 >> 7 ); ! 1636: m_dgrptr[i]->m_add2g_u32 = l_add2g_u32; ! 1637: m_dgrptr[i]->m_sub2g_u32 = l_sub2g_u32; ! 1638: ! 1639: /* ! 1640: * continue with next group ! 1641: */ ! 1642: if( l_end_u32 != _2GB ) { ! 1643: l_start_u32 = l_end_u32; ! 1644: } else { ! 1645: l_start_u32 = _4GB; ! 1646: } ! 1647: ! 1648: } ! 1649: ! 1650: } ! 1651: ! 1652: static int32_t ! 1653: u4_calcDIMMmemmode( void ) ! 1654: { ! 1655: static const uint32_t MAX_ORG = (uint32_t) 0x10; ! 1656: static const uint32_t MIN_BASE = (uint32_t) 0x80; ! 1657: static const uint32_t MAX_MODE = (uint32_t) 0x10; ! 1658: static const uint32_t MODE_ADD = (uint32_t) 0x04; ! 1659: dimm_t *l_dptr; ! 1660: uint32_t l_modeoffs_u32; ! 1661: uint32_t l_sizebase_u32; ! 1662: int32_t ret = RET_OK; ! 1663: uint32_t i, j; ! 1664: ! 1665: /* ! 1666: * loop through all DIMM groups and calculate memmode setting ! 1667: */ ! 1668: for( i = 0; i < m_dgrcnt_u32; i++ ) { ! 1669: l_dptr = m_dgrptr[i]->m_dptr[0]; // all dimms in one group are equal! ! 1670: ! 1671: l_modeoffs_u32 = MAX_ORG / l_dptr->m_orgval_u32; ! 1672: l_modeoffs_u32 /= (uint32_t) 2; ! 1673: l_sizebase_u32 = ( MIN_BASE << l_modeoffs_u32 ); ! 1674: ! 1675: j = 0; ! 1676: while( ( l_sizebase_u32 != l_dptr->m_size_u32 ) && ! 1677: ( j < MAX_MODE ) ) { ! 1678: l_sizebase_u32 <<= 1; ! 1679: j += (uint32_t) MODE_ADD; ! 1680: } ! 1681: ! 1682: // return on error ! 1683: if( j >= MAX_MODE ) { ! 1684: #ifdef U4_INFO ! 1685: uint32_t b, k, l; ! 1686: printf( "\r\n [ERROR -> unsupported memory type in bank(s)" ); ! 1687: ! 1688: l = 0; ! 1689: for( k = 0; k < m_dgrptr[i]->m_dcnt_u32; k++ ) { ! 1690: b = m_dgrptr[i]->m_dptr[k]->m_bank_u32; ! 1691: ! 1692: if( ( l & ( 1 << b ) ) == 0 ) { ! 1693: printf( " %u", b ); ! 1694: l |= ( 1 << b ); ! 1695: } ! 1696: ! 1697: } ! 1698: ! 1699: printf( "]\r\n" ); ! 1700: #endif ! 1701: ! 1702: ret = RET_ERR; ! 1703: } else { ! 1704: m_dgrptr[i]->m_memmd_u32 = l_modeoffs_u32 + j; ! 1705: } ! 1706: ! 1707: } ! 1708: ! 1709: return ret; ! 1710: } ! 1711: ! 1712: static void ! 1713: u4_setupDIMMgroups( void ) ! 1714: { ! 1715: static const uint64_t _1MB = (uint64_t) 0x100000; ! 1716: uint32_t l_bcnt_u32; ! 1717: uint32_t l_bidx_u32[NUM_BANKS]; ! 1718: uint32_t i; ! 1719: ! 1720: /* ! 1721: * calculate number of populated banks ! 1722: * IMPORTANT: array must be in ascending order! ! 1723: */ ! 1724: l_bcnt_u32 = 0; ! 1725: for( i = 0; i < NUM_BANKS; i++ ) { ! 1726: ! 1727: if( m_bankpop_u32[i] != 0 ) { ! 1728: l_bidx_u32[l_bcnt_u32] = i; ! 1729: l_bcnt_u32++; ! 1730: } ! 1731: ! 1732: } ! 1733: ! 1734: switch( l_bcnt_u32 ) { ! 1735: case 4: u4_group4banks( &l_bidx_u32[0] ); break; ! 1736: case 3: u4_group3banks( &l_bidx_u32[0] ); break; ! 1737: case 2: u4_group2banks( &l_bidx_u32[0] ); break; ! 1738: case 1: u4_group1banks( &l_bidx_u32[0] ); break; ! 1739: } ! 1740: ! 1741: /* ! 1742: * sort DIMM groups by size (descending) ! 1743: */ ! 1744: u4_sortDIMMgroups(); ! 1745: ! 1746: /* ! 1747: * calculate overall memory size in bytes ! 1748: * (group size is in MB) ! 1749: */ ! 1750: m_memsize_u64 = 0; ! 1751: for( i = 0; i < m_dgrcnt_u32; i++ ) { ! 1752: m_memsize_u64 += (uint64_t) m_dgrptr[i]->m_size_u32 * _1MB; ! 1753: } ! 1754: ! 1755: } ! 1756: ! 1757: static int32_t ! 1758: u4_setup_core_clock( void ) ! 1759: { ! 1760: static const uint32_t MCLK = (uint32_t) 266; ! 1761: static const uint32_t CDIV = (uint32_t) 66; ! 1762: static const uint32_t CMAX = (uint32_t) 7; ! 1763: static const uint32_t MERR = (uint32_t) 10; ! 1764: uint32_t volatile l_cclk_u32; ! 1765: uint32_t volatile l_pll2_u32; ! 1766: uint32_t i, s; ! 1767: ! 1768: #ifdef U4_INFO ! 1769: printf( " [core clock reset: ]" ); ! 1770: #endif ! 1771: ! 1772: /* ! 1773: * calculate speed value ! 1774: */ ! 1775: s = m_gendimm.m_speed_pu32[m_dclidx_u32]; ! 1776: s -= MCLK; ! 1777: s /= CDIV; ! 1778: ! 1779: /* ! 1780: * insert new core clock value ! 1781: */ ! 1782: l_cclk_u32 = load32_ci( ClkCntl_R ); ! 1783: l_cclk_u32 &= ~CLK_DDR_CLK_MSK; ! 1784: l_cclk_u32 |= ( s << 18 ); ! 1785: ! 1786: ! 1787: // return on error ! 1788: if( s > CMAX ) { ! 1789: #ifdef U4_INFO ! 1790: printf( "\b\b\b\bERR\r\n" ); ! 1791: #endif ! 1792: return RET_ERR; ! 1793: } ! 1794: ! 1795: /* ! 1796: * reset core clock ! 1797: */ ! 1798: store32_ci( ClkCntl_R, l_cclk_u32 ); ! 1799: dly( 0x1000000 ); ! 1800: or32_ci( PLL2Cntl_R, IBIT(0) ); ! 1801: dly( 0x1000000 ); ! 1802: ! 1803: /* ! 1804: * wait for reset to finish ! 1805: */ ! 1806: do { ! 1807: l_pll2_u32 = load32_ci( PLL2Cntl_R ); ! 1808: } while( ( l_pll2_u32 & IBIT(0) ) != 0 ); ! 1809: ! 1810: /* ! 1811: * wait for stable PLL ! 1812: */ ! 1813: s = 0; ! 1814: do { ! 1815: l_pll2_u32 = ( load32_ci( PLL2Cntl_R ) & IBIT(2) ); ! 1816: ! 1817: for( i = 0; i < 4; i++ ) { ! 1818: l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) ); ! 1819: l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) ); ! 1820: l_pll2_u32 &= ( load32_ci( PLL2Cntl_R ) & IBIT(2) ); ! 1821: dly( 0x10000 ); ! 1822: } ! 1823: ! 1824: } while( ( l_pll2_u32 == 0 ) && ( s++ < MERR ) ); ! 1825: ! 1826: if( s >= MERR ) { ! 1827: #ifdef U4_INFO ! 1828: printf( "\b\b\b\bERR\r\n" ); ! 1829: #endif ! 1830: return RET_ERR; ! 1831: } ! 1832: ! 1833: #ifdef U4_INFO ! 1834: printf( "\b\b\bOK\r\n" ); ! 1835: #endif ! 1836: ! 1837: return RET_OK; ! 1838: } ! 1839: ! 1840: static void ! 1841: u4_auto_calib_init( void ) ! 1842: { ! 1843: static const uint32_t SEQ[] = { ! 1844: 0xb1000000, 0xd1000000, 0xd1000000, 0xd1000000, ! 1845: 0xd1000000, 0xd1000000, 0xd1000000, 0xd1000000, ! 1846: 0xd1000000, 0xd1000000, 0xd1000000, 0xd1000000, ! 1847: 0xd1000000, 0xd1000000, 0xd1000400, 0x00000000, ! 1848: }; ! 1849: ! 1850: uint64_t i; ! 1851: uint32_t j; ! 1852: ! 1853: for( i = MemInit00_R, j = 0; i <= MemInit15_R; i += 0x10, j++ ) { ! 1854: store32_ci( i, SEQ[j] ); ! 1855: } ! 1856: ! 1857: } ! 1858: ! 1859: #if 0 ! 1860: static uint32_t ! 1861: u4_RSL_BLane( uint32_t f_Rank_u32, uint32_t f_BLane_u32 ) ! 1862: { ! 1863: static const uint32_t MemProgCntl_V = (uint32_t) 0x80000500; ! 1864: static const uint32_t CalConf0_V = (uint32_t) 0x0000aa10; ! 1865: uint32_t l_MemProgCntl_u32; ! 1866: uint32_t l_CalConf0_u32; ! 1867: uint32_t l_MeasStat_u32; ! 1868: uint32_t l_CalC_u32; ! 1869: uint64_t MeasStat_R; ! 1870: uint64_t CalC_R; ! 1871: uint64_t VerC_R; ! 1872: uint32_t shft; ! 1873: uint32_t v; ! 1874: ! 1875: if( f_BLane_u32 < 4 ) { ! 1876: MeasStat_R = MeasStatusC0_R; ! 1877: CalC_R = CalC0_R; ! 1878: VerC_R = RstLdEnVerniersC0_R; ! 1879: } else if( f_BLane_u32 < 8 ) { ! 1880: f_BLane_u32 -= 4; ! 1881: MeasStat_R = MeasStatusC1_R; ! 1882: CalC_R = CalC1_R; ! 1883: VerC_R = RstLdEnVerniersC1_R; ! 1884: } else if( f_BLane_u32 < 12 ) { ! 1885: f_BLane_u32 -= 8; ! 1886: MeasStat_R = MeasStatusC2_R; ! 1887: CalC_R = CalC2_R; ! 1888: VerC_R = RstLdEnVerniersC2_R; ! 1889: } else if( f_BLane_u32 == 16 ) { ! 1890: f_BLane_u32 = 4; ! 1891: MeasStat_R = MeasStatusC1_R; ! 1892: CalC_R = CalC1_R; ! 1893: VerC_R = RstLdEnVerniersC1_R; ! 1894: } else if( f_BLane_u32 == 17 ) { ! 1895: f_BLane_u32 = 4; ! 1896: MeasStat_R = MeasStatusC3_R; ! 1897: CalC_R = CalC3_R; ! 1898: VerC_R = RstLdEnVerniersC3_R; ! 1899: } else { ! 1900: f_BLane_u32 -= 12; ! 1901: MeasStat_R = MeasStatusC3_R; ! 1902: CalC_R = CalC3_R; ! 1903: VerC_R = RstLdEnVerniersC3_R; ! 1904: } ! 1905: ! 1906: shft = (uint32_t) 28 - ( f_BLane_u32 * 4 ); ! 1907: ! 1908: /* ! 1909: * start auto calibration logic & wait for completion ! 1910: */ ! 1911: or32_ci( MeasStat_R, IBIT(0) ); ! 1912: ! 1913: do { ! 1914: l_MeasStat_u32 = load32_ci( MeasStat_R ); ! 1915: } while( ( l_MeasStat_u32 & IBIT(0) ) == 1 ); ! 1916: ! 1917: l_CalConf0_u32 = CalConf0_V; ! 1918: store32_ci( CalConf0_R, l_CalConf0_u32 ); ! 1919: ! 1920: for( v = 0x000; v < (uint32_t) 0x100; v++ ) { ! 1921: store32_ci( VerC_R, ( v << 24 ) | ( v << 16 ) ); ! 1922: ! 1923: l_MemProgCntl_u32 = MemProgCntl_V; ! 1924: l_MemProgCntl_u32 |= ! 1925: ( (uint32_t) 0x00800000 >> f_Rank_u32 ); ! 1926: store32_ci( MemProgCntl_R, l_MemProgCntl_u32 ); ! 1927: ! 1928: do { ! 1929: l_MemProgCntl_u32 = load32_ci( MemProgCntl_R ); ! 1930: } while( ( l_MemProgCntl_u32 & IBIT(1) ) == 0 ); ! 1931: ! 1932: l_CalC_u32 = ( ( load32_ci( CalC_R ) >> shft ) & ! 1933: (uint32_t) 0xf ); ! 1934: ! 1935: if( l_CalC_u32 != (uint32_t) 0xa ) { ! 1936: v--; ! 1937: break; ! 1938: } ! 1939: ! 1940: } ! 1941: ! 1942: if( v == (uint32_t) 0x100 ) { ! 1943: v = (uint32_t) ~1; ! 1944: } ! 1945: ! 1946: return v; ! 1947: } ! 1948: #endif ! 1949: ! 1950: static uint32_t ! 1951: u4_RMDF_BLane( uint32_t f_Rank_u32, uint32_t f_BLane_u32 ) ! 1952: { ! 1953: static const uint32_t MemProgCntl_V = (uint32_t) 0x80000f00; ! 1954: static const uint32_t CalConf0_V = (uint32_t) 0x0000ac10; ! 1955: uint32_t l_MemProgCntl_u32; ! 1956: uint32_t l_CalConf0_u32; ! 1957: uint32_t l_MeasStat_u32; ! 1958: uint32_t l_CalC_u32; ! 1959: uint64_t MeasStat_R; ! 1960: uint64_t CalC_R; ! 1961: uint64_t VerC_R; ! 1962: uint32_t shft; ! 1963: uint32_t v; ! 1964: ! 1965: if( f_BLane_u32 < 4 ) { ! 1966: MeasStat_R = MeasStatusC0_R; ! 1967: CalC_R = CalC0_R; ! 1968: VerC_R = RstLdEnVerniersC0_R; ! 1969: } else if( f_BLane_u32 < 8 ) { ! 1970: f_BLane_u32 -= 4; ! 1971: MeasStat_R = MeasStatusC1_R; ! 1972: CalC_R = CalC1_R; ! 1973: VerC_R = RstLdEnVerniersC1_R; ! 1974: } else if( f_BLane_u32 < 12 ) { ! 1975: f_BLane_u32 -= 8; ! 1976: MeasStat_R = MeasStatusC2_R; ! 1977: CalC_R = CalC2_R; ! 1978: VerC_R = RstLdEnVerniersC2_R; ! 1979: } else if( f_BLane_u32 == 16 ) { ! 1980: f_BLane_u32 = 4; ! 1981: MeasStat_R = MeasStatusC1_R; ! 1982: CalC_R = CalC1_R; ! 1983: VerC_R = RstLdEnVerniersC1_R; ! 1984: } else if( f_BLane_u32 == 17 ) { ! 1985: f_BLane_u32 = 4; ! 1986: MeasStat_R = MeasStatusC3_R; ! 1987: CalC_R = CalC3_R; ! 1988: VerC_R = RstLdEnVerniersC3_R; ! 1989: } else { ! 1990: f_BLane_u32 -= 12; ! 1991: MeasStat_R = MeasStatusC3_R; ! 1992: CalC_R = CalC3_R; ! 1993: VerC_R = RstLdEnVerniersC3_R; ! 1994: } ! 1995: ! 1996: shft = (uint32_t) 28 - ( f_BLane_u32 * 4 ); ! 1997: ! 1998: /* ! 1999: * start auto calibration logic & wait for completion ! 2000: */ ! 2001: or32_ci( MeasStat_R, IBIT(0) ); ! 2002: ! 2003: do { ! 2004: l_MeasStat_u32 = load32_ci( MeasStat_R ); ! 2005: } while( ( l_MeasStat_u32 & IBIT(0) ) == 1 ); ! 2006: ! 2007: l_CalConf0_u32 = CalConf0_V; ! 2008: l_CalConf0_u32 |= ( f_BLane_u32 << 5 ); ! 2009: store32_ci( CalConf0_R, l_CalConf0_u32 ); ! 2010: ! 2011: for( v = 0x000; v < (uint32_t) 0x100; v++ ) { ! 2012: store32_ci( VerC_R, ( v << 24 ) | ( v << 16 ) ); ! 2013: ! 2014: l_MemProgCntl_u32 = MemProgCntl_V; ! 2015: l_MemProgCntl_u32 |= ! 2016: ( (uint32_t) 0x00800000 >> f_Rank_u32 ); ! 2017: store32_ci( MemProgCntl_R, l_MemProgCntl_u32 ); ! 2018: ! 2019: do { ! 2020: l_MemProgCntl_u32 = load32_ci( MemProgCntl_R ); ! 2021: } while( ( l_MemProgCntl_u32 & IBIT(1) ) == 0 ); ! 2022: ! 2023: l_CalC_u32 = ( ( load32_ci( CalC_R ) >> shft ) & ! 2024: (uint32_t) 0xf ); ! 2025: ! 2026: if( l_CalC_u32 != (uint32_t) 0xa ) { ! 2027: v--; ! 2028: break; ! 2029: } ! 2030: ! 2031: } ! 2032: ! 2033: if( v == (uint32_t) 0x100 ) { ! 2034: v = (uint32_t) ~1; ! 2035: } ! 2036: ! 2037: return v; ! 2038: } ! 2039: ! 2040: static int32_t ! 2041: u4_RMDF_Rank( uint32_t f_Rank_u32, ! 2042: uint32_t *f_Buf_pu32 ) ! 2043: { ! 2044: int32_t l_Err_pi32 = 0; ! 2045: uint32_t b; ! 2046: ! 2047: for( b = 0; ( b < MAX_BLANE ) && ( l_Err_pi32 == 0 ); b++ ) { ! 2048: f_Buf_pu32[b] = u4_RMDF_BLane( f_Rank_u32, b ); ! 2049: ! 2050: if( f_Buf_pu32[b] == (uint32_t) ~0 ) { ! 2051: f_Buf_pu32[b] = 0; ! 2052: l_Err_pi32++; ! 2053: } else if( f_Buf_pu32[b] == (uint32_t) ~1 ) { ! 2054: f_Buf_pu32[b] = (uint32_t) 0xff; ! 2055: l_Err_pi32++; ! 2056: } ! 2057: ! 2058: } ! 2059: ! 2060: return l_Err_pi32; ! 2061: } ! 2062: ! 2063: static int32_t ! 2064: u4_auto_calib_MemBus( auto_calib_t *f_ac_pt ) ! 2065: { ! 2066: uint32_t RdMacDly, RdMacCnt; ! 2067: uint32_t ResMuxDly, ResMuxCnt; ! 2068: uint32_t RdPipeDly; ! 2069: uint32_t l_Buf_pu32[MAX_DRANKS][MAX_BLANE]; ! 2070: uint32_t l_Rnk_pu32[MAX_DRANKS]; ! 2071: uint32_t l_Ver_u32; ! 2072: int32_t l_Err_i32; ! 2073: uint32_t bidx; ! 2074: uint32_t n, r, b; ! 2075: ! 2076: /* ! 2077: * read starting delays out of the MemBus register ! 2078: */ ! 2079: RdMacDly = ( load32_ci( MemBusCnfg_R ) >> 28 ) & 0xf; ! 2080: ResMuxDly = ( load32_ci( MemBusCnfg_R ) >> 24 ) & 0xf; ! 2081: ! 2082: /* ! 2083: * initialize ranks as not populated ! 2084: */ ! 2085: for( r = 0; r < MAX_DRANKS; r++ ) { ! 2086: l_Rnk_pu32[r] = 0; ! 2087: } ! 2088: ! 2089: /* ! 2090: * run through every possible delays of ! 2091: * RdMacDly, ResMuxDly & RdPipeDly until ! 2092: * the first working configuration is found ! 2093: */ ! 2094: RdPipeDly = 0; ! 2095: do { ! 2096: and32_ci( MemBusCnfg2_R, ~0x3 ); ! 2097: or32_ci( MemBusCnfg2_R, RdPipeDly ); ! 2098: ! 2099: RdMacCnt = RdMacDly; ! 2100: ResMuxCnt = ResMuxDly; ! 2101: ! 2102: /* ! 2103: * RdMacDly >= ResMuxDly ! 2104: */ ! 2105: do { ! 2106: and32_ci( MemBusCnfg_R, ( 1 << 24 ) - 1 ); ! 2107: or32_ci( MemBusCnfg_R, ( RdMacCnt << 28 ) | ! 2108: ( ResMuxCnt << 24 ) ); ! 2109: and32_ci( MemBusCnfg2_R, ( 1 << 28 ) - 1 ); ! 2110: or32_ci( MemBusCnfg2_R, ( RdMacCnt << 28 ) ); ! 2111: ! 2112: /* ! 2113: * check the current value for every installed ! 2114: * DIMM on each side for every bytelane ! 2115: */ ! 2116: l_Err_i32 = 0; ! 2117: for( n = 0; ! 2118: ( n < NUM_SLOTS ) && ! 2119: ( l_Err_i32 == 0 ); ! 2120: n += 2 ) { ! 2121: ! 2122: if( m_dimm[n].m_pop_u32 ) { ! 2123: /* ! 2124: * run through all 18 bytelanes of every rank ! 2125: */ ! 2126: for( r = n; ! 2127: ( r < n + m_dimm[n].m_rank_u32 ) && ! 2128: ( l_Err_i32 == 0 ); ! 2129: r++ ) { ! 2130: l_Rnk_pu32[r] = 1; ! 2131: ! 2132: l_Err_i32 = ! 2133: u4_RMDF_Rank( r, ! 2134: &l_Buf_pu32[r][0] ); ! 2135: } ! 2136: ! 2137: } ! 2138: ! 2139: } ! 2140: ! 2141: /* ! 2142: * decrementation before exit is wanted! ! 2143: */ ! 2144: RdMacCnt--; ! 2145: ResMuxCnt--; ! 2146: } while( ( ResMuxCnt > 0 ) && ! 2147: ( l_Err_i32 != 0 ) ); ! 2148: ! 2149: if( l_Err_i32 != 0 ) { ! 2150: RdPipeDly++; ! 2151: } ! 2152: ! 2153: } while( ( RdPipeDly < 4 ) && ! 2154: ( l_Err_i32 != 0 ) ); ! 2155: ! 2156: /* ! 2157: * if l_Err_pi32 == 0 the auto calibration passed ok ! 2158: */ ! 2159: if( l_Err_i32 != 0 ) { ! 2160: return RET_ERR; ! 2161: } ! 2162: ! 2163: /* ! 2164: * insert delay values into return struct ! 2165: */ ! 2166: and32_ci( MemBusCnfg_R, ( 1 << 24 ) - 1 ); ! 2167: or32_ci( MemBusCnfg_R, ( RdMacCnt << 28 ) | ! 2168: ( ResMuxCnt << 24 ) ); ! 2169: and32_ci( MemBusCnfg2_R, ( ( 1 << 28 ) - 1 ) & ~0x3 ); ! 2170: or32_ci( MemBusCnfg2_R, ( RdMacCnt << 28 ) | RdPipeDly ); ! 2171: ! 2172: f_ac_pt->m_MemBusCnfg_u32 = load32_ci( MemBusCnfg_R ); ! 2173: f_ac_pt->m_MemBusCnfg2_u32 = load32_ci( MemBusCnfg2_R ); ! 2174: ! 2175: /* ! 2176: * calculate the average vernier setting for the ! 2177: * bytelanes which share one vernier ! 2178: */ ! 2179: for( b = 0; b < MAX_BLANE - 2; b += 2 ) { ! 2180: n = 0; ! 2181: l_Ver_u32 = 0; ! 2182: ! 2183: for( r = 0; r < MAX_DRANKS; r++ ) { ! 2184: /* ! 2185: * calculation is done or populated ranks only ! 2186: */ ! 2187: if( l_Rnk_pu32[r] != 0 ) { ! 2188: /* ! 2189: * calculate average value ! 2190: */ ! 2191: l_Ver_u32 += l_Buf_pu32[r][b]; ! 2192: l_Ver_u32 += l_Buf_pu32[r][b+1]; ! 2193: n += 2; ! 2194: ! 2195: if( b == 4 ) { ! 2196: l_Ver_u32 += l_Buf_pu32[r][16]; ! 2197: n++; ! 2198: } else if( b == 12 ) { ! 2199: l_Ver_u32 += l_Buf_pu32[r][17]; ! 2200: n++; ! 2201: } ! 2202: ! 2203: } ! 2204: ! 2205: } ! 2206: ! 2207: /* ! 2208: * average the values ! 2209: */ ! 2210: l_Ver_u32 /= n; ! 2211: ! 2212: /* ! 2213: * set appropiate vernier register for ! 2214: * the current bytelane ! 2215: */ ! 2216: bidx = ( b >> 2 ); ! 2217: if( ( b & (uint32_t) 0x3 ) == 0 ) { ! 2218: l_Ver_u32 <<= 24; ! 2219: f_ac_pt->m_RstLdEnVerniers_pu32[bidx] = l_Ver_u32; ! 2220: } else { ! 2221: l_Ver_u32 <<= 16; ! 2222: f_ac_pt->m_RstLdEnVerniers_pu32[bidx] |= l_Ver_u32; ! 2223: } ! 2224: ! 2225: } ! 2226: ! 2227: return RET_OK; ! 2228: } ! 2229: ! 2230: static int32_t ! 2231: u4_auto_calib( auto_calib_t *f_ac_pt ) ! 2232: { ! 2233: uint32_t l_MemBusCnfg_S; ! 2234: uint32_t l_MemBusCnfg2_S; ! 2235: uint32_t l_RstLdEnVerniers_S[4]; ! 2236: int32_t l_Ret_i32; ! 2237: ! 2238: /* ! 2239: * save manipulated registers ! 2240: */ ! 2241: l_MemBusCnfg_S = load32_ci( MemBusCnfg_R ); ! 2242: l_MemBusCnfg2_S = load32_ci( MemBusCnfg2_R ); ! 2243: l_RstLdEnVerniers_S[0] = load32_ci( RstLdEnVerniersC0_R ); ! 2244: l_RstLdEnVerniers_S[1] = load32_ci( RstLdEnVerniersC1_R ); ! 2245: l_RstLdEnVerniers_S[2] = load32_ci( RstLdEnVerniersC2_R ); ! 2246: l_RstLdEnVerniers_S[3] = load32_ci( RstLdEnVerniersC3_R ); ! 2247: ! 2248: u4_auto_calib_init(); ! 2249: l_Ret_i32 = u4_auto_calib_MemBus( f_ac_pt ); ! 2250: ! 2251: /* ! 2252: * restore manipulated registers ! 2253: */ ! 2254: store32_ci( MemBusCnfg_R, l_MemBusCnfg_S ); ! 2255: store32_ci( MemBusCnfg2_R, l_MemBusCnfg2_S ); ! 2256: store32_ci( RstLdEnVerniersC0_R, l_RstLdEnVerniers_S[0] ); ! 2257: store32_ci( RstLdEnVerniersC1_R, l_RstLdEnVerniers_S[1] ); ! 2258: store32_ci( RstLdEnVerniersC2_R, l_RstLdEnVerniers_S[2] ); ! 2259: store32_ci( RstLdEnVerniersC3_R, l_RstLdEnVerniers_S[3] ); ! 2260: ! 2261: return l_Ret_i32; ! 2262: } ! 2263: ! 2264: static int32_t ! 2265: u4_checkeccerr( eccerror_t *f_ecc_pt ) ! 2266: { ! 2267: uint32_t l_val_u32; ! 2268: int32_t ret = RET_OK; ! 2269: ! 2270: l_val_u32 = load32_ci( MESR_R ); ! 2271: l_val_u32 >>= 29; ! 2272: ! 2273: if( ( l_val_u32 & (uint32_t) 0x7 ) != 0 ) { ! 2274: ! 2275: if( ( l_val_u32 & (uint32_t) 0x4 ) != 0 ) { ! 2276: /* UE */ ! 2277: ret = RET_ACERR_UE; ! 2278: } else if( ( l_val_u32 & (uint32_t) 0x1 ) != 0 ) { ! 2279: /* UEWT */ ! 2280: ret = RET_ACERR_UEWT; ! 2281: } else { ! 2282: /* CE */ ! 2283: ret = RET_ACERR_CE; ! 2284: } ! 2285: ! 2286: } ! 2287: ! 2288: f_ecc_pt->m_err_i32 = ret; ! 2289: ! 2290: l_val_u32 = load32_ci( MEAR1_R ); ! 2291: f_ecc_pt->m_uecnt_u32 = ( ( l_val_u32 >> 24 ) & (uint32_t) 0xff ); ! 2292: f_ecc_pt->m_cecnt_u32 = ( ( l_val_u32 >> 16 ) & (uint32_t) 0xff ); ! 2293: ! 2294: l_val_u32 = load32_ci( MEAR0_R ); ! 2295: f_ecc_pt->m_rank_u32 = ( ( l_val_u32 >> 29 ) & (uint32_t) 0x7 ); ! 2296: f_ecc_pt->m_col_u32 = ( ( l_val_u32 >> 18 ) & (uint32_t) 0x7ff ); ! 2297: f_ecc_pt->m_row_u32 = ( ( l_val_u32 >> 0 ) & (uint32_t) 0x7fff ); ! 2298: f_ecc_pt->m_bank_u32 = ( ( l_val_u32 >> 15 ) & (uint32_t) 0x7 ); ! 2299: ! 2300: return ret; ! 2301: } ! 2302: ! 2303: static uint32_t ! 2304: u4_CalcScrubEnd( void ) ! 2305: { ! 2306: uint64_t l_scrend_u64 = m_memsize_u64; ! 2307: ! 2308: /* ! 2309: * check for memory hole at 2GB ! 2310: */ ! 2311: if( l_scrend_u64 > _2GB ) { ! 2312: l_scrend_u64 += _2GB; ! 2313: } ! 2314: ! 2315: l_scrend_u64 -= 0x40; ! 2316: l_scrend_u64 /= 0x10; ! 2317: ! 2318: return( (uint32_t) l_scrend_u64 ); ! 2319: } ! 2320: ! 2321: static int32_t ! 2322: u4_Scrub( uint32_t f_scrub_u32, uint32_t f_pattern_u32, eccerror_t *f_eccerr_pt ) ! 2323: { ! 2324: uint32_t i; ! 2325: int32_t ret; ! 2326: ! 2327: /* ! 2328: * setup scrub parameters ! 2329: */ ! 2330: store32_ci( MSCR_R, 0 ); // stop scrub ! 2331: store32_ci( MSRSR_R, 0x0 ); // set start ! 2332: store32_ci( MSRER_R, u4_CalcScrubEnd() ); // set end ! 2333: store32_ci( MSPR_R, f_pattern_u32 ); // set pattern ! 2334: ! 2335: /* ! 2336: * clear out ECC error registers ! 2337: */ ! 2338: store32_ci( MEAR0_R, 0x0 ); ! 2339: store32_ci( MEAR1_R, 0x0 ); ! 2340: store32_ci( MESR_R, 0x0 ); ! 2341: ! 2342: /* ! 2343: * Setup Scrub Type ! 2344: */ ! 2345: store32_ci( MSCR_R, f_scrub_u32 ); ! 2346: ! 2347: if( f_scrub_u32 != BACKGROUND_SCRUB ) { ! 2348: /* ! 2349: * wait for scrub to complete ! 2350: */ ! 2351: do { ! 2352: progbar(); ! 2353: dly( 15000000 ); ! 2354: i = load32_ci( MSCR_R ); ! 2355: } while( ( i & f_scrub_u32 ) != 0 ); ! 2356: ! 2357: ret = u4_checkeccerr( f_eccerr_pt ); ! 2358: } else { ! 2359: ret = RET_OK; ! 2360: } ! 2361: ! 2362: return ret; ! 2363: } ! 2364: ! 2365: static eccerror_t ! 2366: u4_InitialScrub( void ) ! 2367: { ! 2368: eccerror_t l_eccerr_st[2]; ! 2369: int32_t l_err_i32[2] = { 0, 0 }; ! 2370: ! 2371: l_err_i32[0] = u4_Scrub( IMMEDIATE_SCRUB_WITH_FILL, 0x0, &l_eccerr_st[0] ); ! 2372: ! 2373: if( l_err_i32[0] >= -1 /*CE*/ ) { ! 2374: l_err_i32[1] = u4_Scrub( IMMEDIATE_SCRUB, 0x0, &l_eccerr_st[1] ); ! 2375: } ! 2376: ! 2377: if( l_err_i32[0] < l_err_i32[1] ) { ! 2378: return l_eccerr_st[0]; ! 2379: } else { ! 2380: return l_eccerr_st[1]; ! 2381: } ! 2382: ! 2383: } ! 2384: ! 2385: /* ! 2386: * RND: calculates Timer cycles from the given frequency ! 2387: * devided by the clock frequency. Values are rounded ! 2388: * up to the nearest integer value if the division is not even. ! 2389: */ ! 2390: #define RND( tXXX ) ( ( ( tXXX ) + tCK - 1 ) / tCK ) ! 2391: ! 2392: static void ! 2393: u4_MemInitSequence( uint32_t tRP, uint32_t tWR, uint32_t tRFC, uint32_t CL, ! 2394: uint32_t tCK, uint32_t TD ) ! 2395: { ! 2396: /* ! 2397: * DIMM init sequence ! 2398: */ ! 2399: static const uint32_t INI_SEQ[] = { ! 2400: 0xa0000400, 0x80020000, 0x80030000, 0x80010404, ! 2401: 0x8000100a, 0xa0000400, 0x90000000, 0x90000000, ! 2402: 0x8ff0100a, 0x80010784, 0x80010404, 0x00000000, ! 2403: 0x00000000, 0x00000000, 0x00000000, 0x00000000 ! 2404: }; ! 2405: ! 2406: uint32_t l_MemInit_u32; ! 2407: uint64_t r; ! 2408: uint32_t i; ! 2409: ! 2410: for( r = MemInit00_R, i = 0; r <= MemInit15_R; r += 0x10, i++ ) { ! 2411: l_MemInit_u32 = INI_SEQ[i]; ! 2412: ! 2413: switch( i ) { ! 2414: case 0: ! 2415: case 5: { ! 2416: l_MemInit_u32 |= ( ( RND( tRP ) - TD ) << 20 ); ! 2417: break; ! 2418: } ! 2419: case 3: { ! 2420: store32_ci( EMRSRegCntl_R, l_MemInit_u32 & ! 2421: (uint32_t) 0xffff ); ! 2422: break; ! 2423: } ! 2424: case 4: { ! 2425: l_MemInit_u32 |= IBIT(23); ! 2426: } ! 2427: case 8: { ! 2428: l_MemInit_u32 |= ( ( RND( tWR ) - 1 ) << 9 ); ! 2429: l_MemInit_u32 |= ( CL << 4 ); ! 2430: ! 2431: store32_ci( MRSRegCntl_R, l_MemInit_u32 & ! 2432: (uint32_t) 0xffff ); ! 2433: break; ! 2434: } ! 2435: case 6: ! 2436: case 7: { ! 2437: l_MemInit_u32 |= ( ( RND( tRFC ) - TD ) << 20 ); ! 2438: break; ! 2439: } ! 2440: ! 2441: } ! 2442: ! 2443: store32_ci( r, l_MemInit_u32 ); ! 2444: ! 2445: #ifdef U4_SHOW_REGS ! 2446: printf( "\r\nMemInit%02d (0x%04X): 0x%08X", i, (uint16_t) r, l_MemInit_u32 ); ! 2447: #endif ! 2448: } ! 2449: #ifdef U4_SHOW_REGS ! 2450: printf( "\r\n" ); ! 2451: #endif ! 2452: /* ! 2453: * Kick off memory init sequence & wait for completion ! 2454: */ ! 2455: store32_ci( MemProgCntl_R, IBIT(0) ); ! 2456: ! 2457: do { ! 2458: i = load32_ci( MemProgCntl_R ); ! 2459: } while( ( i & IBIT(1) ) == 0 ); ! 2460: ! 2461: } ! 2462: ! 2463: /* ! 2464: * static DIMM configuartion settings ! 2465: */ ! 2466: static reg_statics_t reg_statics_maui[NUM_SPEED_IDX] = { ! 2467: { /* 400 Mhz */ ! 2468: .RRMux = 1, ! 2469: .WRMux = 1, ! 2470: .WWMux = 1, ! 2471: .RWMux = 1, ! 2472: ! 2473: .MemRdQCnfg = 0x20020820, ! 2474: .MemWrQCnfg = 0x40041040, ! 2475: .MemQArb = 0x00000000, ! 2476: .MemRWArb = 0x30413cc0, ! 2477: ! 2478: .ODTCntl = 0x60000000, ! 2479: .IOPadCntl = 0x001a4000, ! 2480: .MemPhyModeCntl = 0x00000000, ! 2481: .OCDCalCntl = 0x00000000, ! 2482: .OCDCalCmd = 0x00000000, ! 2483: ! 2484: .CKDelayL = 0x34000000, ! 2485: .CKDelayU = 0x34000000, ! 2486: ! 2487: .MemBusCnfg = 0x00000050 | ! 2488: ( ( MAX_RMD << 28 ) | ! 2489: ( ( MAX_RMD - 2 ) << 24 ) ), ! 2490: ! 2491: .CAS1Dly0 = 0, ! 2492: .CAS1Dly1 = 0, ! 2493: ! 2494: .ByteWrClkDel = { ! 2495: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2496: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2497: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2498: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2499: 0x00000000, 0x00000000 ! 2500: }, ! 2501: .ReadStrobeDel = { ! 2502: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2503: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2504: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2505: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2506: 0x00000000, 0x00000000 ! 2507: } ! 2508: ! 2509: }, ! 2510: { /* 533 Mhz */ ! 2511: .RRMux = 1, ! 2512: .WRMux = 1, ! 2513: .WWMux = 1, ! 2514: .RWMux = 1, ! 2515: ! 2516: .MemRdQCnfg = 0x20020820, ! 2517: .MemWrQCnfg = 0x40041040, ! 2518: .MemQArb = 0x00000000, ! 2519: .MemRWArb = 0x30413cc0, ! 2520: ! 2521: .ODTCntl = 0x60000000, ! 2522: .IOPadCntl = 0x001a4000, ! 2523: .MemPhyModeCntl = 0x00000000, ! 2524: .OCDCalCntl = 0x00000000, ! 2525: .OCDCalCmd = 0x00000000, ! 2526: ! 2527: .CKDelayL = 0x18000000, ! 2528: .CKDelayU = 0x18000000, ! 2529: ! 2530: .MemBusCnfg = 0x00002070 | ! 2531: ( ( MAX_RMD << 28 ) | ! 2532: ( ( MAX_RMD - 3 ) << 24 ) ), ! 2533: ! 2534: .CAS1Dly0 = 0, ! 2535: .CAS1Dly1 = 0, ! 2536: ! 2537: .ByteWrClkDel = { ! 2538: ! 2539: 0x12000000, 0x12000000, 0x12000000 , 0x12000000, ! 2540: 0x12000000, 0x12000000, 0x12000000 , 0x12000000, ! 2541: 0x12000000, 0x12000000, 0x12000000 , 0x12000000, ! 2542: 0x12000000, 0x12000000, 0x12000000 , 0x12000000, ! 2543: 0x12000000, 0x12000000 ! 2544: }, ! 2545: .ReadStrobeDel = { ! 2546: 0x00000000, 0x00000000, 0x00000000 , 0x00000000, ! 2547: 0x00000000, 0x00000000, 0x00000000 , 0x00000000, ! 2548: 0x00000000, 0x00000000, 0x00000000 , 0x00000000, ! 2549: 0x00000000, 0x00000000, 0x00000000 , 0x00000000, ! 2550: 0x00000000, 0x00000000 ! 2551: } ! 2552: ! 2553: }, ! 2554: { /* 667 Mhz */ ! 2555: .RRMux = 1, ! 2556: .WRMux = 1, ! 2557: .WWMux = 1, ! 2558: .RWMux = 3, ! 2559: ! 2560: .MemRdQCnfg = 0x20020820, ! 2561: .MemWrQCnfg = 0x40041040, ! 2562: .MemQArb = 0x00000000, ! 2563: .MemRWArb = 0x30413cc0, ! 2564: ! 2565: .ODTCntl = 0x60000000, ! 2566: .IOPadCntl = 0x001a4000, ! 2567: .MemPhyModeCntl = 0x00000000, ! 2568: .OCDCalCntl = 0x00000000, ! 2569: .OCDCalCmd = 0x00000000, ! 2570: ! 2571: .CKDelayL = 0x0a000000, ! 2572: .CKDelayU = 0x0a000000, ! 2573: ! 2574: .MemBusCnfg = 0x000040a0 | ! 2575: ( ( MAX_RMD << 28 ) | ! 2576: ( ( MAX_RMD - 3 ) << 24 ) ), ! 2577: ! 2578: .CAS1Dly0 = 2, ! 2579: .CAS1Dly1 = 2, ! 2580: ! 2581: .ByteWrClkDel = { ! 2582: ! 2583: 0x12000000, 0x12000000, 0x12000000, 0x12000000, ! 2584: 0x12000000, 0x12000000, 0x12000000, 0x12000000, ! 2585: 0x12000000, 0x12000000, 0x12000000, 0x12000000, ! 2586: 0x12000000, 0x12000000, 0x12000000, 0x12000000, ! 2587: 0x12000000, 0x12000000 ! 2588: /* ! 2589: 0x31000000, 0x31000000, 0x31000000, 0x31000000, ! 2590: 0x31000000, 0x31000000, 0x31000000, 0x31000000, ! 2591: 0x31000000, 0x31000000, 0x31000000, 0x31000000, ! 2592: 0x31000000, 0x31000000, 0x31000000, 0x31000000, ! 2593: 0x31000000, 0x31000000 ! 2594: */ ! 2595: }, ! 2596: .ReadStrobeDel = { ! 2597: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2598: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2599: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2600: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2601: 0x00000000, 0x00000000 ! 2602: } ! 2603: ! 2604: } ! 2605: }; ! 2606: ! 2607: static reg_statics_t reg_statics_bimini[NUM_SPEED_IDX] = { ! 2608: { /* 400 Mhz */ ! 2609: .RRMux = 2, ! 2610: .WRMux = 2, ! 2611: .WWMux = 2, ! 2612: .RWMux = 2, ! 2613: ! 2614: .MemRdQCnfg = 0x20020820, ! 2615: .MemWrQCnfg = 0x40041040, ! 2616: .MemQArb = 0x00000000, ! 2617: .MemRWArb = 0x30413cc0, ! 2618: ! 2619: .ODTCntl = 0x40000000, ! 2620: .IOPadCntl = 0x001a4000, ! 2621: .MemPhyModeCntl = 0x00000000, ! 2622: .OCDCalCntl = 0x00000000, ! 2623: .OCDCalCmd = 0x00000000, ! 2624: ! 2625: .CKDelayL = 0x00000000, ! 2626: .CKDelayU = 0x28000000, ! 2627: ! 2628: .MemBusCnfg = 0x00552070 | ! 2629: ( ( MAX_RMD << 28 ) | ! 2630: ( ( MAX_RMD - 2 ) << 24 ) ), ! 2631: ! 2632: .CAS1Dly0 = 0, ! 2633: .CAS1Dly1 = 0, ! 2634: ! 2635: .ByteWrClkDel = { ! 2636: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2637: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2638: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2639: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2640: 0x00000000, 0x00000000 ! 2641: }, ! 2642: .ReadStrobeDel = { ! 2643: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2644: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2645: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2646: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2647: 0x00000000, 0x00000000 ! 2648: } ! 2649: ! 2650: }, ! 2651: { /* 533 Mhz */ ! 2652: .RRMux = 3, ! 2653: .WRMux = 3, ! 2654: .WWMux = 3, ! 2655: .RWMux = 3, ! 2656: ! 2657: .MemRdQCnfg = 0x20020820, ! 2658: .MemWrQCnfg = 0x40041040, ! 2659: .MemQArb = 0x00000000, ! 2660: .MemRWArb = 0x30413cc0, ! 2661: ! 2662: .ODTCntl = 0x40000000, ! 2663: .IOPadCntl = 0x001a4000, ! 2664: .MemPhyModeCntl = 0x00000000, ! 2665: .OCDCalCntl = 0x00000000, ! 2666: .OCDCalCmd = 0x00000000, ! 2667: ! 2668: .CKDelayL = 0x00000000, ! 2669: .CKDelayU = 0x20000000, ! 2670: ! 2671: .MemBusCnfg = 0x00644190 | ! 2672: ( ( MAX_RMD << 28 ) | ! 2673: ( ( MAX_RMD - 3 ) << 24 ) ), ! 2674: ! 2675: .CAS1Dly0 = 2, ! 2676: .CAS1Dly1 = 2, ! 2677: ! 2678: .ByteWrClkDel = { ! 2679: 0x14000000, 0x14000000, 0x14000000, 0x14000000, ! 2680: 0x14000000, 0x14000000, 0x14000000, 0x14000000, ! 2681: 0x14000000, 0x14000000, 0x14000000, 0x14000000, ! 2682: 0x14000000, 0x14000000, 0x14000000, 0x14000000, ! 2683: 0x14000000, 0x14000000 ! 2684: }, ! 2685: .ReadStrobeDel = { ! 2686: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2687: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2688: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2689: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2690: 0x00000000, 0x00000000 ! 2691: } ! 2692: ! 2693: }, ! 2694: { /* 667 Mhz */ ! 2695: .RRMux = 3, ! 2696: .WRMux = 3, ! 2697: .WWMux = 3, ! 2698: .RWMux = 3, ! 2699: ! 2700: .MemRdQCnfg = 0x20020820, ! 2701: .MemWrQCnfg = 0x40041040, ! 2702: .MemQArb = 0x00000000, ! 2703: .MemRWArb = 0x30413cc0, ! 2704: ! 2705: .ODTCntl = 0x40000000, ! 2706: .IOPadCntl = 0x001a4000, ! 2707: .MemPhyModeCntl = 0x00000000, ! 2708: .OCDCalCntl = 0x00000000, ! 2709: .OCDCalCmd = 0x00000000, ! 2710: ! 2711: .CKDelayL = 0x00000000, ! 2712: .CKDelayU = 0x00000000, ! 2713: ! 2714: .MemBusCnfg = 0x00666270 | ! 2715: ( ( MAX_RMD << 28 ) | ! 2716: ( ( MAX_RMD - 3 ) << 24 ) ), ! 2717: ! 2718: .CAS1Dly0 = 2, ! 2719: .CAS1Dly1 = 2, ! 2720: ! 2721: .ByteWrClkDel = { ! 2722: 0x14000000, 0x14000000, 0x14000000, 0x14000000, ! 2723: 0x14000000, 0x14000000, 0x14000000, 0x14000000, ! 2724: 0x14000000, 0x14000000, 0x14000000, 0x14000000, ! 2725: 0x14000000, 0x14000000, 0x14000000, 0x14000000, ! 2726: 0x14000000, 0x14000000 ! 2727: }, ! 2728: .ReadStrobeDel = { ! 2729: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2730: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2731: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2732: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2733: 0x00000000, 0x00000000 ! 2734: } ! 2735: ! 2736: } ! 2737: }; ! 2738: ! 2739: static reg_statics_t reg_statics_kauai[NUM_SPEED_IDX] = { ! 2740: { /* 400 Mhz */ ! 2741: .RRMux = 0, ! 2742: .WRMux = 0, ! 2743: .WWMux = 0, ! 2744: .RWMux = 0, ! 2745: ! 2746: .MemRdQCnfg = 0, ! 2747: .MemWrQCnfg = 0, ! 2748: .MemQArb = 0, ! 2749: .MemRWArb = 0, ! 2750: ! 2751: .ODTCntl = 0, ! 2752: .IOPadCntl = 0, ! 2753: .MemPhyModeCntl = 0, ! 2754: .OCDCalCntl = 0, ! 2755: .OCDCalCmd = 0, ! 2756: ! 2757: .CKDelayL = 0, ! 2758: .CKDelayU = 0, ! 2759: ! 2760: .MemBusCnfg = 0, ! 2761: ! 2762: .CAS1Dly0 = 0, ! 2763: .CAS1Dly1 = 0, ! 2764: ! 2765: .ByteWrClkDel = { ! 2766: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2767: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2768: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2769: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2770: 0x00000000, 0x00000000 ! 2771: }, ! 2772: .ReadStrobeDel = { ! 2773: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2774: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2775: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2776: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2777: 0x00000000, 0x00000000 ! 2778: } ! 2779: ! 2780: }, ! 2781: { /* 533 Mhz */ ! 2782: .RRMux = 0, ! 2783: .WRMux = 0, ! 2784: .WWMux = 0, ! 2785: .RWMux = 0, ! 2786: ! 2787: .MemRdQCnfg = 0, ! 2788: .MemWrQCnfg = 0, ! 2789: .MemQArb = 0, ! 2790: .MemRWArb = 0, ! 2791: ! 2792: .ODTCntl = 0, ! 2793: .IOPadCntl = 0, ! 2794: .MemPhyModeCntl = 0, ! 2795: .OCDCalCntl = 0, ! 2796: .OCDCalCmd = 0, ! 2797: ! 2798: .CKDelayL = 0, ! 2799: .CKDelayU = 0, ! 2800: ! 2801: .MemBusCnfg = 0, ! 2802: ! 2803: .CAS1Dly0 = 0, ! 2804: .CAS1Dly1 = 0, ! 2805: ! 2806: .ByteWrClkDel = { ! 2807: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2808: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2809: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2810: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2811: 0x00000000, 0x00000000 ! 2812: }, ! 2813: .ReadStrobeDel = { ! 2814: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2815: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2816: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2817: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2818: 0x00000000, 0x00000000 ! 2819: } ! 2820: ! 2821: }, ! 2822: { /* 667 Mhz */ ! 2823: .RRMux = 0, ! 2824: .WRMux = 0, ! 2825: .WWMux = 0, ! 2826: .RWMux = 0, ! 2827: ! 2828: .MemRdQCnfg = 0, ! 2829: .MemWrQCnfg = 0, ! 2830: .MemQArb = 0, ! 2831: .MemRWArb = 0, ! 2832: ! 2833: .ODTCntl = 0, ! 2834: .IOPadCntl = 0, ! 2835: .MemPhyModeCntl = 0, ! 2836: .OCDCalCntl = 0, ! 2837: .OCDCalCmd = 0, ! 2838: ! 2839: .CKDelayL = 0, ! 2840: .CKDelayU = 0, ! 2841: ! 2842: .MemBusCnfg = 0, ! 2843: ! 2844: .CAS1Dly0 = 0, ! 2845: .CAS1Dly1 = 0, ! 2846: ! 2847: .ByteWrClkDel = { ! 2848: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2849: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2850: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2851: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2852: 0x00000000, 0x00000000 ! 2853: }, ! 2854: .ReadStrobeDel = { ! 2855: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2856: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2857: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2858: 0x00000000, 0x00000000, 0x00000000, 0x00000000, ! 2859: 0x00000000, 0x00000000 ! 2860: } ! 2861: ! 2862: } ! 2863: }; ! 2864: ! 2865: static int32_t ! 2866: u4_start( eccerror_t *f_ecc_pt ) ! 2867: { ! 2868: /* ! 2869: * maximum runs for auto calibration ! 2870: */ ! 2871: static const uint32_t MAX_ACERR = (uint32_t) 5; ! 2872: ! 2873: /* ! 2874: * fixed u4/DIMM timer/timing values for calculation ! 2875: */ ! 2876: static const uint32_t TD = (uint32_t) 2; // u4 delay cycles for loading a timer ! 2877: static const uint32_t AL = (uint32_t) 0; // additional latency (fix) ! 2878: static const uint32_t BL = (uint32_t) 4; // burst length (fix) ! 2879: ! 2880: uint32_t SPEED = m_gendimm.m_speed_pu32[m_dclidx_u32]; ! 2881: uint32_t CL = m_gendimm.m_clval_pu32[m_dclidx_u32]; ! 2882: uint32_t RL = AL + CL; ! 2883: uint32_t WL = RL - 1; ! 2884: uint32_t tCK = m_gendimm.m_tCK_pu32[m_dclidx_u32]; ! 2885: uint32_t tRAS = m_gendimm.m_tRAS_u32; ! 2886: uint32_t tRTP = m_gendimm.m_tRTP_u32; ! 2887: uint32_t tRP = m_gendimm.m_tRP_u32; ! 2888: uint32_t tWR = m_gendimm.m_tWR_u32; ! 2889: uint32_t tRRD = m_gendimm.m_tRRD_u32; ! 2890: uint32_t tRC = m_gendimm.m_tRC_u32; ! 2891: uint32_t tRCD = m_gendimm.m_tRCD_u32; ! 2892: uint32_t tWTR = m_gendimm.m_tWTR_u32; ! 2893: uint32_t tRFC = m_gendimm.m_tRFC_u32; ! 2894: uint32_t tREF = m_gendimm.m_tREF_u32; ! 2895: ! 2896: reg_statics_t *rst = 0; ! 2897: ! 2898: uint32_t l_RAS0_u32; ! 2899: uint32_t l_RAS1_u32; ! 2900: uint32_t l_CAS0_u32; ! 2901: uint32_t l_CAS1_u32; ! 2902: uint32_t l_MemRfshCntl_u32; ! 2903: uint32_t l_UsrCnfg_u32; ! 2904: uint32_t l_DmCnfg_u32; ! 2905: ! 2906: uint32_t l_MemArbWt_u32; ! 2907: uint32_t l_MemRWArb_u32; ! 2908: uint32_t l_MemBusCnfg_u32; ! 2909: ! 2910: auto_calib_t l_ac_st; ! 2911: int32_t l_ac_i32; ! 2912: uint32_t l_acerr_i32; ! 2913: uint32_t sidx; ! 2914: uint32_t i, j, t0, t1; ! 2915: ! 2916: /* ! 2917: * set index for different 400/533/667 Mhz setup ! 2918: */ ! 2919: switch( SPEED ) { ! 2920: case 400: ! 2921: case 533: ! 2922: case 667: { ! 2923: sidx = SPEED; ! 2924: sidx -= 400; ! 2925: sidx /= 133; ! 2926: break; ! 2927: } ! 2928: ! 2929: default: { ! 2930: #ifdef U4_DEBUG2 ! 2931: printf( "\r\n-> DIMM speed of %03u not supported\r\n", ! 2932: m_gendimm.m_speed_pu32[m_dclidx_u32] ); ! 2933: #endif ! 2934: return RET_ERR; ! 2935: } ! 2936: ! 2937: } ! 2938: ! 2939: /* ! 2940: * setup pointer to the static register settings ! 2941: */ ! 2942: if( IS_MAUI ) { ! 2943: rst = ®_statics_maui[sidx]; ! 2944: } else if( IS_BIMINI ) { ! 2945: rst = ®_statics_bimini[sidx]; ! 2946: } else if( IS_KAUAI ) { ! 2947: rst = ®_statics_kauai[sidx]; ! 2948: } ! 2949: ! 2950: /* ! 2951: * Switch off Fast Path by default for all DIMMs ! 2952: * running with more than 400Mhz ! 2953: */ ! 2954: if( SPEED == 400 ) { ! 2955: or32_ci( APIMemRdCfg_R, IBIT(30) ); ! 2956: #ifdef U4_INFO ! 2957: printf( " [fastpath : ON]\r\n" ); ! 2958: #endif ! 2959: } else { ! 2960: and32_ci( APIMemRdCfg_R, ~IBIT(30) ); ! 2961: #ifdef U4_INFO ! 2962: printf( " [fastpath : OFF]\r\n" ); ! 2963: #endif ! 2964: } ! 2965: ! 2966: ! 2967: #ifdef U4_INFO ! 2968: printf( " [register setup : ]" ); ! 2969: #endif ! 2970: ! 2971: /* ! 2972: * setup RAS/CAS timers2 ! 2973: * NOTE: subtract TD from all values because of the delay ! 2974: * caused by reloading timers (see spec) ! 2975: */ ! 2976: ! 2977: /* ! 2978: * RAS Timer 0 ! 2979: */ ! 2980: // TiAtP = RND(tRAS) -> RAS0[0:4] ! 2981: l_RAS0_u32 = ( ( RND( tRAS ) - TD ) << 27 ); ! 2982: // TiRtP = AL + BL/2 - 2 + RND(tRTP) -> RAS01[5:9] ! 2983: l_RAS0_u32 |= ( ( AL + BL/2 - 2 + RND( tRTP ) - TD ) << 22 ); ! 2984: // TiWtP = WL + BL/2 + RND(tWR) -> RAS0[10:14] ! 2985: l_RAS0_u32 |= ( ( WL + BL/2 + RND( tWR ) - TD ) << 17 ); ! 2986: // TiPtA = RND(tRP) -> RAS0[15:19] ! 2987: l_RAS0_u32 |= ( ( RND( tRP ) - TD ) << 12 ); ! 2988: // TiPAtA = RND(tRP) or ! 2989: // RND(tRP) + 1 for 8 bank devices -> RAS0[20:24] ! 2990: if( m_gendimm.m_bankcnt_u32 <= 4 ) { ! 2991: l_RAS0_u32 |= ( ( RND( tRP ) - TD ) << 7 ); ! 2992: } else { ! 2993: l_RAS0_u32 |= ( ( RND( tRP ) + 1 - TD ) << 7 ); ! 2994: } ! 2995: ! 2996: /* ! 2997: * RAS Timer 1 ! 2998: */ ! 2999: // TiRAPtA = AL + BL/2 - 2 + RND(tRTP + tRP) -> RAS1[0:4] ! 3000: l_RAS1_u32 = ( ( AL + BL/2 - 2 + RND( tRTP + tRP ) - TD ) << 27 ); ! 3001: // TiWAPtA = CL + AL + BL/2 - 1 + RND(tWR + tRP) -> RAS1[5:9] ! 3002: l_RAS1_u32 |= ( ( CL + AL + BL/2 - 1 + RND( tWR + tRP ) - TD ) << 22 ); ! 3003: // TiAtARk = tRRD -> RAS1[10:14] ! 3004: l_RAS1_u32 |= ( ( RND( tRRD ) - TD ) << 17 ); ! 3005: // TiAtABk = tRC -> RAS1[15:19] ! 3006: l_RAS1_u32 |= ( ( RND( tRC ) - TD ) << 12 ); ! 3007: // TiAtRW = tRCD -> RAS1[20:24] ! 3008: l_RAS1_u32 |= ( ( RND( tRCD ) - TD ) << 7 ); ! 3009: // TiSAtARk Win = 4 * tRRD + 2 -> RAS1[25:29] ! 3010: l_RAS1_u32 |= ( ( RND( 4 * tRRD ) + 2 - TD ) << 2 ); ! 3011: ! 3012: /* ! 3013: * CAS Timer 0 ! 3014: */ ! 3015: // TiRtRRk = BL/2 -> CAS0[0:4] ! 3016: l_CAS0_u32 = ( ( BL/2 - TD ) << 27 ); ! 3017: // TiRtRDm = BL/2 + 1 -> CAS0[5:9] ! 3018: l_CAS0_u32 |= ( ( BL/2 + 1 - TD ) << 22 ); ! 3019: // TiRtRSy = BL/2 + RRMux -> CAS0[10:14] ! 3020: l_CAS0_u32 |= ( ( BL/2 + rst->RRMux - TD ) << 17 ); ! 3021: // TiWtRRk = CL - 1 + BL/2 + tWTR ->CAS0[15:19] ! 3022: l_CAS0_u32 |= ( ( CL - 1 + BL/2 + RND( tWTR ) - TD ) << 12 ); ! 3023: // TiWtRDm = BL/2 + 1 -> CAS0[20:24] ! 3024: l_CAS0_u32 |= ( ( BL/2 + 1 - TD ) << 7 ); ! 3025: // TiWtRSy = BL/2 + WRMux -> CAS0[25:29] ! 3026: l_CAS0_u32 |= ( ( BL/2 + rst->WRMux - TD ) << 2 ); ! 3027: ! 3028: /* ! 3029: * CAS Timer 1 ! 3030: */ ! 3031: // TiWtWRk = BL/2 -> CAS1[0:4] ! 3032: l_CAS1_u32 = ( ( BL/2 - TD ) << 27 ); ! 3033: // TiWtWDm = BL/2 + 1 -> CAS1[5:9] ! 3034: l_CAS1_u32 |= ( ( BL/2 + 1 - TD ) << 22 ); ! 3035: // TiWtWSy = BL/2 + WWMux -> CAS1[10:14] ! 3036: l_CAS1_u32 |= ( ( BL/2 + rst->WWMux - TD ) << 17 ); ! 3037: // TiRtWRk = BL/2 + 2 -> CAS1[15:19] ! 3038: l_CAS1_u32 |= ( ( BL/2 + 2 + rst->CAS1Dly0 - TD ) << 12 ); ! 3039: // TiRtWDm = BL/2 + 2 -> CAS1[20:24] ! 3040: l_CAS1_u32 |= ( ( BL/2 + 2 + rst->CAS1Dly1 - TD ) << 7 ); ! 3041: // TiRtWSy = BL/2 + RWMux + 1 -> CAS1[25:29] ! 3042: l_CAS1_u32 |= ( ( BL/2 + rst->RWMux + 1 - TD ) << 2 ); ! 3043: ! 3044: store32_ci( RASTimer0_R, l_RAS0_u32 ); ! 3045: store32_ci( RASTimer1_R, l_RAS1_u32 ); ! 3046: store32_ci( CASTimer0_R, l_CAS0_u32 ); ! 3047: store32_ci( CASTimer1_R, l_CAS1_u32 ); ! 3048: ! 3049: /* ! 3050: * Mem Refresh Control register ! 3051: */ ! 3052: l_MemRfshCntl_u32 = ( ( ( tREF / tCK ) / 16 ) << 23 ); ! 3053: l_MemRfshCntl_u32 |= ( ( RND( tRFC ) - TD ) << 8 ); ! 3054: store32_ci( MemRfshCntl_R, l_MemRfshCntl_u32 ); ! 3055: ! 3056: /* ! 3057: * setup DmXCnfg registers ! 3058: */ ! 3059: store32_ci( Dm0Cnfg_R, (uint32_t) 0x0 ); ! 3060: store32_ci( Dm1Cnfg_R, (uint32_t) 0x0 ); ! 3061: store32_ci( Dm2Cnfg_R, (uint32_t) 0x0 ); ! 3062: store32_ci( Dm3Cnfg_R, (uint32_t) 0x0 ); ! 3063: ! 3064: /* ! 3065: * create DmCnfg & UsrCnfg values out of group data ! 3066: */ ! 3067: l_UsrCnfg_u32 = 0; ! 3068: for( i = 0; i < m_dgrcnt_u32; i++ ) { ! 3069: l_DmCnfg_u32 = ( m_dgrptr[i]->m_add2g_u32 << 27 ); ! 3070: l_DmCnfg_u32 |= ( m_dgrptr[i]->m_sub2g_u32 << 19 ); ! 3071: l_DmCnfg_u32 |= ( m_dgrptr[i]->m_memmd_u32 << 12 ); ! 3072: l_DmCnfg_u32 |= ( m_dgrptr[i]->m_start_u32 << 3 ); ! 3073: l_DmCnfg_u32 |= ( m_dgrptr[i]->m_ss_u32 << 1 ); ! 3074: l_DmCnfg_u32 |= IBIT(31); // enable bit ! 3075: ! 3076: /* ! 3077: * write value into DmXCnfg registers ! 3078: */ ! 3079: for( j = 0; j < m_dgrptr[i]->m_dcnt_u32; j++ ) { ! 3080: t0 = m_dgrptr[i]->m_dptr[j]->m_bank_u32; ! 3081: t1 = Dm0Cnfg_R + 0x10 * t0; ! 3082: ! 3083: if( load32_ci( t1 ) == 0 ) { ! 3084: store32_ci( t1, l_DmCnfg_u32 ); ! 3085: l_UsrCnfg_u32 |= ! 3086: ( m_dgrptr[i]->m_csmode_u32 << ( 30 - 2 * t0 ) ); ! 3087: } ! 3088: ! 3089: } ! 3090: ! 3091: } ! 3092: ! 3093: /* ! 3094: * setup UsrCnfg register ! 3095: *- cs mode is selected above ! 3096: *- Interleave on L2 cache line ! 3097: *- Usually closed page policy ! 3098: */ ! 3099: l_UsrCnfg_u32 |= IBIT(8); // interleave on L2 cache line ! 3100: l_UsrCnfg_u32 &= ~IBIT(9); // usually closed ! 3101: l_UsrCnfg_u32 |= IBIT(10); ! 3102: store32_ci( UsrCnfg_R, l_UsrCnfg_u32 ); ! 3103: ! 3104: /* ! 3105: * Memory Arbiter Weight Register ! 3106: */ ! 3107: // CohWt -> MemAWt[0:1] ! 3108: l_MemArbWt_u32 = ( (uint32_t) 1 << 30 ); ! 3109: // NCohWt -> MemAWt[2:3] ! 3110: l_MemArbWt_u32 |= ( (uint32_t) 1 << 28 ); ! 3111: // ScrbWt -> MemAWt[4:5] ! 3112: l_MemArbWt_u32 |= ( (uint32_t) 0 << 26 ); ! 3113: store32_ci( MemArbWt_R, l_MemArbWt_u32 ); ! 3114: ! 3115: /* ! 3116: * misc fixed register setup ! 3117: */ ! 3118: store32_ci( ODTCntl_R, rst->ODTCntl ); ! 3119: store32_ci( IOPadCntl_R, rst->IOPadCntl ); ! 3120: store32_ci( MemPhyModeCntl_R, rst->MemPhyModeCntl ); ! 3121: store32_ci( OCDCalCntl_R, rst->OCDCalCntl ); ! 3122: store32_ci( OCDCalCmd_R, rst->OCDCalCmd ); ! 3123: ! 3124: /* ! 3125: * CK Delay registers ! 3126: */ ! 3127: store32_ci( CKDelayL_R, rst->CKDelayL ); ! 3128: store32_ci( CKDelayU_R, rst->CKDelayU ); ! 3129: ! 3130: /* ! 3131: * read/write strobe delays ! 3132: */ ! 3133: store32_ci( ByteWrClkDelC0B00_R, rst->ByteWrClkDel[ 0] ); ! 3134: store32_ci( ByteWrClkDelC0B01_R, rst->ByteWrClkDel[ 1] ); ! 3135: store32_ci( ByteWrClkDelC0B02_R, rst->ByteWrClkDel[ 2] ); ! 3136: store32_ci( ByteWrClkDelC0B03_R, rst->ByteWrClkDel[ 3] ); ! 3137: store32_ci( ByteWrClkDelC0B04_R, rst->ByteWrClkDel[ 4] ); ! 3138: store32_ci( ByteWrClkDelC0B05_R, rst->ByteWrClkDel[ 5] ); ! 3139: store32_ci( ByteWrClkDelC0B06_R, rst->ByteWrClkDel[ 6] ); ! 3140: store32_ci( ByteWrClkDelC0B07_R, rst->ByteWrClkDel[ 7] ); ! 3141: store32_ci( ByteWrClkDelC0B16_R, rst->ByteWrClkDel[16] ); ! 3142: store32_ci( ByteWrClkDelC0B08_R, rst->ByteWrClkDel[ 8] ); ! 3143: store32_ci( ByteWrClkDelC0B09_R, rst->ByteWrClkDel[ 9] ); ! 3144: store32_ci( ByteWrClkDelC0B10_R, rst->ByteWrClkDel[10] ); ! 3145: store32_ci( ByteWrClkDelC0B11_R, rst->ByteWrClkDel[11] ); ! 3146: store32_ci( ByteWrClkDelC0B12_R, rst->ByteWrClkDel[12] ); ! 3147: store32_ci( ByteWrClkDelC0B13_R, rst->ByteWrClkDel[13] ); ! 3148: store32_ci( ByteWrClkDelC0B14_R, rst->ByteWrClkDel[14] ); ! 3149: store32_ci( ByteWrClkDelC0B15_R, rst->ByteWrClkDel[15] ); ! 3150: store32_ci( ByteWrClkDelC0B17_R, rst->ByteWrClkDel[17] ); ! 3151: store32_ci( ReadStrobeDelC0B00_R, rst->ReadStrobeDel[ 0] ); ! 3152: store32_ci( ReadStrobeDelC0B01_R, rst->ReadStrobeDel[ 1] ); ! 3153: store32_ci( ReadStrobeDelC0B02_R, rst->ReadStrobeDel[ 2] ); ! 3154: store32_ci( ReadStrobeDelC0B03_R, rst->ReadStrobeDel[ 3] ); ! 3155: store32_ci( ReadStrobeDelC0B04_R, rst->ReadStrobeDel[ 4] ); ! 3156: store32_ci( ReadStrobeDelC0B05_R, rst->ReadStrobeDel[ 5] ); ! 3157: store32_ci( ReadStrobeDelC0B06_R, rst->ReadStrobeDel[ 6] ); ! 3158: store32_ci( ReadStrobeDelC0B07_R, rst->ReadStrobeDel[ 7] ); ! 3159: store32_ci( ReadStrobeDelC0B16_R, rst->ReadStrobeDel[16] ); ! 3160: store32_ci( ReadStrobeDelC0B08_R, rst->ReadStrobeDel[ 8] ); ! 3161: store32_ci( ReadStrobeDelC0B09_R, rst->ReadStrobeDel[ 9] ); ! 3162: store32_ci( ReadStrobeDelC0B10_R, rst->ReadStrobeDel[10] ); ! 3163: store32_ci( ReadStrobeDelC0B11_R, rst->ReadStrobeDel[11] ); ! 3164: store32_ci( ReadStrobeDelC0B12_R, rst->ReadStrobeDel[12] ); ! 3165: store32_ci( ReadStrobeDelC0B13_R, rst->ReadStrobeDel[13] ); ! 3166: store32_ci( ReadStrobeDelC0B14_R, rst->ReadStrobeDel[14] ); ! 3167: store32_ci( ReadStrobeDelC0B15_R, rst->ReadStrobeDel[15] ); ! 3168: store32_ci( ReadStrobeDelC0B17_R, rst->ReadStrobeDel[17] ); ! 3169: ! 3170: /* ! 3171: * Mem Bus Configuration ! 3172: * initial setup used in auto calibration ! 3173: * final values will be written after ! 3174: * auto calibration has finished ! 3175: */ ! 3176: l_MemBusCnfg_u32 = rst->MemBusCnfg; ! 3177: ! 3178: /* values calculation has been dropped, static values are used instead ! 3179: // WdbRqDly = 2 * (CL - 3) (registered DIMMs) -> MBC[16:19] ! 3180: l_MemBusCnfg_u32 += ( ( 2 * ( CL - 3 ) ) << 12 ); ! 3181: // RdOEOnDly = 0 (typically) ! 3182: l_MemBusCnfg_u32 += ( ( 0 ) << 8 ); ! 3183: // RdOEOffDly = (2 * CL) - 4 -> MBC[24:27] ! 3184: // NOTE: formula is not working, changed to: ! 3185: // RdOEOffDly = (2 * CL) - 1 ! 3186: l_MemBusCnfg_u32 += ( ( ( 2 * CL ) - 1 ) << 4 ); ! 3187: */ ! 3188: ! 3189: store32_ci( MemBusCnfg_R, l_MemBusCnfg_u32 ); ! 3190: store32_ci( MemBusCnfg2_R, rst->MemBusCnfg & (uint32_t) 0xf0000000 ); ! 3191: ! 3192: /* ! 3193: * reset verniers registers ! 3194: */ ! 3195: store32_ci( RstLdEnVerniersC0_R, 0x0 ); ! 3196: store32_ci( RstLdEnVerniersC1_R, 0x0 ); ! 3197: store32_ci( RstLdEnVerniersC2_R, 0x0 ); ! 3198: store32_ci( RstLdEnVerniersC3_R, 0x0 ); ! 3199: store32_ci( ExtMuxVernier0_R, 0x0 ); ! 3200: store32_ci( ExtMuxVernier1_R, 0x0 ); ! 3201: ! 3202: /* ! 3203: * Queue Configuration ! 3204: */ ! 3205: store32_ci( MemRdQCnfg_R, rst->MemRdQCnfg ); ! 3206: store32_ci( MemWrQCnfg_R, rst->MemWrQCnfg ); ! 3207: store32_ci( MemQArb_R, rst->MemQArb ); ! 3208: store32_ci( MemRWArb_R, rst->MemRWArb ); ! 3209: ! 3210: #ifdef U4_INFO ! 3211: printf( "\b\b\bOK\r\n" ); ! 3212: #endif ! 3213: ! 3214: /* ! 3215: * start up clocks & wait for pll2 to stabilize ! 3216: */ ! 3217: #ifdef U4_INFO ! 3218: printf( " [start DDR clock : ]" ); ! 3219: #endif ! 3220: ! 3221: store32_ci( MemModeCntl_R, IBIT(0) | IBIT(8) ); ! 3222: dly( 50000000 ); ! 3223: ! 3224: #ifdef U4_INFO ! 3225: printf( "\b\b\bOK\r\n" ); ! 3226: ! 3227: #endif ! 3228: ! 3229: /* ! 3230: * memory initialization sequence ! 3231: */ ! 3232: #ifdef U4_INFO ! 3233: printf( " [memory init : ]" ); ! 3234: #endif ! 3235: u4_MemInitSequence( tRP, tWR, tRFC, CL, tCK, TD ); ! 3236: #ifdef U4_INFO ! 3237: printf( "\b\b\bOK\r\n" ); ! 3238: #endif ! 3239: ! 3240: /* ! 3241: * start ECC before auto calibration to enable ECC bytelane ! 3242: */ ! 3243: store32_ci( MCCR_R, IBIT(0) ); ! 3244: dly( 15000000 ); ! 3245: ! 3246: /* ! 3247: * start up auto calibration ! 3248: */ ! 3249: #ifdef U4_INFO ! 3250: printf( " [auto calibration: ]\b" ); ! 3251: #endif ! 3252: ! 3253: /* ! 3254: * start auto calibration ! 3255: */ ! 3256: l_acerr_i32 = 0; ! 3257: do { ! 3258: progbar(); ! 3259: ! 3260: l_ac_i32 = u4_auto_calib( &l_ac_st ); ! 3261: ! 3262: if( l_ac_i32 != 0 ) { ! 3263: l_acerr_i32++; ! 3264: } ! 3265: ! 3266: dly( 15000000 ); ! 3267: } while( ( l_ac_i32 != 0 ) && ! 3268: ( l_acerr_i32 <= MAX_ACERR ) ); ! 3269: ! 3270: if( l_acerr_i32 > MAX_ACERR ) { ! 3271: #ifdef U4_INFO ! 3272: printf( "\b\b\bERR\r\n" ); ! 3273: #endif ! 3274: return RET_ERR; ! 3275: } ! 3276: ! 3277: /* ! 3278: * insert auto calibration results ! 3279: */ ! 3280: store32_ci( MemBusCnfg_R, l_ac_st.m_MemBusCnfg_u32 ); ! 3281: store32_ci( MemBusCnfg2_R, l_ac_st.m_MemBusCnfg2_u32 ); ! 3282: store32_ci( RstLdEnVerniersC0_R, l_ac_st.m_RstLdEnVerniers_pu32[0] ); ! 3283: store32_ci( RstLdEnVerniersC1_R, l_ac_st.m_RstLdEnVerniers_pu32[1] ); ! 3284: store32_ci( RstLdEnVerniersC2_R, l_ac_st.m_RstLdEnVerniers_pu32[2] ); ! 3285: store32_ci( RstLdEnVerniersC3_R, l_ac_st.m_RstLdEnVerniers_pu32[3] ); ! 3286: ! 3287: /* ! 3288: * insert final timing value into MemRWArb ! 3289: */ ! 3290: l_MemRWArb_u32 = ( ( l_ac_st.m_MemBusCnfg_u32 >> 28 /*RdMacDel*/) + 1 ); ! 3291: l_MemRWArb_u32 *= 10; // needed for rounding ! 3292: l_MemRWArb_u32 /= 2; // due to spec ! 3293: l_MemRWArb_u32 += 9; // round up ! 3294: l_MemRWArb_u32 /= 10; // value is rounded now ! 3295: l_MemRWArb_u32 = l_MemRWArb_u32 + 6 - WL - TD; ! 3296: l_MemRWArb_u32 |= rst->MemRWArb; ! 3297: store32_ci( MemRWArb_R, l_MemRWArb_u32 ); ! 3298: ! 3299: progbar(); ! 3300: dly( 15000000 ); ! 3301: ! 3302: /* ! 3303: * do initial scrubbing ! 3304: */ ! 3305: *f_ecc_pt = u4_InitialScrub(); ! 3306: ! 3307: switch( f_ecc_pt->m_err_i32 ) { ! 3308: case RET_OK: { ! 3309: #ifdef U4_INFO ! 3310: printf( "\b\bOK\r\n" ); ! 3311: #endif ! 3312: break; ! 3313: } ! 3314: ! 3315: case RET_ACERR_CE: { ! 3316: #ifdef U4_INFO ! 3317: printf( "\b\b\b\bWEAK][correctable errors during scrub (%u)]\r\n", ! 3318: f_ecc_pt->m_cecnt_u32 ); ! 3319: #endif ! 3320: break; ! 3321: } ! 3322: ! 3323: case RET_ACERR_UEWT: ! 3324: case RET_ACERR_UE: { ! 3325: #ifdef U4_INFO ! 3326: printf( "\b\b\bERR][uncorrectable errors during scrub (%u)]\r\n", ! 3327: f_ecc_pt->m_uecnt_u32 ); ! 3328: #endif ! 3329: return RET_ACERR_UE; ! 3330: } ! 3331: ! 3332: } ! 3333: ! 3334: /* ! 3335: * start continuous background scrub ! 3336: */ ! 3337: #ifdef U4_INFO ! 3338: printf( " [background scrub: ]" ); ! 3339: #endif ! 3340: ! 3341: u4_Scrub( BACKGROUND_SCRUB, 0, NULL ); ! 3342: ! 3343: #ifdef U4_INFO ! 3344: printf( "\b\b\bOK\r\n" ); ! 3345: #endif ! 3346: ! 3347: /* ! 3348: * finally clear API Exception register ! 3349: * (read to clear) ! 3350: */ ! 3351: load32_ci( APIExcp_R ); ! 3352: ! 3353: return RET_OK; ! 3354: } ! 3355: ! 3356: #undef RND ! 3357: ! 3358: void ! 3359: u4_memtest(uint8_t argCnt, char *pArgs[], uint64_t flags) ! 3360: ! 3361: { ! 3362: #define TEND 99 ! 3363: #define TCHK 100 ! 3364: static const uint64_t _2GB = (uint64_t) 0x80000000; ! 3365: static const uint64_t _start = (uint64_t) 0x08000000; // 128Mb ! 3366: static const uint64_t _bsize = (uint64_t) 0x08000000; // 128MB ! 3367: static const uint64_t _line = (uint64_t) 128; ! 3368: static const uint64_t _256MB = (uint64_t) 0x10000000; ! 3369: ! 3370: static const uint64_t PATTERN[] = { ! 3371: 0x9090909090909090, 0x0020002000200020, ! 3372: 0x0c0c0c0c0c0c0c0c, 0x8080808080808080, ! 3373: 0x1004010004001041, 0x0000000000000000 ! 3374: }; ! 3375: ! 3376: uint64_t mend = (uint64_t) 0x200000000;//m_memsize_u64; ! 3377: uint64_t numblocks = ( mend - _start ) / _bsize; // 128Mb blocks ! 3378: uint64_t numlines = _bsize / _line; ! 3379: uint64_t tstate = 0; ! 3380: uint64_t tlast = 0; ! 3381: uint64_t pidx = 0; ! 3382: uint64_t rotr = 0; ! 3383: uint64_t rotl = 0; ! 3384: uint64_t block; ! 3385: uint64_t line; ! 3386: uint64_t addr; ! 3387: uint64_t i; ! 3388: uint64_t check = 0; ! 3389: uint64_t dcnt; ! 3390: uint64_t uerr = 0; ! 3391: uint64_t cerr = 0; ! 3392: uint64_t merr = 0; ! 3393: char c; ! 3394: ! 3395: printf( "\n\nU4 memory test" ); ! 3396: printf( "\n--------------" ); ! 3397: ! 3398: /* ! 3399: * mask out UEC & CEC ! 3400: */ ! 3401: or32_ci( MCCR_R, IBIT(6) | IBIT(7) ); ! 3402: ! 3403: while( PATTERN[pidx] ) { ! 3404: ! 3405: switch( tstate ) ! 3406: { ! 3407: case 0: { ! 3408: printf( "\npattern fill 0x%08X%08X: ", (uint32_t) (PATTERN[pidx] >> 32), (uint32_t) PATTERN[pidx] ); ! 3409: ! 3410: /* ! 3411: * first switch lines, then blocks. This way the CPU ! 3412: * is not able to cache data ! 3413: */ ! 3414: for( line = 0, dcnt = 0; line < numlines; line++ ) { ! 3415: ! 3416: for( block = 0; block < numblocks; block++ ) { ! 3417: ! 3418: for( i = 0; i < _line; i += 8 ) { ! 3419: addr = _start + ! 3420: ( block * _bsize ) + ! 3421: ( line * _line ) + ! 3422: i; ! 3423: ! 3424: if( addr >= _2GB ) { ! 3425: addr += _2GB; ! 3426: } ! 3427: ! 3428: *( (uint64_t *) addr ) = PATTERN[pidx]; ! 3429: ! 3430: /* ! 3431: * print out a dot every 256Mb ! 3432: */ ! 3433: dcnt += 8; ! 3434: if( dcnt == _256MB ) { ! 3435: dcnt = 0; ! 3436: printf( "*" ); ! 3437: ! 3438: if( io_getchar( &c ) ) { ! 3439: goto mtend; ! 3440: } ! 3441: ! 3442: } ! 3443: ! 3444: } ! 3445: ! 3446: } ! 3447: ! 3448: } ! 3449: ! 3450: check = PATTERN[pidx]; ! 3451: tlast = 0; ! 3452: tstate = TCHK; ! 3453: } break; ! 3454: ! 3455: case 1: { ! 3456: uint64_t one; ! 3457: ! 3458: /* ! 3459: * new check pattern ! 3460: ! 3461: */ ! 3462: one = ( ( check & 0x1 ) != 0 ); ! 3463: check >>= 1; ! 3464: if( one ) { ! 3465: check |= 0x8000000000000000; ! 3466: } ! 3467: ! 3468: printf( "\nrotate right 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check ); ! 3469: ! 3470: /* ! 3471: * first switch lines, then blocks. This way the CPU ! 3472: * is not able to cache data ! 3473: */ ! 3474: for( line = 0, dcnt = 0; line < numlines; line++ ) { ! 3475: ! 3476: for( block = 0; block < numblocks; block++ ) { ! 3477: ! 3478: for( i = 0; i < _line; i += 8 ) { ! 3479: addr = _start + ! 3480: ( block * _bsize ) + ! 3481: ( line * _line ) + ! 3482: i; ! 3483: ! 3484: if( addr >= _2GB ) { ! 3485: addr += _2GB; ! 3486: } ! 3487: ! 3488: *( (uint64_t *) addr ) >>= 1; ! 3489: ! 3490: if( one ) { ! 3491: *( (uint64_t *) addr ) |= ! 3492: (uint64_t) 0x8000000000000000; ! 3493: } ! 3494: ! 3495: /* ! 3496: * print out a dot every 256Mb ! 3497: */ ! 3498: dcnt += 8; ! 3499: if( dcnt == _256MB ) { ! 3500: dcnt = 0; ! 3501: printf( "*" ); ! 3502: ! 3503: if( io_getchar( &c ) ) { ! 3504: goto mtend; ! 3505: } ! 3506: ! 3507: } ! 3508: ! 3509: } ! 3510: ! 3511: } ! 3512: ! 3513: } ! 3514: ! 3515: tlast = 1; ! 3516: tstate = TCHK; ! 3517: } break; ! 3518: ! 3519: case 2: { ! 3520: ! 3521: if( rotr < 6 ) { ! 3522: rotr++; ! 3523: tstate = 1; ! 3524: } else { ! 3525: rotr = 0; ! 3526: tstate = 3; ! 3527: } ! 3528: ! 3529: } break; ! 3530: ! 3531: case 3: { ! 3532: /* ! 3533: * new check pattern ! 3534: */ ! 3535: check ^= (uint64_t) ~0; ! 3536: ! 3537: printf( "\ninverting 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check ); ! 3538: ! 3539: /* ! 3540: * first switch lines, then blocks. This way the CPU ! 3541: * is not able to cache data ! 3542: */ ! 3543: for( line = 0, dcnt = 0; line < numlines; line++ ) { ! 3544: ! 3545: for( block = 0; block < numblocks; block++ ) { ! 3546: ! 3547: for( i = 0; i < _line; i += 8 ) { ! 3548: addr = _start + ! 3549: ( block * _bsize ) + ! 3550: ( line * _line ) + ! 3551: i; ! 3552: ! 3553: if( addr >= _2GB ) { ! 3554: addr += _2GB; ! 3555: } ! 3556: ! 3557: *( (uint64_t *) addr ) ^= (uint64_t) ~0; ! 3558: ! 3559: /* ! 3560: * print out a dot every 256Mb ! 3561: */ ! 3562: dcnt += 8; ! 3563: if( dcnt == _256MB ) { ! 3564: dcnt = 0; ! 3565: printf( "*" ); ! 3566: ! 3567: if( io_getchar( &c ) ) { ! 3568: goto mtend; ! 3569: } ! 3570: ! 3571: } ! 3572: ! 3573: } ! 3574: ! 3575: } ! 3576: ! 3577: } ! 3578: ! 3579: tlast = 3; ! 3580: tstate = TCHK; ! 3581: } break; ! 3582: ! 3583: case 4: { ! 3584: uint64_t one; ! 3585: ! 3586: /* ! 3587: * new check pattern ! 3588: */ ! 3589: one = ( ( check & 0x8000000000000000 ) != 0 ); ! 3590: check <<= 1; ! 3591: if( one ) { ! 3592: check |= 0x1; ! 3593: } ! 3594: ! 3595: printf( "\nrotate left 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check ); ! 3596: ! 3597: /* ! 3598: * first switch lines, then blocks. This way the CPU ! 3599: * is not able to cache data ! 3600: */ ! 3601: for( line = 0, dcnt = 0; line < numlines; line++ ) { ! 3602: ! 3603: for( block = 0; block < numblocks; block++ ) { ! 3604: ! 3605: for( i = 0; i < _line; i += 8 ) { ! 3606: addr = _start + ! 3607: ( block * _bsize ) + ! 3608: ( line * _line ) + ! 3609: i; ! 3610: ! 3611: if( addr >= _2GB ) { ! 3612: addr += _2GB; ! 3613: } ! 3614: ! 3615: *( (uint64_t *) addr ) <<= 1; ! 3616: ! 3617: if( one ) { ! 3618: *( (uint64_t *) addr ) |= ! 3619: (uint64_t) 0x1; ! 3620: } ! 3621: ! 3622: /* ! 3623: * print out a dot every 256Mb ! 3624: */ ! 3625: dcnt += 8; ! 3626: if( dcnt == _256MB ) { ! 3627: dcnt = 0; ! 3628: printf( "*" ); ! 3629: ! 3630: if( io_getchar( &c ) ) { ! 3631: goto mtend; ! 3632: } ! 3633: ! 3634: } ! 3635: ! 3636: } ! 3637: ! 3638: } ! 3639: ! 3640: } ! 3641: ! 3642: tlast = 4; ! 3643: tstate = TCHK; ! 3644: } break; ! 3645: ! 3646: case 5: { ! 3647: ! 3648: if( rotl < 6 ) { ! 3649: rotl++; ! 3650: tstate = 4; ! 3651: } else { ! 3652: rotl = 0; ! 3653: tstate = 6; ! 3654: } ! 3655: ! 3656: } break; ! 3657: ! 3658: case 6: { ! 3659: /* ! 3660: * new check pattern ! 3661: */ ! 3662: check *= ~check; ! 3663: printf( "\nmultiply 0x%08X%08X: ", (uint32_t) (check >> 32), (uint32_t) check ); ! 3664: ! 3665: /* ! 3666: * first switch lines, then blocks. This way the CPU ! 3667: * is not able to cache data ! 3668: */ ! 3669: for( line = 0, dcnt = 0; line < numlines; line++ ) { ! 3670: ! 3671: for( block = 0; block < numblocks; block++ ) { ! 3672: ! 3673: for( i = 0; i < _line; i += 8 ) { ! 3674: addr = _start + ! 3675: ( block * _bsize ) + ! 3676: ( line * _line ) + ! 3677: i; ! 3678: ! 3679: if( addr >= _2GB ) { ! 3680: addr += _2GB; ! 3681: } ! 3682: ! 3683: *( (uint64_t *) addr ) *= ~( *( (uint64_t *) addr ) ); ! 3684: ! 3685: /* ! 3686: * print out a dot every 256Mb ! 3687: */ ! 3688: dcnt += 8; ! 3689: if( dcnt == _256MB ) { ! 3690: dcnt = 0; ! 3691: printf( "*" ); ! 3692: ! 3693: if( io_getchar( &c ) ) { ! 3694: goto mtend; ! 3695: } ! 3696: ! 3697: } ! 3698: ! 3699: } ! 3700: ! 3701: } ! 3702: ! 3703: } ! 3704: ! 3705: tlast = TEND - 1; ! 3706: tstate = TCHK; ! 3707: } break; ! 3708: ! 3709: case TEND: { ! 3710: pidx++; ! 3711: tstate = 0; ! 3712: } break; ! 3713: ! 3714: case TCHK: { ! 3715: uint64_t err; ! 3716: /* ! 3717: * check data ! 3718: */ ! 3719: printf( "\nchecking : " ); ! 3720: ! 3721: for( line = 0, dcnt = 0; line < numlines; line++ ) { ! 3722: ! 3723: for( block = 0; block < numblocks; block++ ) { ! 3724: ! 3725: for( i = 0; i < _line; i += 8 ) { ! 3726: addr = _start + ! 3727: ( block * _bsize ) + ! 3728: ( line * _line ) + ! 3729: i; ! 3730: ! 3731: if( addr >= _2GB ) { ! 3732: addr += _2GB; ! 3733: } ! 3734: ! 3735: err = ( *( (uint64_t *) addr ) != check ); ! 3736: ! 3737: if( err ) { ! 3738: merr++; ! 3739: } ! 3740: ! 3741: /* ! 3742: * print out a dot every 256Mb ! 3743: */ ! 3744: dcnt += 8; ! 3745: if( dcnt == _256MB ) { ! 3746: dcnt = 0; ! 3747: ! 3748: if( err ) { ! 3749: printf( "X" ); ! 3750: } else { ! 3751: printf( "*" ); ! 3752: } ! 3753: ! 3754: if( io_getchar( &c ) ) { ! 3755: goto mtend; ! 3756: } ! 3757: ! 3758: } ! 3759: ! 3760: } ! 3761: ! 3762: } ! 3763: ! 3764: } ! 3765: ! 3766: err = (uint64_t) load32_ci( MEAR1_R ); ! 3767: uerr += ( err >> 24 ) & (uint64_t) 0xff; ! 3768: cerr += ( err >> 16 ) & (uint64_t) 0xff; ! 3769: ! 3770: printf( " (UE: %02llX, CE: %02llX)", ( err >> 24 ) & (uint64_t) 0xff, ( err >> 16 ) & (uint64_t) 0xff ); ! 3771: ! 3772: tstate = tlast + 1; ! 3773: tlast = TCHK; ! 3774: } break; ! 3775: ! 3776: } ! 3777: ! 3778: } ! 3779: ! 3780: mtend: ! 3781: printf( "\n\nmemory test results" ); ! 3782: printf( "\n-------------------" ); ! 3783: printf( "\nuncorrectable errors: %u", (uint32_t) uerr ); ! 3784: printf( "\ncorrectable errors : %u", (uint32_t) cerr ); ! 3785: printf( "\nread/write errors : %u\n", (uint32_t) merr ); ! 3786: ! 3787: and32_ci( MCCR_R, ~( IBIT(6) | IBIT(7) ) ); ! 3788: } ! 3789: ! 3790: void ! 3791: u4_dump(uint8_t argCnt, char *pArgs[], uint64_t flags) ! 3792: { ! 3793: printf( "\r\n*** u4 register dump ***\r\n\n" ); ! 3794: printf( "register (offset): value\r\n" ); ! 3795: printf( "----------------------------------\r\n" ); ! 3796: printf( "Clock Control (0x%04X): 0x%08X\r\n", (uint16_t) ClkCntl_R, load32_ci( ClkCntl_R ) ); ! 3797: printf( "PLL2 Control (0x%04X): 0x%08X\r\n", (uint16_t) PLL2Cntl_R, load32_ci( PLL2Cntl_R ) ); ! 3798: printf( "MemModeCntl (0x%04X): 0x%08X\r\n", (uint16_t) MemModeCntl_R, load32_ci( MemModeCntl_R ) ); ! 3799: printf( "RASTimer0 (0x%04X): 0x%08X\r\n", (uint16_t) RASTimer0_R, load32_ci( RASTimer0_R ) ); ! 3800: printf( "RASTimer1 (0x%04X): 0x%08X\r\n", (uint16_t) RASTimer1_R, load32_ci( RASTimer1_R ) ); ! 3801: printf( "CASTimer0 (0x%04X): 0x%08X\r\n", (uint16_t) CASTimer0_R, load32_ci( CASTimer0_R ) ); ! 3802: printf( "CASTimer1 (0x%04X): 0x%08X\r\n", (uint16_t) CASTimer1_R, load32_ci( CASTimer1_R ) ); ! 3803: printf( "MemRfshCntl (0x%04X): 0x%08X\r\n", (uint16_t) MemRfshCntl_R, load32_ci( MemRfshCntl_R ) ); ! 3804: printf( "Dm0Cnfg (0x%04X): 0x%08X\r\n", (uint16_t) Dm0Cnfg_R, load32_ci( Dm0Cnfg_R ) ); ! 3805: printf( "Dm1Cnfg (0x%04X): 0x%08X\r\n", (uint16_t) Dm1Cnfg_R, load32_ci( Dm1Cnfg_R ) ); ! 3806: printf( "Dm2Cnfg (0x%04X): 0x%08X\r\n", (uint16_t) Dm2Cnfg_R, load32_ci( Dm2Cnfg_R ) ); ! 3807: printf( "Dm3Cnfg (0x%04X): 0x%08X\r\n", (uint16_t) Dm3Cnfg_R, load32_ci( Dm3Cnfg_R ) ); ! 3808: printf( "UsrCnfg (0x%04X): 0x%08X\r\n", (uint16_t) UsrCnfg_R, load32_ci( UsrCnfg_R ) ); ! 3809: printf( "MemArbWt (0x%04X): 0x%08X\r\n", (uint16_t) MemArbWt_R, load32_ci( MemArbWt_R ) ); ! 3810: printf( "ODTCntl (0x%04X): 0x%08X\r\n", (uint16_t) ODTCntl_R, load32_ci( ODTCntl_R ) ); ! 3811: printf( "IOPadCntl (0x%04X): 0x%08X\r\n", (uint16_t) IOPadCntl_R, load32_ci( IOPadCntl_R ) ); ! 3812: printf( "MemPhyMode (0x%04X): 0x%08X\r\n", (uint16_t) MemPhyModeCntl_R, load32_ci( MemPhyModeCntl_R ) ); ! 3813: printf( "OCDCalCntl (0x%04X): 0x%08X\r\n", (uint16_t) OCDCalCntl_R, load32_ci( OCDCalCntl_R ) ); ! 3814: printf( "OCDCalCmd (0x%04X): 0x%08X\r\n", (uint16_t) OCDCalCmd_R, load32_ci( OCDCalCmd_R ) ); ! 3815: printf( "CKDelayL (0x%04X): 0x%08X\r\n", (uint16_t) CKDelayL_R, load32_ci( CKDelayL_R ) ); ! 3816: printf( "CKDelayH (0x%04X): 0x%08X\r\n", (uint16_t) CKDelayU_R, load32_ci( CKDelayU_R ) ); ! 3817: printf( "MemBusCnfg (0x%04X): 0x%08X\r\n", (uint16_t) MemBusCnfg_R, load32_ci( MemBusCnfg_R ) ); ! 3818: printf( "MemBusCnfg2 (0x%04X): 0x%08X\r\n", (uint16_t) MemBusCnfg2_R, load32_ci( MemBusCnfg2_R ) ); ! 3819: printf( "MemRdQCnfg (0x%04X): 0x%08X\r\n", (uint16_t) MemRdQCnfg_R, load32_ci( MemRdQCnfg_R ) ); ! 3820: printf( "MemWrQCnfg (0x%04X): 0x%08X\r\n", (uint16_t) MemWrQCnfg_R, load32_ci( MemWrQCnfg_R ) ); ! 3821: printf( "MemQArb (0x%04X): 0x%08X\r\n", (uint16_t) MemQArb_R, load32_ci( MemQArb_R ) ); ! 3822: printf( "MemRWArb (0x%04X): 0x%08X\r\n", (uint16_t) MemRWArb_R, load32_ci( MemRWArb_R ) ); ! 3823: printf( "ByteWrClkDel (0x%04X): 0x%08X\r\n", (uint16_t) ByteWrClkDelC0B00_R, load32_ci( ByteWrClkDelC0B00_R ) ); ! 3824: printf( "ReadStrobeDel (0x%04X): 0x%08X\r\n", (uint16_t) ReadStrobeDelC0B00_R, load32_ci( ReadStrobeDelC0B00_R ) ); ! 3825: printf( "RstLdEnVerC0 (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC0_R, load32_ci( RstLdEnVerniersC0_R ) ); ! 3826: printf( "RstLdEnVerC1 (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC1_R, load32_ci( RstLdEnVerniersC1_R ) ); ! 3827: printf( "RstLdEnVerC2 (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC2_R, load32_ci( RstLdEnVerniersC2_R ) ); ! 3828: printf( "RstLdEnVerC3 (0x%04X): 0x%08X\r\n", (uint16_t) RstLdEnVerniersC3_R, load32_ci( RstLdEnVerniersC3_R ) ); ! 3829: printf( "APIMemRdCfg (0x%04X): 0x%08X\r\n", (uint16_t) APIMemRdCfg_R, load32_ci( APIMemRdCfg_R ) ); ! 3830: printf( "scrub start (0x%04X): 0x%08X\r\n", (uint16_t) MSRSR_R, load32_ci( MSRSR_R ) ); ! 3831: printf( "scrub end (0x%04X): 0x%08X\r\n", (uint16_t) MSRER_R, load32_ci( MSRER_R ) ); ! 3832: } ! 3833: ! 3834: int32_t ! 3835: u4_memBegin( eccerror_t *f_ecc_pt ) ! 3836: { ! 3837: int32_t i; ! 3838: ! 3839: #ifdef U4_INFO ! 3840: printf( "\r\n" ); ! 3841: printf( "U4 DDR2 memory controller setup V%u.%u\r\n", ! 3842: VER, SUBVER ); ! 3843: printf( "------------------------------------\r\n" ); ! 3844: printf( "> detected board : " ); ! 3845: ! 3846: if( IS_MAUI ) { ! 3847: printf( "MAUI" ); ! 3848: } else if( IS_BIMINI ) { ! 3849: printf( "BIMINI" ); ! 3850: } else if( IS_KAUAI ) { ! 3851: printf( "KAUAI" ); ! 3852: } else { ! 3853: printf( "unknown!" ); ! 3854: return RET_ERR; ! 3855: } ! 3856: #endif ! 3857: ! 3858: do { ! 3859: /* ! 3860: * initialize variables ! 3861: */ ! 3862: m_memsize_u64 = 0; ! 3863: m_dcnt_u32 = 0; ! 3864: m_dgrcnt_u32 = 0; ! 3865: m_dclidx_u32 = 0; ! 3866: ! 3867: for( i = 0; i < NUM_SLOTS; i++ ) { ! 3868: m_dptr[i] = NULL; ! 3869: memset( ( void * ) &m_dimm[i], 0, sizeof( dimm_t ) ); ! 3870: } ! 3871: ! 3872: for( i = 0; i < MAX_DGROUPS; i++ ) { ! 3873: m_dgrptr[i] = NULL; ! 3874: memset( ( void * ) &m_dgroup[i], 0, sizeof( dimm_t ) ); ! 3875: } ! 3876: ! 3877: /* ! 3878: * start configuration ! 3879: */ ! 3880: #ifdef U4_INFO ! 3881: printf( "\r\n> detected DIMM configuration : " ); ! 3882: #endif ! 3883: ! 3884: i = ddr2_readSPDs(); ! 3885: ! 3886: if( i != RET_OK ) { ! 3887: #ifdef U4_INFO ! 3888: printf( "\r\n-------------------------------------------------------------" ); ! 3889: printf( "\r\n switching off memory bank(s) due to SPD integrity failure" ); ! 3890: printf( "\r\n-------------------------------------------------------------\r\n" ); ! 3891: #endif ! 3892: } ! 3893: ! 3894: } while( i != RET_OK ); ! 3895: ! 3896: /* ! 3897: * check DIMM configuration ! 3898: */ ! 3899: if( ddr2_setupDIMMcfg() != RET_OK ) { ! 3900: #ifdef U4_INFO ! 3901: printf( "> initialization failure.\r\n" ); ! 3902: #endif ! 3903: return RET_ERR; ! 3904: } ! 3905: ! 3906: /* ! 3907: * create DIMM groups ! 3908: */ ! 3909: u4_setupDIMMgroups(); ! 3910: ! 3911: /* ! 3912: * start configuration of u4 ! 3913: */ ! 3914: u4_calcDIMMcnfg(); ! 3915: ! 3916: if( u4_calcDIMMmemmode() != RET_OK ) { ! 3917: #ifdef U4_INFO ! 3918: printf( "> initialization failure.\r\n" ); ! 3919: #endif ! 3920: return RET_ERR; ! 3921: } ! 3922: ! 3923: #ifdef U4_INFO ! 3924: printf( "%uMb @ %uMhz, CL %u\r\n", ! 3925: (uint32_t) ( m_memsize_u64 / 0x100000 ), ! 3926: m_gendimm.m_speed_pu32[m_dclidx_u32], ! 3927: m_gendimm.m_clval_pu32[m_dclidx_u32] ); ! 3928: ! 3929: printf( "> initializing memory :\r\n" ); ! 3930: #endif ! 3931: ! 3932: if( u4_setup_core_clock() != RET_OK ) { ! 3933: #ifdef U4_INFO ! 3934: printf( "> initialization failure.\r\n" ); ! 3935: #endif ! 3936: return RET_ERR; ! 3937: } ! 3938: ! 3939: i = u4_start( f_ecc_pt ); ! 3940: if( i != RET_OK ) { ! 3941: #ifdef U4_INFO ! 3942: printf( "> initialization failure.\r\n" ); ! 3943: #endif ! 3944: return i; ! 3945: } ! 3946: ! 3947: #ifdef U4_INFO ! 3948: printf( " [flush cache : ]" ); ! 3949: #endif ! 3950: ! 3951: flush_cache( 0x0, L2_CACHE_SIZE ); ! 3952: ! 3953: #ifdef U4_INFO ! 3954: printf( "\b\b\bOK\r\n" ); ! 3955: printf( "> initialization complete.\r\n" ); ! 3956: #endif ! 3957: ! 3958: #ifdef U4_SHOW_REGS ! 3959: u4_dump(0,0,0); ! 3960: #endif ! 3961: ! 3962: return RET_OK; ! 3963: } ! 3964: ! 3965: static int32_t scrubstarted = 0; ! 3966: ! 3967: void ! 3968: u4_scrubStart(uint8_t argCnt, char *pArgs[], uint64_t flags ) ! 3969: { ! 3970: scrubstarted = 1; ! 3971: ! 3972: /* ! 3973: * setup scrub parameters ! 3974: */ ! 3975: store32_ci( MSCR_R, 0 ); // stop scrub ! 3976: store32_ci( MSRSR_R, 0x0 ); // set start ! 3977: store32_ci( MSRER_R, 0x1c ); // set end ! 3978: store32_ci( MSPR_R, 0x0 ); // set pattern ! 3979: ! 3980: /* ! 3981: * clear out ECC error registers ! 3982: */ ! 3983: store32_ci( MEAR0_R, 0x0 ); ! 3984: store32_ci( MEAR1_R, 0x0 ); ! 3985: store32_ci( MESR_R, 0x0 ); ! 3986: ! 3987: /* ! 3988: * Setup Scrub Type ! 3989: */ ! 3990: store32_ci( MSCR_R, IBIT(1) ); ! 3991: printf( "\r\nscrub started\r\n" ); ! 3992: } ! 3993: ! 3994: void ! 3995: u4_scrubEnd(uint8_t argCnt, char *pArgs[], uint64_t flags ) ! 3996: { ! 3997: store32_ci( MSCR_R, 0 ); // stop scrub ! 3998: scrubstarted = 0; ! 3999: printf( "\r\nscrub stopped\r\n" ); ! 4000: } ! 4001: ! 4002: void ! 4003: u4_memwr(uint8_t argCnt, char *pArgs[], uint64_t flags ) ! 4004: { ! 4005: uint32_t i; ! 4006: uint32_t v = 0; ! 4007: ! 4008: for( i = 0; i < 0x200; i += 4 ) { ! 4009: ! 4010: if( ( i & 0xf ) == 0 ) { ! 4011: v = ~v; ! 4012: } ! 4013: ! 4014: store32_ci( i, v ); ! 4015: } ! 4016: ! 4017: } ! 4018: ! 4019: void ! 4020: u4memInit() ! 4021: { ! 4022: static uint32_t l_isInit_u32 = 0; ! 4023: eccerror_t l_ecc_t; ! 4024: int32_t ret; ! 4025: ! 4026: /* ! 4027: * do not initialize memory more than once ! 4028: */ ! 4029: if( l_isInit_u32 ) { ! 4030: #ifdef U4_INFO ! 4031: printf( "\r\n\nmemory already initialized\r\n" ); ! 4032: #endif ! 4033: return; ! 4034: } else { ! 4035: l_isInit_u32 = 1; ! 4036: } ! 4037: ! 4038: /* ! 4039: * enable all DIMM banks on first run ! 4040: */ ! 4041: m_bankoff_u32 = 0; ! 4042: ! 4043: do { ! 4044: ret = u4_memBegin( &l_ecc_t ); ! 4045: ! 4046: if( ret < RET_ERR ) { ! 4047: uint32_t l_bank_u32 = l_ecc_t.m_rank_u32 / 2; ! 4048: printf( "\r\n-----------------------------------------------------" ); ! 4049: printf( "\r\n switching off memory bank %u due to memory failure", l_bank_u32 ); ! 4050: printf( "\r\n-----------------------------------------------------" ); ! 4051: m_bankoff_u32 |= ( 1 << l_bank_u32 ); ! 4052: } ! 4053: ! 4054: } while( ret < RET_ERR ); ! 4055: ! 4056: } ! 4057: ! 4058: void ! 4059: monitorDDR2( uint8_t argCnt, char *pArgs[], uint64_t flags ) ! 4060: { ! 4061: u4memInit(); ! 4062: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.