i 2 cサブシステムのplatfor_デバイス初期化-smdk 2440_machine_init()


呼び出し完了関数i 2 c_Init後、i 2 cバスの作成に成功します.バスを初期化した後、i 2 cデバイスとi 2 cドライバを初期化する必要がある(一般的にはdeviceを初期化する)、
2440の場合、linuxカーネルのdevice初期化は一般的にplatform deviceによって初期化され、platform deviceの初期化は
/arch/arm/mach-s3c2440/mach-smdk2440.cファイルのsmdk 2440_machine_Init()関数で完了します.
で行ないます.次のようになります.
static void __init smdk2440_machine_init(void)
{
	... ...
	s3c_i2c0_set_platdata(NULL);

	i2c_register_board_info(0, tq2440_i2c_devs,
				ARRAY_SIZE(tq2440_i2c_devs));
	platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
	... ...
}

smdk2440_machine_Initとi 2 cに関する関数は3つです.注意すべきは、ここのi 2 c_register_board_info()関数
後で追加されていない場合は、オリジナルカーネルではこの関数は呼び出されません.ブロガーはmini 2440を参照して、この関数を呼び出す必要があることを決定し、後で分析します.
話の後でまず3つの関数の基本的な機能を上訴して、更にソースコードの分析を行います.
1.s3c_i2c_set_platdata.構築platform_デバイス型デバイスs 3 c_device_i2c0.
2.i2c_register_board_info.ボードに関連するi 2 cデバイス情報をi 2 cデバイスに統一的に登録する
スペアチェーン_i2c_board_リスト上.ここではat 24 c 02の関連パラメータです.
3.platform_add_device.前に作成したplatform_デバイス型デバイスs 3 c_device_i2c0
platform_に追加busバス.
以下、上記3つの関数について順次ソースコード解析を行う.
1.s3c_i2c0_set_platdata
3c_i2c0_set_platdata関数は次のとおりです.
void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
{
	struct s3c2410_platform_i2c *npd;

	if (!pd)
		pd = &default_i2c_data0;

	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
	if (!npd)
		printk(KERN_ERR "%s: no memory for platform data
", __func__); else if (!npd->cfg_gpio) npd->cfg_gpio = s3c_i2c0_cfg_gpio; s3c_device_i2c0.dev.platform_data = npd; }

この関数はまずpdが真であると判断する
	if (!pd)
		pd = &default_i2c_data0;

そしてdefault_i2c_data 0はpdに付与する
static struct s3c2410_platform_i2c default_i2c_data0 __initdata = {
	.flags		= 0,
	.slave_addr	= 0x50,
	.frequency	= 100*1000,
	.sda_delay	= 100,
};
        npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
	
        。。。 。。。

	s3c_device_i2c0.dev.platform_data = npd;
実装default_i2c_data 0の値はs 3 c_に保存されますdevice_i 2 c 0のdev.platform_データ下
struct platform_device s3c_device_i2c0 = {
	.name		  = "s3c2410-i2c",
#ifdef CONFIG_S3C_DEV_I2C1
	.id		  = 0,
#else
	.id		  = -1,
#endif
	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
	.resource	  = s3c_i2c_resource,
};
この時点s 3 c_device_i2c0.dev.platform_dataにslave_を保存addr、frequencyなどの情報.
s 3 c 24 xx_i2c_Probe関数では、3 c 2440のi 2 c関連制御レジスタの初期化操作が
これらのパラメータは関連レジスタに入力されます.ここで特筆すべきはname変数であり,name変数の初期付与値はs 3 c 2410−i 2 cである.
しかし、後の/arch/arm/mach-s 3 c 2440/s 3 c 24 xxになる.cファイルの関数s 3 c 244 x_map_io()でs 3 c 2440-i 2 cに変更します.
この関数の役割は、s 3 c 2410とは異なる周辺機器を修正するために使用される.
2.i2c_register_board_info
パラメータ:
static struct i2c_board_info tq2440_i2c_devs[] __initdata = {
	{
		I2C_BOARD_INFO("24c02", 0x50),
		.platform_data = &at24c02,
	},
};
static struct at24_platform_data at24c02 = {
	.byte_len	= SZ_2K / 8,
	.page_size	= 8,
};

関数:
int __init
i2c_register_board_info(int busnum,
	struct i2c_board_info const *info, unsigned len)
{
	... ...
	/* dynamic bus numbers will be assigned after the last static one */
	if (busnum >= __i2c_first_dynamic_bus_num)
		__i2c_first_dynamic_bus_num = busnum + 1;

	for (status = 0; len; len--, info++) {
		struct i2c_devinfo	*devinfo;

		devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
                ... ...
		devinfo->busnum = busnum;
		devinfo->board_info = *info;
		list_add_tail(&devinfo->list, &__i2c_board_list);
	}
       ... ...
}

この関数は、ボード上のi 2 cのデバイス情報、例えば容量、型番、アドレスなどを_に掛けることを完了します.i2c_board_リストチェーンテーブルにあります.
後でクライアントを初期化するときにチェーンテーブルから取り外し、これらの情報に基づいてクライアントを初期化します.
ここで注意が必要です
	if (busnum >= __i2c_first_dynamic_bus_num)
		__i2c_first_dynamic_bus_num = busnum + 1;

これによりi 2 c_first_dynamic_numの数値はbusnumより大きく,後でprobe関数の解析でこの数値を用いる必要がある.
具体的な_i2c_first_dynamic_bus_num分析参考博文.
3.platform_add_devices
関数パラメータ:
static struct platform_device *smdk2440_devices[] __initdata = {
        。。。 。。。
	&s3c_device_i2c0,
	。。。 。。。
};
ここでplatform_add_デバイスはplatform_デバイス型デバイスs 3 c_device_i2c0
platform_に追加bus上.
具体的なplatform_add_deviceプロセスはネット上の文章を参照します.
まとめ
カーネルはまず関数s 3 cを通過するi2c0_set_platdataはplatformを構築するデバイスタイプのデバイスs 3 c_device_i2c0,
そのうちs 3 c_device_i 2 c 0は、s 3 c 2440上のi 2 c関連レジスタのアドレスと、i 2 cクロックラインに必要なアドレスリソースを含む
のクロック周波数、i 2 cデバイスのスレーブアドレスなどの情報、すなわちシステムi 2 cコントローラの情報を取得する.i 2 c_経由register_board_info
関数は、i 2 cデバイスat 24 c 02をカーネルのi 2 cデバイスチェーンテーブルに登録し、clientの作成を待つときにこれらの情報を使用する.最後の呼び出し
platform_add_デバイスはplatform_デバイスs 3 c_device_i 2 c 0 platform_に登録busバスで、その時に必要です.
これらの情報を使用してi 2 c adapterを初期化します.