About I2c_smbus Series functions __ Functions

Source: Internet
Author: User
Kernel version: linux-4.5

I2c_smbus series functions are:
S32 i2c_smbus_read_byte (const struct i2c_client *client);
S32 i2c_smbus_write_byte (const struct i2c_client *client, U8 value);
S32 i2c_smbus_read_byte_data (const struct i2c_client *client, U8 command);
S32 i2c_smbus_write_byte_data (const struct i2c_client *client, U8
				command, U8 value);
S32 i2c_smbus_read_word_data (const struct i2c_client *client, U8 command);
S32 i2c_smbus_write_word_data (const struct i2c_client *client, U8
				command, U16 value);
S32 i2c_smbus_read_block_data (const struct i2c_client *client, U8
				command, U8 *values);
S32 i2c_smbus_write_block_data (const struct i2c_client *client, U8
				command, U8 length, const U8 *values);
S32 i2c_smbus_read_i2c_block_data (const struct i2c_client *client, U8
				command, U8 length, U8 *values);
S32 i2c_smbus_write_i2c_block_data (const struct i2c_client *client, U8
				command, U8 length, const U8 *values);

The

SMBs is based on the I2C bus, but is slightly different from the I2C bus, and is no longer a concern here. The series of functions above

is ultimately called the I2c_smbus_xfer () function, and the I2c_smbus_xfer () function code is as follows:

