aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2014-05-05 09:33:50 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-06 18:39:03 -0400
commita0dd7b79657bd6644b914d16ce7f23468c44a7b4 (patch)
tree471993f62816ed76d5cb7f96b32659f5bed439a6
parent0f5c890e9b9754d9aa5bf6ae2fc00cae65780d23 (diff)
PM / OPP: Move cpufreq specific OPP functions out of generic OPP library
CPUFreq specific helper functions for OPP (Operating Performance Points) now use generic OPP functions that allow CPUFreq to be be moved back into CPUFreq framework. This allows for independent modifications or future enhancements as needed isolated to just CPUFreq framework alone. Here, we just move relevant code and documentation to make this part of CPUFreq infrastructure. Cc: Kevin Hilman <khilman@deeprootsystems.com> Signed-off-by: Nishanth Menon <nm@ti.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--Documentation/cpu-freq/core.txt29
-rw-r--r--Documentation/power/opp.txt40
-rw-r--r--drivers/base/power/opp.c92
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/cpufreq_opp.c110
-rw-r--r--include/linux/cpufreq.h21
-rw-r--r--include/linux/pm_opp.h20
7 files changed, 167 insertions, 147 deletions
diff --git a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt
index 0060d76b445f..70933eadc308 100644
--- a/Documentation/cpu-freq/core.txt
+++ b/Documentation/cpu-freq/core.txt
@@ -20,6 +20,7 @@ Contents:
20--------- 20---------
211. CPUFreq core and interfaces 211. CPUFreq core and interfaces
222. CPUFreq notifiers 222. CPUFreq notifiers
233. CPUFreq Table Generation with Operating Performance Point (OPP)
23 24
241. General Information 251. General Information
25======================= 26=======================
@@ -92,3 +93,31 @@ values:
92cpu - number of the affected CPU 93cpu - number of the affected CPU
93old - old frequency 94old - old frequency
94new - new frequency 95new - new frequency
96
973. CPUFreq Table Generation with Operating Performance Point (OPP)
98==================================================================
99For details about OPP, see Documentation/power/opp.txt
100
101dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
102 cpufreq_frequency_table_cpuinfo which is provided with the list of
103 frequencies that are available for operation. This function provides
104 a ready to use conversion routine to translate the OPP layer's internal
105 information about the available frequencies into a format readily
106 providable to cpufreq.
107
108 WARNING: Do not use this function in interrupt context.
109
110 Example:
111 soc_pm_init()
112 {
113 /* Do things */
114 r = dev_pm_opp_init_cpufreq_table(dev, &freq_table);
115 if (!r)
116 cpufreq_frequency_table_cpuinfo(policy, freq_table);
117 /* Do other things */
118 }
119
120 NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in
121 addition to CONFIG_PM_OPP.
122
123dev_pm_opp_free_cpufreq_table - Free up the table allocated by dev_pm_opp_init_cpufreq_table
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
index b8a907dc0169..a9adad828cdc 100644
--- a/Documentation/power/opp.txt
+++ b/Documentation/power/opp.txt
@@ -10,8 +10,7 @@ Contents
103. OPP Search Functions 103. OPP Search Functions
114. OPP Availability Control Functions 114. OPP Availability Control Functions
125. OPP Data Retrieval Functions 125. OPP Data Retrieval Functions
136. Cpufreq Table Generation 136. Data Structures
147. Data Structures
15 14
161. Introduction 151. Introduction
17=============== 16===============
@@ -72,7 +71,6 @@ operations until that OPP could be re-enabled if possible.
72OPP library facilitates this concept in it's implementation. The following 71OPP library facilitates this concept in it's implementation. The following
73operational functions operate only on available opps: 72operational functions operate only on available opps:
74opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count 73opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count
75and dev_pm_opp_init_cpufreq_table
76 74
77dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then 75dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then
78be used for dev_pm_opp_enable/disable functions to make an opp available as required. 76be used for dev_pm_opp_enable/disable functions to make an opp available as required.
@@ -96,10 +94,9 @@ using RCU read locks. The opp_find_freq_{exact,ceil,floor},
96opp_get_{voltage, freq, opp_count} fall into this category. 94opp_get_{voltage, freq, opp_count} fall into this category.
97 95
98opp_{add,enable,disable} are updaters which use mutex and implement it's own 96opp_{add,enable,disable} are updaters which use mutex and implement it's own
99RCU locking mechanisms. dev_pm_opp_init_cpufreq_table acts as an updater and uses 97RCU locking mechanisms. These functions should *NOT* be called under RCU locks
100mutex to implment RCU updater strategy. These functions should *NOT* be called 98and other contexts that prevent blocking functions in RCU or mutex operations
101under RCU locks and other contexts that prevent blocking functions in RCU or 99from working.
102mutex operations from working.
103 100
1042. Initial OPP List Registration 1012. Initial OPP List Registration
105================================ 102================================
@@ -311,34 +308,7 @@ dev_pm_opp_get_opp_count - Retrieve the number of available opps for a device
311 /* Do other things */ 308 /* Do other things */
312 } 309 }
313 310
3146. Cpufreq Table Generation 3116. Data Structures
315===========================
316dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
317 cpufreq_frequency_table_cpuinfo which is provided with the list of
318 frequencies that are available for operation. This function provides
319 a ready to use conversion routine to translate the OPP layer's internal
320 information about the available frequencies into a format readily
321 providable to cpufreq.
322
323 WARNING: Do not use this function in interrupt context.
324
325 Example:
326 soc_pm_init()
327 {
328 /* Do things */
329 r = dev_pm_opp_init_cpufreq_table(dev, &freq_table);
330 if (!r)
331 cpufreq_frequency_table_cpuinfo(policy, freq_table);
332 /* Do other things */
333 }
334
335 NOTE: This function is available only if CONFIG_CPU_FREQ is enabled in
336 addition to CONFIG_PM as power management feature is required to
337 dynamically scale voltage and frequency in a system.
338
339dev_pm_opp_free_cpufreq_table - Free up the table allocated by dev_pm_opp_init_cpufreq_table
340
3417. Data Structures
342================== 312==================
343Typically an SoC contains multiple voltage domains which are variable. Each 313Typically an SoC contains multiple voltage domains which are variable. Each
344domain is represented by a device pointer. The relationship to OPP can be 314domain is represented by a device pointer. The relationship to OPP can be
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 38b43bb20878..d9e376a6d19d 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -15,7 +15,6 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/cpufreq.h>
19#include <linux/device.h> 18#include <linux/device.h>
20#include <linux/list.h> 19#include <linux/list.h>
21#include <linux/rculist.h> 20#include <linux/rculist.h>
@@ -596,97 +595,6 @@ int dev_pm_opp_disable(struct device *dev, unsigned long freq)
596} 595}
597EXPORT_SYMBOL_GPL(dev_pm_opp_disable); 596EXPORT_SYMBOL_GPL(dev_pm_opp_disable);
598 597
599#ifdef CONFIG_CPU_FREQ
600/**
601 * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device
602 * @dev: device for which we do this operation
603 * @table: Cpufreq table returned back to caller
604 *
605 * Generate a cpufreq table for a provided device- this assumes that the
606 * opp list is already initialized and ready for usage.
607 *
608 * This function allocates required memory for the cpufreq table. It is
609 * expected that the caller does the required maintenance such as freeing
610 * the table as required.
611 *
612 * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
613 * if no memory available for the operation (table is not populated), returns 0
614 * if successful and table is populated.
615 *
616 * WARNING: It is important for the callers to ensure refreshing their copy of
617 * the table if any of the mentioned functions have been invoked in the interim.
618 *
619 * Locking: The internal device_opp and opp structures are RCU protected.
620 * Since we just use the regular accessor functions to access the internal data
621 * structures, we use RCU read lock inside this function. As a result, users of
622 * this function DONOT need to use explicit locks for invoking.
623 */
624int dev_pm_opp_init_cpufreq_table(struct device *dev,
625 struct cpufreq_frequency_table **table)
626{
627 struct dev_pm_opp *opp;
628 struct cpufreq_frequency_table *freq_table = NULL;
629 int i, max_opps, ret = 0;
630 unsigned long rate;
631
632 rcu_read_lock();
633
634 max_opps = dev_pm_opp_get_opp_count(dev);
635 if (max_opps <= 0) {
636 ret = max_opps ? max_opps : -ENODATA;
637 goto out;
638 }
639
640 freq_table = kzalloc(sizeof(*freq_table) * (max_opps + 1), GFP_KERNEL);
641 if (!freq_table) {
642 ret = -ENOMEM;
643 goto out;
644 }
645
646 for (i = 0, rate = 0; i < max_opps; i++, rate++) {
647 /* find next rate */
648 opp = dev_pm_opp_find_freq_ceil(dev, &rate);
649 if (IS_ERR(opp)) {
650 ret = PTR_ERR(opp);
651 goto out;
652 }
653 freq_table[i].driver_data = i;
654 freq_table[i].frequency = rate / 1000;
655 }
656
657 freq_table[i].driver_data = i;
658 freq_table[i].frequency = CPUFREQ_TABLE_END;
659
660 *table = &freq_table[0];
661
662out:
663 rcu_read_unlock();
664 if (ret)
665 kfree(freq_table);
666
667 return ret;
668}
669EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
670
671/**
672 * dev_pm_opp_free_cpufreq_table() - free the cpufreq table
673 * @dev: device for which we do this operation
674 * @table: table to free
675 *
676 * Free up the table allocated by dev_pm_opp_init_cpufreq_table
677 */
678void dev_pm_opp_free_cpufreq_table(struct device *dev,
679 struct cpufreq_frequency_table **table)
680{
681 if (!table)
682 return;
683
684 kfree(*table);
685 *table = NULL;
686}
687EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
688#endif /* CONFIG_CPU_FREQ */
689
690/** 598/**
691 * dev_pm_opp_get_notifier() - find notifier_head of the device with opp 599 * dev_pm_opp_get_notifier() - find notifier_head of the device with opp
692 * @dev: device pointer used to lookup device OPPs. 600 * @dev: device pointer used to lookup device OPPs.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 0dbb963c1aef..738c8b7b17dc 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -1,5 +1,7 @@
1# CPUfreq core 1# CPUfreq core
2obj-$(CONFIG_CPU_FREQ) += cpufreq.o freq_table.o 2obj-$(CONFIG_CPU_FREQ) += cpufreq.o freq_table.o
3obj-$(CONFIG_PM_OPP) += cpufreq_opp.o
4
3# CPUfreq stats 5# CPUfreq stats
4obj-$(CONFIG_CPU_FREQ_STAT) += cpufreq_stats.o 6obj-$(CONFIG_CPU_FREQ_STAT) += cpufreq_stats.o
5 7
diff --git a/drivers/cpufreq/cpufreq_opp.c b/drivers/cpufreq/cpufreq_opp.c
new file mode 100644
index 000000000000..c0c6f4a4eccf
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_opp.c
@@ -0,0 +1,110 @@
1/*
2 * Generic OPP helper interface for CPUFreq drivers
3 *
4 * Copyright (C) 2009-2014 Texas Instruments Incorporated.
5 * Nishanth Menon
6 * Romit Dasgupta
7 * Kevin Hilman
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/cpufreq.h>
14#include <linux/device.h>
15#include <linux/err.h>
16#include <linux/errno.h>
17#include <linux/export.h>
18#include <linux/kernel.h>
19#include <linux/pm_opp.h>
20#include <linux/rcupdate.h>
21#include <linux/slab.h>
22
23/**
24 * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device
25 * @dev: device for which we do this operation
26 * @table: Cpufreq table returned back to caller
27 *
28 * Generate a cpufreq table for a provided device- this assumes that the
29 * opp list is already initialized and ready for usage.
30 *
31 * This function allocates required memory for the cpufreq table. It is
32 * expected that the caller does the required maintenance such as freeing
33 * the table as required.
34 *
35 * Returns -EINVAL for bad pointers, -ENODEV if the device is not found, -ENOMEM
36 * if no memory available for the operation (table is not populated), returns 0
37 * if successful and table is populated.
38 *
39 * WARNING: It is important for the callers to ensure refreshing their copy of
40 * the table if any of the mentioned functions have been invoked in the interim.
41 *
42 * Locking: The internal device_opp and opp structures are RCU protected.
43 * Since we just use the regular accessor functions to access the internal data
44 * structures, we use RCU read lock inside this function. As a result, users of
45 * this function DONOT need to use explicit locks for invoking.
46 */
47int dev_pm_opp_init_cpufreq_table(struct device *dev,
48 struct cpufreq_frequency_table **table)
49{
50 struct dev_pm_opp *opp;
51 struct cpufreq_frequency_table *freq_table = NULL;
52 int i, max_opps, ret = 0;
53 unsigned long rate;
54
55 rcu_read_lock();
56
57 max_opps = dev_pm_opp_get_opp_count(dev);
58 if (max_opps <= 0) {
59 ret = max_opps ? max_opps : -ENODATA;
60 goto out;
61 }
62
63 freq_table = kzalloc(sizeof(*freq_table) * (max_opps + 1), GFP_KERNEL);
64 if (!freq_table) {
65 ret = -ENOMEM;
66 goto out;
67 }
68
69 for (i = 0, rate = 0; i < max_opps; i++, rate++) {
70 /* find next rate */
71 opp = dev_pm_opp_find_freq_ceil(dev, &rate);
72 if (IS_ERR(opp)) {
73 ret = PTR_ERR(opp);
74 goto out;
75 }
76 freq_table[i].driver_data = i;
77 freq_table[i].frequency = rate / 1000;
78 }
79
80 freq_table[i].driver_data = i;
81 freq_table[i].frequency = CPUFREQ_TABLE_END;
82
83 *table = &freq_table[0];
84
85out:
86 rcu_read_unlock();
87 if (ret)
88 kfree(freq_table);
89
90 return ret;
91}
92EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
93
94/**
95 * dev_pm_opp_free_cpufreq_table() - free the cpufreq table
96 * @dev: device for which we do this operation
97 * @table: table to free
98 *
99 * Free up the table allocated by dev_pm_opp_init_cpufreq_table
100 */
101void dev_pm_opp_free_cpufreq_table(struct device *dev,
102 struct cpufreq_frequency_table **table)
103{
104 if (!table)
105 return;
106
107 kfree(*table);
108 *table = NULL;
109}
110EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index f3822f836e14..9d803b529ac2 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -469,6 +469,27 @@ struct cpufreq_frequency_table {
469 * order */ 469 * order */
470}; 470};
471 471
472#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
473int dev_pm_opp_init_cpufreq_table(struct device *dev,
474 struct cpufreq_frequency_table **table);
475void dev_pm_opp_free_cpufreq_table(struct device *dev,
476 struct cpufreq_frequency_table **table);
477#else
478static inline int dev_pm_opp_init_cpufreq_table(struct device *dev,
479 struct cpufreq_frequency_table
480 **table)
481{
482 return -EINVAL;
483}
484
485static inline void dev_pm_opp_free_cpufreq_table(struct device *dev,
486 struct cpufreq_frequency_table
487 **table)
488{
489}
490#endif
491
492
472bool cpufreq_next_valid(struct cpufreq_frequency_table **pos); 493bool cpufreq_next_valid(struct cpufreq_frequency_table **pos);
473 494
474/* 495/*
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 5151b0059585..0330217abfad 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -15,7 +15,6 @@
15#define __LINUX_OPP_H__ 15#define __LINUX_OPP_H__
16 16
17#include <linux/err.h> 17#include <linux/err.h>
18#include <linux/cpufreq.h>
19#include <linux/notifier.h> 18#include <linux/notifier.h>
20 19
21struct dev_pm_opp; 20struct dev_pm_opp;
@@ -117,23 +116,4 @@ static inline int of_init_opp_table(struct device *dev)
117} 116}
118#endif 117#endif
119 118
120#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
121int dev_pm_opp_init_cpufreq_table(struct device *dev,
122 struct cpufreq_frequency_table **table);
123void dev_pm_opp_free_cpufreq_table(struct device *dev,
124 struct cpufreq_frequency_table **table);
125#else
126static inline int dev_pm_opp_init_cpufreq_table(struct device *dev,
127 struct cpufreq_frequency_table **table)
128{
129 return -EINVAL;
130}
131
132static inline
133void dev_pm_opp_free_cpufreq_table(struct device *dev,
134 struct cpufreq_frequency_table **table)
135{
136}
137#endif /* CONFIG_CPU_FREQ */
138
139#endif /* __LINUX_OPP_H__ */ 119#endif /* __LINUX_OPP_H__ */