您的位置:首页 > 运维架构 > Linux

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

2012-09-22 00:37 567 查看
首先呢, linux的i2c主要有三层:i2c核心层 i2c总线层 i2c设备层

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

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

由于它是内核提供的,那么我们要做的的驱动呢, 分为两块, 一个就是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的驱动之分, 具体新方法查看:

/article/2338806.html

今天分析的是使用 注册 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 /article/2338806.html http://blog.csdn.net/yuanlulu/article/details/6559252
内核源码at24.c
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: