Linux I2C驱动分析与实现(一)

====本文系本站原创,欢迎转载! 转载请注明出处:http://blog.csdn.net/yyplc====

本文基于内核版本linux-2.6.30.4分析.

Linux中i2c子系统框图如下:

Linux I2C驱动分析与实现(一)_第1张图片

•客户驱动

即I2C设备驱动,每个客户驱动可以为一个或多个I2C设备服务,并向用户空间提供相应的访问接口函数。

客户驱动需要向总线注册并通过i2c-core提供的接口与I2C设备通信。与客户程序相关的数据结构主要有struct i2c_driver和struct i2c_client

添加客户驱动:static inline int i2c_add_driver(struct i2c_driver *driver)

删除客户驱动:extern void i2c_del_driver(struct i2c_driver *);   

I2C-core核心

I2c-core核心是I2C总线的核心,承上启下,其实现与平台无关。I2C总线的初始化、注册和适配器添加和注销等相关工作均在I2C核心代码中完成,

除此之外,还向上层客户驱动提供相应的API接口函数,使得客户驱动独立于适配器驱动而工作。

• 适配器驱动

负责对I2C控制器的驱动实现,一个总线对应一个适配器。I2C总线上对I2C slave设备的具体

操作是在适配器驱动中完成的。适配器驱动作为platform_driver而注册,在probe()到驱动设

备后,向总线声明并被添加:i2c_add_numbered_adapter(&i2c->adap);

I2c-dev驱动是系统自带的一个通用客户驱动,它不是针对某一个I2C设备(即没有自己驱动设备id-table),它可以使得用户空间的程序通过i2c-tools访问总线上的i2c/SMBUS设备。

I2C子系统主要数据结构

•struct i2c_msg;             //I2C消息数据结构

•struct i2c_algorithm;       //算法驱动数据结构

•struct i2c_adapter;         //I2C适配器数据结构

•struct i2c_client;          //I2C客户数据结构

•struct i2c_driver;          //I2C设备驱动数据结构

•struct i2c_board_info;      //描述板载I2C设备的信息  
 

以上数据结构在include/linux/i2c.h中定义,下面我们结合源码分析一下这些数据结构

I2C算法结构:

struct i2c_algorithm {

   /* If an adapter algorithm can't do I2C-level access, set master_xfer

      to NULL. If an adapter algorithm can do SMBus access, set

      smbus_xfer. If set to NULL, the SMBus protocol is simulated

      using common I2C messages */

   /* master_xfer should return the number of messages successfully

      processed, or a negative value on error */

   int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,

            int num);

   int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,

            unsigned short flags, char read_write,

            u8 command, int size, union i2c_smbus_data *data);

 

   /* To determine what the adapter supports */

   u32 (*functionality) (struct i2c_adapter *);

};

例如:

s3c2440 i2c 适配器驱动是这样实现这个算法结构体:

static const struct i2c_algorithm s3c24xx_i2c_algorithm = {

     .master_xfer            = s3c24xx_i2c_xfer,

     .functionality          = s3c24xx_i2c_func,

};

s3c24xx_i2c_xfer 是适配器的对I2C设备的读写操作函数

s3c24xx_i2c_func函数决定了该适配器向i2c-core核心支持哪些API函数

I2c_adapter结构标识一个物理I2C总线(适配器),总线通过

算法结构访问到适配器。

struct i2c_adapter {

    struct module *owner;

    unsigned int id;

    unsigned int class;             /* classes to allow probing for */

    const struct i2c_algorithm *algo; /* the algorithm to access the bus */

    void *algo_data;

 

    /* --- administration stuff. */

    int (*client_register)(struct i2c_client *) __deprecated;

    int (*client_unregister)(struct i2c_client *) __deprecated;

 

    /* data fields that are valid for all devices  */

    u8 level;                /* nesting level for lockdep */

    struct mutex bus_lock;

    struct mutex clist_lock;

 

    int timeout;            /* in jiffies */

    int retries;

    struct device dev;      /* the adapter device */

 

    int nr;

    struct list_head clients;     /* DEPRECATED */

    char name[48];

    struct completion dev_released;

};

I2c_msg是I2C消息,I2C通信是以i2c_msg为单位的。

struct i2c_msg {

   __u16 addr;     /* slave address            */

   __u16 flags;

#define I2C_M_TEN      0x0010   /* this is a ten bit chip address */

#define I2C_M_RD       0x0001   /* read data, from slave to master */

#define I2C_M_NOSTART       0x4000   /* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_REV_DIR_ADDR  0x2000   /* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_IGNORE_NAK    0x1000   /* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_NO_RD_ACK 0x0800   /* if I2C_FUNC_PROTOCOL_MANGLING */

#define I2C_M_RECV_LEN 0x0400   /* length will be first received byte */

   __u16 len;      /* msg length               */

   __u8 *buf;      /* pointer to msg data           */

};

I2c_client描述了一个i2c设备。

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 i2c_driver *driver;  /* and our access routines    */

     struct device dev;            /* the device structure          */

     int irq;                     /* irq issued by device          */

     struct list_head list;          /* DEPRECATED */

     struct list_head detected;

     struct completion released;

};

I2c_driver描述了I2C设备的驱动。

struct i2c_driver {

      int id;

      unsigned int class;

 

      /* Notifies the driver that a new bus has appeared. This routine

       * can be used by the driver to test if the bus meets its conditions

       * & seek for the presence of the chip(s) it supports. If found, it

       * registers the client(s) that are on the bus to the i2c admin. via

       * i2c_attach_client.  (LEGACY I2C DRIVERS ONLY)

       */

      int (*attach_adapter)(struct i2c_adapter *);

      int (*detach_adapter)(struct i2c_adapter *);

 

      /* tells the driver that a client is about to be deleted & gives it

       * the chance to remove its private data. Also, if the client struct

       * has been dynamically allocated by the driver in the function above,

       * it must be freed here.  (LEGACY I2C DRIVERS ONLY)

       */

      int (*detach_client)(struct i2c_client *) __deprecated;

      。。。

}

I2C核心提供的API函数

•      extern int i2c_master_send(struct i2c_client *client, const char *buf,

•                    int count);

•      extern int i2c_master_recv(struct i2c_client *client, char *buf, int count);

 

•      extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,

•                 int num);

•      extern s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,

•                   unsigned short flags, char read_write, u8 command,

•                   int size, union i2c_smbus_data *data);

•      extern s32 i2c_smbus_read_byte(struct i2c_client *client);

•      extern s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value);

•      extern s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command);

•      extern s32 i2c_smbus_write_byte_data(struct i2c_client *client,

•                           u8 command, u8 value);

•      extern s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command);

•      extern s32 i2c_smbus_write_word_data(struct i2c_client *client,

•                           u8 command, u16 value);

其中: i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 是实现其他函数的基础,换句话说,其它函数均是通过调用该函数来实现的。

下篇将具体谈谈Linux 中如何实现I2C客户程序。《Linux I2C驱动分析与实现(二)》

 

 

你可能感兴趣的:(Algorithm,数据结构,c,linux,struct,deprecated)