[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