Linux设备驱动剖析之IIC(一)

写在前面

      由于IIC总线只需要两根线就可以完成读写操作,而且通信协议简单,一条总线上可以挂载多个设备,因此被广泛使用。但是IIC总线有一个缺点,就是传输速率比较低。本文基于Linux-2.6.36版本,说说IIC子系统在Linux中的实现。

     借用某书上的IIC子系统的体系结构图:

                            Linux IIC子系统体系结构

       下面开始分析IIC子系统。

      IIC子系统的初始化在drivers/i2c/i2c-core.c文件中的i2c_init函数中:

00001221 static int __init i2c_init(void)
00001222 {
00001223     int retval;
00001224 
00001225     retval = bus_register(&i2c_bus_type);
00001226     if (retval)
00001227         return retval;
00001228 #ifdef CONFIG_I2C_COMPAT
00001229     i2c_adapter_compat_class = class_compat_register("i2c-adapter");
00001230     if (!i2c_adapter_compat_class) {
00001231         retval = -ENOMEM;
00001232         goto bus_err;
00001233     }
00001234 #endif
00001235     retval = i2c_add_driver(&dummy_driver);
00001236     if (retval)
00001237         goto class_err;
00001238     return 0;
00001239 
00001240 class_err:
00001241 #ifdef CONFIG_I2C_COMPAT
00001242     class_compat_unregister(i2c_adapter_compat_class);
00001243 bus_err:
00001244 #endif
00001245     bus_unregister(&i2c_bus_type);
00001246     return retval;
00001247 }

1225行,向系统注册IIC总线,其中i2c_bus_type的定义为:

00000343 struct bus_type i2c_bus_type = {
00000344     .name        = "i2c",
00000345     .match        = i2c_device_match,
00000346     .probe        = i2c_device_probe,
00000347     .remove        = i2c_device_remove,
00000348     .shutdown    = i2c_device_shutdown,
00000349     .pm        = &i2c_device_pm_ops,
00000350 };

345行,i2c_device_match函数时用来匹配IIC总线上的设备和设备驱动的,下面看下它的定义:

00000068 static int i2c_device_match(struct device *dev, struct device_driver *drv)
00000069 {
00000070     struct i2c_client    *client = i2c_verify_client(dev);
00000071     struct i2c_driver    *driver;
00000072 
00000073     if (!client)
00000074         return 0;
00000075 
00000076     /* Attempt an OF style match */
00000077     if (of_driver_match_device(dev, drv))
00000078         return 1;
00000079 
00000080     driver = to_i2c_driver(drv);
00000081     /* match on an id table if there is one */
00000082     if (driver->id_table)
00000083         return i2c_match_id(driver->id_table, client) != NULL;
00000084 
00000085     return 0;
00000086 }

在IIC子系统中,用struct i2c_client来描述一个具体的IIC设备(IIC从机)。73行,如果没有IIC设备的话就直接返回0,表示匹配不成功。

77行,用of的方式进行匹配,应该是设备树方面的,具体没了解过。

82行,如果驱动的id table存在则调用83行的i2c_match_id函数进行匹配:

00000057 static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
00000058                         const struct i2c_client *client)
00000059 {
00000060     while (id->name[0]) {
00000061         if (strcmp(client->name, id->name) == 0)
00000062             return id;
00000063         id++;
00000064     }
00000065     return NULL;
00000066 }

很简单,就是拿驱动的id table中的每一项与i2c_client的name成员进行比较,如果它们的名字相同就表示匹配成功,否则匹配失败,返回NULL。从这里也可以看出IIC的总线匹配方式与platform总线的匹配方式是不一样,一般情况下,IIC总线的匹配方式是根据设备名字和驱动中的id table,而platfrom总线的匹配方式是根据设备名字和驱动名字。下面看i2c_device_probe函数:

00000106 static int i2c_device_probe(struct device *dev)
00000107 {
00000108     struct i2c_client    *client = i2c_verify_client(dev);
00000109     struct i2c_driver    *driver;
00000110     int status;
00000111 
00000112     if (!client)
00000113         return 0;
00000114 
00000115     driver = to_i2c_driver(dev->driver);
00000116     if (!driver->probe || !driver->id_table)
00000117         return -ENODEV;
00000118     client->driver = driver;
00000119     if (!device_can_wakeup(&client->dev))
00000120         device_init_wakeup(&client->dev,
00000121                     client->flags & I2C_CLIENT_WAKE);
00000122     dev_dbg(dev, "probe\n");
00000123 
00000124     status = driver->probe(client, i2c_match_id(driver->id_table, client));
00000125     if (status) {
00000126         client->driver = NULL;
00000127         i2c_set_clientdata(client, NULL);
00000128     }
00000129     return status;
00000130 }

112行,检查IIC设备是否存在。

119至121行,电源管理方面的,IIC在电源管理方面做得还是不错的,有兴趣可以看一下。

124行,重要,调用IIC设备驱动中probe函数。

     下面以tiny6410为具体平台去说IIC子系统的其他内容。S3c6410的IIC控制器驱动位于drivers/i2c/busses/i2c-s3c2410.c文件中,首先看初始化函数:

00001009 static struct platform_driver s3c24xx_i2c_driver = {
00001010     .probe        = s3c24xx_i2c_probe,
00001011     .remove        = s3c24xx_i2c_remove,
00001012     .id_table    = s3c24xx_driver_ids,
00001013     .driver        = {
00001014         .owner    = THIS_MODULE,
00001015         .name    = "s3c-i2c",
00001016         .pm    = S3C24XX_DEV_PM_OPS,
00001017     },
00001018 };
00001019 
00001020 static int __init i2c_adap_s3c_init(void)
00001021 {
00001022     return platform_driver_register(&s3c24xx_i2c_driver);
00001023 }
00001024 subsys_initcall(i2c_adap_s3c_init);

1022行,注册平台驱动,看下s3c24xx_i2c_driver的定义可以发现.driver.name的值与板文件中定义的platform device的name不一样,所以这里采用的是id table方式进行匹配。我们知道,当此驱动与设备匹配后,驱动中的probe函数将会被调用,那么下面看probe函数的定义:

00000790 static int s3c24xx_i2c_probe(struct platform_device *pdev)
00000791 {
00000792     struct s3c24xx_i2c *i2c;
00000793     struct s3c2410_platform_i2c *pdata;
00000794     struct resource *res;
00000795     int ret;
00000796 
00000797     pdata = pdev->dev.platform_data;
00000798     if (!pdata) {
00000799         dev_err(&pdev->dev, "no platform data\n");
00000800         return -EINVAL;
00000801     }
00000802 
00000803     i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
00000804     if (!i2c) {
00000805         dev_err(&pdev->dev, "no memory for state\n");
00000806         return -ENOMEM;
00000807     }
00000808 
00000809     strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
00000810     i2c->adap.owner   = THIS_MODULE;
00000811     i2c->adap.algo    = &s3c24xx_i2c_algorithm;
00000812     i2c->adap.retries = 2;
00000813     i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD;
00000814     i2c->tx_setup     = 50;
00000815 
00000816     spin_lock_init(&i2c->lock);
00000817     init_waitqueue_head(&i2c->wait);
00000818 
00000819     /* find the clock and enable it */
00000820 
00000821     i2c->dev = &pdev->dev;
00000822     i2c->clk = clk_get(&pdev->dev, "i2c");
00000823     if (IS_ERR(i2c->clk)) {
00000824         dev_err(&pdev->dev, "cannot get clock\n");
00000825         ret = -ENOENT;
00000826         goto err_noclk;
00000827     }
00000828 
00000829     dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
00000830 
00000831     clk_enable(i2c->clk);
00000832 
00000833     /* map the registers */
00000834 
00000835     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
00000836     if (res == NULL) {
00000837         dev_err(&pdev->dev, "cannot find IO resource\n");
00000838         ret = -ENOENT;
00000839         goto err_clk;
00000840     }
00000841 
00000842     i2c->ioarea = request_mem_region(res->start, resource_size(res),
00000843                      pdev->name);
00000844 
00000845     if (i2c->ioarea == NULL) {
00000846         dev_err(&pdev->dev, "cannot request IO\n");
00000847         ret = -ENXIO;
00000848         goto err_clk;
00000849     }
00000850 
00000851     i2c->regs = ioremap(res->start, resource_size(res));
00000852 
00000853     if (i2c->regs == NULL) {
00000854         dev_err(&pdev->dev, "cannot map IO\n");
00000855         ret = -ENXIO;
00000856         goto err_ioarea;
00000857     }
00000858 
00000859     dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
00000860         i2c->regs, i2c->ioarea, res);
00000861 
00000862     /* setup info block for the i2c core */
00000863 
00000864     i2c->adap.algo_data = i2c;
00000865     i2c->adap.dev.parent = &pdev->dev;
00000866 
00000867     /* initialise the i2c controller */
00000868 
00000869     ret = s3c24xx_i2c_init(i2c);
00000870     if (ret != 0)
00000871         goto err_iomap;
00000872 
00000873     /* find the IRQ for this unit (note, this relies on the init call to
00000874      * ensure no current IRQs pending
00000875      */
00000876 
00000877     i2c->irq = ret = platform_get_irq(pdev, 0);
00000878     if (ret <= 0) {
00000879         dev_err(&pdev->dev, "cannot find IRQ\n");
00000880         goto err_iomap;
00000881     }
00000882 
00000883     ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
00000884               dev_name(&pdev->dev), i2c);
00000885 
00000886     if (ret != 0) {
00000887         dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
00000888         goto err_iomap;
00000889     }
00000890 
00000891     ret = s3c24xx_i2c_register_cpufreq(i2c);
00000892     if (ret < 0) {
00000893         dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
00000894         goto err_irq;
00000895     }
00000896 
00000897     /* Note, previous versions of the driver used i2c_add_adapter()
00000898      * to add the bus at any number. We now pass the bus number via
00000899      * the platform data, so if unset it will now default to always
00000900      * being bus 0.
00000901      */
00000902 
00000903     i2c->adap.nr = pdata->bus_num;
00000904 
00000905     ret = i2c_add_numbered_adapter(&i2c->adap);
00000906     if (ret < 0) {
00000907         dev_err(&pdev->dev, "failed to add bus to i2c core\n");
00000908         goto err_cpufreq;
00000909     }
00000910 
00000911     platform_set_drvdata(pdev, i2c);
00000912 
00000913     dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
00000914     return 0;
00000915 
00000916  err_cpufreq:
00000917     s3c24xx_i2c_deregister_cpufreq(i2c);
00000918 
00000919  err_irq:
00000920     free_irq(i2c->irq, i2c);
00000921 
00000922  err_iomap:
00000923     iounmap(i2c->regs);
00000924 
00000925  err_ioarea:
00000926     release_resource(i2c->ioarea);
00000927     kfree(i2c->ioarea);
00000928 
00000929  err_clk:
00000930     clk_disable(i2c->clk);
00000931     clk_put(i2c->clk);
00000932 
00000933  err_noclk:
00000934     kfree(i2c);
00000935     return ret;
00000936 }

