电源管理入门-10 OPP介绍
之前的文章设置clock的时候多次提到了Operating Performance PointOPP例如DEVFreq、CPUFreq等在现代SoC上存在有Power Domain也可以以Power Domain为单位进行OPP的电压频率定义。1. 什么是OPP怎么用在SoC内某些domain可以运行在较低的频率和电压下而其他domain可以运行在较高的频率和电压下某个domain所支持的频率电压对的集合被称为Operating Performance Point缩写OPP。在DTS中配置后自动有OPP框架驱动加载使用例如CPU的OPP从设备树文件arch/arm/boot/dts/imx6ull.dtsi中找到cpu0: cpu0{compatiblearm,cortex-a7;device_typecpu;reg0;clock-latency61036;/* two CLK32 periods */ operating-points/* kHz uV */9000001275000792000122500052800011750003960001025000198000950000;fsl,soc-operating-points/* KHz uV */90000011750007920001175000528000117500039600011750001980001175000;2. 系统初始化加载OPP信息DT_MACHINE_START --》imx6ul_init_late --》imx6ul_opp_init --》_of_add_opp_table_v1(dev);--》_opp_add_v1 --》_opp_add_of_add_opp_table_v1中会根据DTS中信息找到对应的信息_opp_add_v1中会把DTS中信息提取出来存入struct dev_pm_opp *new_opp;这里struct dev_pm_opp如下struct dev_pm_opp{struct list_headnode;bool available;unsigned long rate;unsigned long u_volt;struct device_opp *dev_opp;struct rcu_headhead;};node:用于链表管理此设备下的opp。available:用于判断此opp使能可以使用。rate:频率单位Hzu_volt:电压。dev_opp:struct device_opp类型指针指向此opp所属的设备。3. 触发使用例如输入命令echo700000/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed__cpufreq_driver_target-__target_index-cpufreq_driver-target_indexstatic int set_target(struct cpufreq_policy *policy, unsigned int index){struct private_data *privpolicy-driver_data;returndev_pm_opp_set_rate(priv-cpu_dev, policy-freq_table[index].frequency *1000);}dev_pm_opp_set_rate函数在drivers/base/power/opp/core.c中定义opp_table_find_opp_table(dev);clkopp_table-clk;freqclk_round_rate(clk, target_freq);if((long)freq0)freqtarget_freq;old_freqclk_get_rate(clk);ret_generic_set_opp_clk_only(dev, clk, old_freq, freq);clk_set_rate进行频率设置。4. API介绍dev_pm_opp_add ( WARNING: Do not use this function in interrupt context.)向指定的设备添加一个频率/电压opp table组合频率和电压的单位分别是Hz和uV。dev_pm_opp_remove:remove an opp from opp table.dev_pm_opp_get:increment the reference count of opp.dev_pm_opp_enable用于使能指定的OPP调用dev_pm_opp_add添加进去的OPP默认是enable的。dev_pm_opp_disable虽然设备支持某些OPP但driver有可能觉得比较危险不想使用则可以调用dev_pm_opp_disable接口禁止该OPP。dev_pm_opp_get_voltage获得电压。dev_pm_opp_get_freq获得频率。dev_pm_opp_set_regulators进行voltage scalingdev_pm_opp_put_regulatorsfree the resources acquired by the OPP coredev_pm_opp_set_rateThis routine configures the device for the OPP with the lowest frequency greater than or equal to the target frequency.dev_pm_opp_get_opp_count获取opp table opps numbersdev_pm_opp_of_add_table 解析并初始化一个设备的opp table。OPP的查询接口包括dev_pm_opp_find_freq_floor查询小于或者等于指定freq的OPP在返回OPP的同时从freq指针中返回实际的freq值dev_pm_opp_find_freq_ceil查询大于或者等于指定freq的OPP在返回OPP的同时从freq指针中返回实际的freq值dev_pm_opp_find_freq_exact精确查找指定freq的OPP同时通过available变量可以控制是否查找处于disable状态的OPP。上面两个查找接口是不查找处于disable状态的OPP的。后记Linux驱动的套路其实就是DTS里面有个compatible然后内核启动的时候走各种平台设备初始化就会去寻找加载然后变成链表结构体。在使用的时候用户通过设备节点或者中断产生或者内核进程触发就可以运行。“啥都懂一点啥都不精通干啥都能干干啥啥不是专业入门劝退堪称程序员杂家”。欢迎各位自己有博客公众号的留言申请转载多谢后续会继续更新纯干货分析欢迎分享给朋友欢迎点赞、收藏、在看、划线和评论交流以公众号“那路谈OS与SoC嵌入式软件”欢迎关注个人文章汇总https://thatway1989.github.io