mcamd_dimmcfg.c revision 8a40a695ee676a322b094e9afe5375567bfb51e3
/*
* 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
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <mcamd_dimmcfg_impl.h>
/*
* to associate those active chip-selects with actual dimms. To achieve this
* chip-select line.
*
* A logical DIMM comprises up to 2 physical dimms as follows:
*
* - in 64-bit mode without mismatched dimm support logical DIMMs are
* made up of just one physical dimm situated in a "lodimm" slot
* on channel A; the corresponding slot on channel B (if there is
* a channel B) must be empty or will be disabled if populated.
*
* - in 64-bit mode with mismatched dimm support a logical DIMM may
* be made up of 1 or 2 physical dimms - one on channel A and another
* in the corresponding slot on channel B. They are accessed
* independently.
*
* - in 128 bit mode a logical DIMM is made up of two physical dimms -
* a pair of one slot on channel A and its partner on channel B.
* The lodimm on channel A provides data [63:0] while the updimm
* on channel B provides data [127:64]. The two dimms must be
* identical in size and organisation (number of ranks etc).
*
* For our dimm numbering purposes we need go no further than deriving
* of quadrank support and mismatched dimms. For logical DIMM number N
* (N = 0, 1, 2, or 3):
*
* - the lodimm, if present, is numbered N * 2
* - the updimm, if present, is numbered N * 2 + 1
*
* Presence is deduced by observed configuration, as above. This numbering
* scheme, however, often bears little or no resemblance to how the dimm slots
* are physically labelled/silkscreened (which in turn often bears little
* resemblance to how SMBIOS data, if available, describes the slot). To
* determine slot labels we will map chip-select *line* to slot name in
* some hand-crafted tables (which live in the libtopo enumerator and are
* built after consulting the board schematics for a platform). To provide
* the chip-select line name we will perform some additional gymnastics here
* to derive the chip-select line or lines (in 128 bit mode) associated
* with a chip-select rank. This is achieved via matching against the
* "DRAM CS Base and DRAM CS Mask Registers" with and without mismatched
* dimm support tables of the BKDG (tables 5 and 6 of BKDG 3.31 for rev E
* and earlier; tables 8 and 9 of BKDG 3.01 for rev F and G).
*
* The following tables could be implemented programtically, but are more
* readily reviewed for correctness presented as tables.
*/
/* BEGIN CSTYLED */
/*
* Revision E and earlier mapping with mismatched dimm support disabled.
*/
static const struct mcdcfg_csmapline csmap_nomod64mux_preF[] = {
/*
* Pkgs base dramconfig ldimm cs A cs B
*
* Base reg 0 (mask 0)
*/
/*
* Base reg 1 (mask 1)
*/
/*
* Base reg 2 (mask 2)
*/
/*
* Base reg 3 (mask 3)
*/
/*
* Base reg 4 (mask 4)
*/
/*
* Base reg 5 (mask 5)
*/
/*
* Base reg 6 (mask 6)
*/
/*
* Base reg 7 (mask 7)
*/
};
/*
* Revision E and earlier mapping with mismatched dimm support.
* Mismatched dimm support applies only to the socket 939 package.
* Socket 939 does not support registered dimms, so quadrank RDIMMs are
* not an issue here.
*/
static const struct mcdcfg_csmapline csmap_mod64mux_preF[] = {
/*
* Pkgs base dramconfig ldimm cs A cs B
*
* Base reg 0 (mask 0)
*/
/*
* Base reg 1 (mask 1)
*/
/*
* Base reg 2 (mask 2)
*/
/*
* Base reg 3 (mask 3)
*/
/*
* Base reg 4 (mask 4)
*/
/*
* Base reg 5 (mask 5)
*/
/*
* Base reg 6 (mask 6)
*/
/*
* Base reg 7 (mask 7)
*/
};
/*
*
* We can reduce the tables by a few lines by taking into account which
* DIMM types are supported by the different package types:
*
* Number of dimms of given type supported per dram channel
* Package Reg'd DIMM 4-rank reg'd Unbuffered SO-DIMMs
* F(1207) 4 2 0 0
* AM2 0 0 2 1
* S1g1 0 0 0 1
*/
/*
* NPT (rev F & G) mapping with mismatched dimm support disabled.
*/
static const struct mcdcfg_csmapline csmap_nomod64mux_fg[] = {
/*
* Pkgs base dramconfig ldimm cs A cs B
*
* Base reg 0 (mask 0)
*/
/*
* Base reg 1 (mask 0)
*/
/*
* Base reg 2 (mask 1)
*/
/*
* Base reg 3 (mask 1)
*/
/*
* Base reg 4 (mask 2)
*/
/*
* Base reg 5 (mask 2)
*/
/*
* Base reg 6 (mask 3)
*/
/*
* Base reg 7 (mask 3)
*/
};
/*
* NPT (rev F & G) mapping with mismatched dimm support.
* Mismatched dimm support applies only to the AM2 and S1g1 packages.
* AM2 and S1g1 do not support registered dimms.
*/
static const struct mcdcfg_csmapline csmap_mod64mux_fg[] = {
/*
* Pkgs base dramconfig ldimm cs A cs B
*
* Base reg 0 (mask 0)
*/
/*
* Base reg 1 (mask 0)
*/
/*
* Base reg 2 (mask 1)
*/
/*
* Base reg 3 (mask 1)
*/
/*
* Base reg 4 (mask 2)
*/
/*
* Base reg 5 (mask 2)
*/
/*
* Base reg 6 (mask 3)
*/
/*
* Base reg 7 (mask 3)
*/
};
/* END CSTYLED */
#define DCFG_NTBL 4
static const struct {
int mod64mux; /* mismatched support or not */
const struct mcdcfg_csmapline *map;
int nmapents;
} csmap_tbls[DCFG_NTBL] = {
{ MC_REVS_BCDE, 0, &csmap_nomod64mux_preF[0],
sizeof (csmap_nomod64mux_preF) / sizeof (struct mcdcfg_csmapline) },
sizeof (csmap_mod64mux_preF) / sizeof (struct mcdcfg_csmapline) },
{ MC_REVS_FG, 0, &csmap_nomod64mux_fg[0],
sizeof (csmap_nomod64mux_fg) / sizeof (struct mcdcfg_csmapline) },
sizeof (csmap_mod64mux_fg) / sizeof (struct mcdcfg_csmapline) }
};
int
{
int nmapents;
int dcfg;
int i;
/*
* Validate aspects that the table lookup won't.
*/
return (-1);
for (i = 0; i < DCFG_NTBL; i++) {
break;
}
}
return (-1);
if (r4)
else if (s4)
else
break;
}
if (i == nmapents)
return (-1);
/*
* We return the dimm instance number here for the topology, based
* on the AMD Motherboard Design Guide.
*
* 0/1, 2/3, 4/5, 6/7 - ie 2 * pairnum and 2 * pairnum + 1 for
* pairnum = 0, 1, 2, 3. But we can't use logical dimm number
* for pairnum in that calculation, since in the presence of
* mismtached dimms logicial dimms 2 and 3 are used for those
* dimm modules on the B channel. Instead we number using the
* slot number on that dram channel, offsetting those on the B
* channel by 1.
*/
for (i = 0; i < ndimm; i++) {
}
return (0);
}
/*
* Given a chip-select line and package type return the chip-select line
* pin label for that package type.
*/
void
{
int csnum;
switch (pkg) {
case X86_SOCKET_754:
case X86_SOCKET_940:
/*
* Format is: MEMCS_L[{0..7}]. That does not identify
* a single dimm (since a single chip-select is shared
* by both members of a dimm pair in socket 940) so
* we tack on some channel identification.
*/
break;
case X86_SOCKET_939:
/*
* Format is: MEMCS_{1,2}{L,H}_L[{1,0}]
* {1,2} - dimm pair
* {L,H} - lodimm or updimm
* {1,0} - rank
*/
break;
case X86_SOCKET_F1207:
case X86_SOCKET_AM2:
case X86_SOCKET_S1g1:
/*
* Format is: M{B,A}{0,1,2,3}_CS_L[{0,1,2,3}]
* {B,A} - channel
* {0,1,2,3} - slot on channel
* {0,1,2,3} - rank
*/
break;
default:
break;
}
}