797至801行,没有平台数据是不行的。

803至807行,为具体平台的IIC控制器数据结构申请内存,一般来说,不仅是IIC控制器,每一个控制器都会有一个结构体来描述。struct s3c24xx_i2c的定义也是在drivers/i2c/busses/i2c-s3c2410.c中:

00000060 struct s3c24xx_i2c {
00000061     spinlock_t        lock;
00000062     wait_queue_head_t    wait;
00000063     unsigned int        suspended:1;
00000064 
00000065     struct i2c_msg        *msg;
00000066     unsigned int        msg_num;
00000067     unsigned int        msg_idx;
00000068     unsigned int        msg_ptr;
00000069 
00000070     unsigned int        tx_setup;
00000071     unsigned int        irq;
00000072 
00000073     enum s3c24xx_i2c_state    state;
00000074     unsigned long        clkrate;
00000075 
00000076     void __iomem        *regs;
00000077     struct clk        *clk;
00000078     struct device        *dev;
00000079     struct resource        *ioarea;
00000080     struct i2c_adapter    adap;
00000081 
00000082 #ifdef CONFIG_CPU_FREQ
00000083     struct notifier_block    freq_transition;
00000084 #endif
00000085 };

63行,表示IIC控制器是否已经挂起,挂起的话就不能操作IIC控制器了。

65行,struct i2c_msg用来描述一次读写操作包含的信息。定义在include/linux/i2c.h,比较简单:

00000507 struct i2c_msg {
00000508     __u16 addr;    /* slave address            */
00000509     __u16 flags;
00000510 #define I2C_M_TEN        0x0010    /* this is a ten bit chip address */
00000511 #define I2C_M_RD        0x0001    /* read data, from slave to master */
00000512 #define I2C_M_NOSTART        0x4000    /* if I2C_FUNC_PROTOCOL_MANGLING */
00000513 #define I2C_M_REV_DIR_ADDR    0x2000    /* if I2C_FUNC_PROTOCOL_MANGLING */
00000514 #define I2C_M_IGNORE_NAK    0x1000    /* if I2C_FUNC_PROTOCOL_MANGLING */
00000515 #define I2C_M_NO_RD_ACK        0x0800    /* if I2C_FUNC_PROTOCOL_MANGLING */
00000516 #define I2C_M_RECV_LEN        0x0400    /* length will be first received byte */
00000517     __u16 len;        /* msg length                */
00000518     __u8 *buf;        /* pointer to msg data            */
00000519 };

