I2C 和 SPI 很相似,放在一起讲。
I2C 和 SPI 都是 SOC 上的外设,厂商已经实现好了主机控制器驱动,所以无论换什么芯片,驱动的写法都是一样的。
总线架构
I2C 功能架构:

SPI 功能架构:

原来的名称匹配、ID 匹配被淘汰了(需要手动创建 struct i2c_client 结构体对象),现在都用设备树匹配了,
内核启动时解析设备树,会自动将I2C设备节点转换为一个 struct i2c_client 结构对象,当有匹配的驱动注册时,会调用其 probe 函数。
设备树语法
I2C:
&i2c2 {
clock_frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
gt9147: gt9147@14 {
compatible = "goodix,gt9147", "goodix,gt9xx";
reg = <0x14>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ts_int
&pinctrl_ts_reset>;
interrupt-parent = <&gpio1>;
interrupts = <9 0>;
reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
interrupt-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
status="okay";
};
};设备节点写在 i2c 节点下,关键是设置设备的通信地址 reg = <0x14>,这个地址是 7 位地址,不包括读写位。
SPI:
使用方法
有两种使用方式:
应用层直接使用主机控制器驱动,即使用
/dev/i2c-N或/dev/spidev总线号.片选编号设备文件,这种情况适合外设比较简单的。如果外设比较复杂,还是需要写个专门的驱动给应用层屏蔽一下复杂的操作,。
第一种方式:
这个的前提是配置中开启了:
ioctl(fd, I2C_SLAVE, long addr)
ioctl(fd, I2C_FUNCS, unsigned long * funcs)
ioctl(fd, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)ioctl:
第二种方式:
i2c_add_driver
i2c_set_clientdata设备相关函数:
1、注册和删除 I2C 设备驱动
i2c_add_driver
i2c_del_driver示例:
static struct i2c_driver gt9147_driver = {
.driver = {
.name = "gt9147",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gt9147_of_match),
},
.probe = gt9147_probe,
.remove = gt9147_remove,
};
static int __init gt9147_init(void)
{
return i2c_add_driver(>9147_driver);
}
static void __exit gt9147_exit(void)
{
i2c_del_driver(>9147_driver);
}
module_init(gt9147_init);
module_exit(gt9147_exit);从 static int __init gt9147_init(void) 到 module_exit(gt9147_exit); 这一段代码都是固定的,有专门简化的宏:
module_i2c_driver(gt9147_driver);2、设置/获取客户端数据
3、检查
(2)数据收发函数:
s32 i2c_smbus_write_byte_data(const struct i2c_client *client,
u8 command, u8 value);
s32 i2c_smbus_read_byte_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_word_data(const struct i2c_client *client,
u8 command);
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);原始函数:
int i2c_master_send(const struct i2c_client *client, const char *buf, int count);
int i2c_master_recv(const struct i2c_client *client, char *buf, int count);