http://blog.csdn.net/bob_fly1984/article/details/8820670

struct ov5640_data {
    struct ov5640_platform_data chip;
    bool use_smbus;

    /*  
     * Lock protects against activities from other Linux tasks,
     * but not from changes by other I2C masters.
     */
    struct mutex lock;
    struct bin_attribute bin;

    u8 *writebuf;
    unsigned write_max;
    unsigned num_addresses;

    /*  
     * Some chips tie up multiple I2C addresses; dummy devices reserve
     * them for us, and we'll use them with SMBus calls.
     */
    struct i2c_client *client[];
};

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

static struct ov5640_platform_data ov5640_chip_info;

static struct i2c_board_info ov5640_i2c_board_info  __initdata ={
    .type = CONFIG_OV5640_TYPE,
    .addr = CONFIG_OV5640_DEVICE_ADDR,
};

static void __init i2c_board_init(void)
{
    int i;
    for (i = 0; i < sizeof(ov5640_list) / sizeof(struct ov5640_info); i++) {
        if (strcmp(ov5640_i2c_board_info.type, ov5640_list[i].name) == 0) {
            ov5640_chip_info.byte_len = ov5640_list[i].byte_len;
            ov5640_chip_info.page_size = ov5640_list[i].page_size;
            ov5640_chip_info.flags = ov5640_list[i].flags;
            ov5640_i2c_board_info.platform_data = &ov5640_chip_info;
            break;
        }
    }
    i2c_register_board_info(CONFIG_OV5640_I2C_BUS_NUM, &ov5640_i2c_board_info, 1);
}
这一堆是一个从设备client dev的注册

一个从设备的属性,注册通过

i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned n);

struct i2c_board_info {
    char        type[I2C_NAME_SIZE];/×相当于设备名用于区分×/
    unsigned short  flags;
    unsigned short  addr;
    void        *platform_data;    
    struct dev_archdata *archdata;
    struct device_node *of_node;   
    struct acpi_dev_node acpi_node;
    int     irq;
};

自定义一个结构体

struct ov5640_info {
    char *name;
    unsigned int byte_len;   /* size (sum of all addr) */
    unsigned short page_size;  /* for writes */
    unsigned char flags;
};

定义一个结构体数组

static const struct ov5640_info ov5640_list[] = {
    { "OV5640",   128 / 8,     1,   ov5640_FLAG_TAKE8ADDR },
    { NULL,      0,           0,   0 }  /* END OF LIST */
};

相当于busnum,几路i2c

定义一个结构体存储用户数据

struct at24_platform_data {
    u32     byte_len;       /* size (sum of all addr) */
    u16     page_size;      /* for writes */
    u8      flags;
#define AT24_FLAG_ADDR16    0x80    /* address pointer is 16 bit */
#define AT24_FLAG_READONLY  0x40    /* sysfs-entry will be read-only */
#define AT24_FLAG_IRUGO     0x20    /* sysfs-entry will be world-readable */
#define AT24_FLAG_TAKE8ADDR 0x10    /* take always 8 addresses (24c00) */

    void        (*setup)(struct memory_accessor *, void *context);
    void        *context;
};

static struct ov5640_platform_data ov5640_chip_info;

static struct i2c_board_info ov5640_i2c_board_info  __initdata ={
    .type = CONFIG_OV5640_TYPE,
    .addr = CONFIG_OV5640_DEVICE_ADDR,
};

static void __init i2c_board_init(void)
{
    int i;
    for (i = 0; i < sizeof(ov5640_list) / sizeof(struct ov5640_info); i++) {
        if (strcmp(ov5640_i2c_board_info.type, ov5640_list[i].name) == 0) {
            ov5640_chip_info.byte_len = ov5640_list[i].byte_len;
            ov5640_chip_info.page_size = ov5640_list[i].page_size;
            ov5640_chip_info.flags = ov5640_list[i].flags;
            ov5640_i2c_board_info.platform_data = &ov5640_chip_info;
            break;
        }
    }
    i2c_register_board_info(CONFIG_OV5640_I2C_BUS_NUM, &ov5640_i2c_board_info, 1);
}

将定义的platform_data注册进去

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

static const struct i2c_device_id ov5640_ids[] = {
    { "OV5640", 0 },
};
MODULE_DEVICE_TABLE(i2c, ov5640_ids);

static struct i2c_driver ov5640_driver = {
    .driver = {
        .name = "OV5640",
        .owner = THIS_MODULE,
    },
    .probe = ov5640_probe,
    .remove = __devexit_p(ov5640_remove),
    .id_table = ov5640_ids,
};

i2c_driver模型

struct i2c_driver {
    unsigned int class;       

    /* Notifies the driver that a new bus has appeared. You should avoid
     * using this, it will be removed in a near future.
     */
    int (*attach_adapter)(struct i2c_adapter *) __deprecated;

    /* Standard driver model interfaces */
    int (*probe)(struct i2c_client *, const struct i2c_device_id *);
    int (*remove)(struct i2c_client *);

    /* driver model interfaces that don't relate to enumeration  */
    void (*shutdown)(struct i2c_client *);
    int (*suspend)(struct i2c_client *, pm_message_t mesg);
    int (*resume)(struct i2c_client *);

    /* Alert callback, for example for the SMBus alert protocol.
     * The format and meaning of the data value depends on the protocol.
     * For the SMBus alert protocol, there is a single bit of data passed
     * as the alert response's low bit ("event flag").
     */
    void (*alert)(struct i2c_client *, unsigned int data);

