Loading Documentation/ABI/testing/sysfs-devices-system-cpu +15 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,21 @@ Description: Discover and change clock speed of CPUs to learn how to control the knobs. What: /sys/devices/system/cpu/cpu#/cpufreq/freqdomain_cpus Date: June 2013 Contact: cpufreq@vger.kernel.org Description: Discover CPUs in the same CPU frequency coordination domain freqdomain_cpus is the list of CPUs (online+offline) that share the same clock/freq domain (possibly at the hardware level). That information may be hidden from the cpufreq core and the value of related_cpus may be different from freqdomain_cpus. This attribute is useful for user space DVFS controllers to get better power/performance results for platforms using acpi-cpufreq. This file is only present if the acpi-cpufreq driver is in use. What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1} Date: August 2008 KernelVersion: 2.6.27 Loading Documentation/android.txt +0 −1 Original line number Diff line number Diff line Loading @@ -101,7 +101,6 @@ DEBUG_SPINLOCK_SLEEP DEBUG_INFO FRAME_POINTER CPU_FREQ CPU_FREQ_TABLE CPU_FREQ_DEFAULT_GOV_ONDEMAND CPU_FREQ_GOV_ONDEMAND CRC_CCITT Loading Documentation/cpu-freq/cpu-drivers.txt +20 −19 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ Contents: 1.1 Initialization 1.2 Per-CPU Initialization 1.3 verify 1.4 target or setpolicy? 1.5 target 1.4 target/target_index or setpolicy? 1.5 target/target_index 1.6 setpolicy 2. Frequency Table Helpers Loading @@ -50,15 +50,14 @@ What shall this struct cpufreq_driver contain? cpufreq_driver.name - The name of this driver. cpufreq_driver.owner - THIS_MODULE; cpufreq_driver.init - A pointer to the per-CPU initialization function. cpufreq_driver.verify - A pointer to a "verification" function. cpufreq_driver.setpolicy _or_ cpufreq_driver.target - See below on the differences. cpufreq_driver.target/ target_index - See below on the differences. And optionally Loading @@ -68,7 +67,7 @@ cpufreq_driver.resume - A pointer to a per-CPU resume function which is called with interrupts disabled and _before_ the pre-suspend frequency and/or policy is restored by a call to ->target or ->setpolicy. ->target/target_index or ->setpolicy. cpufreq_driver.attr - A pointer to a NULL-terminated list of "struct freq_attr" which allow to Loading Loading @@ -105,8 +104,8 @@ policy->governor must contain the "default policy" for this CPU. A few moments later, cpufreq_driver.verify and either cpufreq_driver.setpolicy or cpufreq_driver.target is called with these values. cpufreq_driver.target/target_index is called with these values. For setting some of these values (cpuinfo.min[max]_freq, policy->min[max]), the frequency table helpers might be helpful. See the section 2 for more information Loading Loading @@ -135,20 +134,28 @@ range) is within policy->min and policy->max. If necessary, increase policy->max first, and only if this is no solution, decrease policy->min. 1.4 target or setpolicy? 1.4 target/target_index or setpolicy? ---------------------------- Most cpufreq drivers or even most cpu frequency scaling algorithms only allow the CPU to be set to one frequency. For these, you use the ->target call. ->target/target_index call. Some cpufreq-capable processors switch the frequency between certain limits on their own. These shall use the ->setpolicy call 1.4. target 1.4. target/target_index ------------- The target_index call has two arguments: struct cpufreq_policy *policy, and unsigned int index (into the exposed frequency table). The CPUfreq driver must set the new frequency when called here. The actual frequency must be determined by freq_table[index].frequency. Deprecated: ---------- The target call has three arguments: struct cpufreq_policy *policy, unsigned int target_frequency, unsigned int relation. Loading Loading @@ -186,7 +193,7 @@ As most cpufreq processors only allow for being set to a few specific frequencies, a "frequency table" with some functions might assist in some work of the processor driver. Such a "frequency table" consists of an array of struct cpufreq_frequency_table entries, with any value in "index" you want to use, and the corresponding frequency in "driver_data" you want to use, and the corresponding frequency in "frequency". At the end of the table, you need to add a cpufreq_frequency_table entry with frequency set to CPUFREQ_TABLE_END. And if you want to skip one entry in the table, set the frequency to Loading Loading @@ -214,10 +221,4 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, is the corresponding frequency table helper for the ->target stage. Just pass the values to this function, and the unsigned int index returns the number of the frequency table entry which contains the frequency the CPU shall be set to. PLEASE NOTE: This is not the "index" which is in this cpufreq_table_entry.index, but instead cpufreq_table[index]. So, the new frequency is cpufreq_table[index].frequency, and the value you stored into the frequency table "index" field is cpufreq_table[index].index. the frequency the CPU shall be set to. Documentation/cpu-freq/governors.txt +2 −2 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ Most cpufreq drivers (in fact, all except one, longrun) or even most cpu frequency scaling algorithms only offer the CPU to be set to one frequency. In order to offer dynamic frequency scaling, the cpufreq core must be able to tell these drivers of a "target frequency". So these specific drivers will be transformed to offer a "->target" these specific drivers will be transformed to offer a "->target/target_index" call instead of the existing "->setpolicy" call. For "longrun", all stays the same, though. Loading Loading @@ -72,7 +72,7 @@ CPU can be set to switch independently | CPU can only be set / the limits of policy->{min,max} / \ / \ Using the ->setpolicy call, Using the ->target call, Using the ->setpolicy call, Using the ->target/target_index call, the limits and the the frequency closest "policy" is set. to target_freq is set. It is assured that it Loading Documentation/power/opp.txt +52 −52 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ We can represent these as three OPPs as the following {Hz, uV} tuples: OPP library provides a set of helper functions to organize and query the OPP information. The library is located in drivers/base/power/opp.c and the header is located in include/linux/opp.h. OPP library can be enabled by enabling is located in include/linux/pm_opp.h. OPP library can be enabled by enabling CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to optionally boot at a certain OPP without needing cpufreq. Loading Loading @@ -71,14 +71,14 @@ operations until that OPP could be re-enabled if possible. OPP library facilitates this concept in it's implementation. The following operational functions operate only on available opps: opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count and opp_init_cpufreq_table opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count and dev_pm_opp_init_cpufreq_table opp_find_freq_exact is meant to be used to find the opp pointer which can then be used for opp_enable/disable functions to make an opp available as required. 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. WARNING: Users of OPP library should refresh their availability count using get_opp_count if opp_enable/disable functions are invoked for a device, the 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 Loading @@ -96,24 +96,24 @@ using RCU read locks. The opp_find_freq_{exact,ceil,floor}, opp_get_{voltage, freq, opp_count} fall into this category. opp_{add,enable,disable} are updaters which use mutex and implement it's own RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses RCU locking mechanisms. dev_pm_opp_init_cpufreq_table acts as an updater and uses mutex to implment RCU updater strategy. These functions should *NOT* be called under RCU locks and other contexts that prevent blocking functions in RCU or mutex operations from working. 2. Initial OPP List Registration ================================ The SoC implementation calls opp_add function iteratively to add OPPs per 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 opp_enable / disable functions. OPPs dynamically using the dev_pm_opp_enable / disable functions. opp_add - Add a new OPP for a specific domain represented by the device pointer. dev_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 it's availability can be done with the opp_enable/disable functions. OPP library internally stores with the dev_pm_opp_enable/disable functions. OPP library internally stores and manages this information in the opp struct. This function may be used by SoC framework to define a optimal list as per the demands of SoC usage environment. Loading @@ -124,7 +124,7 @@ opp_add - Add a new OPP for a specific domain represented by the device pointer. soc_pm_init() { /* Do things */ r = opp_add(mpu_dev, 1000000, 900000); 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; Loading @@ -143,44 +143,44 @@ 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. opp_find_freq_exact - Search for an OPP based on an *exact* frequency and dev_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 opp_enable to actually make it available. find the OPP prior to call the dev_pm_opp_enable to actually make it available. rcu_read_lock(); opp = opp_find_freq_exact(dev, 1000000000, false); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); rcu_read_unlock(); /* dont operate on the pointer.. just do a sanity check.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* trigger appropriate actions.. */ } else { opp_enable(dev,1000000000); dev_pm_opp_enable(dev,1000000000); } NOTE: This is the only search function that operates on OPPs which are not available. opp_find_freq_floor - Search for an available OPP which is *at most* the dev_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; rcu_read_lock(); opp_find_freq_floor(dev, &freq); dev_pm_opp_find_freq_floor(dev, &freq); rcu_read_unlock(); opp_find_freq_ceil - Search for an available OPP which is *at least* the 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; rcu_read_lock(); opp_find_freq_ceil(dev, &freq); dev_pm_opp_find_freq_ceil(dev, &freq); rcu_read_unlock(); Example 2: A simplified implementation of a SoC cpufreq_driver->target: soc_cpufreq_target(..) Loading @@ -188,7 +188,7 @@ opp_find_freq_ceil - Search for an available OPP which is *at least* the /* Do stuff like policy checks etc. */ /* Find the best frequency match for the req */ rcu_read_lock(); opp = opp_find_freq_ceil(dev, &freq); opp = dev_pm_opp_find_freq_ceil(dev, &freq); rcu_read_unlock(); if (!IS_ERR(opp)) soc_switch_to_freq_voltage(freq); Loading @@ -208,34 +208,34 @@ as thermal considerations (e.g. don't use OPPx until the temperature drops). WARNING: Do not use these functions in interrupt context. opp_enable - Make a OPP available for operation. dev_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 */ rcu_read_lock(); opp = opp_find_freq_exact(dev, 1000000000, false); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); rcu_read_unlock(); /* just error check */ if (!IS_ERR(opp)) ret = opp_enable(dev, 1000000000); ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; } opp_disable - Make an OPP to be not available for operation dev_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 */ rcu_read_lock(); opp = opp_find_freq_exact(dev, 1000000000, true); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); rcu_read_unlock(); /* just error check */ if (!IS_ERR(opp)) ret = opp_disable(dev, 1000000000); ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; } Loading @@ -247,7 +247,7 @@ information from the 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. opp_get_voltage - Retrieve the voltage represented by the opp pointer. dev_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 Loading @@ -256,15 +256,15 @@ opp_get_voltage - Retrieve the voltage represented by the opp pointer. { /* do things */ rcu_read_lock(); opp = opp_find_freq_ceil(dev, &freq); v = opp_get_voltage(opp); opp = dev_pm_opp_find_freq_ceil(dev, &freq); v = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); if (v) regulator_set_voltage(.., v); /* do other things */ } opp_get_freq - Retrieve the freq represented by the opp pointer. 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. Loading @@ -273,8 +273,8 @@ opp_get_freq - Retrieve the freq represented by the opp pointer. /* do things.. */ max_freq = ULONG_MAX; rcu_read_lock(); max_opp = opp_find_freq_floor(dev,&max_freq); requested_opp = opp_find_freq_ceil(dev,&freq); 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); rcu_read_unlock(); Loading @@ -282,25 +282,25 @@ opp_get_freq - Retrieve the freq represented by the opp pointer. } soc_test_validity(..) { if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp)) if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) return -EINVAL; if(opp_get_freq(max_opp) < opp_get_freq(requested_opp)) if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) return -EINVAL; /* do things.. */ } opp_get_opp_count - Retrieve the number of available opps for a device 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 */ rcu_read_lock(); num_available = opp_get_opp_count(dev); num_available = dev_pm_opp_get_opp_count(dev); speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL); /* populate the table in increasing order */ freq = 0; while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) { while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { speeds[i] = freq; freq++; i++; Loading @@ -313,7 +313,7 @@ opp_get_opp_count - Retrieve the number of available opps for a device 6. Cpufreq Table Generation =========================== opp_init_cpufreq_table - cpufreq framework typically is initialized with dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with cpufreq_frequency_table_cpuinfo which is provided with the list of frequencies that are available for operation. This function provides a ready to use conversion routine to translate the OPP layer's internal Loading @@ -326,7 +326,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with soc_pm_init() { /* Do things */ r = opp_init_cpufreq_table(dev, &freq_table); r = dev_pm_opp_init_cpufreq_table(dev, &freq_table); if (!r) cpufreq_frequency_table_cpuinfo(policy, freq_table); /* Do other things */ Loading @@ -336,7 +336,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with addition to CONFIG_PM as power management feature is required to dynamically scale voltage and frequency in a system. opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table dev_pm_opp_free_cpufreq_table - Free up the table allocated by dev_pm_opp_init_cpufreq_table 7. Data Structures ================== Loading Loading @@ -366,8 +366,8 @@ struct opp - The internal data structure of OPP library which is used to identifier for OPP in the interactions with OPP layer. WARNING: The struct opp pointer should not be parsed or modified by the users. The defaults of for an instance is populated by opp_add, but the availability of the OPP can be modified by opp_enable/disable functions. 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. struct device - This is used to identify a domain to the OPP layer. The nature of the device and it's implementation is left to the user of Loading @@ -377,19 +377,19 @@ Overall, in a simplistic view, the data structure operations is represented as following: Initialization / modification: +-----+ /- opp_enable opp_add --> | opp | <------- | +-----+ \- opp_disable +-----+ /- dev_pm_opp_enable dev_pm_opp_add --> | opp | <------- | +-----+ \- dev_pm_opp_disable \-------> domain_info(device) Search functions: /-- opp_find_freq_ceil ---\ +-----+ domain_info<---- opp_find_freq_exact -----> | opp | \-- opp_find_freq_floor ---/ +-----+ /-- dev_pm_opp_find_freq_ceil ---\ +-----+ domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | \-- dev_pm_opp_find_freq_floor ---/ +-----+ Retrieval functions: +-----+ /- opp_get_voltage +-----+ /- dev_pm_opp_get_voltage | opp | <--- +-----+ \- opp_get_freq +-----+ \- dev_pm_opp_get_freq domain_info <- opp_get_opp_count domain_info <- dev_pm_opp_get_opp_count Loading
Documentation/ABI/testing/sysfs-devices-system-cpu +15 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,21 @@ Description: Discover and change clock speed of CPUs to learn how to control the knobs. What: /sys/devices/system/cpu/cpu#/cpufreq/freqdomain_cpus Date: June 2013 Contact: cpufreq@vger.kernel.org Description: Discover CPUs in the same CPU frequency coordination domain freqdomain_cpus is the list of CPUs (online+offline) that share the same clock/freq domain (possibly at the hardware level). That information may be hidden from the cpufreq core and the value of related_cpus may be different from freqdomain_cpus. This attribute is useful for user space DVFS controllers to get better power/performance results for platforms using acpi-cpufreq. This file is only present if the acpi-cpufreq driver is in use. What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1} Date: August 2008 KernelVersion: 2.6.27 Loading
Documentation/android.txt +0 −1 Original line number Diff line number Diff line Loading @@ -101,7 +101,6 @@ DEBUG_SPINLOCK_SLEEP DEBUG_INFO FRAME_POINTER CPU_FREQ CPU_FREQ_TABLE CPU_FREQ_DEFAULT_GOV_ONDEMAND CPU_FREQ_GOV_ONDEMAND CRC_CCITT Loading
Documentation/cpu-freq/cpu-drivers.txt +20 −19 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ Contents: 1.1 Initialization 1.2 Per-CPU Initialization 1.3 verify 1.4 target or setpolicy? 1.5 target 1.4 target/target_index or setpolicy? 1.5 target/target_index 1.6 setpolicy 2. Frequency Table Helpers Loading @@ -50,15 +50,14 @@ What shall this struct cpufreq_driver contain? cpufreq_driver.name - The name of this driver. cpufreq_driver.owner - THIS_MODULE; cpufreq_driver.init - A pointer to the per-CPU initialization function. cpufreq_driver.verify - A pointer to a "verification" function. cpufreq_driver.setpolicy _or_ cpufreq_driver.target - See below on the differences. cpufreq_driver.target/ target_index - See below on the differences. And optionally Loading @@ -68,7 +67,7 @@ cpufreq_driver.resume - A pointer to a per-CPU resume function which is called with interrupts disabled and _before_ the pre-suspend frequency and/or policy is restored by a call to ->target or ->setpolicy. ->target/target_index or ->setpolicy. cpufreq_driver.attr - A pointer to a NULL-terminated list of "struct freq_attr" which allow to Loading Loading @@ -105,8 +104,8 @@ policy->governor must contain the "default policy" for this CPU. A few moments later, cpufreq_driver.verify and either cpufreq_driver.setpolicy or cpufreq_driver.target is called with these values. cpufreq_driver.target/target_index is called with these values. For setting some of these values (cpuinfo.min[max]_freq, policy->min[max]), the frequency table helpers might be helpful. See the section 2 for more information Loading Loading @@ -135,20 +134,28 @@ range) is within policy->min and policy->max. If necessary, increase policy->max first, and only if this is no solution, decrease policy->min. 1.4 target or setpolicy? 1.4 target/target_index or setpolicy? ---------------------------- Most cpufreq drivers or even most cpu frequency scaling algorithms only allow the CPU to be set to one frequency. For these, you use the ->target call. ->target/target_index call. Some cpufreq-capable processors switch the frequency between certain limits on their own. These shall use the ->setpolicy call 1.4. target 1.4. target/target_index ------------- The target_index call has two arguments: struct cpufreq_policy *policy, and unsigned int index (into the exposed frequency table). The CPUfreq driver must set the new frequency when called here. The actual frequency must be determined by freq_table[index].frequency. Deprecated: ---------- The target call has three arguments: struct cpufreq_policy *policy, unsigned int target_frequency, unsigned int relation. Loading Loading @@ -186,7 +193,7 @@ As most cpufreq processors only allow for being set to a few specific frequencies, a "frequency table" with some functions might assist in some work of the processor driver. Such a "frequency table" consists of an array of struct cpufreq_frequency_table entries, with any value in "index" you want to use, and the corresponding frequency in "driver_data" you want to use, and the corresponding frequency in "frequency". At the end of the table, you need to add a cpufreq_frequency_table entry with frequency set to CPUFREQ_TABLE_END. And if you want to skip one entry in the table, set the frequency to Loading Loading @@ -214,10 +221,4 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, is the corresponding frequency table helper for the ->target stage. Just pass the values to this function, and the unsigned int index returns the number of the frequency table entry which contains the frequency the CPU shall be set to. PLEASE NOTE: This is not the "index" which is in this cpufreq_table_entry.index, but instead cpufreq_table[index]. So, the new frequency is cpufreq_table[index].frequency, and the value you stored into the frequency table "index" field is cpufreq_table[index].index. the frequency the CPU shall be set to.
Documentation/cpu-freq/governors.txt +2 −2 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ Most cpufreq drivers (in fact, all except one, longrun) or even most cpu frequency scaling algorithms only offer the CPU to be set to one frequency. In order to offer dynamic frequency scaling, the cpufreq core must be able to tell these drivers of a "target frequency". So these specific drivers will be transformed to offer a "->target" these specific drivers will be transformed to offer a "->target/target_index" call instead of the existing "->setpolicy" call. For "longrun", all stays the same, though. Loading Loading @@ -72,7 +72,7 @@ CPU can be set to switch independently | CPU can only be set / the limits of policy->{min,max} / \ / \ Using the ->setpolicy call, Using the ->target call, Using the ->setpolicy call, Using the ->target/target_index call, the limits and the the frequency closest "policy" is set. to target_freq is set. It is assured that it Loading
Documentation/power/opp.txt +52 −52 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ We can represent these as three OPPs as the following {Hz, uV} tuples: OPP library provides a set of helper functions to organize and query the OPP information. The library is located in drivers/base/power/opp.c and the header is located in include/linux/opp.h. OPP library can be enabled by enabling is located in include/linux/pm_opp.h. OPP library can be enabled by enabling CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to optionally boot at a certain OPP without needing cpufreq. Loading Loading @@ -71,14 +71,14 @@ operations until that OPP could be re-enabled if possible. OPP library facilitates this concept in it's implementation. The following operational functions operate only on available opps: opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count and opp_init_cpufreq_table opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count and dev_pm_opp_init_cpufreq_table opp_find_freq_exact is meant to be used to find the opp pointer which can then be used for opp_enable/disable functions to make an opp available as required. 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. WARNING: Users of OPP library should refresh their availability count using get_opp_count if opp_enable/disable functions are invoked for a device, the 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 Loading @@ -96,24 +96,24 @@ using RCU read locks. The opp_find_freq_{exact,ceil,floor}, opp_get_{voltage, freq, opp_count} fall into this category. opp_{add,enable,disable} are updaters which use mutex and implement it's own RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses RCU locking mechanisms. dev_pm_opp_init_cpufreq_table acts as an updater and uses mutex to implment RCU updater strategy. These functions should *NOT* be called under RCU locks and other contexts that prevent blocking functions in RCU or mutex operations from working. 2. Initial OPP List Registration ================================ The SoC implementation calls opp_add function iteratively to add OPPs per 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 opp_enable / disable functions. OPPs dynamically using the dev_pm_opp_enable / disable functions. opp_add - Add a new OPP for a specific domain represented by the device pointer. dev_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 it's availability can be done with the opp_enable/disable functions. OPP library internally stores with the dev_pm_opp_enable/disable functions. OPP library internally stores and manages this information in the opp struct. This function may be used by SoC framework to define a optimal list as per the demands of SoC usage environment. Loading @@ -124,7 +124,7 @@ opp_add - Add a new OPP for a specific domain represented by the device pointer. soc_pm_init() { /* Do things */ r = opp_add(mpu_dev, 1000000, 900000); 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; Loading @@ -143,44 +143,44 @@ 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. opp_find_freq_exact - Search for an OPP based on an *exact* frequency and dev_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 opp_enable to actually make it available. find the OPP prior to call the dev_pm_opp_enable to actually make it available. rcu_read_lock(); opp = opp_find_freq_exact(dev, 1000000000, false); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); rcu_read_unlock(); /* dont operate on the pointer.. just do a sanity check.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); /* trigger appropriate actions.. */ } else { opp_enable(dev,1000000000); dev_pm_opp_enable(dev,1000000000); } NOTE: This is the only search function that operates on OPPs which are not available. opp_find_freq_floor - Search for an available OPP which is *at most* the dev_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; rcu_read_lock(); opp_find_freq_floor(dev, &freq); dev_pm_opp_find_freq_floor(dev, &freq); rcu_read_unlock(); opp_find_freq_ceil - Search for an available OPP which is *at least* the 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; rcu_read_lock(); opp_find_freq_ceil(dev, &freq); dev_pm_opp_find_freq_ceil(dev, &freq); rcu_read_unlock(); Example 2: A simplified implementation of a SoC cpufreq_driver->target: soc_cpufreq_target(..) Loading @@ -188,7 +188,7 @@ opp_find_freq_ceil - Search for an available OPP which is *at least* the /* Do stuff like policy checks etc. */ /* Find the best frequency match for the req */ rcu_read_lock(); opp = opp_find_freq_ceil(dev, &freq); opp = dev_pm_opp_find_freq_ceil(dev, &freq); rcu_read_unlock(); if (!IS_ERR(opp)) soc_switch_to_freq_voltage(freq); Loading @@ -208,34 +208,34 @@ as thermal considerations (e.g. don't use OPPx until the temperature drops). WARNING: Do not use these functions in interrupt context. opp_enable - Make a OPP available for operation. dev_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 */ rcu_read_lock(); opp = opp_find_freq_exact(dev, 1000000000, false); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); rcu_read_unlock(); /* just error check */ if (!IS_ERR(opp)) ret = opp_enable(dev, 1000000000); ret = dev_pm_opp_enable(dev, 1000000000); else goto try_something_else; } opp_disable - Make an OPP to be not available for operation dev_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 */ rcu_read_lock(); opp = opp_find_freq_exact(dev, 1000000000, true); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); rcu_read_unlock(); /* just error check */ if (!IS_ERR(opp)) ret = opp_disable(dev, 1000000000); ret = dev_pm_opp_disable(dev, 1000000000); else goto try_something_else; } Loading @@ -247,7 +247,7 @@ information from the 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. opp_get_voltage - Retrieve the voltage represented by the opp pointer. dev_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 Loading @@ -256,15 +256,15 @@ opp_get_voltage - Retrieve the voltage represented by the opp pointer. { /* do things */ rcu_read_lock(); opp = opp_find_freq_ceil(dev, &freq); v = opp_get_voltage(opp); opp = dev_pm_opp_find_freq_ceil(dev, &freq); v = dev_pm_opp_get_voltage(opp); rcu_read_unlock(); if (v) regulator_set_voltage(.., v); /* do other things */ } opp_get_freq - Retrieve the freq represented by the opp pointer. 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. Loading @@ -273,8 +273,8 @@ opp_get_freq - Retrieve the freq represented by the opp pointer. /* do things.. */ max_freq = ULONG_MAX; rcu_read_lock(); max_opp = opp_find_freq_floor(dev,&max_freq); requested_opp = opp_find_freq_ceil(dev,&freq); 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); rcu_read_unlock(); Loading @@ -282,25 +282,25 @@ opp_get_freq - Retrieve the freq represented by the opp pointer. } soc_test_validity(..) { if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp)) if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp)) return -EINVAL; if(opp_get_freq(max_opp) < opp_get_freq(requested_opp)) if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp)) return -EINVAL; /* do things.. */ } opp_get_opp_count - Retrieve the number of available opps for a device 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 */ rcu_read_lock(); num_available = opp_get_opp_count(dev); num_available = dev_pm_opp_get_opp_count(dev); speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL); /* populate the table in increasing order */ freq = 0; while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) { while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) { speeds[i] = freq; freq++; i++; Loading @@ -313,7 +313,7 @@ opp_get_opp_count - Retrieve the number of available opps for a device 6. Cpufreq Table Generation =========================== opp_init_cpufreq_table - cpufreq framework typically is initialized with dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with cpufreq_frequency_table_cpuinfo which is provided with the list of frequencies that are available for operation. This function provides a ready to use conversion routine to translate the OPP layer's internal Loading @@ -326,7 +326,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with soc_pm_init() { /* Do things */ r = opp_init_cpufreq_table(dev, &freq_table); r = dev_pm_opp_init_cpufreq_table(dev, &freq_table); if (!r) cpufreq_frequency_table_cpuinfo(policy, freq_table); /* Do other things */ Loading @@ -336,7 +336,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with addition to CONFIG_PM as power management feature is required to dynamically scale voltage and frequency in a system. opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table dev_pm_opp_free_cpufreq_table - Free up the table allocated by dev_pm_opp_init_cpufreq_table 7. Data Structures ================== Loading Loading @@ -366,8 +366,8 @@ struct opp - The internal data structure of OPP library which is used to identifier for OPP in the interactions with OPP layer. WARNING: The struct opp pointer should not be parsed or modified by the users. The defaults of for an instance is populated by opp_add, but the availability of the OPP can be modified by opp_enable/disable functions. 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. struct device - This is used to identify a domain to the OPP layer. The nature of the device and it's implementation is left to the user of Loading @@ -377,19 +377,19 @@ Overall, in a simplistic view, the data structure operations is represented as following: Initialization / modification: +-----+ /- opp_enable opp_add --> | opp | <------- | +-----+ \- opp_disable +-----+ /- dev_pm_opp_enable dev_pm_opp_add --> | opp | <------- | +-----+ \- dev_pm_opp_disable \-------> domain_info(device) Search functions: /-- opp_find_freq_ceil ---\ +-----+ domain_info<---- opp_find_freq_exact -----> | opp | \-- opp_find_freq_floor ---/ +-----+ /-- dev_pm_opp_find_freq_ceil ---\ +-----+ domain_info<---- dev_pm_opp_find_freq_exact -----> | opp | \-- dev_pm_opp_find_freq_floor ---/ +-----+ Retrieval functions: +-----+ /- opp_get_voltage +-----+ /- dev_pm_opp_get_voltage | opp | <--- +-----+ \- opp_get_freq +-----+ \- dev_pm_opp_get_freq domain_info <- opp_get_opp_count domain_info <- dev_pm_opp_get_opp_count