Messages in this thread | | | Date | Thu, 30 Mar 2006 16:45:57 +0200 (CEST) | Subject | Re: I2C SMBUS problem | From | "Jean Delvare" <> |
| |
Hi Aubrey,
On 2006-03-30, Aubrey wrote: > I'm writing a driver for ADI's chip AD7142, the following is the > single register I2C write operation of it: > > [Write] > > (s)-(6-BIT device addr )-(W)-(ACK)- \ > (register addr[15:8])-(ACK)- \ > (register addr[7:0])-(ACK)- \ > (Write Data[15:8])-(ACK)- \ > (Write Data[7:0])-(ACK)-(P)
I guess you really mean 7-bit device address? That's what I2C/SMBus uses.
> I found it does not match any mode of the existing SMBUS specs. > Because the number of the internal register exceeds 8-bit(approximate > 600), the register address(command field) needs 2-byte. > > In the kernel, I found the doc about it. part of it is here: > Documentation/i2c/smbus-protocol > (...) > I2C Block Write > =============== > > The opposite of the Block Read command, this writes bytes to > a device, to a designated register that is specified through the > Comm byte. Note that command lengths of 0, 2, or more bytes are > supported as they are indistinguishable from data. > > S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P > ============================== > > As the doc mentioned, the [Comm] field can be 2 or more bytes. But > this does not match the I2C driver code, see the file > "drivers/i2c/i2c-core.c" > =============================================== > s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 > command, u8 *values) > s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, > u8 length, u8 *values) > > The type of the parameter [command] of these two routines are "u8", I > think that means you can't pass 2 or more bytes command to the > routine. > > So this is my problem. Did I missing something?
You're mostly right. In fact, the documentation you pointed us to is about the I2C protocol itself, not the kernel implementation. In the kernel, we have helper functions for all the SMBus commands (SMBus is a subset of I2C) and two very common non-SMBus transactions (1-byte address block read, and 1-byte address block write). Other transactions can still be done, but are almost never implemented in SMBus masters, so they have no helper functions. You have to use the lower-level i2c access interface.
> I may need to modify the common I2C SMBUS driver and finalize my chip > driver. I want to know if it's acceptable.
You should be able to go with what the core offers. The transaction you want to do is not an SMBus transaction, so you have to go with the i2c access functions: i2c_transfer, i2c_master_send and i2c_master_recv. In your case, i2c_master_send is the best choice.
Or you can use a trick and go with i2c_smbus_write_i2c_block_data after all. The I2C protocol doesn't differenciate between register addresses and written data, it's purely a matter of convention with the addressed chip. So, you can see your transaction not as two register address bytes followed by two data bytes, but as one register address byte followed by three data bytes. It's really the same on the wire, and this fits well in i2c_smbus_write_i2c_block_data.
I would go with i2c_master_send, unless you need some kind of SMBus master compatibility (many SMBus masters implement I2C-like block transfers). May I ask what i2c adapter driver you are using to talk to your AD7142 chip?
-- Jean Delvare - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |