编写i2c设备驱动(从设备)一般有两种方式:

1.用户自己编写独立的从设备驱动,应用程序直接使用即可。

2.linux内核内部已经实现了一个通用的设备驱动,利用通用设备驱动编写一个应用程序(用户态驱动),在应用程序中用到大量设备驱动提供的接口,通过应用程序来控制从设备。

总线驱动

4.1 概述

I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力,比如起始,停止,应答信号和master_xfer的实现函数。

I2C总线驱动由i2c_adapter和i2c_algorithm来描述

4.2 S3c2440I2C控制器的硬件描述

S3c2440处理器内部集成了一个I2C控制器,通过四个寄存器来进行控制:

IICCON     I2C控制寄存器

IICSTAT     I2C状态寄存器

IICDS       I2C收发数据移位寄存器

IICADD     I2C地址寄存器

通过IICCON,IICDS,IICADD寄存器操作,可在I2C总线上产生开始位、停止位、数据和地址,而传输的状态则通过IICSTAT寄存器来获取。

4.3 i2c-s3c2410总线驱动分析(platform_driver)

I2C总线驱动代码在drivers/i2c/busses/i2c-s3c2410.c,这个代码同样支持s3c2410,s3c6410,s5pc110等Samsung 系列的芯片。

初始化模块和卸载模块

  1. static int __init i2c_adap_s3c_init(void)
  2. {
  3. returnplatform_driver_register(&s3c24xx_i2c_driver);
  4. }
  5. static void __exit i2c_adap_s3c_exit(void)
  6. {
  7. platform_driver_unregister(&s3c24xx_i2c_driver);
  8. }

总线驱动是基于platform来实现的,很符合设备驱动模型的思想。

  1. static struct platform_drivers3c24xx_i2c_driver = {
  2. .probe                = s3c24xx_i2c_probe,
  3. .remove            = s3c24xx_i2c_remove,
  4. .id_table  = s3c24xx_driver_ids,
  5. .driver                = {
  6. .owner     = THIS_MODULE,
  7. .name       = "s3c-i2c",
  8. .pm  = S3C24XX_DEV_PM_OPS,
  9. .of_match_table= s3c24xx_i2c_match,
  10. },
  11. };

s3c24xx_i2c_probe函数

当调用platform_driver_register函数注册platform_driver结构体时,如果platformdevice 和 platform driver匹配成功后,会调用probe函数,来初始化适配器硬件。

  1. static int s3c24xx_i2c_probe(structplatform_device *pdev)
  2. {
  3. ……
  4. /*初始化适配器信息 */
  5. strlcpy(i2c->adap.name,"s3c2410-i2c", sizeof(i2c->adap.name));
  6. i2c->adap.owner   = THIS_MODULE;
  7. i2c->adap.algo    = &s3c24xx_i2c_algorithm;
  8. i2c->adap.retries= 2;
  9. i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD;
  10. i2c->tx_setup     = 50;
  11. /*初始化自旋锁和等待队列头 */
  12. spin_lock_init(&i2c->lock);
  13. init_waitqueue_head(&i2c->wait);
  14. /*映射寄存器 */
  15. res= platform_get_resource(pdev, IORESOURCE_MEM, 0);
  16. i2c->ioarea= request_mem_region(res->start, resource_size(res),
  17. pdev->name);
  18. i2c->regs= ioremap(res->start, resource_size(res));
  19. /*设置I2C核心需要的信息 */
  20. i2c->adap.algo_data= i2c;
  21. i2c->adap.dev.parent= &pdev->dev;
  22. /*初始化I2C控制器 */
  23. ret= s3c24xx_i2c_init(i2c);
  24. /*申请中断 */
  25. i2c->irq= ret = platform_get_irq(pdev, 0);
  26. ret= request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
  27. dev_name(&pdev->dev), i2c);
  28. /* 注册I2C适配器 */
  29. ret= i2c_add_numbered_adapter(&i2c->adap);
  30. ……
  31. }

Probe主要工作是时能硬件并申请I2C适配器使用的IO地址,中断号等,然后向I2C核心添加这个适配器。I2c_adapter注册过程i2c_add_numbered_adapter->i2c_register_adapter

I2C总线通信方法

  1. static const struct i2c_algorithms3c24xx_i2c_algorithm = {
  2. .master_xfer             = s3c24xx_i2c_xfer,
  3. .functionality             = s3c24xx_i2c_func,
  4. };

s3c24xx_i2c_xfer函数是总线通信方式的具体实现,依赖于s3c24xx_i2c_doxfer和s3c24xx_i2c_message_start两个函数;

  1. static int s3c24xx_i2c_doxfer(structs3c24xx_i2c *i2c,
  2. struct i2c_msg *msgs, int num)
  3. {
  4. ret =s3c24xx_i2c_set_master(i2c);
  5. i2c->msg     = msgs;
  6. i2c->msg_num= num;
  7. i2c->msg_ptr= 0;
  8. i2c->msg_idx= 0;
  9. i2c->state   = STATE_START;
  10. s3c24xx_i2c_message_start(i2c,msgs);
  11. }

首先设置s3c I2C设备器为主设备,然后调用s3c24xx_i2c_message_start函数启动I2C消息传输。

s3c24xx_i2c_func函数返回适配器所支持的通信功能。

4.4 适配器的设备资源(platform_device)

S3c2440的I2C总线驱动是基于platform来实现,前面我们分析了platformdriver部分,再来看下platform device部分。

在arch/arm/plat-samsung/dev-i2c0.c文件中定义了platform_device结构体以及I2C控制器的资源信息:

  1. static struct resource s3c_i2c_resource[] ={
  2. [0]= {
  3. .start= S3C_PA_IIC,
  4. .end   = S3C_PA_IIC + SZ_4K - 1,
  5. .flags= IORESOURCE_MEM,
  6. },
  7. [1]= {
  8. .start= IRQ_IIC,
  9. .end  = IRQ_IIC,
  10. .flags= IORESOURCE_IRQ,
  11. },
  12. };
  13. struct platform_device s3c_device_i2c0 = {
  14. .name                 = "s3c2410-i2c",   /* 设备名 */
  15. #ifdef CONFIG_S3C_DEV_I2C1
  16. .id               = 0,
  17. #else
  18. .id               = -1,
  19. #endif
  20. .num_resources         =ARRAY_SIZE(s3c_i2c_resource),
  21. .resource   =s3c_i2c_resource,
  22. };
  23. struct s3c2410_platform_i2cdefault_i2c_data __initdata = {
  24. .flags                  = 0,
  25. .slave_addr      = 0x10,  /* I2C适配器的地址 */
  26. .frequency        = 100*1000,  /* 总线频率 */
  27. .sda_delay        = 100,   /* SDA边沿延迟时间ns */
  28. };
  29. void __init s3c_i2c0_set_platdata(structs3c2410_platform_i2c *pd)
  30. {
  31. structs3c2410_platform_i2c *npd;
  32. if(!pd)
  33. pd= &default_i2c_data;
  34. npd= s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
  35. &s3c_device_i2c0);
  36. if(!npd->cfg_gpio)
  37. npd->cfg_gpio= s3c_i2c0_cfg_gpio;
  38. }

在板文件中把platform_device注册进内核:

  1. static struct platform_device*mini2440_devices[] __initdata = {
  2. ……
  3. &s3c_device_i2c0,
  4. ……
  5. };

调用s3c_i2c0_set_platdata 函数把适配器具体的数据赋值给dev.platform_data:

  1. static void __init mini2440_init(void)
  2. {
  3. ……
  4. s3c_i2c0_set_platdata(NULL);
  5. }

I2C总线驱动就分析到这里。

linux之i2c子系统架构---总线驱动的更多相关文章

  1. 嵌入式Linux内核I2C子系统详解

    1.1 I2C总线知识 1.1.1  I2C总线物理拓扑结构     I2C总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成.通信原理是通过对SCL和SDA线高 ...

  2. Linux下smi/mdio总线驱动

    Linux下smi/mdio总线驱动 韩大卫@吉林师范大学 MII(媒体独立接口), 是IEEE802.3定义的以太网行业标准接口, smi是mii中的标准管理接口, 有两跟管脚, mdio 和mdc ...

  3. linux内核I2C子系统学习(三)

    写设备驱动: 四部曲: 构建i2c_driver 注册i2c_driver 构建i2c_client ( 第一种方法:注册字符设备驱动.第二种方法:通过板文件的i2c_board_info填充,然后注 ...

  4. linux之i2c子系统维护者源码仓库地址

    仓库地址: git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git

  5. Linux驱动编程--基于I2C子系统的I2C驱动

    代码中,我添加了很多注释,应该不难理解,有错误大家可以指出来,我再改正 #include <linux/kernel.h> #include <linux/module.h> ...

  6. linux input输入子系统应用分析

    输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理是底层在按键.触摸等动作发送时产生一个中断(或驱动通过timer定时查询),然后CPU通过SPI.I2 C或外部存储器总线读取 ...

  7. LinuxI2C核心、总线驱动与设备驱动

    I2C体系结构分为三个部分:I2C核心.总线驱动.设备驱动 I2C核心: I2C核心提供了一组不依赖硬件的接口函数,I2C总线驱动和设备驱动之间依赖于I2C核心作为纽带 (1)增加/删除i2c_ada ...

  8. 【驱动】linux下I2C驱动架构全面分析

    I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线. ...

  9. linux下I2C驱动架构全面分析【转】

    本文转载自:http://blog.csdn.net/wangpengqi/article/details/17711165 I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一 ...

随机推荐

  1. X60的BIOS白名单-黑苹果之路

    一时兴起装起了黑苹果,用了最古老的thinkpad X60.装完了才发现无线网卡是硬伤,无法驱动,只有淘了个博通的无线网卡,但商家告诉我需要搞定白名单. 于是在商家的帮助下折腾半天,终于搞定. 1.在 ...

  2. (Loadrunner)Abnormal termination, caused by mdrv process termination.(转)

    Load generator跑了太多用户导致CPU和内存爆满,进程无法处理请求 确认自定义的代码是否释放内存 合理调整或增加思考时间 关闭extended log 尽量避免使用Load generat ...

  3. 软件测试入门——测试模型(V型 W型 H型)

    软件测试工程师称为“QA”,质量保证者——这是入门的第一点要学习的. 首先看基本的测试模型 1.“V”型 特点:[活动串行]这是一种古老的瀑布模型,反映了实际和测试之间的关系. 局限:仅仅把测试过程作 ...

  4. 用github pages展示你的静态网页,多项目支持

    我看到有分享用github pages来做博客的,不过我并不想挂博客在上面,我只是想将我的一些作品挂上去,然后链接到我的简历里,这样HR可以直接看到. 首先是最基本的操作,在github上创建一个新的 ...

  5. Oracle 存储过程包

    create or replace package body cuttoship_lots is procedure prod_run(p_w_day date) as begin delete cu ...

  6. mongodb分组,的两种方式,先记一下

    using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.Builders; using NationalUnion.AdGalle ...

  7. Digest [information value filtering]

    http://oak.cs.ucla.edu/~cho/papers/cho-filter.pdf 最近对评估方法进行研究,这篇paper是一种对IR方法进行总结,不错的角度,也比较全面

  8. Ov

  9. 【Linux】基于Bind_DLZ和MySQL数据的DNS搭建

    参考:http://www.linuxfromscratch.org/blfs/view/cvs/server/bind.html 参考:http://bind-dlz.sourceforge.net ...

  10. java jdbc 封装。。

    JDBC工具类...package it.cast.jdbcutils; import java.io.InputStream; import java.sql.Connection; import ...