Linux I2C 子系統採用三層架構:I2C 核心、I2C 總線驅動(適配器)、I2C 裝置驅動(客戶端)。本文系統剖析架構分工、四大核心資料結構(i2c_adapter、i2c_algorithm、i2c_driver、i2c_client)、核心原始碼組織、sysfs 介面,並提供驅動開發模板與 S3C2410/SAA7113H 實戰案例。
| 層級 | 核心檔案 | 職責 |
|---|---|---|
| I2C 核心 | i2c-core.c | 適配器/客戶端註冊登記、通用演算法、裝置探測、/proc/bus/i2c* 介面 |
| I2C 總線驅動 | busses/i2c-xxx.c | 實作硬體適配器操作:i2c_adapter、i2c_algorithm、產生 START/STOP/ACK 等時序訊號 |
| I2C 裝置驅動 | chips/xxx.c | 實作特定晶片操作:i2c_driver、i2c_client、讀寫暫存器、裝置初始化 |
struct i2c_adapter {
struct module *owner;
unsigned int id; // 演算法類型 (I2C_ALGO_*)
unsigned int class;
struct i2c_algorithm *algo; // 傳輸演算法指標
void *algo_data; // 演算法私有資料
int (*client_register)(struct i2c_client *);
int (*client_unregister)(struct i2c_client *);
struct semaphore bus_lock; // 並發鎖
struct semaphore clist_lock;
int timeout;
int retries;
struct device dev; // sysfs 裝置
struct class_device class_dev;
int nr;
struct list_head clients; // 掛載的 client 鏈表
struct list_head list;
};
struct i2c_algorithm {
int (*master_xfer)(struct i2c_adapter *, struct i2c_msg *, int); // 主機傳輸
int (*smbus_xfer) (struct i2c_adapter *, struct i2c_smbus_ioctl_data *); // SMBus
u32 (*functionality)(struct i2c_adapter *); // 支援功能位圖
};
struct i2c_driver {
int (*attach_adapter)(struct i2c_adapter *); // 掃描裝置
int (*detach_client)(struct i2c_client *); // 移除裝置
int (*command)(struct i2c_client *, unsigned int, void *); // Ioctl 類命令
struct device_driver driver;
struct list_head list;
};
struct i2c_client {
unsigned short flags;
unsigned short addr; // 7-bit 位址
struct i2c_adapter *adapter; // 所屬適配器
struct i2c_driver *driver; // 綁定的驅動
struct device dev; // sysfs 裝置
struct list_head list;
char name[I2C_NAME_SIZE];
};
i2c-core.c:核心邏輯、/proc/bus/i2c*i2c-dev.c:用戶空間介面(/dev/i2c-N),提供 read/write/ioctl 通用存取chips/:特定晶片驅動(EEPROM、RTC、感測器等)busses/:控制器驅動(i2c-s3c2410.c 等)algos/:通用演算法實作(位元撥動、硬體控制器等)核心 2.6+ 所有 I2C 裝置出現在 /sys/bus/i2c/:
/sys/bus/i2c/
|-- devices
| |-- 0-0048 -> ../../../devices/legacy/i2c-0/0-0048
| `-- ...
`-- drivers
|-- i2c_adapter
`-- lm75
|-- 0-0048 -> ...
`-- ...
命名規則:adapter_addr-addr(如 0-0048 表示適配器 0、位址 0x48)。
i2c_algorithm 實作 master_xferi2c_adapter,指向 algoi2c_add_adapter(&adapter) 註冊i2c_driver,實作 attach_adapter(呼叫 i2c_probe() 掃描)i2c_add_driver(&driver) 註冊i2c_client,i2c_attach_client()i2c_master_send/recv() 或 i2c_transfer() 通訊i2c-s3c2410.c 實作 S3C2410 I2C 控制器寄存器操作chips/saa7113h.c 實作視訊解碼器初始化、暫存器配置i2c_board_info 靜態註冊裝置位址