[PATCH 1/6] decode-dimms: Implement DDR5 checksum parsing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Stephen Horvath <s.horvath@xxxxxxxxxxxxxx>

The code here was mostly written by Guenter Roeck with some modifications
for compatibility with other types by me, but it was originally written
only to verify that the eeprom is being read correctly while developing
spd5118. It looks okay to me, although there might be a better way of
figuring out the amount of bytes needed to check the checksum.

Link: https://lore.kernel.org/linux-hwmon/efb77b37-30e5-48a8-b4af-eb9995a2882b@xxxxxxxxxxxx/
Cc: Guenter Roeck <linux@xxxxxxxxxxxx>
Signed-off-by: Stephen Horvath <s.horvath@xxxxxxxxxxxxxx>
---
 eeprom/decode-dimms | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/eeprom/decode-dimms b/eeprom/decode-dimms
index 32e840a107cd3425039fcbc6ce317e2ef610acc1..88ebe67d86d52486c8ce439d885fb3f9c89526b6 100755
--- a/eeprom/decode-dimms
+++ b/eeprom/decode-dimms
@@ -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);

-- 
2.45.2






[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux