当前位置: 首页 > 工具软件 > NSLU2 Linux > 使用案例 >

linux I2C驱动分析整理

帅煌
2023-12-01

最近用到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的资源,另外两个类似。接着就是用platform_add_devices函数注册平台资源,这个函数就不列出来。


有了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,
    },   
};

名字“sun4i-i2c”和前面的 adapter资源名字是一样的,而且前面有3个adapter,所以会调用3次i2c_sunxi_probe函数来注册3个adapter。在probe函数中重点语句:

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

bus_num分别为0, 1, 2;i2c_sunxi_algorithm即为该芯片i2c通讯的核心算法,所有发送、接收数据都是在该结构的函数中处理,也就是操作I2C的硬件寄存器、FIFO等来发送接收数据,这属于最底层的硬件操作。

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

这里i2c_sunxi_functionality就表示这3个adatper支持的i2c通讯类型。后续i2c drvier中用到的i2c_check_functionality来检查adapter是否支持某个i2c协议的传输,最终就是调用这里的函数。

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

从具体函数分析就可以很容易理解上述所说的。idr_pre_get函数是预分配内存空间,防止内存不足出现问题;idr_get_new_above,将adapter插入到一个能高效搜索的树上,函数前面的说明也很清楚,传进去一个adap->nr,得到的id可能等于或者大于adap->nr,只要之前没有插入过该编号的adapter,就会返回等于adap->nr的id, 所以后续判断如果不等于的话就失败了。

而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);

这里bus和type均为i2c 核心自己定义的,后续i2c 驱动会用到。

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

第一个参数busnum就是该设备注册到那一个i2c adapter中,也就是前面的编号0、1、2中的一个。

    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地址范围是否合法,这个就要看具体的硬件设备了,如果硬件支持10位地址,一定要在i2c_board_info结构体中赋值.flag = I2C_CLIENT_TEN;

否则这里检查失败的。

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

其注册过程就是用i2c_add_driver注册i2c驱动,寻找对应的i2c_board_info结构过程,最终匹配规则是和pcf8563_id中定义的名字和i2c_board_info所定义的一致,调用的方法是i2c_bus_type中的i2c_device_match函数:

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

它也有一个platform_device_id,但是如果platform_device_id没有定义,还可以匹配platform_device的名字和device_drvier的名字,而一般的platform驱动中都是用后者来写。


有了上述的分析,可以自己写一个驱动,不用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);
}

先定义struct i2c_board_info info,并且给它赋值地址和名字即可,注意名字要和i2c_device_id一致;

接着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 <a.zummo@towertech.it>
 * 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 <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/i2c-gpio.h>
#include <mach/sys_config.h>
#include <linux/platform_device.h>

#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 <a.zummo@towertech.it>");
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);

module_init(pcf8563_init);
module_exit(pcf8563_exit);

i2c-gpio.c:

/*
 * 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 <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <mach/sys_config.h>

//#include <asm/gpio.h>

#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");

编译好后,先insmod i2c-gpio.ko,然后是rtc-pcf8563.ko,否则找不到adapter 4,可以看到正确的log信息:

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

调用i2c_detect函数:

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


接着看for循环中的i2c_detect_address函数,只列出重点语句:

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

例行检查地址合法和是否重复,然后调用detect, 如果type不为0,就创建一个i2c_new_device啦,看到这是不是很高兴,所以我们的detect函数中要为info赋值;还有由于所有的adapter( 不止是4,还有0、1、2)添加进来的时候都会调用bus_for_each_drv来遍历;所以detect函数中还要判断如果编号是我们希望的话才给info赋值。所以detect函数可以写成如下:

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

这样,编译好两个ko后,不管insmod那一个先,都能得到正确的时间啦,log如下:

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












 类似资料: