linux platformプラットフォームデバイス駆動
11099 ワード
一.プラットフォームバス
1. バス構造体
2.バスの初期化
3.paltform_matchメソッド
二.プラットフォームデバイス
1.プラットフォームデバイス構造体
2.プラットフォームデバイス登録
2.1プラットフォーム追加設備
2.2プラットフォーム設備の登録は一般的にBoard-xxxに置く.cプレートレベル駆動中
複数のプラットフォーム・デバイスの登録が必要な場合は、次のように配列を定義できます.
そしてそのプレートレベルで駆動する.init_machineが指定した初期化関数には、次のように登録されています.
2.3 platform_の使用add_デバイスは複数のプラットフォームデバイスを同時に登録する
2.4プラットフォームデバイス動的作成platform_device_alloc
3.プラットフォームデバイスのログアウト
三.プラットフォーム駆動
1.プラットフォーム駆動構造体
2.プラットフォームドライバ登録
2.1 platform_drv_probe
2.2 platform_drv_remove
2.3 platform_drv_shutdown
2.4プラットフォーム駆動は対応する駆動ディレクトリの下に置く
プラットフォーム駆動とプラットフォーム設備のnameドメインは、プラットフォームバスにmatchをマッチングするために同じであるべきであり、プラットフォーム駆動のprobeメソッドを呼び出す.
プラットフォームリソースの取得は一般的にprobeメソッドに置かれ、platform_を使用する.get_义齿
2.5上記プラットフォーム駆動登録方式は、ホットスワップ対応機器用platform_driver_probe登録
3. プラットフォーム駆動ログアウト
四.プラットフォームリソース
1.しげんこうぞうたい
1.1一般的なリソースのタイプは次のとおりです.
1.2プラットフォーム資源の取得パラメータは:資源が所属するプラットフォーム設備、資源を取得するタイプ、取得した資源個数
1. バス構造体
struct bus_type platform_bus_type = {
.name = "platform", //
.dev_attrs = platform_dev_attrs, //
.match = platform_match, //
.uevent = platform_uevent, //
.pm = &platform_dev_pm_ops, //
};
2.バスの初期化
int __init platform_bus_init(void)
{
int error;
early_platform_cleanup();
error = device_register(&platform_bus); //
if (error)
return error;
error = bus_register(&platform_bus_type); //
if (error)
device_unregister(&platform_bus);
return error;
}
3.paltform_matchメソッド
static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev); //
struct platform_driver *pdrv = to_platform_driver(drv); //
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv)) // ?
return 1;
/* Then try to match against the id table */
if (pdrv->id_table) //id ?
return platform_match_id(pdrv->id_table, pdev) != NULL;
/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0); //
}
二.プラットフォームデバイス
1.プラットフォームデバイス構造体
struct platform_device {
const char * name; //
int id; // id
struct device dev; //
u32 num_resources; //
struct resource * resource; //
const struct platform_device_id *id_entry;
/* arch specific additions */
struct pdev_archdata archdata;
};
2.プラットフォームデバイス登録
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev);
return platform_device_add(pdev);
}
2.1プラットフォーム追加設備
int platform_device_add(struct platform_device *pdev)
{
int i, ret = 0;
if (!pdev)
return -EINVAL;
if (!pdev->dev.parent)
pdev->dev.parent = &platform_bus; //
pdev->dev.bus = &platform_bus_type; //
if (pdev->id != -1) //
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
else
dev_set_name(&pdev->dev, "%s", pdev->name);
for (i = 0; i < pdev->num_resources; i++) { //
struct resource *p, *r = &pdev->resource[i];
if (r->name == NULL)
r->name = dev_name(&pdev->dev);
p = r->parent;
if (!p) {
if (resource_type(r) == IORESOURCE_MEM)
p = &iomem_resource;
else if (resource_type(r) == IORESOURCE_IO)
p = &ioport_resource;
}
if (p && insert_resource(p, r)) {
printk(KERN_ERR
"%s: failed to claim resource %d
",
dev_name(&pdev->dev), i);
ret = -EBUSY;
goto failed;
}
}
pr_debug("Registering platform device '%s'. Parent at %s
",
dev_name(&pdev->dev), dev_name(pdev->dev.parent));
ret = device_add(&pdev->dev); //
if (ret == 0)
return ret;
failed:
while (--i >= 0) {
struct resource *r = &pdev->resource[i];
unsigned long type = resource_type(r);
if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
release_resource(r);
}
return ret;
}
2.2プラットフォーム設備の登録は一般的にBoard-xxxに置く.cプレートレベル駆動中
複数のプラットフォーム・デバイスの登録が必要な場合は、次のように配列を定義できます.
static struct platform_device platform_device_1 = {
.name = "paltform_1",
.id = -1, // id -1
.num_resources = 0,
.dev = {
.platform_data = &paltform_1_pdata,
}
};
static struct platform_device platform_device_2 = {
.name = "paltform_2",
.id = -1,
.resource = &paltform_2_resource, //
.num_resources = 1, //
};
....
static struct platform_device *test_devices[] __initdata = {
&platform_device_1,
&platform_device_2,
&platform_device_3,
};
そしてそのプレートレベルで駆動する.init_machineが指定した初期化関数には、次のように登録されています.
//
platform_device_register(&platform_device_1);
platform_device_register(&platform_device_2);
platform_device_register(&platform_device_3);
//
platform_add_devices(test_devices,ARRAY_SIZE(test_devices))
2.3 platform_の使用add_デバイスは複数のプラットフォームデバイスを同時に登録する
int platform_add_devices(struct platform_device **devs, int num)
{
int i, ret = 0;
for (i = 0; i < num; i++) {
ret = platform_device_register(devs[i]); // platform_device_register
if (ret) {
while (--i >= 0)
platform_device_unregister(devs[i]);
break;
}
}
return ret;
}
2.4プラットフォームデバイス動的作成platform_device_alloc
struct platform_device *platform_device_alloc(const char *name, int id)
{
struct platform_object *pa;
pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
if (pa) {
strcpy(pa->name, name);
pa->pdev.name = pa->name; // .name
pa->pdev.id = id; // .id
device_initialize(&pa->pdev.dev);
pa->pdev.dev.release = platform_device_release;
}
return pa ? &pa->pdev : NULL;
}
3.プラットフォームデバイスのログアウト
void platform_device_unregister(struct platform_device *pdev)
{
platform_device_del(pdev);
platform_device_put(pdev);
}
三.プラットフォーム駆動
1.プラットフォーム駆動構造体
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver; //
const struct platform_device_id *id_table; // id
};
2.プラットフォームドライバ登録
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type; //
if (drv->probe)
drv->driver.probe = platform_drv_probe; // probe
if (drv->remove)
drv->driver.remove = platform_drv_remove; // remove
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown; // shutdown
return driver_register(&drv->driver); //
}
2.1 platform_drv_probe
static int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver); //
struct platform_device *dev = to_platform_device(_dev); //
return drv->probe(dev); // probe
}
2.2 platform_drv_remove
static int platform_drv_remove(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver); //
struct platform_device *dev = to_platform_device(_dev); //
return drv->remove(dev); // remove
}
2.3 platform_drv_shutdown
static void platform_drv_shutdown(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver); //
struct platform_device *dev = to_platform_device(_dev); //
drv->shutdown(dev); // shutdown
}
2.4プラットフォーム駆動は対応する駆動ディレクトリの下に置く
プラットフォーム駆動とプラットフォーム設備のnameドメインは、プラットフォームバスにmatchをマッチングするために同じであるべきであり、プラットフォーム駆動のprobeメソッドを呼び出す.
プラットフォームリソースの取得は一般的にprobeメソッドに置かれ、platform_を使用する.get_义齿
2.5上記プラットフォーム駆動登録方式は、ホットスワップ対応機器用platform_driver_probe登録
int __init_or_module platform_driver_probe(struct platform_driver *drv,int (*probe)(struct platform_device *))
{
int retval, code;
/* make sure driver won't have bind/unbind attributes */
drv->driver.suppress_bind_attrs = true;
/* temporary section violation during probe() */
drv->probe = probe; // probe probe , probe
retval = code = platform_driver_register(drv);
/*
* Fixup that section violation, being paranoid about code scanning
* the list of drivers in order to probe new devices. Check to see
* if the probe was successful, and make sure any forced probes of
* new devices fail.
*/
spin_lock(&drv->driver.bus->p->klist_drivers.k_lock);
drv->probe = NULL;
if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
retval = -ENODEV;
drv->driver.probe = platform_drv_probe_fail;
spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock);
if (code != retval)
platform_driver_unregister(drv);
return retval;
}
3. プラットフォーム駆動ログアウト
void platform_driver_unregister(struct platform_driver *drv)
{
driver_unregister(&drv->driver);
}
四.プラットフォームリソース
1.しげんこうぞうたい
struct resource {
resource_size_t start; //
resource_size_t end; //
const char *name; //
unsigned long flags; //
struct resource *parent, *sibling, *child;
};
1.1一般的なリソースのタイプは次のとおりです.
#define IORESOURCE_IO 0x00000100 //io
#define IORESOURCE_MEM 0x00000200 //
#define IORESOURCE_IRQ 0x00000400 //
1.2プラットフォーム資源の取得パラメータは:資源が所属するプラットフォーム設備、資源を取得するタイプ、取得した資源個数
struct resource *platform_get_resource(struct platform_device *dev,unsigned int type, unsigned int num)
{
int i;
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
if (type == resource_type(r) && num-- == 0)
return r;
}
return NULL;
}