zz-linux-i2c驱动分析am335x框架调用150103d

//zz//#######################################################################

zz-linux-i2c驱动分析am335x框架调用150103d.txt
    框架,调用流程

zz-Write:
    @2015-1-2 23:19:50
    @2015-1-3 10:38:54
    @2015-1-4 00:12:33
    @2015-1-4 00:26:50
    @

REF:
    ti-sdk-am335x-evm-06.00.00.00-Linux-x86-Install.bin
    linux-3.2.0-psp04.06ti-zz150103a.zip
    
    linux下I2C驱动架构全面分析
    http://blog.csdn.net/wangpengqi/article/details/17711165
     
    i2c--2.6.34文档:如何枚举产生i2c_client
    http://blog.csdn.net/yuanlulu/article/details/6557901
    
    linux I2C 驱动之----i2c_client 的注册
    http://blog.csdn.net/tanxjian/article/details/7479444

KeyWord:

    // i2c 设备接口层,供上层应用读写
    app => i2c_client i2c_driver-> read/write/ioctl => i2c-core
        // i2c 总线接口层,通过linux架构操作硬件
        => i2c_adapter i2c_algorithm
        => hardware adapter[i] 芯片i2c接口寄存器组 ==> i2c slave devices 外设


    四个重要的 i2c 结构体类型
    i2c_driver i2c_client i2c_adapter i2c_algorithm
    
    linux内核 i2c 相关驱动源码位置
    drivers/i2c/
        i2c-dev.c
            i2c_dev_init() => i2cdev_fops linux设备文件通过此 => 调用 i2c-core => i2c架构 ??
        i2c-core.c
            与具体芯片平台无关的函数,linux-i2c驱动框架常用函数          
        algos/
        busses/
            i2c-s3c2410.c 平台mini2440相关的 platform_driver
            i2c-omap.c 平台am335x相关 platform_driver
        chips/
            i2c_driver 由外设决定缺省放这里,实际是在 drivers/misc/eeprom/at24.c
    
    arch/arm/mach-omap2/board-am335xevm.c
        i2c_board_info am335x_i2c1_boardinfo[] (for i2c_client)
    arch/arm/plat-omap/i2c.c
        platform_device omap_i2c_devices[] (for i2c platform_device)


    arch/arm/mach-s3c2440/mach-mini2440.c
        platform_device s3c_device_i2c0 (for i2c platform_device)


//zz//#######################################################################
1.
i2c 从应用层到外部设备的操作顺序.
应用程序读写 i2c (外设相关的)设备文件
内核提供一套接口,向下操作寄存器完成和外设的通信,发送/接收数据


    // i2c 设备接口层,供上层应用读写
    app => i2c_client i2c_driver-> read/write/ioctl => i2c-core
        // i2c 总线接口层,通过linux架构操作硬件
        => i2c_adapter i2c_algorithm
        => hardware adapter[i] 芯片i2c接口寄存器组 ==> i2c slave devices 外设


        
//zz//#######################################################################
2.
四个重要的 i2c 结构体类型


注意与 platform_ 平台设备(大部分设备的入口点,i2c也是)不是一个东西:
对于 am335x i2c 使用平台设备的方式来注册到内核的,这是 am335x i2c 驱动的开始点


平台设备的驱动:
drivers/i2c/busses/i2c-omap.c
platform_driver omap_i2c_driver
    .driver.name = "omap_i2c"
    .id_table 没设置


平台设备的设备:
arch/arm/plat-omap/i2c.c
platform_device omap_i2c_devices[]
    char name[] = "omap_i2c";


1)
i2c_driver
外设相关的驱动
    struct list_head clients; //结构体内有存放支持的 i2c_client 外设的链表


例如 rtc-ds1307 芯片用的i2c接口,
drivers/rtc/rtc-ds1307.c


例如 at24(系列)的i2c接口外部设备分析如下
drivers/misc/eeprom/at24.c
i2c_driver at24_driver
{
    .probe = at24_probe //探针函数
    .driver
        .name = "at24"
    .id_tble = {"",..}  //支持的外设设备的 .name 表
    
    .attach_adapter =   //为空则 __attach_adapter() 时候不调用
}
    
    注册时候的调用流程:
    /drivers/misc/eeprom/at24.c
    module_init() => at24_init()
    i2c_add_driver() => i2c_register_driver()


    i2c_register_driver() 注册时候,设置.driver.bus = & i2c_bus_type (全局的 并且 .name="i2c")


    bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);
    驱动与总线上的设备逐个匹配,调用 __attach_adapter() => .attach_adapter(i2c_driver 此函数指针不为NULL则调用),对总线  i2c_bus_type  上的每个设备都进行匹配
    


2)
i2c_client
    struct list_head detected; //结构体内有链表,存放什么?


使用 i2c_board_info 结构体信息来创建 i2c_client(不是直接定义)
    i2c_register_board_info(busnum,i2c_board_info *,num);
    busnum 为适配器号,num为(指针所指数组)要注册的数量
    i2c_board_info
    {
        .name = "??"    //外设的名字
        .addr = 0x??    //外设的i2c总线上相应的设备地址
    }


am335x 是使用 i2c_board_info 注册的
    am335x_evm_init() => am335x_evm_i2c_init() => gen_purp_evm_dev_cfg[] i2c1_init()
        => omap_register_i2c_bus(2, 100,am335x_i2c1_boardinfo,ARRAY_SIZE(..));
    第一个参数 2 ,表示注册到第二个 i2c 口,因为是从1开始 => 对应 i2c1 接口(adapter)
    
    => i2c_register_board_info(bus_id, info, len) => list_add_tail(&devinfo->list, &__i2c_board_list);
    以上完成,静态注册i2c设备到芯片的i2c接口上,即向 i2c1接口(i2c_adapter) 中添加一个 外设(i2c_client)
    
__i2c_board_list 是个全局的链表头,存放芯片所有i2c接口(i2c_adapter)支持的所有 i2c_client 信息
    devinfo->busnum = bus_id 就是 i2c接口号(i2c_adapter)
    各 i2c_adapter 上挂载的 i2c 设备,都放这个链表中,但链表上 devinfo 是有记录 i2c_client 在哪个 i2c_adapter 上的


但是 mini2440 没看到这样注册,那是怎么注册的呢?
    根本没注册,从应用层app看,所有i2c外设都用的 i2c-0 这个设备节点文件;
    相当于app层操作适配器而非设备来访问外设的
    
注意:
    wds韦东山及linux-2.6.34网友教程说动态(insmod *.ko)创建 i2c_client
    枚举设备 i2c_new_device() 或者 i2c_new_probed_device()
    利用 i2c_driver 的 .attach_adapter(或.detect) 
        => i2c_probe(adapter, &addr_data, at24cxx_detect); 这种方式动态添加 i2c_client


3)
i2c_adapter
    struct list_head userspace_clients; //结构体的内链表,存放支持的 i2c_client
芯片 i2c 接口,每个i2c口(两个引脚+寄存器组)对应为一个 i2c_adapter
drivers/i2c/busses/i2c-omap.c
platform_driver omap_i2c_driver
    .name = "omap_i2c"
    .probe = omap_i2c_probe()
    {
        //zz// 获取 platform_device 资源及中断/am335x的寄存器地址
        platform_get_resource(pdev, IORESOURCE_MEM, 0);
        platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    
        omap_i2c_init(dev);
        request_irq(dev->irq, isr, IRQF_NO_SUSPEND, pdev->name, dev);
        
        //zz// 指定通讯协议,使用 omap-am335x 平台的,寄存器的操作在 algo 的函数中实现的
        adap->algo = &omap_i2c_algo;


        i2c_add_numbered_adapter(adap);
        drivers/i2c/i2c-core.c 
            i2c_register_adapter(adap);
            {
                //zz// i2c adapter dev file is: "i2c-0" "i2c-1" ..
                dev_set_name(&adap->dev, "i2c-%d", adap->nr);
                
                //zz// 设置总线类型为 i2c_bus_type (.name = "i2c")
                adap->dev.bus = &i2c_bus_type;
                
                //zz// i2c_driver 匹配 i2c_adapter
                bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
            }
    }


4)
i2c_algorithm
芯片平台相关的底层通讯协议,本结构放在 i2c_adapter 的函数指针成员变量中
芯片内含n个 i2c引脚+寄存器组 => 对应n个 i2c_adapter 结构
用来操作寄存器实现 i2c 发送接收


drivers/i2c/busses/i2c-omap.c
    i2c_algorithm omap_i2c_algo
    {
        //zz// am335x 实际操作i2cx寄存器进行通信的函数(最底层,寄存器控制i2c总线数据流)
        .master_xfer = omap_i2c_xfer()
        //zz// 本 algo 支持的操作;返回 i2c_adapter,i2c_algorithm 支持的操作,位表示的
        //  返回值可用于检测位 I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL 等功能是否支持
        .functionality = omap_i2c_func()
    }


5)
以上4种结构体类型的定义都在
include/linux/i2c.h


如下结构体类型,用于 adapter->algo->master_xfer() 发送接收i2c总线上的数据用的
struct i2c_msg {
    u16 addr;   //要操作的外设的内部地址
    u16 flags;  //1读或0写操作
    u16 len;    //数据的长度和缓冲区指针
    u8  *buf;


};


//zz//#######################################################################
3.
linux内核 i2c 相关驱动源码位置


1)
四个重要结构体,定义相关的变量所在文件位置
芯片平台相关的(i2c 硬件寄存器)适配器操作驱动 platfor_driver驱动安装
i2c外部设备相关的驱动 i2c_driver 的定义
    drivers/i2c/
        i2c-dev.c
            i2c_dev_init() => i2cdev_fops linux设备文件通过
            => 调用 i2c-core => i2c架构 4结构体类型 => 访问i2c外设??
            i2cdev_open() 从设备节点获得 i2c_client => i2c_adapter 等等


        i2c-core.c
            与具体芯片平台无关的函数,linux-i2c驱动框架常用函数
            i2c_add_numbered_adapter() i2c_register_adapter() 添加注册适配器
            i2c_register_driver() __attach_adapter() 注册i2c_driver 及其结构中关联适配器的函数(共用)
            i2c_detect() 适配器与驱动匹配
            
        algos/
        busses/
            i2c-s3c2410.c 平台mini2440相关的 platform_driver .name是"s3c2410-i2c"
            i2c-omap.c 平台am335x相关 platform_driver
        chips/
            设备芯片相关的 i2c_driver..
            但实际不在这里,而是在 drivers/misc/eeprom/at24.c 中的 i2c_driver at24_driver 


2)
对于 am335x i2c 使用平台设备的方式来注册到内核的,这是 am335x i2c 驱动的开始点
注意与 platform_ 平台设备(大部分设备的入口点,i2c也是)不是一个东西
    平台设备的名字,平台驱动的名字都是 "omap_i2c",这样才能匹配上


平台设备的驱动:
drivers/i2c/busses/i2c-omap.c
platform_driver omap_i2c_driver
    .driver.name = "omap_i2c"
    .id_table 没设置


平台设备的设备:
arch/arm/plat-omap/i2c.c
platform_device omap_i2c_devices[]
    char name[] = "omap_i2c";
    #define I2C_DEV_BUILDER(bus_id, res, data)
    {
        .id = (bus_id),
        .name = name,
        .resource = (res),
        .dev
            .platform_data = (data)
        ..
    }
    
    platform_device omap_i2c_devices[] = 
    {
        I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]),
    };


//zz//#######################################################################



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值