18a40a695Sgavinm /*
28a40a695Sgavinm  * CDDL HEADER START
38a40a695Sgavinm  *
48a40a695Sgavinm  * The contents of this file are subject to the terms of the
58a40a695Sgavinm  * Common Development and Distribution License (the "License").
68a40a695Sgavinm  * You may not use this file except in compliance with the License.
78a40a695Sgavinm  *
88a40a695Sgavinm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98a40a695Sgavinm  * or http://www.opensolaris.org/os/licensing.
108a40a695Sgavinm  * See the License for the specific language governing permissions
118a40a695Sgavinm  * and limitations under the License.
128a40a695Sgavinm  *
138a40a695Sgavinm  * When distributing Covered Code, include this CDDL HEADER in each
148a40a695Sgavinm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158a40a695Sgavinm  * If applicable, add the following below this CDDL HEADER, with the
168a40a695Sgavinm  * fields enclosed by brackets "[]" replaced with your own identifying
178a40a695Sgavinm  * information: Portions Copyright [yyyy] [name of copyright owner]
188a40a695Sgavinm  *
198a40a695Sgavinm  * CDDL HEADER END
208a40a695Sgavinm  */
218a40a695Sgavinm 
228a40a695Sgavinm /*
23*e4b86885SCheng Sean Ye  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
248a40a695Sgavinm  * Use is subject to license terms.
258a40a695Sgavinm  */
268a40a695Sgavinm 
278a40a695Sgavinm #include <sys/types.h>
288a40a695Sgavinm #include <sys/cmn_err.h>
298a40a695Sgavinm #include <mcamd_dimmcfg_impl.h>
308a40a695Sgavinm 
318a40a695Sgavinm /*
328a40a695Sgavinm  * We have built a list of the active csbase/csmask pairs, and now we want
338a40a695Sgavinm  * to associate those active chip-selects with actual dimms.  To achieve this
348a40a695Sgavinm  * we must map the csbase/csmask pair to an associated logical DIMM and
358a40a695Sgavinm  * chip-select line.
368a40a695Sgavinm  *
378a40a695Sgavinm  * A logical DIMM comprises up to 2 physical dimms as follows:
388a40a695Sgavinm  *
398a40a695Sgavinm  *	- in 64-bit mode without mismatched dimm support logical DIMMs are
408a40a695Sgavinm  *	  made up of just one physical dimm situated in a "lodimm" slot
418a40a695Sgavinm  *	  on channel A;  the corresponding slot on channel B (if there is
428a40a695Sgavinm  *	  a channel B) must be empty or will be disabled if populated.
438a40a695Sgavinm  *
448a40a695Sgavinm  *	- in 64-bit mode with mismatched dimm support a logical DIMM may
458a40a695Sgavinm  *	  be made up of 1 or 2 physical dimms - one on channel A and another
468a40a695Sgavinm  *	  in the corresponding slot on channel B.  They are accessed
478a40a695Sgavinm  *	  independently.
488a40a695Sgavinm  *
498a40a695Sgavinm  *	- in 128 bit mode a logical DIMM is made up of two physical dimms -
508a40a695Sgavinm  *	  a pair of one slot on channel A and its partner on channel B.
518a40a695Sgavinm  *	  The lodimm on channel A provides data [63:0] while the updimm
528a40a695Sgavinm  *	  on channel B provides data [127:64].  The two dimms must be
538a40a695Sgavinm  *	  identical in size and organisation (number of ranks etc).
548a40a695Sgavinm  *
55715d5c9bSgavinm  * The following tables are derived from the corresponding
568a40a695Sgavinm  * "DRAM CS Base and DRAM CS Mask Registers" with and without mismatched
578a40a695Sgavinm  * dimm support tables of the BKDG (tables 5 and 6 of BKDG 3.31 for rev E
58715d5c9bSgavinm  * and earlier; tables 8 and 9 of BKDG 3.01 for rev F and G).  They could
59715d5c9bSgavinm  * be implemented programatically, but are more readily reviewed for correctness
60715d5c9bSgavinm  * presented as tables.
61715d5c9bSgavinm  *
62715d5c9bSgavinm  * When we observe a given chip-select base/mask pair to be enabled in a
63715d5c9bSgavinm  * system configuration we lookup in the following tables to match on
64715d5c9bSgavinm  * all of base register pair number, processor revision, socket type
65715d5c9bSgavinm  * and dram configuration (e.g., quadrank registered or not); the remainder
66715d5c9bSgavinm  * of the matched line provides the corresponding logical dimm (ldimm)
67715d5c9bSgavinm  * number that the chip-select is to be associated with and details of
68715d5c9bSgavinm  * which chip-select line is used to operate that chip-select (specified
69715d5c9bSgavinm  * as a (channel, slot-number, rank-number) triple.  With this
70715d5c9bSgavinm  * information we determine the topology instance number of each physical
71715d5c9bSgavinm  * DIMM.  There are three distinct cases to consider:
72715d5c9bSgavinm  *
73715d5c9bSgavinm  * 128-bit MC mode:
74715d5c9bSgavinm  *
75715d5c9bSgavinm  *	The lodimm (channel A) and updimm (channel B) dimm in a pair
76715d5c9bSgavinm  *	have instance numbers 2 * ldimm and 2 * ldimm + 1, i.e.
77715d5c9bSgavinm  *	0/1, 2/3, 4/5, 5/6 for ldimm = 0, 1, 2, 3 (ldimms 2 and 3
78715d5c9bSgavinm  *	are only supported for socket 940 and socket F(1207).
79715d5c9bSgavinm  *
80715d5c9bSgavinm  * 64-bit MC mode, no mismatched dimm support:
81715d5c9bSgavinm  *
82715d5c9bSgavinm  *	All dimms reside on channel A.  If there is a channel B
83715d5c9bSgavinm  *	(anything other than socket 754) then any DIMMs on it will
84715d5c9bSgavinm  *	not be configured into the system.  We number as for
85715d5c9bSgavinm  *	128-bit mode but omiting the channel B DIMMs, i.e.
86715d5c9bSgavinm  *	0, 2, 4, 6 for ldimm = 0, 1, 2, 3.
87715d5c9bSgavinm  *
88715d5c9bSgavinm  * 64-bit MC mode, mismatched dimm support enabled:
89715d5c9bSgavinm  *
90715d5c9bSgavinm  *	Each rank of every DIMM is treated as a separate logical
91715d5c9bSgavinm  *	dimm, so while the package (939 or AM2) only supports two
92715d5c9bSgavinm  *	DIMMS per channel and normally logical dimms 2 and 3
93715d5c9bSgavinm  *	would not be supported they do spring into existence in this
94715d5c9bSgavinm  *	special mode.
958a40a695Sgavinm  *
96715d5c9bSgavinm  * Because of the mismatched DIMM support case we cannot derive
97715d5c9bSgavinm  * instance number from logical dimm number alone.  For that case we use the
98715d5c9bSgavinm  * slot number on the channel - that tracks the ldimm except in the
99715d5c9bSgavinm  * mismatched case.  This provides consistent instance numbering
100715d5c9bSgavinm  * even for a system cycled through each of the above configurations -
101715d5c9bSgavinm  * the instance dimm remains the same for a given channel and slot
102715d5c9bSgavinm  * number.
103715d5c9bSgavinm  *
104715d5c9bSgavinm  * When quadrank DIMMs - quadrank registered or quadrank SODIMM - are in
105715d5c9bSgavinm  * use we must always base the instance number off of the ldimm regardless
106715d5c9bSgavinm  * of mismatched DIMM support.
1078a40a695Sgavinm  */
1088a40a695Sgavinm 
109715d5c9bSgavinm #define	MCAMD_TOPONUM(ldimm, cslp, quadrank, mod64mux) \
110715d5c9bSgavinm 	(((quadrank) || !(mod64mux)) ? \
111715d5c9bSgavinm 	2 * (ldimm) + ((cslp)->csl_chan == CH_B) : \
112715d5c9bSgavinm 	2 * (cslp)->csl_slot + ((cslp)->csl_chan == CH_B))
113715d5c9bSgavinm 
1148a40a695Sgavinm /* BEGIN CSTYLED */
1158a40a695Sgavinm 
1168a40a695Sgavinm /*
1178a40a695Sgavinm  * Revision E and earlier mapping with mismatched dimm support disabled.
1188a40a695Sgavinm  */
1198a40a695Sgavinm static const struct mcdcfg_csmapline csmap_nomod64mux_preF[] = {
1208a40a695Sgavinm     /*
1218a40a695Sgavinm      * Pkgs   base dramconfig	     ldimm   cs A              cs B
1228a40a695Sgavinm      *
1238a40a695Sgavinm      * Base reg 0 (mask 0)
1248a40a695Sgavinm      */
1258a40a695Sgavinm     { SKT_ALL,	0, DCFG_ALL,		0, { { CH_A, 0, 0 }, { CH_B, 0, 0 } } },
1268a40a695Sgavinm     /*
1278a40a695Sgavinm      * Base reg 1 (mask 1)
1288a40a695Sgavinm      */
1298a40a695Sgavinm     { SKT_ALL,	1, DCFG_ALL,		0, { { CH_A, 0, 1 }, { CH_B, 0, 1 } } },
1308a40a695Sgavinm     /*
1318a40a695Sgavinm      * Base reg 2 (mask 2)
1328a40a695Sgavinm      */
1338a40a695Sgavinm     { SKT_ALL,	2, DCFG_ALL,		1, { { CH_A, 1, 0 }, { CH_B, 1, 0 } } },
1348a40a695Sgavinm     /*
1358a40a695Sgavinm      * Base reg 3 (mask 3)
1368a40a695Sgavinm      */
1378a40a695Sgavinm     { SKT_ALL,	3, DCFG_ALL,		1, { { CH_A, 1, 1 }, { CH_B, 1, 1 } } },
1388a40a695Sgavinm     /*
1398a40a695Sgavinm      * Base reg 4 (mask 4)
1408a40a695Sgavinm      */
141715d5c9bSgavinm     { SKT_754,	4, DCFG_N,		2, { { CH_A, 2, 0 } } },
1428a40a695Sgavinm     { SKT_940,	4, DCFG_N,		2, { { CH_A, 2, 0 }, { CH_B, 2, 0 } } },
1438a40a695Sgavinm     { SKT_940,	4, DCFG_R4,		0, { { CH_A, 2, 0 }, { CH_B, 2, 0 } } },
1448a40a695Sgavinm     /*
1458a40a695Sgavinm      * Base reg 5 (mask 5)
1468a40a695Sgavinm      */
147715d5c9bSgavinm     { SKT_754,	5, DCFG_N,		2, { { CH_A, 2, 1 } } },
1488a40a695Sgavinm     { SKT_940,	5, DCFG_N,		2, { { CH_A, 2, 1 }, { CH_B, 2, 1 } } },
1498a40a695Sgavinm     { SKT_940,	5, DCFG_R4,		0, { { CH_A, 2, 1 }, { CH_B, 2, 1 } } },
1508a40a695Sgavinm     /*
1518a40a695Sgavinm      * Base reg 6 (mask 6)
1528a40a695Sgavinm      */
153715d5c9bSgavinm     { SKT_754,	6, DCFG_N,		3, { { CH_A, 3, 0 } } },
1548a40a695Sgavinm     { SKT_940,	6, DCFG_N,		3, { { CH_A, 3, 0 }, { CH_B, 3, 0 } } },
1558a40a695Sgavinm     { SKT_940,	6, DCFG_R4,		1, { { CH_A, 3, 0 }, { CH_B, 3, 0 } } },
1568a40a695Sgavinm     /*
1578a40a695Sgavinm      * Base reg 7 (mask 7)
1588a40a695Sgavinm      */
159715d5c9bSgavinm     { SKT_754,	7, DCFG_N,		3, { { CH_A, 3, 1 } } },
1608a40a695Sgavinm     { SKT_940,	7, DCFG_N,		3, { { CH_A, 3, 1 }, { CH_B, 3, 1 } } },
1618a40a695Sgavinm     { SKT_940,	7, DCFG_R4,		1, { { CH_A, 3, 1 }, { CH_B, 3, 1 } } }
1628a40a695Sgavinm };
1638a40a695Sgavinm 
1648a40a695Sgavinm /*
1658a40a695Sgavinm  * Revision E and earlier mapping with mismatched dimm support.
1668a40a695Sgavinm  * Mismatched dimm support applies only to the socket 939 package.
1678a40a695Sgavinm  * Socket 939 does not support registered dimms, so quadrank RDIMMs are
1688a40a695Sgavinm  * not an issue here.
1698a40a695Sgavinm  */
1708a40a695Sgavinm static const struct mcdcfg_csmapline csmap_mod64mux_preF[] = {
1718a40a695Sgavinm     /*
1728a40a695Sgavinm      * Pkgs   base dramconfig	     ldimm   cs A              cs B
1738a40a695Sgavinm      *
1748a40a695Sgavinm      * Base reg 0 (mask 0)
1758a40a695Sgavinm      */
1768a40a695Sgavinm     { SKT_939,	0, DCFG_N,		0, { { CH_A, 0, 0 } } },
1778a40a695Sgavinm     /*
1788a40a695Sgavinm      * Base reg 1 (mask 1)
1798a40a695Sgavinm      */
1808a40a695Sgavinm     { SKT_939,	1, DCFG_N,		0, { { CH_A, 0, 1 } } },
1818a40a695Sgavinm     /*
1828a40a695Sgavinm      * Base reg 2 (mask 2)
1838a40a695Sgavinm      */
1848a40a695Sgavinm     { SKT_939,	2, DCFG_N,		1, { { CH_A, 1, 0 } } },
1858a40a695Sgavinm     /*
1868a40a695Sgavinm      * Base reg 3 (mask 3)
1878a40a695Sgavinm      */
1888a40a695Sgavinm     { SKT_939,	3, DCFG_N,		1, { { CH_A, 1, 1 } } },
1898a40a695Sgavinm     /*
1908a40a695Sgavinm      * Base reg 4 (mask 4)
1918a40a695Sgavinm      */
192715d5c9bSgavinm     { SKT_939,	4, DCFG_N,		2, { { CH_B, 0, 0 } } },
1938a40a695Sgavinm     /*
1948a40a695Sgavinm      * Base reg 5 (mask 5)
1958a40a695Sgavinm      */
196715d5c9bSgavinm     { SKT_939,	5, DCFG_N,		2, { { CH_B, 0, 1 } } },
1978a40a695Sgavinm     /*
1988a40a695Sgavinm      * Base reg 6 (mask 6)
1998a40a695Sgavinm      */
200715d5c9bSgavinm     { SKT_939,	6, DCFG_N,		3, { { CH_B, 1, 0 } } },
2018a40a695Sgavinm     /*
2028a40a695Sgavinm      * Base reg 7 (mask 7)
2038a40a695Sgavinm      */
204715d5c9bSgavinm     { SKT_939,	7, DCFG_N,		3, { { CH_B, 1, 1 } } }
2058a40a695Sgavinm };
2068a40a695Sgavinm 
2078a40a695Sgavinm /*
2088a40a695Sgavinm  * Rev F and G csbase/csmask to logical DIMM and cs line mappings.
2098a40a695Sgavinm  *
2108a40a695Sgavinm  * We can reduce the tables by a few lines by taking into account which
2118a40a695Sgavinm  * DIMM types are supported by the different package types:
2128a40a695Sgavinm  *
2138a40a695Sgavinm  *		Number of dimms of given type supported per dram channel
2148a40a695Sgavinm  * Package	Reg'd DIMM	4-rank reg'd	Unbuffered	SO-DIMMs
2158a40a695Sgavinm  * F(1207)	4		2		0		0
2168a40a695Sgavinm  * AM2		0		0		2		1
2178a40a695Sgavinm  * S1g1		0		0		0		1
2188a40a695Sgavinm  */
2198a40a695Sgavinm 
2208a40a695Sgavinm /*
2218a40a695Sgavinm  * NPT (rev F & G) mapping with mismatched dimm support disabled.
2228a40a695Sgavinm  */
2238a40a695Sgavinm static const struct mcdcfg_csmapline csmap_nomod64mux_fg[] = {
2248a40a695Sgavinm     /*
2258a40a695Sgavinm      * Pkgs   base dramconfig	     ldimm   cs A              cs B
2268a40a695Sgavinm      *
2278a40a695Sgavinm      * Base reg 0 (mask 0)
2288a40a695Sgavinm      */
2298a40a695Sgavinm     { SKT_NPT,	0, DCFG_ALLNPT,		0, { { CH_A, 0, 0 }, { CH_B, 0, 0 } } },
2308a40a695Sgavinm     /*
2318a40a695Sgavinm      * Base reg 1 (mask 0)
2328a40a695Sgavinm      */
2338a40a695Sgavinm     { SKT_NPT,	1, DCFG_ALLNPT,		0, { { CH_A, 0, 1 }, { CH_B, 0, 1 } } },
2348a40a695Sgavinm     /*
2358a40a695Sgavinm      * Base reg 2 (mask 1)
2368a40a695Sgavinm      */
2378a40a695Sgavinm     { AM2F1207,	2, DCFG_N | DCFG_R4,	1, { { CH_A, 1, 0 }, { CH_B, 1, 0 } } },
2388a40a695Sgavinm     { AM2,	2, DCFG_S4,		0, { { CH_A, 1, 0 }, { CH_B, 1, 0 } } },
2398a40a695Sgavinm     { S1g1,	2, DCFG_N,		1, { { CH_A, 0, 2 }, { CH_B, 0, 2 } } },
2408a40a695Sgavinm     { S1g1,	2, DCFG_S4,		0, { { CH_A, 0, 2 }, { CH_B, 0, 2 } } },
2418a40a695Sgavinm     /*
2428a40a695Sgavinm      * Base reg 3 (mask 1)
2438a40a695Sgavinm      */
2448a40a695Sgavinm     { AM2F1207,	3, DCFG_N | DCFG_R4,	1, { { CH_A, 1, 1 }, { CH_B, 1, 1 } } },
245715d5c9bSgavinm     { AM2,	3, DCFG_S4,		0, { { CH_A, 1, 1 }, { CH_B, 1, 1 } } },
246715d5c9bSgavinm     { S1g1,	3, DCFG_N,		1, { { CH_A, 0, 3 }, { CH_B, 0, 3 } } },
2478a40a695Sgavinm     { S1g1,	3, DCFG_S4,		0, { { CH_A, 0, 3 }, { CH_B, 0, 3 } } },
2488a40a695Sgavinm     /*
2498a40a695Sgavinm      * Base reg 4 (mask 2)
2508a40a695Sgavinm      */
2518a40a695Sgavinm     { F1207,	4, DCFG_N,		2, { { CH_A, 2, 0 }, { CH_B, 2, 0 } } },
2528a40a695Sgavinm     { F1207,	4, DCFG_R4,		0, { { CH_A, 2, 0 }, { CH_B, 2, 0 } } },
2538a40a695Sgavinm     /*
2548a40a695Sgavinm      * Base reg 5 (mask 2)
2558a40a695Sgavinm      */
2568a40a695Sgavinm     { F1207,	5, DCFG_N,		2, { { CH_A, 2, 1 }, { CH_B, 2, 1 } } },
2578a40a695Sgavinm     { F1207,	5, DCFG_R4,		0, { { CH_A, 2, 1 }, { CH_B, 2, 1 } } },
2588a40a695Sgavinm     /*
2598a40a695Sgavinm      * Base reg 6 (mask 3)
2608a40a695Sgavinm      */
2618a40a695Sgavinm     { F1207,	6, DCFG_N,		3, { { CH_A, 3, 0 }, { CH_B, 3, 0 } } },
2628a40a695Sgavinm     { F1207,	6, DCFG_R4,		1, { { CH_A, 3, 0 }, { CH_B, 3, 0 } } },
2638a40a695Sgavinm     /*
2648a40a695Sgavinm      * Base reg 7 (mask 3)
2658a40a695Sgavinm      */
2668a40a695Sgavinm     { F1207,	7, DCFG_N,		3, { { CH_A, 3, 1 }, { CH_B, 3, 1 } } },
2678a40a695Sgavinm     { F1207,	7, DCFG_R4,		1, { { CH_A, 3, 1 }, { CH_B, 3, 1 } } }
2688a40a695Sgavinm };
2698a40a695Sgavinm 
2708a40a695Sgavinm /*
2718a40a695Sgavinm  * NPT (rev F & G) mapping with mismatched dimm support.
2728a40a695Sgavinm  * Mismatched dimm support applies only to the AM2 and S1g1 packages.
2738a40a695Sgavinm  * AM2 and S1g1 do not support registered dimms.
2748a40a695Sgavinm  */
2758a40a695Sgavinm static const struct mcdcfg_csmapline csmap_mod64mux_fg[] = {
2768a40a695Sgavinm     /*
2778a40a695Sgavinm      * Pkgs   base dramconfig	     ldimm   cs A              cs B
2788a40a695Sgavinm      *
2798a40a695Sgavinm      * Base reg 0 (mask 0)
2808a40a695Sgavinm      */
2818a40a695Sgavinm     { AM2S1g1,	0, DCFG_N | DCFG_S4,	0, { { CH_A, 0, 0 } } },
2828a40a695Sgavinm     /*
2838a40a695Sgavinm      * Base reg 1 (mask 0)
2848a40a695Sgavinm      */
2858a40a695Sgavinm     { AM2S1g1,	1, DCFG_N | DCFG_S4,	0, { { CH_A, 0, 1 } } },
2868a40a695Sgavinm     /*
2878a40a695Sgavinm      * Base reg 2 (mask 1)
2888a40a695Sgavinm      */
2898a40a695Sgavinm     { AM2,	2, DCFG_N,		1, { { CH_A, 1, 0 } } },
2908a40a695Sgavinm     { AM2,	2, DCFG_S4,		0, { { CH_A, 1, 0 } } },
2918a40a695Sgavinm     { S1g1,	2, DCFG_N,		1, { { CH_A, 0, 2 } } },
2928a40a695Sgavinm     { S1g1,	2, DCFG_S4,		0, { { CH_A, 0, 2 } } },
2938a40a695Sgavinm     /*
2948a40a695Sgavinm      * Base reg 3 (mask 1)
2958a40a695Sgavinm      */
2968a40a695Sgavinm     { AM2,	3, DCFG_N,		1, { { CH_A, 1, 1 } } },
2978a40a695Sgavinm     { AM2,	3, DCFG_S4,		0, { { CH_A, 1, 1 } } },
2988a40a695Sgavinm     { S1g1,	3, DCFG_N,		1, { { CH_A, 0, 3 } } },
2998a40a695Sgavinm     { S1g1,	3, DCFG_S4,		0, { { CH_A, 0, 3 } } },
3008a40a695Sgavinm     /*
3018a40a695Sgavinm      * Base reg 4 (mask 2)
3028a40a695Sgavinm      */
3038a40a695Sgavinm     { AM2S1g1,	4, DCFG_N,		2, { { CH_B, 0, 0 } } },
3048a40a695Sgavinm     { AM2S1g1,	4, DCFG_S4,		1, { { CH_B, 0, 0 } } },
3058a40a695Sgavinm     /*
3068a40a695Sgavinm      * Base reg 5 (mask 2)
3078a40a695Sgavinm      */
3088a40a695Sgavinm     { AM2S1g1,	5, DCFG_N,		2, { { CH_B, 0, 1 } } },
3098a40a695Sgavinm     { AM2S1g1,	5, DCFG_S4,		1, { { CH_B, 0, 1 } } },
3108a40a695Sgavinm     /*
3118a40a695Sgavinm      * Base reg 6 (mask 3)
3128a40a695Sgavinm      */
3138a40a695Sgavinm     { AM2,	6, DCFG_N,		3, { { CH_B, 1, 0 } } },
3148a40a695Sgavinm     { AM2,	6, DCFG_S4,		1, { { CH_B, 1, 0 } } },
3158a40a695Sgavinm     { S1g1,	6, DCFG_N,		3, { { CH_B, 0, 2 } } },
3168a40a695Sgavinm     { S1g1,	6, DCFG_S4,		1, { { CH_B, 0, 2 } } },
3178a40a695Sgavinm     /*
3188a40a695Sgavinm      * Base reg 7 (mask 3)
3198a40a695Sgavinm      */
3208a40a695Sgavinm     { AM2,	7, DCFG_N,		3, { { CH_B, 1, 1 } } },
3218a40a695Sgavinm     { AM2,	7, DCFG_S4,		1, { { CH_B, 1, 1 } } },
3228a40a695Sgavinm     { S1g1,	7, DCFG_N,		3, { { CH_B, 0, 3 } } },
3238a40a695Sgavinm     { S1g1,	7, DCFG_S4,		1, { { CH_B, 0, 3 } } }
3248a40a695Sgavinm };
3258a40a695Sgavinm 
3268a40a695Sgavinm /* END CSTYLED */
3278a40a695Sgavinm 
3288a40a695Sgavinm #define	DCFG_NTBL	4
3298a40a695Sgavinm 
3308a40a695Sgavinm static const struct {
3318a40a695Sgavinm 	uint32_t revmask;		/* applicable chip revs */
3328a40a695Sgavinm 	int mod64mux;			/* mismatched support or not */
3338a40a695Sgavinm 	const struct mcdcfg_csmapline *map;
3348a40a695Sgavinm 	int nmapents;
3358a40a695Sgavinm } csmap_tbls[DCFG_NTBL] = {
33620c794b3Sgavinm 	{ MC_F_REVS_BCDE, 0, &csmap_nomod64mux_preF[0],
3378a40a695Sgavinm 	    sizeof (csmap_nomod64mux_preF) / sizeof (struct mcdcfg_csmapline) },
33820c794b3Sgavinm 	{ MC_F_REVS_BCDE, 1, &csmap_mod64mux_preF[0],
3398a40a695Sgavinm 	    sizeof (csmap_mod64mux_preF) / sizeof (struct mcdcfg_csmapline) },
34020c794b3Sgavinm 	{ MC_F_REVS_FG, 0, &csmap_nomod64mux_fg[0],
3418a40a695Sgavinm 	    sizeof (csmap_nomod64mux_fg) / sizeof (struct mcdcfg_csmapline) },
34220c794b3Sgavinm 	{ MC_F_REVS_FG, 1, &csmap_mod64mux_fg[0],
3438a40a695Sgavinm 	    sizeof (csmap_mod64mux_fg) / sizeof (struct mcdcfg_csmapline) }
3448a40a695Sgavinm };
3458a40a695Sgavinm 
3468a40a695Sgavinm int
mcdcfg_lookup(uint32_t rev,int mod64mux,int accwidth,int basenum,uint32_t pkg,int r4,int s4,mcdcfg_rslt_t * rsltp)3478a40a695Sgavinm mcdcfg_lookup(uint32_t rev, int mod64mux, int accwidth, int basenum,
3488a40a695Sgavinm     uint32_t pkg, int r4, int s4, mcdcfg_rslt_t *rsltp)
3498a40a695Sgavinm {
3508a40a695Sgavinm 	const struct mcdcfg_csmapline *csm = NULL;
3518a40a695Sgavinm 	int ismux = (mod64mux != 0);
3528a40a695Sgavinm 	int nmapents;
3538a40a695Sgavinm 	int ndimm = (accwidth == 128) ? 2 : 1;
3548a40a695Sgavinm 	int dcfg;
3558a40a695Sgavinm 	int i;
3568a40a695Sgavinm 
3578a40a695Sgavinm 	/*
3588a40a695Sgavinm 	 * Validate aspects that the table lookup won't.
3598a40a695Sgavinm 	 */
3608a40a695Sgavinm 	if ((accwidth != 64 && accwidth != 128) || (r4 != 0 && s4 != 0))
3618a40a695Sgavinm 		return (-1);
3628a40a695Sgavinm 
3638a40a695Sgavinm 	for (i = 0; i < DCFG_NTBL; i++) {
3648a40a695Sgavinm 		if (MC_REV_MATCH(rev, csmap_tbls[i].revmask) &&
3658a40a695Sgavinm 		    ismux == csmap_tbls[i].mod64mux) {
3668a40a695Sgavinm 			csm = csmap_tbls[i].map;
3678a40a695Sgavinm 			nmapents = csmap_tbls[i].nmapents;
3688a40a695Sgavinm 			break;
3698a40a695Sgavinm 		}
3708a40a695Sgavinm 	}
3718a40a695Sgavinm 	if (csm == NULL)
3728a40a695Sgavinm 		return (-1);
3738a40a695Sgavinm 
3748a40a695Sgavinm 	if (r4)
3758a40a695Sgavinm 		dcfg = DCFG_R4;
3768a40a695Sgavinm 	else if (s4)
3778a40a695Sgavinm 		dcfg = DCFG_S4;
3788a40a695Sgavinm 	else
3798a40a695Sgavinm 		dcfg = DCFG_N;
3808a40a695Sgavinm 
3818a40a695Sgavinm 	for (i = 0; i < nmapents; i++, csm++) {
3828a40a695Sgavinm 		if (X86_SOCKET_MATCH(pkg, csm->csm_pkg) &&
3838a40a695Sgavinm 		    basenum == csm->csm_basereg &&
3848a40a695Sgavinm 		    (dcfg & csm->csm_dimmcfg) != 0)
3858a40a695Sgavinm 			break;
3868a40a695Sgavinm 	}
3878a40a695Sgavinm 	if (i == nmapents)
3888a40a695Sgavinm 		return (-1);
3898a40a695Sgavinm 
3908a40a695Sgavinm 	/*
3918a40a695Sgavinm 	 * We return the dimm instance number here for the topology, based
3928a40a695Sgavinm 	 * on the AMD Motherboard Design Guide.
3938a40a695Sgavinm 	 */
3948a40a695Sgavinm 	rsltp->ldimm = csm->csm_ldimm;
3958a40a695Sgavinm 	rsltp->ndimm = ndimm;
3968a40a695Sgavinm 	for (i = 0; i < ndimm; i++) {
397715d5c9bSgavinm 		const struct mcdcfg_csl *cslp = &csm->csm_cs[i];
398715d5c9bSgavinm 
399715d5c9bSgavinm 		rsltp->dimm[i].toponum =
400715d5c9bSgavinm 		    MCAMD_TOPONUM(rsltp->ldimm, cslp, r4 || s4, ismux);
401715d5c9bSgavinm 		rsltp->dimm[i].cslp = cslp;
4028a40a695Sgavinm 	}
4038a40a695Sgavinm 
4048a40a695Sgavinm 	return (0);
4058a40a695Sgavinm }
4068a40a695Sgavinm 
4078a40a695Sgavinm /*
4088a40a695Sgavinm  * Given a chip-select line and package type return the chip-select line
4098a40a695Sgavinm  * pin label for that package type.
4108a40a695Sgavinm  */
4118a40a695Sgavinm void
mcdcfg_csname(uint32_t pkg,const mcdcfg_csl_t * cslp,char * buf,int buflen)4128a40a695Sgavinm mcdcfg_csname(uint32_t pkg, const mcdcfg_csl_t *cslp, char *buf, int buflen)
4138a40a695Sgavinm {
4148a40a695Sgavinm 	int csnum;
4158a40a695Sgavinm 
4168a40a695Sgavinm 	switch (pkg) {
4178a40a695Sgavinm 	case X86_SOCKET_754:
418715d5c9bSgavinm 		/*
419715d5c9bSgavinm 		 * Format is: MEMCS_L[{0..7}].  There is only channel A.
420715d5c9bSgavinm 		 */
421715d5c9bSgavinm 		csnum = 2 * cslp->csl_slot + cslp->csl_rank;
422715d5c9bSgavinm 		(void) snprintf(buf, buflen, "MEMCS_L%d", csnum);
423715d5c9bSgavinm 		break;
424715d5c9bSgavinm 
4258a40a695Sgavinm 	case X86_SOCKET_940:
4268a40a695Sgavinm 		/*
4278a40a695Sgavinm 		 * Format is: MEMCS_L[{0..7}].  That does not identify
4288a40a695Sgavinm 		 * a single dimm (since a single chip-select is shared
4298a40a695Sgavinm 		 * by both members of a dimm pair in socket 940) so
4308a40a695Sgavinm 		 * we tack on some channel identification.
4318a40a695Sgavinm 		 */
4328a40a695Sgavinm 		csnum = 2 * cslp->csl_slot + cslp->csl_rank;
4338a40a695Sgavinm 		(void) snprintf(buf, buflen, "MEMCS_L%d (channel %s)", csnum,
434715d5c9bSgavinm 		    cslp->csl_chan == CH_A ? "A" : "B");
4358a40a695Sgavinm 
4368a40a695Sgavinm 		break;
4378a40a695Sgavinm 
4388a40a695Sgavinm 	case X86_SOCKET_939:
4398a40a695Sgavinm 		/*
4408a40a695Sgavinm 		 * Format is: MEMCS_{1,2}{L,H}_L[{1,0}]
4418a40a695Sgavinm 		 *		{1,2} - dimm pair
4428a40a695Sgavinm 		 *		{L,H} - lodimm or updimm
4438a40a695Sgavinm 		 *		{1,0} - rank
4448a40a695Sgavinm 		 */
4458a40a695Sgavinm 		(void) snprintf(buf, buflen, "MEMCS_%d%s_L[%d]",
4468a40a695Sgavinm 		    cslp->csl_slot + 1,
447715d5c9bSgavinm 		    cslp->csl_chan == CH_A ? "A" : "B",
4488a40a695Sgavinm 		    cslp->csl_rank);
4498a40a695Sgavinm 		break;
4508a40a695Sgavinm 
4518a40a695Sgavinm 	case X86_SOCKET_F1207:
4528a40a695Sgavinm 	case X86_SOCKET_AM2:
4538a40a695Sgavinm 	case X86_SOCKET_S1g1:
4548a40a695Sgavinm 		/*
4558a40a695Sgavinm 		 * Format is: M{B,A}{0,1,2,3}_CS_L[{0,1,2,3}]
4568a40a695Sgavinm 		 *		{B,A} - channel
4578a40a695Sgavinm 		 *		{0,1,2,3} - slot on channel
4588a40a695Sgavinm 		 *		{0,1,2,3} - rank
4598a40a695Sgavinm 		 */
4608a40a695Sgavinm 		(void) snprintf(buf, buflen, "M%s%d_CS_L[%d]",
461715d5c9bSgavinm 		    cslp->csl_chan == CH_A ? "A" : "B",
4628a40a695Sgavinm 		    cslp->csl_slot,
4638a40a695Sgavinm 		    cslp->csl_rank);
4648a40a695Sgavinm 		break;
4658a40a695Sgavinm 
4668a40a695Sgavinm 	default:
4678a40a695Sgavinm 		(void) snprintf(buf, buflen, "Unknown");
4688a40a695Sgavinm 		break;
4698a40a695Sgavinm 	}
4708a40a695Sgavinm }
471