I2C驱动框架理解


相关对象

1、 I2C总线
2、 I2C设备驱动
4、 I2C设备
3、 I2C适配器

-------------------------------------------------------------------------------------------------------

I2C总线
struct bus_type变量i2c_bus_type定义了I2C总线
    struct bus_type i2c_bus_type = {
        .name        = "i2c",
        .match        = i2c_device_match,
        .probe        = i2c_device_probe,
        .remove        = i2c_device_remove,
        .shutdown    = i2c_device_shutdown,
        .pm        = &i2c_device_pm_ops,
    };

I2C总线对应着/bus下的一条总线,这个i2c总线结构体管理着i2c设备与I2C驱动的匹配,删除等操作,I2C总线会调用i2c_device_match函数看I2C设备和I2C驱动是否匹配,如果匹配就调用i2c_device_probe函数,进而调用I2C驱动的probe函数;

I2C总线注册
    I2C总线属于I2C核心层,在driver/i2c/i2c-core.c中postcore_initcall(i2c_init)开始I2C总线注册,调用过程如下:
    postcore_initcall(i2c_init);
            i2c_init(void)
                bus_register(&i2c_bus_type);
        
    i2c_init()实现如下:
    static int __init i2c_init(void)
    {
        ... ...
        retval = bus_register(&i2c_bus_type);
        ... ...
    }

-------------------------------------------------------------------------------------------------------

I2C设备驱动
    定义在include/linux/i2c.h中的struct i2c_driver结构描述I2C驱动,
    struct i2c_driver
    {
        unsigned int class;

        int (*attach_adapter)(struct i2c_adapter *) __deprecated;
        int (*detach_adapter)(struct i2c_adapter *) __deprecated;

        int (*probe)(struct i2c_client *, const struct i2c_device_id *);
        int (*remove)(struct i2c_client *);

        void (*shutdown)(struct i2c_client *);
        int (*suspend)(struct i2c_client *, pm_message_t mesg);
        int (*resume)(struct i2c_client *);
        void (*alert)(struct i2c_client *, unsigned int data);
        int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);

        struct device_driver driver; // 表示这是一个设备驱动
        const struct i2c_device_id *id_table;
        int (*detect)(struct i2c_client *, struct i2c_board_info *);
        const unsigned short *address_list;
        struct list_head clients;
    };

-------------------------------------------------------------------------------------------------------

I2C设备
    struct i2c_client结构体描述一个I2C设备,定义在include/linux/i2c.h中
    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;    // 适配器
        struct i2c_driver *driver;        // 设备对应驱动
        struct device dev;                // 表明这个是一个设备
        int irq;                        // 中断号
        struct list_head detected;
    };

-------------------------------------------------------------------------------------------------------

I2C适配器
    I2C适配器就是SOC上的I2C控制器
    struct i2c_adapter {
        ... ...
        const struct i2c_algorithm *algo;
        struct device dev;
        ... ...
    };
    
    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驱动、I2C设备),管理I2C设备和I2C驱动的匹配和删除等
I2C驱动:I2C设备驱动程序
I2C设备:具体硬件设备的一个抽象
I2C适配器:用于I2C驱动和I2C设备间的通道,SOC上I2C控制器的抽象

-------------------------------------------------------------------------------------------------------

