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

Android学习之Platform总线 1

2013年10月13日 ⁄ 综合 ⁄ 共 7105字 ⁄ 字号 评论关闭

借鉴http://wenku.baidu.com/view/107d915377232f60ddcca113.html学习i.mx53

1.platform

Platform 总线是 2.6kernel引入的一种虚拟总线,用来管理CPU的片上资源,具有更好的移植性,很多驱动都用platform改写了。

platform_bus_typeKernel_imx/drivers/base/platform.c中定义如下:

struct bus_type platform_bus_type = {

       .name             = "platform",

       .dev_attrs       = platform_dev_attrs,

       .match            = platform_match,

       .uevent           = platform_uevent,

       .pm         = &platform_dev_pm_ops,

};

EXPORT_SYMBOL_GPL(platform_bus_type);

bus_typekernel_imx/include/linux/device.h 中定义如下

 

struct bus_type {

       const char              *name;

       struct bus_attribute *bus_attrs;

       struct device_attribute    *dev_attrs;

       struct driver_attribute    *drv_attrs;

 

       int (*match)(struct device *dev, struct device_driver *drv);

       int (*uevent)(struct device *dev, struct kobj_uevent_env *env);

       int (*probe)(struct device *dev);

       int (*remove)(struct device *dev);

       void (*shutdown)(struct device *dev);

 

       int (*suspend)(struct device *dev, pm_message_t state);

       int (*resume)(struct device *dev);

 

       const struct dev_pm_ops *pm;

 

       struct bus_type_private *p;

};

 

可见,platform其只是bus_type的一种。

总线bus是联系drivedevice的中间枢纽,Device通过所属的bus找到driver,由match操作方法进行匹配。

 

2 deviceplatform_device

Platform device会有一个名字用于driver binding,另外IRQ以及地址空间等资源也要给出。

Platform_device 结构体用来描述设备的名称、资源信息等。定义在

kernel_imx/include/linux/platform_device.h 中定义如下

struct platform_device {

       const char       * name;

       int          id;

       struct device   dev;

       u32         num_resources;

       struct resource * resource;

 

       const struct platform_device_id     *id_entry;

 

       /* arch specific additions */

       struct pdev_archdata      archdata;

};

其封装了struct devicestruct resource,可知platform_devicedevice派生而来。

 

struct resource {

       resource_size_t start;

       resource_size_t end;

       const char *name;

       unsigned long flags;

       struct resource *parent, *sibling, *child;

};

 

 

struct device {

       struct device          *parent;

 

       struct device_private      *p;

 

       struct kobject kobj;

       const char              *init_name; /* initial name of the device */

       struct device_type   *type;

 

       struct mutex           mutex;    /* mutex to synchronize calls to

                                    * its driver.

                                    */

 

       struct bus_type       *bus;              /* type of bus device is on */

       struct device_driver *driver;  /* which driver has allocated this

                                      device */

       void        *platform_data;      /* Platform specific data, device

                                      core doesn't touch it */

       struct dev_pm_info power;

 

#ifdef CONFIG_NUMA

       int          numa_node;    /* NUMA node this device is close to */

#endif

       u64         *dma_mask;   /* dma mask (if dma'able device) */

       u64         coherent_dma_mask;/* Like dma_mask, but for

                                        alloc_coherent mappings as

                                        not all hardware supports

                                        64 bit addresses for consistent

                                        allocations such descriptors. */

 

       struct device_dma_parameters *dma_parms;

 

       struct list_head       dma_pools;     /* dma pools (if dma'ble) */

 

       struct dma_coherent_mem     *dma_mem; /* internal for coherent mem

                                        override */

       /* arch specific additions */

       struct dev_archdata archdata;

#ifdef CONFIG_OF

       struct device_node  *of_node;

#endif

 

       dev_t                    devt;       /* dev_t, creates the sysfs "dev" */

 

       spinlock_t              devres_lock;

       struct list_head       devres_head;

 

       struct klist_node     knode_class;

       struct class             *class;

       const struct attribute_group **groups;  /* optional groups */

 

       void (*release)(struct device *dev);

}

 

3 device_registerplatform_device_register

3.1

Kernel_imx/drivers/base/core.c

int device_register(struct device *dev)

{

       device_initialize(dev);

       return device_add(dev);

}

/**

 * device_add - add device to device hierarchy.

 * @dev: device.

 *

 * This is part 2 of device_register(), though may be called

 * separately _iff_ device_initialize() has been called separately.

 *

 * This adds @dev to the kobject hierarchy via kobject_add(), adds it

 * to the global and sibling lists for the device, then

 * adds it to the other relevant subsystems of the driver model.

 *

 * NOTE: _Never_ directly free @dev after calling this function, even

 * if it returned an error! Always use put_device() to give up your

 * reference instead.

 */

int device_add(struct device *dev)

{

       struct device *parent = NULL;

       struct class_interface *class_intf;

       int error = -EINVAL;

 

       dev = get_device(dev);

       if (!dev)

              goto done;

 

       if (!dev->p) {

              error = device_private_init(dev);

              if (error)

                     goto done;

       }

 

       /*

        * for statically allocated devices, which should all be converted

        * some day, we need to initialize the name. We prevent reading back

        * the name, and force the use of dev_name()

        */

       if (dev->init_name) {

              dev_set_name(dev, "%s", dev->init_name);

              dev->init_name = NULL;

       }

 

       if (!dev_name(dev)) {

              error = -EINVAL;

              goto name_error;

       }

 

       pr_debug("device: '%s': %s/n", dev_name(dev), __func__);

 

       parent = get_device(dev->parent);

       setup_parent(dev, parent);

 

       /* use parent numa_node */

       if (parent)

              set_dev_node(dev, dev_to_node(parent));

 

       /* first, register with generic layer. */

       /* we require the name to be set before, and pass NULL */

       error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);

       if (error)

              goto Error;

 

       /* notify platform of device entry */

       if (platform_notify)

              platform_notify(dev);

 

       error = device_create_file(dev, &uevent_attr);

       if (error)

              goto attrError;

 

       if (MAJOR(dev->devt)) {

              error = device_create_file(dev, &devt_attr);

              if (error)

                     goto ueventattrError;

 

              error = device_create_sys_dev_entry(dev);

              if (error)

                     goto devtattrError;

 

              devtmpfs_create_node(dev);

       }

 

       error = device_add_class_symlinks(dev);

       if (error)

              goto SymlinkError;

       error = device_add_attrs(dev);

       if (error)

              goto AttrsError;

       error = bus_add_device(dev);

       if (error)

              goto BusError;

       error = dpm_sysfs_add(dev);

       if (error)

              goto DPMError;

       device_pm_add(dev);

 

       /* Notify clients of device addition.  This call must come

        * after dpm_sysf_add() and before kobject_uevent().

        */

       if (dev->bus)

              blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

                                        BUS_NOTIFY_ADD_DEVICE, dev);

 

       kobject_uevent(&dev->kobj, KOBJ_ADD);

       bus_probe_device(dev);

       if (parent)

              klist_add_tail(&dev->p->knode_parent,

                            &parent->p->klist_children);

 

       if (dev->class) {

              mutex_lock(&dev->class->p->class_mutex);

              /* tie the class to the device */

              klist_add_tail(&dev->knode_class,

                            &dev->class->p->class_devices);

 

              /* notify any interfaces that the device is here */

              list_for_each_entry(class_intf,

                                &dev->class->p->class_interfaces, node)

                     if (class_intf->add_dev)

抱歉!评论已关闭.