根據自己的理解翻譯了http://lxr.linux.no/linux+v2.6.34/Documentation/i2c/instantiating-devices 中關於枚舉建立i2c_client的文檔。有異議或疑問請參照原文,畢竟內核的文檔纔是真正的精華。
方法1:使用總線號聲明設備。
- static struct i2c_board_info __initdata h4_i2c_board_info[] = {
- {
- I2C_BOARD_INFO("isp1301_omap",0x2d),
- .irq = OMAP_GPIO_IRQ(125),
- },
- { /* EEPROM on mainboard */
- I2C_BOARD_INFO("24c01", 0x52),
- .platform_data = &m24c01,
- },
- { /* EEPROM on cpu card */
- I2C_BOARD_INFO("24c01", 0x57),
- .platform_data = &m24c01,
- },
- };
- static void __init omap_h4_init(void)
- {
- (...)
- i2c_register_board_info(1,h4_i2c_board_info,
- ARRAY_SIZE(h4_i2c_board_info));
- (...)
- }
- Example (from the pnx4008 OHCI driver):
- static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
- static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
- {
- (...)
- struct i2c_adapter *i2c_adap;
- struct i2c_board_info i2c_info;
- (...)
- i2c_adap = i2c_get_adapter(2);
- memset(&i2c_info, 0, sizeof(struct i2c_board_info));
- strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
- isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
- normal_i2c);
- i2c_put_adapter(i2c_adap);
- (...)
- }
i2c_new_probed_device的原型是:
struct
i2c_client * i2c_new_probed_device(struct i2c_adapter *adap,struct i2c_board_info *info,unsigned short const *addr_list);
這個函數將會在指定的總線上探測addr_list中的地址,將第一個有ACK反饋的地址賦給info->addr 然後使用前兩個參數調用i2c_new_device。它的返回值也是一個可用的i2c_client指針。 i2c_unregister_device() 可以註銷 i2c_new_device()/i2c_new_probed_device()申請的i2c_client。
補充:驅動開發者如何知道一個物理i2c總線的編號?
[root@zlg /]# cat /sys/class/i2c-dev/i2c-0/name
PNX4008-I2C0
[root@zlg /]# cat /sys/class/i2c-dev/i2c-1/name
PNX4008-I2C1
[root@zlg /]# cat /sys/class/i2c-dev/i2c-2/name
USB-I2C
方法3:在所有i2c總線上探測特定設備
內核文檔中關於方法2的限制及方法3的好處我沒看懂。說一下自己的理解,那就是方法2雖然可以探測多個地址,但是僅僅能在一個指定的總線上探測,並且探測到第一個可用的地址就停止探測了。如果之前並不確定總線的編號,或者一次探測多個i2c設備,就需要用到方法3了。實現方法3需要兩個條件:******實現i2c_driver的detect成員。這個成員函數原型是:
int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *);
這個函數必須檢查第二個參數的addr域是否自己支持的地址,是的話則至少填充info->type,info的其它成員也可以填充,但不應該修改addr。
如果是就返回0,否則返回-ENODEV。
******初始化i2c_driver的
address_list成員。i2c_driver註冊的時候,i2c_core會在所有已經註冊的i2c_adapter上探測
address_list中的所有地址,硬件探測成功之後後調用i2c_driver的detect成員,然後根據detect填充的info建立一個i2c_client。如果兩個總線上有相同的地址的設備,那麼會分別建立兩個i2c_client。如果
address_list中的多個地址都有設備佔用,那麼會建立多個i2c_client。
或許因爲方法3太過於強大和靈活,內核文檔不推薦這種方法。優先選用方法1和2。
方法4:從用戶控件枚舉。如果編寫驅動的時候實在無法知道i2c設備的地址(連可能的地址列表也不知道),那就需要系統運行後從用戶空間輸入了。
用戶空間通過兩個sysfs屬性文件來建立和刪除i2c_client:new_device和delete_device。這兩個文件都是隻寫的。
new_device有兩個參數:i2c設備的名字(字符串)和地址(以0x開頭的16進制數)。
delete_device只有一個參數,那就是設備的地址。
舉例:
# echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device可以看到,此時已經指定了總線編號。
補充--方法5 :在i2c_driver中的attach_adapter中調用i2c_new_device()或者i2c_new_probed_device()
這個方法色實質和方法2類似。
這樣的例子在2.6.34內核的/sound/ppc/keywest.c中,可以參考。
i2c_driver和i2c_client的總線類型均爲i2c_bus_type,i2c_client的name成員(對應info->type)和i2c_driver中的id_table中的名字 是它們相互綁定的依據。
不同的 i2c_adapter上可以掛靠相同地址的設備,但是i2c設備的名字是全局的,因此不同設備的名字不要相同。(並不是不能相同)。
轉自:http://blog.csdn.net/newger/article/details/6571740