    /* a ioctl like command that can be used to perform specific functions
     * with the device.
     */
    int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);

    struct device_driver driver;
    const struct i2c_device_id *id_table;

    /* Device detection callback for automatic device creation */
    int (*detect)(struct i2c_client *, struct i2c_board_info *);
    const unsigned short *address_list;
    struct list_head clients;
};

struct i2c_client {
    unsigned short flags;       /* div., see below      */
    unsigned short addr;        /* chip address - NOTE: 7bit    */
                    /* addresses are stored in the  */
                    /* _LOWER_ 7 bits       */
    char name[I2C_NAME_SIZE];
    struct i2c_adapter *adapter;    /* the adapter we sit on    */
    struct device dev;      /* the device structure     */
    int irq;            /* irq issued by device     */
    struct list_head detected;
};

static int __init ov5640_init(void)
{
    io_limit = rounddown_pow_of_two(io_limit);
    return i2c_add_driver(&ov5640_driver);
}
module_init(ov5640_init);

static void __exit ov5640_exit(void)
{
    i2c_del_driver(&ov5640_driver);
}
module_exit(ov5640_exit);

/* eeprom device private list */

linux设备驱动的更多相关文章

  1. 浅谈Android系统移植、Linux设备驱动

    一.Android系统架构 第一层:Linux内核 包括驱动程序,管理内存.进程.电源等资源的程序 第二层:C/C++代码库 包括Linux的.so文件以及嵌入到APK程序中的NDK代码 第三层:An ...

  2. linux设备驱动概述,王明学learn

    linux设备驱动学习-1 本章节主要学习有操作系统的设备驱动和无操作系统设备驱动的区别,以及对操作系统和设备驱动关系的认识. 一.设备驱动的作用 对设备驱动最通俗的解释就是“驱使硬件设备行动” .设 ...

  3. Linux设备驱动工程师之路——内核链表的使用【转】

    本文转载自:http://blog.csdn.net/forever_key/article/details/6798685 Linux设备驱动工程师之路——内核链表的使用 K-Style 转载请注明 ...

  4. linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-119723.html linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟 xxxxxxxxxx ...

  5. linux设备驱动归纳总结(十二):简单的数码相框【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-116926.html linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxx ...

  6. linux设备驱动归纳总结(十一):写个简单的看门狗驱动【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-112879.html linux设备驱动归纳总结(十一):写个简单的看门狗驱动 xxxxxxxxxxx ...

  7. linux设备驱动归纳总结(十):1.udev&misc【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-111839.html linux设备驱动归纳总结(十):1.udev&misc xxxxxxx ...

  8. linux设备驱动归纳总结(九):1.platform总线的设备和驱动【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-111745.html linux设备驱动归纳总结(九):1.platform总线的设备和驱动 xxxx ...

  9. linux设备驱动归纳总结(八):4.总线热插拔【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-110774.html linux设备驱动归纳总结(八):4.总线热插拔 xxxxxxxxxxxxxxx ...

  10. linux设备驱动归纳总结(八):3.设备管理的分层与面向对象思想【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-110738.html linux设备驱动归纳总结(八):3.设备管理的分层与面向对象思想 xxxxxx ...

随机推荐

  1. struts文件上传,获取文件名和文件类型

    struts文件上传,获取文件名和文件类型   Action中还有两个属 性:uploadFileName和uploadContentType,这两个属性分别用于封装上传文件的文件名.文件类型.这是S ...

  2. 深入理解javascript原型和闭包(14)——从【自由变量】到【作用域链】

    先解释一下什么是“自由变量”. 在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量.如下图 如上程序中,在调用fn()函数时,函数体中第6 ...

  3. tyvj1008 传球游戏

    背景 NOIP2008复赛普及组第三题 描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一 ...

  4. [Hadoop] Hadoop学习笔记之Hadoop基础

    1 Hadoop是什么? Google公司发表了两篇论文:一篇论文是“The Google File System”,介绍如何实现分布式地存储海量数据:另一篇论文是“Mapreduce:Simplif ...

  5. jQuery入门(1)jQuery中万能的选择器

    jQuery入门(1)jQuery中万能的选择器 jQuery入门(2)使用jQuery操作元素的属性与样式 jQuery入门(3)事件与事件对象 jQuery入门(4)jQuery中的Ajax()应 ...

  6. Linux C 字符串输出函数 puts()、fputs()、printf() 详解

    一.puts() 函数详解 puts()函数用来向 标准输出设备 (屏幕)写字符串并换行,调用格式为: puts(s); 其中s为字符串变量(字符串数组名或字符串指针). puts()函数的作用与语 ...

  7. How do I enable log4net internal debugging?

    http://logging.apache.org/log4net/release/faq.html

  8. css pre标签

    浏览器:firfox49.0.2 在使用<pre>标签输出格式化文本的时候,遇到了一个小问题. 要在页面的底部输出两行文本,但是最后一行的文字总是距离屏幕的底部太大.下面图中的样子: 相关 ...

  9. java9

    1:StringBuffer(掌握) (1)用字符串做拼接,比较耗时并且也耗内存,而这种拼接操作又是比较常见的,为了解决这个问题,Java就提供了 一个字符串缓冲区类.StringBuffer供我们使 ...

  10. Linux下安装OpenCV+Python支持

    以下说明在Linux下Python和OpenCV结合安装的过程,Python要使用OpenCV模块,则必须导入OpenCV提供的包,所以要提供Python支持,首先在安装OpenCV前安装必要的组件, ...