• linux dpm机制分析(下)【转】


    转自:http://blog.csdn.net/lixiaojie1012/article/details/23707901

    1      设备注册到dpm_list路径

    (Platform_device->device->device_driver指向platform_driver->driver)

    2      低功耗接口

    dpm_suspend_start():调用注册到dpm_list的设备的回调函数,执行睡眠前的准备和保存工作;

    dpm_suspend_end():执行suspend_late和suspend_noirq设备的回调函数,进行睡眠前的准备工作。

    睡眠时,设备在链表中的转移:

    dpm_list--->dpm_prepared_list-->dpm_suspended_list---->

    dpm_late_early_list--->dpm_noirq_list

    Dpm_resume_start():执行设备的resume_noirq和resume_early回调,恢复suspend_noirq和suspend_late阶段保存的东西

    dpm_resume_end():执行各设备的resume和complete回调接口,做suspend和prepare的逆操作

    唤醒时,设备从链表中的转移顺序是上述suspend阶段顺序的逆序。

    3      低功耗接口是如何调用到各设备驱动注册的回调函数的

    系统进入睡眠前回调设备的回调函数是有选择的:

    如果dev->pm_domain域的回调函数注册的话,首选此处的回调函数

    否则,如果dev->type域和dev->type->pm域都注册的话,会选择dev->type->pm处的回调函数

    否则,如果dev->class 和 dev->class->pm两处都注册回调函数的话,会选择dev->class->pm的回调函数

    如果dev->bus 和 dev->bus->pm两处都注册回调函数的话,会选择dev->bus->pm的回调函数

    示例方法1和方法4:

    3.1       在dev域的电源域进行注册

    struct platform_device {

           const char       * name;

           int          id;

           bool        id_auto;

           struct device   dev;

           u32         num_resources;

           struct resource * resource;

           const struct platform_device_id     *id_entry;

           /* MFD cell pointer */

           struct mfd_cell *mfd_cell;

           /* arch specific additions */

           struct pdev_archdata      archdata;

    };

    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;

    …….}

    struct dev_pm_domain {

           struct dev_pm_ops  ops;

    };

    struct dev_pm_ops {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    };

    低功耗接口在函数__device_suspend函数内会首先调用在struct device电源域注册的回调函数。

    唤醒时调用顺序:

    3.2       在bus的ops电源域进行注册

    注册设备和注册驱动进行匹配成功后

    Platform_device->device->device_driver指针会指向platform_driver->driver成员

    设备注册:

     (1)int platform_device_add(struct platform_device *pdev)

    {

           ……………

           if (!pdev->dev.parent)

                  pdev->dev.parent = &platform_bus;

           pdev->dev.bus = &platform_bus_type;

    …………..

    }

    (2)struct bus_type platform_bus_type = {

           .name             = "platform",

           .dev_attrs       = platform_dev_attrs,

           .match            = platform_match,

           .uevent           = platform_uevent,

           .pm         = &platform_dev_pm_ops,

    };

    (3)static const struct dev_pm_ops platform_dev_pm_ops = {

           .runtime_suspend = pm_generic_runtime_suspend,

           .runtime_resume = pm_generic_runtime_resume,

           .runtime_idle = pm_generic_runtime_idle,

           USE_PLATFORM_PM_SLEEP_OPS

    };

    (4)#define USE_PLATFORM_PM_SLEEP_OPS

           .suspend = platform_pm_suspend,

           .resume = platform_pm_resume,

           .freeze = platform_pm_freeze,

           .thaw = platform_pm_thaw,

           .poweroff = platform_pm_poweroff,

           .restore = platform_pm_restore,

    (5) int platform_pm_suspend(struct device *dev)

    {

           struct device_driver *drv = dev->driver;

           int ret = 0;

           if (!drv)

                  return 0;

           if (drv->pm) {

                  if (drv->pm->suspend)

                         ret = drv->pm->suspend(dev);

           } else {

                  ret = platform_legacy_suspend(dev, PMSG_SUSPEND);

           }

           return ret;

    }

  • 相关阅读:
    hdu2438 三分
    hdu3786 找出直系亲属 水题
    hdu3786 找出直系亲属 水题
    hdu4561 连续最大积
    hdu4561 连续最大积
    hdu4604 不错的子序列问题
    hdu4604 不错的子序列问题
    hdu4450 不错的贪心
    hdu1722 切蛋糕
    hdu3768 spfa+全排列
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/5333660.html
Copyright © 2020-2023  润新知