Changeset 5248

Show
Ignore:
Timestamp:
05/11/08 19:16:27 (6 years ago)
Author:
khali
Message:

Rework all device detection routines which use SMBus read word
transactions in address range 0x40-0x48. Some devices don't like word
transactions, so we now try to do as much of the detection as possible
using byte transactions, and only use word transactions when there is
a good chance that the detection will succeed.

Location:
lm-sensors/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • lm-sensors/trunk/CHANGES

    r5247 r5248  
    2020                          Fix the parsing of I2C addresses not to scan 
    2121                          Detect and skip 1-register-only I2C devices 
     22                          Avoid SMBus word transactions where possible 
    2223 
    23242.10.6 "Welcome Home Lina" (20080306) 
  • lm-sensors/trunk/prog/detect/sensors-detect

    r5247 r5248  
    27252725# $_[1]: Command byte (usually register number) 
    27262726# Returns: -1 on failure, the read word on success. 
     2727# Use this function with care, some devices don't like word reads, 
     2728# so you should do as much of the detection as possible using byte reads, 
     2729# and only start using word reads when there is a good chance that 
     2730# the detection will succeed. 
    27272731# Note: some devices use the wrong endiannes; use swap_bytes to correct for  
    27282732# this. 
     
    35883592# all register addresses from 0x04 to 0x0f behave like 0x04-0x07 do for 
    35893593# the LM75. 
     3594# Not all devices enjoy SMBus read word transactions, so we use read byte 
     3595# transactions even for the 16-bit registers. The low bits aren't very 
     3596# useful for detection anyway. 
    35903597sub lm75_detect 
    35913598{ 
    35923599  my $i; 
    35933600  my ($chip, $file, $addr) = @_; 
    3594   my $cur = i2c_smbus_read_word_data($file,0x00); 
     3601  my $cur = i2c_smbus_read_byte_data($file, 0x00); 
    35953602  my $conf = i2c_smbus_read_byte_data($file,0x01); 
    35963603 
    3597   my $hyst = i2c_smbus_read_word_data($file,0x02); 
     3604  my $hyst = i2c_smbus_read_byte_data($file, 0x02); 
    35983605  my $maxreg = $chip == 1 ? 0x0f : 0x07; 
    35993606  for $i (0x04 .. $maxreg) { 
    3600     return if i2c_smbus_read_word_data($file, $i) != $hyst; 
    3601   } 
    3602  
    3603   my $os = i2c_smbus_read_word_data($file,0x03); 
     3607    return if i2c_smbus_read_byte_data($file, $i) != $hyst; 
     3608  } 
     3609 
     3610  my $os = i2c_smbus_read_byte_data($file, 0x03); 
    36043611  for $i (0x04 .. $maxreg) { 
    3605     return if i2c_smbus_read_word_data($file, $i) != $os; 
     3612    return if i2c_smbus_read_byte_data($file, $i) != $os; 
    36063613  } 
    36073614 
     
    36093616    for ($i = 8; $i <= 248; $i += 40) { 
    36103617      return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf 
    3611              or i2c_smbus_read_word_data($file, $i + 0x02) != $hyst 
    3612              or i2c_smbus_read_word_data($file, $i + 0x03) != $os; 
     3618             or i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst 
     3619             or i2c_smbus_read_byte_data($file, $i + 0x03) != $os; 
    36133620    } 
    36143621  } 
    36153622 
    36163623  # All registers hold the same value, obviously a misdetection 
    3617   return if $conf == ($cur & 0xff) and $cur == $hyst 
    3618     and $cur == $os; 
    3619  
    3620   $cur = swap_bytes($cur); 
    3621   $hyst = swap_bytes($hyst); 
    3622   $os = swap_bytes($os); 
     3624  return if $conf == $cur and $cur == $hyst and $cur == $os; 
     3625 
    36233626  # Unused bits 
    36243627  return if $chip == 0 and ($conf & 0xe0); 
    36253628  return if $chip == 1 and ($conf & 0x80); 
    36263629 
    3627   $cur = $cur >> 8; 
    3628   $hyst = $hyst >> 8; 
    3629   $os = $os >> 8; 
    36303630  # Most probable value ranges 
    36313631  return 6 if $cur <= 100 and ($hyst >= 10 && $hyst <= 125) 
     
    36463646#   0x04: Low limit 
    36473647#   0x05: High limit 
    3648 #   0x04-0x07: No registers 
     3648#   0x06-0x07: No registers 
    36493649# The first detection step is based on the fact that the LM77 has only 
    36503650# six registers, and cycles addresses over 8-byte boundaries. We use the 
     
    36533653# documented. 
    36543654# Note that register 0x00 may change, so we can't use the modulo trick on it. 
     3655# Not all devices enjoy SMBus read word transactions, so we use read byte 
     3656# transactions even for the 16-bit registers at first. We only use read word 
     3657# transactions in the end when we are already almost certain that we have an 
     3658# LM77 chip. 
    36553659sub lm77_detect 
    36563660{ 
    36573661  my $i; 
    36583662  my ($file,$addr) = @_; 
    3659   my $cur = i2c_smbus_read_word_data($file,0x00); 
     3663  my $cur = i2c_smbus_read_byte_data($file, 0x00); 
    36603664  my $conf = i2c_smbus_read_byte_data($file,0x01); 
    3661   my $hyst = i2c_smbus_read_word_data($file,0x02); 
    3662   my $os = i2c_smbus_read_word_data($file,0x03); 
    3663  
    3664   my $low = i2c_smbus_read_word_data($file,0x04); 
    3665   return if i2c_smbus_read_word_data($file,0x06) != $low; 
    3666   return if i2c_smbus_read_word_data($file,0x07) != $low; 
    3667  
    3668   my $high = i2c_smbus_read_word_data($file,0x05); 
    3669   return if i2c_smbus_read_word_data($file,0x06) != $high; 
    3670   return if i2c_smbus_read_word_data($file,0x07) != $high; 
     3665  my $hyst = i2c_smbus_read_byte_data($file, 0x02); 
     3666  my $os = i2c_smbus_read_byte_data($file, 0x03); 
     3667 
     3668  my $low = i2c_smbus_read_byte_data($file, 0x04); 
     3669  return if i2c_smbus_read_byte_data($file, 0x06) != $low; 
     3670  return if i2c_smbus_read_byte_data($file, 0x07) != $low; 
     3671 
     3672  my $high = i2c_smbus_read_byte_data($file, 0x05); 
     3673  return if i2c_smbus_read_byte_data($file, 0x06) != $high; 
     3674  return if i2c_smbus_read_byte_data($file, 0x07) != $high; 
    36713675 
    36723676  for ($i = 8; $i <= 248; $i += 40) { 
    36733677    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf; 
    3674     return if i2c_smbus_read_word_data($file, $i + 0x02) != $hyst; 
    3675     return if i2c_smbus_read_word_data($file, $i + 0x03) != $os; 
    3676     return if i2c_smbus_read_word_data($file, $i + 0x04) != $low; 
    3677     return if i2c_smbus_read_word_data($file, $i + 0x05) != $high; 
     3678    return if i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst; 
     3679    return if i2c_smbus_read_byte_data($file, $i + 0x03) != $os; 
     3680    return if i2c_smbus_read_byte_data($file, $i + 0x04) != $low; 
     3681    return if i2c_smbus_read_byte_data($file, $i + 0x05) != $high; 
    36783682  } 
    36793683 
    36803684  # All registers hold the same value, obviously a misdetection 
    3681   return if $conf == ($cur & 0xff) and $cur == $hyst 
     3685  return if $conf == $cur and $cur == $hyst 
    36823686    and $cur == $os and $cur == $low and $cur == $high; 
    36833687 
    3684   $cur = swap_bytes($cur); 
    3685   $os = swap_bytes($os); 
    3686   $hyst = swap_bytes($hyst); 
    3687   $low = swap_bytes($low); 
    3688   $high = swap_bytes($high); 
    36893688  # Unused bits 
    36903689  return if ($conf & 0xe0) 
    3691     or (($cur >> 12) != 0 && ($cur >> 12) != 0xf) 
    3692     or (($hyst >> 12) != 0 && ($hyst >> 12) != 0xf) 
    3693     or (($os >> 12) != 0 && ($os >> 12) != 0xf) 
    3694     or (($low >> 12) != 0 && ($low >> 12) != 0xf) 
    3695     or (($high >> 12) != 0 && ($high >> 12) != 0xf); 
     3690    or (($cur >> 4) != 0 && ($cur >> 4) != 0xf) 
     3691    or (($hyst >> 4) != 0 && ($hyst >> 4) != 0xf) 
     3692    or (($os >> 4) != 0 && ($os >> 4) != 0xf) 
     3693    or (($low >> 4) != 0 && ($low >> 4) != 0xf) 
     3694    or (($high >> 4) != 0 && ($high >> 4) != 0xf); 
     3695 
     3696  # Make sure the chip supports SMBus read word transactions 
     3697  $cur = i2c_smbus_read_word_data($file, 0x00); 
     3698  return if $cur < 0; 
     3699  $hyst = i2c_smbus_read_word_data($file, 0x02); 
     3700  return if $hyst < 0; 
     3701  $os = i2c_smbus_read_word_data($file, 0x03); 
     3702  return if $os < 0; 
     3703  $low = i2c_smbus_read_word_data($file, 0x04); 
     3704  return if $low < 0; 
     3705  $high = i2c_smbus_read_word_data($file, 0x05); 
     3706  return if $high < 0; 
    36963707 
    36973708  $cur /= 16; 
     
    37213732# limited number of registers, which cycle modulo 16 address values. 
    37223733# Note that register 0x00 may change, so we can't use the modulo trick on it. 
     3734# Not all devices enjoy SMBus read word transactions, so we use read byte 
     3735# transactions even for the 16-bit registers at first. We only use read 
     3736# word transactions in the end when we are already almost certain that we 
     3737# have an LM92 chip or compatible. 
    37233738sub lm92_detect 
    37243739{ 
     
    37263741 
    37273742  my $conf = i2c_smbus_read_byte_data($file, 0x01); 
    3728   my $hyst = i2c_smbus_read_word_data($file, 0x02); 
    3729   my $crit = i2c_smbus_read_word_data($file, 0x03); 
    3730   my $low = i2c_smbus_read_word_data($file, 0x04); 
    3731   my $high = i2c_smbus_read_word_data($file, 0x05); 
     3743  my $hyst = i2c_smbus_read_byte_data($file, 0x02); 
     3744  my $crit = i2c_smbus_read_byte_data($file, 0x03); 
     3745  my $low = i2c_smbus_read_byte_data($file, 0x04); 
     3746  my $high = i2c_smbus_read_byte_data($file, 0x05); 
    37323747 
    37333748  return if $conf == 0 and $hyst == 0 and $crit == 0 
    37343749        and $low == 0 and $high == 0; 
    37353750 
     3751  # Unused bits 
     3752  return if ($chip == 0 || $chip == 1) 
     3753        and ($conf & 0xE0); 
     3754 
     3755  for (my $i = 0; $i <= 240; $i += 16) { 
     3756    return if i2c_smbus_read_byte_data($file, $i + 0x01) != $conf; 
     3757    return if i2c_smbus_read_byte_data($file, $i + 0x02) != $hyst; 
     3758    return if i2c_smbus_read_byte_data($file, $i + 0x03) != $crit; 
     3759    return if i2c_smbus_read_byte_data($file, $i + 0x04) != $low; 
     3760    return if i2c_smbus_read_byte_data($file, $i + 0x05) != $high; 
     3761  } 
     3762   
    37363763  return if $chip == 0 
    37373764        and i2c_smbus_read_word_data($file, 0x07) != 0x0180; 
    3738    
    3739   return if ($chip == 0 || $chip == 1) 
    3740         and ($conf & 0xE0); 
    3741  
    3742   for (my $i = 0; $i < 8; $i++) { 
    3743     return if i2c_smbus_read_byte_data($file, $i*16+0x01) != $conf; 
    3744     return if i2c_smbus_read_word_data($file, $i*16+0x02) != $hyst; 
    3745     return if i2c_smbus_read_word_data($file, $i*16+0x03) != $crit; 
    3746     return if i2c_smbus_read_word_data($file, $i*16+0x04) != $low; 
    3747     return if i2c_smbus_read_word_data($file, $i*16+0x05) != $high; 
    3748   } 
    3749    
     3765 
     3766  # Make sure the chip supports SMBus read word transactions 
     3767  $hyst = i2c_smbus_read_word_data($file, 0x02); 
     3768  return if $hyst < 0; 
     3769  $crit = i2c_smbus_read_word_data($file, 0x03); 
     3770  return if $crit < 0; 
     3771  $low = i2c_smbus_read_word_data($file, 0x04); 
     3772  return if $low < 0; 
     3773  $high = i2c_smbus_read_word_data($file, 0x05); 
     3774  return if $high < 0; 
     3775 
    37503776  foreach my $temp ($hyst, $crit, $low, $high) { 
    37513777    return if $chip == 2 and ($temp & 0x7F00); 
     
    37643790#   0xA1: High limit 
    37653791#   0xA2: Low limit 
     3792#   0xA8: Counter 
     3793#   0xA9: Slope 
    37663794#   0xAC: Configuration 
    37673795# Detection is weak. We check if bit 4 (NVB) is clear, because it is 
    37683796# unlikely to be set (would mean that EEPROM is currently being accessed). 
    3769 # Temperature checkings will hopefully prevent LM75 or other chips from 
    3770 # being detected as a DS1621. 
     3797# We also check the value of the counter and slope registers, the datasheet 
     3798# doesn't mention the possible values but the conversion formula together 
     3799# with experimental evidence suggest possible sanity checks. 
     3800# Not all devices enjoy SMBus read word transactions, so we do as much as 
     3801# possible with read byte transactions first, and only use read word 
     3802# transactions second. 
    37713803sub ds1621_detect 
    37723804{ 
    3773   my $i; 
    37743805  my ($file,$addr) = @_; 
     3806 
     3807  my $conf = i2c_smbus_read_byte_data($file, 0xAC); 
     3808  return if ($conf & 0x10); 
     3809 
     3810  my $counter = i2c_smbus_read_byte_data($file, 0xA8); 
     3811  my $slope = i2c_smbus_read_byte_data($file, 0xA9); 
     3812  return if ($slope != 0x10 || $counter > $slope); 
     3813 
    37753814  my $temp = i2c_smbus_read_word_data($file,0xAA); 
     3815  return if $temp < 0 || ($temp & 0x7f00); 
    37763816  my $high = i2c_smbus_read_word_data($file,0xA1); 
     3817  return if $high < 0 || ($high & 0x7f00); 
    37773818  my $low = i2c_smbus_read_word_data($file,0xA2); 
    3778   return if ($temp | $high | $low) & 0x7F00; 
    3779   my $conf = i2c_smbus_read_byte_data($file,0xAC); 
     3819  return if $low < 0 || ($low & 0x7f00); 
     3820 
    37803821  return if ($temp == 0 && $high == 0 && $low == 0 && $conf == 0); 
    3781   return 3 if ($conf & 0x10) == 0x00; 
    3782   return; 
     3822 
     3823  return 3; 
    37833824} 
    37843825