Linux裝置驅動子系統- I2C__Linux

來源:互聯網
上載者:User

本文轉自:http://blog.csdn.net/qianjin0703/article/details/5894869


1. Overview

2. Data Structure

3. Adapter

4. I2C-core

5. Slave Device

 

1. Overview

  1.1 Definition  I2C           Inter-Integrated Circuit  SMBUS      System Management Bus, the I2C subset

  1.2 Characteristics  The amount of data exchanged is small.  The required data transfer rate is low.

  1.3 Speed  Fast speed     400 kbps  Full speed      100 kbps

  1.4 Topology

 

 

 

2 Data Structure

     理解資料結構對理解整個驅動程式子系統是很重要的。I2C的主要有兩大資料結構,struct i2c_client 和 struct i2c_adapter。

  2.1 i2c_client

     struct i2c_client {
        unsigned short flags;  /* div., see below  */
        unsigned short addr;  /* chip address */
        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 (or -1) */
        char driver_name[KOBJ_NAME_LEN];
        struct list_head list;  /* DEPRECATED */
        struct completion released;
};

      struct i2c_client代表一個掛載到i2c匯流排上的i2c從裝置,該裝置所需要的資料結構,其中包括 該i2c從裝置所依附的i2c主裝置 struct i2c_adapter *adapter 該i2c從裝置的驅動程式struct i2c_driver *driver 作為i2c從裝置所通用的成員變數,比如addr, name等 該i2c從裝置驅動所特有的資料,依附於dev->driver_data下

  2.2 i2c_adapter

     struct i2c_adapter {
        struct module *owner;
        unsigned int id;
        unsigned int class;
        const struct i2c_algorithm *algo; /* the algorithm to access the bus */
        void *algo_data;

        ... ...

     };
     struct i2c_adapter代表主晶片所支援的一個i2c主裝置,該裝置所需要的資料結構,

     其中,struct i2c_algorithm *algo是該i2c主裝置傳輸資料的一種演算法,或者說是在i2c匯流排上完成主從裝置間資料通訊的一種能力。

     struct i2c_algorithm {
        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);
        u32 (*functionality) (struct i2c_adapter *);
    };

    接下來,要實現整個i2c子系統的驅動,便圍繞這兩個資料結構展開,其主要步驟可總結為以下三步, 實現i2c主裝置驅動                (drivers/i2c/bus/*) 註冊i2c從裝置的i2c_client    (drivers/i2c/i2c-core) 實現i2c從裝置驅動

 3 Adapter

   核心目錄drivers/i2c下有兩個檔案夾,algorithm和bus,其中bus存放i2c主裝置的驅動,主裝置驅動完成兩大任務, 提供該i2c主裝置與從裝置間完成資料通訊的能力 完成該i2c_adapter和所有已知的i2c_client的註冊

   以i2c-pxa.c為例,

  /* drivers/i2c/bus/i2c-pxa.c */

 static int __init i2c_adap_pxa_init(void)
{
 return platform_driver_register(&i2c_pxa_driver);
}

static struct platform_driver i2c_pxa_driver = {
 .probe  = i2c_pxa_probe,
 ... ...
 .id_table = i2c_pxa_id_table,
};

 static int i2c_pxa_probe(struct platform_device *dev)
{
 struct pxa_i2c *i2c;
  i2c->adap.algo = i2c_pxa_algorithm;             // 提供該i2c主裝置與從裝置間完成資料通訊的能力

  i2c_add_numbered_adapter(&i2c->adap);      // 調用i2c-core.c中的介面函數,完成該i2c_adapter和i2c_client的註冊

  ... ...
 }

static const struct i2c_algorithm i2c_pxa_algorithm = {
 .master_xfer = i2c_pxa_xfer,                  // 根據pxa具體晶片的要求,完成i2c資料轉送
 .functionality = i2c_pxa_functionality,
};

 

 4 I2C-core

   核心目錄drivers/i2c下的i2c-core.c,顧名思義,是核心為I2C提供的統一系統介面。

   看看i2c_add_numbered_adapter做了些什麼,

   int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{
   ... ...
  status = i2c_register_adapter(adap);
  return status;
}

 

static int i2c_register_adapter(struct i2c_adapter *adap)
{
   ... ...
  device_register(&adap->dev);     //完成I2C主裝置adapter的註冊,即註冊object和發送uevent等
  i2c_scan_static_board_info(adap);      

   ... ...
}
 i2c_scan_static_board_info(adap),此函數為整個I2C子系統的核心,它會去遍曆一個由I2C從裝置群組成的雙向迴圈鏈表,並完成所有I2C從裝置的i2c_client的註冊,具體過程如下,

 static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
 struct i2c_devinfo *devinfo;     //已經建立好了的I2C從裝置鏈表


 list_for_each_entry(devinfo, &__i2c_board_list, list) {
     i2c_new_device(adapter,&devinfo->board_info);
     ... ...
 }
}

 struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
   ... ...
   i2c_attach_client(client);
   ... ...

}
int i2c_attach_client(struct i2c_client *client)
{
   ... ...
   device_register(&client->dev);     //完成I2C從裝置client的註冊
   ... ...
}

 那麼,這個I2C從裝置群組成的雙向迴圈鏈表,是什麼時候通過什麼方式建立起來的呢。

 以某重力感應裝置為例,

/* /arch/arm/mach-pxa/starwood_p1.c */

static void __init saar_init(void)

{

   ... ...

   i2c_register_board_info(0, ARRAY_AND_SIZE(saar_i2c_bma220_info));

   ... ...

}

static struct i2c_board_info saar_i2c_bma220_info[] = {
 {
  .driver_name = "bma220",
  .addr  = 0x0B,
  .irq  = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO15)), 
 },
};

 /* drivers/i2c/i2c-boardinfo.c */

 int __init i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)
{

   ... ...

  struct i2c_devinfo *devinfo;
  devinfo->board_info = *info;
  list_add_tail(&devinfo->list, &__i2c_board_list);    //將I2C從裝置加入該鏈表中
   ... ...
}

 所以,在系統初始化的過程中,我們可以通過 i2c_register_board_info,將所需要的I2C從裝置加入一個名為__i2c_board_list雙向迴圈鏈表,系統在成功載入I2C主裝置adapt後,就會對這張鏈表裡所有I2C從裝置逐一地完成 i2c_client的註冊。

 

  5 Slave Driver

       如果說硬體方面,I2C主裝置已經整合在主晶片內,軟體方面,linux也為我們提供了相應的驅動程式,位於drivers/i2c/bus下,那麼接下來I2C從裝置驅動就變得容易得多。既然系統載入I2C主裝置驅動時已經註冊了i2c_adapter和i2c_client,那麼I2C從裝置主要完成三大任務, 系統初始化時添加以i2c_board_info為結構的I2C從裝置的資訊 在I2C從裝置驅動程式裡使用i2c_adapter裡所提供的演算法,即實現I2C通訊。 將I2C從裝置的特有資料結構掛在到i2c_client.dev->driver_data下。

以重力感應裝置為例,

static int __init BMA220_init(void)
{
 return i2c_add_driver(&bma220_driver);
}

static struct i2c_driver bma220_driver = { 
 .driver = {
  .owner = THIS_MODULE, 
  .name = "bma220",
 },
 .class  = I2C_CLASS_HWMON,
 .probe  = bma220_probe,
 .remove  = bma220_remove,
};

static int bma220_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
 struct bma220_data *data;     
 i2c_check_functionality(client->adapter, I2C_FUNC_I2C)

 i2c_smbus_read_word_data(client, 0x00);    // i2c-core提供的介面,利用i2c_adapter的演算法實現I2C通訊
 i2c_set_clientdata(bma220_client, data);      // 將裝置的資料結構掛到i2c_client.dev->driver_data下
 misc_register(&bma_device);
 request_irq(client->irq, bma220_irq_handler, IRQF_TRIGGER_RISING, "bma220", &data->bma220);
 bma220_set_en_tt_xyz(0);
 bma220_reset_int();

 ... ...
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.