[LinuxBIOS] i82830 raminit.c
Corey Osgood
corey.osgood at gmail.com
Fri Jul 6 03:57:25 CEST 2007
Joseph Smith wrote:
<snip>
>> I really, _REALLY_ don't like this, even if it does work. Reading from
>> spd byte 31 gives you the bank size, in units of 4mb, for both sides of
>> an asymetrical dimm. Please look at the spd spec (Intel or Jedec) to see
>> what you need to do to read it, it's a bit odd. You need to figure out
>> how many places the 1 is shifted, the number of places * 4mb is the size
>> of the bank, if the banks are asymetrical the smaller size is side2. And
>> if you do decide to use it anyways, please add the original copyright
>> holder, I think this is from e7501?
>
> Your right, I don't really feel the above method is necessary. The
> only problem is this with Byte 31:
>
> # Banks Density of Bank 1 Density of bank 2 Byte 31 contents
> 1 32MByte N/A 0000 1000
> 2 32MByte 32MBbyte 0000 1000
> 2 32MByte 16MByte 0000 1100
>
> You can see Byte 31 contents are going to be the same when the density
> is the same no matter how many banks it has. Could this potentially
> give a false reading?? You could also use Byte 5 to determine the
> banks. Could we say something like; if byte 5 has 1 bank than byte 31
> is correct and if byte 5 has 2 banks to muliply byte 31 by 2?? But
> what about the third example above when you have more than 1 bank and
> the densities are different??
Below is a simple example. There are better/faster ways to do it, but
this should just work. Also, coding style is probably very broken, blame
that on Thunderbird.
int i, spd_byte_31, spd_byte_5;
spd_byte_31 = smbus_read_byte(device, 31); //please rename device to dimm
spd_byte_5 = smbus_read_byte(device, 5);
for (i = 8; i >= 0; i--) {
/* Find the larger value. The larger side is always side1 */
if (spd_byte_31 & (1 << i) == (1 << i)) {
sz.side1 = i;
break;
}
}
/* Set to 0 in case it's single sided */
sz.side2 = 0;
/* Test if it's a dual-sided dimm */
if (spd_byte_5 > 1) {
/* Test to see if there's a second value, if so it's asymmetrical */
if (spd_byte_31 != (1 << i)) {
/* Find the second value, picking up where we left off */
/* i-- done initially to make sure we don't get the same value
again */
for (i--; i >= 0; i--) {
if (spd_byte_31 == (1 << i) {
sz.side2 = i;
break;
}
}
/* If not, it's symmetrical */
else {
sz.side2 = sz.side1;
}
return sz; //sizes are now in units of 4mb, so 1 = 4mb, 2 = 8mb, etc.
}
BTW, this has finally made me see the correlation that the i810 uses!
Expect a patch sometime for some major cleanup.
>>> static long spd_set_ram_size(const struct mem_controller *ctrl,
>>> long dimm_mask)
>>> {
>>> int i;
>>> int cum;
>>>
>>> for(i = cum = 0; i < DIMM_SOCKETS; i++) {
>>> struct dimm_size sz;
>>> if (dimm_mask & (1 << i)) {
>>> sz = spd_get_dimm_size(ctrl->channel0[i]);
>>>
>>> /* WISHLIST: would be nice to display it as decimal? */
>>> print_debug("DIMM is ");
>>> print_debug_hex8(sz.side1);
>>> print_debug(" On Side 1\r\n");
>>> print_debug("DIMM is ");
>>> print_debug_hex8(sz.side2);
>>> print_debug(" On Side 2\r\n");
>>>
>>> /* Set the row offset, in KBytes (should this be
>>> * Kbits?). Note that this offset is the start of the
>>> * next row.
>>> */
>>> row_offset = ((sz.side1 + sz.side2) * 1024);
>>>
>>
>> If you're still in the initial testing stages, try to get one
>> single-sided dimm working first. Also, if you have a dual-sided dimm,
>> row_offset needs to be the address at the second side (as far as I
>> know), so only sz.side1 * 1024. This might be chip-dependent,
>> board-dependent, or I might be completely wrong...
> My test board has 128MB on-board, Remember this is a set-top-box. To
> the registry, with the stock bios it shows up as a sindle sided
> so-dimm in socket 2. Initially I could just hardcode alot of this but
> I would like to make it versitial and have the ability to use socket 1
> also. Alot of Laptops use this chip also, so this could open up
> LinuxBios to that front.
Does that dimm provide spd data? lm-sensors dimms-detect.pl should tell
you from userspace, or else dump_spd_data from linuxbios. If not, ignore
it completely for now, just act like it doesn't exist and hardcode it in
later. If so, use that as your test dimm/slot. I suspect it's probably
the former. Once you have one dimm working, try for another. Going for
both the first time through would take a lot of luck.
-Corey
More information about the coreboot
mailing list