* [lm-sensors] Ticket #2323 - Preliminary support for DDR3 in
@ 2008-11-22 21:36 Paul Goyette
2008-11-23 8:39 ` Jean Delvare
0 siblings, 1 reply; 2+ messages in thread
From: Paul Goyette @ 2008-11-22 21:36 UTC (permalink / raw)
To: lm-sensors
[-- Attachment #1: Type: TEXT/PLAIN, Size: 553 bytes --]
The attached diffs provide some preliminary decode of the DDR3 SPD...
Warning: I'm no perl expert. The code I've written is probably ugly to
most of the readers of this list. But it does work!
----------------------------------------------------------------------
| Paul Goyette | PGP DSS Key fingerprint: | E-mail addresses: |
| Customer Service | FA29 0E3B 35AF E8AE 6651 | paul@whooppee.com |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette@juniper.net |
----------------------------------------------------------------------
[-- Attachment #2: Type: TEXT/PLAIN, Size: 6742 bytes --]
872a873,983
> # Parameter: bytes 0-127
> sub decode_ddr3_sdram($)
> {
> my $bytes = shift;
> my $l;
> my $temp;
> my $ctime;
>
> # SPD revision
> if ($bytes->[62] != 0xff) {
> printl "SPD Revision", ($bytes->[62] >> 4) . "." .
> ($bytes->[62] & 0xf);
> }
>
> # speed
> prints "Memory Characteristics";
>
> $l = "Fine time base";
> my $dividend = ($bytes->[9] >> 4) & 15;
> my $divisor = $bytes->[9] & 15;
> printl $l, sprintf("%.3f", $dividend / $divisor) . " ps";
>
> $l = "Medium time base";
> $dividend = $bytes->[10];
> $divisor = $bytes->[11];
> my $mtb = $dividend / $divisor;
> printl $l, sprintf("%.3f", $mtb) . " ns";
>
> $l = "Maximum module speed";
> $ctime = $bytes->[12] * $mtb;
> my $ddrclk = 2 * (1000 / $ctime);
> my $tbits = 1 << (($bytes->[8] & 7) + 3);
> my $pcclk = int ($ddrclk * $tbits / 8);
> $ddrclk = int ($ddrclk);
> printl $l, "${ddrclk}MHz (PC3-${pcclk})";
>
> # Size computation
>
> my $cap = ($bytes->[4] & 15) + 28;
> $cap += ($bytes->[8] & 7) + 3;
> $cap -= ($bytes->[7] & 7) + 2;
> $cap -= 20 + 3;
> my $k = (($bytes->[7] >> 3) & 31) + 1;
> printl "Size", ((1 << $cap) * $k) . " MB";
>
> printl "Banks x Rows x Columns x Bits",
> join(' x ', 1 << ((($bytes->[4] >> 4) & 7) + 3),
> ((($bytes->[5] >> 3) & 31) + 12),
> ( ($bytes->[5] & 7) + 9),
> ( 1 << (($bytes->[6] & 7) + 3)) );
> printl "Ranks", $k;
>
> printl "SDRAM Device Width", $bytes->[13]." bits";
>
> my $taa;
> my $trcd;
> my $trp;
> my $tras;
>
> $taa = int($bytes->[16] / $bytes->[12]);
> $trcd = int($bytes->[18] / $bytes->[12]);
> $trp = int($bytes->[20] / $bytes->[12]);
> $tras = int((($bytes->[21] >> 4) * 256 + $bytes->[22]) / $bytes->[12]);
>
> printl "tCL-tRCD-tRP-tRAS", join("-", $taa, $trcd, $trp, $tras);
>
> prints "Manufacturer Data";
>
> $l = "Module Manufacturer Code";
> printl $l, sprintf("0x%.2X%.2X", $bytes->[118], $bytes->[117]);
>
> $l = "DRAM Manufacturer Code";
> printl $l, sprintf("0x%.2X%.2X", $bytes->[148], $bytes->[149]);
>
> $l = "Manufacturing Location";
> $temp = (chr($bytes->[8]) =~ m/^[\w\d]$/) ? chr($bytes->[8])
> : sprintf("0x%.2X", $bytes->[8]);
> printl $l, $temp;
>
> $l = "Part Number";
> $temp = "";
> for (my $i = 128; $i <= 145; $i++) {
> $temp .= chr($bytes->[$i]);
> };
> printl $l, $temp;
>
> $l = "Revision";
> $temp = sprintf("0x%02X%02X\n", $bytes->[146], $bytes->[147]);
> printl $l, $temp;
>
> $l = "Manufacturing Date";
> # In theory the year and week are in BCD format, but
> # this is not always true in practice :(
> if (($bytes->[120] & 0xf0) <= 0x90
> && ($bytes->[120] & 0x0f) <= 0x09
> && ($bytes->[121] & 0xf0) <= 0x90
> && ($bytes->[121] & 0x0f) <= 0x09) {
> # Note that this heuristic will break in year 2080
> $temp = sprintf("%d%02X-W%02X\n",
> $bytes->[120] >= 0x80 ? 19 : 20,
> $bytes->[120], $bytes->[121]);
> } else {
> $temp = sprintf("0x%02X%02X\n", $bytes->[120], $bytes->[121]);
> }
> printl $l, $temp;
>
> $l = "Assembly Serial Number";
> $temp = sprintf("0x%02X%02X%02X%02X\n", $bytes->[122], $bytes->[123]);
> printl $l, $temp;
> }
>
1063a1175
> "DDR3 SDRAM" => \&decode_ddr3_sdram,
1181a1294,1319
> sub readfullspd($$) # reads all bytes from SPD-EEPROM
> {
> my ($size, $dimm_i) = @_;
> my @bytes;
> if ($use_hexdump) {
> @bytes = read_hexdump($dimm_i);
> return @bytes[0..$size];
> } elsif ($use_sysfs) {
> # Kernel 2.6 with sysfs
> sysopen(HANDLE, "/sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom", O_RDONLY)
> or die "Cannot open /sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom";
> binmode HANDLE;
> sysseek(HANDLE, 0, SEEK_SET);
> sysread(HANDLE, my $eeprom, $size);
> close HANDLE;
> @bytes = unpack(sprintf("C%d", $size), $eeprom);
> } else {
> # Kernel 2.4 with procfs
> for my $i (0 .. $size/16) {
> my $hexoff = sprintf('%02x', $i * 16);
> push @bytes, split(" ", `cat /proc/sys/dev/sensors/$dimm_i/$hexoff`);
> }
> }
> return @bytes;
> }
>
1274,1276d1411
< next unless $bytes[63] == $dimm_checksum || $opt_igncheck;
< $dimm_count++;
<
1295,1300d1429
< my $l = "EEPROM Checksum of bytes 0-62";
< printl $l, ($bytes[63] == $dimm_checksum ?
< sprintf("OK (0x%.2X)", $bytes[63]):
< sprintf("Bad\n(found 0x%.2X, calculated 0x%.2X)\n",
< $bytes[63], $dimm_checksum));
<
1302c1431,1476
< my $is_rambus = $bytes[0] < 4;
---
> my $is_rambus = ($bytes[0] < 4 && $bytes[0] >= 0);
>
> if ($is_rambus || $bytes[2] <= 8) {
> my $l = "EEPROM Checksum of bytes 0-62";
> printl $l, ($bytes[63] == $dimm_checksum ?
> sprintf("OK (0x%.2X)", $bytes[63]):
> sprintf("Bad\n(found 0x%.2X, calculated 0x%.2X)\n",
> $bytes[63], $dimm_checksum));
> next unless $bytes[63] == $dimm_checksum ||
> $opt_igncheck;
> $dimm_count++;
>
> } else {
> my @sizes = ( 128, 176, 256, 0, 0, 0, 0, 0);
> my $spdsize = $sizes[($bytes[0] >> 4) & 7];
>
> @bytes = readfullspd($spdsize, $dimm_list[$i]);
> my $dimm_crc = 0;
> my $crc_cover = $bytes[0] & 0x80 ? 116 : 125;
> my $crc_ptr = 0;
> my $crc_bit;
> while ($crc_ptr <= $crc_cover) {
> $dimm_crc = $dimm_crc ^ ($bytes[$crc_ptr] << 8);
> for ($crc_bit = 0; $crc_bit < 8; $crc_bit++) {
> if ($dimm_crc & 0x8000) {
> $dimm_crc = ($dimm_crc << 1) ^
> 0x1021;
> } else {
> $dimm_crc = $dimm_crc << 1
> }
> }
> $crc_ptr++;
> }
> $dimm_crc = $dimm_crc & 0xffff;
>
> my $l = "EEPROM CRC of bytes 0-" .
> sprintf("%d", $crc_cover);
> my $crc_calc = $bytes[127] << 8 | $bytes[126];
> printl $l, ($dimm_crc == $crc_calc)?
> sprintf("OK (0x%.4X)", $dimm_crc):
> sprintf("Bad\n(found 0x%.4X, calculated 0x%.4X)\n",
> $crc_calc, $dimm_crc);
> next unless $crc_calc == $dimm_crc || $opt_igncheck;
> $dimm_count++;
> }
>
1315c1489
< $l = "Total number of bytes in EEPROM";
---
> my $l = "Total number of bytes in EEPROM";
1335a1510,1512
> elsif ($bytes[2] == 9) { $type = "FB-DIMM"; }
> elsif ($bytes[2] == 10) { $type = "FB-DIMM PROBE"; }
> elsif ($bytes[2] == 11) { $type = "DDR3 SDRAM"; }
1342a1520,1524
> # DDR3 Manufacturer info is already decoded
> # (It's NOT common!)
>
> next if ($type == "DDR3 SDRAM");
>
1346c1528,1532
< @bytes = readspd64(64, $dimm_list[$i]);
---
> if ($#bytes == 63) {
> @bytes = readspd64(64, $dimm_list[$i]);
> } else {
> @bytes = @bytes[64..$#bytes];
> }
[-- Attachment #3: Type: text/plain, Size: 153 bytes --]
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [lm-sensors] Ticket #2323 - Preliminary support for DDR3 in
2008-11-22 21:36 [lm-sensors] Ticket #2323 - Preliminary support for DDR3 in Paul Goyette
@ 2008-11-23 8:39 ` Jean Delvare
0 siblings, 0 replies; 2+ messages in thread
From: Jean Delvare @ 2008-11-23 8:39 UTC (permalink / raw)
To: lm-sensors
Hi Paul,
On Sat, 22 Nov 2008 13:36:48 -0800 (PST), Paul Goyette wrote:
> The attached diffs provide some preliminary decode of the DDR3 SPD...
>
> Warning: I'm no perl expert. The code I've written is probably ugly to
> most of the readers of this list. But it does work!
The decode-dimms script has moved to package i2c-tools:
http://www.lm-sensors.org/wiki/I2CTools
Please make sure your patch applies to the version of the decode-dimms
script that is found in this package, then post it to the linux-i2c list:
http://vger.kernel.org/vger-lists.html#linux-i2c
Thanks,
--
Jean Delvare
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-11-23 8:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-22 21:36 [lm-sensors] Ticket #2323 - Preliminary support for DDR3 in Paul Goyette
2008-11-23 8:39 ` Jean Delvare
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.