I2C_BOARD_INFO{} / i2c_register_board_info() / i2c_match_id() / probe()

来源:互联网 发布:js什么是原型 编辑:程序博客网 时间:2024/06/18 17:41

 233/**

234  * struct i2c_board_info - template for device creation235  * @type: chip type, to initialize i2c_client.name236  * @flags: to initialize i2c_client.flags237  * @addr: stored in i2c_client.addr238  * @platform_data: stored in i2c_client.dev.platform_data239  * @archdata: copied into i2c_client.dev.archdata240  * @of_node: pointer to OpenFirmware device node241  * @irq: stored in i2c_client.irq242  *243  * I2C doesn't actually support hardware probing, although controllers and244  * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's245  * a device at a given address.  Drivers commonly need more information than246  * that, such as chip type, configuration, associated IRQ, and so on.247  *248  * i2c_board_info is used to build tables of information listing I2C devices249  * that are present.  This information is used to grow the driver model tree.250  * For mainboards this is done statically using i2c_register_board_info();251  * bus numbers identify adapters that aren't yet available.  For add-on boards,252  * i2c_new_device() does this dynamically with the adapter already known.253  */254 struct i2c_board_info {255         char            type[I2C_NAME_SIZE];256         unsigned short  flags;257         unsigned short  addr;258         void            *platform_data;259         struct dev_archdata     *archdata;260         struct device_node *of_node;261         int             irq;262 };263 264 /**265  * I2C_BOARD_INFO - macro used to list an i2c device and its address266  * @dev_type: identifies the device type267  * @dev_addr: the device's address on the bus.268  *269  * This macro initializes essential fields of a struct i2c_board_info,270  * declaring what has been provided on a particular board.  Optional271  * fields (such as associated irq, or device-specific platform_data)272  * are provided using conventional syntax.273  */274 #define I2C_BOARD_INFO(dev_type, dev_addr) \275         .type = dev_type, .addr = (dev_addr)


Probe方式(new style)

●    构建i2c_driver

和LEGACY方式一样,也需要构建i2c_driver,但是内容有所不同。

static struct i2c_driver pca953x_driver = {
                .driver = {
                        .name= "pca953x",
                        },
                        .probe= pca953x_probe, //当有i2c_client和i2c_driver匹配时调用
                        .remove= pca953x_remove,//注销时调用
                        .id_table= pca953x_id,//匹配规则
        };

●    注册i2c_driver

static int __init pca953x_init(void)
        {
                return i2c_add_driver(&pca953x_driver);
        }
        module_init(pca953x_init);

在注册i2c_driver的过程中,是将driver注册到了i2c_bus_type的总线上。此总线的匹配规则是:

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

可以看出是利用i2c_client的名称和id_table中的名称做匹配的。本驱动中的id_table为

static conststruct i2c_device_idpca953x_id[] = {
                { "pca9534", 8, },
                { "pca9535", 16, },
                { "pca9536", 4, },
                { "pca9537", 4, },
                { "pca9538", 8, },
                { "pca9539", 16, },
                { "pca9554", 8, },
                { "pca9555", 16, },
                { "pca9557", 8, },
                { "max7310", 8, },
                { }
        };

看到现在我们应该会有这样的疑问,在Adapter模式中,i2c_client是我们自己构造出来的,而现在的i2c_client是从哪来的呢?看看下面的解释

●    注册i2c_board_info

对于Probe模式,通常在平台代码中要完成i2c_board_info的注册。方法如下:

static struct i2c_board_info__initdata test_i2c_devices[] = {
                {
                        I2C_BOARD_INFO("pca9555", 0x27),//pca9555为芯片名称,0x27为芯片地址
                        .platform_data = &pca9555_data,
                }, 

     {
                        I2C_BOARD_INFO("mt9v022", 0x48),
                        .platform_data = &iclink[0], /* With extender */
                }, 

     {
                        I2C_BOARD_INFO("mt9m001", 0x5d),
                        .platform_data = &iclink[0], /* With extender */
                },
        };
        i2c_register_board_info(0, test_i2c_devices,ARRAY_SIZE(test_i2c_devices)); //注册

i2c_client就是在注册过程中构建的。但有一点需要注意的是i2c_register_board_info并没有EXPORT_SYMBOL给模块使用。

●    字符驱动注册

在Probe方式下,添加字符驱动的位置在pca953x_probe中。

static int __devinit pca953x_probe(struct i2c_client *client,const struct i2c_device_id *id)
        {
                        ……
                        /****字符设备驱动注册位置****/
                        ……
                        return 0;
        }

●    注销i2c_driver

static void __exit pca953x_exit(void)
        {
                i2c_del_driver(&pca953x_driver);
        }
        module_exit(pca953x_exit);

●    注销字符设备驱动

在Probe方式下,注销字符驱动的位置在pca953x_remove中。

static int __devinit pca953x_remove (struct i2c_client *client)
        {
                ……
                /****字符设备驱动注销的位置****/
                ……
                return 0;
        }

●    I2C设备的数据交互方法(即:调用适配器操作设备的方法)和Adapter方式下相同。

I2C_BOARD_INFO{}

Name

I2C_BOARD_INFO — macro used to list an i2c device and its address

Synopsis

I2C_BOARD_INFO ( dev_type,  dev_addr);

Arguments

dev_type

identifies the device type

dev_addr

the device's address on the bus.

Description

This macro initializes essential fields of a struct i2c_board_info, declaring what has been provided on a particular board. Optional fields (such as associated irq, or device-specific platform_data) are provided using conventional syntax.


i2c_register_board_info()

Name

i2c_register_board_info — statically declare I2C devices

Synopsis

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

Arguments

busnum

identifies the bus to which these devices belong

info

vector of i2c device descriptors

len

how many descriptors in the vector; may be zero to reserve the specified bus number.

Description

Systems using the Linux I2C driver stack can declare tables of board info while they initialize. This should be done in board-specific init code near arch_initcall time, or equivalent, before any I2C adapter driver is registered. For example, mainboard init code could define several devices, as could the init code for each daughtercard in a board stack.

The I2C devices will be created later, after the adapter for the relevant bus has been registered. After that moment, standard driver model tools are used to bind “new style” I2C drivers to the devices. The bus number for any device declared using this routine is not available for dynamic allocation.

The board info passed can safely be __initdata, but be careful of embedded pointers (for platform_data, functions, etc) since that won't be copied.