ARM linux PLATFORM 设备注册
static struct platform_driver power_driver = {
.driver.name = "power",
.suspend_late = power_suspend_late,
};
static struct platform_device power_device = {
.name = "power",
};
static int __init wakelocks_init(void)
{
ret = platform_device_register(&power_device);
if (ret) {
pr_err("wakelocks_init: platform_device_register failed/n");
goto err_platform_device_register;
}
ret = platform_driver_register(&power_driver);
;
;
}
设备注册到总线
struct platform_device pxa_device_fb = {
.name= "pxa2xx-fb",
.id= -1,
.dev= {
.dma_mask= &fb_dma_mask,
.coherent_dma_mask = 0xffffffff,
},
.num_resources= ARRAY_SIZE(pxafb_resources),
.resource= pxafb_resources,
};
void __init set_pxa_fb_info(struct pxafb_mach_info *info)
{
pxa_register_device(&pxa_device_fb, info);
}
void __init pxa_register_device(struct platform_device *dev, void *data)
{
int ret;
dev->dev.platform_data = data;
ret = platform_device_register(dev);
if (ret)
dev_err(&dev->dev, "unable to register device: %d/n", ret);
}
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev);
return platform_device_add(pdev);
}
int platform_device_add(struct platform_device *pdev)
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, 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/n",
dev_name(&pdev->dev), i);
ret = -EBUSY;
goto failed;
}
}
pr_debug("Registering platform device '%s'. Parent at %s/n",
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;
}
驱动注册到总线
static int __devinit pxafb_init(void)--------> Pxafb.c (kernel/drivers/video
int platform_driver_register(struct platform_driver *drv)--->Platform.c (kernel/drivers/base)
int driver_register(struct device_driver *drv)------->driver.c (kernel/drivers/base)
struct device_driver *driver_find(const char *name, struct bus_type *bus)-------->driver.c (kernel/drivers/base)
int bus_add_driver(struct device_driver *drv)----->bus.c (kernel/drivers/base)
static int driver_add_groups(struct device_driver *drv, struct attribute_group **groups)--->driver.c (kernel/drivers/base)
int driver_attach(struct device_driver *drv)----->Dd.c (kernel、drivers/base)
static int __driver_attach(struct device *dev, void *data)------>Dd.c (kernel/drivers/base)
drv->bus->match(dev, drv) (不同的总线这个match指向的函数不一样在各个bus定义,例如I2c为i2c_device_match )
int driver_probe_device(struct device_driver *drv, struct device *dev)--->Dd.c (kernel/drivers/base)
static int really_probe(struct device *dev, struct device_driver *drv)----->Dd.c (kernel/drivers/base)
static int really_probe(struct device *dev, struct device_driver *drv)
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
static int __init pxafb_probe(struct platform_device *dev)---->Pxafb.c (kernel/drivers/video
platform_device_register 将设备的名字注册到设备链表
platform_driver_register将设备和驱动的名字对比,调用probe函数初始化
struct bus_type i2c_bus_type = {
.name= "i2c",
.dev_attrs= i2c_dev_attrs,
.match= i2c_device_match,
.uevent= i2c_device_uevent,
.probe= i2c_device_probe,
.remove= i2c_device_remove,
.shutdown= i2c_device_shutdown,
.suspend= i2c_device_suspend,
.resume= i2c_device_resume,
};
EXPORT_SYMBOL_GPL(i2c_bus_type);
struct bus_type platform_bus_type = {
.name= "platform",
.dev_attrs= platform_dev_attrs,
.match= platform_match,
.uevent= platform_uevent,
.pm= PLATFORM_PM_OPS_PTR,
};
EXPORT_SYMBOL_GPL(platform_bus_type);
struct bus_type usb_bus_type = {
.name ="usb",
.match =usb_device_match,
.uevent =usb_uevent,
};
struct bus_type ac97_bus_type = {
.name= "ac97",
.match= ac97_bus_match,
#ifdef CONFIG_PM
.suspend= ac97_bus_suspend,
.resume= ac97_bus_resume,
#endif /* CONFIG_PM */
};
static int __init ac97_bus_init(void)
{
return bus_register(&ac97_bus_type);
}
static struct bus_type sdio_bus_type = {
.name= "sdio",
.dev_attrs= sdio_dev_attrs,
.match= sdio_bus_match,
.uevent= sdio_bus_uevent,
.probe= sdio_bus_probe,
.remove= sdio_bus_remove,
.suspend= sdio_bus_suspend,
.resume= sdio_bus_resume,
};
int sdio_register_bus(void)
{
return bus_register(&sdio_bus_type);
}
static struct bus_type serio_bus = {
.name= "serio",
.dev_attrs= serio_device_attrs,
.drv_attrs= serio_driver_attrs,
.match= serio_bus_match,
.uevent= serio_uevent,
.probe= serio_driver_probe,
.remove= serio_driver_remove,
.shutdown= serio_shutdown,
#ifdef CONFIG_PM
.suspend= serio_suspend,
.resume= serio_resume,
#endif
};
static int __init serio_init(void)
{
int error;
error = bus_register(&serio_bus);
if (error) {
printk(KERN_ERR "serio: failed to register serio bus, error: %d/n", error);
return error;
}
serio_task = kthread_run(serio_thread, NULL, "kseriod");
if (IS_ERR(serio_task)) {
bus_unregister(&serio_bus);
error = PTR_ERR(serio_task);
printk(KERN_ERR "serio: Failed to start kseriod, error: %d/n", error);
return error;
}
return 0;
}
struct bus_type scsi_bus_type = {
.name= "scsi",
.match= scsi_bus_match,
.uevent= scsi_bus_uevent,
.suspend= scsi_bus_suspend,
.resume= scsi_bus_resume,
.remove= scsi_bus_remove,
};
EXPORT_SYMBOL_GPL(scsi_bus_type);
int scsi_sysfs_register(void)
{
int error;
error = bus_register(&scsi_bus_type);
if (!error) {
error = class_register(&sdev_class);
if (error)
bus_unregister(&scsi_bus_type);
}
return error;
}
struct bus_type pci_bus_type = {
.name= "pci",
.match= pci_bus_match,
.uevent= pci_uevent,
.probe= pci_device_probe,
.remove= pci_device_remove,
.shutdown= pci_device_shutdown,
.dev_attrs= pci_dev_attrs,
.pm= PCI_PM_OPS_PTR,
};
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}
static struct bus_type w1_bus_type = {
.name = "w1",
.match = w1_master_match,
.uevent = w1_uevent,
};
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
const struct i2c_client *client)
{
while (id->name[0]) {
if (strcmp(client->name, id->name) == 0)
return id;
id++;
}
return NULL;
}
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client*client = to_i2c_client(dev);
struct i2c_driver*driver = to_i2c_driver(drv);
/* make legacy i2c drivers bypass driver model probing entirely;
* such drivers scan each i2c adapter/bus themselves.
*/
if (!is_newstyle_driver(driver))
return 0;
/* match on an id table if there is one */
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL;
return 0;
}