1 i2c_probe_address() 2 i2c_smbus_xfer() 3 i2c_smbus_xfer_emulated(); 4 i2c_transfer(); 5 adap->algo->master_xfer(adap,msgs,num);
adap->algo->master_xfer(adap,msgs,num);实际调用的是bit_xfer()
探测到ssd1306后,其实也就说明了探测到的I2C地址有效, 还需要注册一个描述SSD1306的i2c_client。
static int ssd1306_detect(struct i2c_adapter *adapter, int address, int kind)
{
printk("ssd1306_detect\n");
ssd1306_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
ssd1306_client->addr = address;
ssd1306_client->adapter = adapter;
ssd1306_client->driver = &ssd1306_driver;
strcpy(ssd1306_client->name, "ssd1306");
i2c_attach_client(ssd1306_client);
... ...
}
先转下话题。
在i2c-gpio.c中,
1 static int __init i2c_gpio_init(void) 2 { 3 ... ... 4 ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe); 5 ... ... 6 }
这里实际上是注册了一个platform_driver,我们还要对应的为他注册一个platform_device,
这个platform_device提供了硬件相关的设置,如指定那两个io口为SCL和SDA。
I2c_gpio_dev.c中
static struct i2c_gpio_platform_data i2c_dev = {
.sda_pin = S3C2410_GPG6,
.scl_pin = S3C2410_GPG5,
.udelay = 0,
.timeout = 0,
.sda_is_open_drain = 1,
.scl_is_open_drain = 1,
.scl_is_output_only = 1
};
static struct platform_device i2c_platform_dev = {
.name = "i2c-gpio",
.id = -1,
.dev = {
.release = i2c_dev_release,
.platform_data = (void *)&i2c_dev,
},
};
static int i2c_dev_init(void)
{
platform_device_register(&i2c_platform_dev);
return 0;
}
如果platform_device和platform_driver匹配,就会调用i2c_gpio_probe()
static int __init i2c_gpio_probe(struct platform_device *pdev)
{
struct i2c_gpio_platform_data *pdata;
struct i2c_algo_bit_data *bit_data;
struct i2c_adapter *adap;
... ...
pdata = pdev->dev.platform_data;
... ...
i2c_bit_add_bus(adap);
... ...
}
只有platform_device和platform_driver匹配才能注册i2c_adapter。
到这里,就可以操作ssd1306了。ssd1306写一个字节的操作:
static void ssd1306_write_byte(uint8_t chData, uint8_t chCmd)
{
uint8_t cmd = 0x00;
if (chCmd) {
cmd = 0x40;
} else {
cmd = 0x00;
}
i2c_smbus_write_byte_data(ssd1306_client, cmd, chData);
}
实际上调用了i2c_smbus_write_byte_data()
I2c_core.c提供了几个I2C的读写函数:
1 s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value); 2 s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command); 3 ... ... 4 s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values); 5 s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, 6 u8 length, const u8 *values)
运行代码
注:由于源码的i2c-gpio-bit.c只支持具有开漏输入输出功能的IO模拟I2C, 而我的开发板已经没有具有开漏输入输出功能的IO了,只能使用普通的上啦输入输出IO,对SDA的读写操作,需要切换输入输出方向。因此我把i2c-gpio-bit.c改成普通IO操作SDA,命名为my-i2c-gpio-bit.c,同时i2c-gpio-bit.h和i2c-gpio.c也要做相应改动,分别改为my-i2c-gpio-bit.h和my-i2c-gpio.c。如果使用具有开漏输入输出功能的IO,可以直接使用i2c-gpio-bit.c,i2c-gpio-bit.h,i2c-gpio.c。
代码
i2c_gpio_dev.c
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>