现在的位置: 首页 > 综合 > 正文

ARM linux PLATFORM 设备注册

2013年12月05日 ⁄ 综合 ⁄ 共 6988字 ⁄ 字号 评论关闭

                  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;
}

抱歉!评论已关闭.