[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