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