Re: i2c-i801 partially broken on Lynx Point PCH?

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

 



On Wed, 11 May 2016 10:43:22 +0200, Jean Delvare wrote:
> On Wed, 11 May 2016 09:34:52 +0200, Jean Delvare wrote:
> > In commit 062737fb6d90 you added support for the Intel Lynx Point PCH
> > to the i2c-i801 driver. I happen to have a machine with this chipset
> > since a few weeks, and found that the i2c-i801 driver doesn't work
> > properly on it. Specifically, the eeprom driver return 0xff for all
> > EEPROM bytes. The at24 driver fails too, with a timeout.
> > 
> > After some testing using i2cdetect, i2cdump and i2cget, I found that
> > some I2C transactions work (SMBUS_QUICK, SMBUS_READ_BYTE,
> > SMBUS_READ_BYTE_DATA, SMBUS_READ_WORD_DATA, SMBUS_READ_BLOCK_DATA),
> > however others do not (SMBUS_WRITE_BYTE, SMBUS_READ_I2C_BLOCK.) I can't
> > easily test other transaction types as all I have on the SMBus are SPD
> > EEPROMs on my memory modules.
> > 
> > Did you test the i2c-i801 driver on an actual Lynx Point PCH chipset?
> > Or did you only add the PCI ID of the device, assuming it would work?
> 
> As an additional data point, I managed to find a machine on the SUSE
> network with a Lynx Point PCH. I tested it and everything works fine
> there. So not all systems with the Lynx Point PCH [8086:8c22] have the
> problem.
> 
> One difference between my system and the working one is the PCI device
> revision (04 for me, 05 for the working machine.) So maybe it has
> something to do with the revision. Or maybe it's a problem with the way
> the BIOS initializes the device (my system is from Dell, the working
> one from Intel.)

OK, I know what's going on.

Starting with the 8-Series/C220 chipsets, Intel introduced a new
configuration bit for the SMBus controller in register HOSTC (PCI
D31:F3 Address Offset 40h):

Bit 4  SPD Write Disable - R/WO.
       0 = SPD write enabled.
       1 = SPD write disabled. Writes to SMBus addresses 50h - 57h are
           disabled.

This bit is set on my machine, and not set on the machine on the SUSE
network, which is why the behavior differs.

I understand the idea of protecting SPD EEPROMs from accidental writes
(even though in practice most memory module vendors write-protect the
EEPROMs themselves.) However I am afraid Intel got the implementation
wrong. They appear to be simply checking bit 0 of the XMIT_SLVA
register to decide if a transaction is a read or a write. Unfortunately
this fails for the 2 best methods available to read EEPROMs:

* The I2C Block Read transaction must set this bit to 0 (write) even if
  it is a read transaction. This is explicitly mentioned in the
  datasheet (page 215, "For I2C Read command, the value written into
  bit 0 of the Transmit Slave Address Register (SMB I/O register,
  offset 04h) needs to be 0.")

* If using continuous byte reads (Receive Byte in SMBus terminology) to
  retrieve the contents of the EEPROM, the read pointer must be reset
  to 0 beforehand. This is done with a Send Byte transaction. While
  this transaction doesn't write data to the EEPROM, it is still
  blocked by the write protection mechanism.

So the only ways left to read the EEPROM contents are 1-byte reads or
at best 2-byte reads. This is far less efficient than I2C Block reads
or continuous byte reads.

Mika/Jarkko, is there any chance to get your hardware people involved?
I wonder if there is any workaround to this issue? Any chance to get
this fixed in future chipsets? Not sure about Send Byte but the write
protection should definitely not block I2C Block Read transactions.

For now we need to come up with a software workaround. I can think of 3
approaches:

1* Remove I2C_FUNC_SMBUS_READ_I2C_BLOCK from the list of supported
   transactions whenever SPD write protection is enabled. In practice I
   think I2C Block Read is only useful for EEPROMs anyway, so I doubt
   anyone else will miss it. This is clearly a hack, but it's quite
   simple. Then the eeprom and at24 drivers will automatically fall
   back to slower read methods.

2* Hack the eeprom and at24 drivers so that in case I2C Block Reads were
   supposed to work but do not, they fallback dynamically to the other
   read methods. The downside is that one-time failures would trigger
   the fallback too.

3* Introduce a finer-grained version of i2c_check_functionality() which
   takes the slave address as an extra parameter. The i2c-i801 driver
   would implement an extra callback function to handle it, and mask out
   I2C_FUNC_SMBUS_READ_I2C_BLOCK and all write transactions if the slave
   address is in the 0x50-0x57 range and the SPD protection bit is set.
   This is more work, enlarges the size of struct i2c_algorithm by one
   pointer, but is certainly cleaner than the two hacks above.

If anyone can think of any better solution, please let me know.

-- 
Jean Delvare
SUSE L3 Support
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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