sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget /power/oppmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/zh_TW/power/oppmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/it_IT/power/oppmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/ja_JP/power/oppmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/ko_KR/power/oppmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hPortuguese (Brazilian)}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/pt_BR/power/oppmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/sp_SP/power/oppmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhJ/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/power/opp.rsthKubhnote)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]h paragraph)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hh5Documentation/translations/zh_CN/disclaimer-zh_CN.rsthKhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh field_list)}(hhh](hfield)}(hhh](h field_name)}(hOriginalh]hOriginal}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh field_body)}(hDocumentation/power/opp.rst h]h)}(hDocumentation/power/opp.rsth]hDocumentation/power/opp.rst}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h翻译h]h翻译}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhKubj)}(h.唐艺舟 Tang Yizhou h]h)}(h-唐艺舟 Tang Yizhou h](h唐艺舟 Tang Yizhou <}(hj4hhhNhNubh reference)}(htangyeechou@gmail.comh]htangyeechou@gmail.com}(hj>hhhNhNubah}(h]h ]h"]h$]h&]refurimailto:tangyeechou@gmail.comuh1j<hj4ubh>}(hj4hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj0ubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubhsection)}(hhh](htitle)}(h操作性能值(OPP)库h]h操作性能值(OPP)库}(hjqhhhNhNubah}(h]h ]h"]h$]h&]uh1johjlhhhhhK ubhenumerated_list)}(hhh]h list_item)}(h92009-2010 Nishanth Menon , 德州仪器公司 h]h)}(h82009-2010 Nishanth Menon , 德州仪器公司h](h2009-2010 Nishanth Menon <}(hjhhhNhNubj=)}(h nm@ti.comh]h nm@ti.com}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:nm@ti.comuh1j<hjubh>, 德州仪器公司}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubah}(h]h ]h"]h$]h&]enumtype upperalphaprefix(suffix)startKuh1jhjlhhhhhKubh)}(h目录 1. 简介 2. OPP链表初始注册 3. OPP搜索函数 4. OPP可用性控制函数 5. OPP数据检索函数 6. 数据结构h]h目录 1. 简介 2. OPP链表初始注册 3. OPP搜索函数 4. OPP可用性控制函数 5. OPP数据检索函数 6. 数据结构}hjsbah}(h]h ]h"]h$]h&]hhuh1hhjlhhhhhKubjk)}(hhh](jp)}(h 1. 简介h]h 1. 简介}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhKubjk)}(hhh](jp)}(h%1.1 何为操作性能值(OPP)?h]h%1.1 何为操作性能值(OPP)?}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhKubh)}(hX当今复杂的单片系统(SoC)由多个子模块组成,这些子模块会联合工作。在一个执行不同用例 的操作系统中,并不是SoC中的所有模块都需要一直以最高频率工作。为了促成这一点,SoC中 的子模块被分组为不同域,允许一些域以较低的电压和频率运行,而其它域则以较高的“电压/ 频率对”运行。h]hX当今复杂的单片系统(SoC)由多个子模块组成,这些子模块会联合工作。在一个执行不同用例 的操作系统中,并不是SoC中的所有模块都需要一直以最高频率工作。为了促成这一点,SoC中 的子模块被分组为不同域,允许一些域以较低的电压和频率运行,而其它域则以较高的“电压/ 频率对”运行。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hy设备按域支持的由频率电压对组成的离散的元组的集合,被称为操作性能值(组),或OPPs。h]hy设备按域支持的由频率电压对组成的离散的元组的集合,被称为操作性能值(组),或OPPs。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK$hjhhubh)}(h举例来说:h]h举例来说:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK&hjhhubh)}(h让我们考虑一个支持下述频率、电压值的内存保护单元(MPU)设备: {300MHz,最低电压为1V}, {800MHz,最低电压为1.2V}, {1GHz,最低电压为1.3V}h]h让我们考虑一个支持下述频率、电压值的内存保护单元(MPU)设备: {300MHz,最低电压为1V}, {800MHz,最低电压为1.2V}, {1GHz,最低电压为1.3V}}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK(hjhhubh)}(h我们能将它们表示为3个OPP,如下述{Hz, uV}元组(译注:频率的单位是赫兹,电压的单位是 微伏)。h]h我们能将它们表示为3个OPP,如下述{Hz, uV}元组(译注:频率的单位是赫兹,电压的单位是 微伏)。}(hj'hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK+hjhhubh bullet_list)}(hhh](j)}(h{300000000, 1000000}h]h)}(hj<h]h{300000000, 1000000}}(hj>hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK.hj:ubah}(h]h ]h"]h$]h&]uh1jhj7hhhhhNubj)}(h{800000000, 1200000}h]h)}(hjSh]h{800000000, 1200000}}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK/hjQubah}(h]h ]h"]h$]h&]uh1jhj7hhhhhNubj)}(h{1000000000, 1300000} h]h)}(h{1000000000, 1300000}h]h{1000000000, 1300000}}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK0hjhubah}(h]h ]h"]h$]h&]uh1jhj7hhhhhNubeh}(h]h ]h"]h$]h&]bullet-uh1j5hhhK.hjhhubeh}(h]id2ah ]h"]%1.1 何为操作性能值(opp)?ah$]h&]uh1jjhjhhhhhKubjk)}(hhh](jp)}(h1.2 操作性能值库h]h1.2 操作性能值库}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhK3ubh)}(hX2OPP库提供了一组辅助函数来组织和查询OPP信息。该库位于drivers/opp/目录下,其头文件 位于include/linux/pm_opp.h中。OPP库可以通过开启CONFIG_PM_OPP来启用。某些SoC, 如德州仪器的OMAP框架允许在不需要cpufreq的情况下可选地在某一OPP下启动。h]hX2OPP库提供了一组辅助函数来组织和查询OPP信息。该库位于drivers/opp/目录下,其头文件 位于include/linux/pm_opp.h中。OPP库可以通过开启CONFIG_PM_OPP来启用。某些SoC, 如德州仪器的OMAP框架允许在不需要cpufreq的情况下可选地在某一OPP下启动。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK5hjhhubh)}(hOPP库的典型用法如下::h]hOPP库的典型用法如下:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK9hjhhubh literal_block)}(h(用户) -> 注册一个默认的OPP集合 -> (库) (SoC框架) -> 在必要的情况下,对某些OPP进行修改 -> OPP layer -> 搜索/检索信息的查询 ->h]h(用户) -> 注册一个默认的OPP集合 -> (库) (SoC框架) -> 在必要的情况下,对某些OPP进行修改 -> OPP layer -> 搜索/检索信息的查询 ->}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhK;hjhhubh)}(hX5OPP层期望每个域由一个唯一的设备指针来表示。SoC框架在OPP层为每个设备注册了一组初始 OPP。这个链表的长度被期望是一个最优化的小数字,通常每个设备大约5个。初始链表包含了 一个OPP集合,这个集合被期望能在系统中安全使能。h]hX5OPP层期望每个域由一个唯一的设备指针来表示。SoC框架在OPP层为每个设备注册了一组初始 OPP。这个链表的长度被期望是一个最优化的小数字,通常每个设备大约5个。初始链表包含了 一个OPP集合,这个集合被期望能在系统中安全使能。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK?hjhhubjk)}(hhh](jp)}(h关于OPP可用性的说明h]h关于OPP可用性的说明}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhKDubh)}(hX.随着系统的运行,SoC框架可能会基于各种外部因素选择让某些OPP在每个设备上可用或不可用, 示例:温度管理或其它异常场景中,SoC框架可能会选择禁用一个较高频率的OPP以安全地继续 运行,直到该OPP被重新启用(如果可能)。h]hX.随着系统的运行,SoC框架可能会基于各种外部因素选择让某些OPP在每个设备上可用或不可用, 示例:温度管理或其它异常场景中,SoC框架可能会选择禁用一个较高频率的OPP以安全地继续 运行,直到该OPP被重新启用(如果可能)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKFhjhhubh)}(hOPP库在它的实现中达成了这个概念。以下操作函数只能对可用的OPP使用: dev_pm_opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count。h]hOPP库在它的实现中达成了这个概念。以下操作函数只能对可用的OPP使用: dev_pm_opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKJhjhhubh)}(hdev_pm_opp_find_freq_exact是用来查找OPP指针的,该指针可被用在dev_pm_opp_enable/ disable函数,使一个OPP在被需要时变为可用。h]hdev_pm_opp_find_freq_exact是用来查找OPP指针的,该指针可被用在dev_pm_opp_enable/ disable函数,使一个OPP在被需要时变为可用。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKNhjhhubh)}(hXq警告:如果对一个设备调用dev_pm_opp_enable/disable函数,OPP库的用户应该使用 dev_pm_opp_get_opp_count来刷新OPP的可用性计数。触发这些的具体机制,或者对有依赖的 子系统(比如cpufreq)的通知机制,都是由使用OPP库的SoC特定框架酌情处理的。在这些操作 中,同样需要注意刷新cpufreq表。h]hXq警告:如果对一个设备调用dev_pm_opp_enable/disable函数,OPP库的用户应该使用 dev_pm_opp_get_opp_count来刷新OPP的可用性计数。触发这些的具体机制,或者对有依赖的 子系统(比如cpufreq)的通知机制,都是由使用OPP库的SoC特定框架酌情处理的。在这些操作 中,同样需要注意刷新cpufreq表。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKQhjhhubeh}(h]id4ah ]h"]关于opp可用性的说明ah$]h&]uh1jjhjhhhhhKDubeh}(h]id3ah ]h"]1.2 操作性能值库ah$]h&]uh1jjhjhhhhhK3ubeh}(h]id1ah ]h"] 1. 简介ah$]h&]uh1jjhjlhhhhhKubjk)}(hhh](jp)}(h2. OPP链表初始注册h]h2. OPP链表初始注册}(hj?hhhNhNubah}(h]h ]h"]h$]h&]uh1johj<hhhhhKWubh)}(hXVSoC的实现会迭代调用dev_pm_opp_add函数来增加每个设备的OPP。预期SoC框架将以最优的 方式注册OPP条目 - 典型的数字范围小于5。通过注册OPP生成的OPP链表,在整个设备运行过程 中由OPP库维护。SoC框架随后可以使用dev_pm_opp_enable / disable函数动态地 控制OPP的可用性。h]hXVSoC的实现会迭代调用dev_pm_opp_add函数来增加每个设备的OPP。预期SoC框架将以最优的 方式注册OPP条目 - 典型的数字范围小于5。通过注册OPP生成的OPP链表,在整个设备运行过程 中由OPP库维护。SoC框架随后可以使用dev_pm_opp_enable / disable函数动态地 控制OPP的可用性。}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKXhj<hhubhdefinition_list)}(hhh]hdefinition_list_item)}(hXdev_pm_opp_add 为设备指针所指向的特定域添加一个新的OPP。OPP是用频率和电压定义的。一旦完成 添加,OPP被认为是可用的,可以用dev_pm_opp_enable/disable函数来控制其可用性。 OPP库内部用dev_pm_opp结构体存储并管理这些信息。这个函数可以被SoC框架根据SoC 的使用环境的需求来定义一个最优链表。 警告: 不要在中断上下文使用这个函数。 示例:: soc_pm_init() { /* 做一些事情 */ r = dev_pm_opp_add(mpu_dev, 1000000, 900000); if (!r) { pr_err("%s: unable to register mpu opp(%d)\n", r); goto no_cpufreq; } /* 做一些和cpufreq相关的事情 */ no_cpufreq: /* 做剩余的事情 */ } h](hterm)}(hdev_pm_opp_addh]hdev_pm_opp_add}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKshjbubh definition)}(hhh](h)}(hXp为设备指针所指向的特定域添加一个新的OPP。OPP是用频率和电压定义的。一旦完成 添加,OPP被认为是可用的,可以用dev_pm_opp_enable/disable函数来控制其可用性。 OPP库内部用dev_pm_opp结构体存储并管理这些信息。这个函数可以被SoC框架根据SoC 的使用环境的需求来定义一个最优链表。h]hXp为设备指针所指向的特定域添加一个新的OPP。OPP是用频率和电压定义的。一旦完成 添加,OPP被认为是可用的,可以用dev_pm_opp_enable/disable函数来控制其可用性。 OPP库内部用dev_pm_opp结构体存储并管理这些信息。这个函数可以被SoC框架根据SoC 的使用环境的需求来定义一个最优链表。}(hj{hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK^hjxubj\)}(hhh]ja)}(h8警告: 不要在中断上下文使用这个函数。 h](jg)}(h 警告:h]h 警告:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKdhjubjw)}(hhh]h)}(h-不要在中断上下文使用这个函数。h]h-不要在中断上下文使用这个函数。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKdhjubah}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhKdhjubah}(h]h ]h"]h$]h&]uh1j[hjxubh)}(h示例::h]h示例:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKfhjxubj)}(hX;soc_pm_init() { /* 做一些事情 */ r = dev_pm_opp_add(mpu_dev, 1000000, 900000); if (!r) { pr_err("%s: unable to register mpu opp(%d)\n", r); goto no_cpufreq; } /* 做一些和cpufreq相关的事情 */ no_cpufreq: /* 做剩余的事情 */ }h]hX;soc_pm_init() { /* 做一些事情 */ r = dev_pm_opp_add(mpu_dev, 1000000, 900000); if (!r) { pr_err("%s: unable to register mpu opp(%d)\n", r); goto no_cpufreq; } /* 做一些和cpufreq相关的事情 */ no_cpufreq: /* 做剩余的事情 */ }}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhhjxubeh}(h]h ]h"]h$]h&]uh1jvhjbubeh}(h]h ]h"]h$]h&]uh1j`hhhKshj]ubah}(h]h ]h"]h$]h&]uh1j[hj<hhhhhNubeh}(h]id5ah ]h"]2. opp链表初始注册ah$]h&]uh1jjhjlhhhhhKWubjk)}(hhh](jp)}(h3. OPP搜索函数h]h3. OPP搜索函数}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1johjhhhhhKvubh)}(hXncpufreq等高层框架对频率进行操作,为了将频率映射到相应的OPP,OPP库提供了便利的函数 来搜索OPP库内部管理的OPP链表。这些搜索函数如果找到匹配的OPP,将返回指向该OPP的指针, 否则返回错误。这些错误预计由标准的错误检查,如IS_ERR()来处理,并由调用者采取适当的 行动。h]hXncpufreq等高层框架对频率进行操作,为了将频率映射到相应的OPP,OPP库提供了便利的函数 来搜索OPP库内部管理的OPP链表。这些搜索函数如果找到匹配的OPP,将返回指向该OPP的指针, 否则返回错误。这些错误预计由标准的错误检查,如IS_ERR()来处理,并由调用者采取适当的 行动。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKwhjhhubh)}(h这些函数的调用者应在使用完OPP后调用dev_pm_opp_put()。否则,OPP的内存将永远不会 被释放,并导致内存泄露。h]h这些函数的调用者应在使用完OPP后调用dev_pm_opp_put()。否则,OPP的内存将永远不会 被释放,并导致内存泄露。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK|hjhhubj\)}(hhh](ja)}(hXvdev_pm_opp_find_freq_exact 根据 *精确的* 频率和可用性来搜索OPP。这个函数对默认不可用的OPP特别有用。 例子:在SoC框架检测到更高频率可用的情况下,它可以使用这个函数在调用 dev_pm_opp_enable之前找到OPP:: opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* 不要操作指针.. 只是做有效性检查.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* 触发合适的操作.. */ } else { dev_pm_opp_enable(dev,1000000000); } 注意: 这是唯一一个可以搜索不可用OPP的函数。 h](jg)}(hdev_pm_opp_find_freq_exacth]hdev_pm_opp_find_freq_exact}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKhj'ubjw)}(hhh](h)}(h根据 *精确的* 频率和可用性来搜索OPP。这个函数对默认不可用的OPP特别有用。 例子:在SoC框架检测到更高频率可用的情况下,它可以使用这个函数在调用 dev_pm_opp_enable之前找到OPP::h](h根据 }(hj<hhhNhNubhemphasis)}(h *精确的*h]h 精确的}(hjFhhhNhNubah}(h]h ]h"]h$]h&]uh1jDhj<ubh 频率和可用性来搜索OPP。这个函数对默认不可用的OPP特别有用。 例子:在SoC框架检测到更高频率可用的情况下,它可以使用这个函数在调用 dev_pm_opp_enable之前找到OPP:}(hj<hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj9ubj)}(hXopp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* 不要操作指针.. 只是做有效性检查.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* 触发合适的操作.. */ } else { dev_pm_opp_enable(dev,1000000000); }h]hXopp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* 不要操作指针.. 只是做有效性检查.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* 触发合适的操作.. */ } else { dev_pm_opp_enable(dev,1000000000); }}hj^sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj9ubj\)}(hhh]ja)}(hA注意: 这是唯一一个可以搜索不可用OPP的函数。 h](jg)}(h 注意:h]h 注意:}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKhjoubjw)}(hhh]h)}(h6这是唯一一个可以搜索不可用OPP的函数。h]h6这是唯一一个可以搜索不可用OPP的函数。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jvhjoubeh}(h]h ]h"]h$]h&]uh1j`hhhKhjlubah}(h]h ]h"]h$]h&]uh1j[hj9ubeh}(h]h ]h"]h$]h&]uh1jvhj'ubeh}(h]h ]h"]h$]h&]uh1j`hhhKhj$ubja)}(hX7dev_pm_opp_find_freq_floor 搜索一个 *最多* 提供指定频率的可用OPP。这个函数在搜索较小的匹配或按频率 递减的顺序操作OPP信息时很有用。 例子:要找的一个设备的最高OPP:: freq = ULONG_MAX; opp = dev_pm_opp_find_freq_floor(dev, &freq); dev_pm_opp_put(opp); h](jg)}(hdev_pm_opp_find_freq_floorh]hdev_pm_opp_find_freq_floor}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKhjubjw)}(hhh](h)}(h搜索一个 *最多* 提供指定频率的可用OPP。这个函数在搜索较小的匹配或按频率 递减的顺序操作OPP信息时很有用。 例子:要找的一个设备的最高OPP::h](h 搜索一个 }(hjhhhNhNubjE)}(h*最多*h]h最多}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jDhjubh 提供指定频率的可用OPP。这个函数在搜索较小的匹配或按频率 递减的顺序操作OPP信息时很有用。 例子:要找的一个设备的最高OPP:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hTfreq = ULONG_MAX; opp = dev_pm_opp_find_freq_floor(dev, &freq); dev_pm_opp_put(opp);h]hTfreq = ULONG_MAX; opp = dev_pm_opp_find_freq_floor(dev, &freq); dev_pm_opp_put(opp);}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjubeh}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhKhj$hhubja)}(hXdev_pm_opp_find_freq_ceil 搜索一个 *最少* 提供指定频率的可用OPP。这个函数在搜索较大的匹配或按频率 递增的顺序操作OPP信息时很有用。 例1:找到一个设备最小的OPP:: freq = 0; opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp); 例: 一个SoC的cpufreq_driver->target的简易实现:: soc_cpufreq_target(..) { /* 做策略检查等操作 */ /* 找到和请求最接近的频率 */ opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp); if (!IS_ERR(opp)) soc_switch_to_freq_voltage(freq); else /* 当不能满足请求时,要做的事 */ /* 做其它事 */ } h](jg)}(hdev_pm_opp_find_freq_ceilh]hdev_pm_opp_find_freq_ceil}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKhjubjw)}(hhh](h)}(h搜索一个 *最少* 提供指定频率的可用OPP。这个函数在搜索较大的匹配或按频率 递增的顺序操作OPP信息时很有用。 例1:找到一个设备最小的OPP::h](h 搜索一个 }(hjhhhNhNubjE)}(h*最少*h]h最少}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jDhjubh 提供指定频率的可用OPP。这个函数在搜索较大的匹配或按频率 递增的顺序操作OPP信息时很有用。 例1:找到一个设备最小的OPP:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hKfreq = 0; opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp);h]hKfreq = 0; opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp);}hj4sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjubh)}(h8例: 一个SoC的cpufreq_driver->target的简易实现::h]h7例: 一个SoC的cpufreq_driver->target的简易实现:}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hXlsoc_cpufreq_target(..) { /* 做策略检查等操作 */ /* 找到和请求最接近的频率 */ opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp); if (!IS_ERR(opp)) soc_switch_to_freq_voltage(freq); else /* 当不能满足请求时,要做的事 */ /* 做其它事 */ }h]hXlsoc_cpufreq_target(..) { /* 做策略检查等操作 */ /* 找到和请求最接近的频率 */ opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp); if (!IS_ERR(opp)) soc_switch_to_freq_voltage(freq); else /* 当不能满足请求时,要做的事 */ /* 做其它事 */ }}hjPsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjubeh}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhKhj$hhubeh}(h]h ]h"]h$]h&]uh1j[hjhhhNhNubeh}(h]id6ah ]h"]3. opp搜索函数ah$]h&]uh1jjhjlhhhhhKvubjk)}(hhh](jp)}(h4. OPP可用性控制函数h]h4. OPP可用性控制函数}(hj{hhhNhNubah}(h]h ]h"]h$]h&]uh1johjxhhhhhKubh)}(hXx在OPP库中注册的默认OPP链表也许无法满足所有可能的场景。OPP库提供了一套函数来修改 OPP链表中的某个OPP的可用性。这使得SoC框架能够精细地动态控制哪一组OPP是可用于操作 的。设计这些函数的目的是在诸如考虑温度时 *暂时地* 删除某个OPP(例如,在温度下降 之前不要使用某OPP)。h](hX#在OPP库中注册的默认OPP链表也许无法满足所有可能的场景。OPP库提供了一套函数来修改 OPP链表中的某个OPP的可用性。这使得SoC框架能够精细地动态控制哪一组OPP是可用于操作 的。设计这些函数的目的是在诸如考虑温度时 }(hjhhhNhNubjE)}(h *暂时地*h]h 暂时地}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jDhjubhJ 删除某个OPP(例如,在温度下降 之前不要使用某OPP)。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjxhhubj\)}(hhh](ja)}(h8警告: 不要在中断上下文使用这些函数。 h](jg)}(h 警告:h]h 警告:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKhjubjw)}(hhh]h)}(h-不要在中断上下文使用这些函数。h]h-不要在中断上下文使用这些函数。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhKhjubja)}(hXdev_pm_opp_enable 使一个OPP可用于操作。 例子:假设1GHz的OPP只有在SoC温度低于某个阈值时才可用。SoC框架的实现可能 会选择做以下事情:: if (cur_temp < temp_low_thresh) { /* 若1GHz未使能,则使能 */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* 仅仅是错误检查 */ if (!IS_ERR(opp)) ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; } h](jg)}(hdev_pm_opp_enableh]hdev_pm_opp_enable}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKhjubjw)}(hhh](h)}(h使一个OPP可用于操作。 例子:假设1GHz的OPP只有在SoC温度低于某个阈值时才可用。SoC框架的实现可能 会选择做以下事情::h]h使一个OPP可用于操作。 例子:假设1GHz的OPP只有在SoC温度低于某个阈值时才可用。SoC框架的实现可能 会选择做以下事情:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hXSif (cur_temp < temp_low_thresh) { /* 若1GHz未使能,则使能 */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* 仅仅是错误检查 */ if (!IS_ERR(opp)) ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; }h]hXSif (cur_temp < temp_low_thresh) { /* 若1GHz未使能,则使能 */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* 仅仅是错误检查 */ if (!IS_ERR(opp)) ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; }}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjubeh}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhKhjhhubja)}(hXdev_pm_opp_disable 使一个OPP不可用于操作。 例子:假设1GHz的OPP只有在SoC温度高于某个阈值时才可用。SoC框架的实现可能 会选择做以下事情:: if (cur_temp > temp_high_thresh) { /* 若1GHz已使能,则关闭 */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); dev_pm_opp_put(opp); /* 仅仅是错误检查 */ if (!IS_ERR(opp)) ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; } h](jg)}(hdev_pm_opp_disableh]hdev_pm_opp_disable}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKhjubjw)}(hhh](h)}(h使一个OPP不可用于操作。 例子:假设1GHz的OPP只有在SoC温度高于某个阈值时才可用。SoC框架的实现可能 会选择做以下事情::h]h使一个OPP不可用于操作。 例子:假设1GHz的OPP只有在SoC温度高于某个阈值时才可用。SoC框架的实现可能 会选择做以下事情:}(hj-hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj*ubj)}(hXTif (cur_temp > temp_high_thresh) { /* 若1GHz已使能,则关闭 */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); dev_pm_opp_put(opp); /* 仅仅是错误检查 */ if (!IS_ERR(opp)) ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; }h]hXTif (cur_temp > temp_high_thresh) { /* 若1GHz已使能,则关闭 */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); dev_pm_opp_put(opp); /* 仅仅是错误检查 */ if (!IS_ERR(opp)) ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; }}hj;sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj*ubeh}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhKhjhhubeh}(h]h ]h"]h$]h&]uh1j[hjxhhhhhNubeh}(h]id7ah ]h"]4. opp可用性控制函数ah$]h&]uh1jjhjlhhhhhKubjk)}(hhh](jp)}(h5. OPP数据检索函数h]h5. OPP数据检索函数}(hjfhhhNhNubah}(h]h ]h"]h$]h&]uh1johjchhhhhKubh)}(h由于OPP库对OPP信息进行了抽象化处理,因此需要一组函数来从dev_pm_opp结构体中提取 信息。一旦使用搜索函数检索到一个OPP指针,以下函数就可以被SoC框架用来检索OPP层 内部描述的信息。h]h由于OPP库对OPP信息进行了抽象化处理,因此需要一组函数来从dev_pm_opp结构体中提取 信息。一旦使用搜索函数检索到一个OPP指针,以下函数就可以被SoC框架用来检索OPP层 内部描述的信息。}(hjthhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjchhubj\)}(hhh](ja)}(hXdev_pm_opp_get_voltage 检索OPP指针描述的电压。 例子: 当cpufreq切换到到不同频率时,SoC框架需要用稳压器框架将OPP描述 的电压设置到提供电压的电源管理芯片中:: soc_switch_to_freq_voltage(freq) { /* 做一些事情 */ opp = dev_pm_opp_find_freq_ceil(dev, &freq); v = dev_pm_opp_get_voltage(opp); dev_pm_opp_put(opp); if (v) regulator_set_voltage(.., v); /* 做其它事 */ } h](jg)}(hdev_pm_opp_get_voltageh]hdev_pm_opp_get_voltage}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhKhjubjw)}(hhh](h)}(h检索OPP指针描述的电压。 例子: 当cpufreq切换到到不同频率时,SoC框架需要用稳压器框架将OPP描述 的电压设置到提供电压的电源管理芯片中::h]h检索OPP指针描述的电压。 例子: 当cpufreq切换到到不同频率时,SoC框架需要用稳压器框架将OPP描述 的电压设置到提供电压的电源管理芯片中:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hXsoc_switch_to_freq_voltage(freq) { /* 做一些事情 */ opp = dev_pm_opp_find_freq_ceil(dev, &freq); v = dev_pm_opp_get_voltage(opp); dev_pm_opp_put(opp); if (v) regulator_set_voltage(.., v); /* 做其它事 */ }h]hXsoc_switch_to_freq_voltage(freq) { /* 做一些事情 */ opp = dev_pm_opp_find_freq_ceil(dev, &freq); v = dev_pm_opp_get_voltage(opp); dev_pm_opp_put(opp); if (v) regulator_set_voltage(.., v); /* 做其它事 */ }}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjubeh}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhKhjubja)}(hXdev_pm_opp_get_freq 检索OPP指针描述的频率。 例子:比方说,SoC框架使用了几个辅助函数,通过这些函数,我们可以将OPP 指针传入,而不是传入额外的参数,用来处理一系列数据参数:: soc_cpufreq_target(..) { /* 做一些事情.. */ max_freq = ULONG_MAX; max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) r = soc_test_validity(max_opp, requested_opp); dev_pm_opp_put(max_opp); dev_pm_opp_put(requested_opp); /* 做其它事 */ } soc_test_validity(..) { if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) return -EINVAL; if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) return -EINVAL; /* 做一些事情.. */ } h](jg)}(hdev_pm_opp_get_freqh]hdev_pm_opp_get_freq}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhM hjubjw)}(hhh](h)}(h检索OPP指针描述的频率。 例子:比方说,SoC框架使用了几个辅助函数,通过这些函数,我们可以将OPP 指针传入,而不是传入额外的参数,用来处理一系列数据参数::h]h检索OPP指针描述的频率。 例子:比方说,SoC框架使用了几个辅助函数,通过这些函数,我们可以将OPP 指针传入,而不是传入额外的参数,用来处理一系列数据参数:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hXsoc_cpufreq_target(..) { /* 做一些事情.. */ max_freq = ULONG_MAX; max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) r = soc_test_validity(max_opp, requested_opp); dev_pm_opp_put(max_opp); dev_pm_opp_put(requested_opp); /* 做其它事 */ } soc_test_validity(..) { if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) return -EINVAL; if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) return -EINVAL; /* 做一些事情.. */ }h]hXsoc_cpufreq_target(..) { /* 做一些事情.. */ max_freq = ULONG_MAX; max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) r = soc_test_validity(max_opp, requested_opp); dev_pm_opp_put(max_opp); dev_pm_opp_put(requested_opp); /* 做其它事 */ } soc_test_validity(..) { if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) return -EINVAL; if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) return -EINVAL; /* 做一些事情.. */ }}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjubeh}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhM hjhhubja)}(hXdev_pm_opp_get_opp_count 检索某个设备可用的OPP数量。 例子:假设SoC中的一个协处理器需要知道某个表中的可用频率,主处理器可以 按如下方式发出通知:: soc_notify_coproc_available_frequencies() { /* 做一些事情 */ num_available = dev_pm_opp_get_opp_count(dev); speeds = kcalloc(num_available, sizeof(u32), GFP_KERNEL); /* 按升序填充表 */ freq = 0; while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { speeds[i] = freq; freq++; i++; dev_pm_opp_put(opp); } soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); /* 做其它事 */ } h](jg)}(hdev_pm_opp_get_opp_counth]hdev_pm_opp_get_opp_count}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhM!hjubjw)}(hhh](h)}(h检索某个设备可用的OPP数量。 例子:假设SoC中的一个协处理器需要知道某个表中的可用频率,主处理器可以 按如下方式发出通知::h]h检索某个设备可用的OPP数量。 例子:假设SoC中的一个协处理器需要知道某个表中的可用频率,主处理器可以 按如下方式发出通知:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hjubj)}(hXsoc_notify_coproc_available_frequencies() { /* 做一些事情 */ num_available = dev_pm_opp_get_opp_count(dev); speeds = kcalloc(num_available, sizeof(u32), GFP_KERNEL); /* 按升序填充表 */ freq = 0; while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { speeds[i] = freq; freq++; i++; dev_pm_opp_put(opp); } soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); /* 做其它事 */ }h]hXsoc_notify_coproc_available_frequencies() { /* 做一些事情 */ num_available = dev_pm_opp_get_opp_count(dev); speeds = kcalloc(num_available, sizeof(u32), GFP_KERNEL); /* 按升序填充表 */ freq = 0; while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { speeds[i] = freq; freq++; i++; dev_pm_opp_put(opp); } soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); /* 做其它事 */ }}hj"sbah}(h]h ]h"]h$]h&]hhuh1jhhhMhjubeh}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhM!hjhhubeh}(h]h ]h"]h$]h&]uh1j[hjchhhhhNubeh}(h]id8ah ]h"]5. opp数据检索函数ah$]h&]uh1jjhjlhhhhhKubjk)}(hhh](jp)}(h6. 数据结构h]h6. 数据结构}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1johjJhhhhhM$ubh)}(h通常,一个SoC包含多个可变电压域。每个域由一个设备指针描述。和OPP之间的关系可以 按以下方式描述::h]h通常,一个SoC包含多个可变电压域。每个域由一个设备指针描述。和OPP之间的关系可以 按以下方式描述:}(hj[hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM%hjJhhubj)}(hSoC |- device 1 | |- opp 1 (availability, freq, voltage) | |- opp 2 .. ... ... | `- opp n .. |- device 2 ... `- device mh]hSoC |- device 1 | |- opp 1 (availability, freq, voltage) | |- opp 2 .. ... ... | `- opp n .. |- device 2 ... `- device m}hjisbah}(h]h ]h"]h$]h&]hhuh1jhhhM(hjJhhubh)}(hOPP库维护着一个内部链表,SoC框架使用上文描述的各个函数来填充和访问。然而,描述 真实OPP和域的结构体是OPP库自身的内部组成,以允许合适的抽象在不同系统中得到复用。h]hOPP库维护着一个内部链表,SoC框架使用上文描述的各个函数来填充和访问。然而,描述 真实OPP和域的结构体是OPP库自身的内部组成,以允许合适的抽象在不同系统中得到复用。}(hjwhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM2hjJhhubj\)}(hhh](ja)}(hXstruct dev_pm_opp OPP库的内部数据结构,用于表示一个OPP。除了频率、电压、可用性信息外, 它还包含OPP库运行所需的内部统计信息。指向这个结构体的指针被提供给 用户(比如SoC框架)使用,在与OPP层的交互中作为OPP的标识符。 警告: 结构体dev_pm_opp的指针不应该由用户解析或修改。一个实例的默认值由 dev_pm_opp_add填充,但OPP的可用性由dev_pm_opp_enable/disable函数 修改。 h](jg)}(hstruct dev_pm_opph]hstruct dev_pm_opp}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhM=hjubjw)}(hhh](h)}(hXOPP库的内部数据结构,用于表示一个OPP。除了频率、电压、可用性信息外, 它还包含OPP库运行所需的内部统计信息。指向这个结构体的指针被提供给 用户(比如SoC框架)使用,在与OPP层的交互中作为OPP的标识符。h]hXOPP库的内部数据结构,用于表示一个OPP。除了频率、电压、可用性信息外, 它还包含OPP库运行所需的内部统计信息。指向这个结构体的指针被提供给 用户(比如SoC框架)使用,在与OPP层的交互中作为OPP的标识符。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM6hjubj\)}(hhh]ja)}(h警告: 结构体dev_pm_opp的指针不应该由用户解析或修改。一个实例的默认值由 dev_pm_opp_add填充,但OPP的可用性由dev_pm_opp_enable/disable函数 修改。 h](jg)}(h 警告:h]h 警告:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhM=hjubjw)}(hhh]h)}(h结构体dev_pm_opp的指针不应该由用户解析或修改。一个实例的默认值由 dev_pm_opp_add填充,但OPP的可用性由dev_pm_opp_enable/disable函数 修改。h]h结构体dev_pm_opp的指针不应该由用户解析或修改。一个实例的默认值由 dev_pm_opp_add填充,但OPP的可用性由dev_pm_opp_enable/disable函数 修改。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM;hjubah}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhM=hjubah}(h]h ]h"]h$]h&]uh1j[hjubeh}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhM=hjubja)}(hstruct device 这用于向OPP层标识一个域。设备的性质和它的实现是由OPP库的用户决定的, 如SoC框架。 h](jg)}(h struct deviceh]h struct device}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jfhhhMAhjubjw)}(hhh]h)}(hs这用于向OPP层标识一个域。设备的性质和它的实现是由OPP库的用户决定的, 如SoC框架。h]hs这用于向OPP层标识一个域。设备的性质和它的实现是由OPP库的用户决定的, 如SoC框架。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM@hjubah}(h]h ]h"]h$]h&]uh1jvhjubeh}(h]h ]h"]h$]h&]uh1j`hhhMAhjhhubeh}(h]h ]h"]h$]h&]uh1j[hjJhhhNhNubh)}(hb总体来说,以一个简化的视角看,对数据结构的操作可以描述为下面各图::h]ha总体来说,以一个简化的视角看,对数据结构的操作可以描述为下面各图:}(hj$hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMChjJhhubj)}(hX初始化 / 修改: +-----+ /- dev_pm_opp_enable dev_pm_opp_add --> | opp | <------- | +-----+ \- dev_pm_opp_disable \-------> domain_info(device) 搜索函数: /-- dev_pm_opp_find_freq_ceil ---\ +-----+ domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | \-- dev_pm_opp_find_freq_floor ---/ +-----+ 检索函数: +-----+ /- dev_pm_opp_get_voltage | opp | <--- +-----+ \- dev_pm_opp_get_freq domain_info <- dev_pm_opp_get_opp_counth]hX初始化 / 修改: +-----+ /- dev_pm_opp_enable dev_pm_opp_add --> | opp | <------- | +-----+ \- dev_pm_opp_disable \-------> domain_info(device) 搜索函数: /-- dev_pm_opp_find_freq_ceil ---\ +-----+ domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | \-- dev_pm_opp_find_freq_floor ---/ +-----+ 检索函数: +-----+ /- dev_pm_opp_get_voltage | opp | <--- +-----+ \- dev_pm_opp_get_freq domain_info <- dev_pm_opp_get_opp_count}hj2sbah}(h]h ]h"]h$]h&]hhuh1jhhhMEhjJhhubeh}(h]id9ah ]h"]6. 数据结构ah$]h&]uh1jjhjlhhhhhM$ubeh}(h]oppah ]h"]操作性能值(opp)库ah$]h&]uh1jjhhhhhhhK ubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(joN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjserror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourcehnj _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jMjJj9j6jjj1j.j)j&jjjujrj`j]jGjDjEjBu nametypes}(jMj9jj1j)jjuj`jGjEuh}(jJjlj6jjjj.jj&jjj<jrjj]jxjDjcjBjJu footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jK sRparse_messages]hsystem_message)}(hhh]h)}(h:Enumerated list start value not ordinal-1: "C" (ordinal 3)h]h>Enumerated list start value not ordinal-1: “C” (ordinal 3)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypeINFOsourcehnjlineK uh1jhjlhhhhhKubatransform_messages] transformerN include_log].Documentation/translations/zh_CN/power/opp.rst(NNNNta decorationNhhub.