1. I2C设备树
i2c1: i2c@021a0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
reg = <0x021a0000 0x4000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_I2C1>;
status = "disabled";
};
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
mag3110@0e {
compatible = "fsl,mag3110";
reg = <0x0e>;
position = <2>;
};
fxls8471@1e {
compatible = "fsl,fxls8471";
reg = <0x1e>;
position = <0>;
interrupt-parent = <&gpio5>;
interrupts = <0 8>;
};
};
Device-Tree bindings for i2c gpio driver
Required properties:
- compatible = "i2c-gpio";
- gpios: sda and scl gpio
Optional properties:
- i2c-gpio,sda-open-drain: sda as open drain
- i2c-gpio,scl-open-drain: scl as open drain
- i2c-gpio,scl-output-only: scl as output only
- i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform)
- i2c-gpio,timeout-ms: timeout to get data
Example nodes:
i2c@0 { compatible = "i2c-gpio";
gpios = <&pioA 23 0 /* sda */ &pioA 24 0 /* scl */ >; i2c-gpio,sda-open-drain;
i2c-gpio,scl-open-drain;
i2c-gpio,delay-us = <2>; /* ~100 kHz */
#address-cells = <1>;
#size-cells = <0>;
rv3029c2@56 { compatible = "rv3029c2";
reg = <0x56>; }; };
2. 相关数据结构体
2.1 i2c_adapter-控制器
I2C 适配器,也就是 SOC 的 I2C 控制器。i2c_adapter 结构体定义在 include/linux/i2c.h
/*
* i2c_adapter is the structure used to identify a physical i2c bus along
* with the access algorithms necessary to access it.
*/
struct i2c_adapter {
struct module *owner;
/* 适配器的类类型,在一些口I2C设备驱动中会检查该成员,以判断设备能否被该适配器操作 */
unsigned int class; /* classes to allow probing for */
/* 适配器的类类型,在一些口I2C设备驱动中会检查该成员,以判断设备能否被该适配器操作 */
const struct i2c_algorithm *algo; /* the algorithm to access the bus */
指向通信方法数据的指针,该成员不会被I2C核心层修改,仅供具体的 i2c_algorithm使用
void *algo_data;
/* data fields that are valid for all devices */
struct rt_mutex bus_lock;
/* 传输超时时间 */
int timeout; /* in jiffies */
/* 传输超时的重试次数 */
int retries;
struct device dev; /* the adapter device */
int nr; /*总线编号(也是适配器编号),同时对应设备节点/dev/i2c-x (x=0,1,2 …)中的 x */
/* 适配器名称,该名称可以通过sys/bus/i2c/devices/i2c-x/name (x=0,1,2 … )来访问 */
char name[48];
struct completion dev_released;
struct mutex userspace_clients_lock;
struct list_head userspace_clients;
struct i2c_bus_recovery_info *bus_recovery_info;
const struct i2c_adapter_quirks *quirks;
};
2.2 i2c_algorithm-通信方法
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); //I2C 适配器的传输函数,可以通过此函数来完成与 IIC 设备之 间的通信
int (*master_xfer_atomic)(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); //SMBUS 总线协议的传输函数
int (*smbus_xfer_atomic)(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 *adap); //查看适配的能力。这些功能都是以宏定义的方式表示,定义在include/linux/i2c.h中,以I2C_FUNC开头:
#if IS_ENABLED(CONFIG_I2C_SLAVE)
int (*reg_slave)(struct i2c_client *client);
int (*unreg_slave)(struct i2c_client *client);
#endif
};
/* To determine what functionality is present */
#define I2C_FUNC_I2C 0x00000001
#define I2C_FUNC_10BIT_ADDR 0x00000002
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_IGNORE_NAK etc. */
#define I2C_FUNC_SMBUS_PEC 0x00000008
#define I2C_FUNC_NOSTART 0x00000010 /* I2C_M_NOSTART */
#define I2C_FUNC_SLAVE 0x00000020
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_QUICK 0x00010000
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
#define I2C_FUNC_SMBUS_HOST_NOTIFY 0x10000000
#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
I2C_FUNC_SMBUS_WRITE_BYTE)
#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
I2C_FUNC_SMBUS_WRITE_WORD_DATA)
#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
2.3 i2c_driver-I从设备驱动
struct i2c_driver {
unsigned int class;
/* Notifies the driver that a new bus has appeared. You should avoid
* using this, it will be removed in a near future.
*/
int (*attach_adapter)(struct i2c_adapter *) __deprecated;
/* Standard driver model interfaces */
int (*probe)(struct i2c_client *, const struct i2c_device_id *); //设备和驱动匹配时调用
int (*remove)(struct i2c_client *);
/* New driver model interface to aid the seamless removal of the
* current probe()'s, more commonly unused than used second parameter.
*/
int (*probe_new)(struct i2c_client *);
/* driver model interfaces that don't relate to enumeration */
void (*shutdown)(struct i2c_client *);
/* Alert callback, for example for the SMBus alert protocol.
* The format and meaning of the data value depends on the protocol.
* For the SMBus alert protocol, there is a single bit of data passed
* as the alert response's low bit ("event flag").
* For the SMBus Host Notify protocol, the data corresponds to the
* 16-bit payload data reported by the slave device acting as master.
*/
void (*alert)(struct i2c_client *, enum i2c_alert_protocol protocol,
unsigned int data); // 警告回调函数(例如SMBus警报协议)
/* a ioctl like command that can be used to perform specific functions
* with the device.
*/
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); // 类似于ioctl 的命令控制函数
struct device_driver driver; //在注册i2c_driver对象时,i2c_driver->driver的总线类型被指定为i2c_bus_type
const struct i2c_device_id *id_table; // 这个i2c驱动支持的设备链表
/* Device detection callback for automatic device creation */
int (*detect)(struct i2c_client *, struct i2c_board_info *); // 检测设备的回调函数;
const unsigned short *address_list; // 要探测的I2C地址(用于检测)
struct list_head clients; //探测到的设备列表
bool disable_i2c_core_irq_mapping;
};
2.4 i2c_client-从设备
struct i2c_client{
unsigned short flags; //描述从设备的一些特性,如I2C_CLIENT_TEN---使用的10位地址
unsigned short addr; //设备的i2c地址,7位地址用低7位,10位地址用低10位。
char name[I2C_NAME_SIZE]; // 设备的名字;
struct i2c_adapter *adapter; //所属的适配器i2c_adapter,挂载在哪条i2c物理总线上
struct i2c_driver *driver; //匹配成功的i2c_driver
int irq;
};
3. I2C子系统API
3.1 注册控制器
int i2c_add_adapter(struct i2c_adapter *adapter);//include/linux/i2c.h
int i2c_add_numbered_adapter(struct i2c_adapter *adap);
3.2 注销控制器
void i2c_del_adapter(struct i2c_adapter * adap);
3.3 添加i2c设备驱动
int i2c_register_driver(struct module *owner, struct i2c_driver *driver);//include/linux/i2c.h
/* use a define to avoid include chaining to get THIS_MODULE */
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver);
3.4 删除i2c设备驱动
void i2c_del_driver(struct i2c_driver *driver);
3.5 I2C数据传输
Int i2c_transfer(struct i2c_adapter *adap,struct i2c_msg *msgs, int num);
3.6 smbus输出传输
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)
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_write_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values)
s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values)
4. I2C驱动
I2C驱动模型大概可以分为四层:
- 第一层是应用层,应用层可以使用默写具体设备的驱动程序,也可以通过i2c-dev.c使用原始的I2C通讯方式
- 第二层就是具体设备的应用程序,还有直接控制i2c控制器的控制程序
- I2C Core是对I2C控制器的API的封装
- I2C Controller Driver是对I2C控制器的驱动程序
4.1 核心core层注册
i2c_bus_type的匹配过程与platform_bus_type大概一致
4.2 i2c-dev.c
i2c-dev.c的使用:
i2c-dev.c驱动分析: