Linux I2C设备驱动分析 基于2440 2.6.32内核

首先呢, linux的i2c主要有三层:i2c核心层 i2c总线层  i2c设备层

i2c核心内核为我们提供的, 它主要的作用就是提供了

  1. i2c总线驱动中的适配器(adapter)和运算方法(algorithm)还有i2c设备驱动的注册, 撤销方法 
  2. 探测设备和设备地址的上层代码等

由于它是内核提供的,那么我们要做的的驱动呢, 分为两块, 一个就是i2c总线的驱动 另一个就是i2c设备的驱动,

i2c总线的驱动主要是对硬件体系结构的适配器的实现, 说白了, 就是传输的那些具体的传输的开始信号, 停止信号, ack等的设置(当然还有其他的....)

而, 今天分析的并不分析i2c总线的驱动, 我们的总线驱动可以利用现成的那就是i2c-s3c2410.c这个函数.

今天分析的主要是i2c设备驱动, 

i2c设备驱动主要有两个结构体: 

i2c_client 和 

i2c_driver

 

i2c_driver是一套驱动方法,用于辅助作用的数据结构,不对应任何物理实体。

i2c_client对应真实的物理设备,每个I2C设备都需要一个i2c_client来描述。

在2.6内核已经没有了以前的legacy model和standard drivermodel的驱动之分, 具体新方法查看:

http://blog.csdn.net/yuanlulu/article/details/6557901

今天分析的是使用 注册 i2c_board_info 让 i2c核心帮我们创建i2c_client , 这样的话在i2c_driver注册的时候就会调用 其指定的probe函数.

首先我们先写个最简单的i2c设备驱动, 主要是能够让i2c 核心帮我们匹配到设备:

 
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/mutex.h>

#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR "zhutoubenben"
#define DRIVER_DESC "i i c iic_at24c08..."
#define I2C_DEVICE  "24c08"

static int i2c_at24c08_probe(struct i2c_client *i2c_client, const struct i2c_device_id *i2c_device_id){
	printk("i2c_at24c08_probe , probe the device ..\n");
	return 0;
}

static int i2c_at24c08_remove(struct i2c_client *i2c_client){
	printk("i2c_at24c08_remove , remove the device ..\n");
	return 0;
}

struct i2c_device_id at24c08_id[] = {
	{I2C_DEVICE,0},{}  //  这里会和i2c_client的名字匹配,一样的话就调用probe
};

MODULE_DEVICE_TABLE(i2c, at24c08_id);


static struct i2c_driver i2c_at24c08_driver = {
	.driver = {
		.name = I2C_DEVICE
	},
	.probe    = i2c_at24c08_probe,
	.remove    = i2c_at24c08_remove,
	.id_table    = at24c08_id,
};

static int __init i2c_at24c08_init(void){
	int result;
	result = i2c_add_driver(&i2c_at24c08_driver); // 注册i2c_driver
	if (result)
		printk("i2c_add_driver failed. Error number %d", result);
	return result;
}

static void __exit i2c_at24c08_exit(void){
	i2c_del_driver(&i2c_at24c08_driver);
}

module_init(i2c_at24c08_init);
module_exit(i2c_at24c08_exit);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);

接下来我们得在mach-mini2440.c下添加:

static struct i2c_board_info __initdata mini2440_i2c_board_info[] = {  
         {  
                I2C_BOARD_INFO("24c08", 0x50),  
         },   
}; 


 

在 mini2440_machine_init()函数下添加:

 
i2c_register_board_info(0, mini2440_i2c_board_info,
                         ARRAY_SIZE(mini2440_i2c_board_info));


 
//  那么接下来我们先分析系统启动的时候 我们的i2c_client怎么来的呢?
//  接下来这一整段主要是系统启动的时候 , 当s3c2410-i2c平台设备和驱动都加载时,调用driver中的probe
//  而其中会分析到i2c_client的分配
s3c24xx_i2c_probe
    i2c_add_numbered_adapter
        i2c_register_adapter
            device_register // 
            i2c_scan_static_board_info
                list_for_each_entry
                if (devinfo->busnum == adapter->nr \
                    && !i2c_new_device(adapter,	&devinfo->board_info))//分配i2c_client, 并指定adapter
                bus_for_each_drv(&i2c_bus_type, NULL, adap,i2c_do_add_adapter);// 此时i2cbus还没有driver,不调用


i2c_add_driver
    i2c_register_driver
        driver_register //  注册驱动, 接下来就是通用的sysfs下的驱动添加到bus下的匹配方法
            bus_add_driver
                driver_attach
                    __driver_attach
                        driver_probe_device
                            really_probe
//到此的
really_probe{
    ...
   if (dev->bus->probe) {
                   ret = dev->bus->probe(dev);//调用bus的probe
                   if (ret)
                           goto probe_failed;
           } else if (drv->probe) {
                   ret = drv->probe(dev);
                   if (ret)
                           goto probe_failed;
           }
   ...
}
      
/*
 if (dev->bus->probe)判断bus是否有probe方法, 
 而我们的i2c bus是有probe方法的, 即i2c_device_probe
 最后调用driver->probe(client, i2c_match_id(driver->id_table, client));//此处的client是上面分析的创建的那个
 也就是我们自己的probe函数了
*/

i2c驱动的数据结构图:

接下来具体读写的主要在: http://blog.csdn.net/zhutoubenben/article/details/8007432

参考文献: 

http://blog.csdn.net/sadamoo/article/details/7968011

http://blog.csdn.net/yuanlulu/article/details/6557901

http://blog.csdn.net/yuanlulu/article/details/6559252

内核源码at24.c

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值