1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 /* 25 * Copyright 2022 Oxide Computer Co. 26 */ 27 28 #ifndef _MC_AMD_H 29 #define _MC_AMD_H 30 31 #include <sys/mc.h> 32 #include <sys/isa_defs.h> 33 #include <sys/x86_archext.h> 34 35 #ifdef __cplusplus 36 extern "C" { 37 #endif 38 39 /* 40 * Definitions, register offsets, register structure etc pertaining to 41 * the memory controller on AMD64 systems. These are used by both the 42 * AMD cpu module and the mc-amd driver. 43 */ 44 45 /* 46 * The mc-amd driver exports an nvlist to userland, where the primary 47 * consumer is the "chip" topology enumerator for this platform type which 48 * builds a full topology subtree from this information. Others can use 49 * it, too, but don't depend on it not changing without an ARC contract 50 * (and the contract should probably concern the topology, not this nvlist). 51 * 52 * In the initial mc-amd implementation this nvlist was not versioned; 53 * we'll think of that as version 0 and it may be recognised by the absence 54 * of a "mcamd-nvlist-version member. 55 * 56 * Version 1 is defined as follows. A name in square brackets indicates 57 * that member is optional (only present if the actual value is valid). 58 * 59 * Name Type Description 60 * -------------------- --------------- --------------------------------------- 61 * mcamd-nvlist-version uint8 Exported nvlist version number 62 * num uint64 Chip id of this memory controller 63 * revision uint64 cpuid_getchiprev() result 64 * revname string cpuid_getchiprevstr() result 65 * socket string "Socket 755|939|940|AM2|F(1207)|S1g1" 66 * ecc-type string "ChipKill 128/16" or "Normal 64/8" 67 * base-addr uint64 Node base address 68 * lim-addr uint64 Node limit address 69 * node-ilen uint64 0|1|3|7 for 0/2/4/8 way node interleave 70 * node-ilsel uint64 Node interleave position of this node 71 * cs-intlv-factor uint64 chip-select interleave: 1/2/4/8 72 * dram-hole-size uint64 size in bytes from dram hole addr reg 73 * access-width uint64 MC mode, 64 or 128 bit 74 * bank-mapping uint64 Raw DRAM Bank Address Mapping Register 75 * bankswizzle uint64 1 if bank swizzling enabled; else 0 76 * mismatched-dimm-support uint64 1 if active; else 0 77 * [spare-csnum] uint64 Chip-select pair number of any spare 78 * [bad-csnum] uint64 Chip-select pair number of swapped cs 79 * cslist nvlist array See below; may have 0 members 80 * dimmlist nvlist array See below; may have 0 members 81 * 82 * cslist is an array of nvlist, each as follows: 83 * 84 * Name Type Description 85 * -------------------- --------------- --------------------------------------- 86 * num uint64 Chip-select base/mask pair number 87 * base-addr uint64 Chip-select base address (rel to node) 88 * mask uint64 Chip-select mask 89 * size uint64 Chip-select size in bytes 90 * dimm1-num uint64 First dimm (lodimm if a pair) 91 * dimm1-csname string Socket cs# line name for 1st dimm rank 92 * [dimm2-num] uint64 Second dimm if applicable (updimm) 93 * [dimm2-csname] string Socket cs# line name for 2nd dimm rank 94 * 95 * dimmlist is an array of nvlist, each as follows: 96 * 97 * Name Type Description 98 * -------------------- --------------- --------------------------------------- 99 * num uint64 DIMM instance number 100 * size uint64 DIMM size in bytes 101 * csnums uint64 array CS base/mask pair(s) on this DIMM 102 * csnames string array Socket cs# line name(s) on this DIMM 103 * 104 * The n'th csnums entry corresponds to the n'th csnames entry 105 */ 106 #define MC_NVLIST_VERSTR "mcamd-nvlist-version" 107 #define MC_NVLIST_VERS0 0 108 #define MC_NVLIST_VERS1 1 109 #define MC_NVLIST_VERS MC_NVLIST_VERS1 110 111 /* 112 * Constants and feature/revision test macros that are not expected to vary 113 * among different AMD family 0xf processor revisions. 114 */ 115 116 /* 117 * Configuration constants 118 */ 119 #define MC_CHIP_MAXNODES 8 /* max number of MCs in system */ 120 #define MC_CHIP_NDIMM 8 /* max dimms per MC */ 121 #define MC_CHIP_NCS 8 /* number of chip-selects per MC */ 122 #define MC_CHIP_NDRAMCHAN 2 /* maximum number of dram channels */ 123 #define MC_CHIP_DIMMRANKMAX 4 /* largest number of ranks per dimm */ 124 #define MC_CHIP_DIMMPERCS 2 /* max number of dimms per cs */ 125 #define MC_CHIP_DIMMPAIR(csnum) (csnum / MC_CHIP_DIMMPERCS) 126 127 /* 128 * Memory controller registers are read via PCI config space accesses on 129 * bus 0, device 0x18 + NodeId, and function as follows: 130 * 131 * Function 0: HyperTransport Technology Configuration 132 * Function 1: Address Map 133 * Function 2: DRAM Controller & HyperTransport Technology Trace Mode 134 * Function 3: Miscellaneous Control 135 */ 136 137 #define MC_AMD_DEV_OFFSET 0x18 /* node ID + offset == PCI dev num */ 138 139 enum mc_funcnum { 140 MC_FUNC_HTCONFIG = 0, 141 MC_FUNC_ADDRMAP = 1, 142 MC_FUNC_DRAMCTL = 2, 143 MC_FUNC_MISCCTL = 3 144 }; 145 146 /* 147 * For a given (bus, device, function) a particular offset selects the 148 * desired register. All registers are 32-bits wide. 149 * 150 * Different family 0xf processor revisions vary slightly in the content 151 * of these configuration registers. The biggest change is with rev F 152 * where DDR2 support has been introduced along with some hardware-controlled 153 * correctable memory error thresholding. Fortunately most of the config info 154 * required by the mc-amd driver is similar across revisions. 155 * 156 * We will try to insulate most of the driver code from config register 157 * details by reading all memory-controller PCI config registers that we 158 * will need at driver attach time for each of functions 0 through 3, and 159 * storing them in a "cooked" form as memory controller properties. 160 * These are to be accessed directly where we have an mc_t to hand, otherwise 161 * through mcamd_get_numprop. As such we expect most/all use of the 162 * structures and macros defined below to be in those attach codepaths. 163 */ 164 165 /* 166 * Function 0 (HT Config) offsets 167 */ 168 #define MC_HT_REG_RTBL_NODE_0 0x40 169 #define MC_HT_REG_RTBL_INCR 4 170 #define MC_HT_REG_NODEID 0x60 171 #define MC_HT_REG_UNITID 0x64 172 173 /* 174 * Function 1 (address map) offsets for DRAM base, DRAM limit, DRAM hole 175 * registers. 176 */ 177 #define MC_AM_REG_DRAMBASE_0 0x40 /* Offset for DRAM Base 0 */ 178 #define MC_AM_REG_DRAMLIM_0 0x44 /* Offset for DRAM Limit 0 */ 179 #define MC_AM_REG_DRAM_INCR 8 /* incr between base/limit pairs */ 180 #define MC_AM_REG_HOLEADDR 0xf0 /* DRAM Hole Address Register */ 181 182 /* 183 * Function 2 (dram controller) offsets for chip-select base, chip-select mask, 184 * DRAM bank address mapping, DRAM configuration registers. 185 */ 186 #define MC_DC_REG_CS_INCR 4 /* incr for CS base and mask */ 187 #define MC_DC_REG_CSBASE_0 0x40 /* 0x40 - 0x5c */ 188 #define MC_DC_REG_CSMASK_0 0x60 /* 0x60 - 0x7c */ 189 #define MC_DC_REG_BANKADDRMAP 0x80 /* DRAM Bank Address Mapping */ 190 #define MC_DC_REG_DRAMCFGLO 0x90 /* DRAM Configuration Low */ 191 #define MC_DC_REG_DRAMCFGHI 0x94 /* DRAM Configuration High */ 192 #define MC_DC_REG_DRAMMISC 0xa0 /* DRAM Miscellaneous */ 193 194 /* 195 * Function 3 (misc control) offset for NB MCA config, scrubber control, 196 * online spare control and NB capabilities. 197 */ 198 #define MC_CTL_REG_NBCFG 0x44 /* MCA NB configuration register */ 199 #define MC_CTL_REG_SCRUBCTL 0x58 /* Scrub control register */ 200 #define MC_CTL_REG_SCRUBADDR_LO 0x5c /* DRAM Scrub Address Low */ 201 #define MC_CTL_REG_SCRUBADDR_HI 0x60 /* DRAM Scrub Address High */ 202 #define MC_CTL_REG_SPARECTL 0xb0 /* On-line spare control register */ 203 #define MC_CTL_REG_NBCAP 0xe8 /* NB Capabilities */ 204 #define MC_CTL_REG_EXTNBCFG 0x180 /* Ext. MCA NB configuration register */ 205 206 #define MC_NBCAP_L3CAPABLE (1U << 25) 207 #define MC_NBCAP_MULTINODECPU (1U << 29) 208 #define MC_EXTNBCFG_ECCSYMSZ (1U << 25) 209 210 /* 211 * MC4_MISC MSR and MC4_MISCj MSRs 212 */ 213 #define MC_MSR_NB_MISC0 0x413 214 #define MC_MSR_NB_MISC1 0xc0000408 215 #define MC_MSR_NB_MISC2 0xc0000409 216 #define MC_MSR_NB_MISC3 0xc000040a 217 #define MC_MSR_NB_MISC(j) \ 218 ((j) == 0 ? MC_MSR_NB_MISC0 : MC_MSR_NB_MISC1 + (j) - 1) 219 220 /* 221 * PCI registers will be represented as unions, with one fixed-width unsigned 222 * integer member providing access to the raw register value and one or more 223 * structs breaking the register out into bitfields (more than one struct if 224 * the register definitions varies across processor revisions). 225 * 226 * The "raw" union member will always be '_val32'. Use MCREG_VAL32 to 227 * access this member. 228 * 229 * The bitfield structs are all named _fmt_xxx where xxx identifies the 230 * processor revision to which it applies. At this point the only xxx 231 * values in use are: 232 * 'cmn' - applies to all revisions 233 * 'f_preF' - applies to revisions E and earlier 234 * 'f_revFG' - applies to revisions F and G 235 * 236 * Variants such as 'preD', 'revDE', 'postCG' etc should be introduced 237 * as requirements arise. The MC_REV_* and MC_REV_MATCH etc macros 238 * will also need to grow to match. Use MCREG_FIELD_* to access the 239 * individual bitfields of a register, perhaps using MC_REV_* and MC_REV_MATCH 240 * to decide which revision suffix to provide. Where a bitfield appears 241 * in different revisions but has the same use it should be named identically 242 * (even if the BKDG varies a little) so that the MC_REG_FIELD_* macros 243 * can lookup that member based on revision only. 244 */ 245 246 #define MC_REV_UNKNOWN X86_CHIPREV_UNKNOWN 247 248 #define MC_F_REV_B X86_CHIPREV_AMD_LEGACY_F_REV_B 249 #define MC_F_REV_C (X86_CHIPREV_AMD_LEGACY_F_REV_C0 | \ 250 X86_CHIPREV_AMD_LEGACY_F_REV_CG) 251 #define MC_F_REV_D X86_CHIPREV_AMD_LEGACY_F_REV_D 252 #define MC_F_REV_E X86_CHIPREV_AMD_LEGACY_F_REV_E 253 #define MC_F_REV_F X86_CHIPREV_AMD_LEGACY_F_REV_F 254 #define MC_F_REV_G X86_CHIPREV_AMD_LEGACY_F_REV_G 255 256 #define MC_10_REV_A X86_CHIPREV_AMD_LEGACY_10_REV_A 257 #define MC_10_REV_B X86_CHIPREV_AMD_LEGACY_10_REV_B 258 259 /* 260 * The most common groupings for memory controller features. 261 */ 262 #define MC_F_REVS_BC (MC_F_REV_B | MC_F_REV_C) 263 #define MC_F_REVS_DE (MC_F_REV_D | MC_F_REV_E) 264 #define MC_F_REVS_BCDE (MC_F_REVS_BC | MC_F_REVS_DE) 265 #define MC_F_REVS_FG (MC_F_REV_F | MC_F_REV_G) 266 267 #define MC_10_REVS_AB (MC_10_REV_A | MC_10_REV_B) 268 269 /* 270 * Is 'rev' included in the 'revmask' bitmask? 271 */ 272 #define MC_REV_MATCH(rev, revmask) chiprev_matches(rev, revmask) 273 274 /* 275 * Is 'rev' at least revision 'revmin' or greater 276 */ 277 #define MC_REV_ATLEAST(rev, minrev) chiprev_at_least(rev, minrev) 278 279 #define _MCREG_FIELD(up, revsuffix, field) ((up)->_fmt_##revsuffix.field) 280 281 #define MCREG_VAL32(up) ((up)->_val32) 282 283 /* 284 * Access a field that has the same structure in all families and revisions 285 */ 286 #define MCREG_FIELD_CMN(up, field) _MCREG_FIELD(up, cmn, field) 287 288 /* 289 * Access a field as defined for family 0xf prior to revision F 290 */ 291 #define MCREG_FIELD_F_preF(up, field) _MCREG_FIELD(up, f_preF, field) 292 293 /* 294 * Access a field as defined for family 0xf revisions F and G 295 */ 296 #define MCREG_FIELD_F_revFG(up, field) _MCREG_FIELD(up, f_revFG, field) 297 298 /* 299 * Access a field as defined for family 0x10 revisions A and 300 */ 301 #define MCREG_FIELD_10_revAB(up, field) _MCREG_FIELD(up, 10_revAB, field) 302 303 /* 304 * We will only define the register bitfields for little-endian order 305 */ 306 #ifdef _BIT_FIELDS_LTOH 307 308 /* 309 * Function 0 - HT Configuration: Routing Table Node Register 310 */ 311 union mcreg_htroute { 312 uint32_t _val32; 313 struct { 314 uint32_t RQRte:4; /* 3:0 */ 315 uint32_t reserved1:4; /* 7:4 */ 316 uint32_t RPRte:4; /* 11:8 */ 317 uint32_t reserved2:4; /* 15:12 */ 318 uint32_t BCRte:4; /* 19:16 */ 319 uint32_t reserved3:12; /* 31:20 */ 320 } _fmt_cmn; 321 }; 322 323 /* 324 * Function 0 - HT Configuration: Node ID Register 325 */ 326 union mcreg_nodeid { 327 uint32_t _val32; 328 struct { 329 uint32_t NodeId:3; /* 2:0 */ 330 uint32_t reserved1:1; /* 3:3 */ 331 uint32_t NodeCnt:3; /* 6:4 */ 332 uint32_t reserved2:1; /* 7:7 */ 333 uint32_t SbNode:3; /* 10:8 */ 334 uint32_t reserved3:1; /* 11:11 */ 335 uint32_t LkNode:3; /* 14:12 */ 336 uint32_t reserved4:1; /* 15:15 */ 337 uint32_t CpuCnt:4; /* 19:16 */ 338 uint32_t reserved:12; /* 31:20 */ 339 } _fmt_cmn; 340 }; 341 342 #define HT_COHERENTNODES(up) (MCREG_FIELD_CMN(up, NodeCnt) + 1) 343 #define HT_SYSTEMCORECOUNT(up) (MCREG_FIELD_CMN(up, CpuCnt) + 1) 344 345 /* 346 * Function 0 - HT Configuration: Unit ID Register 347 */ 348 union mcreg_unitid { 349 uint32_t _val32; 350 struct { 351 uint32_t C0Unit:2; /* 1:0 */ 352 uint32_t C1Unit:2; /* 3:2 */ 353 uint32_t McUnit:2; /* 5:4 */ 354 uint32_t HbUnit:2; /* 7:6 */ 355 uint32_t SbLink:2; /* 9:8 */ 356 uint32_t reserved:22; /* 31:10 */ 357 } _fmt_cmn; 358 }; 359 360 /* 361 * Function 1 - DRAM Address Map: DRAM Base i Registers 362 * 363 */ 364 365 union mcreg_drambase { 366 uint32_t _val32; 367 struct { 368 uint32_t RE:1; /* 0:0 - Read Enable */ 369 uint32_t WE:1; /* 1:1 - Write Enable */ 370 uint32_t reserved1:6; /* 7:2 */ 371 uint32_t IntlvEn:3; /* 10:8 - Interleave Enable */ 372 uint32_t reserved2:5; /* 15:11 */ 373 uint32_t DRAMBasei:16; /* 31:16 - Base Addr 39:24 */ 374 } _fmt_cmn; 375 }; 376 377 #define MC_DRAMBASE(up) ((uint64_t)MCREG_FIELD_CMN(up, DRAMBasei) << 24) 378 379 /* 380 * Function 1 - DRAM Address Map: DRAM Limit i Registers 381 * 382 */ 383 384 union mcreg_dramlimit { 385 uint32_t _val32; 386 struct { 387 uint32_t DstNode:3; /* 2:0 - Destination Node */ 388 uint32_t reserved1:5; /* 7:3 */ 389 uint32_t IntlvSel:3; /* 10:8 - Interleave Select */ 390 uint32_t reserved2:5; /* 15:11 */ 391 uint32_t DRAMLimiti:16; /* 31:16 - Limit Addr 39:24 */ 392 } _fmt_cmn; 393 }; 394 395 #define MC_DRAMLIM(up) \ 396 ((uint64_t)MCREG_FIELD_CMN(up, DRAMLimiti) << 24 | \ 397 (MCREG_FIELD_CMN(up, DRAMLimiti) ? ((1 << 24) - 1) : 0)) 398 399 /* 400 * Function 1 - DRAM Address Map: DRAM Hole Address Register 401 */ 402 403 union mcreg_dramhole { 404 uint32_t _val32; 405 struct { 406 uint32_t DramHoleValid:1; /* 0:0 */ 407 uint32_t reserved1:7; /* 7:1 */ 408 uint32_t DramHoleOffset:8; /* 15:8 */ 409 uint32_t reserved2:8; /* 23:16 */ 410 uint32_t DramHoleBase:8; /* 31:24 */ 411 } _fmt_cmn; 412 }; 413 414 #define MC_DRAMHOLE_SIZE(up) (MCREG_FIELD_CMN(up, DramHoleOffset) << 24) 415 416 /* 417 * Function 2 - DRAM Controller: DRAM CS Base Address Registers 418 */ 419 420 union mcreg_csbase { 421 uint32_t _val32; 422 /* 423 * Register format in family 0xf revisions E and earlier 424 */ 425 struct { 426 uint32_t CSEnable:1; /* 0:0 - CS Bank Enable */ 427 uint32_t reserved1:8; /* 8:1 */ 428 uint32_t BaseAddrLo:7; /* 15:9 - Base Addr 19:13 */ 429 uint32_t reserved2:5; /* 20:16 */ 430 uint32_t BaseAddrHi:11; /* 31:21 - Base Addr 35:25 */ 431 } _fmt_f_preF; 432 /* 433 * Register format in family 0xf revisions F and G 434 */ 435 struct { 436 uint32_t CSEnable:1; /* 0:0 - CS Bank Enable */ 437 uint32_t Spare:1; /* 1:1 - Spare Rank */ 438 uint32_t TestFail:1; /* 2:2 - Memory Test Failed */ 439 uint32_t reserved1:2; /* 4:3 */ 440 uint32_t BaseAddrLo:9; /* 13:5 - Base Addr 21:13 */ 441 uint32_t reserved2:5; /* 18:14 */ 442 uint32_t BaseAddrHi:10; /* 28:19 - Base Addr 36:27 */ 443 uint32_t reserved3:3; /* 31:39 */ 444 } _fmt_f_revFG; 445 }; 446 447 #define MC_CSBASE(up, rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? \ 448 (uint64_t)MCREG_FIELD_F_revFG(up, BaseAddrHi) << 27 | \ 449 (uint64_t)MCREG_FIELD_F_revFG(up, BaseAddrLo) << 13 : \ 450 (uint64_t)MCREG_FIELD_F_preF(up, BaseAddrHi) << 25 | \ 451 (uint64_t)MCREG_FIELD_F_preF(up, BaseAddrLo) << 13) 452 453 /* 454 * Function 2 - DRAM Controller: DRAM CS Mask Registers 455 */ 456 457 union mcreg_csmask { 458 uint32_t _val32; 459 /* 460 * Register format in family 0xf revisions E and earlier 461 */ 462 struct { 463 uint32_t reserved1:9; /* 8:0 */ 464 uint32_t AddrMaskLo:7; /* 15:9 - Addr Mask 19:13 */ 465 uint32_t reserved2:5; /* 20:16 */ 466 uint32_t AddrMaskHi:9; /* 29:21 - Addr Mask 33:25 */ 467 uint32_t reserved3:2; /* 31:30 */ 468 } _fmt_f_preF; 469 /* 470 * Register format in family 0xf revisions F and G 471 */ 472 struct { 473 uint32_t reserved1:5; /* 4:0 */ 474 uint32_t AddrMaskLo:9; /* 13:5 - Addr Mask 21:13 */ 475 uint32_t reserved2:5; /* 18:14 */ 476 uint32_t AddrMaskHi:10; /* 28:19 - Addr Mask 36:27 */ 477 uint32_t reserved3:3; /* 31:29 */ 478 } _fmt_f_revFG; 479 }; 480 481 #define MC_CSMASKLO_LOBIT(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 13 : 13) 482 #define MC_CSMASKLO_HIBIT(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 21 : 19) 483 484 #define MC_CSMASKHI_LOBIT(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 27 : 25) 485 #define MC_CSMASKHI_HIBIT(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 36 : 33) 486 487 #define MC_CSMASK_UNMASKABLE(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 0 : 2) 488 489 #define MC_CSMASK(up, rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? \ 490 (uint64_t)MCREG_FIELD_F_revFG(up, AddrMaskHi) << 27 | \ 491 (uint64_t)MCREG_FIELD_F_revFG(up, AddrMaskLo) << 13 | 0x7c01fff : \ 492 (uint64_t)MCREG_FIELD_F_preF(up, AddrMaskHi) << 25 | \ 493 (uint64_t)MCREG_FIELD_F_preF(up, AddrMaskLo) << 13 | 0x1f01fff) 494 495 /* 496 * Function 2 - DRAM Controller: DRAM Bank Address Mapping Registers 497 */ 498 499 union mcreg_bankaddrmap { 500 uint32_t _val32; 501 /* 502 * Register format in family 0xf revisions E and earlier 503 */ 504 struct { 505 uint32_t cs10:4; /* 3:0 - CS1/0 */ 506 uint32_t cs32:4; /* 7:4 - CS3/2 */ 507 uint32_t cs54:4; /* 11:8 - CS5/4 */ 508 uint32_t cs76:4; /* 15:12 - CS7/6 */ 509 uint32_t reserved1:14; /* 29:16 */ 510 uint32_t BankSwizzleMode:1; /* 30:30 */ 511 uint32_t reserved2:1; /* 31:31 */ 512 } _fmt_f_preF; 513 /* 514 * Register format in family 0xf revisions F and G 515 */ 516 struct { 517 uint32_t cs10:4; /* 3:0 - CS1/0 */ 518 uint32_t cs32:4; /* 7:4 - CS3/2 */ 519 uint32_t cs54:4; /* 11:8 - CS5/4 */ 520 uint32_t cs76:4; /* 15:12 - CS7/6 */ 521 uint32_t reserved1:16; /* 31:16 */ 522 } _fmt_f_revFG; 523 /* 524 * Accessing all mode encodings as one uint16 525 */ 526 struct { 527 uint32_t allcsmodes:16; /* 15:0 */ 528 uint32_t pad:16; /* 31:16 */ 529 } _fmt_bankmodes; 530 }; 531 532 #define MC_DC_BAM_CSBANK_MASK 0x0000000f 533 #define MC_DC_BAM_CSBANK_SHIFT 4 534 535 #define MC_CSBANKMODE(up, csnum) ((up)->_fmt_bankmodes.allcsmodes >> \ 536 MC_DC_BAM_CSBANK_SHIFT * MC_CHIP_DIMMPAIR(csnum) & MC_DC_BAM_CSBANK_MASK) 537 538 /* 539 * Function 2 - DRAM Controller: DRAM Configuration Low and High 540 */ 541 542 union mcreg_dramcfg_lo { 543 uint32_t _val32; 544 /* 545 * Register format in family 0xf revisions E and earlier. 546 * Bit 7 is a BIOS ScratchBit in revs D and earlier, 547 * PwrDwnTriEn in revision E; we don't use it so 548 * we'll call it ambig1. 549 */ 550 struct { 551 uint32_t DLL_Dis:1; /* 0 */ 552 uint32_t D_DRV:1; /* 1 */ 553 uint32_t QFC_EN:1; /* 2 */ 554 uint32_t DisDqsHys:1; /* 3 */ 555 uint32_t reserved1:1; /* 4 */ 556 uint32_t Burst2Opt:1; /* 5 */ 557 uint32_t Mod64BitMux:1; /* 6 */ 558 uint32_t ambig1:1; /* 7 */ 559 uint32_t DramInit:1; /* 8 */ 560 uint32_t DualDimmEn:1; /* 9 */ 561 uint32_t DramEnable:1; /* 10 */ 562 uint32_t MemClrStatus:1; /* 11 */ 563 uint32_t ESR:1; /* 12 */ 564 uint32_t SR_S:1; /* 13 */ 565 uint32_t RdWrQByp:2; /* 15:14 */ 566 uint32_t Width128:1; /* 16 */ 567 uint32_t DimmEcEn:1; /* 17 */ 568 uint32_t UnBufDimm:1; /* 18 */ 569 uint32_t ByteEn32:1; /* 19 */ 570 uint32_t x4DIMMs:4; /* 23:20 */ 571 uint32_t DisInRcvrs:1; /* 24 */ 572 uint32_t BypMax:3; /* 27:25 */ 573 uint32_t En2T:1; /* 28 */ 574 uint32_t UpperCSMap:1; /* 29 */ 575 uint32_t PwrDownCtl:2; /* 31:30 */ 576 } _fmt_f_preF; 577 /* 578 * Register format in family 0xf revisions F and G 579 */ 580 struct { 581 uint32_t InitDram:1; /* 0 */ 582 uint32_t ExitSelfRef:1; /* 1 */ 583 uint32_t reserved1:2; /* 3:2 */ 584 uint32_t DramTerm:2; /* 5:4 */ 585 uint32_t reserved2:1; /* 6 */ 586 uint32_t DramDrvWeak:1; /* 7 */ 587 uint32_t ParEn:1; /* 8 */ 588 uint32_t SelRefRateEn:1; /* 9 */ 589 uint32_t BurstLength32:1; /* 10 */ 590 uint32_t Width128:1; /* 11 */ 591 uint32_t x4DIMMs:4; /* 15:12 */ 592 uint32_t UnBuffDimm:1; /* 16 */ 593 uint32_t reserved3:2; /* 18:17 */ 594 uint32_t DimmEccEn:1; /* 19 */ 595 uint32_t reserved4:12; /* 31:20 */ 596 } _fmt_f_revFG; 597 }; 598 599 /* 600 * Function 2 - DRAM Controller: DRAM Controller Miscellaneous Data 601 */ 602 603 union mcreg_drammisc { 604 uint32_t _val32; 605 /* 606 * Register format in family 0xf revisions F and G 607 */ 608 struct { 609 uint32_t reserved2:1; /* 0 */ 610 uint32_t DisableJitter:1; /* 1 */ 611 uint32_t RdWrQByp:2; /* 3:2 */ 612 uint32_t Mod64Mux:1; /* 4 */ 613 uint32_t DCC_EN:1; /* 5 */ 614 uint32_t ILD_lmt:3; /* 8:6 */ 615 uint32_t DramEnabled:1; /* 9 */ 616 uint32_t PwrSavingsEn:1; /* 10 */ 617 uint32_t reserved1:13; /* 23:11 */ 618 uint32_t MemClkDis:8; /* 31:24 */ 619 } _fmt_f_revFG; 620 }; 621 622 union mcreg_dramcfg_hi { 623 uint32_t _val32; 624 /* 625 * Register format in family 0xf revisions E and earlier. 626 */ 627 struct { 628 uint32_t AsyncLat:4; /* 3:0 */ 629 uint32_t reserved1:4; /* 7:4 */ 630 uint32_t RdPreamble:4; /* 11:8 */ 631 uint32_t reserved2:1; /* 12 */ 632 uint32_t MemDQDrvStren:2; /* 14:13 */ 633 uint32_t DisableJitter:1; /* 15 */ 634 uint32_t ILD_lmt:3; /* 18:16 */ 635 uint32_t DCC_EN:1; /* 19 */ 636 uint32_t MemClk:3; /* 22:20 */ 637 uint32_t reserved3:2; /* 24:23 */ 638 uint32_t MCR:1; /* 25 */ 639 uint32_t MC0_EN:1; /* 26 */ 640 uint32_t MC1_EN:1; /* 27 */ 641 uint32_t MC2_EN:1; /* 28 */ 642 uint32_t MC3_EN:1; /* 29 */ 643 uint32_t reserved4:1; /* 30 */ 644 uint32_t OddDivisorCorrect:1; /* 31 */ 645 } _fmt_f_preF; 646 /* 647 * Register format in family 0xf revisions F and G 648 */ 649 struct { 650 uint32_t MemClkFreq:3; /* 2:0 */ 651 uint32_t MemClkFreqVal:1; /* 3 */ 652 uint32_t MaxAsyncLat:4; /* 7:4 */ 653 uint32_t reserved1:4; /* 11:8 */ 654 uint32_t RDqsEn:1; /* 12 */ 655 uint32_t reserved2:1; /* 13 */ 656 uint32_t DisDramInterface:1; /* 14 */ 657 uint32_t PowerDownEn:1; /* 15 */ 658 uint32_t PowerDownMode:1; /* 16 */ 659 uint32_t FourRankSODimm:1; /* 17 */ 660 uint32_t FourRankRDimm:1; /* 18 */ 661 uint32_t reserved3:1; /* 19 */ 662 uint32_t SlowAccessMode:1; /* 20 */ 663 uint32_t reserved4:1; /* 21 */ 664 uint32_t BankSwizzleMode:1; /* 22 */ 665 uint32_t undocumented1:1; /* 23 */ 666 uint32_t DcqBypassMax:4; /* 27:24 */ 667 uint32_t FourActWindow:4; /* 31:28 */ 668 } _fmt_f_revFG; 669 }; 670 671 /* 672 * Function 3 - Miscellaneous Control: Scrub Control Register 673 */ 674 675 union mcreg_scrubctl { 676 uint32_t _val32; 677 struct { 678 uint32_t DramScrub:5; /* 4:0 */ 679 uint32_t reserved3:3; /* 7:5 */ 680 uint32_t L2Scrub:5; /* 12:8 */ 681 uint32_t reserved2:3; /* 15:13 */ 682 uint32_t DcacheScrub:5; /* 20:16 */ 683 uint32_t reserved1:11; /* 31:21 */ 684 } _fmt_cmn; 685 }; 686 687 union mcreg_dramscrublo { 688 uint32_t _val32; 689 struct { 690 uint32_t ScrubReDirEn:1; /* 0 */ 691 uint32_t reserved:5; /* 5:1 */ 692 uint32_t ScrubAddrLo:26; /* 31:6 */ 693 } _fmt_cmn; 694 }; 695 696 union mcreg_dramscrubhi { 697 uint32_t _val32; 698 struct { 699 uint32_t ScrubAddrHi:8; /* 7:0 */ 700 uint32_t reserved:24; /* 31:8 */ 701 } _fmt_cmn; 702 }; 703 704 /* 705 * Function 3 - Miscellaneous Control: On-Line Spare Control Register 706 */ 707 708 union mcreg_nbcfg { 709 uint32_t _val32; 710 /* 711 * Register format in family 0xf revisions E and earlier. 712 */ 713 struct { 714 uint32_t CpuEccErrEn:1; /* 0 */ 715 uint32_t CpuRdDatErrEn:1; /* 1 */ 716 uint32_t SyncOnUcEccEn:1; /* 2 */ 717 uint32_t SyncPktGenDis:1; /* 3 */ 718 uint32_t SyncPktPropDis:1; /* 4 */ 719 uint32_t IoMstAbortDis:1; /* 5 */ 720 uint32_t CpuErrDis:1; /* 6 */ 721 uint32_t IoErrDis:1; /* 7 */ 722 uint32_t WdogTmrDis:1; /* 8 */ 723 uint32_t WdogTmrCntSel:3; /* 11:9 */ 724 uint32_t WdogTmrBaseSel:2; /* 13:12 */ 725 uint32_t LdtLinkSel:2; /* 15:14 */ 726 uint32_t GenCrcErrByte0:1; /* 16 */ 727 uint32_t GenCrcErrByte1:1; /* 17 */ 728 uint32_t reserved1:2; /* 19:18 */ 729 uint32_t SyncOnWdogEn:1; /* 20 */ 730 uint32_t SyncOnAnyErrEn:1; /* 21 */ 731 uint32_t EccEn:1; /* 22 */ 732 uint32_t ChipKillEccEn:1; /* 23 */ 733 uint32_t IoRdDatErrEn:1; /* 24 */ 734 uint32_t DisPciCfgCpuErrRsp:1; /* 25 */ 735 uint32_t reserved2:1; /* 26 */ 736 uint32_t NbMcaToMstCpuEn:1; /* 27 */ 737 uint32_t reserved3:4; /* 31:28 */ 738 } _fmt_f_preF; 739 /* 740 * Register format in family 0xf revisions F and G 741 */ 742 struct { 743 uint32_t CpuEccErrEn:1; /* 0 */ 744 uint32_t CpuRdDatErrEn:1; /* 1 */ 745 uint32_t SyncOnUcEccEn:1; /* 2 */ 746 uint32_t SyncPktGenDis:1; /* 3 */ 747 uint32_t SyncPktPropDis:1; /* 4 */ 748 uint32_t IoMstAbortDis:1; /* 5 */ 749 uint32_t CpuErrDis:1; /* 6 */ 750 uint32_t IoErrDis:1; /* 7 */ 751 uint32_t WdogTmrDis:1; /* 8 */ 752 uint32_t WdogTmrCntSel:3; /* 11:9 */ 753 uint32_t WdogTmrBaseSel:2; /* 13:12 */ 754 uint32_t LdtLinkSel:2; /* 15:14 */ 755 uint32_t GenCrcErrByte0:1; /* 16 */ 756 uint32_t GenCrcErrByte1:1; /* 17 */ 757 uint32_t reserved1:2; /* 19:18 */ 758 uint32_t SyncOnWdogEn:1; /* 20 */ 759 uint32_t SyncOnAnyErrEn:1; /* 21 */ 760 uint32_t EccEn:1; /* 22 */ 761 uint32_t ChipKillEccEn:1; /* 23 */ 762 uint32_t IoRdDatErrEn:1; /* 24 */ 763 uint32_t DisPciCfgCpuErrRsp:1; /* 25 */ 764 uint32_t reserved2:1; /* 26 */ 765 uint32_t NbMcaToMstCpuEn:1; /* 27 */ 766 uint32_t DisTgtAbtCpuErrRsp:1; /* 28 */ 767 uint32_t DisMstAbtCpuErrRsp:1; /* 29 */ 768 uint32_t SyncOnDramAdrParErrEn:1; /* 30 */ 769 uint32_t reserved3:1; /* 31 */ 770 771 } _fmt_f_revFG; 772 }; 773 774 /* 775 * Function 3 - Miscellaneous Control: On-Line Spare Control Register 776 */ 777 778 union mcreg_sparectl { 779 uint32_t _val32; 780 /* 781 * Register format in family 0xf revisions F and G 782 */ 783 struct { 784 uint32_t SwapEn:1; /* 0 */ 785 uint32_t SwapDone:1; /* 1 */ 786 uint32_t reserved1:2; /* 3:2 */ 787 uint32_t BadDramCs:3; /* 6:4 */ 788 uint32_t reserved2:5; /* 11:7 */ 789 uint32_t SwapDoneInt:2; /* 13:12 */ 790 uint32_t EccErrInt:2; /* 15:14 */ 791 uint32_t EccErrCntDramCs:3; /* 18:16 */ 792 uint32_t reserved3:1; /* 19 */ 793 uint32_t EccErrCntDramChan:1; /* 20 */ 794 uint32_t reserved4:2; /* 22:21 */ 795 uint32_t EccErrCntWrEn:1; /* 23 */ 796 uint32_t EccErrCnt:4; /* 27:24 */ 797 uint32_t reserved5:4; /* 31:28 */ 798 } _fmt_f_revFG; 799 /* 800 * Regiser format in family 0x10 revisions A and B 801 */ 802 struct { 803 uint32_t SwapEn0:1; /* 0 */ 804 uint32_t SwapDone0:1; /* 1 */ 805 uint32_t SwapEn1:1; /* 2 */ 806 uint32_t SwapDone1:1; /* 3 */ 807 uint32_t BadDramCs0:3; /* 6:4 */ 808 uint32_t reserved1:1; /* 7 */ 809 uint32_t BadDramCs1:3; /* 10:8 */ 810 uint32_t reserved2:1; /* 11 */ 811 uint32_t SwapDoneInt:2; /* 13:12 */ 812 uint32_t EccErrInt:2; /* 15:14 */ 813 uint32_t EccErrCntDramCs:4; /* 19:16 */ 814 uint32_t EccErrCntDramChan:2; /* 21:20 */ 815 uint32_t reserved4:1; /* 22 */ 816 uint32_t EccErrCntWrEn:1; /* 23 */ 817 uint32_t EccErrCnt:4; /* 27:24 */ 818 uint32_t LvtOffset:4; /* 31:28 */ 819 } _fmt_10_revAB; 820 }; 821 822 /* 823 * Since the NB is on-chip some registers are also accessible as MSRs. 824 * We will represent such registers as bitfields as in the 32-bit PCI 825 * registers above, with the restriction that we must compile for 32-bit 826 * kernels and so 64-bit bitfields cannot be used. 827 */ 828 829 #define _MCMSR_FIELD(up, revsuffix, field) ((up)->_fmt_##revsuffix.field) 830 831 #define MCMSR_VAL(up) ((up)->_val64) 832 833 #define MCMSR_FIELD_CMN(up, field) _MCMSR_FIELD(up, cmn, field) 834 #define MCMSR_FIELD_F_preF(up, field) _MCMSR_FIELD(up, f_preF, field) 835 #define MCMSR_FIELD_F_revFG(up, field) _MCMSR_FIELD(up, f_revFG, field) 836 #define MCMSR_FIELD_10_revAB(up, field) _MCMSR_FIELD(up, 10_revAB, field) 837 838 /* 839 * The NB MISC registers. On family 0xf rev F this was introduced with 840 * a 12-bit ECC error count of all ECC errors observed on this memory- 841 * controller (regardless of channel or chip-select) and the ability to 842 * raise an interrupt or SMI on overflow. In family 0x10 it has a similar 843 * purpose, but the register is is split into 4 misc registers 844 * MC4_MISC{0,1,2,3} accessible via both MSRs and PCI config space; 845 * they perform thresholding for dram, l3, HT errors. 846 */ 847 848 union mcmsr_nbmisc { 849 uint64_t _val64; 850 /* 851 * MSR format in family 0xf revision F and later 852 */ 853 struct { 854 /* 855 * Lower 32 bits 856 */ 857 struct { 858 uint32_t _reserved; /* 31:0 */ 859 } _mcimisc_lo; 860 /* 861 * Upper 32 bits 862 */ 863 struct { 864 uint32_t _ErrCount:12; /* 43:32 */ 865 uint32_t _reserved1:4; /* 47:44 */ 866 uint32_t _Ovrflw:1; /* 48 */ 867 uint32_t _IntType:2; /* 50:49 */ 868 uint32_t _CntEn:1; /* 51 */ 869 uint32_t _LvtOff:4; /* 55:52 */ 870 uint32_t _reserved2:5; /* 60:56 */ 871 uint32_t _Locked:1; /* 61 */ 872 uint32_t _CntP:1; /* 62 */ 873 uint32_t _Valid:1; /* 63 */ 874 } _mcimisc_hi; 875 } _fmt_f_revFG; 876 /* 877 * MSR format in family 0x10 revisions A and B 878 */ 879 struct { 880 /* 881 * Lower 32 bits 882 */ 883 struct { 884 uint32_t _reserved:24; /* 23:0 */ 885 uint32_t _BlkPtr:8; /* 31:24 */ 886 } _mcimisc_lo; 887 /* 888 * Upper 32 bits 889 */ 890 struct { 891 uint32_t _ErrCnt:12; /* 43:32 */ 892 uint32_t _reserved1:4; /* 47:44 */ 893 uint32_t _Ovrflw:1; /* 48 */ 894 uint32_t _IntType:2; /* 50:49 */ 895 uint32_t _CntEn:1; /* 51 */ 896 uint32_t _LvtOff:4; /* 55:52 */ 897 uint32_t _reserved2:5; /* 60:56 */ 898 uint32_t _Locked:1; /* 61 */ 899 uint32_t _CntP:1; /* 62 */ 900 uint32_t _Valid:1; /* 63 */ 901 902 } _mcimisc_hi; 903 } _fmt_10_revAB; 904 }; 905 906 #define mcmisc_BlkPtr _mcimisc_lo._BlkPtr 907 #define mcmisc_ErrCount _mcimisc_hi._ErrCount 908 #define mcmisc_Ovrflw _mcimisc_hi._Ovrflw 909 #define mcmisc_IntType _mcimisc_hi._IntType 910 #define mcmisc_CntEn _mcimisc_hi._CntEn 911 #define mcmisc_LvtOff _mcimisc_hi._LvtOff 912 #define mcmisc_Locked _mcimisc_hi._Locked 913 #define mcmisc_CntP _mcimisc_hi._CntP 914 #define mcmisc_Valid _mcimisc_hi._Valid 915 916 #endif /* _BIT_FIELDS_LTOH */ 917 918 #ifdef __cplusplus 919 } 920 #endif 921 922 #endif /* _MC_AMD_H */ 923