gm45: Move spd address map to board-specific config.
Change-Id: I8f45a821ecd414dbd0129ae6d583d4e7dc06bc5a Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com> Reviewed-on: http://review.coreboot.org/5931 Reviewed-by: Patrick Georgi <patrick@georgi-clan.de> Tested-by: build bot (Jenkins)
This commit is contained in:
parent
a838aafc63
commit
c4d8948797
|
@ -171,6 +171,10 @@ void main(unsigned long bist)
|
||||||
/* RAM initialization */
|
/* RAM initialization */
|
||||||
enter_raminit_or_reset();
|
enter_raminit_or_reset();
|
||||||
get_gmch_info(&sysinfo);
|
get_gmch_info(&sysinfo);
|
||||||
|
sysinfo.spd_map[0] = 0x50;
|
||||||
|
sysinfo.spd_map[1] = 0;
|
||||||
|
sysinfo.spd_map[2] = 0x52;
|
||||||
|
sysinfo.spd_map[3] = 0;
|
||||||
raminit(&sysinfo, s3resume);
|
raminit(&sysinfo, s3resume);
|
||||||
|
|
||||||
raminit_thermal(&sysinfo);
|
raminit_thermal(&sysinfo);
|
||||||
|
|
|
@ -143,6 +143,7 @@ typedef struct {
|
||||||
int spd_type;
|
int spd_type;
|
||||||
timings_t selected_timings;
|
timings_t selected_timings;
|
||||||
dimminfo_t dimms[2];
|
dimminfo_t dimms[2];
|
||||||
|
u8 spd_map[4];
|
||||||
} sysinfo_t;
|
} sysinfo_t;
|
||||||
#define TOTAL_CHANNELS 2
|
#define TOTAL_CHANNELS 2
|
||||||
#define CHANNEL_IS_POPULATED(dimms, idx) (dimms[idx].card_type != 0)
|
#define CHANNEL_IS_POPULATED(dimms, idx) (dimms[idx].card_type != 0)
|
||||||
|
|
|
@ -235,61 +235,62 @@ void enter_raminit_or_reset(void)
|
||||||
|
|
||||||
/* For a detected DIMM, test the value of an SPD byte to
|
/* For a detected DIMM, test the value of an SPD byte to
|
||||||
match the expected value after masking some bits. */
|
match the expected value after masking some bits. */
|
||||||
static int test_dimm(int dimm, int addr, int bitmask, int expected)
|
static int test_dimm(sysinfo_t *const sysinfo,
|
||||||
|
int dimm, int addr, int bitmask, int expected)
|
||||||
{
|
{
|
||||||
return (smbus_read_byte(DIMM0 + dimm, addr) & bitmask) == expected;
|
return (smbus_read_byte(sysinfo->spd_map[dimm], addr) & bitmask) == expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function dies if dimm is unsuitable for the chipset. */
|
/* This function dies if dimm is unsuitable for the chipset. */
|
||||||
static void verify_ddr3_dimm(int dimm)
|
static void verify_ddr3_dimm(sysinfo_t *const sysinfo, int dimm)
|
||||||
{
|
{
|
||||||
if (!test_dimm(dimm, 3, 15, 3))
|
if (!test_dimm(sysinfo, dimm, 3, 15, 3))
|
||||||
die("Chipset only supports SO-DIMM\n");
|
die("Chipset only supports SO-DIMM\n");
|
||||||
|
|
||||||
if (!test_dimm(dimm, 8, 0x18, 0))
|
if (!test_dimm(sysinfo, dimm, 8, 0x18, 0))
|
||||||
die("Chipset doesn't support ECC RAM\n");
|
die("Chipset doesn't support ECC RAM\n");
|
||||||
|
|
||||||
if (!test_dimm(dimm, 7, 0x38, 0) &&
|
if (!test_dimm(sysinfo, dimm, 7, 0x38, 0) &&
|
||||||
!test_dimm(dimm, 7, 0x38, 8))
|
!test_dimm(sysinfo, dimm, 7, 0x38, 8))
|
||||||
die("Chipset wants single or double sided DIMMs\n");
|
die("Chipset wants single or double sided DIMMs\n");
|
||||||
|
|
||||||
if (!test_dimm(dimm, 7, 7, 1) &&
|
if (!test_dimm(sysinfo, dimm, 7, 7, 1) &&
|
||||||
!test_dimm(dimm, 7, 7, 2))
|
!test_dimm(sysinfo, dimm, 7, 7, 2))
|
||||||
die("Chipset requires x8 or x16 width\n");
|
die("Chipset requires x8 or x16 width\n");
|
||||||
|
|
||||||
if (!test_dimm(dimm, 4, 0x0f, 0) &&
|
if (!test_dimm(sysinfo, dimm, 4, 0x0f, 0) &&
|
||||||
!test_dimm(dimm, 4, 0x0f, 1) &&
|
!test_dimm(sysinfo, dimm, 4, 0x0f, 1) &&
|
||||||
!test_dimm(dimm, 4, 0x0f, 2) &&
|
!test_dimm(sysinfo, dimm, 4, 0x0f, 2) &&
|
||||||
!test_dimm(dimm, 4, 0x0f, 3))
|
!test_dimm(sysinfo, dimm, 4, 0x0f, 3))
|
||||||
die("Chipset requires 256Mb, 512Mb, 1Gb or 2Gb chips.");
|
die("Chipset requires 256Mb, 512Mb, 1Gb or 2Gb chips.");
|
||||||
|
|
||||||
if (!test_dimm(dimm, 4, 0x70, 0))
|
if (!test_dimm(sysinfo, dimm, 4, 0x70, 0))
|
||||||
die("Chipset requires 8 banks on DDR3\n");
|
die("Chipset requires 8 banks on DDR3\n");
|
||||||
|
|
||||||
/* How to check if burst length is 8?
|
/* How to check if burst length is 8?
|
||||||
Other values are not supported, are they even possible? */
|
Other values are not supported, are they even possible? */
|
||||||
|
|
||||||
if (!test_dimm(dimm, 10, 0xff, 1))
|
if (!test_dimm(sysinfo, dimm, 10, 0xff, 1))
|
||||||
die("Code assumes 1/8ns MTB\n");
|
die("Code assumes 1/8ns MTB\n");
|
||||||
|
|
||||||
if (!test_dimm(dimm, 11, 0xff, 8))
|
if (!test_dimm(sysinfo, dimm, 11, 0xff, 8))
|
||||||
die("Code assumes 1/8ns MTB\n");
|
die("Code assumes 1/8ns MTB\n");
|
||||||
|
|
||||||
if (!test_dimm(dimm, 62, 0x9f, 0) &&
|
if (!test_dimm(sysinfo, dimm, 62, 0x9f, 0) &&
|
||||||
!test_dimm(dimm, 62, 0x9f, 1) &&
|
!test_dimm(sysinfo, dimm, 62, 0x9f, 1) &&
|
||||||
!test_dimm(dimm, 62, 0x9f, 2) &&
|
!test_dimm(sysinfo, dimm, 62, 0x9f, 2) &&
|
||||||
!test_dimm(dimm, 62, 0x9f, 3) &&
|
!test_dimm(sysinfo, dimm, 62, 0x9f, 3) &&
|
||||||
!test_dimm(dimm, 62, 0x9f, 5))
|
!test_dimm(sysinfo, dimm, 62, 0x9f, 5))
|
||||||
die("Only raw card types A, B, C, D and F are supported.\n");
|
die("Only raw card types A, B, C, D and F are supported.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For every detected DIMM, test if it's suitable for the chipset. */
|
/* For every detected DIMM, test if it's suitable for the chipset. */
|
||||||
static void verify_ddr3(int mask)
|
static void verify_ddr3(sysinfo_t *const sysinfo, int mask)
|
||||||
{
|
{
|
||||||
int cur = 0;
|
int cur = 0;
|
||||||
while (mask) {
|
while (mask) {
|
||||||
if (mask & 1) {
|
if (mask & 1) {
|
||||||
verify_ddr3_dimm(cur);
|
verify_ddr3_dimm(sysinfo, cur);
|
||||||
}
|
}
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
cur++;
|
cur++;
|
||||||
|
@ -321,14 +322,15 @@ typedef struct {
|
||||||
* This function collects RAM characteristics from SPD, assuming that RAM
|
* This function collects RAM characteristics from SPD, assuming that RAM
|
||||||
* is generally within chipset's requirements, since verify_ddr3() passed.
|
* is generally within chipset's requirements, since verify_ddr3() passed.
|
||||||
*/
|
*/
|
||||||
static void collect_ddr3(spdinfo_t *const config)
|
static void collect_ddr3(sysinfo_t *const sysinfo, spdinfo_t *const config)
|
||||||
{
|
{
|
||||||
int mask = config->dimm_mask;
|
int mask = config->dimm_mask;
|
||||||
int cur = 0;
|
int cur = 0;
|
||||||
while (mask != 0) {
|
while (mask != 0) {
|
||||||
if (mask & 1) {
|
/* FIXME: support several dimms on same channel. */
|
||||||
|
if ((mask & 1) && sysinfo->spd_map[2 * cur]) {
|
||||||
int tmp;
|
int tmp;
|
||||||
const int smb_addr = DIMM0 + cur*2;
|
const int smb_addr = sysinfo->spd_map[2 * cur];
|
||||||
|
|
||||||
config->channel[cur].rows = ((smbus_read_byte(smb_addr, 5) >> 3) & 7) + 12;
|
config->channel[cur].rows = ((smbus_read_byte(smb_addr, 5) >> 3) & 7) + 12;
|
||||||
config->channel[cur].cols = (smbus_read_byte(smb_addr, 5) & 7) + 9;
|
config->channel[cur].cols = (smbus_read_byte(smb_addr, 5) & 7) + 9;
|
||||||
|
@ -358,7 +360,7 @@ static void collect_ddr3(spdinfo_t *const config)
|
||||||
config->channel[cur].raw_card = smbus_read_byte(smb_addr, 62) & 0x1f;
|
config->channel[cur].raw_card = smbus_read_byte(smb_addr, 62) & 0x1f;
|
||||||
}
|
}
|
||||||
cur++;
|
cur++;
|
||||||
mask >>= 2; /* Only every other address is used. */
|
mask >>= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,17 +592,20 @@ static void collect_dimm_config(sysinfo_t *const sysinfo)
|
||||||
spdinfo.dimm_mask = 0;
|
spdinfo.dimm_mask = 0;
|
||||||
sysinfo->spd_type = 0;
|
sysinfo->spd_type = 0;
|
||||||
|
|
||||||
/* at most 2 dimms, on even slots */
|
for (i = 0; i < 4; i++)
|
||||||
for (i = 0; i < 4; i += 2) {
|
if (sysinfo->spd_map[i]) {
|
||||||
const u8 spd = smbus_read_byte(DIMM0 + i, 2);
|
const u8 spd = smbus_read_byte(sysinfo->spd_map[i], 2);
|
||||||
if ((spd == 7) || (spd == 8) || (spd == 0xb)) {
|
printk (BIOS_DEBUG, "%x:%x:%x\n",
|
||||||
spdinfo.dimm_mask |= 1 << i;
|
i, sysinfo->spd_map[i],
|
||||||
if (sysinfo->spd_type && sysinfo->spd_type != spd) {
|
spd);
|
||||||
die("Multiple types of DIMM installed in the system, don't do that!\n");
|
if ((spd == 7) || (spd == 8) || (spd == 0xb)) {
|
||||||
|
spdinfo.dimm_mask |= 1 << i;
|
||||||
|
if (sysinfo->spd_type && sysinfo->spd_type != spd) {
|
||||||
|
die("Multiple types of DIMM installed in the system, don't do that!\n");
|
||||||
|
}
|
||||||
|
sysinfo->spd_type = spd;
|
||||||
}
|
}
|
||||||
sysinfo->spd_type = spd;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (spdinfo.dimm_mask == 0) {
|
if (spdinfo.dimm_mask == 0) {
|
||||||
die("Could not find any DIMM.\n");
|
die("Could not find any DIMM.\n");
|
||||||
}
|
}
|
||||||
|
@ -612,8 +617,8 @@ static void collect_dimm_config(sysinfo_t *const sysinfo)
|
||||||
if (sysinfo->spd_type == DDR2) {
|
if (sysinfo->spd_type == DDR2) {
|
||||||
die("DDR2 not supported at this time.\n");
|
die("DDR2 not supported at this time.\n");
|
||||||
} else if (sysinfo->spd_type == DDR3) {
|
} else if (sysinfo->spd_type == DDR3) {
|
||||||
verify_ddr3(spdinfo.dimm_mask);
|
verify_ddr3(sysinfo, spdinfo.dimm_mask);
|
||||||
collect_ddr3(&spdinfo);
|
collect_ddr3(sysinfo, &spdinfo);
|
||||||
} else {
|
} else {
|
||||||
die("Will never support DDR1.\n");
|
die("Will never support DDR1.\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue