LINUX裝置驅動i2c架構分析(二)

來源:互聯網
上載者:User
四:i2c driver註冊在分析i2c driver的時候,有必要先分析一下i2c架構的初始化代碼如下:static int __init i2c_init(void){    int retval;     retval = bus_register(&i2c_bus_type);    if (retval)        return retval;    retval = class_register(&i2c_adapter_class);    if (retval)        goto bus_err;    retval = i2c_add_driver(&dummy_driver);    if (retval)        goto class_err;    return 0; class_err:    class_unregister(&i2c_adapter_class);bus_err:    bus_unregister(&i2c_bus_type);    return retval;} subsys_initcall(i2c_init); 很明顯,i2c_init()會在系統初始化的時候被調用.在i2c_init中,先註冊了i2c_bus_type的bus,i2c_adapter_class的class.然後再調用i2c_add_driver()註冊了一個i2c driver. I2c_bus_type結構如下:static struct bus_type i2c_bus_type = {    .name       = "i2c",    .dev_attrs  = i2c_dev_attrs,    .match      = i2c_device_match,    .uevent     = i2c_device_uevent,    .probe      = i2c_device_probe,    .remove     = i2c_device_remove,    .shutdown   = i2c_device_shutdown,    .suspend    = i2c_device_suspend,    .resume     = i2c_device_resume,}; 這個結構先放在這裡吧,以後還會用到裡面的資訊的.從上面的初始化函數裡也看到了,註冊i2c driver的介面為i2c_add_driver().代碼如下:static inline int i2c_add_driver(struct i2c_driver *driver){    return i2c_register_driver(THIS_MODULE, driver);}繼續跟蹤:int i2c_register_driver(struct module *owner, struct i2c_driver *driver){    int res;     /* new style driver methods can't mix with legacy ones */    //如果是一個newstyle的driver.但又定義了attach_adapter/detach_adapter.非法    if (is_newstyle_driver(driver)) {        if (driver->attach_adapter || driver->detach_adapter                || driver->detach_client) {            printk(KERN_WARNING                    "i2c-core: driver [%s] is confused/n",                    driver->driver.name);            return -EINVAL;        }    }     /* add the driver to the list of i2c drivers in the driver core */    //關聯到i2c_bus_types    driver->driver.owner = owner;    driver->driver.bus = &i2c_bus_type;     /* for new style drivers, when registration returns the driver core     * will have called probe() for all matching-but-unbound devices.     */     //註冊內嵌的driver    res = driver_register(&driver->driver);    if (res)        return res;     mutex_lock(&core_lock);     pr_debug("i2c-core: driver [%s] registered/n", driver->driver.name);     /* legacy drivers scan i2c busses directly */    //遍曆所有的adapter,對其都調用driver->attach_adapter    if (driver->attach_adapter) {        struct i2c_adapter *adapter;         down(&i2c_adapter_class.sem);        list_for_each_entry(adapter, &i2c_adapter_class.devices,                    dev.node) {            driver->attach_adapter(adapter);        }        up(&i2c_adapter_class.sem);    }     mutex_unlock(&core_lock);    return 0;} 這裡也有兩種形式的區分,對於第一種,只需要將內嵌的driver註冊就可以了,對於legacy的情況,對每一個adapter都調用driver->attach_adapter().現在,我們可以將adapter和i2c driver關聯起來考慮一下了:1:如果是news style形式的,在註冊adapter的時候,將它上面的i2c 裝置轉換成了struct client.struct client->dev->bus又指定了和i2c driver同一個bus.因為,它們可以發生probe.2:如果是legacy形式,就直接找到對應的對象,調用driver->attach_adapter().五: i2c_bus_type的相關操作I2c_bus_type的操作主要存在於new-style形式的驅動中.接下來分析一下對應的probe過程:5.1:match過程分析Match對應的操作函數為i2c_device_match().代碼如下static int i2c_device_match(struct device *dev, struct device_driver *drv){    struct i2c_client   *client = to_i2c_client(dev);    struct i2c_driver   *driver = to_i2c_driver(drv);     /* make legacy i2c drivers bypass driver model probing entirely;     * such drivers scan each i2c adapter/bus themselves.     */    if (!is_newstyle_driver(driver))        return 0;     /* match on an id table if there is one */    if (driver->id_table)        return i2c_match_id(driver->id_table, client) != NULL;     return 0;}如果該驅動不是一個new-style形式的.或者driver沒有定義匹配的id_table.都會匹配失敗.繼續跟蹤進i2c_match_id():static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,                        const struct i2c_client *client){    while (id->name[0]) {        if (strcmp(client->name, id->name) == 0)            return id;        id++;    }    return NULL;}由此可見.如果client的名字和driver->id_table[]中的名稱匹配即為成功. 5.2:probe過程分析Probe對應的函數為: i2c_device_probe()static int i2c_device_probe(struct device *dev){    struct i2c_client   *client = to_i2c_client(dev);    struct i2c_driver   *driver = to_i2c_driver(dev->driver);    const struct i2c_device_id *id;    int status;     if (!driver->probe)        return -ENODEV;    client->driver = driver;    dev_dbg(dev, "probe/n");     if (driver->id_table)        id = i2c_match_id(driver->id_table, client);    else        id = NULL;    status = driver->probe(client, id);    if (status)        client->driver = NULL;    return status;}這個函數也很簡單,就是將probe流程回溯到i2c driver的probe()
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.