linux IICサブシステム分析(四)——I 2 c bus初期化

3739 ワード

ここでのI 2 C Busは通信上のバスではなく、linuxシステムがデバイスを管理し、駆動するために仮想化されており、I 2 C Busが後で使用するI 2 Cアダプタ(adapter)とI 2 Cデバイス(client)をマウントするために使用される.また、platform deviceとplatform driverを使用します.ここでi 2 c busはplatform busと同じタイプのバスではないことに注意してください.platform busはplatform driverとplatform deviceを管理するために使用されます.ここは混同しないでください.のlinuxシステム全体にplatform busが1つしかありません.カーネルの起動時に初期化されます.
start_kernel ->
rest_init ->
kernel_thread(システムプロセスの作成)->
kernel_init -> do_basic_setup -> 
driver_init -> platform_bus_init -> 
device_register(&platform_bus)
前章ではlinux iicサブシステムが最初に初期化されたのはi 2 c_であることを知っています.Init()関数、IIC Busはこの関数で初期化されています.
/dricer/i2c/i2c-core.c
static int __init i2c_init(void)
{
	int retval;

	retval = bus_register(&i2c_bus_type);                                (1.0)
	if (retval)
		return retval;
#ifdef CONFIG_I2C_COMPAT                                                     (2.0)
	i2c_adapter_compat_class = class_compat_register("i2c-adapter");     
	if (!i2c_adapter_compat_class) {
		retval = -ENOMEM;
		goto bus_err;
	}
#endif
	retval = i2c_add_driver(&dummy_driver);                               (3.0)
	if (retval)
		goto class_err;
	return 0;

class_err:
#ifdef CONFIG_I2C_COMPAT
	class_compat_unregister(i2c_adapter_compat_class);
bus_err:
#endif
	bus_unregister(&i2c_bus_type);
	return retval;
}

(1.0)bus経由_register()関数はIICバスを登録します.パラメータi 2 c_を見てみましょうbus_typeは、次のように定義されます.
struct bus_type i2c_bus_type = {
	.name		= "i2c",
	.match		= i2c_device_match,                 (1.1)
	.probe		= i2c_device_probe,                 (1.2)
	.remove		= i2c_device_remove,
	.shutdown	= i2c_device_shutdown,
	.suspend	= i2c_device_suspend,
	.resume		= i2c_device_resume,
};

(1.1)バスが提供するmatchメソッド:matchメソッドはdeviceとdriverのマッチングに使用され、バスにデバイスを登録したり駆動したりするときに呼び出されます.
関数は次のように定義されます.
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
	struct i2c_client	*client = i2c_verify_client(dev);            (1.1.0)
	struct i2c_driver	*driver;

	if (!client)
		return 0;                                                    (1.1.1)

	driver = to_i2c_driver(drv);
	/* match on an id table if there is one */
	if (driver->id_table)
		return i2c_match_id(driver->id_table, client) != NULL;       (1.1.2)

	return 0;
}

(1.1.0)struct i 2 c_でクライアントは、クライアントデバイスを指す特定のIICデバイスを記述する.(1.1.1)デバイスツリーでデバイスパラメータが検索されない場合は、直接戻ります.一致が失敗したことを示します.
(1.1.2)IIC駆動のid_tableが存在する場合はi 2 c_を使用match_idは関数をマッチングします.マッチする方法はid_を取ることですtableの各項目はclientのnameと一致し、名前が同じであれば一致に成功します.ここから、IICバスのマッチング方式はplatformバスのマッチング方式とは異なることがわかります.
IICバスは、デバイス名とドライバのid_に基づいてテーブルマッチング
platformバスは、デバイス名とデバイス駆動名に基づいてマッチングします.
(1.2)バスが提供するprobeメソッド:probeメソッドは、デバイスと駆動のペアリングが完了した後に実行を呼び出す.
static int i2c_device_probe(struct device *dev)
{
	struct i2c_client	*client = i2c_verify_client(dev);
	struct i2c_driver	*driver;
	int status;

	if (!client)
		return 0;

	driver = to_i2c_driver(dev->driver);
	if (!driver->probe || !driver->id_table)
		return -ENODEV;
	client->driver = driver;
	if (!device_can_wakeup(&client->dev))                                       (1.2.0)
		device_init_wakeup(&client->dev,
					client->flags & I2C_CLIENT_WAKE);
	dev_dbg(dev, "probe
"); status = driver->probe(client, i2c_match_id(driver->id_table, client)); (1.2.1) if (status) client->driver = NULL; return status; }

(1.2.0)IICの電源管理(1.2.1)IICデバイス駆動中のProbe関数を呼び出す
(2.0)CONFIG_I2C_COMPATというマクロは具体的にどのような役割を果たしているのか分からないので、理解していません.eepromを操作する過程で、マクロは定義されていません.
(3.0)ここでは虚偽のiic clientドライバを追加していますが、実際には何もしていません.なぜ定義するのか分かりません.