@@ -2402,7 +2402,12 @@ sub spd_sizes($)
my $bytes = shift;
my $type = $bytes->[2];
- if ($type == 12 || $type == 14 || $type == 16 || $type == 17) {
+ if ($type == 18 || $type == 19 || $type == 20 || $type == 21) {
+ # DDR5
+ my $spd_len = 256 * ((($bytes->[0] >> 4) & 7) + 1);
+ my $used = $spd_len;
+ return ($spd_len, $used);
+ } elsif ($type == 12 || $type == 14 || $type == 16 || $type == 17) {
# DDR4
my $spd_len = 256 * (($bytes->[0] >> 4) & 7);
my $used = 128 * ($bytes->[0] & 15);
@@ -2511,10 +2516,16 @@ sub calculate_crc($$$)
sub check_crc($)
{
my $bytes = shift;
+ my $is_ddr5 = ($bytes->[0] & 0x70) == 0x30;
my $crc_cover = $bytes->[0] & 0x80 ? 116 : 125;
+ my $crc_start = 126;
+ if ($is_ddr5) {
+ $crc_cover = 509;
+ $crc_start = 510;
+ }
my $crc = calculate_crc($bytes, 0, $crc_cover + 1);
- my $dimm_crc = ($bytes->[127] << 8) | $bytes->[126];
+ my $dimm_crc = ($bytes->[$crc_start + 1] << 8) | $bytes->[$crc_start];
return ("EEPROM CRC of bytes 0-$crc_cover",
($dimm_crc == $crc) ? 1 : 0,
sprintf("0x%04X", $dimm_crc),
@@ -2617,7 +2628,8 @@ sub get_dimm_list
if ($use_sysfs) {
@drivers = ('eeprom',
'at24',
- 'ee1004'); # DDR4
+ 'ee1004', # DDR4
+ 'spd5118'); # DDR5
} else {
@drivers = ('eeprom');
$dir = '/proc/sys/dev/sensors';
@@ -2642,7 +2654,8 @@ sub get_dimm_list
next unless defined $attr &&
($attr eq "eeprom" ||
$attr eq "spd" ||
- $attr eq "ee1004"); # DDR4
+ $attr eq "ee1004" || # DDR4
+ $attr eq "spd5118"); # DDR5
} else {
next unless $file =~ /^eeprom-/;
}
@@ -2684,6 +2697,9 @@ for my $i (0 .. $#dimm) {
$dimm[$i]->{chk_spd}, $dimm[$i]->{chk_calc}) =
checksum(\@bytes);
} else {
+ if (($bytes[0] & 0x70) == 0x30) { # DDR5's checksum is at 510-511
+ push(@bytes, readspd(@bytes, 512, $dimm[$i]->{file}));
+ }
($dimm[$i]->{chk_label}, $dimm[$i]->{chk_valid},
$dimm[$i]->{chk_spd}, $dimm[$i]->{chk_calc}) =
check_crc(\@bytes);