/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _MC_AMD_H #define _MC_AMD_H #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Definitions, register offsets, register structure etc pertaining to * the memory controller on AMD64 systems. These are used by both the * AMD cpu module and the mc-amd driver. */ /* * The mc-amd driver exports an nvlist to userland, where the primary * consumer is the "chip" topology enumerator for this platform type which * builds a full topology subtree from this information. Others can use * it, too, but don't depend on it not changing without an ARC contract * (and the contract should probably concern the topology, not this nvlist). * * In the initial mc-amd implementation this nvlist was not versioned; * we'll think of that as version 0 and it may be recognised by the absence * of a "mcamd-nvlist-version member. * * Version 1 is defined as follows. A name in square brackets indicates * that member is optional (only present if the actual value is valid). * * Name Type Description * -------------------- --------------- --------------------------------------- * mcamd-nvlist-version uint8 Exported nvlist version number * num uint64 Chip id of this memory controller * revision uint64 cpuid_getchiprev() result * revname string cpuid_getchiprevstr() result * socket string "Socket 755|939|940|AM2|F(1207)|S1g1" * ecc-type string "ChipKill 128/16" or "Normal 64/8" * base-addr uint64 Node base address * lim-addr uint64 Node limit address * node-ilen uint64 0|1|3|7 for 0/2/4/8 way node interleave * node-ilsel uint64 Node interleave position of this node * cs-intlv-factor uint64 chip-select interleave: 1/2/4/8 * dram-hole-size uint64 size in bytes from dram hole addr reg * access-width uint64 MC mode, 64 or 128 bit * bank-mapping uint64 Raw DRAM Bank Address Mapping Register * bankswizzle uint64 1 if bank swizzling enabled; else 0 * mismatched-dimm-support uint64 1 if active; else 0 * [spare-csnum] uint64 Chip-select pair number of any spare * [bad-csnum] uint64 Chip-select pair number of swapped cs * cslist nvlist array See below; may have 0 members * dimmlist nvlist array See below; may have 0 members * * cslist is an array of nvlist, each as follows: * * Name Type Description * -------------------- --------------- --------------------------------------- * num uint64 Chip-select base/mask pair number * base-addr uint64 Chip-select base address (rel to node) * mask uint64 Chip-select mask * size uint64 Chip-select size in bytes * dimm1-num uint64 First dimm (lodimm if a pair) * dimm1-csname string Socket cs# line name for 1st dimm rank * [dimm2-num] uint64 Second dimm if applicable (updimm) * [dimm2-csname] string Socket cs# line name for 2nd dimm rank * * dimmlist is an array of nvlist, each as follows: * * Name Type Description * -------------------- --------------- --------------------------------------- * num uint64 DIMM instance number * size uint64 DIMM size in bytes * csnums uint64 array CS base/mask pair(s) on this DIMM * csnames string array Socket cs# line name(s) on this DIMM * * The n'th csnums entry corresponds to the n'th csnames entry */ #define MC_NVLIST_VERSTR "mcamd-nvlist-version" #define MC_NVLIST_VERS0 0 #define MC_NVLIST_VERS1 1 #define MC_NVLIST_VERS MC_NVLIST_VERS1 /* * Constants and feature/revision test macros that are not expected to vary * among different AMD family 0xf processor revisions. */ /* * Configuration constants */ #define MC_CHIP_MAXNODES 8 /* max number of MCs in system */ #define MC_CHIP_NDIMM 8 /* max dimms per MC */ #define MC_CHIP_NCS 8 /* number of chip-selects per MC */ #define MC_CHIP_NDRAMCHAN 2 /* maximum number of dram channels */ #define MC_CHIP_DIMMRANKMAX 4 /* largest number of ranks per dimm */ #define MC_CHIP_DIMMPERCS 2 /* max number of dimms per cs */ #define MC_CHIP_DIMMPAIR(csnum) (csnum / MC_CHIP_DIMMPERCS) /* * Memory controller registers are read via PCI config space accesses on * bus 0, device 0x18 + NodeId, and function as follows: * * Function 0: HyperTransport Technology Configuration * Function 1: Address Map * Function 2: DRAM Controller & HyperTransport Technology Trace Mode * Function 3: Miscellaneous Control */ #define MC_AMD_DEV_OFFSET 0x18 /* node ID + offset == PCI dev num */ enum mc_funcnum { MC_FUNC_HTCONFIG = 0, MC_FUNC_ADDRMAP = 1, MC_FUNC_DRAMCTL = 2, MC_FUNC_MISCCTL = 3 }; /* * For a given (bus, device, function) a particular offset selects the * desired register. All registers are 32-bits wide. * * Different family 0xf processor revisions vary slightly in the content * of these configuration registers. The biggest change is with rev F * where DDR2 support has been introduced along with some hardware-controlled * correctable memory error thresholding. Fortunately most of the config info * required by the mc-amd driver is similar across revisions. * * We will try to insulate most of the driver code from config register * details by reading all memory-controller PCI config registers that we * will need at driver attach time for each of functions 0 through 3, and * storing them in a "cooked" form as memory controller properties. * These are to be accessed directly where we have an mc_t to hand, otherwise * through mcamd_get_numprop. As such we expect most/all use of the * structures and macros defined below to be in those attach codepaths. */ /* * Function 0 (HT Config) offsets */ #define MC_HT_REG_RTBL_NODE_0 0x40 #define MC_HT_REG_RTBL_INCR 4 #define MC_HT_REG_NODEID 0x60 #define MC_HT_REG_UNITID 0x64 /* * Function 1 (address map) offsets for DRAM base, DRAM limit, DRAM hole * registers. */ #define MC_AM_REG_DRAMBASE_0 0x40 /* Offset for DRAM Base 0 */ #define MC_AM_REG_DRAMLIM_0 0x44 /* Offset for DRAM Limit 0 */ #define MC_AM_REG_DRAM_INCR 8 /* incr between base/limit pairs */ #define MC_AM_REG_HOLEADDR 0xf0 /* DRAM Hole Address Register */ /* * Function 2 (dram controller) offsets for chip-select base, chip-select mask, * DRAM bank address mapping, DRAM configuration registers. */ #define MC_DC_REG_CS_INCR 4 /* incr for CS base and mask */ #define MC_DC_REG_CSBASE_0 0x40 /* 0x40 - 0x5c */ #define MC_DC_REG_CSMASK_0 0x60 /* 0x60 - 0x7c */ #define MC_DC_REG_BANKADDRMAP 0x80 /* DRAM Bank Address Mapping */ #define MC_DC_REG_DRAMCFGLO 0x90 /* DRAM Configuration Low */ #define MC_DC_REG_DRAMCFGHI 0x94 /* DRAM Configuration High */ #define MC_DC_REG_DRAMMISC 0xa0 /* DRAM Miscellaneous */ /* * Function 3 (misc control) offset for NB MCA config, scrubber control, * online spare control and NB capabilities. */ #define MC_CTL_REG_NBCFG 0x44 /* MCA NB configuration register */ #define MC_CTL_REG_SCRUBCTL 0x58 /* Scrub control register */ #define MC_CTL_REG_SCRUBADDR_LO 0x5c /* DRAM Scrub Address Low */ #define MC_CTL_REG_SCRUBADDR_HI 0x60 /* DRAM Scrub Address High */ #define MC_CTL_REG_SPARECTL 0xb0 /* On-line spare control register */ #define MC_CTL_REG_NBCAP 0xe8 /* NB Capabilities */ #define MC_CTL_REG_EXTNBCFG 0x180 /* Ext. MCA NB configuration register */ #define MC_NBCAP_L3CAPABLE (1U << 25) #define MC_NBCAP_MULTINODECPU (1U << 29) #define MC_EXTNBCFG_ECCSYMSZ (1U << 25) /* * MC4_MISC MSR and MC4_MISCj MSRs */ #define MC_MSR_NB_MISC0 0x413 #define MC_MSR_NB_MISC1 0xc0000408 #define MC_MSR_NB_MISC2 0xc0000409 #define MC_MSR_NB_MISC3 0xc000040a #define MC_MSR_NB_MISC(j) \ ((j) == 0 ? MC_MSR_NB_MISC0 : MC_MSR_NB_MISC1 + (j) - 1) /* * PCI registers will be represented as unions, with one fixed-width unsigned * integer member providing access to the raw register value and one or more * structs breaking the register out into bitfields (more than one struct if * the register definitions varies across processor revisions). * * The "raw" union member will always be '_val32'. Use MCREG_VAL32 to * access this member. * * The bitfield structs are all named _fmt_xxx where xxx identifies the * processor revision to which it applies. At this point the only xxx * values in use are: * 'cmn' - applies to all revisions * 'f_preF' - applies to revisions E and earlier * 'f_revFG' - applies to revisions F and G * * Variants such as 'preD', 'revDE', 'postCG' etc should be introduced * as requirements arise. The MC_REV_* and MC_REV_MATCH etc macros * will also need to grow to match. Use MCREG_FIELD_* to access the * individual bitfields of a register, perhaps using MC_REV_* and MC_REV_MATCH * to decide which revision suffix to provide. Where a bitfield appears * in different revisions but has the same use it should be named identically * (even if the BKDG varies a little) so that the MC_REG_FIELD_* macros * can lookup that member based on revision only. */ #define MC_REV_UNKNOWN X86_CHIPREV_UNKNOWN #define MC_F_REV_B X86_CHIPREV_AMD_F_REV_B #define MC_F_REV_C (X86_CHIPREV_AMD_F_REV_C0 | X86_CHIPREV_AMD_F_REV_CG) #define MC_F_REV_D X86_CHIPREV_AMD_F_REV_D #define MC_F_REV_E X86_CHIPREV_AMD_F_REV_E #define MC_F_REV_F X86_CHIPREV_AMD_F_REV_F #define MC_F_REV_G X86_CHIPREV_AMD_F_REV_G #define MC_10_REV_A X86_CHIPREV_AMD_10_REV_A #define MC_10_REV_B X86_CHIPREV_AMD_10_REV_B /* * The most common groupings for memory controller features. */ #define MC_F_REVS_BC (MC_F_REV_B | MC_F_REV_C) #define MC_F_REVS_DE (MC_F_REV_D | MC_F_REV_E) #define MC_F_REVS_BCDE (MC_F_REVS_BC | MC_F_REVS_DE) #define MC_F_REVS_FG (MC_F_REV_F | MC_F_REV_G) #define MC_10_REVS_AB (MC_10_REV_A | MC_10_REV_B) /* * Is 'rev' included in the 'revmask' bitmask? */ #define MC_REV_MATCH(rev, revmask) X86_CHIPREV_MATCH(rev, revmask) /* * Is 'rev' at least revision 'revmin' or greater */ #define MC_REV_ATLEAST(rev, minrev) X86_CHIPREV_ATLEAST(rev, minrev) #define _MCREG_FIELD(up, revsuffix, field) ((up)->_fmt_##revsuffix.field) #define MCREG_VAL32(up) ((up)->_val32) /* * Access a field that has the same structure in all families and revisions */ #define MCREG_FIELD_CMN(up, field) _MCREG_FIELD(up, cmn, field) /* * Access a field as defined for family 0xf prior to revision F */ #define MCREG_FIELD_F_preF(up, field) _MCREG_FIELD(up, f_preF, field) /* * Access a field as defined for family 0xf revisions F and G */ #define MCREG_FIELD_F_revFG(up, field) _MCREG_FIELD(up, f_revFG, field) /* * Access a field as defined for family 0x10 revisions A and */ #define MCREG_FIELD_10_revAB(up, field) _MCREG_FIELD(up, 10_revAB, field) /* * We will only define the register bitfields for little-endian order */ #ifdef _BIT_FIELDS_LTOH /* * Function 0 - HT Configuration: Routing Table Node Register */ union mcreg_htroute { uint32_t _val32; struct { uint32_t RQRte:4; /* 3:0 */ uint32_t reserved1:4; /* 7:4 */ uint32_t RPRte:4; /* 11:8 */ uint32_t reserved2:4; /* 15:12 */ uint32_t BCRte:4; /* 19:16 */ uint32_t reserved3:12; /* 31:20 */ } _fmt_cmn; }; /* * Function 0 - HT Configuration: Node ID Register */ union mcreg_nodeid { uint32_t _val32; struct { uint32_t NodeId:3; /* 2:0 */ uint32_t reserved1:1; /* 3:3 */ uint32_t NodeCnt:3; /* 6:4 */ uint32_t reserved2:1; /* 7:7 */ uint32_t SbNode:3; /* 10:8 */ uint32_t reserved3:1; /* 11:11 */ uint32_t LkNode:3; /* 14:12 */ uint32_t reserved4:1; /* 15:15 */ uint32_t CpuCnt:4; /* 19:16 */ uint32_t reserved:12; /* 31:20 */ } _fmt_cmn; }; #define HT_COHERENTNODES(up) (MCREG_FIELD_CMN(up, NodeCnt) + 1) #define HT_SYSTEMCORECOUNT(up) (MCREG_FIELD_CMN(up, CpuCnt) + 1) /* * Function 0 - HT Configuration: Unit ID Register */ union mcreg_unitid { uint32_t _val32; struct { uint32_t C0Unit:2; /* 1:0 */ uint32_t C1Unit:2; /* 3:2 */ uint32_t McUnit:2; /* 5:4 */ uint32_t HbUnit:2; /* 7:6 */ uint32_t SbLink:2; /* 9:8 */ uint32_t reserved:22; /* 31:10 */ } _fmt_cmn; }; /* * Function 1 - DRAM Address Map: DRAM Base i Registers * */ union mcreg_drambase { uint32_t _val32; struct { uint32_t RE:1; /* 0:0 - Read Enable */ uint32_t WE:1; /* 1:1 - Write Enable */ uint32_t reserved1:6; /* 7:2 */ uint32_t IntlvEn:3; /* 10:8 - Interleave Enable */ uint32_t reserved2:5; /* 15:11 */ uint32_t DRAMBasei:16; /* 31:16 - Base Addr 39:24 */ } _fmt_cmn; }; #define MC_DRAMBASE(up) ((uint64_t)MCREG_FIELD_CMN(up, DRAMBasei) << 24) /* * Function 1 - DRAM Address Map: DRAM Limit i Registers * */ union mcreg_dramlimit { uint32_t _val32; struct { uint32_t DstNode:3; /* 2:0 - Destination Node */ uint32_t reserved1:5; /* 7:3 */ uint32_t IntlvSel:3; /* 10:8 - Interleave Select */ uint32_t reserved2:5; /* 15:11 */ uint32_t DRAMLimiti:16; /* 31:16 - Limit Addr 39:24 */ } _fmt_cmn; }; #define MC_DRAMLIM(up) \ ((uint64_t)MCREG_FIELD_CMN(up, DRAMLimiti) << 24 | \ (MCREG_FIELD_CMN(up, DRAMLimiti) ? ((1 << 24) - 1) : 0)) /* * Function 1 - DRAM Address Map: DRAM Hole Address Register */ union mcreg_dramhole { uint32_t _val32; struct { uint32_t DramHoleValid:1; /* 0:0 */ uint32_t reserved1:7; /* 7:1 */ uint32_t DramHoleOffset:8; /* 15:8 */ uint32_t reserved2:8; /* 23:16 */ uint32_t DramHoleBase:8; /* 31:24 */ } _fmt_cmn; }; #define MC_DRAMHOLE_SIZE(up) (MCREG_FIELD_CMN(up, DramHoleOffset) << 24) /* * Function 2 - DRAM Controller: DRAM CS Base Address Registers */ union mcreg_csbase { uint32_t _val32; /* * Register format in family 0xf revisions E and earlier */ struct { uint32_t CSEnable:1; /* 0:0 - CS Bank Enable */ uint32_t reserved1:8; /* 8:1 */ uint32_t BaseAddrLo:7; /* 15:9 - Base Addr 19:13 */ uint32_t reserved2:5; /* 20:16 */ uint32_t BaseAddrHi:11; /* 31:21 - Base Addr 35:25 */ } _fmt_f_preF; /* * Register format in family 0xf revisions F and G */ struct { uint32_t CSEnable:1; /* 0:0 - CS Bank Enable */ uint32_t Spare:1; /* 1:1 - Spare Rank */ uint32_t TestFail:1; /* 2:2 - Memory Test Failed */ uint32_t reserved1:2; /* 4:3 */ uint32_t BaseAddrLo:9; /* 13:5 - Base Addr 21:13 */ uint32_t reserved2:5; /* 18:14 */ uint32_t BaseAddrHi:10; /* 28:19 - Base Addr 36:27 */ uint32_t reserved3:3; /* 31:39 */ } _fmt_f_revFG; }; #define MC_CSBASE(up, rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? \ (uint64_t)MCREG_FIELD_F_revFG(up, BaseAddrHi) << 27 | \ (uint64_t)MCREG_FIELD_F_revFG(up, BaseAddrLo) << 13 : \ (uint64_t)MCREG_FIELD_F_preF(up, BaseAddrHi) << 25 | \ (uint64_t)MCREG_FIELD_F_preF(up, BaseAddrLo) << 13) /* * Function 2 - DRAM Controller: DRAM CS Mask Registers */ union mcreg_csmask { uint32_t _val32; /* * Register format in family 0xf revisions E and earlier */ struct { uint32_t reserved1:9; /* 8:0 */ uint32_t AddrMaskLo:7; /* 15:9 - Addr Mask 19:13 */ uint32_t reserved2:5; /* 20:16 */ uint32_t AddrMaskHi:9; /* 29:21 - Addr Mask 33:25 */ uint32_t reserved3:2; /* 31:30 */ } _fmt_f_preF; /* * Register format in family 0xf revisions F and G */ struct { uint32_t reserved1:5; /* 4:0 */ uint32_t AddrMaskLo:9; /* 13:5 - Addr Mask 21:13 */ uint32_t reserved2:5; /* 18:14 */ uint32_t AddrMaskHi:10; /* 28:19 - Addr Mask 36:27 */ uint32_t reserved3:3; /* 31:29 */ } _fmt_f_revFG; }; #define MC_CSMASKLO_LOBIT(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 13 : 13) #define MC_CSMASKLO_HIBIT(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 21 : 19) #define MC_CSMASKHI_LOBIT(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 27 : 25) #define MC_CSMASKHI_HIBIT(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 36 : 33) #define MC_CSMASK_UNMASKABLE(rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? 0 : 2) #define MC_CSMASK(up, rev) (MC_REV_MATCH(rev, MC_F_REVS_FG) ? \ (uint64_t)MCREG_FIELD_F_revFG(up, AddrMaskHi) << 27 | \ (uint64_t)MCREG_FIELD_F_revFG(up, AddrMaskLo) << 13 | 0x7c01fff : \ (uint64_t)MCREG_FIELD_F_preF(up, AddrMaskHi) << 25 | \ (uint64_t)MCREG_FIELD_F_preF(up, AddrMaskLo) << 13 | 0x1f01fff) /* * Function 2 - DRAM Controller: DRAM Bank Address Mapping Registers */ union mcreg_bankaddrmap { uint32_t _val32; /* * Register format in family 0xf revisions E and earlier */ struct { uint32_t cs10:4; /* 3:0 - CS1/0 */ uint32_t cs32:4; /* 7:4 - CS3/2 */ uint32_t cs54:4; /* 11:8 - CS5/4 */ uint32_t cs76:4; /* 15:12 - CS7/6 */ uint32_t reserved1:14; /* 29:16 */ uint32_t BankSwizzleMode:1; /* 30:30 */ uint32_t reserved2:1; /* 31:31 */ } _fmt_f_preF; /* * Register format in family 0xf revisions F and G */ struct { uint32_t cs10:4; /* 3:0 - CS1/0 */ uint32_t cs32:4; /* 7:4 - CS3/2 */ uint32_t cs54:4; /* 11:8 - CS5/4 */ uint32_t cs76:4; /* 15:12 - CS7/6 */ uint32_t reserved1:16; /* 31:16 */ } _fmt_f_revFG; /* * Accessing all mode encodings as one uint16 */ struct { uint32_t allcsmodes:16; /* 15:0 */ uint32_t pad:16; /* 31:16 */ } _fmt_bankmodes; }; #define MC_DC_BAM_CSBANK_MASK 0x0000000f #define MC_DC_BAM_CSBANK_SHIFT 4 #define MC_CSBANKMODE(up, csnum) ((up)->_fmt_bankmodes.allcsmodes >> \ MC_DC_BAM_CSBANK_SHIFT * MC_CHIP_DIMMPAIR(csnum) & MC_DC_BAM_CSBANK_MASK) /* * Function 2 - DRAM Controller: DRAM Configuration Low and High */ union mcreg_dramcfg_lo { uint32_t _val32; /* * Register format in family 0xf revisions E and earlier. * Bit 7 is a BIOS ScratchBit in revs D and earlier, * PwrDwnTriEn in revision E; we don't use it so * we'll call it ambig1. */ struct { uint32_t DLL_Dis:1; /* 0 */ uint32_t D_DRV:1; /* 1 */ uint32_t QFC_EN:1; /* 2 */ uint32_t DisDqsHys:1; /* 3 */ uint32_t reserved1:1; /* 4 */ uint32_t Burst2Opt:1; /* 5 */ uint32_t Mod64BitMux:1; /* 6 */ uint32_t ambig1:1; /* 7 */ uint32_t DramInit:1; /* 8 */ uint32_t DualDimmEn:1; /* 9 */ uint32_t DramEnable:1; /* 10 */ uint32_t MemClrStatus:1; /* 11 */ uint32_t ESR:1; /* 12 */ uint32_t SR_S:1; /* 13 */ uint32_t RdWrQByp:2; /* 15:14 */ uint32_t Width128:1; /* 16 */ uint32_t DimmEcEn:1; /* 17 */ uint32_t UnBufDimm:1; /* 18 */ uint32_t ByteEn32:1; /* 19 */ uint32_t x4DIMMs:4; /* 23:20 */ uint32_t DisInRcvrs:1; /* 24 */ uint32_t BypMax:3; /* 27:25 */ uint32_t En2T:1; /* 28 */ uint32_t UpperCSMap:1; /* 29 */ uint32_t PwrDownCtl:2; /* 31:30 */ } _fmt_f_preF; /* * Register format in family 0xf revisions F and G */ struct { uint32_t InitDram:1; /* 0 */ uint32_t ExitSelfRef:1; /* 1 */ uint32_t reserved1:2; /* 3:2 */ uint32_t DramTerm:2; /* 5:4 */ uint32_t reserved2:1; /* 6 */ uint32_t DramDrvWeak:1; /* 7 */ uint32_t ParEn:1; /* 8 */ uint32_t SelRefRateEn:1; /* 9 */ uint32_t BurstLength32:1; /* 10 */ uint32_t Width128:1; /* 11 */ uint32_t x4DIMMs:4; /* 15:12 */ uint32_t UnBuffDimm:1; /* 16 */ uint32_t reserved3:2; /* 18:17 */ uint32_t DimmEccEn:1; /* 19 */ uint32_t reserved4:12; /* 31:20 */ } _fmt_f_revFG; }; /* * Function 2 - DRAM Controller: DRAM Controller Miscellaneous Data */ union mcreg_drammisc { uint32_t _val32; /* * Register format in family 0xf revisions F and G */ struct { uint32_t reserved2:1; /* 0 */ uint32_t DisableJitter:1; /* 1 */ uint32_t RdWrQByp:2; /* 3:2 */ uint32_t Mod64Mux:1; /* 4 */ uint32_t DCC_EN:1; /* 5 */ uint32_t ILD_lmt:3; /* 8:6 */ uint32_t DramEnabled:1; /* 9 */ uint32_t PwrSavingsEn:1; /* 10 */ uint32_t reserved1:13; /* 23:11 */ uint32_t MemClkDis:8; /* 31:24 */ } _fmt_f_revFG; }; union mcreg_dramcfg_hi { uint32_t _val32; /* * Register format in family 0xf revisions E and earlier. */ struct { uint32_t AsyncLat:4; /* 3:0 */ uint32_t reserved1:4; /* 7:4 */ uint32_t RdPreamble:4; /* 11:8 */ uint32_t reserved2:1; /* 12 */ uint32_t MemDQDrvStren:2; /* 14:13 */ uint32_t DisableJitter:1; /* 15 */ uint32_t ILD_lmt:3; /* 18:16 */ uint32_t DCC_EN:1; /* 19 */ uint32_t MemClk:3; /* 22:20 */ uint32_t reserved3:2; /* 24:23 */ uint32_t MCR:1; /* 25 */ uint32_t MC0_EN:1; /* 26 */ uint32_t MC1_EN:1; /* 27 */ uint32_t MC2_EN:1; /* 28 */ uint32_t MC3_EN:1; /* 29 */ uint32_t reserved4:1; /* 30 */ uint32_t OddDivisorCorrect:1; /* 31 */ } _fmt_f_preF; /* * Register format in family 0xf revisions F and G */ struct { uint32_t MemClkFreq:3; /* 2:0 */ uint32_t MemClkFreqVal:1; /* 3 */ uint32_t MaxAsyncLat:4; /* 7:4 */ uint32_t reserved1:4; /* 11:8 */ uint32_t RDqsEn:1; /* 12 */ uint32_t reserved2:1; /* 13 */ uint32_t DisDramInterface:1; /* 14 */ uint32_t PowerDownEn:1; /* 15 */ uint32_t PowerDownMode:1; /* 16 */ uint32_t FourRankSODimm:1; /* 17 */ uint32_t FourRankRDimm:1; /* 18 */ uint32_t reserved3:1; /* 19 */ uint32_t SlowAccessMode:1; /* 20 */ uint32_t reserved4:1; /* 21 */ uint32_t BankSwizzleMode:1; /* 22 */ uint32_t undocumented1:1; /* 23 */ uint32_t DcqBypassMax:4; /* 27:24 */ uint32_t FourActWindow:4; /* 31:28 */ } _fmt_f_revFG; }; /* * Function 3 - Miscellaneous Control: Scrub Control Register */ union mcreg_scrubctl { uint32_t _val32; struct { uint32_t DramScrub:5; /* 4:0 */ uint32_t reserved3:3; /* 7:5 */ uint32_t L2Scrub:5; /* 12:8 */ uint32_t reserved2:3; /* 15:13 */ uint32_t DcacheScrub:5; /* 20:16 */ uint32_t reserved1:11; /* 31:21 */ } _fmt_cmn; }; union mcreg_dramscrublo { uint32_t _val32; struct { uint32_t ScrubReDirEn:1; /* 0 */ uint32_t reserved:5; /* 5:1 */ uint32_t ScrubAddrLo:26; /* 31:6 */ } _fmt_cmn; }; union mcreg_dramscrubhi { uint32_t _val32; struct { uint32_t ScrubAddrHi:8; /* 7:0 */ uint32_t reserved:24; /* 31:8 */ } _fmt_cmn; }; /* * Function 3 - Miscellaneous Control: On-Line Spare Control Register */ union mcreg_nbcfg { uint32_t _val32; /* * Register format in family 0xf revisions E and earlier. */ struct { uint32_t CpuEccErrEn:1; /* 0 */ uint32_t CpuRdDatErrEn:1; /* 1 */ uint32_t SyncOnUcEccEn:1; /* 2 */ uint32_t SyncPktGenDis:1; /* 3 */ uint32_t SyncPktPropDis:1; /* 4 */ uint32_t IoMstAbortDis:1; /* 5 */ uint32_t CpuErrDis:1; /* 6 */ uint32_t IoErrDis:1; /* 7 */ uint32_t WdogTmrDis:1; /* 8 */ uint32_t WdogTmrCntSel:3; /* 11:9 */ uint32_t WdogTmrBaseSel:2; /* 13:12 */ uint32_t LdtLinkSel:2; /* 15:14 */ uint32_t GenCrcErrByte0:1; /* 16 */ uint32_t GenCrcErrByte1:1; /* 17 */ uint32_t reserved1:2; /* 19:18 */ uint32_t SyncOnWdogEn:1; /* 20 */ uint32_t SyncOnAnyErrEn:1; /* 21 */ uint32_t EccEn:1; /* 22 */ uint32_t ChipKillEccEn:1; /* 23 */ uint32_t IoRdDatErrEn:1; /* 24 */ uint32_t DisPciCfgCpuErrRsp:1; /* 25 */ uint32_t reserved2:1; /* 26 */ uint32_t NbMcaToMstCpuEn:1; /* 27 */ uint32_t reserved3:4; /* 31:28 */ } _fmt_f_preF; /* * Register format in family 0xf revisions F and G */ struct { uint32_t CpuEccErrEn:1; /* 0 */ uint32_t CpuRdDatErrEn:1; /* 1 */ uint32_t SyncOnUcEccEn:1; /* 2 */ uint32_t SyncPktGenDis:1; /* 3 */ uint32_t SyncPktPropDis:1; /* 4 */ uint32_t IoMstAbortDis:1; /* 5 */ uint32_t CpuErrDis:1; /* 6 */ uint32_t IoErrDis:1; /* 7 */ uint32_t WdogTmrDis:1; /* 8 */ uint32_t WdogTmrCntSel:3; /* 11:9 */ uint32_t WdogTmrBaseSel:2; /* 13:12 */ uint32_t LdtLinkSel:2; /* 15:14 */ uint32_t GenCrcErrByte0:1; /* 16 */ uint32_t GenCrcErrByte1:1; /* 17 */ uint32_t reserved1:2; /* 19:18 */ uint32_t SyncOnWdogEn:1; /* 20 */ uint32_t SyncOnAnyErrEn:1; /* 21 */ uint32_t EccEn:1; /* 22 */ uint32_t ChipKillEccEn:1; /* 23 */ uint32_t IoRdDatErrEn:1; /* 24 */ uint32_t DisPciCfgCpuErrRsp:1; /* 25 */ uint32_t reserved2:1; /* 26 */ uint32_t NbMcaToMstCpuEn:1; /* 27 */ uint32_t DisTgtAbtCpuErrRsp:1; /* 28 */ uint32_t DisMstAbtCpuErrRsp:1; /* 29 */ uint32_t SyncOnDramAdrParErrEn:1; /* 30 */ uint32_t reserved3:1; /* 31 */ } _fmt_f_revFG; }; /* * Function 3 - Miscellaneous Control: On-Line Spare Control Register */ union mcreg_sparectl { uint32_t _val32; /* * Register format in family 0xf revisions F and G */ struct { uint32_t SwapEn:1; /* 0 */ uint32_t SwapDone:1; /* 1 */ uint32_t reserved1:2; /* 3:2 */ uint32_t BadDramCs:3; /* 6:4 */ uint32_t reserved2:5; /* 11:7 */ uint32_t SwapDoneInt:2; /* 13:12 */ uint32_t EccErrInt:2; /* 15:14 */ uint32_t EccErrCntDramCs:3; /* 18:16 */ uint32_t reserved3:1; /* 19 */ uint32_t EccErrCntDramChan:1; /* 20 */ uint32_t reserved4:2; /* 22:21 */ uint32_t EccErrCntWrEn:1; /* 23 */ uint32_t EccErrCnt:4; /* 27:24 */ uint32_t reserved5:4; /* 31:28 */ } _fmt_f_revFG; /* * Regiser format in family 0x10 revisions A and B */ struct { uint32_t SwapEn0:1; /* 0 */ uint32_t SwapDone0:1; /* 1 */ uint32_t SwapEn1:1; /* 2 */ uint32_t SwapDone1:1; /* 3 */ uint32_t BadDramCs0:3; /* 6:4 */ uint32_t reserved1:1; /* 7 */ uint32_t BadDramCs1:3; /* 10:8 */ uint32_t reserved2:1; /* 11 */ uint32_t SwapDoneInt:2; /* 13:12 */ uint32_t EccErrInt:2; /* 15:14 */ uint32_t EccErrCntDramCs:4; /* 19:16 */ uint32_t EccErrCntDramChan:2; /* 21:20 */ uint32_t reserved4:1; /* 22 */ uint32_t EccErrCntWrEn:1; /* 23 */ uint32_t EccErrCnt:4; /* 27:24 */ uint32_t LvtOffset:4; /* 31:28 */ } _fmt_10_revAB; }; /* * Since the NB is on-chip some registers are also accessible as MSRs. * We will represent such registers as bitfields as in the 32-bit PCI * registers above, with the restriction that we must compile for 32-bit * kernels and so 64-bit bitfields cannot be used. */ #define _MCMSR_FIELD(up, revsuffix, field) ((up)->_fmt_##revsuffix.field) #define MCMSR_VAL(up) ((up)->_val64) #define MCMSR_FIELD_CMN(up, field) _MCMSR_FIELD(up, cmn, field) #define MCMSR_FIELD_F_preF(up, field) _MCMSR_FIELD(up, f_preF, field) #define MCMSR_FIELD_F_revFG(up, field) _MCMSR_FIELD(up, f_revFG, field) #define MCMSR_FIELD_10_revAB(up, field) _MCMSR_FIELD(up, 10_revAB, field) /* * The NB MISC registers. On family 0xf rev F this was introduced with * a 12-bit ECC error count of all ECC errors observed on this memory- * controller (regardless of channel or chip-select) and the ability to * raise an interrupt or SMI on overflow. In family 0x10 it has a similar * purpose, but the register is is split into 4 misc registers * MC4_MISC{0,1,2,3} accessible via both MSRs and PCI config space; * they perform thresholding for dram, l3, HT errors. */ union mcmsr_nbmisc { uint64_t _val64; /* * MSR format in family 0xf revision F and later */ struct { /* * Lower 32 bits */ struct { uint32_t _reserved; /* 31:0 */ } _mcimisc_lo; /* * Upper 32 bits */ struct { uint32_t _ErrCount:12; /* 43:32 */ uint32_t _reserved1:4; /* 47:44 */ uint32_t _Ovrflw:1; /* 48 */ uint32_t _IntType:2; /* 50:49 */ uint32_t _CntEn:1; /* 51 */ uint32_t _LvtOff:4; /* 55:52 */ uint32_t _reserved2:5; /* 60:56 */ uint32_t _Locked:1; /* 61 */ uint32_t _CntP:1; /* 62 */ uint32_t _Valid:1; /* 63 */ } _mcimisc_hi; } _fmt_f_revFG; /* * MSR format in family 0x10 revisions A and B */ struct { /* * Lower 32 bits */ struct { uint32_t _reserved:24; /* 23:0 */ uint32_t _BlkPtr:8; /* 31:24 */ } _mcimisc_lo; /* * Upper 32 bits */ struct { uint32_t _ErrCnt:12; /* 43:32 */ uint32_t _reserved1:4; /* 47:44 */ uint32_t _Ovrflw:1; /* 48 */ uint32_t _IntType:2; /* 50:49 */ uint32_t _CntEn:1; /* 51 */ uint32_t _LvtOff:4; /* 55:52 */ uint32_t _reserved2:5; /* 60:56 */ uint32_t _Locked:1; /* 61 */ uint32_t _CntP:1; /* 62 */ uint32_t _Valid:1; /* 63 */ } _mcimisc_hi; } _fmt_10_revAB; }; #define mcmisc_BlkPtr _mcimisc_lo._BlkPtr #define mcmisc_ErrCount _mcimisc_hi._ErrCount #define mcmisc_Ovrflw _mcimisc_hi._Ovrflw #define mcmisc_IntType _mcimisc_hi._IntType #define mcmisc_CntEn _mcimisc_hi._CntEn #define mcmisc_LvtOff _mcimisc_hi._LvtOff #define mcmisc_Locked _mcimisc_hi._Locked #define mcmisc_CntP _mcimisc_hi._CntP #define mcmisc_Valid _mcimisc_hi._Valid #endif /* _BIT_FIELDS_LTOH */ #ifdef __cplusplus } #endif #endif /* _MC_AMD_H */