xref: /illumos-gate/usr/src/uts/intel/sys/mc_amd.h (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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