转自: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;

}

linux dpm机制分析(下)【转】的更多相关文章

  1. linux dpm机制分析(上)【转】

    转自:http://blog.csdn.net/lixiaojie1012/article/details/23707681 1      DPM介绍 1.1        Dpm:  设备电源管理, ...

  2. 【原创】Linux信号量机制分析

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  3. 【转】Linux Writeback机制分析

    1. bdi是什么? bdi,即是backing device info的缩写,顾名思义它描述备用存储设备相关描述信息,这在内核代码里用一个结构体backing_dev_info来表示. bdi,备用 ...

  4. 【原创】Linux Mutex机制分析

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  5. 仿照linux dpm机制,实现自己的dpm【转】

    转自:http://blog.csdn.net/lixiaojie1012/article/details/23788713 前边我们讨论分析了linux 内核的dpm实现,分析的目的在于学以致用:在 ...

  6. Linux mips64r2 PCI中断路由机制分析

    Linux mips64r2 PCI中断路由机制分析 本文主要分析mips64r2 PCI设备中断路由原理和irq号分配实现方法,并尝试回答如下问题: PCI设备驱动中断注册(request_irq) ...

  7. linux内核3.4基于wakeup_source的autosleep机制分析

    点击打开链接 一:wakeup_source简介: linux 3.4内核PM使用了wakeup_source来保持唤醒状态,也就是keep awake.之前android一直是基于Linux加入了w ...

  8. Linux信号(signal) 机制分析

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

  9. Linux内核态抢占机制分析(转)

    Linux内核态抢占机制分析  http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive ...

随机推荐

  1. 【bzoj1441】Min 扩展裴蜀定理

    题目描述 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1*X1+...An*Xn>0,且S的值最小 输入 第一行给出数字N,代表有N个数 下面一行给出N个数 输出 S ...

  2. 转:概率主题模型简介 --- ---David M. Blei所写的《Introduction to Probabilistic Topic Models》的译文

    概率主题模型简介 Introduction to Probabilistic Topic Models      转:http://www.cnblogs.com/siegfang/archive/2 ...

  3. CentOS 不间断会话(ssh关闭后如何保证程序继续运行)(nohup和screen)

    当使用ssh与远程主机的会话被关闭时,在远程主机上运行的命令也随之被中断. 就是ssh 打开以后,bash等都是他的子程序,一旦ssh关闭,系统将所有相关进程杀掉!! 导致一旦ssh关闭,执行中的任务 ...

  4. java动态代理(JDK和CGLIB)笔记

    动态代理:为一堆interface或类的实现提供统一的执行通道,从含义上就像局域网电脑通过代理上网一样,走统一的通道,代理控制通道,自然可以在通道里加上自定义实现,例如像AOP切面,日志等. JDK的 ...

  5. [洛谷P4174][NOI2006]最大获利

    题目大意:同Petya and Graph,数据范围改成$n\leqslant5\times10^3,m\leqslant5\times10^4$ 题解:同上 卡点:无 C++ Code: #incl ...

  6. POJ2724:Purifying Machine——题解

    http://poj.org/problem?id=2724 描述迈克是奶酪工厂的老板.他有2^N个奶酪,每个奶酪都有一个00 ... 0到11 ... 1的二进制数.为了防止他的奶酪免受病毒侵袭,他 ...

  7. Delight for a Cat

    Time Limit: 1000 ms Memory Limit: 512 MB Description ​ 从前,有一只懒猫叫CJB.每个小时,这只猫要么在睡觉,要么在吃东西,但不能一边睡觉一边吃东 ...

  8. Java Web用Freemarker生成带图片的Word文档

    步骤一:模板制作 用world2003做一个导出模板,如果有图片则加入一张图片占位,将world另存为xml,将xml中需要导出的内容用Freemarker标签表示,最后另存为.ftl结尾的模板: 步 ...

  9. Xcode 问题

    问题: 昨天在写代码的时候,不知道修改了哪个地方,Xcode6突然犯病了,在当前项目下无法代码提示,但是在新建工程中没有任何问题,其中重装了Xcode6也没有把问题解决, 最终的解决办法是: 在fin ...

  10. Android Studio中进行单元测试

    写单元测试类 1.创建单元测试文件夹,即新建一个用于单元测试的包,存放单元测试的类. 2.创建一个类如 ExampleTest,注意要继承自InstrumentationTestCase类. 3.创建 ...