- lib-build-add-missing-dependencies.patch: Fix random failure
of parallel builds. - decode-dimms-hackweek-DDR4.patch: Add DDR4 SDRAM memory support to decode-dimms (Hackweek 0x10 project.) OBS-URL: https://build.opensuse.org/package/show/Base:System/i2c-tools?expand=0&rev=46
This commit is contained in:
parent
198c06506c
commit
8264074f83
471
decode-dimms-hackweek-DDR4.patch
Normal file
471
decode-dimms-hackweek-DDR4.patch
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
From: Jean Delvare <jdelvare@suse.de>
|
||||||
|
Subject: decode-dimms: Add support for DDR4 SDRAM memory
|
||||||
|
Patch-mainline: yes
|
||||||
|
Git-commit: f91ab551fa73e4fe831122fb390ac2166e66af67
|
||||||
|
Git-commit: 56149a6f847933aa6c51392bfe9d513cbc0e443d
|
||||||
|
Git-commit: 9ae51c4a4f8e1e1836470ac7e5fec9c7f6df8ce6
|
||||||
|
Git-commit: 52cd6c60d6db0e39f00a67f5931c06cccb63e178
|
||||||
|
Git-commit: eea0b508aaefd687ed559992cece05608418c605
|
||||||
|
Git-commit: 84da8192c7c409f37c1906b60ef166c58aafc847
|
||||||
|
|
||||||
|
This is my hackweek 0x10 project:
|
||||||
|
Add support for DDR4 SDRAM memory modules to decode-dimms
|
||||||
|
|
||||||
|
* Add preliminary DDR4 support
|
||||||
|
* Decode size and timings of DDR4
|
||||||
|
* Decode misc parameters of DDR4
|
||||||
|
* Decode physical characteristics of DDR4
|
||||||
|
* Documentation update for DDR4
|
||||||
|
* Verify the CRC of DDR4 data block 1
|
||||||
|
---
|
||||||
|
eeprom/decode-dimms | 326 ++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||||
|
eeprom/decode-dimms.1 | 7 -
|
||||||
|
2 files changed, 320 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
--- a/eeprom/decode-dimms
|
||||||
|
+++ b/eeprom/decode-dimms
|
||||||
|
@@ -5,7 +5,7 @@
|
||||||
|
# Copyright 1998, 1999 Philip Edelbrock <phil@netroedge.com>
|
||||||
|
# modified by Christian Zuckschwerdt <zany@triq.net>
|
||||||
|
# modified by Burkart Lingner <burkart@bollchen.de>
|
||||||
|
-# Copyright (C) 2005-2013 Jean Delvare <jdelvare@suse.de>
|
||||||
|
+# Copyright (C) 2005-2017 Jean Delvare <jdelvare@suse.de>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -1404,6 +1404,7 @@ sub ddr3_mtb_ftb($$$$)
|
||||||
|
return $byte1 * $mtb + $byte2 * $ftb / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
+# Also works for DDR4
|
||||||
|
sub ddr3_reference_card($$)
|
||||||
|
{
|
||||||
|
my ($rrc, $ext) = @_;
|
||||||
|
@@ -1702,6 +1703,251 @@ sub decode_ddr3_sdram($)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
+# Return combined time in ns
|
||||||
|
+sub ddr4_mtb_ftb($$$$)
|
||||||
|
+{
|
||||||
|
+ my ($byte1, $byte2, $mtb, $ftb) = @_;
|
||||||
|
+
|
||||||
|
+ # byte1 is unsigned in ps, but byte2 is signed in ps
|
||||||
|
+ $byte2 -= 0x100 if $byte2 & 0x80;
|
||||||
|
+
|
||||||
|
+ return ($byte1 * $mtb + $byte2 * $ftb) / 1000;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+# Rounded per DDR4 specifications
|
||||||
|
+sub ddr4_core_timings($$$$$)
|
||||||
|
+{
|
||||||
|
+ my ($cas, $ctime, $trcd, $trp, $tras) = @_;
|
||||||
|
+
|
||||||
|
+ return $cas . "-" . ceil($trcd/$ctime - 0.025) .
|
||||||
|
+ "-" . ceil($trp/$ctime - 0.025) .
|
||||||
|
+ "-" . ceil($tras/$ctime - 0.025);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+use constant DDR4_UNBUFFERED => 1;
|
||||||
|
+use constant DDR4_REGISTERED => 2;
|
||||||
|
+use constant DDR4_LOAD_REDUCED => 4;
|
||||||
|
+
|
||||||
|
+# Parameter: EEPROM bytes 0-383 (using 1-255)
|
||||||
|
+sub decode_ddr4_sdram($)
|
||||||
|
+{
|
||||||
|
+ my $bytes = shift;
|
||||||
|
+ my ($ctime, $ctime_max);
|
||||||
|
+ my ($ftb, $mtb);
|
||||||
|
+ my $ii;
|
||||||
|
+
|
||||||
|
+ my @module_types = (
|
||||||
|
+ { type => "Extended type", },
|
||||||
|
+ { type => "RDIMM", family => DDR4_REGISTERED },
|
||||||
|
+ { type => "UDIMM", family => DDR4_UNBUFFERED },
|
||||||
|
+ { type => "SO-DIMM", family => DDR4_UNBUFFERED },
|
||||||
|
+ { type => "LRDIMM", family => DDR4_LOAD_REDUCED },
|
||||||
|
+ { type => "Mini-RDIMM", family => DDR4_REGISTERED },
|
||||||
|
+ { type => "Mini-UDIMM", family => DDR4_UNBUFFERED },
|
||||||
|
+ { type => "Reserved (0x07)", },
|
||||||
|
+ { type => "72b-SO-RDIMM", family => DDR4_REGISTERED },
|
||||||
|
+ { type => "72b-SO-UDIMM", family => DDR4_UNBUFFERED },
|
||||||
|
+ { type => "Reserved (0x0A)", },
|
||||||
|
+ { type => "Reserved (0x0B)", },
|
||||||
|
+ { type => "16b-SO-DIMM", family => DDR4_UNBUFFERED },
|
||||||
|
+ { type => "32b-SO-DIMM", family => DDR4_UNBUFFERED },
|
||||||
|
+ { type => "Reserved (0x0E)", },
|
||||||
|
+ { type => "No base memory", },
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+# SPD revision
|
||||||
|
+ printl_cond($bytes->[1] != 0xff, "SPD Revision",
|
||||||
|
+ ($bytes->[1] >> 4) . "." . ($bytes->[1] & 0xf));
|
||||||
|
+
|
||||||
|
+ printl("Module Type", $module_types[$bytes->[3] & 0x0f]->{type});
|
||||||
|
+
|
||||||
|
+# CRC of block 1
|
||||||
|
+ my $crc_calc = calculate_crc($bytes, 128, 126);
|
||||||
|
+ my $crc_spd = ($bytes->[255] << 8) | $bytes->[254];
|
||||||
|
+ my $crc_block_1_ok = $crc_calc == $crc_spd;
|
||||||
|
+ printl("EEPROM CRC of bytes 128-253", $crc_block_1_ok ?
|
||||||
|
+ sprintf("OK (0x\%04X)", $crc_calc) :
|
||||||
|
+ sprintf("Bad\n(found 0x\%04X, calculated 0x\%04X)",
|
||||||
|
+ $crc_spd, $crc_calc));
|
||||||
|
+
|
||||||
|
+# time bases
|
||||||
|
+ if (($bytes->[17] & 0x03) != 0x00 || ($bytes->[17] & 0xc0) != 0x00) {
|
||||||
|
+ print STDERR "Unknown time base values, can't decode\n";
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ $ftb = 1; # ps
|
||||||
|
+ $mtb = 125; # ps
|
||||||
|
+
|
||||||
|
+# speed
|
||||||
|
+ prints("Memory Characteristics");
|
||||||
|
+
|
||||||
|
+ $ctime = ddr4_mtb_ftb($bytes->[18], $bytes->[125], $mtb, $ftb);
|
||||||
|
+ $ctime_max = ddr4_mtb_ftb($bytes->[19], $bytes->[124], $mtb, $ftb);
|
||||||
|
+
|
||||||
|
+ my $ddrclk = 2 * (1000 / $ctime);
|
||||||
|
+ my $tbits = 8 << ($bytes->[13] & 7);
|
||||||
|
+ my $pcclk = int ($ddrclk * $tbits / 8);
|
||||||
|
+ # Round down to comply with Jedec
|
||||||
|
+ $pcclk = $pcclk - ($pcclk % 100);
|
||||||
|
+ $ddrclk = int ($ddrclk);
|
||||||
|
+ printl("Maximum module speed", "$ddrclk MHz (PC4-${pcclk})");
|
||||||
|
+
|
||||||
|
+# Size computation
|
||||||
|
+ my $sdram_width = 4 << ($bytes->[12] & 0x07);
|
||||||
|
+ my $ranks = (($bytes->[12] >> 3) & 0x07) + 1;
|
||||||
|
+ my $signal_loading = $bytes->[6] & 0x03;
|
||||||
|
+ my $die_count = (($bytes->[6] >> 4) & 0x07) + 1;
|
||||||
|
+ my $cap = (256 << ($bytes->[4] & 0x0f)) / 8;
|
||||||
|
+ $cap *= (8 << ($bytes->[13] & 0x07)) / $sdram_width;
|
||||||
|
+ $cap *= $ranks;
|
||||||
|
+ $cap *= $die_count if $signal_loading == 0x02; # 3DS
|
||||||
|
+ printl("Size", $cap . " MB");
|
||||||
|
+
|
||||||
|
+ printl("Banks x Rows x Columns x Bits",
|
||||||
|
+ join(' x ', (1 << ($bytes->[4] >> 6)) * (4 << (($bytes->[4] >> 4) & 0x03)),
|
||||||
|
+ ((($bytes->[5] >> 3) & 7) + 12),
|
||||||
|
+ ( ($bytes->[5] & 7) + 9),
|
||||||
|
+ (8 << ($bytes->[13] & 0x07))));
|
||||||
|
+
|
||||||
|
+ printl("SDRAM Device Width", "$sdram_width bits");
|
||||||
|
+ printl("Ranks", $ranks);
|
||||||
|
+ printl_cond($ranks > 1, "Rank Mix",
|
||||||
|
+ $bytes->[12] & 0x40 ? "Asymmetrical" : "Symmetrical");
|
||||||
|
+ printl_cond($bytes->[13] & 0x18, "Bus Width Extension", ($bytes->[13] & 0x18)." bits");
|
||||||
|
+
|
||||||
|
+ my $taa;
|
||||||
|
+ my $trcd;
|
||||||
|
+ my $trp;
|
||||||
|
+ my $tras;
|
||||||
|
+
|
||||||
|
+ $taa = ddr4_mtb_ftb($bytes->[24], $bytes->[123], $mtb, $ftb);
|
||||||
|
+ $trcd = ddr4_mtb_ftb($bytes->[25], $bytes->[122], $mtb, $ftb);
|
||||||
|
+ $trp = ddr4_mtb_ftb($bytes->[26], $bytes->[121], $mtb, $ftb);
|
||||||
|
+ $tras = ((($bytes->[27] & 0x0f) << 8) + $bytes->[28]) * $mtb / 1000;
|
||||||
|
+
|
||||||
|
+ printl("AA-RCD-RP-RAS (cycles)",
|
||||||
|
+ ddr4_core_timings(ceil($taa/$ctime - 0.025), $ctime,
|
||||||
|
+ $trcd, $trp, $tras));
|
||||||
|
+
|
||||||
|
+# latencies
|
||||||
|
+ my %cas;
|
||||||
|
+ my $cas_sup = ($bytes->[23] << 24) + ($bytes->[22] << 16) +
|
||||||
|
+ ($bytes->[21] << 8) + $bytes->[20];
|
||||||
|
+ my $base_cas = $bytes->[23] & 0x80 ? 23 : 7;
|
||||||
|
+
|
||||||
|
+ for ($ii = 0; $ii < 30; $ii++) {
|
||||||
|
+ if ($cas_sup & (1 << $ii)) {
|
||||||
|
+ $cas{$base_cas + $ii}++;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ printl("Supported CAS Latencies", cas_latencies(keys %cas));
|
||||||
|
+
|
||||||
|
+# standard DDR4 speeds
|
||||||
|
+ prints("Timings at Standard Speeds");
|
||||||
|
+ foreach my $ctime_at_speed (15/24, 15/22, 15/20, 15/18, 15/16, 15/14, 15/12) {
|
||||||
|
+ my $best_cas = 0;
|
||||||
|
+
|
||||||
|
+ # Find min CAS latency at this speed
|
||||||
|
+ for ($ii = 29; $ii >= 0; $ii--) {
|
||||||
|
+ next unless ($cas_sup & (1 << $ii));
|
||||||
|
+ if (ceil($taa/$ctime_at_speed - 0.025) <= $base_cas + $ii) {
|
||||||
|
+ $best_cas = $base_cas + $ii;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ printl_cond($best_cas && $ctime_at_speed >= $ctime
|
||||||
|
+ && $ctime_at_speed <= $ctime_max,
|
||||||
|
+ "AA-RCD-RP-RAS (cycles)" . as_ddr(4, $ctime_at_speed),
|
||||||
|
+ ddr4_core_timings($best_cas, $ctime_at_speed,
|
||||||
|
+ $trcd, $trp, $tras));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+# more timing information
|
||||||
|
+ prints("Timing Parameters");
|
||||||
|
+
|
||||||
|
+ printl("Minimum Cycle Time (tCKmin)", tns3($ctime));
|
||||||
|
+ printl("Maximum Cycle Time (tCKmax)", tns3($ctime_max));
|
||||||
|
+ printl("Minimum CAS Latency Time (tAA)", tns3($taa));
|
||||||
|
+ printl("Minimum RAS to CAS Delay (tRCD)", tns3($trcd));
|
||||||
|
+ printl("Minimum Row Precharge Delay (tRP)", tns3($trp));
|
||||||
|
+ printl("Minimum Active to Precharge Delay (tRAS)", tns3($tras));
|
||||||
|
+ printl("Minimum Active to Auto-Refresh Delay (tRC)",
|
||||||
|
+ tns3(ddr4_mtb_ftb((($bytes->[27] & 0xf0) << 4) + $bytes->[29],
|
||||||
|
+ $bytes->[120], $mtb, $ftb)));
|
||||||
|
+ printl("Minimum Recovery Delay (tRFC1)",
|
||||||
|
+ tns3((($bytes->[31] << 8) + $bytes->[30]) * $mtb / 1000));
|
||||||
|
+ printl("Minimum Recovery Delay (tRFC2)",
|
||||||
|
+ tns3((($bytes->[33] << 8) + $bytes->[32]) * $mtb / 1000));
|
||||||
|
+ printl("Minimum Recovery Delay (tRFC4)",
|
||||||
|
+ tns3((($bytes->[35] << 8) + $bytes->[34]) * $mtb / 1000));
|
||||||
|
+ printl("Minimum Four Activate Window Delay (tFAW)",
|
||||||
|
+ tns3(((($bytes->[36] & 0x0f) << 8) + $bytes->[37]) * $mtb / 1000));
|
||||||
|
+ printl("Minimum Row Active to Row Active Delay (tRRD_S)",
|
||||||
|
+ tns3(ddr4_mtb_ftb($bytes->[38], $bytes->[119], $mtb, $ftb)));
|
||||||
|
+ printl("Minimum Row Active to Row Active Delay (tRRD_L)",
|
||||||
|
+ tns3(ddr4_mtb_ftb($bytes->[39], $bytes->[118], $mtb, $ftb)));
|
||||||
|
+ printl("Minimum CAS to CAS Delay (tCCD_L)",
|
||||||
|
+ tns3(ddr4_mtb_ftb($bytes->[40], $bytes->[117], $mtb, $ftb)));
|
||||||
|
+
|
||||||
|
+ # Optional?
|
||||||
|
+ my $twr = ((($bytes->[41] & 0x0f) << 8) + $bytes->[42]) * $mtb / 1000;
|
||||||
|
+ printl_cond($twr, "Minimum Write Recovery Time (tWR)", tns3($twr));
|
||||||
|
+ my $twtr = ((($bytes->[43] & 0x0f) << 8) + $bytes->[44]) * $mtb / 1000;
|
||||||
|
+ printl_cond($twtr, "Minimum Write to Read Time (tWTR_S)", tns3($twtr));
|
||||||
|
+ $twtr = ((($bytes->[43] & 0xf0) << 4) + $bytes->[45]) * $mtb / 1000;
|
||||||
|
+ printl_cond($twtr, "Minimum Write to Read Time (tWTR_L)", tns3($twtr));
|
||||||
|
+
|
||||||
|
+# miscellaneous stuff
|
||||||
|
+ prints("Other Information");
|
||||||
|
+
|
||||||
|
+ my $package_type = ($bytes->[6] & 0x80) == 0x00 ? "Monolithic" :
|
||||||
|
+ $signal_loading == 0x01 ? "Multi-load stack" :
|
||||||
|
+ $signal_loading == 0x02 ? "3DS" : "Unknown";
|
||||||
|
+ $package_type .= sprintf(" (%u dies)", $die_count) if $die_count >= 2;
|
||||||
|
+ printl("Package Type", $package_type);
|
||||||
|
+
|
||||||
|
+ my @mac = ("Untested",
|
||||||
|
+ "700 K", "600 K", "500 K", "400 K", "300 K", "200 K",
|
||||||
|
+ undef, "Unlimited");
|
||||||
|
+ my $mac = $bytes->[7] & 0x0f;
|
||||||
|
+ printl_cond(defined $mac[$mac], "Maximum Activate Count", $mac[$mac]);
|
||||||
|
+
|
||||||
|
+ my $ppr = $bytes->[9] >> 6;
|
||||||
|
+ printl("Post Package Repair",
|
||||||
|
+ $ppr == 0x00 ? "Not supported" :
|
||||||
|
+ $ppr == 0x01 ? "One row per bank group" : "Unknown");
|
||||||
|
+ printl_cond($ppr != 0x00, "Soft PPR", $bytes->[9] & 0x20 ?
|
||||||
|
+ "Supported" : "Not Supported");
|
||||||
|
+
|
||||||
|
+ printl("Module Nominal Voltage",
|
||||||
|
+ $bytes->[11] & 0x01 ? "1.2 V" :
|
||||||
|
+ $bytes->[11] & 0x02 ? "Unknown (1.2 V endurant)" : "Unknown");
|
||||||
|
+
|
||||||
|
+ printl("Thermal Sensor",
|
||||||
|
+ $bytes->[14] & 0x80 ? "TSE2004 compliant" : "No");
|
||||||
|
+
|
||||||
|
+# type-specific settings
|
||||||
|
+ return unless $crc_block_1_ok || $opt_igncheck;
|
||||||
|
+
|
||||||
|
+ if ($module_types[$bytes->[3] & 0x0f]->{family} == DDR4_UNBUFFERED ||
|
||||||
|
+ $module_types[$bytes->[3] & 0x0f]->{family} == DDR4_REGISTERED ||
|
||||||
|
+ $module_types[$bytes->[3] & 0x0f]->{family} == DDR4_LOAD_REDUCED) {
|
||||||
|
+ prints("Physical Characteristics");
|
||||||
|
+
|
||||||
|
+ my $height = $bytes->[128] & 0x1f;
|
||||||
|
+ printl("Module Height",
|
||||||
|
+ $height == 0x00 ? "15 mm or less" :
|
||||||
|
+ $height == 0x1f ? "more than 45 mm" :
|
||||||
|
+ sprintf("%u mm", $height + 15));
|
||||||
|
+ printl("Module Thickness",
|
||||||
|
+ sprintf("%d mm front, %d mm back",
|
||||||
|
+ ($bytes->[129] & 0x0f) + 1,
|
||||||
|
+ (($bytes->[129] >> 4) & 15) + 1));
|
||||||
|
+ printl("Module Reference Card",
|
||||||
|
+ ddr3_reference_card($bytes->[130], $bytes->[128]));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
# Parameter: EEPROM bytes 0-127 (using 4-5)
|
||||||
|
sub decode_direct_rambus($)
|
||||||
|
{
|
||||||
|
@@ -1747,6 +1993,10 @@ sub decode_rambus($)
|
||||||
|
"DDR SDRAM" => \&decode_ddr_sdram,
|
||||||
|
"DDR2 SDRAM" => \&decode_ddr2_sdram,
|
||||||
|
"DDR3 SDRAM" => \&decode_ddr3_sdram,
|
||||||
|
+ "DDR4 SDRAM" => \&decode_ddr4_sdram,
|
||||||
|
+ "DDR4E SDRAM" => \&decode_ddr4_sdram,
|
||||||
|
+ "LPDDR4 SDRAM" => \&decode_ddr4_sdram,
|
||||||
|
+ "LPDDR4X SDRAM" => \&decode_ddr4_sdram,
|
||||||
|
"Direct Rambus" => \&decode_direct_rambus,
|
||||||
|
"Rambus" => \&decode_rambus,
|
||||||
|
);
|
||||||
|
@@ -1819,6 +2069,35 @@ sub decode_ddr3_mfg_data($)
|
||||||
|
sprintf("0x%02X%02X", $bytes->[146], $bytes->[147]));
|
||||||
|
}
|
||||||
|
|
||||||
|
+# Parameter: EEPROM bytes 0-383 (using 320-351)
|
||||||
|
+sub decode_ddr4_mfg_data($)
|
||||||
|
+{
|
||||||
|
+ my $bytes = shift;
|
||||||
|
+
|
||||||
|
+ prints("Manufacturer Data");
|
||||||
|
+
|
||||||
|
+ printl("Module Manufacturer",
|
||||||
|
+ manufacturer_ddr3($bytes->[320], $bytes->[321]));
|
||||||
|
+
|
||||||
|
+ printl_cond(spd_written(@{$bytes}[350..351]),
|
||||||
|
+ "DRAM Manufacturer",
|
||||||
|
+ manufacturer_ddr3($bytes->[350], $bytes->[351]));
|
||||||
|
+
|
||||||
|
+ printl_mfg_location_code($bytes->[322]);
|
||||||
|
+
|
||||||
|
+ printl_cond(spd_written(@{$bytes}[323..324]),
|
||||||
|
+ "Manufacturing Date",
|
||||||
|
+ manufacture_date($bytes->[323], $bytes->[324]));
|
||||||
|
+
|
||||||
|
+ printl_mfg_assembly_serial(@{$bytes}[325..328]);
|
||||||
|
+
|
||||||
|
+ printl("Part Number", part_number(@{$bytes}[329..348]));
|
||||||
|
+
|
||||||
|
+ printl_cond(spd_written(@{$bytes}[349]),
|
||||||
|
+ "Revision Code",
|
||||||
|
+ sprintf("0x%02X", $bytes->[349]));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
# Parameter: EEPROM bytes 0-127 (using 64-98)
|
||||||
|
sub decode_manufacturing_information($)
|
||||||
|
{
|
||||||
|
@@ -1941,8 +2220,14 @@ sub read_hexdump($)
|
||||||
|
sub spd_sizes($)
|
||||||
|
{
|
||||||
|
my $bytes = shift;
|
||||||
|
+ my $type = $bytes->[2];
|
||||||
|
|
||||||
|
- if ($bytes->[2] >= 9) {
|
||||||
|
+ if ($type == 12 || $type == 14 || $type == 16 || $type == 17) {
|
||||||
|
+ # DDR4
|
||||||
|
+ my $spd_len = 256 * (($bytes->[0] >> 4) & 7);
|
||||||
|
+ my $used = 128 * ($bytes->[0] & 15);
|
||||||
|
+ return ($spd_len, $used);
|
||||||
|
+ } elsif ($type >= 9) {
|
||||||
|
# For FB-DIMM and newer, decode number of bytes written
|
||||||
|
my $spd_len = ($bytes->[0] >> 4) & 7;
|
||||||
|
my $size = 64 << ($bytes->[0] & 15);
|
||||||
|
@@ -2014,15 +2299,14 @@ sub checksum($)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Calculate and verify CRC
|
||||||
|
-sub check_crc($)
|
||||||
|
+sub calculate_crc($$$)
|
||||||
|
{
|
||||||
|
- my $bytes = shift;
|
||||||
|
+ my ($bytes, $start, $len) = @_;
|
||||||
|
my $crc = 0;
|
||||||
|
- my $crc_cover = $bytes->[0] & 0x80 ? 116 : 125;
|
||||||
|
- my $crc_ptr = 0;
|
||||||
|
+ my $crc_ptr = $start;
|
||||||
|
my $crc_bit;
|
||||||
|
|
||||||
|
- while ($crc_ptr <= $crc_cover) {
|
||||||
|
+ while ($crc_ptr < $start + $len) {
|
||||||
|
$crc = $crc ^ ($bytes->[$crc_ptr] << 8);
|
||||||
|
for ($crc_bit = 0; $crc_bit < 8; $crc_bit++) {
|
||||||
|
if ($crc & 0x8000) {
|
||||||
|
@@ -2033,7 +2317,15 @@ sub check_crc($)
|
||||||
|
}
|
||||||
|
$crc_ptr++;
|
||||||
|
}
|
||||||
|
- $crc &= 0xffff;
|
||||||
|
+
|
||||||
|
+ return $crc & 0xffff;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+sub check_crc($)
|
||||||
|
+{
|
||||||
|
+ my $bytes = shift;
|
||||||
|
+ my $crc_cover = $bytes->[0] & 0x80 ? 116 : 125;
|
||||||
|
+ my $crc = calculate_crc($bytes, 0, $crc_cover + 1);
|
||||||
|
|
||||||
|
my $dimm_crc = ($bytes->[127] << 8) | $bytes->[126];
|
||||||
|
return ("EEPROM CRC of bytes 0-$crc_cover",
|
||||||
|
@@ -2136,7 +2428,9 @@ sub get_dimm_list
|
||||||
|
my (@dirs, $dir, $opened, $file, @files);
|
||||||
|
|
||||||
|
if ($use_sysfs) {
|
||||||
|
- @dirs = ('/sys/bus/i2c/drivers/eeprom', '/sys/bus/i2c/drivers/at24');
|
||||||
|
+ @dirs = ('/sys/bus/i2c/drivers/eeprom',
|
||||||
|
+ '/sys/bus/i2c/drivers/at24',
|
||||||
|
+ '/sys/bus/i2c/drivers/ee1004'); # DDR4
|
||||||
|
} else {
|
||||||
|
@dirs = ('/proc/sys/dev/sensors');
|
||||||
|
}
|
||||||
|
@@ -2154,7 +2448,9 @@ sub get_dimm_list
|
||||||
|
# or spd (driver at24)
|
||||||
|
my $attr = sysfs_device_attribute("$dir/$file", "name");
|
||||||
|
next unless defined $attr &&
|
||||||
|
- ($attr eq "eeprom" || $attr eq "spd");
|
||||||
|
+ ($attr eq "eeprom" ||
|
||||||
|
+ $attr eq "spd" ||
|
||||||
|
+ $attr eq "ee1004"); # DDR4
|
||||||
|
} else {
|
||||||
|
next unless $file =~ /^eeprom-/;
|
||||||
|
}
|
||||||
|
@@ -2285,6 +2581,9 @@ for $current (0 .. $#dimm) {
|
||||||
|
"DDR SGRAM", "DDR SDRAM", # 6, 7
|
||||||
|
"DDR2 SDRAM", "FB-DIMM", # 8, 9
|
||||||
|
"FB-DIMM Probe", "DDR3 SDRAM", # 10, 11
|
||||||
|
+ "DDR4 SDRAM", "Reserved", # 12, 13
|
||||||
|
+ "DDR4E SDRAM", "LPDDR3 SDRAM", # 14, 15
|
||||||
|
+ "LPDDR4 SDRAM", "LPDDR4X SDRAM", # 16, 17
|
||||||
|
);
|
||||||
|
if ($bytes[2] < @type_list) {
|
||||||
|
$type = $type_list[$bytes[2]];
|
||||||
|
@@ -2300,6 +2599,13 @@ for $current (0 .. $#dimm) {
|
||||||
|
# Decode DDR3-specific manufacturing data in bytes
|
||||||
|
# 117-149
|
||||||
|
decode_ddr3_mfg_data(\@bytes)
|
||||||
|
+ } elsif ($type eq "DDR4 SDRAM" ||
|
||||||
|
+ $type eq "DDR4E SDRAM" ||
|
||||||
|
+ $type eq "LPDDR4 SDRAM" ||
|
||||||
|
+ $type eq "LPDDR4X SDRAM") {
|
||||||
|
+ # Decode DDR4-specific manufacturing data in bytes
|
||||||
|
+ # 320-383
|
||||||
|
+ decode_ddr4_mfg_data(\@bytes)
|
||||||
|
} else {
|
||||||
|
# Decode next 35 bytes (64-98, common to most
|
||||||
|
# memory types)
|
||||||
|
--- a/eeprom/decode-dimms.1
|
||||||
|
+++ b/eeprom/decode-dimms.1
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
.\"
|
||||||
|
.\" decode-dimms.1 - manpage for the i2c-tools/decode-dimms utility
|
||||||
|
.\" Copyright (C) 2013 Jaromir Capik
|
||||||
|
+.\" Copyright (C) 2017 Jean Delvare
|
||||||
|
.\"
|
||||||
|
.\" This program is free software; you can redistribute it and/or modify
|
||||||
|
.\" it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -16,7 +17,7 @@
|
||||||
|
.\" with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
.\"
|
||||||
|
-.TH decode-dimms 1 "Oct 2013" "i2c-tools" "User Commands"
|
||||||
|
+.TH decode-dimms 1 "Nov 2017" "i2c-tools" "User Commands"
|
||||||
|
.SH NAME
|
||||||
|
decode-dimms \- decode the information found in memory module SPD EEPROMs
|
||||||
|
.SH SYNOPSIS
|
||||||
|
@@ -31,8 +32,8 @@ The purpose of the
|
||||||
|
.B decode-dimms
|
||||||
|
tool is to decode the information found in memory module SPD EEPROMs.
|
||||||
|
The SPD data is read either from the running system or dump files.
|
||||||
|
-In the former case, the tool requires either the eeprom kernel module
|
||||||
|
-or the at24 kernel module to be loaded.
|
||||||
|
+In the former case, the tool requires a kernel module to be loaded:
|
||||||
|
+eeprom, at24 or ee1004 (for DDR4 SDRAM.)
|
||||||
|
.SH PARAMETERS
|
||||||
|
.TP
|
||||||
|
.B \-f, --format
|
@ -1,3 +1,11 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Dec 6 16:01:02 CET 2017 - jdelvare@suse.com
|
||||||
|
|
||||||
|
- lib-build-add-missing-dependencies.patch: Fix random failure
|
||||||
|
of parallel builds.
|
||||||
|
- decode-dimms-hackweek-DDR4.patch: Add DDR4 SDRAM memory support
|
||||||
|
to decode-dimms (Hackweek 0x10 project.)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Mon Oct 30 15:57:32 CET 2017 - jdelvare@suse.com
|
Mon Oct 30 15:57:32 CET 2017 - jdelvare@suse.com
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ Url: https://i2c.wiki.kernel.org/index.php/I2C_Tools
|
|||||||
Source0: https://www.kernel.org/pub/software/utils/i2c-tools/%{name}-%{version}.tar.xz
|
Source0: https://www.kernel.org/pub/software/utils/i2c-tools/%{name}-%{version}.tar.xz
|
||||||
Source1: https://www.kernel.org/pub/software/utils/i2c-tools/%{name}-%{version}.tar.sign
|
Source1: https://www.kernel.org/pub/software/utils/i2c-tools/%{name}-%{version}.tar.sign
|
||||||
Patch1: i2cbusses-path-overflows.patch
|
Patch1: i2cbusses-path-overflows.patch
|
||||||
|
Patch2: lib-build-add-missing-dependencies.patch
|
||||||
|
Patch3: decode-dimms-hackweek-DDR4.patch
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||||
ExcludeArch: s390 s390x
|
ExcludeArch: s390 s390x
|
||||||
|
|
||||||
@ -60,6 +62,8 @@ connected to the I2C or SMBus buses of the system.
|
|||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
%patch1 -p1
|
%patch1 -p1
|
||||||
|
%patch2 -p1
|
||||||
|
%patch3 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
make %{?_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" CC="%{__cc}" BUILD_STATIC_LIB:=0
|
make %{?_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" CC="%{__cc}" BUILD_STATIC_LIB:=0
|
||||||
|
28
lib-build-add-missing-dependencies.patch
Normal file
28
lib-build-add-missing-dependencies.patch
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
From: Jean Delvare <jdelvare@suse.de>
|
||||||
|
Date: Wed, 6 Dec 2017 09:55:04 +0100
|
||||||
|
Subject: lib/Module.mk: Add missing dependencies
|
||||||
|
Patch-mainline: yes
|
||||||
|
Git-commit: a6a59693066fd8da81f7107479df3e32a129247d
|
||||||
|
|
||||||
|
The lib symlinks lacked a dependency to the actual library file, so
|
||||||
|
parallel builds could run into a race and break.
|
||||||
|
---
|
||||||
|
lib/Module.mk | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
--- a/lib/Module.mk
|
||||||
|
+++ b/lib/Module.mk
|
||||||
|
@@ -42,11 +42,11 @@ endif
|
||||||
|
$(LIB_DIR)/$(LIB_SHLIBNAME): $(LIB_DIR)/smbus.o
|
||||||
|
$(CC) -shared $(LDFLAGS) -Wl,--version-script=$(LIB_DIR)/libi2c.map -Wl,-soname,$(LIB_SHSONAME) -o $@ $^ -lc
|
||||||
|
|
||||||
|
-$(LIB_DIR)/$(LIB_SHSONAME):
|
||||||
|
+$(LIB_DIR)/$(LIB_SHSONAME): $(LIB_DIR)/$(LIB_SHLIBNAME)
|
||||||
|
$(RM) $@
|
||||||
|
$(LN) $(LIB_SHLIBNAME) $@
|
||||||
|
|
||||||
|
-$(LIB_DIR)/$(LIB_SHBASENAME):
|
||||||
|
+$(LIB_DIR)/$(LIB_SHBASENAME): $(LIB_DIR)/$(LIB_SHLIBNAME)
|
||||||
|
$(RM) $@
|
||||||
|
$(LN) $(LIB_SHLIBNAME) $@
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user