/** * I2c_smbus_xfer-execute SMBus Protocol operations * @adapter: Handle to I2C Bus * @addr: Address of SMBus Slave On, Bus * @flags: i2c_client_* flags (usually zero or i2c_client_pec) * @read_write: I2c_smbus_read or I2c_smbus_wri TE * @command: Byte interpreted by slave, for protocols which use such bytes * @protocol: SMBus protocol operation to ex Ecute, such as I2c_smbus_proc_call * @data: Data to is read or written * * This executes a SMBUS protocol, a
 nd returns a negative * errno code else Zero on success. * * S32 i2c_smbus_xfer (struct i2c_adapter *adapter, U16 addr, unsigned short flags, char read_write, U8 command, int p
	Rotocol, Union i2c_smbus_data *data) {unsigned long orig_jiffies;
	int try;

	S32 Res;
	 /* If enabled, the following two tracepoints are conditional on * read_write and protocol.
	* * Trace_smbus_write (adapter, addr, flags, Read_write, command, Protocol, data);
		Trace_smbus_read (adapter, addr, flags, Read_write,	 command, protocol); Flags &= I2c_m_ten | I2c_client_pec |

	I2C_CLIENT_SCCB;

		if (adapter->algo->smbus_xfer) {I2c_lock_adapter (adapter);
		/* Retry automatically on Arbitration loss * * orig_jiffies = jiffies; for (res = 0, try = 0; try <= adapter->retries; try++) {res = Adapter->algo->smbus_xfer (adapter, ADDR, Fla
			GS, Read_write, command, Protocol, data);
			if (res!=-eagain) break;
		if (Time_after (jiffies, orig_jiffies + adapter->timeout)) break;

		} i2c_unlock_adapter (adapter);
		if (res!=-eopnotsupp | |!adapter->algo->master_xfer) goto trace; 
		 * * Fall back to i2c_smbus_xfer_emulated if the adapter doesn ' t * implement native for the support SMBus.

*/Res = i2c_smbus_xfer_emulated (adapter, addr, flags, Read_write, command, Protocol, data); Trace:/* If enabled, the reply tracepoint is conditional on read_write. * * Trace_smbus_reply (adapter, addr, flags, READ_write, command, Protocol, data);

	Trace_smbus_result (adapter, addr, flags, Read_write, command, Protocol, RES);
return res; } export_symbol (I2c_smbus_xfer);
First, the i2c_smbus_xfer_emulated () function is called directly to determine whether the host controller supports Smbus_xfer transmission, but usually I2C the primary controller is not supported.
/* Simulate a SMBus command using the I2C protocol No checking of parameters is done! * * static S32 i2c_smbus_xfer_emulated (struct i2c_adapter *adapter, U16 addr, unsigned short flags, char read _write, U8 command, int size, Union i2c_smbus_data *data) {/* so we need to generate a series of msgs. In the case of writing, we are need to use only one; When reading, we need two. We Initialize most things with sane defaults, to keep the code below somewhat.
	* * unsigned char msgbuf0[i2c_smbus_block_max+3];
	unsigned char msgbuf1[i2c_smbus_block_max+2]; int num = Read_write = = I2c_smbus_read?
	2:1;
	int i;
	U8 Partial_pec = 0;
	int status;
			struct I2c_msg msg[2] = {{. addr = addr,. Flags = Flags,. Len = 1,. buf = msgbuf0,}, {. addr = addr, . Flags = Flags |

	I2c_m_rd,. Len = 0,. buf = Msgbuf1,},};
	MSGBUF0[0] = command;
		switch (size) {case I2c_smbus_quick:msg[0].len = 0; /* Special case:the Read/writE field is used as data */Msg[0].flags = Flags |
					(Read_write = = I2c_smbus_read?)
		i2c_m_rd:0);
		num = 1;
	Break Case I2c_smbus_byte:if (Read_write = = I2c_smbus_read) {/* Special case:only a read! * * msg[0].flags = I2C_M_RD |
			Flags
		num = 1;
	} break;
		Case I2c_smbus_byte_data:if (Read_write = = i2c_smbus_read) Msg[1].len = 1;
			else {Msg[0].len = 2;
		MSGBUF0[1] = data->byte;
	} break;
		Case I2c_smbus_word_data:if (Read_write = = i2c_smbus_read) Msg[1].len = 2;
			else {Msg[0].len = 3;
			MSGBUF0[1] = Data->word & 0xFF;
		MSGBUF0[2] = Data->word >> 8;
	} break; Case i2c_smbus_proc_call:num = 2;
		/* Special Case */read_write = I2c_smbus_read;
		Msg[0].len = 3;
		Msg[1].len = 2;
		MSGBUF0[1] = Data->word & 0xFF;
		MSGBUF0[2] = Data->word >> 8;
	Break
			Case I2c_smbus_block_data:if (Read_write = = i2c_smbus_read) {msg[1].flags |= i2c_m_recv_len; Msg[1].len = 1; /* block length would be Added by the underlying bus driver/else {Msg[0].len = data->block[0] + 2;
					if (Msg[0].len > I2c_smbus_block_max + 2) {Dev_err (&adapter->dev, "Invalid block write size%d\n",
				Data->block[0]);
			Return-einval;
		for (i = 1; i < Msg[0].len i++) msgbuf0[i] = data->block[i-1];
	} break; Case i2c_smbus_block_proc_call:num = 2;
		/* Another Special Case * * * read_write = I2c_smbus_read;
				if (Data->block[0] > I2c_smbus_block_max) {dev_err (&adapter->dev, "Invalid block write size%d\n",
			Data->block[0]);
		Return-einval;
		} Msg[0].len = data->block[0] + 2;
		for (i = 1; i < Msg[0].len i++) msgbuf0[i] = data->block[i-1];
		Msg[1].flags |= I2c_m_recv_len; Msg[1].len = 1;
	/* block length is added by the underlying bus driver * * break;
		Case I2c_smbus_i2c_block_data:if (Read_write = = i2c_smbus_read) {Msg[1].len = data->block[0]; else {MSG[0].LEn = data->block[0] + 1;
					if (Msg[0].len > I2c_smbus_block_max + 1) {Dev_err (&adapter->dev, "Invalid block write size%d\n",
				Data->block[0]);
			Return-einval;
		for (i = 1; I <= data->block[0]; i++) msgbuf0[i] = data->block[i];
	} break;
		Default:dev_err (&adapter->dev, "Unsupported transaction%d\n", size);
	Return-eopnotsupp; } i = ((Flags & I2C_CLIENT_PEC) && size!= i2c_smbus_quick && size!= i2c_smbus_i2c_block_
	DATA); if (i) {/* Compute PEC if is a write */if (!
			Msg[0].flags & I2c_m_rd)) {if (num = 1)/* Write only/I2c_smbus_add_pec (&msg[0));
		else/* Write followed by read/Partial_pec = I2c_smbus_msg_pec (0, &msg[0));
	}/* Ask for PEC if last, a read */if (Msg[num-1].flags & I2c_m_rd) msg[num-1].len++;
	Status = I2c_transfer (adapter, MSG, num);

	if (Status < 0) return status; /* Check PEC if LAST message is a read */if (I && (Msg[num-1].flags & I2c_m_rd)) {status = I2c_smbus_check_pec (Partial_pec
		, &msg[num-1]);
	if (Status < 0) return status;
			} if (Read_write = = i2c_smbus_read) switch (size) {case i2c_smbus_byte:data->byte = msgbuf0[0];
		Break
			Case i2c_smbus_byte_data:data->byte = msgbuf1[0];
		Break Case I2c_smbus_word_data:case I2c_smbus_proc_call:data->word = msgbuf1[0] |
			(Msgbuf1[1] << 8);
		Break
			Case i2c_smbus_i2c_block_data:for (i = 0; i < data->block[0]; i++) data->block[i+1] = Msgbuf1[i];
		Break Case I2c_smbus_block_data:case i2c_smbus_block_proc_call:for (i = 0; i < msgbuf1[0] + 1; i++) Data->block
			[i] = msgbuf1[i];
		Break
return 0; }
First two i2c_msg are defined, remember the I2c_transfer () function, and the buf of these two msg are msgbuf0, MSGBUF1, respectively.

And then come to the switch here, which is mainly for the I2c_smbus series of functions.

1. I2c_smbus_read_byte (), I2c_smbus_write_byte ()
These two functions are not of much significance, if it is read, then the site is not even read, if it is write, it is simple to send the value of the past, the device may not know whether this is sent to write the base address or write data, these two functions are somewhat similar to I2C_MASTER_RECV (), I2c_master_send ().

2. I2c_smbus_read_byte_data (), I2c_smbus_write_byte_data ()
The first is read, if read, which transmits two msg, the first msg is used to transmit the read base address, and the second MSG is used to read the data.

Then the Write,write only sends a MSG, sending only one msg bad place is only the single direction transmission, for example writes can only write, reads can only read (note reads the base address is writes the direction). But here's why you can only send a msg, because the direction of the transfer has not changed, including the write base address, write the data are written direction, but the length of the write data is 2, write base address or command, write the data is value.

3. I2c_smbus_read_word_data (), I2c_smbus_write_word_data ()
Similar to the above, only read and write two bytes at a time.

4. I2c_smbus_read_block_data (), I2c_smbus_write_block_data ()
Read note that the length of the read data is not specified here.

5. I2c_smbus_read_i2c_block_data (), I2c_smbus_write_i2c_block_data ()
Unlike the above, read has a length designation.

Unlike the above, the I2c_smbus_write_block_data () function sends the length of the data sent to the device, but not here.


The I2c_transfer function is eventually invoked to send Msg.

So in our I2C device driver, you can simply call the above I2c_smbs interface function, or you can construct i2c_msg, and then call I2c_transfer to send the data.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.