€•úÎŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ/translations/zh_CN/power/opp”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/zh_TW/power/opp”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/it_IT/power/opp”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/ja_JP/power/opp”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/ko_KR/power/opp”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/pt_BR/power/opp”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ/translations/sp_SP/power/opp”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒ*Operating Performance Points (OPP) Library”h]”hŒ*Operating Performance Points (OPP) Library”…””}”(hh¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhh·h²hh³Œ7/var/lib/git/docbuild/linux/Documentation/power/opp.rst”h´KubhŒenumerated_list”“”)”}”(hhh]”hŒ list_item”“”)”}”(hŒE2009-2010 Nishanth Menon , Texas Instruments Incorporated ”h]”hŒ paragraph”“”)”}”(hŒD2009-2010 Nishanth Menon , Texas Instruments Incorporated”h]”(hŒ2009-2010 Nishanth Menon <”…””}”(hhØh²hh³Nh´NubhŒ reference”“”)”}”(hŒ nm@ti.com”h]”hŒ nm@ti.com”…””}”(hhâh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œmailto:nm@ti.com”uh1hàhhØubhŒ!>, Texas Instruments Incorporated”…””}”(hhØh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KhhÒubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhhÍh²hh³hÊh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œ upperalpha”Œprefix”Œ(”Œsuffix”Œ)”Œstart”Kuh1hËhh·h²hh³hÊh´KubhŒcomment”“”)”}”(hŒ«Contents 1. Introduction 2. Initial OPP List Registration 3. OPP Search Functions 4. OPP Availability Control Functions 5. OPP Data Retrieval Functions 6. Data Structures”h]”hŒ«Contents 1. Introduction 2. Initial OPP List Registration 3. OPP Search Functions 4. OPP Availability Control Functions 5. OPP Data Retrieval Functions 6. Data Structures”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒ1. Introduction”h]”hŒ1. Introduction”…””}”(hj$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj!h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒ11.1 What is an Operating Performance Point (OPP)?”h]”hŒ11.1 What is an Operating Performance Point (OPP)?”…””}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj2h²hh³hÊh´Kubh×)”}”(hX¨Complex SoCs of today consists of a multiple sub-modules working in conjunction. In an operational system executing varied use cases, not all modules in the SoC need to function at their highest performing frequency all the time. To facilitate this, sub-modules in a SoC are grouped into domains, allowing some domains to run at lower voltage and frequency while other domains run at voltage/frequency pairs that are higher.”h]”hX¨Complex SoCs of today consists of a multiple sub-modules working in conjunction. In an operational system executing varied use cases, not all modules in the SoC need to function at their highest performing frequency all the time. To facilitate this, sub-modules in a SoC are grouped into domains, allowing some domains to run at lower voltage and frequency while other domains run at voltage/frequency pairs that are higher.”…””}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Khj2h²hubh×)”}”(hŒThe set of discrete tuples consisting of frequency and voltage pairs that the device will support per domain are called Operating Performance Points or OPPs.”h]”hŒThe set of discrete tuples consisting of frequency and voltage pairs that the device will support per domain are called Operating Performance Points or OPPs.”…””}”(hjQh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Khj2h²hubh×)”}”(hŒAs an example:”h]”hŒAs an example:”…””}”(hj_h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K!hj2h²hubh×)”}”(hŒ¥Let us consider an MPU device which supports the following: {300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V}, {1GHz at minimum voltage of 1.3V}”h]”hŒ¥Let us consider an MPU device which supports the following: {300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V}, {1GHz at minimum voltage of 1.3V}”…””}”(hjmh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K#hj2h²hubh×)”}”(hŒFWe can represent these as three OPPs as the following {Hz, uV} tuples:”h]”hŒFWe can represent these as three OPPs as the following {Hz, uV} tuples:”…””}”(hj{h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K'hj2h²hubhŒ bullet_list”“”)”}”(hhh]”(hÑ)”}”(hŒ{300000000, 1000000}”h]”h×)”}”(hjh]”hŒ{300000000, 1000000}”…””}”(hj’h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K)hjŽubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhj‹h²hh³hÊh´NubhÑ)”}”(hŒ{800000000, 1200000}”h]”h×)”}”(hj§h]”hŒ{800000000, 1200000}”…””}”(hj©h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K*hj¥ubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhj‹h²hh³hÊh´NubhÑ)”}”(hŒ{1000000000, 1300000} ”h]”h×)”}”(hŒ{1000000000, 1300000}”h]”hŒ{1000000000, 1300000}”…””}”(hjÀh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K+hj¼ubah}”(h]”h ]”h"]”h$]”h&]”uh1hÐhj‹h²hh³hÊh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1j‰h³hÊh´K)hj2h²hubeh}”(h]”Œ*what-is-an-operating-performance-point-opp”ah ]”h"]”Œ11.1 what is an operating performance point (opp)?”ah$]”h&]”uh1hµhj!h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒ(1.2 Operating Performance Points Library”h]”hŒ(1.2 Operating Performance Points Library”…””}”(hjçh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjäh²hh³hÊh´K.ubh×)”}”(hX–OPP library provides a set of helper functions to organize and query the OPP information. The library is located in drivers/opp/ directory and the header is located in include/linux/pm_opp.h. OPP library can be enabled by enabling CONFIG_PM_OPP from power management menuconfig menu. Certain SoCs such as Texas Instrument's OMAP framework allows to optionally boot at a certain OPP without needing cpufreq.”h]”hX˜OPP library provides a set of helper functions to organize and query the OPP information. The library is located in drivers/opp/ directory and the header is located in include/linux/pm_opp.h. OPP library can be enabled by enabling CONFIG_PM_OPP from power management menuconfig menu. Certain SoCs such as Texas Instrument’s OMAP framework allows to optionally boot at a certain OPP without needing cpufreq.”…””}”(hjõh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K0hjäh²hubh×)”}”(hŒ0Typical usage of the OPP library is as follows::”h]”hŒ/Typical usage of the OPP library is as follows:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K7hjäh²hubhŒ literal_block”“”)”}”(hŒÙ(users) -> registers a set of default OPPs -> (library) SoC framework -> modifies on required cases certain OPPs -> OPP layer -> queries to search/retrieve information ->”h]”hŒÙ(users) -> registers a set of default OPPs -> (library) SoC framework -> modifies on required cases certain OPPs -> OPP layer -> queries to search/retrieve information ->”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´K9hjäh²hubh×)”}”(hX`OPP layer expects each domain to be represented by a unique device pointer. SoC framework registers a set of initial OPPs per device with the OPP layer. This list is expected to be an optimally small number typically around 5 per device. This initial list contains a set of OPPs that the framework expects to be safely enabled by default in the system.”h]”hX`OPP layer expects each domain to be represented by a unique device pointer. SoC framework registers a set of initial OPPs per device with the OPP layer. This list is expected to be an optimally small number typically around 5 per device. This initial list contains a set of OPPs that the framework expects to be safely enabled by default in the system.”…””}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K=hjäh²hubh¶)”}”(hhh]”(h»)”}”(hŒNote on OPP Availability”h]”hŒNote on OPP Availability”…””}”(hj2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj/h²hh³hÊh´KDubh×)”}”(hXpAs the system proceeds to operate, SoC framework may choose to make certain OPPs available or not available on each device based on various external factors. Example usage: Thermal management or other exceptional situations where SoC framework might choose to disable a higher frequency OPP to safely continue operations until that OPP could be re-enabled if possible.”h]”hXpAs the system proceeds to operate, SoC framework may choose to make certain OPPs available or not available on each device based on various external factors. Example usage: Thermal management or other exceptional situations where SoC framework might choose to disable a higher frequency OPP to safely continue operations until that OPP could be re-enabled if possible.”…””}”(hj@h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KFhj/h²hubh×)”}”(hŒêOPP library facilitates this concept in its implementation. The following operational functions operate only on available opps: dev_pm_opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count.”h]”hŒêOPP library facilitates this concept in its implementation. The following operational functions operate only on available opps: dev_pm_opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count.”…””}”(hjNh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KLhj/h²hubh×)”}”(hŒ«dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then be used for dev_pm_opp_enable/disable functions to make an opp available as required.”h]”hŒ«dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then be used for dev_pm_opp_enable/disable functions to make an opp available as required.”…””}”(hj\h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KQhj/h²hubh×)”}”(hX¿WARNING: Users of OPP library should refresh their availability count using get_opp_count if dev_pm_opp_enable/disable functions are invoked for a device, the exact mechanism to trigger these or the notification mechanism to other dependent subsystems such as cpufreq are left to the discretion of the SoC specific framework which uses the OPP library. Similar care needs to be taken care to refresh the cpufreq table in cases of these operations.”h]”hX¿WARNING: Users of OPP library should refresh their availability count using get_opp_count if dev_pm_opp_enable/disable functions are invoked for a device, the exact mechanism to trigger these or the notification mechanism to other dependent subsystems such as cpufreq are left to the discretion of the SoC specific framework which uses the OPP library. Similar care needs to be taken care to refresh the cpufreq table in cases of these operations.”…””}”(hjjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KUhj/h²hubeh}”(h]”Œnote-on-opp-availability”ah ]”h"]”Œnote on opp availability”ah$]”h&]”uh1hµhjäh²hh³hÊh´KDubeh}”(h]”Œ$operating-performance-points-library”ah ]”h"]”Œ(1.2 operating performance points library”ah$]”h&]”uh1hµhj!h²hh³hÊh´K.ubeh}”(h]”Œ introduction”ah ]”h"]”Œ1. introduction”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒ 2. Initial OPP List Registration”h]”hŒ 2. Initial OPP List Registration”…””}”(hj“h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjh²hh³hÊh´K]ubh×)”}”(hX¾The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per device. It is expected that the SoC framework will register the OPP entries optimally- typical numbers range to be less than 5. The list generated by registering the OPPs is maintained by OPP library throughout the device operation. The SoC framework can subsequently control the availability of the OPPs dynamically using the dev_pm_opp_enable / disable functions.”h]”hX¾The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per device. It is expected that the SoC framework will register the OPP entries optimally- typical numbers range to be less than 5. The list generated by registering the OPPs is maintained by OPP library throughout the device operation. The SoC framework can subsequently control the availability of the OPPs dynamically using the dev_pm_opp_enable / disable functions.”…””}”(hj¡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K^hjh²hubhŒdefinition_list”“”)”}”(hhh]”hŒdefinition_list_item”“”)”}”(hXXdev_pm_opp_add Add a new OPP for a specific domain represented by the device pointer. The OPP is defined using the frequency and voltage. Once added, the OPP is assumed to be available and control of its availability can be done with the dev_pm_opp_enable/disable functions. OPP library internally stores and manages this information in the dev_pm_opp struct. This function may be used by SoC framework to define a optimal list as per the demands of SoC usage environment. WARNING: Do not use this function in interrupt context. Example:: soc_pm_init() { /* Do things */ 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; } /* Do cpufreq things */ no_cpufreq: /* Do remaining things */ } ”h]”(hŒterm”“”)”}”(hŒdev_pm_opp_add”h]”hŒdev_pm_opp_add”…””}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´K~hj¶ubhŒ definition”“”)”}”(hhh]”(h×)”}”(hXÉAdd a new OPP for a specific domain represented by the device pointer. The OPP is defined using the frequency and voltage. Once added, the OPP is assumed to be available and control of its availability can be done with the dev_pm_opp_enable/disable functions. OPP library internally stores and manages this information in the dev_pm_opp struct. This function may be used by SoC framework to define a optimal list as per the demands of SoC usage environment.”h]”hXÉAdd a new OPP for a specific domain represented by the device pointer. The OPP is defined using the frequency and voltage. Once added, the OPP is assumed to be available and control of its availability can be done with the dev_pm_opp_enable/disable functions. OPP library internally stores and manages this information in the dev_pm_opp struct. This function may be used by SoC framework to define a optimal list as per the demands of SoC usage environment.”…””}”(hjÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KfhjÌubj°)”}”(hhh]”jµ)”}”(hŒ8WARNING: Do not use this function in interrupt context. ”h]”(j»)”}”(hŒWARNING:”h]”hŒWARNING:”…””}”(hjäh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´KohjàubjË)”}”(hhh]”h×)”}”(hŒ.Do not use this function in interrupt context.”h]”hŒ.Do not use this function in interrupt context.”…””}”(hjõh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Kohjòubah}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjàubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´KohjÝubah}”(h]”h ]”h"]”h$]”h&]”uh1j¯hjÌubh×)”}”(hŒ Example::”h]”hŒExample:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KqhjÌubj)”}”(hX%soc_pm_init() { /* Do things */ 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; } /* Do cpufreq things */ no_cpufreq: /* Do remaining things */ }”h]”hX%soc_pm_init() { /* Do things */ 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; } /* Do cpufreq things */ no_cpufreq: /* Do remaining things */ }”…””}”hj#sbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´KshjÌubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhj¶ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´K~hj±ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¯hjh²hh³hÊh´Nubeh}”(h]”Œinitial-opp-list-registration”ah ]”h"]”Œ 2. initial opp list registration”ah$]”h&]”uh1hµhh·h²hh³hÊh´K]ubh¶)”}”(hhh]”(h»)”}”(hŒ3. OPP Search Functions”h]”hŒ3. OPP Search Functions”…””}”(hjNh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjKh²hh³hÊh´Kubh×)”}”(hXÂHigh level framework such as cpufreq operates on frequencies. To map the frequency back to the corresponding OPP, OPP library provides handy functions to search the OPP list that OPP library internally manages. These search functions return the matching pointer representing the opp if a match is found, else returns error. These errors are expected to be handled by standard error checks such as IS_ERR() and appropriate actions taken by the caller.”h]”hXÂHigh level framework such as cpufreq operates on frequencies. To map the frequency back to the corresponding OPP, OPP library provides handy functions to search the OPP list that OPP library internally manages. These search functions return the matching pointer representing the opp if a match is found, else returns error. These errors are expected to be handled by standard error checks such as IS_ERR() and appropriate actions taken by the caller.”…””}”(hj\h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K‚hjKh²hubh×)”}”(hŒ¡Callers of these functions shall call dev_pm_opp_put() after they have used the OPP. Otherwise the memory for the OPP will never get freed and result in memleak.”h]”hŒ¡Callers of these functions shall call dev_pm_opp_put() after they have used the OPP. Otherwise the memory for the OPP will never get freed and result in memleak.”…””}”(hjjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K‰hjKh²hubj°)”}”(hhh]”(jµ)”}”(hXdev_pm_opp_find_freq_exact Search for an OPP based on an *exact* frequency and availability. This function is especially useful to enable an OPP which is not available by default. Example: In a case when SoC framework detects a situation where a higher frequency could be made available, it can use this function to find the OPP prior to call the dev_pm_opp_enable to actually make it available:: opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* dont operate on the pointer.. just do a sanity check.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* trigger appropriate actions.. */ } else { dev_pm_opp_enable(dev,1000000000); } NOTE: This is the only search function that operates on OPPs which are not available. ”h]”(j»)”}”(hŒdev_pm_opp_find_freq_exact”h]”hŒdev_pm_opp_find_freq_exact”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´K¢hj{ubjË)”}”(hhh]”(h×)”}”(hXqSearch for an OPP based on an *exact* frequency and availability. This function is especially useful to enable an OPP which is not available by default. Example: In a case when SoC framework detects a situation where a higher frequency could be made available, it can use this function to find the OPP prior to call the dev_pm_opp_enable to actually make it available::”h]”(hŒSearch for an OPP based on an ”…””}”(hjh²hh³Nh´NubhŒemphasis”“”)”}”(hŒ*exact*”h]”hŒexact”…””}”(hjšh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j˜hjubhXK frequency and availability. This function is especially useful to enable an OPP which is not available by default. Example: In a case when SoC framework detects a situation where a higher frequency could be made available, it can use this function to find the OPP prior to call the dev_pm_opp_enable to actually make it available:”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KŽhjubj)”}”(hX*opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* dont operate on the pointer.. just do a sanity check.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* trigger appropriate actions.. */ } else { dev_pm_opp_enable(dev,1000000000); }”h]”hX*opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* dont operate on the pointer.. just do a sanity check.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* trigger appropriate actions.. */ } else { dev_pm_opp_enable(dev,1000000000); }”…””}”hj²sbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´K–hjubj°)”}”(hhh]”jµ)”}”(hŒVNOTE: This is the only search function that operates on OPPs which are not available. ”h]”(j»)”}”(hŒNOTE:”h]”hŒNOTE:”…””}”(hjÇh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´K¢hjÃubjË)”}”(hhh]”h×)”}”(hŒOThis is the only search function that operates on OPPs which are not available.”h]”hŒOThis is the only search function that operates on OPPs which are not available.”…””}”(hjØh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K¡hjÕubah}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjÃubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´K¢hjÀubah}”(h]”h ]”h"]”h$]”h&]”uh1j¯hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhj{ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´K¢hjxubjµ)”}”(hXldev_pm_opp_find_freq_floor Search for an available OPP which is *at most* the provided frequency. This function is useful while searching for a lesser match OR operating on OPP information in the order of decreasing frequency. Example: To find the highest opp for a device:: freq = ULONG_MAX; opp = dev_pm_opp_find_freq_floor(dev, &freq); dev_pm_opp_put(opp); ”h]”(j»)”}”(hŒdev_pm_opp_find_freq_floor”h]”hŒdev_pm_opp_find_freq_floor”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´K­hjubjË)”}”(hhh]”(h×)”}”(hŒ÷Search for an available OPP which is *at most* the provided frequency. This function is useful while searching for a lesser match OR operating on OPP information in the order of decreasing frequency. Example: To find the highest opp for a device::”h]”(hŒ%Search for an available OPP which is ”…””}”(hjh²hh³Nh´Nubj™)”}”(hŒ *at most*”h]”hŒat most”…””}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j˜hjubhŒÈ the provided frequency. This function is useful while searching for a lesser match OR operating on OPP information in the order of decreasing frequency. Example: To find the highest opp for a device:”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K¥hjubj)”}”(hŒTfreq = ULONG_MAX; opp = dev_pm_opp_find_freq_floor(dev, &freq); dev_pm_opp_put(opp);”h]”hŒTfreq = ULONG_MAX; opp = dev_pm_opp_find_freq_floor(dev, &freq); dev_pm_opp_put(opp);”…””}”hj9sbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´K«hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´K­hjxh²hubjµ)”}”(hX=dev_pm_opp_find_freq_ceil Search for an available OPP which is *at least* the provided frequency. This function is useful while searching for a higher match OR operating on OPP information in the order of increasing frequency. Example 1: To find the lowest opp for a device:: freq = 0; opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp); Example 2: A simplified implementation of a SoC cpufreq_driver->target:: soc_cpufreq_target(..) { /* Do stuff like policy checks etc. */ /* Find the best frequency match for the req */ 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 /* do something when we can't satisfy the req */ /* do other stuff */ } ”h]”(j»)”}”(hŒdev_pm_opp_find_freq_ceil”h]”hŒdev_pm_opp_find_freq_ceil”…””}”(hjWh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´KÇhjSubjË)”}”(hhh]”(h×)”}”(hŒùSearch for an available OPP which is *at least* the provided frequency. This function is useful while searching for a higher match OR operating on OPP information in the order of increasing frequency. Example 1: To find the lowest opp for a device::”h]”(hŒ%Search for an available OPP which is ”…””}”(hjhh²hh³Nh´Nubj™)”}”(hŒ *at least*”h]”hŒat least”…””}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j˜hjhubhŒÉ the provided frequency. This function is useful while searching for a higher match OR operating on OPP information in the order of increasing frequency. Example 1: To find the lowest opp for a device:”…””}”(hjhh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´K°hjeubj)”}”(hŒKfreq = 0; opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp);”h]”hŒKfreq = 0; opp = dev_pm_opp_find_freq_ceil(dev, &freq); dev_pm_opp_put(opp);”…””}”hjˆsbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´K¶hjeubh×)”}”(hŒHExample 2: A simplified implementation of a SoC cpufreq_driver->target::”h]”hŒGExample 2: A simplified implementation of a SoC cpufreq_driver->target:”…””}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Kºhjeubj)”}”(hXsoc_cpufreq_target(..) { /* Do stuff like policy checks etc. */ /* Find the best frequency match for the req */ 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 /* do something when we can't satisfy the req */ /* do other stuff */ }”h]”hXsoc_cpufreq_target(..) { /* Do stuff like policy checks etc. */ /* Find the best frequency match for the req */ 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 /* do something when we can't satisfy the req */ /* do other stuff */ }”…””}”hj¤sbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´K¼hjeubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjSubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´KÇhjxh²hubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¯hjKh²hh³Nh´Nubeh}”(h]”Œopp-search-functions”ah ]”h"]”Œ3. opp search functions”ah$]”h&]”uh1hµhh·h²hh³hÊh´Kubh¶)”}”(hhh]”(h»)”}”(hŒ%4. OPP Availability Control Functions”h]”hŒ%4. OPP Availability Control Functions”…””}”(hjÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjÌh²hh³hÊh´KÊubh×)”}”(hXÏA default OPP list registered with the OPP library may not cater to all possible situation. The OPP library provides a set of functions to modify the availability of a OPP within the OPP list. This allows SoC frameworks to have fine grained dynamic control of which sets of OPPs are operationally available. These functions are intended to *temporarily* remove an OPP in conditions such as thermal considerations (e.g. don't use OPPx until the temperature drops).”h]”(hXTA default OPP list registered with the OPP library may not cater to all possible situation. The OPP library provides a set of functions to modify the availability of a OPP within the OPP list. This allows SoC frameworks to have fine grained dynamic control of which sets of OPPs are operationally available. These functions are intended to ”…””}”(hjÝh²hh³Nh´Nubj™)”}”(hŒ *temporarily*”h]”hŒ temporarily”…””}”(hjåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j˜hjÝubhŒp remove an OPP in conditions such as thermal considerations (e.g. don’t use OPPx until the temperature drops).”…””}”(hjÝh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KËhjÌh²hubj°)”}”(hhh]”(jµ)”}”(hŒ:WARNING: Do not use these functions in interrupt context. ”h]”(j»)”}”(hŒWARNING:”h]”hŒWARNING:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´KÓhjubjË)”}”(hhh]”h×)”}”(hŒ0Do not use these functions in interrupt context.”h]”hŒ0Do not use these functions in interrupt context.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KÓhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´KÓhjýubjµ)”}”(hXTdev_pm_opp_enable Make a OPP available for operation. Example: Lets say that 1GHz OPP is to be made available only if the SoC temperature is lower than a certain threshold. The SoC framework implementation might choose to do something as follows:: if (cur_temp < temp_low_thresh) { /* Enable 1GHz if it was disabled */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* just error check */ if (!IS_ERR(opp)) ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; } ”h]”(j»)”}”(hŒdev_pm_opp_enable”h]”hŒdev_pm_opp_enable”…””}”(hj3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´Kähj/ubjË)”}”(hhh]”(h×)”}”(hŒåMake a OPP available for operation. Example: Lets say that 1GHz OPP is to be made available only if the SoC temperature is lower than a certain threshold. The SoC framework implementation might choose to do something as follows::”h]”hŒäMake a OPP available for operation. Example: Lets say that 1GHz OPP is to be made available only if the SoC temperature is lower than a certain threshold. The SoC framework implementation might choose to do something as follows:”…””}”(hjDh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´KÖhjAubj)”}”(hXPif (cur_temp < temp_low_thresh) { /* Enable 1GHz if it was disabled */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* just error check */ if (!IS_ERR(opp)) ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; }”h]”hXPif (cur_temp < temp_low_thresh) { /* Enable 1GHz if it was disabled */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); dev_pm_opp_put(opp); /* just error check */ if (!IS_ERR(opp)) ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; }”…””}”hjRsbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´KÛhjAubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhj/ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´Kähjýh²hubjµ)”}”(hXIdev_pm_opp_disable Make an OPP to be not available for operation Example: Lets say that 1GHz OPP is to be disabled if the temperature exceeds a threshold value. The SoC framework implementation might choose to do something as follows:: if (cur_temp > temp_high_thresh) { /* Disable 1GHz if it was enabled */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); dev_pm_opp_put(opp); /* just error check */ if (!IS_ERR(opp)) ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; } ”h]”(j»)”}”(hŒdev_pm_opp_disable”h]”hŒdev_pm_opp_disable”…””}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´KõhjlubjË)”}”(hhh]”(h×)”}”(hŒØMake an OPP to be not available for operation Example: Lets say that 1GHz OPP is to be disabled if the temperature exceeds a threshold value. The SoC framework implementation might choose to do something as follows::”h]”hŒ×Make an OPP to be not available for operation Example: Lets say that 1GHz OPP is to be disabled if the temperature exceeds a threshold value. The SoC framework implementation might choose to do something as follows:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Kçhj~ubj)”}”(hXQif (cur_temp > temp_high_thresh) { /* Disable 1GHz if it was enabled */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); dev_pm_opp_put(opp); /* just error check */ if (!IS_ERR(opp)) ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; }”h]”hXQif (cur_temp > temp_high_thresh) { /* Disable 1GHz if it was enabled */ opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); dev_pm_opp_put(opp); /* just error check */ if (!IS_ERR(opp)) ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; }”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´Kìhj~ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjlubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´Kõhjýh²hubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¯hjÌh²hh³hÊh´Nubeh}”(h]”Œ"opp-availability-control-functions”ah ]”h"]”Œ%4. opp availability control functions”ah$]”h&]”uh1hµhh·h²hh³hÊh´KÊubh¶)”}”(hhh]”(h»)”}”(hŒ5. OPP Data Retrieval Functions”h]”hŒ5. OPP Data Retrieval Functions”…””}”(hjºh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhj·h²hh³hÊh´Køubh×)”}”(hX8Since OPP library abstracts away the OPP information, a set of functions to pull information from the dev_pm_opp structure is necessary. Once an OPP pointer is retrieved using the search functions, the following functions can be used by SoC framework to retrieve the information represented inside the OPP layer.”h]”hX8Since OPP library abstracts away the OPP information, a set of functions to pull information from the dev_pm_opp structure is necessary. Once an OPP pointer is retrieved using the search functions, the following functions can be used by SoC framework to retrieve the information represented inside the OPP layer.”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Kùhj·h²hubj°)”}”(hhh]”(jµ)”}”(hX2dev_pm_opp_get_voltage Retrieve the voltage represented by the opp pointer. Example: At a cpufreq transition to a different frequency, SoC framework requires to set the voltage represented by the OPP using the regulator framework to the Power Management chip providing the voltage:: soc_switch_to_freq_voltage(freq) { /* do things */ 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); /* do other things */ } ”h]”(j»)”}”(hŒdev_pm_opp_get_voltage”h]”hŒdev_pm_opp_get_voltage”…””}”(hjÝh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´MhjÙubjË)”}”(hhh]”(h×)”}”(hXRetrieve the voltage represented by the opp pointer. Example: At a cpufreq transition to a different frequency, SoC framework requires to set the voltage represented by the OPP using the regulator framework to the Power Management chip providing the voltage::”h]”hXRetrieve the voltage represented by the opp pointer. Example: At a cpufreq transition to a different frequency, SoC framework requires to set the voltage represented by the OPP using the regulator framework to the Power Management chip providing the voltage:”…””}”(hjîh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Kÿhjëubj)”}”(hX soc_switch_to_freq_voltage(freq) { /* do things */ 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); /* do other things */ }”h]”hX soc_switch_to_freq_voltage(freq) { /* do things */ 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); /* do other things */ }”…””}”hjüsbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´Mhjëubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjÙubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´MhjÖubjµ)”}”(hXËdev_pm_opp_get_freq Retrieve the freq represented by the opp pointer. Example: Lets say the SoC framework uses a couple of helper functions we could pass opp pointers instead of doing additional parameters to handle quiet a bit of data parameters:: soc_cpufreq_target(..) { /* do things.. */ 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); /* do other things */ } 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; /* do things.. */ } ”h]”(j»)”}”(hŒdev_pm_opp_get_freq”h]”hŒdev_pm_opp_get_freq”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´M)hjubjË)”}”(hhh]”(h×)”}”(hŒäRetrieve the freq represented by the opp pointer. Example: Lets say the SoC framework uses a couple of helper functions we could pass opp pointers instead of doing additional parameters to handle quiet a bit of data parameters::”h]”hŒãRetrieve the freq represented by the opp pointer. Example: Lets say the SoC framework uses a couple of helper functions we could pass opp pointers instead of doing additional parameters to handle quiet a bit of data parameters:”…””}”(hj+h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Mhj(ubj)”}”(hX¼soc_cpufreq_target(..) { /* do things.. */ 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); /* do other things */ } 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; /* do things.. */ }”h]”hX¼soc_cpufreq_target(..) { /* do things.. */ 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); /* do other things */ } 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; /* do things.. */ }”…””}”hj9sbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´Mhj(ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´M)hjÖh²hubjµ)”}”(hX dev_pm_opp_get_opp_count Retrieve the number of available opps for a device Example: Lets say a co-processor in the SoC needs to know the available frequencies in a table, the main processor can notify as following:: soc_notify_coproc_available_frequencies() { /* Do things */ num_available = dev_pm_opp_get_opp_count(dev); speeds = kcalloc(num_available, sizeof(u32), GFP_KERNEL); /* populate the table in increasing order */ 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); /* Do other things */ } ”h]”(j»)”}”(hŒdev_pm_opp_get_opp_count”h]”hŒdev_pm_opp_get_opp_count”…””}”(hjWh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´M@hjSubjË)”}”(hhh]”(h×)”}”(hŒ¿Retrieve the number of available opps for a device Example: Lets say a co-processor in the SoC needs to know the available frequencies in a table, the main processor can notify as following::”h]”hŒ¾Retrieve the number of available opps for a device Example: Lets say a co-processor in the SoC needs to know the available frequencies in a table, the main processor can notify as following:”…””}”(hjhh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´M,hjeubj)”}”(hXsoc_notify_coproc_available_frequencies() { /* Do things */ num_available = dev_pm_opp_get_opp_count(dev); speeds = kcalloc(num_available, sizeof(u32), GFP_KERNEL); /* populate the table in increasing order */ 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); /* Do other things */ }”h]”hXsoc_notify_coproc_available_frequencies() { /* Do things */ num_available = dev_pm_opp_get_opp_count(dev); speeds = kcalloc(num_available, sizeof(u32), GFP_KERNEL); /* populate the table in increasing order */ 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); /* Do other things */ }”…””}”hjvsbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´M0hjeubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjSubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´M@hjÖh²hubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¯hj·h²hh³hÊh´Nubeh}”(h]”Œopp-data-retrieval-functions”ah ]”h"]”Œ5. opp data retrieval functions”ah$]”h&]”uh1hµhh·h²hh³hÊh´Køubh¶)”}”(hhh]”(h»)”}”(hŒ6. Data Structures”h]”hŒ6. Data Structures”…””}”(hj¡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hºhjžh²hh³hÊh´MCubh×)”}”(hŒ®Typically an SoC contains multiple voltage domains which are variable. Each domain is represented by a device pointer. The relationship to OPP can be represented as follows::”h]”hŒ­Typically an SoC contains multiple voltage domains which are variable. Each domain is represented by a device pointer. The relationship to OPP can be represented as follows:”…””}”(hj¯h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´MDhjžh²hubj)”}”(hŒŠSoC |- device 1 | |- opp 1 (availability, freq, voltage) | |- opp 2 .. ... ... | `- opp n .. |- device 2 ... `- device m”h]”hŒŠSoC |- device 1 | |- opp 1 (availability, freq, voltage) | |- opp 2 .. ... ... | `- opp n .. |- device 2 ... `- device m”…””}”hj½sbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´MHhjžh²hubh×)”}”(hXOPP library maintains a internal list that the SoC framework populates and accessed by various functions as described above. However, the structures representing the actual OPPs and domains are internal to the OPP library itself to allow for suitable abstraction reusable across systems.”h]”hXOPP library maintains a internal list that the SoC framework populates and accessed by various functions as described above. However, the structures representing the actual OPPs and domains are internal to the OPP library itself to allow for suitable abstraction reusable across systems.”…””}”(hjËh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´MRhjžh²hubj°)”}”(hhh]”(jµ)”}”(hXˆstruct dev_pm_opp The internal data structure of OPP library which is used to represent an OPP. In addition to the freq, voltage, availability information, it also contains internal book keeping information required for the OPP library to operate on. Pointer to this structure is provided back to the users such as SoC framework to be used as a identifier for OPP in the interactions with OPP layer. WARNING: The struct dev_pm_opp pointer should not be parsed or modified by the users. The defaults of for an instance is populated by dev_pm_opp_add, but the availability of the OPP can be modified by dev_pm_opp_enable/disable functions. ”h]”(j»)”}”(hŒstruct dev_pm_opp”h]”hŒstruct dev_pm_opp”…””}”(hjàh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´MchjÜubjË)”}”(hhh]”(h×)”}”(hX~The internal data structure of OPP library which is used to represent an OPP. In addition to the freq, voltage, availability information, it also contains internal book keeping information required for the OPP library to operate on. Pointer to this structure is provided back to the users such as SoC framework to be used as a identifier for OPP in the interactions with OPP layer.”h]”hX~The internal data structure of OPP library which is used to represent an OPP. In addition to the freq, voltage, availability information, it also contains internal book keeping information required for the OPP library to operate on. Pointer to this structure is provided back to the users such as SoC framework to be used as a identifier for OPP in the interactions with OPP layer.”…””}”(hjñh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´MXhjîubj°)”}”(hhh]”jµ)”}”(hŒîWARNING: The struct dev_pm_opp pointer should not be parsed or modified by the users. The defaults of for an instance is populated by dev_pm_opp_add, but the availability of the OPP can be modified by dev_pm_opp_enable/disable functions. ”h]”(j»)”}”(hŒWARNING:”h]”hŒWARNING:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´MchjubjË)”}”(hhh]”h×)”}”(hŒäThe struct dev_pm_opp pointer should not be parsed or modified by the users. The defaults of for an instance is populated by dev_pm_opp_add, but the availability of the OPP can be modified by dev_pm_opp_enable/disable functions.”h]”hŒäThe struct dev_pm_opp pointer should not be parsed or modified by the users. The defaults of for an instance is populated by dev_pm_opp_add, but the availability of the OPP can be modified by dev_pm_opp_enable/disable functions.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´M`hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´Mchjÿubah}”(h]”h ]”h"]”h$]”h&]”uh1j¯hjîubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjÜubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´MchjÙubjµ)”}”(hŒ°struct device This is used to identify a domain to the OPP layer. The nature of the device and its implementation is left to the user of OPP library such as the SoC framework. ”h]”(j»)”}”(hŒ struct device”h]”hŒ struct device”…””}”(hjGh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jºh³hÊh´MhhjCubjË)”}”(hhh]”h×)”}”(hŒ¡This is used to identify a domain to the OPP layer. The nature of the device and its implementation is left to the user of OPP library such as the SoC framework.”h]”hŒ¡This is used to identify a domain to the OPP layer. The nature of the device and its implementation is left to the user of OPP library such as the SoC framework.”…””}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´MfhjUubah}”(h]”h ]”h"]”h$]”h&]”uh1jÊhjCubeh}”(h]”h ]”h"]”h$]”h&]”uh1j´h³hÊh´MhhjÙh²hubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¯hjžh²hh³Nh´Nubh×)”}”(hŒZOverall, in a simplistic view, the data structure operations is represented as following::”h]”hŒYOverall, in a simplistic view, the data structure operations is represented as following:”…””}”(hjxh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖh³hÊh´Mjhjžh²hubj)”}”(hXInitialization / modification: +-----+ /- dev_pm_opp_enable dev_pm_opp_add --> | opp | <------- | +-----+ \- dev_pm_opp_disable \-------> domain_info(device) Search functions: /-- dev_pm_opp_find_freq_ceil ---\ +-----+ domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | \-- dev_pm_opp_find_freq_floor ---/ +-----+ Retrieval functions: +-----+ /- dev_pm_opp_get_voltage | opp | <--- +-----+ \- dev_pm_opp_get_freq domain_info <- dev_pm_opp_get_opp_count”h]”hXInitialization / modification: +-----+ /- dev_pm_opp_enable dev_pm_opp_add --> | opp | <------- | +-----+ \- dev_pm_opp_disable \-------> domain_info(device) Search functions: /-- dev_pm_opp_find_freq_ceil ---\ +-----+ domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | \-- dev_pm_opp_find_freq_floor ---/ +-----+ Retrieval functions: +-----+ /- dev_pm_opp_get_voltage | opp | <--- +-----+ \- dev_pm_opp_get_freq domain_info <- dev_pm_opp_get_opp_count”…””}”hj†sbah}”(h]”h ]”h"]”h$]”h&]”jj uh1jh³hÊh´Mmhjžh²hubeh}”(h]”Œdata-structures”ah ]”h"]”Œ6. data structures”ah$]”h&]”uh1hµhh·h²hh³hÊh´MCubeh}”(h]”Œ(operating-performance-points-opp-library”ah ]”h"]”Œ*operating performance points (opp) library”ah$]”h&]”uh1hµhhh²hh³hÊh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÊuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hºNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jÇŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÊŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j¡jžjjŠjájÞj…j‚j}jzjHjEjÉjÆj´j±j›j˜j™j–uŒ nametypes”}”(j¡‰j‰já‰j…‰j}‰jH‰jɉj´‰j›‰j™‰uh}”(jžh·jŠj!jÞj2j‚jäjzj/jEjjÆjKj±jÌj˜j·j–jžuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”hŒsystem_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)”…””}”(hj.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÖhj+ubah}”(h]”h ]”h"]”h$]”h&]”Œlevel”KŒtype”ŒINFO”Œsource”hÊŒline”Kuh1j)hh·h²hh³hÊh´KubaŒtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.