美文网首页
4-platform总线_基础驱动模型

4-platform总线_基础驱动模型

作者: ibo | 来源:发表于2017-02-03 15:37 被阅读0次
    platform总线:是管理片上资源的虚拟总线
    • platform组成:
      • 1.platform_device: 描述与硬件相关信息的数据结构体
      • 2.platform_driver: 描述与硬件无关的数据结构体
      • 3.platform_bus_type:管理和匹配platform_device和platform_driver
    基础驱动模型:
    • 1.device
    • 2.device_driver
    • 3.bus_type
    • 4.class
    基础驱动模型的设计初衷是实现硬件与驱动的分离,使得linux实现跨平台的特性。基础驱动模型应用于内核的各种框架和总线
    其他驱动: other drivers
    platform总线: platform_device platform_driver platform_bus_type
    基础驱动模型: device device_driver bus_type
    基础数据结构: kobject/kset/ktype
    /**
     * struct device_driver - The basic device driver structure
     * @name:   Name of the device driver.
     * @bus:    The bus which the device of this driver belongs to.
     * @owner:  The module owner.
     * @mod_name:   Used for built-in modules.
     * @suppress_bind_attrs: Disables bind/unbind via sysfs.
     * @of_match_table: The open firmware table.
     * @acpi_match_table: The ACPI match table.
     * @probe:  Called to query the existence of a specific device,
     *      whether this driver can work with it, and bind the driver
     *      to a specific device.
     * @remove: Called when the device is removed from the system to
     *      unbind a device from this driver.
     * @shutdown:   Called at shut-down time to quiesce the device.
     * @suspend:    Called to put the device to sleep mode. Usually to a
     *      low power state.
     * @resume: Called to bring a device from sleep mode.
     * @groups: Default attributes that get created by the driver core
     *      automatically.
     * @pm:     Power management operations of the device which matched
     *      this driver.
     * @p:      Driver core's private data, no one other than the driver
     *      core can touch this.
     *
     * The device driver-model tracks all of the drivers known to the system.
    * The main reason for this tracking is to enable the driver core to match
     * up drivers with new devices. Once drivers are known objects within the
     * system, however, a number of other things become possible. Device drivers
     * can export information and configuration variables that are independent
     * of any specific device.
     */
    struct device_driver {
        const char      *name;
        struct bus_type     *bus;
    
        struct module       *owner;
        const char      *mod_name;  /* used for built-in modules */
    
        bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */
    
        const struct of_device_id   *of_match_table;
        const struct acpi_device_id *acpi_match_table;
    
        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 attribute_group **groups;
    
        const struct dev_pm_ops *pm;
    
        struct driver_private *p;
    };
    
    
    /**
     * struct device - The basic device structure
     * @parent: The device's "parent" device, the device to which it is attached.
     *      In most cases, a parent device is some sort of bus or host
     *      controller. If parent is NULL, the device, is a top-level device,
     *      which is not usually what you want.
     * @p:      Holds the private data of the driver core portions of the device.
     *      See the comment of the struct device_private for detail.
     * @kobj:   A top-level, abstract class from which other classes are derived.
     * @init_name:  Initial name of the device.
     * @type:   The type of device.
     *      This identifies the device type and carries type-specific
     *      information.
     * @mutex:  Mutex to synchronize calls to its driver.
     * @bus:    Type of bus device is on.
     * @driver: Which driver has allocated this
     * @platform_data: Platform data specific to the device.
     *      Example: For devices on custom boards, as typical of embedded
     *      and SOC based hardware, Linux often uses platform_data to point
     *      to board-specific structures describing devices and how they
     *      are wired.  That can include what ports are available, chip
     *      variants, which GPIO pins act in what additional roles, and so
     *      on.  This shrinks the "Board Support Packages" (BSPs) and
     *      minimizes board-specific #ifdefs in drivers.
     * @power:  For device power management.
     *      See Documentation/power/devices.txt for details.
     * @pm_domain:  Provide callbacks that are executed during system suspend,
     *      hibernation, system resume and during runtime PM transitions
     *      along with subsystem-level and driver-level callbacks.
     * @pins:   For device pin management.
     *      See Documentation/pinctrl.txt for details.
     * @numa_node:  NUMA node this device is close to.
     * @dma_mask:   Dma mask (if dma'ble device).
     * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
     *      hardware supports 64-bit addresses for consistent allocations
     *      such descriptors.
     * @dma_parms:  A low level driver may set these to teach IOMMU code about
     *      segment limitations.
     * @dma_pools:  Dma pools (if dma'ble device).
     * @dma_mem:    Internal for coherent mem override.
     * @cma_area:   Contiguous memory area for dma allocations
     * @archdata:   For arch-specific additions.
     * @of_node:    Associated device tree node.
     * @acpi_node:  Associated ACPI device node.
     * @devt:   For creating the sysfs "dev".
     * @id:     device instance
     * @devres_lock: Spinlock to protect the resource of the device.
     * @devres_head: The resources list of the device.
     * @knode_class: The node used to add the device to the class list.
     * @class:  The class of the device.
     * @groups: Optional attribute groups.
     * @release:    Callback to free the device after all references have
    *      gone away. This should be set by the allocator of the
     *      device (i.e. the bus driver that discovered the device).
     * @iommu_group: IOMMU group the device belongs to.
     *
     * @offline_disabled: If set, the device is permanently online.
     * @offline:    Set after successful invocation of bus type's .offline().
     *
     * At the lowest level, every device in a Linux system is represented by an
     * instance of struct device. The device structure contains the information
     * that the device model core needs to model the system. Most subsystems,
     * however, track additional information about the devices they host. As a
     * result, it is rare for devices to be represented by bare device structures;
     * instead, that structure, like kobject structures, is usually embedded within
     * a higher-level representation of the device.
     */
    struct device {
        struct device       *parent;
    
        struct device_private   *p;
    
        struct kobject kobj;
        const char      *init_name; /* initial name of the device */
        const 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;
        struct dev_pm_domain    *pm_domain;
    
    #ifdef CONFIG_PINCTRL
        struct dev_pin_info *pins;
    #endif
    
    #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 */
    #ifdef CONFIG_DMA_CMA
        struct cma *cma_area;       /* contiguous memory area for dma
                           allocations */
    #endif
        /* arch specific additions */
        struct dev_archdata archdata;
    
        struct device_node  *of_node; /* associated device tree node */
        struct acpi_dev_node    acpi_node; /* associated ACPI device node */
    
        dev_t           devt;   /* dev_t, creates the sysfs "dev" */
        u32         id; /* device instance */
    
        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);
      struct iommu_group  *iommu_group;
    
        bool            offline_disabled:1;
        bool            offline:1;
    };
    
    
    /**
     * struct bus_type - The bus type of the device
     *
     * @name:   The name of the bus.
     * @dev_name:   Used for subsystems to enumerate devices like ("foo%u", dev->id).
     * @dev_root:   Default device to use as the parent.
     * @dev_attrs:  Default attributes of the devices on the bus.
     * @bus_groups: Default attributes of the bus.
     * @dev_groups: Default attributes of the devices on the bus.
     * @drv_groups: Default attributes of the device drivers on the bus.
     * @match:  Called, perhaps multiple times, whenever a new device or driver
     *      is added for this bus. It should return a nonzero value if the
     *      given device can be handled by the given driver.
     * @uevent: Called when a device is added, removed, or a few other things
     *      that generate uevents to add the environment variables.
     * @probe:  Called when a new device or driver add to this bus, and callback
     *      the specific driver's probe to initial the matched device.
     * @remove: Called when a device removed from this bus.
     * @shutdown:   Called at shut-down time to quiesce the device.
     *
     * @online: Called to put the device back online (after offlining it).
     * @offline:    Called to put the device offline for hot-removal. May fail.
     *
     * @suspend:    Called when a device on this bus wants to go to sleep mode.
     * @resume: Called to bring a device on this bus out of sleep mode.
     * @pm:     Power management operations of this bus, callback the specific
     *      device driver's pm-ops.
     * @iommu_ops:  IOMMU specific operations for this bus, used to attach IOMMU
     *              driver implementations to a bus and allow the driver to do
     *              bus-specific setup
     * @p:      The private data of the driver core, only the driver core can
     *      touch this.
     * @lock_key:   Lock class key for use by the lock validator
     *
     * A bus is a channel between the processor and one or more devices. For the
     * purposes of the device model, all devices are connected via a bus, even if
     * it is an internal, virtual, "platform" bus. Buses can plug into each other.
     * A USB controller is usually a PCI device, for example. The device model
     * represents the actual connections between buses and the devices they control.
     * A bus is represented by the bus_type structure. It contains the name, the
     * default attributes, the bus' methods, PM operations, and the driver core's
     * private data.
     */
    struct bus_type {
        const char      *name;
        const char      *dev_name;
        struct device       *dev_root;
        struct device_attribute *dev_attrs; /* use dev_groups instead */
        const struct attribute_group **bus_groups;
        const struct attribute_group **dev_groups;
        const struct attribute_group **drv_groups;
    
        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 (*online)(struct device *dev);
        int (*offline)(struct device *dev);
    
        int (*suspend)(struct device *dev, pm_message_t state);
        int (*resume)(struct device *dev);
    
        const struct dev_pm_ops *pm;
    
        struct iommu_ops *iommu_ops;
    
        struct subsys_private *p;
        struct lock_class_key lock_key;
    };
    

    struct platform_driver {
        int (*probe)(struct platform_device *);//当platform_driver和platform_device匹配成功时,此函数将自动执行,一般在probe函数中实现driver的初始化程序设计
        int (*remove)(struct platform_device *); //当platform_driver和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匹配的标识
        bool prevent_deferred_probe; //匹配尝试的次数
    };
    

    /**
     * platform_match - bind platform device to platform driver.
     * @dev: device.
     * @drv: driver.
     *
     * Platform device IDs are assumed to be encoded like this:
     * "<name><instance>", where <name> is a short description of the type of
     * device, like "pci" or "floppy", and <instance> is the enumerated
     * instance of the device, like '0' or '42'.  Driver IDs are simply
     * "<name>".  So, extract the <name> from the platform_device structure,
     * and compare it against the name of the driver. Return whether they match
     * or not.
     */
    此函数是platform_bus_type中实现platform_driver和platform_device的关键函数:
    
    
    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 ACPI style match *///再尝试ACPI风格的匹配
        if (acpi_driver_match_device(dev, drv))
            return 1;
       /* Then try to match against the id table *///再尝试设备id风格的匹配
        if (pdrv->id_table)
            return platform_match_id(pdrv->id_table, pdev) != NULL;
    
        /* fall-back to driver name match */ //尝试设备名称匹配
        return (strcmp(pdev->name, drv->name) == 0);
    }
    

    struct platform_device {
        const char  *name;  //是设备名称,是platform_device和platform_driver名字匹配的标识
        int     id;    //设备id
        bool        id_auto; //设备id自动赋值
        struct device   dev; //内嵌的基础驱动模型
        u32     num_resources; //描述硬件资源的个数
        struct resource *resource; //描述硬件资源的数据结构体
    
        const struct platform_device_id *id_entry; //设备id属性
    
        /* MFD cell pointer */
        struct mfd_cell *mfd_cell; //多功能设备属性
    
        /* arch specific additions */
        struct pdev_archdata    archdata; //平台私有数据
    };
    

    /*************************************************************************/
    /**
     * platform_device_register - add a platform-level device
     * @pdev: platform device we're adding
     */
    int platform_device_register(struct platform_device *pdev)
    函数功能: 向内核注册platform_device
    返回值:  成功为0,失败返回负数
    参数1:   要注册的platform_device结构体指针
    /*************************************************************************/
    
    /*************************************************************************/
    /**
     * platform_device_unregister - unregister a platform-level device
     * @pdev: platform device we're unregistering
     *
     * Unregistration is done in 2 steps. First we release all resources
     * and remove it from the subsystem, then we drop reference count by
     * calling platform_device_put().
     */
    void platform_device_unregister(struct platform_device *pdev)
    函数功能: 从内核注销platform_device
    返回值:  无
    参数1:   要注销的platform_device结构体指针
    /*************************************************************************/
    
    /*************************************************************************/
    /*
     * use a macro to avoid include chaining to get THIS_MODULE
     */
    #define platform_driver_register(drv) \
        __platform_driver_register(drv, THIS_MODULE)
    函数功能: 向内核注册platform_driver
    返回值:  无
    参数1:   要注册的platform_driver结构体指针
    /*************************************************************************/
    
    /*************************************************************************/
    /**
     * platform_driver_unregister - unregister a driver for platform-level devices
     * @drv: platform driver structure
     */
    void platform_driver_unregister(struct platform_driver *drv)
    函数功能: 从内核注销platform_driver
    返回值:  无
    参数1:   要注销的platform_driver结构体指针
    /*******************************************1******************************/
    

    相关文章

      网友评论

          本文标题:4-platform总线_基础驱动模型

          本文链接:https://www.haomeiwen.com/subject/njydittx.html