[i2c] How do I use auto-increment?
Jean Delvare
khali at linux-fr.org
Sat Aug 11 16:54:40 CEST 2007
On Fri, 27 Jul 2007 17:26:52 -0500, Syed Mohammed, Khasim wrote:
> >"The CS4270 has MAP auto increment capability, enabled by the INCR bit in
> >the MAP. If INCR
> >is 0, then the MAP will stay constant for successive writes. If INCR is
> >set, then MAP will
> >auto increment after each byte is written, allowing block reads or writes
> >of successive
> >registers."
> >
> >How can I enhance my function to use the auto-increment feature?
>
> If your I2C controller driver supports multi byte read/write, then from your client driver you could do the following
>
> <Your Client structure> *client;
> struct i2c_msg *msg;
>
> /* [MSG1] fill the register address data */
> msg = &(client->xfer_msg[0]);
> msg->addr = client->address;
> msg->len = 1;
> msg->flags = 0; /* Read the register value */
> val = <register address>;
> msg->buf = &val;
>
> /* [MSG2] fill the data rx buffer */
> msg = &(client->xfer_msg[1]);
> msg->addr = client->address;
> msg->flags = I2C_M_RD; /* Read the register value */
> msg->len = num_bytes; /* <NUMBER OF BYTES TO BE READ> */
> msg->buf = <read buffer address>;
>
> ret = i2c_transfer(client->client.adapter, client->xfer_msg, 2);
Also known as i2c_smbus_read_i2c_block_data(client, buffer, num_bytes)
if kernel version >= 2.6.23-rc1 and num_bytes <= 32.
Note though that this is different from auto-increment. Auto-increment
simply means that you can read from the next register without reading
its address, that is, use i2c_smbus_read_byte() instead of
i2c_smbus_read_byte_data(). This is less efficient than the block read
proposed by Kashim, but some chips support auto-increment but not block
reads. Auto-increment would look like:
/* TO DO: Enable auto-increment */
i2c_smbus_write_byte(i2c_client, CS4270_FIRSTREG);
for (i=0; i < CS4270_NUMREGS; i++) {
data = i2c_smbus_read_byte_data(i2c_client);
if (data < 0) {
printk(KERN_ERR "cs4270: I2C read failure, addr=%u reg=%u\n",
i2c_client->addr, CS4270_FIRSTREG + i);
return -EIO;
}
cache[i] = (u8) data;
printk(KERN_INFO "%s: [%u]=%x\n", CS4270_FIRSTREG + i, data);
}
That is, call i2c_smbus_write_byte() to set the initial register
pointer value, then use i2c_smbus_read_byte() instead of
i2c_smbus_read_byte_data() to read the data. This is what the "c" mode
of i2cdump does, if you want to take a look. It's user-space code but
the idea is nevertheless the same.
--
Jean Delvare
More information about the i2c
mailing list