最近用到I2C时候,发现对其中一些函数理解还不透彻,加上以前分析的也没有做下笔记,现在重新整理一份,供以后参考。
平台是allwinner A10 linux3.0内核的。
该芯片有3个i2c适配器,资源在linux-3.0/arch/arm/mach-sun4i/devices.c中,定义如下:
/* twi0 */
static struct sun4i_i2c_platform_data sun4i_twi0_pdata[] = {
{
.bus_num = 0,
.frequency = I2C0_TRANSFER_SPEED,
},
};
static struct resource sun4i_twi0_resources[] = {
{
.start = TWI0_BASE_ADDR_START,
.end = TWI0_BASE_ADDR_END,
.flags = IORESOURCE_MEM,
}, {
.start = SW_INT_IRQNO_TWI0,
.end = SW_INT_IRQNO_TWI0,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device sun4i_twi0_device = {
.name = "sun4i-i2c",
.id = 0,
.resource = sun4i_twi0_resources,
.num_resources = ARRAY_SIZE(sun4i_twi0_resources),
.dev = {
.platform_data = sun4i_twi0_pdata,
},
};
有了adapter的资源,就可以注册adapter 到i2c核心中去了,代码在linux-3.0/drivers/i2c/busses/i2c-sunxi.c中,只分析其中的重点代码。
首先是platform_driver:
static struct platform_driver i2c_sunxi_driver = {
.probe = i2c_sunxi_probe,
.remove = __exit_p(i2c_sunxi_remove),
.suspend = i2c_sunxi_suspend,
.resume = i2c_sunxi_resume,
.driver = {
#if defined CONFIG_ARCH_SUN4I
.name = "sun4i-i2c",
#endif
.owner = THIS_MODULE,
},
};
i2c->adap.nr = pdata->bus_num;
i2c->bus_num = pdata->bus_num;
i2c->adap.algo = &i2c_sunxi_algorithm;
ret = request_irq(irq, i2c_sunxi_handler, IRQF_DISABLED, i2c->adap.name, i2c);
ret = i2c_add_numbered_adapter(&i2c->adap);
static unsigned int i2c_sunxi_functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C|I2C_FUNC_10BIT_ADDR|I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm i2c_sunxi_algorithm = {
.master_xfer = i2c_sunxi_xfer,
.functionality = i2c_sunxi_functionality,
};
接着request_irq就是中断到来后接收数据,或者发送数据准备好后,触发中断以发送数据。
i2c_add_numbered_adapter就是核心所在了,前面创建好adatper后,就要将它添加到i2c核心中去。该方法是静态注册一个adapter,还有一个方法叫i2c_add_adapter,是动态注册adapter,有什么区别呢?
区别是一个编号是固定的,如果该编号已经注册过,则失败;另一个是系统自己分配。其实这是软件约定的一个编号而已,和硬件无关。比如,前面有3个adpater,编号分别为0,1,2,这是人为给它编号的,而且电路图上一般也都是这么标记;
所以后续在i2c driver中,就可以根据这里约定的编号来判断自己的设备是否挂在想要的总线上,又比如还可以用i2c_get_adapter(1)函数来获得编号为1的adapter,等等。
int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{
int id;
int status;
if (adap->nr & ~MAX_ID_MASK)
return -EINVAL;
retry:
if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
return -ENOMEM;
mutex_lock(&core_lock);
/* "above" here means "above or equal to", sigh;
* we need the "equal to" result to force the result
*/
status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
if (status == 0 && id != adap->nr) {
status = -EBUSY;
idr_remove(&i2c_adapter_idr, id);
}
mutex_unlock(&core_lock);
if (status == -EAGAIN)
goto retry;
if (status == 0)
status = i2c_register_adapter(adap);
return status;
}
而i2c_add_adapter函数的区别仅仅在于将adap->nr参数改为__i2c_first_dynamic_bus_num,这个参数怎么来的后面再分析。
接着是i2c_register_adapter函数,只列出重点的语句:
dev_set_name(&adap->dev, "i2c-%d", adap->nr);
adap->dev.bus = &i2c_bus_type;
adap->dev.type = &i2c_adapter_type;
res = device_register(&adap->dev);
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
__i2c_first_dynamic_bus_num又出现了,去看看它是怎么来的吧?
在平台的devices.c文件中一般都有i2c_register_board_info来注册i2c设备:
int __init
i2c_register_board_info(int busnum,
struct i2c_board_info const *info, unsigned len)
{
int status;
down_write(&__i2c_board_lock);
/* dynamic bus numbers will be assigned after the last static one */
if (busnum >= __i2c_first_dynamic_bus_num)
__i2c_first_dynamic_bus_num = busnum + 1;
for (status = 0; len; len--, info++) {
struct i2c_devinfo *devinfo;
devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
if (!devinfo) {
pr_debug("i2c-core: can't register boardinfo!\n");
status = -ENOMEM;
break;
}
devinfo->busnum = busnum;
devinfo->board_info = *info;
list_add_tail(&devinfo->list, &__i2c_board_list);
}
up_write(&__i2c_board_lock);
return status;
}
if (busnum >= __i2c_first_dynamic_bus_num)
__i2c_first_dynamic_bus_num = busnum + 1;
__i2c_first_dynamic_bus_num初始化为0的,从这两句可以看出,__i2c_first_dynamic_bus_num编号是要放在busnum之后的,即如果0、1、2编号都用i2c_register_board_info来注册过的话,__i2c_first_dynamic_bus_num为3。这样就把注册的设备信息挂在了__i2c_board_list链表中。
所以回到i2c core中,调用了i2c_scan_static_board_info函数:
static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
struct i2c_devinfo *devinfo;
down_read(&__i2c_board_lock);
list_for_each_entry(devinfo, &__i2c_board_list, list) {
if (devinfo->busnum == adapter->nr
&& !i2c_new_device(adapter,
&devinfo->board_info))
dev_err(&adapter->dev,
"Can't create device at 0x%02x\n",
devinfo->board_info.addr);
}
up_read(&__i2c_board_lock);
}
遍历前面的链表,找到相应编号的i2c_board_info信息(每个i2c_board_info表示一个设备,同一个编号上可能找到多个i2c_board_info信息),调用i2c_new_device函数,这样,挂在该adapter上的设备就得到了该adapter提供的驱动能力,如中断,读写等逻辑。
可见,如果用i2c_register_board_info来注册i2c设备,属于静态注册,而且必须先于i2c adapter注册,这样i2c adapter注册时候就会为该设备分配好i2c_client结构。否则,是在i2c driver注册过程中才会分配,这个在接下来分析中可以看到。
只列出该函数重点语句:
struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
struct i2c_client *client;
int status;
client = kzalloc(sizeof *client, GFP_KERNEL);
if (!client)
return NULL;
client->adapter = adap;
client->dev.platform_data = info->platform_data;
if (info->archdata)
client->dev.archdata = *info->archdata;
client->flags = info->flags;
client->addr = info->addr;
client->irq = info->irq;
strlcpy(client->name, info->type, sizeof(client->name));
/* Check for address business */
status = i2c_check_addr_busy(adap, client->addr);
if (status)
goto out_err;
client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type;
client->dev.of_node = info->of_node;
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
client->addr);
status = device_register(&client->dev);
i2c_client即为具体设备对应的操作方法集合,可以说是将前面的i2c_board_info结构体信息具体化,i2c核心分别为每个挂载I2C上的具体的硬件创建一个i2c_client,又由于可能多个硬件设备挂载同一个i2c_adapter上,所以可能多个i2c_client指向同一个i2c_adapter;并且同一个cpu上的几个adpter一般都是寄存器地址不同,但是收发数据,产生中断的逻辑等均是相同的,所以可能多个i2c_adapter指向同一个i2c_algorithm。
client创建好后,用device_register注册,这样如果i2c driver已经注册过来,则会调用driver的probe方法。到这里设备和驱动已经匹配上来,可是有可能设备不是用i2c_register_board_info注册的,所以还要继续往下走调用bus_for_each_drv。
所以先概括一下,这里的CPU平台i2c代码中有一个i2c_algorithm;3个i2c_adapter;有多少个i2c接口的硬件,就有多少个i2c_client。
继续分析前面的语句:
client->adapter = adap;
client->addr = info->addr;
client->irq = info->irq;
可以看到client指向了对应的adapter, 并且有了设备的I2C地址和中断号。(注意这个中断号为具体设备的,不是adapter的哦)
strlcpy(client->name, info->type, sizeof(client->name));则是将名字拷贝到client中,后续的i2c driver要根据这个名字找到相应的client。
static int i2c_check_client_addr_validity(const struct i2c_client *client)
{
if (client->flags & I2C_CLIENT_TEN) {
/* 10-bit address, all values are valid */
if (client->addr > 0x3ff)
return -EINVAL;
} else {
/* 7-bit address, reject the general call address */
if (client->addr == 0x00 || client->addr > 0x7f)
return -EINVAL;
}
return 0;
}
否则这里检查失败的。
i2c_check_addr_busy则是遍历同一个adapter下所有的client,看是否有相同地址的i2c设备,如果有,则失败(以前项目中遇到过两个不同型号的摄像头挂载同一个adapter上并且i2c地址是一样的,可以就该这个函数来处理避免,因为项目中同一时刻只需要打开一个摄像头)。
最后device_register就将该client注册到系统中去了。
分析完成i2c_scan_static_board_info后,接着调用 bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter),该函数遍历bus总线上的device_driver,并调用__process_new_adapter - > i2c_do_add_adapter来处理。
为什么要这样做呢?那是因为i2c_drvier注册时候,通过i2c_add_driver -> i2c_register_driver -> driver_register -> bus_add_driver,在该函数中,如果driver_attach成功(即已经有了i2c_board_info信息并且名字一致),那么会继续调用klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers)将信息保存到knode_bus节点中,但是如果i2c设备不是用i2c_register_board_info注册的,则这里匹配失败;所以这里添加完成一个adapter后,用bus_for_each_drv遍历knode_bus节点的klist_drivers,并且用i2c_do_add_adapter来处理,这要求i2c driver必须实现detect等方法才能匹配成功。这个过程我们后续通过一个具体的例子来分析就非常清楚了,所以先继续往下走。
最后就是我们编写的i2c drvier的注册过程了,写驱动的主要工作就是在这里完成的。比如rtc时钟芯片pcf8563的驱动:
static struct i2c_driver pcf8563_driver = {
.driver = {
.name = "rtc-pcf8563",
},
.probe = pcf8563_probe,
.remove = pcf8563_remove,
.id_table = pcf8563_id,
};
static int __init pcf8563_init(void)
{
return i2c_add_driver(&pcf8563_driver);
}
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
if (!client)
return 0;
/* Attempt an OF style match */
if (of_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);
/* match on an id table if there is one */
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL;
return 0;
}
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
const struct i2c_client *client)
{
while (id->name[0]) {
if (strcmp(client->name, id->name) == 0)
return id;
id++;
}
return NULL;
}
从上述的函数可以清楚看到匹配过程。一个i2c_client理论上可以对应多个i2c_driver,表示该设备具有不同的驱动能力。
如果找不到i2c_board_info,也就没办法调用probe方法,说明i2c设备不是静态注册的,那么也没有关系,因为在i2c_register_driver中最后还会调用i2c_for_each_dev(driver, __process_new_driver),这要求驱动中实现detect方法,这样也会创建i2c client,这个过程在后面分析。
这里要注意的是,每个总线都有其匹配规则,这里的i2c总线匹配的是i2c_device_id定义的名字"pcf8563",而并非device_driver中定义的"rtc-pcf8563";
其他的如platform总线匹配的又有不同,如:
static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;
/* Then try to match against the id table */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0);
}
有了上述的分析,可以自己写一个驱动,不用i2c_register_board_info静态注册,而是把所有信息定义在一个文件中。
与通常的i2c驱动区别步骤在于要自己填写i2c_board_info和获得adapter,并且将两者结合在一起而已,仿照静态注册的方法:
static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
struct i2c_devinfo *devinfo;
down_read(&__i2c_board_lock);
list_for_each_entry(devinfo, &__i2c_board_list, list) {
if (devinfo->busnum == adapter->nr
&& !i2c_new_device(adapter,
&devinfo->board_info))
dev_err(&adapter->dev,
"Can't create device at 0x%02x\n",
devinfo->board_info.addr);
}
up_read(&__i2c_board_lock);
}
接着adapter可以用i2c_get_adapter来获得;
有了这两个参数,用i2c_new_device就可以将两者结合在一起,用来创建一个i2c_cilent操作方法集。
这样i2c_driver通过名字匹配,可以获得i2c_client,并且调用自己的probe方法,i2c_client又有了adapter的信息,一个i2c驱动的所需要的操作方法都具备了,就可以读写设备了,详细的步骤如下:
static struct i2c_client *client = NULL;
static int register_iic_client(void)
{
struct i2c_board_info info;
struct i2c_adapter *adapter;
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = PCF8563_I2C_ADDRESS;
strlcpy(info.type, I2C_DEVICE_NAME, I2C_NAME_SIZE);
adapter = i2c_get_adapter(1);
if (!adapter) {
printk("%s : can't get i2c adapter %d\n",__func__,1);
goto err_driver;
}
client = i2c_new_device(adapter, &info);
i2c_put_adapter(adapter);
if (!client) {
printk("%s : can't add i2c device at 0x%x\n",__func__,
(unsigned int)info.addr);
goto err_driver;
}
printk("%s i2c add success! \n",__func__);
return 0;
err_driver:
return -ENODEV;
}
把所有信息写在一个文件的好处是添加一个i2c drvier不需要动到其他文件,不用往devices.c中再添加i2c_board_info信息了,可以直接编译成ko加载即可。
后续有时间再补一个整体流程图。
最后还有一个例子,是用kernel中的模拟i2c总线实现的pcf8563通讯。代码位置在drivers/i2c/busses/i2c-gpio.c中,由于我的平台对gipo的申请操作做了修改,不能用标准的gpio_request等函数,所以只是修改了一下gpio的操作,其他不变。
把它模拟成adapter 4,并且拿出来单独编译成了i2c-gpio.ko和rtc-pcf8563.ko,完整代码如下:
rtc-pcf8563.c
/*
* An I2C driver for the Philips PCF8563 RTC
* Copyright 2005-06 Tower Technologies
*
* Author: Alessandro Zummo
* Maintainers: http://www.nslu2-linux.org/
*
* based on the other drivers in this same directory.
*
* http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include
#include
#include
#include
#include
#include
#include
#define DRV_VERSION "0.4.3"
#define PCF8563_REG_ST1 0x00 /* status */
#define PCF8563_REG_ST2 0x01
#define PCF8563_REG_SC 0x02 /* datetime */
#define PCF8563_REG_MN 0x03
#define PCF8563_REG_HR 0x04
#define PCF8563_REG_DM 0x05
#define PCF8563_REG_DW 0x06
#define PCF8563_REG_MO 0x07
#define PCF8563_REG_YR 0x08
#define PCF8563_REG_AMN 0x09 /* alarm */
#define PCF8563_REG_AHR 0x0A
#define PCF8563_REG_ADM 0x0B
#define PCF8563_REG_ADW 0x0C
#define PCF8563_REG_CLKO 0x0D /* clock out */
#define PCF8563_REG_TMRC 0x0E /* timer control */
#define PCF8563_REG_TMR 0x0F /* timer */
#define PCF8563_SC_LV 0x80 /* low voltage */
#define PCF8563_MO_C 0x80 /* century */
static struct i2c_driver pcf8563_driver;
struct pcf8563 {
struct rtc_device *rtc;
/*
* The meaning of MO_C bit varies by the chip type.
* From PCF8563 datasheet: this bit is toggled when the years
* register overflows from 99 to 00
* 0 indicates the century is 20xx
* 1 indicates the century is 19xx
* From RTC8564 datasheet: this bit indicates change of
* century. When the year digit data overflows from 99 to 00,
* this bit is set. By presetting it to 0 while still in the
* 20th century, it will be set in year 2000, ...
* There seems no reliable way to know how the system use this
* bit. So let's do it heuristically, assuming we are live in
* 1970...2069.
*/
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
};
/*
* In the routines that deal directly with the pcf8563 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
*/
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
{
struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
unsigned char buf[13] = { PCF8563_REG_ST1 };
struct i2c_msg msgs[] = {
{ client->addr, 0, 1, buf }, /* setup read ptr */
{ client->addr, I2C_M_RD, 13, buf }, /* read status + date */
};
/* read registers */
if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
dev_info(&client->dev,
"low voltage detected, date/time is not reliable.\n");
dev_dbg(&client->dev,
"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
__func__,
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7],
buf[8]);
tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
if (tm->tm_year < 70)
tm->tm_year += 100; /* assume we are in 1970...2069 */
/* detect the polarity heuristically. see note above. */
pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
(tm->tm_year >= 100) : (tm->tm_year < 100);
printk("sclu %s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* the clock can give out invalid datetime, but we cannot return
* -EINVAL otherwise hwclock will refuse to set the time on bootup.
*/
if (rtc_valid_tm(tm) < 0)
dev_err(&client->dev, "retrieved date/time is not valid.\n");
return 0;
}
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
int i, err;
unsigned char buf[9];
printk("sclu %s: secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* hours, minutes and seconds */
buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
/* month, 1 - 12 */
buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
/* year and century */
buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
buf[PCF8563_REG_MO] |= PCF8563_MO_C;
buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
/* write register's data */
for (i = 0; i < 7; i++) {
unsigned char data[2] = { PCF8563_REG_SC + i,
buf[PCF8563_REG_SC + i] };
err = i2c_master_send(client, data, sizeof(data));
if (err != sizeof(data)) {
dev_err(&client->dev,
"%s: err=%d addr=%02x, data=%02x\n",
__func__, err, data[0], data[1]);
return -EIO;
}
};
return 0;
}
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return pcf8563_get_datetime(to_i2c_client(dev), tm);
}
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return pcf8563_set_datetime(to_i2c_client(dev), tm);
}
static const struct rtc_class_ops pcf8563_rtc_ops = {
.read_time = pcf8563_rtc_read_time,
.set_time = pcf8563_rtc_set_time,
};
static int pcf8563_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf8563 *pcf8563;
int err = 0;
dev_dbg(&client->dev, "%s\n", __func__);
printk("%s, addr = %x, line = %d\n", __func__, client->addr, client->adapter->nr);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);
if (!pcf8563)
return -ENOMEM;
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
i2c_set_clientdata(client, pcf8563);
pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
&client->dev, &pcf8563_rtc_ops, THIS_MODULE);
if (IS_ERR(pcf8563->rtc)) {
err = PTR_ERR(pcf8563->rtc);
goto exit_kfree;
}
return 0;
exit_kfree:
kfree(pcf8563);
return err;
}
static int pcf8563_remove(struct i2c_client *client)
{
struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
if (pcf8563->rtc)
rtc_device_unregister(pcf8563->rtc);
kfree(pcf8563);
return 0;
}
#define I2C_DEVICE_NAME "pcf8563"
static struct i2c_client *client = NULL;
static int register_iic_client(void)
{
struct i2c_board_info info;
struct i2c_adapter *adapter;
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = 0x51;
strlcpy(info.type, I2C_DEVICE_NAME, I2C_NAME_SIZE);
adapter = i2c_get_adapter(4);
if (!adapter) {
printk("%s : can't get i2c adapter %d\n",__func__,4);
goto err_driver;
}
client = i2c_new_device(adapter, &info);
i2c_put_adapter(adapter);
if (!client) {
printk("%s : can't add i2c device at 0x%x\n",__func__,
(unsigned int)info.addr);
goto err_driver;
}
printk("%s i2c add success! \n",__func__);
return 0;
err_driver:
return -ENODEV;
}
static const struct i2c_device_id pcf8563_id[] = {
{ I2C_DEVICE_NAME, 0 },
{ "rtc8564", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf8563_id);
static struct i2c_driver pcf8563_driver = {
.driver = {
.name = "sun4i-00",
},
.probe = pcf8563_probe,
.remove = pcf8563_remove,
.id_table = pcf8563_id,
};
struct i2c_gpio_platform_data gpio_data = {
// .sda_pin = gpio_sda,
// .scl_pin = gpio_scl,
// .udelay = ,
// .timeout = ,
};
static struct platform_device i2c_gpio_device = {
.name = "i2c-gpio",
.id = 4,//i2c-core会自动分配编号
.dev.platform_data = &gpio_data,
};
static void config_gpio(void)
{
int ret;
user_gpio_set_t gpio_info_sda = {
.port = 2, //PB
.port_num = 19, //PB19
.mul_sel = 1, //
.pull = 1,
.drv_level = 1,
.data = 1,
};
strcpy(gpio_info_sda.gpio_name, "gpio_sda");
user_gpio_set_t gpio_info_scl = {
.port = 2, //PB
.port_num = 18, //PB18
.mul_sel = 1, //
.pull = 1,
.drv_level = 1,
.data = 1,
};
strcpy(gpio_info_scl.gpio_name, "gpio_scl");
ret = gpio_request(&gpio_info_sda, 1);
if(!ret) {
printk("gpio request sda err\n");
} else
gpio_data.sda_pin = ret;
ret = gpio_request(&gpio_info_scl, 1);
if(!ret) {
printk("gpio request scl err\n");
} else
gpio_data.scl_pin = ret;
}
static int __init pcf8563_init(void)
{
int ret;
printk("%s\n",__func__);
config_gpio();
platform_device_register(&i2c_gpio_device);
ret = i2c_add_driver(&pcf8563_driver);
register_iic_client();
return ret;
}
static void __exit pcf8563_exit(void)
{
printk("%s\n",__func__);
if(client != NULL)
i2c_unregister_device(client);
i2c_del_driver(&pcf8563_driver);
platform_device_unregister(&i2c_gpio_device);
}
MODULE_AUTHOR("Alessandro Zummo ");
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
module_init(pcf8563_init);
module_exit(pcf8563_exit);
/*
* Bitbanging I2C bus driver using the GPIO API
*
* Copyright (C) 2007 Atmel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#define gpio_direction_input(hdle, name) set_pin_mul_sel(hdle, name, 0, 0)
#define gpio_direction_output(hdle, name, value) set_pin_mul_sel(hdle, name, 1, value)
#define gpio_set_value(hdle, value) gpio_write_one_pin_value(hdle, value, NULL)
#define gpio_get_value(hdle) gpio_read_one_pin_value(hdle, NULL)
#define gpio_free(hdle) gpio_release(hdle, 1)
void set_pin_mul_sel(unsigned int gpio_hdle, const char * gpio_name, int mul_sel, int value) {
user_gpio_set_t gpio_status;
int ret;
memset(&gpio_status, 0x00, sizeof(gpio_status));
ret = gpio_get_one_pin_status(gpio_hdle, &gpio_status, gpio_name, 1);
if (ret != EGPIO_SUCCESS) {
pr_err("%s, %d\n", __FUNCTION__, __LINE__);
}
gpio_status.mul_sel = mul_sel;
gpio_status.data = value;
ret = gpio_set_one_pin_status(gpio_hdle, &gpio_status, gpio_name, 1);
if (ret != EGPIO_SUCCESS) {
pr_err("%s, gpio change status err, %d\n", __FUNCTION__, ret);
}
}
/* Toggle SDA by changing the direction of the pin */
static void i2c_gpio_setsda_dir(void *data, int state)
{
struct i2c_gpio_platform_data *pdata = data;
if (state)
gpio_direction_input(pdata->sda_pin, "gpio_sda");
else
gpio_direction_output(pdata->sda_pin, "gpio_sda", 0);
}
/*
* Toggle SDA by changing the output value of the pin. This is only
* valid for pins configured as open drain (i.e. setting the value
* high effectively turns off the output driver.)
*/
static void i2c_gpio_setsda_val(void *data, int state)
{
struct i2c_gpio_platform_data *pdata = data;
gpio_set_value(pdata->sda_pin, state);
}
/* Toggle SCL by changing the direction of the pin. */
static void i2c_gpio_setscl_dir(void *data, int state)
{
struct i2c_gpio_platform_data *pdata = data;
if (state)
gpio_direction_input(pdata->scl_pin, "gpio_scl");
else
gpio_direction_output(pdata->scl_pin, "gpio_scl", 0);
}
/*
* Toggle SCL by changing the output value of the pin. This is used
* for pins that are configured as open drain and for output-only
* pins. The latter case will break the i2c protocol, but it will
* often work in practice.
*/
static void i2c_gpio_setscl_val(void *data, int state)
{
struct i2c_gpio_platform_data *pdata = data;
gpio_set_value(pdata->scl_pin, state);
}
static int i2c_gpio_getsda(void *data)
{
struct i2c_gpio_platform_data *pdata = data;
return gpio_get_value(pdata->sda_pin);
}
static int i2c_gpio_getscl(void *data)
{
struct i2c_gpio_platform_data *pdata = data;
return gpio_get_value(pdata->scl_pin);
}
static int __devinit i2c_gpio_probe(struct platform_device *pdev)
{
struct i2c_gpio_platform_data *pdata;
struct i2c_algo_bit_data *bit_data;
struct i2c_adapter *adap;
int ret;
pdata = pdev->dev.platform_data;
if (!pdata)
return -ENXIO;
ret = -ENOMEM;
adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
if (!adap)
goto err_alloc_adap;
bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL);
if (!bit_data)
goto err_alloc_bit_data;
#if 0
ret = gpio_request(pdata->sda_pin, "sda");
if (ret)
goto err_request_sda;
ret = gpio_request(pdata->scl_pin, "scl");
if (ret)
goto err_request_scl;
#endif
if (pdata->sda_is_open_drain) {
gpio_direction_output(pdata->sda_pin, "gpio_sda", 1);
bit_data->setsda = i2c_gpio_setsda_val;
} else {
gpio_direction_input(pdata->sda_pin, "gpio_sda");
bit_data->setsda = i2c_gpio_setsda_dir;
}
if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
gpio_direction_output(pdata->scl_pin, "gpio_scl", 1);
bit_data->setscl = i2c_gpio_setscl_val;
} else {
gpio_direction_input(pdata->scl_pin, "gpio_scl");
bit_data->setscl = i2c_gpio_setscl_dir;
}
if (!pdata->scl_is_output_only)
bit_data->getscl = i2c_gpio_getscl;
bit_data->getsda = i2c_gpio_getsda;
if (pdata->udelay)
bit_data->udelay = pdata->udelay;
else if (pdata->scl_is_output_only)
bit_data->udelay = 50; /* 10 kHz */
else
bit_data->udelay = 5; /* 100 kHz */
if (pdata->timeout)
bit_data->timeout = pdata->timeout;
else
bit_data->timeout = HZ / 10; /* 100 ms */
bit_data->data = pdata;
adap->owner = THIS_MODULE;
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
adap->algo_data = bit_data;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = &pdev->dev;
/*
* If "dev->id" is negative we consider it as zero.
* The reason to do so is to avoid sysfs names that only make
* sense when there are multiple adapters.
*/
adap->nr = (pdev->id != -1) ? pdev->id : 0;
ret = i2c_bit_add_numbered_bus(adap);
if (ret)
goto err_add_bus;
platform_set_drvdata(pdev, adap);
dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
pdata->sda_pin, pdata->scl_pin,
pdata->scl_is_output_only
? ", no clock stretching" : "");
return 0;
err_add_bus:
gpio_free(pdata->scl_pin);
err_request_scl:
gpio_free(pdata->sda_pin);
err_request_sda:
kfree(bit_data);
err_alloc_bit_data:
kfree(adap);
err_alloc_adap:
return ret;
}
static int __devexit i2c_gpio_remove(struct platform_device *pdev)
{
struct i2c_gpio_platform_data *pdata;
struct i2c_adapter *adap;
adap = platform_get_drvdata(pdev);
pdata = pdev->dev.platform_data;
i2c_del_adapter(adap);
gpio_free(pdata->scl_pin);
gpio_free(pdata->sda_pin);
kfree(adap->algo_data);
kfree(adap);
return 0;
}
static struct platform_driver i2c_gpio_driver = {
.driver = {
.name = "i2c-gpio",
.owner = THIS_MODULE,
},
.probe = i2c_gpio_probe,
.remove = __devexit_p(i2c_gpio_remove),
};
static int __init i2c_gpio_init(void)
{
int ret;
ret = platform_driver_register(&i2c_gpio_driver);
if (ret)
printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
return ret;
}
subsys_initcall(i2c_gpio_init);
static void __exit i2c_gpio_exit(void)
{
platform_driver_unregister(&i2c_gpio_driver);
}
module_exit(i2c_gpio_exit);
MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:i2c-gpio");
[ 25.436100] pcf8563_init
[ 25.442576] i2c-gpio i2c-gpio.4: using pins 3874463360 (SDA) and 3874463232 (SCL)
[ 25.451627] pcf8563_probe, addr = 51, line = 4
[ 25.456078] sun4i-00 4-0051: chip found, driver version 0.4.3
[ 25.464178] sun4i-00 4-0051: low voltage detected, date/time is not reliable.
[ 25.471340] sclu pcf8563_get_datetime: tm is secs=44, mins=29, hours=0, mday=14, mon=0, year=90, wday=4
[ 25.482709] using rtc device, sun4i-00, for alarms
[ 25.487364] sun4i-00 4-0051: rtc core: registered sun4i-00 as rtc0
[ 25.493816] register_iic_client i2c add success!
确实是用adapter 4来通讯,也就是模拟的i2c.
最后,解决前面分析i2c_do_add_adapter函数时候留下的一个问题,就是这个函数具体做什么的?
其实这个问题可以通过思考前面的insmod ko的先后顺序来得到答案,我如果硬要先insmod rtc-pcf8563.ko,然后再insmod i2c-gpio.ko,也就是说不管先后顺序都可以挂载得上,那该怎么办?如果能解决这个问题,那前一个问题也就可以解决了。
我们先来看,先insmod rtc-pcf8563.ko带来的问题是i2c_get_adapter(4)这个函数得不到adapter,因为这个adapter是要insmod i2c-gpio.ko才能创建;
而前面分析i2c_do_add_adapter时候说过,每添加一个adapter,都会用bus_for_each_drv来遍历挂在链表中的device_driver;我们既然已经insmod rtc-pcf8563.ko了,那该device_driver就存在了;只不过要符合一定条件才能让adapter和它结合起来。是什么条件呢?我们进入i2c core看源代码最清楚了。
i2c_do_add_adapter函数:
static int i2c_do_add_adapter(struct i2c_driver *driver,
struct i2c_adapter *adap)
{
/* Detect supported devices on that bus, and instantiate them */
i2c_detect(adap, driver);
/* Let legacy drivers scan this bus for matching devices */
if (driver->attach_adapter) {
dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n",
driver->driver.name);
dev_warn(&adap->dev, "Please use another way to instantiate "
"your i2c_client\n");
/* We ignore the return code; if it fails, too bad */
driver->attach_adapter(adap);
}
return 0;
}
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
{
const unsigned short *address_list;
struct i2c_client *temp_client;
int i, err = 0;
int adap_id = i2c_adapter_id(adapter);
address_list = driver->address_list;
if (!driver->detect || !address_list)
return 0;
/* Stop here if the classes do not match */
if (!(adapter->class & driver->class))
return 0;
/* Set up a temporary client to help detect callback */
temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!temp_client)
return -ENOMEM;
temp_client->adapter = adapter;
for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
"addr 0x%02x\n", adap_id, address_list[i]);
temp_client->addr = address_list[i];
err = i2c_detect_address(temp_client, driver);
if (unlikely(err))
break;
}
kfree(temp_client);
return err;
}
首先driver->detect和address_list任何一个没有定义的话,那么返回;并且adapter->class 和driver->class要一致;所以我们要在驱动中定义一个他们:
static struct i2c_driver pcf8563_driver = {
.driver = {
.name = "sun4i-00",
},
.probe = pcf8563_probe,
.remove = pcf8563_remove,
.id_table = pcf8563_id,
.detect = pcf8563_detect,
.address_list = normal_i2c,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
};
接着的for循环中,就是遍历address_list的地址,和他们通讯,看是否成功,所以我们的normal_i2c定义如下:
const unsigned short normal_i2c[2] = {0x51, I2C_CLIENT_END};
static int i2c_detect_address(struct i2c_client *temp_client,
struct i2c_driver *driver)
{
struct i2c_board_info info;
struct i2c_adapter *adapter = temp_client->adapter;
int addr = temp_client->addr;
/* Make sure the address is valid */
err = i2c_check_addr_validity(addr);
/* Skip if already in use */
if (i2c_check_addr_busy(adapter, addr))
return 0;
/* Finally call the custom detection function */
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = addr;
err = driver->detect(temp_client, &info);
/* Consistency check */
if (info.type[0] == '\0') {
} else {
struct i2c_client *client;
/* Detection succeeded, instantiate the device */
client = i2c_new_device(adapter, &info);
if (client)
list_add_tail(&client->detected, &driver->clients);
}
}
static int pcf8563_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
printk("sclu %s, %d\n", __func__, __LINE__);
if(4 == adapter->nr)
{
printk("sclu %s, %d\n", __func__, __LINE__);
strlcpy(info->type, I2C_DEVICE_NAME, I2C_NAME_SIZE);
return 0;
}else{
return -ENODEV;
}
}
[ 27.849589] pcf8563_init
[ 27.854492] sclu pcf8563_detect, 279 //这是 adapter 0的
[ 27.858078] sclu pcf8563_detect, 279 //这是adapter 1的
[ 27.861729] sclu pcf8563_detect, 279 //这是adapter 2的
[ 27.865307] register_iic_client : can't get i2c adapter 4
[ 34.991841] sclu pcf8563_detect, 279 //这是adapter 4的,终于找到了
[ 34.995444] sclu pcf8563_detect, 282
[ 34.999750] pcf8563_probe, addr = 51, line = 4 //i2c_new_device中会用device_register该client dev,所以会调用我们驱动的probe函数
[ 35.004290] sun4i-00 4-0051: chip found, driver version 0.4.3
[ 35.012378] sun4i-00 4-0051: low voltage detected, date/time is not reliable.
[ 35.019513] sclu pcf8563_get_datetime: tm is secs=36, mins=4, hours=2, mday=10, mon=0, year=80, wday=4
[ 35.031141] using rtc device, sun4i-00, for alarms
[ 35.035927] sun4i-00 4-0051: rtc core: registered sun4i-00 as rtc0
[ 35.042376] i2c-gpio i2c-gpio.4: using pins 3873330176 (SDA) and 3873332864 (SCL)
用户空间也可以直接操作I2c,前提是kernel中打开了i2c-dev.c设备,这样,将会出现设备节点/dev/I2c-xx(xx=0, 1, 2 ...);
下面列出常用的一组读和写函数:
unsigned char _i2c_read(unsigned char device_addr, unsigned char sub_addr, unsigned char *buff, int ByteNo) {
struct i2c_rdwr_ioctl_data io_data;
struct i2c_msg msg[2];
unsigned char ret;
buff[0] = sub_addr;
msg[0].flags = !I2C_M_RD;
msg[0].len = 1;
msg[0].buf = &sub_addr;
msg[0].addr = device_addr;
msg[1].flags = I2C_M_RD;
msg[1].len = ByteNo;
msg[1].buf = buff;
msg[1].addr = device_addr;
io_data.nmsgs = 2;
io_data.msgs = msg;
return ioctl(fd, I2C_RDWR, io_data);
}
unsigned char _i2c_write(unsigned char device_addr, unsigned char sub_addr, unsigned char *buff, int ByteNo) {
struct i2c_rdwr_ioctl_data io_data;
struct i2c_msg msg[1];
unsigned char ret;
unsigned char *p_w;
p_w = (unsigned char *)malloc(ByteNo + 1);
p_w[0] = sub_addr;
memcpy(p_w + 1, buff, ByteNo);
msg[0].flags = !I2C_M_RD;
msg[0].len = ByteNo + 1;
msg[0].buf = p_w;
msg[0].addr = device_addr;
io_data.nmsgs = 1;
io_data.msgs = msg;
ret = ioctl(fd, I2C_RDWR, io_data);
free(p_w);
return ret;
}