分享

Linux Kernel 设备驱动之I2C之host之数据传输

 WUCANADA 2018-03-28
在前面我们介绍了I2C host的数据结构描述struct i2c_adapter,其中提到结构中
struct i2c_algorithm *algo;
这个数据结构用于描述或者说用于控制I2C总线上数据格式,其体现了host对传输数据要求,一般我们
在i2c_add_adapter()时需要实现这样一个对象。struct i2c_algorithm定义如下:
/**
 * struct i2c_algorithm - represent I2C transfer method
 * @master_xfer: Issue a set of i2c transactions to the given I2C adapter
 *   defined by the msgs array, with num messages available to transfer via
 *   the adapter specified by adap.
 * @smbus_xfer: Issue smbus transactions to the given I2C adapter. If this
 *   is not present, then the bus layer will try and convert the SMBus calls
 *   into I2C transfers instead.
 * @functionality: Return the flags that this algorithm/adapter pair supports
 *   from the I2C_FUNC_* flags.
 * @reg_slave: Register given client to I2C slave mode of this adapter
 * @unreg_slave: Unregister given client from I2C slave mode of this adapter
 *
 * The following structs are for those who like to implement new bus drivers:
 * i2c_algorithm is the interface to a class of hardware solutions which can
 * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
 * to name two of the most common.
 *
 * The return codes from the @master_xfer field should indicate the type of
 * error code that occurred during the transfer, as documented in the kernel
 * Documentation file Documentation/i2c/fault-codes.
 */
struct i2c_algorithm {
 /* If an adapter algorithm can't do I2C-level access, set master_xfer
    to NULL. If an adapter algorithm can do SMBus access, set
    smbus_xfer. If set to NULL, the SMBus protocol is simulated
    using common I2C messages */
 /* master_xfer should return the number of messages successfully
    processed, or a negative value on error */
 int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
      int num);
 int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
      unsigned short flags, char read_write,
      u8 command, int size, union i2c_smbus_data *data);

 /* To determine what the adapter supports */  u32 (*functionality) (struct i2c_adapter *);

#if IS_ENABLED(CONFIG_I2C_SLAVE)  int (*reg_slave)(struct i2c_client *client);  int (*unreg_slave)(struct i2c_client *client); #endif }; 由于这些跟具体的host相关,所以,在理解host ic之上实现这些函数。

其实根据上面两个函数master_xfersmbus_xfer就可以明白,I2C支持两个类别的传输。对此

内核封装两个函数:i2c_smbus_xfer和__i2c_transfer(),对于后者,其提供封装接口i2c_transfer()

/**  * __i2c_transfer - unlocked flavor of i2c_transfer  * @adap: Handle to I2C bus  * @msgs: One or more messages to execute before STOP is issued to  * terminate the operation; each message begins with a START.  * @num: Number of messages to be executed.  *  * Returns negative errno, else the number of messages executed.  *  * Adapter lock must be held when calling this function. No debug logging  * takes place. adap->algo->master_xfer existence isn't checked.  */ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) {  unsigned long orig_jiffies;  int ret, try;

 if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))   return -EOPNOTSUPP;

 /* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets   * enabled.  This is an efficient way of keeping the for-loop from   * being executed when not needed.   */  if (static_key_false(&i2c_trace_msg)) {   int i;   for (i = 0; i < num; i++)    if (msgs[i].flags & I2C_M_RD)     trace_i2c_read(adap, &msgs[i], i);    else     trace_i2c_write(adap, &msgs[i], i);  }

 /* Retry automatically on arbitration loss */  orig_jiffies = jiffies;  for (ret = 0, try = 0; try <= adap->retries; try++) {   ret = adap->algo->master_xfer(adap, msgs, num);   if (ret != -EAGAIN)    break;   if (time_after(jiffies, orig_jiffies + adap->timeout))    break;  }

 if (static_key_false(&i2c_trace_msg)) {   int i;   for (i = 0; i < ret; i++)    if (msgs[i].flags & I2C_M_RD)     trace_i2c_reply(adap, &msgs[i], i);   trace_i2c_result(adap, i, ret);  }

 return ret; }

/**  * i2c_smbus_xfer - execute SMBus protocol operations  * @adapter: Handle to I2C bus  * @addr: Address of SMBus slave on that bus  * @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC)  * @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE  * @command: Byte interpreted by slave, for protocols which use such bytes  * @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL  * @data: Data to be read or written  *  * This executes an SMBus protocol operation, and 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 protocol,      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_bus(adapter, I2C_LOCK_SEGMENT);

  /* Retry automatically on arbitration loss */   orig_jiffies = jiffies;   for (res = 0, try = 0; try <= adapter->retries; try++) {    res = adapter->algo->smbus_xfer(adapter, addr, flags,        read_write, command,        protocol, data);    if (res != -EAGAIN)     break;    if (time_after(jiffies,            orig_jiffies + adapter->timeout))     break;   }   i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);

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

 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; }

 

 

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多