Changeset 5930

Show
Ignore:
Timestamp:
02/16/11 16:08:25 (4 years ago)
Author:
khali
Message:

Fix detection of SPD EEPROM on DDR3 memory modules. DDR3 uses CRC16 over
128 bytes instead of basic checksum over 64 bytes. Contributed by
Clemens Ladisch.

Location:
lm-sensors/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • lm-sensors/trunk/CHANGES

    r5919 r5930  
    2727                        EMC1072, EMC1073, EMC1074, EMC1402, and EMC1424 
    2828                  Fixed address ranges checked for SMSC EMC1403 and EMC1404. 
     29                  Fix detection of SPD EEPROM on DDR3 memory modules 
    2930 
    30313.2.0 (2010-10-10) 
  • lm-sensors/trunk/prog/detect/sensors-detect

    r5916 r5930  
    52655265 
    52665266# Registers used: 
    5267 #   0-63: SPD Data and Checksum 
     5267#   0-63: SPD Data and Checksum (up to DDR2) 
     5268#   0-127: SPD data and CRC (DDR3) 
    52685269sub eeprom_detect 
    52695270{ 
    52705271        my ($file, $addr) = @_; 
     5272        my $device_type = i2c_smbus_read_byte_data($file, 2); 
    52715273        my $checksum = 0; 
    52725274 
    5273         # Check the checksum for validity (works for most DIMMs and RIMMs) 
    5274         for (my $i = 0; $i <= 62; $i++) { 
    5275                 $checksum += i2c_smbus_read_byte_data($file, $i); 
    5276         } 
    5277         $checksum &= 255; 
    5278  
    5279         return 8 if $checksum == i2c_smbus_read_byte_data($file, 63); 
     5275        # Check the checksum or CRC16 for validity 
     5276        if ($device_type >= 1 and $device_type <= 8) { 
     5277                for (my $i = 0; $i < 63; $i++) { 
     5278                        $checksum += i2c_smbus_read_byte_data($file, $i); 
     5279                } 
     5280                $checksum &= 0xff; 
     5281 
     5282                return 8 if $checksum == i2c_smbus_read_byte_data($file, 63); 
     5283        } elsif ($device_type => 9 && $device_type <= 11) { 
     5284                # see JEDEC 21-C 4.1.2.11 2.4 
     5285                my $crc_coverage = i2c_smbus_read_byte_data($file, 0); 
     5286                $crc_coverage = ($crc_coverage & 0x80) ? 117 : 126; 
     5287                for (my $i = 0; $i < $crc_coverage; $i++) { 
     5288                        $checksum ^= i2c_smbus_read_byte_data($file, $i) << 8; 
     5289                        for (my $bit = 0; $bit < 8; $bit++) { 
     5290                                if ($checksum & 0x8000) { 
     5291                                        $checksum = ($checksum << 1) ^ 0x1021; 
     5292                                } else { 
     5293                                        $checksum <<= 1; 
     5294                                } 
     5295                        } 
     5296                } 
     5297                $checksum &= 0xffff; 
     5298 
     5299                return 8 if ($checksum & 0xff) == i2c_smbus_read_byte_data($file, 126) and 
     5300                            ($checksum >> 8) == i2c_smbus_read_byte_data($file, 127); 
     5301 
     5302                # note: if bit 7 of byte 32 is set, a jc42 sensor is at $addr-0x38 
     5303        } 
     5304 
    52805305        return; 
    52815306}