508行,IIC从机的地址。

509行,flags的取值就是510至516行这些值。

517行,这次读写操作的数据长度。518行,读写数据的地址。

      回到struct s3c24xx_i2c,66行,message的数量。67行,当前是第几个message。68行,缓冲区数组成员的索引值,表示当前要读写的是第几个数据。

70行,当数据写入IIC控制器的数据移位寄存器后需要延时多久,在s3c6410里的单位是ns。

71行,IIC控制器使用的中断号。

73行,IIC控制器的状态,具体来说有以下几种状态:

00000047 enum s3c24xx_i2c_state {
00000048     STATE_IDLE,
00000049     STATE_START,
00000050     STATE_READ,
00000051     STATE_WRITE,
00000052     STATE_STOP
00000053 };

74行,IIC总线的速率。76行,IIC控制器寄存器起始地址。

77行,IIC控制器时钟。78行,设备模型相关的。79行,IO口资源。

80行,每一个IIC控制器对应一个adapter。struct i2c_adapter同样是在include/linux/i2c.h中定义:

00000354 struct i2c_adapter {
00000355     struct module *owner;
00000356     unsigned int id;
00000357     unsigned int class;          /* classes to allow probing for */
00000358     const struct i2c_algorithm *algo; /* the algorithm to access the bus */
00000359     void *algo_data;
00000360 
00000361     /* data fields that are valid for all devices    */
00000362     struct rt_mutex bus_lock;
00000363 
00000364     int timeout;            /* in jiffies */
00000365     int retries;
00000366     struct device dev;        /* the adapter device */
00000367 
00000368     int nr;
00000369     char name[48];
00000370     struct completion dev_released;
00000371 
00000372     struct mutex userspace_clients_lock;
00000373     struct list_head userspace_clients;
00000374 };

355行,模块的所有者。

356行,此适配器的编号,第1个适配器的编号为0,以此类推。

358行,算法?第一眼看到的时候差点被吓倒了,其实就是定义了3个函数指针,这些函数来完成具体的读写操作。

364行,超时时间。365行,重试次数,一次读写操作不成功的话就多试几次。368行,适配器编号。369行,适配器的名字。

     回到s3c24xx_i2c_probe函数,809行,设置适配器的名字。

811行,s3c6410的IIC控制器进行读写操作时所使用的逻辑,等碰到时再详细说吧。

813行,刚才在说struct i2c_adapter时被忽略的成员class就是在这里被赋值的。

814行,对于s3c6410的IIC控制器而言,数据被写入移位寄存器后需要延时50ns。

822至831行,获取IIC时钟并使能。

835至857行,获取IO口资源并进行映射。

869行,设置相应的IO口为IIC功能,并设置IICADD寄存器和IICCON寄存器。

877至889行,申请IIC中断,中断处理函数为s3c24xx_i2c_irq,后面会遇到,到时再说。

891至895行,CPU频率相关的,略过吧。

905行,“重头戏”啊,注册IIC适配器和注册IIC设备等都发生在里面,i2c_add_numbered_adapter函数在drivers/i2c/i2c-core.c里定义:

00000948 int i2c_add_numbered_adapter(struct i2c_adapter *adap)
00000949 {
00000950     int    id;
00000951     int    status;
00000952 
00000953     if (adap->nr & ~MAX_ID_MASK)
00000954         return -EINVAL;
00000955 
00000956 retry:
00000957     if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
00000958         return -ENOMEM;
00000959 
00000960     mutex_lock(&core_lock);
00000961     /* "above" here means "above or equal to", sigh;
00000962      * we need the "equal to" result to force the result
00000963      */
00000964     status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
00000965     if (status == 0 && id != adap->nr) {
00000966         status = -EBUSY;
00000967         idr_remove(&i2c_adapter_idr, id);
00000968     }
00000969     mutex_unlock(&core_lock);
00000970     if (status == -EAGAIN)
00000971         goto retry;
00000972 
00000973     if (status == 0)
00000974         status = i2c_register_adapter(adap);
00000975     return status;
00000976 }

 

posted @ 2013-08-17 20:37  lknlfy  阅读(4455)  评论(1编辑  收藏  举报