summaryrefslogtreecommitdiff
path: root/usr/src/uts/intel/sys/mc_amd.h
blob: 91b4f9c4cbcf31d3861f3b579072ed5127342069 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
/*
 * 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 <sys/mc.h>
#include <sys/isa_defs.h>
#include <sys/x86_archext.h>

#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 */