I2C驱动注册
    通过调用i2c_add_driver函数注册I2C驱动
    static inline int i2c_add_driver(struct i2c_driver *driver)
    {
        return i2c_register_driver(THIS_MODULE, driver);
    }
    再调用i2c_register_driver注册
    int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
    {    
        /*        
        struct bus_type i2c_bus_type = {
            .name        = "i2c",
            .match        = i2c_device_match,
            .probe        = i2c_device_probe,
            .remove        = i2c_device_remove,
            .shutdown    = i2c_device_shutdown,
            .pm        = &i2c_device_pm_ops,
        };
        */
        ... ...
        driver->driver.bus = &i2c_bus_type;  //绑定总线
        ... ...
        res = driver_register(&driver->driver);    //向总线注册驱动
        ... ...
        /* 遍历I2C总线上的所有设备,调用__process_new_driver函数 */
        i2c_for_each_dev(driver, __process_new_driver);

        return 0;
    }

    进入driver_register函数
    int driver_register(struct device_driver *drv)
    {
        ... ...
        ret = bus_add_driver(drv); // 将驱动添加到总线
    }

    进入bus_add_driver函数:
    int bus_add_driver(struct device_driver *drv)
    {    
        ... ...
        if (drv->bus->p->drivers_autoprobe) {
            error = driver_attach(drv);
            if (error)
                goto out_unregister;
        }

        klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
        ... ...
    }

    进入driver_attach函数:
    int driver_attach(struct device_driver *drv)
    {
        return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
    }

    int bus_for_each_dev(struct bus_type *bus, struct device *start,
             void *data, int (*fn)(struct device *, void *))
    {    
        /* 遍历总线的所有设备链表(bus->p->klist_devices)的所有设备,执行fn函数 */
        while ((dev = next_device(&i)) && !error)
            error = fn(dev, data);
    }
    对于bus_for_each_dev(drv->bus, NULL, drv, __driver_attach),fn对应的函数就是__driver_attach

    进入__driver_attach函数:
    static int __driver_attach(struct device *dev, void *data)
    {
        // 判断驱动与设备是否匹配
        if (!driver_match_device(drv, dev))
            return 0;

        // 如果匹配,调用driver_probe_device函数            
        if (!dev->driver)
            driver_probe_device(drv, dev);
    }

    进入driver_match_device函数
    static inline int driver_match_device(struct device_driver *drv, struct device *dev)
    {
        // 调用bus总线的match函数,判断是否匹配
        return drv->bus->match ? drv->bus->match(dev, drv) : 1;
    }

    match函数在哪里?在最开始的i2c_register_driver函数中,driver->driver.bus = &i2c_bus_type;
    i2c_bus_type被赋值给了bus
        struct bus_type i2c_bus_type = {
            .name        = "i2c",
            .match        = i2c_device_match,
            .probe        = i2c_device_probe,
            .remove        = i2c_device_remove,
            .shutdown    = i2c_device_shutdown,
            .pm        = &i2c_device_pm_ops,
        };

        drv->bus->match对应的就是i2c_device_match函数;

    进入i2c_device_match函数:
    static int i2c_device_match(struct device *dev, struct device_driver *drv)
    {
        struct i2c_client    *client = i2c_verify_client(dev); // 由device获得i2c_client
        struct i2c_driver    *driver = to_i2c_driver(drv); // 由device_driver获取到i2c_driver
        
        return i2c_match_id(driver->id_table, client) != NULL;
    }

    进入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;
    }

    strcmp(client->name, id->name)    
    比较i2c_client的char name[I2C_NAME_SIZE]与i2c_driver的i2c_device_id中的char name[I2C_NAME_SIZE];
    
    回到__driver_attach函数:
    static int __driver_attach(struct device *dev, void *data)
    {
        // 判断驱动与设备是否匹配
        if (!driver_match_device(drv, dev))
            return 0;

        // 如果匹配,调用driver_probe_device函数            
        if (!dev->driver)
            driver_probe_device(drv, dev);
    }
    driver_match_device匹配成功后,调用driver_probe_device函数

    进入driver_probe_device函数
    int driver_probe_device(struct device_driver *drv, struct device *dev)
    {
        ret = really_probe(dev, drv);
    }

    进入really_probe函数
    static int really_probe(struct device *dev, struct device_driver *drv)
    {
        if (dev->bus->probe) {
            ret = dev->bus->probe(dev); //优先调用总线的probe函数
        } else if (drv->probe) {
            ret = drv->probe(dev);
        }
    }
    
    优先调用总线的probe函数,由总线定义:
    struct bus_type i2c_bus_type = {
        .name        = "i2c",
        .match        = i2c_device_match,
        .probe        = i2c_device_probe,
        .remove        = i2c_device_remove,
        .shutdown    = i2c_device_shutdown,
        .pm        = &i2c_device_pm_ops,
    };
    
    dev->bus->probe就是i2c_device_probe函数;
    
    进入i2c_device_probe函数
    static int i2c_device_probe(struct device *dev)
    {
        struct i2c_driver    *driver = to_i2c_driver(dev->driver);
        // 调用i2c驱动i2c_driver的probe函数
        status = driver->probe(client, i2c_match_id(driver->id_table, client));
    }

    通过上面的分析,可以知道i2c总线控制,当向内核注册i2c驱动时,会将i2c驱动添加到总线的链表中,遍历总线上所有设备,通过i2c_client->name, i2c_driver->i2c_device_id->name进行字符串匹配,如果匹配,就调用驱动程序的probe函数;

    继续回到i2c_register_driver函数
    int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
    {    
        /*        
        struct bus_type i2c_bus_type = {
            .name        = "i2c",
            .match        = i2c_device_match,
            .probe        = i2c_device_probe,
            .remove        = i2c_device_remove,
            .shutdown    = i2c_device_shutdown,
            .pm        = &i2c_device_pm_ops,
        };
        */
        ... ...
        driver->driver.bus = &i2c_bus_type;  //绑定总线
        ... ...
        res = driver_register(&driver->driver);    //向总线注册驱动
        ... ...
        /* 遍历I2C总线上的所有设备,调用__process_new_driver函数 */
        i2c_for_each_dev(driver, __process_new_driver);
    }
    
    分析i2c_for_each_dev(driver, __process_new_driver),进入i2c_for_each_dev函数
    int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
    {
        res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
    }

    进入bus_for_each_dev函数:
    int bus_for_each_dev(struct bus_type *bus, struct device *start,
             void *data, int (*fn)(struct device *, void *))
    {
        struct device *dev;
        /* 遍历I2C总线上所有的device,调用fn函数 */
        while ((dev = next_device(&i)) && !error)
            error = fn(dev, data);
    }
    bus_for_each_dev遍历总线上所有的device,调用fn函数,fn由i2c_for_each_dev传入的__process_new_driver函数

    进入__process_new_driver函数
    static int __process_new_driver(struct device *dev, void *data)
    {
        return i2c_do_add_adapter(data, to_i2c_adapter(dev));
    }
    
    进入i2c_do_add_adapter函数
    static int i2c_do_add_adapter(struct i2c_driver *driver,
                  struct i2c_adapter *adap)
    {
        /* 探测I2C总线上能支持的设备 */
        i2c_detect(adap, driver);

        /* Let legacy drivers scan this bus for matching devices */
        if (driver->attach_adapter) {
            driver->attach_adapter(adap);
        }
        return 0;
    }

    进入i2c_detect函数:
    static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
    {
        ......
        for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
            err = i2c_detect_address(temp_client, driver);
        }
    }

    进入i2c_detect_address函数
    static int i2c_detect_address(struct i2c_client *temp_client, struct i2c_driver *driver)
    {
        i2c_check_addr_validity(addr);

        i2c_check_addr_busy(adapter, addr);
            
        i2c_default_probe(adapter, addr);
        
        driver->detect(temp_client, &info);
    
        client = i2c_new_device(adapter, &info);
        list_add_tail(&client->detected, &driver->clients);
    }

I2C设备注册
    内核调用i2c_new_device完成I2C设备注册
    进入i2c_new_device函数:
    struct i2c_client *i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
    {
        struct i2c_client    *client; // i2c_client描述一个I2C设备
    
        client = kzalloc(sizeof *client, GFP_KERNEL);
        client->adapter = adap;    // I2C适配器
        client->dev.platform_data = info->platform_data;
        client->flags = info->flags;
        client->addr = info->addr;
        client->irq = info->irq;
        strlcpy(client->name, info->type, sizeof(client->name));
        i2c_check_client_addr_validity(client);
        i2c_check_addr_busy(adap, client->addr);
        client->dev.parent = &client->adapter->dev;
        client->dev.bus = &i2c_bus_type;
        client->dev.type = &i2c_client_type;
        client->dev.of_node = info->of_node;

        dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), client->addr);

        device_register(&client->dev);
        .......
    }
        
    进入device_register函数:
    int device_register(struct device *dev)
    {
        device_initialize(dev);
        device_add(dev);
    }

    进入device_add函数:
    int device_add(struct device *dev)
    {    
        bus_add_device(dev);     //将I2C设备加入I2C总线
        bus_probe_device(dev);    //为设备probe对应的驱动
    }

    进入bus_probe_device:
    void bus_probe_device(struct device *dev)
    {
        if (bus && bus->p->drivers_autoprobe) {
            ret = device_attach(dev);
        }
    }

    进入device_attach:
    int device_attach(struct device *dev)
    {
        bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
    }

    进入bus_for_each_drv:
    int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
             void *data, int (*fn)(struct device_driver *, void *))
    {
        struct device_driver *drv;;
        while ((drv = next_driver(&i)) && !error)
            fn(drv, data);
    }
    遍历driver链表,调用fn, fn为device_attach重调用bus_for_each_drv传入的__device_attach函数;

    进入__device_attach函数:
    static int __device_attach(struct device_driver *drv, void *data)
    {
        driver_match_device(drv, dev)
        driver_probe_device(drv, dev);
    }

    进入driver_match_device:
    static inline int driver_match_device(struct device_driver *drv,
                      struct device *dev)
    {
        // 调用i2c_bus_type的i2c_device_match函数,判断是否匹配
        drv->bus->match(dev, drv)
    }

    进入driver_probe_device:
    int driver_probe_device(struct device_driver *drv, struct device *dev)
    {
        ret = really_probe(dev, drv);
    }

    进入really_probe(dev, drv):
    static int really_probe(struct device *dev, struct device_driver *drv)
    {
        if (dev->bus->probe) {
            ret = dev->bus->probe(dev); //优先调用总线的probe函数
        } else if (drv->probe) {
            ret = drv->probe(dev);
        }
    }
    
    优先调用总线的probe函数,由总线定义:
    struct bus_type i2c_bus_type = {
        .name        = "i2c",
        .match        = i2c_device_match,
        .probe        = i2c_device_probe,
        .remove        = i2c_device_remove,
        .shutdown    = i2c_device_shutdown,
        .pm        = &i2c_device_pm_ops,
    };
    
    dev->bus->probe就是i2c_device_probe函数;
    
    进入i2c_device_probe函数
    static int i2c_device_probe(struct device *dev)
    {
        struct i2c_driver    *driver = to_i2c_driver(dev->driver);
        // 调用i2c驱动i2c_driver的probe函数
        status = driver->probe(client, i2c_match_id(driver->id_table, client));
    }

    最终调用driver的probe函数;

    通过i2c_register_board_info注册I2C设备,如在MINI2440Z中:
    
    MACHINE_START(MINI2440, "MINI2440")
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io        = mini2440_map_io,
        .init_machine    = mini2440_init,
        .init_irq    = s3c24xx_init_irq,
        .timer        = &s3c24xx_timer,
    MACHINE_END

    进入mini2440_init函数:
    static void __init mini2440_init(void)
    {
        i2c_register_board_info(0, mini2440_i2c_devs, ARRAY_SIZE(mini2440_i2c_devs));
    }

    进入i2c_register_board_info:
    int __init i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)
    {
        for (status = 0; len; len--, info++) {
            struct i2c_devinfo    *devinfo;
            devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
            devinfo->busnum = busnum;
            devinfo->board_info = *info;
            /* 将i2c_devinfo加入__i2c_board_list链表 */
            list_add_tail(&devinfo->list, &__i2c_board_list);
        }
    }

    __i2c_board_list调用的另一条线:
    __i2c_board_list在什么用?__i2c_board_list在i2c_scan_static_board_info函数中被使用;

    进入i2c_scan_static_board_info函数:
    static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
    {
        struct i2c_devinfo    *devinfo;
        list_for_each_entry(devinfo, &__i2c_board_list, list) {
            if (devinfo->busnum == adapter->nr
                    && !i2c_new_device(adapter,
                            &devinfo->board_info))
        }
    }
    循环遍历__i2c_board_list,调用i2c_new_device函数,最终还是调用i2c_new_device函数
    
    i2c_scan_static_board_info在哪里调用?i2c_scan_static_board_info在i2c_register_adapter函数被调用:
    
    进入i2c_register_adapter函数:
    static int i2c_register_adapter(struct i2c_adapter *adap)
    {        
        dev_set_name(&adap->dev, "i2c-%d", adap->nr);
        adap->dev.bus = &i2c_bus_type;
        adap->dev.type = &i2c_adapter_type;
        res = device_register(&adap->dev);

        // 注册I2C适配器到I2C总线,type为i2c_adapter_type
        device_register(&adap->dev);
    
        if (adap->nr < __i2c_first_dynamic_bus_num)
            i2c_scan_static_board_info(adap);

        bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
    }
    在i2c_register_adapter函数中同时调用了__process_new_adapter函数,与i2c_register_driver注册driver一样。
    也就是说,在注册I2C适配器的过程中,通过i2c_scan_static_board_info将静态注册的I2C设备调用i2c_new_device注册到I2C总线上,
    I2C设备注册完成后,在调用__process_new_adapter探测该适配器上所有地址,探测成功,调用i2c_new_device生成I2C设备,整个过程也就进入
    了上面的I2C设备注册过程。
    
    
    
    
    
    

    
        


            

你可能感兴趣的:(linux驱动,驱动开发,linux)