欢迎来到冰点文库! | 帮助中心 分享价值,成长自我!
冰点文库
全部分类
  • 临时分类>
  • IT计算机>
  • 经管营销>
  • 医药卫生>
  • 自然科学>
  • 农林牧渔>
  • 人文社科>
  • 工程科技>
  • PPT模板>
  • 求职职场>
  • 解决方案>
  • 总结汇报>
  • ImageVerifierCode 换一换
    首页 冰点文库 > 资源分类 > PDF文档下载
    分享到微信 分享到微博 分享到QQ空间

    《Linux设备驱动开发详解:基于最新的Linux-4.0内核》19.-Linux电源管理系统架构和驱动.pdf

    • 资源ID:14660254       资源大小:1.22MB        全文页数:35页
    • 资源格式: PDF        下载积分:1金币
    快捷下载 游客一键下载
    账号登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录
    二维码
    微信扫一扫登录
    下载资源需要1金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP,免费下载
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    《Linux设备驱动开发详解:基于最新的Linux-4.0内核》19.-Linux电源管理系统架构和驱动.pdf

    1、以下电子书来源于宋宝华 LinuxLinux 设备驱动开发详解:基于最新的设备驱动开发详解:基于最新的 Linux 4.0Linux 4.0 内核内核 第 19 章 Linux 电源管理系统架构和驱动 本章导读 Linux 在消费电子领域的应用已经铺天盖地,而对于消费电子产品而言,省电是一个重要的议题。本章将介绍 Linux 设备树(Device Tree)的起源、结构和因为设备树而引起的驱动和 BSP变更。19.1 节阐述了 Linux 电源管理的总体架构。19.219.8 节分别论述了 CPUFreq、CPUIdle、CPU 热插拔以及底层的基础设施 Regulator、OPP 以及电源管

    2、理的调试工具 PowerTop。19.9 节讲解了系统 Suspend to RAM 的过程以及设备驱动如何提供对 Suspend to RAM 的支持。19.10 节讲解了设备驱动的 Runtime suspend。本章是相对Linux 设备驱动开发详解(第 2 版)全新的一章内容,也是 Linux 设备驱动工程师必备的知识体系。第十九章第十九章 Linux 电源管理系统电源管理系统架构架构和和驱动驱动 1.Linux 电源管理全局架构电源管理全局架构 Linux 电源管理非常复杂,牵扯到系统级的待机、频率电压变换、系统空闲时的处理以及每个设备驱动对于系统待机的支持和每个设备的运行时电源管理

    3、,可以说和系统中的每个设备驱动都息息相关。对于消费电子产品来说,电源管理相当重要。因此,这部分工作往往在开发周期中占据相当大的比重,图 19.1 呈现了 Linux 内核电源管理的整体架构。大体可以归纳为如下几类:1.CPU 在运行时根据系统负载进行动态电压和频率变换的 CPUFreq 2.CPU 在系统空闲时根据空闲的情况进行低功耗模式的 CPUIdle 3.多核系统下 CPU 的热插拔支持 4.系统和设备对于延迟的特别需求而提出申请的 PM QoS,它会作用于 CPUIdle 的具体策略 5.设备驱动针对系统 Suspend to RAM/Disk 的一系列入口函数 6.SoC 进入 su

    4、spend 状态、SDRAM 自刷新的入口 7.设备的 runtime(运行时)动态电源管理,根据使用情况动态开关设备 8.底层的时钟、稳压器、频率/电压表(OPP 模块完成)支撑,各驱动子系统都可能用到 用户空间基础设施CPUPower ManagerCPUIdleCPU hotplugCPU DVFS(CPUFreq)OPPecho sysfsPower Applicationsclkregulator设备系统级suspend/resumeRuntime suspend/resume设备DVFS(Devfreq)SoC平台级电源操作callbacksPM QoS 图图 19.1 Linux

    5、 电源管理系统架构电源管理系统架构 2.CPUFreq 驱动驱动 CPUFreq 子系统位于 drivers/cpufreq 目录,负责进行运行过程中 CPU 频率和电压的动态调整,即 DVFS(Dynamic Voltage Frequency Scaling,动态电压频率调整)。运行时进行 CPU电压和频率调整的原因是:CMOS 电路中的功耗与电压的平方成正比、与频率成正比(),因此降低电压和频率可降低功耗。CPUFreq 的核心层位于 drivers/cpufreq/cpufreq.c,它为各个 SoC 的 CPUFreq 驱动的实现提供了一套统一的接口,并实现了一套 notifier

    6、的机制,可以在 CPUFreq 的 policy 和频率改变的时候向其他模块发出通知。另外,在 CPU 运行频率发生变化的时候,内核的loops_per_jiffy 常数也会发生相应变化。1.1 SoC 的的 CPUFreq 驱动实现驱动实现 具体的每个 SoC 的 CPUFreq 驱动实例只需要实现电压、频率表,以及从硬件层面完成这些变化。CPUFreq 核心层提供了如下 API 供 SoC 注册自身的 CPUFreq 驱动:int cpufreq_register_driver(struct cpufreq_driver*driver_data);其参数为一个 cpufreq_driver

    7、 结构体指针,实际上,cpufreq_driver 封装了一个具体的 SoC的 CPUFreq 驱动的主体,该结构体形如代码清单 19.1。代码清单代码清单 19.1 19.1 cpufreq_drivercpufreq_driver 结构体结构体 1 struct cpufreq_driver 2 struct module *owner;3 char nameCPUFREQ_NAME_LEN;4 u8 flags;5 6 /*needed by all drivers*/7 int (*init)(struct cpufreq_policy*policy);8 int (*verify)(

    8、struct cpufreq_policy*policy);9 10 /*define one out of two*/11 int (*setpolicy)(struct cpufreq_policy*policy);12 int (*target)(struct cpufreq_policy*policy,13 unsigned inttarget_freq,14 unsigned int relation);15 16 /*should be defined,if possible*/17 unsigned int (*get)(unsigned intcpu);18 19 /*opti

    9、onal*/20 unsigned int(*getavg)(struct cpufreq_policy*policy,21 unsigned intcpu);22 int (*bios_limit)(intcpu,unsigned int*limit);23 24 int (*exit)(struct cpufreq_policy*policy);25 int (*suspend)(struct cpufreq_policy*policy);26 int (*resume)(struct cpufreq_policy*policy);27 structfreq_attr *attr;28;其

    10、中的 owner 成员一般被设置为 THIS_MODULE;name 成员是 CPUFreq 驱动名字,如drivers/cpufreq/s5pv210-cpufreq.c 设置 name 为s5pv210,如 drivers/cpufreq/omap-cpufreq.c设置 name 为omap;flags 是一些暗示性的标志,譬如,若设置了 CPUFREQ_CONST_LOOPS,则是告诉内核 loops_per_jiffy 不会因为 CPU 频率的变化而变化。init()成员是一个 per-CPU 初始化函数指针,每当一个新的 CPU 被注册进系统的时候,该函数就被调用,该函数接受一个

    11、cpufreq_policy 的指针参数,在 init()成员函数中,可进行如下设置:policy-cpuinfo.min_freq policy-cpuinfo.max_freq 该 CPU 支持的最小频率和最大频率(单位是 kHz)。policy-cpuinfo.transition_latency CPU 进行频率切换所需要的延迟(单位是纳秒)policy-cur CPU 当前频率 policy-policy policy-governor policy-min policy-max 定义该 CPU 的缺省 policy,以及缺省 policy 情况下该 policy 支持的最小、最大

    12、CPU 频率。verify()成员函数用于对用户的 CPUFreq policy 设置进行有效性验证和数据修正。每次用户设定一个新 policy 时,该函数根据老的 policy 和新的 policy,检验新 policy 设置的有效性并对无效设置进行必要的修正。在该成员函数的具体实现中,常用到如下辅助函数:cpufreq_verify_within_limits(struct cpufreq_policy*policy,unsigned intmin_freq,unsigned intmax_freq);setpolicy()成员函数接受一个 policy 参数(包含 policy-poli

    13、cy,policy-min 和 policy-max等成员),实现了这个成员函数的 CPU 一般具备在一个范围(limit,从 policy-min 到policy-max)里面自动调整频率的能力。目前少数驱动如 intel_pstate.c 和 longrun.c 包含这样的成员函数。而绝大多数 CPU 都不会实现此函数,一般实现 target()成员函数,target()的参数直接就是一个指定的频率。target()成员函数用于将频率调整到一个指定的值,接受 3 个参数:policy、target_freq和 relation。target_freq 是目标频率,实际驱动总是要设定真实的

    14、CPU 频率到最接近于target_freq,并且设定的频率必须位于 policy-min 到 policy-max 之间。在设定频率接近target_freq 的情况下,relation 若为 CPUFREQ_REL_L,暗示设置的频率应该大于或等于target_freq;relation 若为 CPUFREQ_REL_H,暗示设置的频率应该小于或等于 target_freq。下表描述了 setpolicy()和 target()所针对的 CPU 以及调用方式上的区别:setpolicy target CPU 具备在一定范围内独立调整频率的能力 CPU 只能被指定频率 CPUfreq pol

    15、icy调用到 setpolicy,由 CPU 独立在 limit 内调整频率 由 CPUFreq core 根据系统负载和 policy 综合决定目标频率 由于芯片内部 PLL 和分频器的关系,ARM SoC 一般不具备独立调整频率的能力,往往 SoC的 CPUFreq 驱动会提供一个频率表,在该表的范围内进行变更,所以一般实现 target()成员函数。CPUFreq 核心层提供了一组频率表相关的辅助 API。int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy*policy,struct cpufreq_frequency_ta

    16、ble*table);它是 cpufreq_driver 的 init()成员函数的助手,用于将 policy-min 和 policy-max 设置为与 cpuinfo.min_freq 和 cpuinfo.max_freq 相同的值。int cpufreq_frequency_table_verify(struct cpufreq_policy*policy,struct cpufreq_frequency_table*table);它是 cpufreq_driver 的 verify()成员函数的助手,确保至少 1 个有效的 CPU 频率位于policy-min 到 policy-max

    17、 范围内。int cpufreq_frequency_table_target(struct cpufreq_policy*policy,struct cpufreq_frequency_table*table,unsigned int target_freq,unsigned int relation,unsigned int*index);它是 cpufreq_driver 的 target()成员函数的助手,返回需要设定的频率在频率表中的索引。省略掉具体的细节,1 个 SoC 的 CPUFreq 驱动的实例 drivers/cpufreq/s3c64xx-cpufreq.c的核心结构如代

    18、码清单 19.2。代码清单代码清单 19.2 S3C64XX19.2 S3C64XX 的的 CPUFreqCPUFreq 驱动驱动 001 static unsigned long regulator_latency;002 003 struct s3c64xx_dvfs 004 unsigned intvddarm_min;005 unsigned intvddarm_max;006;007 008 static struct s3c64xx_dvfs s3c64xx_dvfs_table=009 0=1000000,1150000,010 011 4=1300000,1350000,012

    19、;013 014 static struct cpufreq_frequency_table s3c64xx_freq_table=015 0,66000,016 0,100000,017 018 0,CPUFREQ_TABLE_END,019;020 021 static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy*policy)022 023 if(policy-cpu!=0)024 return-EINVAL;025 026 return cpufreq_frequency_table_verify(policy,s3c6

    20、4xx_freq_table);027 028 029 static unsigned int s3c64xx_cpufreq_get_speed(unsigned intcpu)030 031 if(cpu!=0)032 return 0;033 034 return clk_get_rate(armclk)/1000;035 036 037 static int s3c64xx_cpufreq_set_target(struct cpufreq_policy*policy,038 unsigned int target_freq,039 unsigned int relation)040

    21、041 042 ret=cpufreq_frequency_table_target(policy,s3c64xx_freq_table,043 target_freq,relation,&i);044 045 freqs.cpu=0;046 freqs.old=clk_get_rate(armclk)/1000;047 freqs.new=s3c64xx_freq_tablei.frequency;048 freqs.flags=0;049 dvfs=&s3c64xx_dvfs_tables3c64xx_freq_tablei.index;050 051 if(freqs.old=freqs

    22、.new)052 return 0;053 054 cpufreq_notify_transition(&freqs,CPUFREQ_PRECHANGE);055 056 if(vddarm&freqs.newfreqs.old)057 ret=regulator_set_voltage(vddarm,058 dvfs-vddarm_min,059 dvfs-vddarm_max);060 061 062 063 ret=clk_set_rate(armclk,freqs.new*1000);064 065 cpufreq_notify_transition(&freqs,CPUFREQ_PO

    23、STCHANGE);066 067 if(vddarm&freqs.newvddarm_min,070 dvfs-vddarm_max);071 072 073 074 return 0;075 076 077 static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy*policy)078 079 080 armclk=clk_get(NULL,armclk);081 082 vddarm=regulator_get(NULL,vddarm);083 084 s3c64xx_cpufreq_config_regulator();0

    24、85 086 freq=s3c64xx_freq_table;087 while(freq-frequency!=CPUFREQ_TABLE_END)088 unsigned long r;089 090 091 092 policy-cur=clk_get_rate(armclk)/1000;093 policy-cpuinfo.transition_latency=(500*1000)+regulator_latency;094 ret=cpufreq_frequency_table_cpuinfo(policy,s3c64xx_freq_table);095 096 return ret

    25、;097 098 099 staticstruct cpufreq_driver s3c64xx_cpufreq_driver=100 .owner =THIS_MODULE,101 .flags =0,102 .verify =s3c64xx_cpufreq_verify_speed,103 .target =s3c64xx_cpufreq_set_target,104 .get =s3c64xx_cpufreq_get_speed,105 .init =s3c64xx_cpufreq_driver_init,106 .name =s3c,107;108 109 static int _in

    26、it s3c64xx_cpufreq_init(void)110 111 return cpufreq_register_driver(&s3c64xx_cpufreq_driver);112 113 module_init(s3c64xx_cpufreq_init);第 37 行 s3c64xx_cpufreq_set_target()就是完成目标频率设置的函数,它调用了cpufreq_frequency_table_target()从s3c64xx支持的频率表s3c64xx_freq_table里找到合适的频率。在具体的频率和电压设置环节,用的都是 Linux 的标准 API regula

    27、tor_set_voltage()和clk_set_rate()之类的函数。第 111 行在模块初始化的时候透过 cpufreq_register_driver()注册了 cpufreq_driver 的实例,第 94 行,CPUFreq 的初始化阶段调用 cpufreq_frequency_table_cpuinfo()注册了频率表。关于频率表,比较新的内核喜欢使用后面章节将介绍的 OPP。在当前的Linux内核中,存在一个通用的cpufreq-dt驱动,位于drivers/cpufreq/cpufreq-dt.c,很多 SoC 都可以兼容这个驱动,“grep”arch/arm/的代码发现

    28、mach-imx/imx27-dt.c、mach-imx/mach-imx51.c、mach-imx/mach-imx53.c、mach-mvebu/pmsu.c、mach-omap2/pm.c、mach-rockchip/rockchip.c、mach-shmobile/cpufreq.c、mach-sunxi/sunxi.c、mach-sunxi/sunxi.c都注册了 cpufreq-dt 平台设备。1.2 CPUFreq 的的 policy SoC CPUFreq 驱动只是设定了 CPU 的频率参数,以及提供了设置频率的途径,但是它并不会管自身 CPU 究竟应该运行在什么频率上。究竟频

    29、率依据什么样的标准,进行何种变化,则完全由 CPUFreq 的 policy(策略)决定,这些 policy 如下表:CPUFreq 的 policy 策略实现方法 cpufreq_ondemand 平时以低速方式运行,当系统负载提高时候按需自动提高频率 cpufreq_performance CPU 以最高频率运行,即 scaling_max_freq cpufreq_conservative 字面含义是传统的、保守的,跟 ondemand相似,区别在于动态频率变更的时候采用渐进的方式 cpufreq_powersave CPU 以最低频率运行,即 scaling_min_freq cpuf

    30、req_userspace 让 root 用户透过 sys 结点 scaling_setspeed 设置频率 在 Android 系统中,则增加了 1 个 interactive policy,该 policy 适合对延迟敏感的 UI 交互任务,当有 UI 交互任务的时候,该 policy 会更加激进和及时地调整 CPU 频率。总地来说,系统的状态以及CPUFreq的Policy共同决定了CPU频率跳变的target,CPUFreq核心层并将 target 频率传递给底层具体 SoC 的 CPUFreq 驱动,该驱动修改硬件,完成频率的变换,如图 19.2 所示。系统负载CPUFreq Cor

    31、eCPUFreq PolicySoC CPUFreq驱动CPU硬件 图图 19.2 CPUFreq、系统负载、系统负载、policy 与调频与调频 用户空间一般可通过/sys/devices/system/cpu/cpux/cpufreq 结点来设置 CPUFreq。譬如,我们要设置 CPUFreq 到 700MHz,采用 userspace 策略,则运行如下命令:#echo userspace /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor#echo 700000 /sys/devices/system/cpu/cpu0/cpufr

    32、eq/scaling_setspeed 1.3 CPUFreq 的的性能测试和调优性能测试和调优 Linux 3.1 以后的内核已经将 cpupower-utils 工具集放入内核的 tools/power/cpupower 目录,该工具集当中的 cpufreq-bench 工具可帮助工程师分析采用 CPUFreq 后对系统性能的影响。cpufreq-bench 工具的工作原理是模拟系统运行时候的“空闲忙空闲忙”场景,从而触发系统的动态频率变化,然后计算在使用 ondemand、conservative、interactive等 policy 的情况下,做同样的运算与在 performance

    33、 高频模式下做同样运算完成任务的时间比例。交叉编译该工具后,可放入目标电路板文件系统的/usr/sbin/等目录,运行该工具:#cpufreq-bench-l 50000-s 100000-x 50000-y 100000-g ondemand-r 5-n 5-v 会输出一系列的结果,我们提取其中的 Round n 这样的行,它表明了-g ondemand 选项中设定的 ondemand policy 相对于 performance policy 的性能比例,假设值为:Round 1-39.74%Round 2-36.35%Round 3-47.91%Round 4-54.22%Round 5-58.64%显然不太理想,我们在同样的平台下采用 Android 的 interactive policy,得到新的测试结果:Round 1-72.95%Round 2-87.20%Round 3-


    注意事项

    本文(《Linux设备驱动开发详解:基于最新的Linux-4.0内核》19.-Linux电源管理系统架构和驱动.pdf)为本站会员主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    copyright@ 2008-2023 冰点文库 网站版权所有

    经营许可证编号:鄂ICP备19020893号-2


    收起
    展开