ドライバの登録 (platform_driver_register)

ドライバの登録とは

 ドライバの登録は、ドライバをLinux OSに登録し、コールバック関数を呼び出してもらう為の処理です。4章の「ドライバの初期化処理について」の「driverとしての初期化」で始めに出てきたplatform_driver_registerが、ドライバを登録する為の関数となり、これについて使い方と動作について説明します。

使い方

 platform_driver_registerについては「kernel/mediatek/4.4/Documentation/driver-model/platform.txt」 に簡単な説明があります。以下に抜粋を記載します。

Platform drivers
~~~~~~~~~~~~~~~~
Platform drivers follow the standard driver model convention, where discovery/enumeration is handled outside the drivers, 
and drivers provide probe() and remove() methods. 

They support power management and shutdown notifications using the standard conventions.

Platform drivers register themselves the normal way:
	int platform_driver_register(struct platform_driver *drv);
プラットフォームドライバー
~~~~~~~~~~~~~~~~
プラットフォーム・ドライバは標準的なドライバ・モデルの慣習に従っており、ディスカバリ/列挙はドライバの外部で処理され、ドライバは probe() と remove() メソッドを提供します。

ドライバは、標準的な規約を使用して、電源管理とシャットダウン通知をサポートします。

プラットフォーム・ドライバは通常の方法で登録する:
	int platform_driver_register(struct platform_driver *drv);

コールバック関数等を登録した構造体である、struct platform_driver型のポインタを引数に取る事でドライバの登録ができます。近接照度センサドライバでは以下で呼び出されています。

kernel/mediatek/4.4/drivers/misc/mediatek/sensors-1.0/alsps/alsps.c

if (platform_driver_register(&als_ps_driver))

引数であるals_ps_driverは以下の通り定義されています。

static struct platform_driver als_ps_driver = {
	.probe	  = als_ps_probe,
	.remove	 = als_ps_remove,
	.driver = {

		.name  = "als_ps",
	#ifdef CONFIG_OF
		.of_match_table = als_ps_of_match,
		#endif
	}
};

probeに登録しているals_ps_probe関数が、登録完了後に呼び出されるコールバック関数となり、ドライバ登録完了後、以下のreally_probe関数によりLinuxカーネルから呼び出されます。

kernel/mediatek/4.4/drivers/base/dd.c

static int really_probe(struct device *dev, struct device_driver *drv)
{
	int ret = -EPROBE_DEFER;
	int local_trigger_count = atomic_read(&deferred_trigger_count);
#ifdef CONFIG_MTPROF
	unsigned long long ts = 0;
#endif

	if (defer_all_probes) {
		/*
		 * Value of defer_all_probes can be set only by
		 * device_defer_all_probes_enable() which, in turn, will call
		 * wait_for_device_probe() right after that to avoid any races.
		 */
		dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
		driver_deferred_probe_add(dev);
		return ret;
	}

	atomic_inc(&probe_count);
	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
		 drv->bus->name, __func__, drv->name, dev_name(dev));
	WARN_ON(!list_empty(&dev->devres_head));

	dev->driver = drv;

	/* If using pinctrl, bind pins now before probing */
	ret = pinctrl_bind_pins(dev);
	if (ret)
		goto probe_failed;

	if (driver_sysfs_add(dev)) {
		printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
			__func__, dev_name(dev));
		goto probe_failed;
	}

	if (dev->pm_domain && dev->pm_domain->activate) {
		ret = dev->pm_domain->activate(dev);
		if (ret)
			goto probe_failed;
	}

	if (dev->bus->probe) {
		TIME_LOG_START();
		ret = dev->bus->probe(dev);
		TIME_LOG_END();
		bootprof_probe(ts, dev, drv, (unsigned long)dev->bus->probe);
		if (ret)
			goto probe_failed;
	} else if (drv->probe) {
		TIME_LOG_START();
		ret = drv->probe(dev);
		TIME_LOG_END();
		bootprof_probe(ts, dev, drv, (unsigned long)drv->probe);
		if (ret)
			goto probe_failed;
	}

最後に

 基本的には、als_ps_driverのprobe処理であるals_ps_probeにdriverの初期化処理を記載するのが一般的ですが、本ドライバにおいては、4章の「ドライバの初期化処理について」で説明した通り、処理をあまりしておりません。

 また、platform_driver構造体のshutdownに登録しているコールバック関数は電源OFF時に
kernel/mediatek/4.4/drivers/base/core.c」のdevice_shutdown関数によりLinuxカーネルから呼び出されます。このshutdown処理で、リセットが起きると電源OFFがリセットに代わり、フリーズが起きるとリセットによる復旧もできなくなるので注意が必要です。

コメント

タイトルとURLをコピーしました