diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-01-11 19:11:25 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-01-11 19:11:25 -0500 |
commit | b366f976323d5d9ccb612e20afaaddf1fb84418d (patch) | |
tree | 3d3a357a309d7ed82dbd14ce7de1ea6c34653856 | |
parent | 7f4a3702bda0f9f5d34f0241cc81467a55162d7a (diff) | |
parent | a032d2de0b5f17631844b34481c61cb799d0af6b (diff) |
Merge branch 'pm-cpufreq'
* pm-cpufreq: (30 commits)
Documentation: cpufreq: intel_pstate: enhance documentation
cpufreq-dt: fix handling regulator_get_voltage() result
cpufreq: governor: Fix negative idle_time when configured with CONFIG_HZ_PERIODIC
cpufreq: mt8173: migrate to use operating-points-v2 bindings
cpufreq: Simplify core code related to boost support
cpufreq: acpi-cpufreq: Simplify boost-related code
cpufreq: Make cpufreq_boost_supported() static
blackfin-cpufreq: Mark cpu_set_cclk() as static
blackfin-cpufreq: Change return type of cpu_set_cclk() to that of clk_set_rate()
dt: cpufreq: st: Provide bindings for ST's CPUFreq implementation
cpufreq: st: Provide runtime initialised driver for ST's platforms
cpufreq: mt8173: Move resources allocation into ->probe()
cpufreq: intel_pstate: Account for IO wait time
cpufreq: intel_pstate: Account for non C0 time
cpufreq: intel_pstate: Configurable algorithm to get target pstate
cpufreq: mt8173: check return value of regulator_get_voltage() call
cpufreq: mt8173: remove redundant regulator_get_voltage() call
cpufreq: mt8173: add CPUFREQ_HAVE_GOVERNOR_PER_POLICY flag
cpufreq: qoriq: Register cooling device based on device tree
cpufreq: pcc-cpufreq: update default value of cpuinfo_transition_latency
...
-rw-r--r-- | Documentation/cpu-freq/intel-pstate.txt | 241 | ||||
-rw-r--r-- | Documentation/cpu-freq/pcc-cpufreq.txt | 4 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/arm/cpus.txt | 17 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt | 91 | ||||
-rw-r--r-- | drivers/cpufreq/Kconfig.arm | 12 | ||||
-rw-r--r-- | drivers/cpufreq/Makefile | 1 | ||||
-rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 24 | ||||
-rw-r--r-- | drivers/cpufreq/arm_big_little.c | 41 | ||||
-rw-r--r-- | drivers/cpufreq/blackfin-cpufreq.c | 2 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq-dt.c | 14 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 28 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_conservative.c | 6 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.c | 146 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.h | 18 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 61 | ||||
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 73 | ||||
-rw-r--r-- | drivers/cpufreq/mt8173-cpufreq.c | 135 | ||||
-rw-r--r-- | drivers/cpufreq/pcc-cpufreq.c | 2 | ||||
-rw-r--r-- | drivers/cpufreq/qoriq-cpufreq.c | 24 | ||||
-rw-r--r-- | drivers/cpufreq/sti-cpufreq.c | 294 | ||||
-rw-r--r-- | include/linux/cpufreq.h | 6 |
21 files changed, 1014 insertions, 226 deletions
diff --git a/Documentation/cpu-freq/intel-pstate.txt b/Documentation/cpu-freq/intel-pstate.txt index be8d4006bf76..f7b12c071d53 100644 --- a/Documentation/cpu-freq/intel-pstate.txt +++ b/Documentation/cpu-freq/intel-pstate.txt | |||
@@ -1,61 +1,131 @@ | |||
1 | Intel P-state driver | 1 | Intel P-State driver |
2 | -------------------- | 2 | -------------------- |
3 | 3 | ||
4 | This driver provides an interface to control the P state selection for | 4 | This driver provides an interface to control the P-State selection for the |
5 | SandyBridge+ Intel processors. The driver can operate two different | 5 | SandyBridge+ Intel processors. |
6 | modes based on the processor model, legacy mode and Hardware P state (HWP) | 6 | |
7 | mode. | 7 | The following document explains P-States: |
8 | 8 | http://events.linuxfoundation.org/sites/events/files/slides/LinuxConEurope_2015.pdf | |
9 | In legacy mode, the Intel P-state implements two internal governors, | 9 | As stated in the document, P-State doesn’t exactly mean a frequency. However, for |
10 | performance and powersave, that differ from the general cpufreq governors of | 10 | the sake of the relationship with cpufreq, P-State and frequency are used |
11 | the same name (the general cpufreq governors implement target(), whereas the | 11 | interchangeably. |
12 | internal Intel P-state governors implement setpolicy()). The internal | 12 | |
13 | performance governor sets the max_perf_pct and min_perf_pct to 100; that is, | 13 | Understanding the cpufreq core governors and policies are important before |
14 | the governor selects the highest available P state to maximize the performance | 14 | discussing more details about the Intel P-State driver. Based on what callbacks |
15 | of the core. The internal powersave governor selects the appropriate P state | 15 | a cpufreq driver provides to the cpufreq core, it can support two types of |
16 | based on the current load on the CPU. | 16 | drivers: |
17 | 17 | - with target_index() callback: In this mode, the drivers using cpufreq core | |
18 | In HWP mode P state selection is implemented in the processor | 18 | simply provide the minimum and maximum frequency limits and an additional |
19 | itself. The driver provides the interfaces between the cpufreq core and | 19 | interface target_index() to set the current frequency. The cpufreq subsystem |
20 | the processor to control P state selection based on user preferences | 20 | has a number of scaling governors ("performance", "powersave", "ondemand", |
21 | and reporting frequency to the cpufreq core. In this mode the | 21 | etc.). Depending on which governor is in use, cpufreq core will call for |
22 | internal Intel P-state governor code is disabled. | 22 | transitions to a specific frequency using target_index() callback. |
23 | 23 | - setpolicy() callback: In this mode, drivers do not provide target_index() | |
24 | In addition to the interfaces provided by the cpufreq core for | 24 | callback, so cpufreq core can't request a transition to a specific frequency. |
25 | controlling frequency the driver provides sysfs files for | 25 | The driver provides minimum and maximum frequency limits and callbacks to set a |
26 | controlling P state selection. These files have been added to | 26 | policy. The policy in cpufreq sysfs is referred to as the "scaling governor". |
27 | /sys/devices/system/cpu/intel_pstate/ | 27 | The cpufreq core can request the driver to operate in any of the two policies: |
28 | 28 | "performance: and "powersave". The driver decides which frequency to use based | |
29 | max_perf_pct: limits the maximum P state that will be requested by | 29 | on the above policy selection considering minimum and maximum frequency limits. |
30 | the driver stated as a percentage of the available performance. The | 30 | |
31 | available (P states) performance may be reduced by the no_turbo | 31 | The Intel P-State driver falls under the latter category, which implements the |
32 | setpolicy() callback. This driver decides what P-State to use based on the | ||
33 | requested policy from the cpufreq core. If the processor is capable of | ||
34 | selecting its next P-State internally, then the driver will offload this | ||
35 | responsibility to the processor (aka HWP: Hardware P-States). If not, the | ||
36 | driver implements algorithms to select the next P-State. | ||
37 | |||
38 | Since these policies are implemented in the driver, they are not same as the | ||
39 | cpufreq scaling governors implementation, even if they have the same name in | ||
40 | the cpufreq sysfs (scaling_governors). For example the "performance" policy is | ||
41 | similar to cpufreq’s "performance" governor, but "powersave" is completely | ||
42 | different than the cpufreq "powersave" governor. The strategy here is similar | ||
43 | to cpufreq "ondemand", where the requested P-State is related to the system load. | ||
44 | |||
45 | Sysfs Interface | ||
46 | |||
47 | In addition to the frequency-controlling interfaces provided by the cpufreq | ||
48 | core, the driver provides its own sysfs files to control the P-State selection. | ||
49 | These files have been added to /sys/devices/system/cpu/intel_pstate/. | ||
50 | Any changes made to these files are applicable to all CPUs (even in a | ||
51 | multi-package system). | ||
52 | |||
53 | max_perf_pct: Limits the maximum P-State that will be requested by | ||
54 | the driver. It states it as a percentage of the available performance. The | ||
55 | available (P-State) performance may be reduced by the no_turbo | ||
32 | setting described below. | 56 | setting described below. |
33 | 57 | ||
34 | min_perf_pct: limits the minimum P state that will be requested by | 58 | min_perf_pct: Limits the minimum P-State that will be requested by |
35 | the driver stated as a percentage of the max (non-turbo) | 59 | the driver. It states it as a percentage of the max (non-turbo) |
36 | performance level. | 60 | performance level. |
37 | 61 | ||
38 | no_turbo: limits the driver to selecting P states below the turbo | 62 | no_turbo: Limits the driver to selecting P-State below the turbo |
39 | frequency range. | 63 | frequency range. |
40 | 64 | ||
41 | turbo_pct: displays the percentage of the total performance that | 65 | turbo_pct: Displays the percentage of the total performance that |
42 | is supported by hardware that is in the turbo range. This number | 66 | is supported by hardware that is in the turbo range. This number |
43 | is independent of whether turbo has been disabled or not. | 67 | is independent of whether turbo has been disabled or not. |
44 | 68 | ||
45 | num_pstates: displays the number of pstates that are supported | 69 | num_pstates: Displays the number of P-States that are supported |
46 | by hardware. This number is independent of whether turbo has | 70 | by hardware. This number is independent of whether turbo has |
47 | been disabled or not. | 71 | been disabled or not. |
48 | 72 | ||
73 | For example, if a system has these parameters: | ||
74 | Max 1 core turbo ratio: 0x21 (Max 1 core ratio is the maximum P-State) | ||
75 | Max non turbo ratio: 0x17 | ||
76 | Minimum ratio : 0x08 (Here the ratio is called max efficiency ratio) | ||
77 | |||
78 | Sysfs will show : | ||
79 | max_perf_pct:100, which corresponds to 1 core ratio | ||
80 | min_perf_pct:24, max_efficiency_ratio / max 1 Core ratio | ||
81 | no_turbo:0, turbo is not disabled | ||
82 | num_pstates:26 = (max 1 Core ratio - Max Efficiency Ratio + 1) | ||
83 | turbo_pct:39 = (max 1 core ratio - max non turbo ratio) / num_pstates | ||
84 | |||
85 | Refer to "Intel® 64 and IA-32 Architectures Software Developer’s Manual | ||
86 | Volume 3: System Programming Guide" to understand ratios. | ||
87 | |||
88 | cpufreq sysfs for Intel P-State | ||
89 | |||
90 | Since this driver registers with cpufreq, cpufreq sysfs is also presented. | ||
91 | There are some important differences, which need to be considered. | ||
92 | |||
93 | scaling_cur_freq: This displays the real frequency which was used during | ||
94 | the last sample period instead of what is requested. Some other cpufreq driver, | ||
95 | like acpi-cpufreq, displays what is requested (Some changes are on the | ||
96 | way to fix this for acpi-cpufreq driver). The same is true for frequencies | ||
97 | displayed at /proc/cpuinfo. | ||
98 | |||
99 | scaling_governor: This displays current active policy. Since each CPU has a | ||
100 | cpufreq sysfs, it is possible to set a scaling governor to each CPU. But this | ||
101 | is not possible with Intel P-States, as there is one common policy for all | ||
102 | CPUs. Here, the last requested policy will be applicable to all CPUs. It is | ||
103 | suggested that one use the cpupower utility to change policy to all CPUs at the | ||
104 | same time. | ||
105 | |||
106 | scaling_setspeed: This attribute can never be used with Intel P-State. | ||
107 | |||
108 | scaling_max_freq/scaling_min_freq: This interface can be used similarly to | ||
109 | the max_perf_pct/min_perf_pct of Intel P-State sysfs. However since frequencies | ||
110 | are converted to nearest possible P-State, this is prone to rounding errors. | ||
111 | This method is not preferred to limit performance. | ||
112 | |||
113 | affected_cpus: Not used | ||
114 | related_cpus: Not used | ||
115 | |||
49 | For contemporary Intel processors, the frequency is controlled by the | 116 | For contemporary Intel processors, the frequency is controlled by the |
50 | processor itself and the P-states exposed to software are related to | 117 | processor itself and the P-State exposed to software is related to |
51 | performance levels. The idea that frequency can be set to a single | 118 | performance levels. The idea that frequency can be set to a single |
52 | frequency is fiction for Intel Core processors. Even if the scaling | 119 | frequency is fictional for Intel Core processors. Even if the scaling |
53 | driver selects a single P state the actual frequency the processor | 120 | driver selects a single P-State, the actual frequency the processor |
54 | will run at is selected by the processor itself. | 121 | will run at is selected by the processor itself. |
55 | 122 | ||
56 | For legacy mode debugfs files have also been added to allow tuning of | 123 | Tuning Intel P-State driver |
57 | the internal governor algorythm. These files are located at | 124 | |
58 | /sys/kernel/debug/pstate_snb/ These files are NOT present in HWP mode. | 125 | When HWP mode is not used, debugfs files have also been added to allow the |
126 | tuning of the internal governor algorithm. These files are located at | ||
127 | /sys/kernel/debug/pstate_snb/. The algorithm uses a PID (Proportional | ||
128 | Integral Derivative) controller. The PID tunable parameters are: | ||
59 | 129 | ||
60 | deadband | 130 | deadband |
61 | d_gain_pct | 131 | d_gain_pct |
@@ -63,3 +133,90 @@ the internal governor algorythm. These files are located at | |||
63 | p_gain_pct | 133 | p_gain_pct |
64 | sample_rate_ms | 134 | sample_rate_ms |
65 | setpoint | 135 | setpoint |
136 | |||
137 | To adjust these parameters, some understanding of driver implementation is | ||
138 | necessary. There are some tweeks described here, but be very careful. Adjusting | ||
139 | them requires expert level understanding of power and performance relationship. | ||
140 | These limits are only useful when the "powersave" policy is active. | ||
141 | |||
142 | -To make the system more responsive to load changes, sample_rate_ms can | ||
143 | be adjusted (current default is 10ms). | ||
144 | -To make the system use higher performance, even if the load is lower, setpoint | ||
145 | can be adjusted to a lower number. This will also lead to faster ramp up time | ||
146 | to reach the maximum P-State. | ||
147 | If there are no derivative and integral coefficients, The next P-State will be | ||
148 | equal to: | ||
149 | current P-State - ((setpoint - current cpu load) * p_gain_pct) | ||
150 | |||
151 | For example, if the current PID parameters are (Which are defaults for the core | ||
152 | processors like SandyBridge): | ||
153 | deadband = 0 | ||
154 | d_gain_pct = 0 | ||
155 | i_gain_pct = 0 | ||
156 | p_gain_pct = 20 | ||
157 | sample_rate_ms = 10 | ||
158 | setpoint = 97 | ||
159 | |||
160 | If the current P-State = 0x08 and current load = 100, this will result in the | ||
161 | next P-State = 0x08 - ((97 - 100) * 0.2) = 8.6 (rounded to 9). Here the P-State | ||
162 | goes up by only 1. If during next sample interval the current load doesn't | ||
163 | change and still 100, then P-State goes up by one again. This process will | ||
164 | continue as long as the load is more than the setpoint until the maximum P-State | ||
165 | is reached. | ||
166 | |||
167 | For the same load at setpoint = 60, this will result in the next P-State | ||
168 | = 0x08 - ((60 - 100) * 0.2) = 16 | ||
169 | So by changing the setpoint from 97 to 60, there is an increase of the | ||
170 | next P-State from 9 to 16. So this will make processor execute at higher | ||
171 | P-State for the same CPU load. If the load continues to be more than the | ||
172 | setpoint during next sample intervals, then P-State will go up again till the | ||
173 | maximum P-State is reached. But the ramp up time to reach the maximum P-State | ||
174 | will be much faster when the setpoint is 60 compared to 97. | ||
175 | |||
176 | Debugging Intel P-State driver | ||
177 | |||
178 | Event tracing | ||
179 | To debug P-State transition, the Linux event tracing interface can be used. | ||
180 | There are two specific events, which can be enabled (Provided the kernel | ||
181 | configs related to event tracing are enabled). | ||
182 | |||
183 | # cd /sys/kernel/debug/tracing/ | ||
184 | # echo 1 > events/power/pstate_sample/enable | ||
185 | # echo 1 > events/power/cpu_frequency/enable | ||
186 | # cat trace | ||
187 | gnome-terminal--4510 [001] ..s. 1177.680733: pstate_sample: core_busy=107 | ||
188 | scaled=94 from=26 to=26 mperf=1143818 aperf=1230607 tsc=29838618 | ||
189 | freq=2474476 | ||
190 | cat-5235 [002] ..s. 1177.681723: cpu_frequency: state=2900000 cpu_id=2 | ||
191 | |||
192 | |||
193 | Using ftrace | ||
194 | |||
195 | If function level tracing is required, the Linux ftrace interface can be used. | ||
196 | For example if we want to check how often a function to set a P-State is | ||
197 | called, we can set ftrace filter to intel_pstate_set_pstate. | ||
198 | |||
199 | # cd /sys/kernel/debug/tracing/ | ||
200 | # cat available_filter_functions | grep -i pstate | ||
201 | intel_pstate_set_pstate | ||
202 | intel_pstate_cpu_init | ||
203 | ... | ||
204 | |||
205 | # echo intel_pstate_set_pstate > set_ftrace_filter | ||
206 | # echo function > current_tracer | ||
207 | # cat trace | head -15 | ||
208 | # tracer: function | ||
209 | # | ||
210 | # entries-in-buffer/entries-written: 80/80 #P:4 | ||
211 | # | ||
212 | # _-----=> irqs-off | ||
213 | # / _----=> need-resched | ||
214 | # | / _---=> hardirq/softirq | ||
215 | # || / _--=> preempt-depth | ||
216 | # ||| / delay | ||
217 | # TASK-PID CPU# |||| TIMESTAMP FUNCTION | ||
218 | # | | | |||| | | | ||
219 | Xorg-3129 [000] ..s. 2537.644844: intel_pstate_set_pstate <-intel_pstate_timer_func | ||
220 | gnome-terminal--4510 [002] ..s. 2537.649844: intel_pstate_set_pstate <-intel_pstate_timer_func | ||
221 | gnome-shell-3409 [001] ..s. 2537.650850: intel_pstate_set_pstate <-intel_pstate_timer_func | ||
222 | <idle>-0 [000] ..s. 2537.654843: intel_pstate_set_pstate <-intel_pstate_timer_func | ||
diff --git a/Documentation/cpu-freq/pcc-cpufreq.txt b/Documentation/cpu-freq/pcc-cpufreq.txt index 9e3c3b33514c..0a94224ad296 100644 --- a/Documentation/cpu-freq/pcc-cpufreq.txt +++ b/Documentation/cpu-freq/pcc-cpufreq.txt | |||
@@ -159,8 +159,8 @@ to be strictly associated with a P-state. | |||
159 | 159 | ||
160 | 2.2 cpuinfo_transition_latency: | 160 | 2.2 cpuinfo_transition_latency: |
161 | ------------------------------- | 161 | ------------------------------- |
162 | The cpuinfo_transition_latency field is 0. The PCC specification does | 162 | The cpuinfo_transition_latency field is CPUFREQ_ETERNAL. The PCC specification |
163 | not include a field to expose this value currently. | 163 | does not include a field to expose this value currently. |
164 | 164 | ||
165 | 2.3 cpuinfo_cur_freq: | 165 | 2.3 cpuinfo_cur_freq: |
166 | --------------------- | 166 | --------------------- |
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 3a07a87fef20..6aca64f289b6 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt | |||
@@ -242,6 +242,23 @@ nodes to be present and contain the properties described below. | |||
242 | Definition: Specifies the syscon node controlling the cpu core | 242 | Definition: Specifies the syscon node controlling the cpu core |
243 | power domains. | 243 | power domains. |
244 | 244 | ||
245 | - dynamic-power-coefficient | ||
246 | Usage: optional | ||
247 | Value type: <prop-encoded-array> | ||
248 | Definition: A u32 value that represents the running time dynamic | ||
249 | power coefficient in units of mW/MHz/uVolt^2. The | ||
250 | coefficient can either be calculated from power | ||
251 | measurements or derived by analysis. | ||
252 | |||
253 | The dynamic power consumption of the CPU is | ||
254 | proportional to the square of the Voltage (V) and | ||
255 | the clock frequency (f). The coefficient is used to | ||
256 | calculate the dynamic power as below - | ||
257 | |||
258 | Pdyn = dynamic-power-coefficient * V^2 * f | ||
259 | |||
260 | where voltage is in uV, frequency is in MHz. | ||
261 | |||
245 | Example 1 (dual-cluster big.LITTLE system 32-bit): | 262 | Example 1 (dual-cluster big.LITTLE system 32-bit): |
246 | 263 | ||
247 | cpus { | 264 | cpus { |
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt new file mode 100644 index 000000000000..d91a02a3b6b0 --- /dev/null +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt | |||
@@ -0,0 +1,91 @@ | |||
1 | Binding for ST's CPUFreq driver | ||
2 | =============================== | ||
3 | |||
4 | ST's CPUFreq driver attempts to read 'process' and 'version' attributes | ||
5 | from the SoC, then supplies the OPP framework with 'prop' and 'supported | ||
6 | hardware' information respectively. The framework is then able to read | ||
7 | the DT and operate in the usual way. | ||
8 | |||
9 | For more information about the expected DT format [See: ../opp/opp.txt]. | ||
10 | |||
11 | Frequency Scaling only | ||
12 | ---------------------- | ||
13 | |||
14 | No vendor specific driver required for this. | ||
15 | |||
16 | Located in CPU's node: | ||
17 | |||
18 | - operating-points : [See: ../power/opp.txt] | ||
19 | |||
20 | Example [safe] | ||
21 | -------------- | ||
22 | |||
23 | cpus { | ||
24 | cpu@0 { | ||
25 | /* kHz uV */ | ||
26 | operating-points = <1500000 0 | ||
27 | 1200000 0 | ||
28 | 800000 0 | ||
29 | 500000 0>; | ||
30 | }; | ||
31 | }; | ||
32 | |||
33 | Dynamic Voltage and Frequency Scaling (DVFS) | ||
34 | -------------------------------------------- | ||
35 | |||
36 | This requires the ST CPUFreq driver to supply 'process' and 'version' info. | ||
37 | |||
38 | Located in CPU's node: | ||
39 | |||
40 | - operating-points-v2 : [See ../power/opp.txt] | ||
41 | |||
42 | Example [unsafe] | ||
43 | ---------------- | ||
44 | |||
45 | cpus { | ||
46 | cpu@0 { | ||
47 | operating-points-v2 = <&cpu0_opp_table>; | ||
48 | }; | ||
49 | }; | ||
50 | |||
51 | cpu0_opp_table: opp_table { | ||
52 | compatible = "operating-points-v2"; | ||
53 | |||
54 | /* ############################################################### */ | ||
55 | /* # WARNING: Do not attempt to copy/replicate these nodes, # */ | ||
56 | /* # they are only to be supplied by the bootloader !!! # */ | ||
57 | /* ############################################################### */ | ||
58 | opp0 { | ||
59 | /* Major Minor Substrate */ | ||
60 | /* 2 all all */ | ||
61 | opp-supported-hw = <0x00000004 0xffffffff 0xffffffff>; | ||
62 | opp-hz = /bits/ 64 <1500000000>; | ||
63 | clock-latency-ns = <10000000>; | ||
64 | |||
65 | opp-microvolt-pcode0 = <1200000>; | ||
66 | opp-microvolt-pcode1 = <1200000>; | ||
67 | opp-microvolt-pcode2 = <1200000>; | ||
68 | opp-microvolt-pcode3 = <1200000>; | ||
69 | opp-microvolt-pcode4 = <1170000>; | ||
70 | opp-microvolt-pcode5 = <1140000>; | ||
71 | opp-microvolt-pcode6 = <1100000>; | ||
72 | opp-microvolt-pcode7 = <1070000>; | ||
73 | }; | ||
74 | |||
75 | opp1 { | ||
76 | /* Major Minor Substrate */ | ||
77 | /* all all all */ | ||
78 | opp-supported-hw = <0xffffffff 0xffffffff 0xffffffff>; | ||
79 | opp-hz = /bits/ 64 <1200000000>; | ||
80 | clock-latency-ns = <10000000>; | ||
81 | |||
82 | opp-microvolt-pcode0 = <1110000>; | ||
83 | opp-microvolt-pcode1 = <1150000>; | ||
84 | opp-microvolt-pcode2 = <1100000>; | ||
85 | opp-microvolt-pcode3 = <1080000>; | ||
86 | opp-microvolt-pcode4 = <1040000>; | ||
87 | opp-microvolt-pcode5 = <1020000>; | ||
88 | opp-microvolt-pcode6 = <980000>; | ||
89 | opp-microvolt-pcode7 = <930000>; | ||
90 | }; | ||
91 | }; | ||
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index b1f8a73e5a94..0031069b64c9 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
@@ -6,6 +6,8 @@ | |||
6 | config ARM_BIG_LITTLE_CPUFREQ | 6 | config ARM_BIG_LITTLE_CPUFREQ |
7 | tristate "Generic ARM big LITTLE CPUfreq driver" | 7 | tristate "Generic ARM big LITTLE CPUfreq driver" |
8 | depends on (ARM_CPU_TOPOLOGY || ARM64) && HAVE_CLK | 8 | depends on (ARM_CPU_TOPOLOGY || ARM64) && HAVE_CLK |
9 | # if CPU_THERMAL is on and THERMAL=m, ARM_BIT_LITTLE_CPUFREQ cannot be =y | ||
10 | depends on !CPU_THERMAL || THERMAL | ||
9 | select PM_OPP | 11 | select PM_OPP |
10 | help | 12 | help |
11 | This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. | 13 | This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. |
@@ -217,6 +219,16 @@ config ARM_SPEAR_CPUFREQ | |||
217 | help | 219 | help |
218 | This adds the CPUFreq driver support for SPEAr SOCs. | 220 | This adds the CPUFreq driver support for SPEAr SOCs. |
219 | 221 | ||
222 | config ARM_STI_CPUFREQ | ||
223 | tristate "STi CPUFreq support" | ||
224 | depends on SOC_STIH407 | ||
225 | help | ||
226 | This driver uses the generic OPP framework to match the running | ||
227 | platform with a predefined set of suitable values. If not provided | ||
228 | we will fall-back so safe-values contained in Device Tree. Enable | ||
229 | this config option if you wish to add CPUFreq support for STi based | ||
230 | SoCs. | ||
231 | |||
220 | config ARM_TEGRA20_CPUFREQ | 232 | config ARM_TEGRA20_CPUFREQ |
221 | bool "Tegra20 CPUFreq support" | 233 | bool "Tegra20 CPUFreq support" |
222 | depends on ARCH_TEGRA | 234 | depends on ARCH_TEGRA |
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index c0af1a1281c8..9e63fb1b09f8 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile | |||
@@ -73,6 +73,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o | |||
73 | obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o | 73 | obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o |
74 | obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o | 74 | obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o |
75 | obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o | 75 | obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o |
76 | obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o | ||
76 | obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o | 77 | obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o |
77 | obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o | 78 | obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o |
78 | obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o | 79 | obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o |
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index cec1ee2d2f74..51eef87bbc37 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -135,7 +135,7 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask) | |||
135 | wrmsr_on_cpus(cpumask, msr_addr, msrs); | 135 | wrmsr_on_cpus(cpumask, msr_addr, msrs); |
136 | } | 136 | } |
137 | 137 | ||
138 | static int _store_boost(int val) | 138 | static int set_boost(int val) |
139 | { | 139 | { |
140 | get_online_cpus(); | 140 | get_online_cpus(); |
141 | boost_set_msrs(val, cpu_online_mask); | 141 | boost_set_msrs(val, cpu_online_mask); |
@@ -158,29 +158,24 @@ static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf) | |||
158 | cpufreq_freq_attr_ro(freqdomain_cpus); | 158 | cpufreq_freq_attr_ro(freqdomain_cpus); |
159 | 159 | ||
160 | #ifdef CONFIG_X86_ACPI_CPUFREQ_CPB | 160 | #ifdef CONFIG_X86_ACPI_CPUFREQ_CPB |
161 | static ssize_t store_boost(const char *buf, size_t count) | 161 | static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf, |
162 | size_t count) | ||
162 | { | 163 | { |
163 | int ret; | 164 | int ret; |
164 | unsigned long val = 0; | 165 | unsigned int val = 0; |
165 | 166 | ||
166 | if (!acpi_cpufreq_driver.boost_supported) | 167 | if (!acpi_cpufreq_driver.set_boost) |
167 | return -EINVAL; | 168 | return -EINVAL; |
168 | 169 | ||
169 | ret = kstrtoul(buf, 10, &val); | 170 | ret = kstrtouint(buf, 10, &val); |
170 | if (ret || (val > 1)) | 171 | if (ret || val > 1) |
171 | return -EINVAL; | 172 | return -EINVAL; |
172 | 173 | ||
173 | _store_boost((int) val); | 174 | set_boost(val); |
174 | 175 | ||
175 | return count; | 176 | return count; |
176 | } | 177 | } |
177 | 178 | ||
178 | static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf, | ||
179 | size_t count) | ||
180 | { | ||
181 | return store_boost(buf, count); | ||
182 | } | ||
183 | |||
184 | static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf) | 179 | static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf) |
185 | { | 180 | { |
186 | return sprintf(buf, "%u\n", acpi_cpufreq_driver.boost_enabled); | 181 | return sprintf(buf, "%u\n", acpi_cpufreq_driver.boost_enabled); |
@@ -905,7 +900,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = { | |||
905 | .resume = acpi_cpufreq_resume, | 900 | .resume = acpi_cpufreq_resume, |
906 | .name = "acpi-cpufreq", | 901 | .name = "acpi-cpufreq", |
907 | .attr = acpi_cpufreq_attr, | 902 | .attr = acpi_cpufreq_attr, |
908 | .set_boost = _store_boost, | ||
909 | }; | 903 | }; |
910 | 904 | ||
911 | static void __init acpi_cpufreq_boost_init(void) | 905 | static void __init acpi_cpufreq_boost_init(void) |
@@ -916,7 +910,7 @@ static void __init acpi_cpufreq_boost_init(void) | |||
916 | if (!msrs) | 910 | if (!msrs) |
917 | return; | 911 | return; |
918 | 912 | ||
919 | acpi_cpufreq_driver.boost_supported = true; | 913 | acpi_cpufreq_driver.set_boost = set_boost; |
920 | acpi_cpufreq_driver.boost_enabled = boost_state(0); | 914 | acpi_cpufreq_driver.boost_enabled = boost_state(0); |
921 | 915 | ||
922 | cpu_notifier_register_begin(); | 916 | cpu_notifier_register_begin(); |
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index c5d256caa664..c251247ae661 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/cpu.h> | 23 | #include <linux/cpu.h> |
24 | #include <linux/cpufreq.h> | 24 | #include <linux/cpufreq.h> |
25 | #include <linux/cpumask.h> | 25 | #include <linux/cpumask.h> |
26 | #include <linux/cpu_cooling.h> | ||
26 | #include <linux/export.h> | 27 | #include <linux/export.h> |
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
@@ -55,6 +56,7 @@ static bool bL_switching_enabled; | |||
55 | #define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq) | 56 | #define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq) |
56 | #define VIRT_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq >> 1 : freq) | 57 | #define VIRT_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq >> 1 : freq) |
57 | 58 | ||
59 | static struct thermal_cooling_device *cdev[MAX_CLUSTERS]; | ||
58 | static struct cpufreq_arm_bL_ops *arm_bL_ops; | 60 | static struct cpufreq_arm_bL_ops *arm_bL_ops; |
59 | static struct clk *clk[MAX_CLUSTERS]; | 61 | static struct clk *clk[MAX_CLUSTERS]; |
60 | static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1]; | 62 | static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1]; |
@@ -493,6 +495,12 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) | |||
493 | static int bL_cpufreq_exit(struct cpufreq_policy *policy) | 495 | static int bL_cpufreq_exit(struct cpufreq_policy *policy) |
494 | { | 496 | { |
495 | struct device *cpu_dev; | 497 | struct device *cpu_dev; |
498 | int cur_cluster = cpu_to_cluster(policy->cpu); | ||
499 | |||
500 | if (cur_cluster < MAX_CLUSTERS) { | ||
501 | cpufreq_cooling_unregister(cdev[cur_cluster]); | ||
502 | cdev[cur_cluster] = NULL; | ||
503 | } | ||
496 | 504 | ||
497 | cpu_dev = get_cpu_device(policy->cpu); | 505 | cpu_dev = get_cpu_device(policy->cpu); |
498 | if (!cpu_dev) { | 506 | if (!cpu_dev) { |
@@ -507,6 +515,38 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) | |||
507 | return 0; | 515 | return 0; |
508 | } | 516 | } |
509 | 517 | ||
518 | static void bL_cpufreq_ready(struct cpufreq_policy *policy) | ||
519 | { | ||
520 | struct device *cpu_dev = get_cpu_device(policy->cpu); | ||
521 | int cur_cluster = cpu_to_cluster(policy->cpu); | ||
522 | struct device_node *np; | ||
523 | |||
524 | /* Do not register a cpu_cooling device if we are in IKS mode */ | ||
525 | if (cur_cluster >= MAX_CLUSTERS) | ||
526 | return; | ||
527 | |||
528 | np = of_node_get(cpu_dev->of_node); | ||
529 | if (WARN_ON(!np)) | ||
530 | return; | ||
531 | |||
532 | if (of_find_property(np, "#cooling-cells", NULL)) { | ||
533 | u32 power_coefficient = 0; | ||
534 | |||
535 | of_property_read_u32(np, "dynamic-power-coefficient", | ||
536 | &power_coefficient); | ||
537 | |||
538 | cdev[cur_cluster] = of_cpufreq_power_cooling_register(np, | ||
539 | policy->related_cpus, power_coefficient, NULL); | ||
540 | if (IS_ERR(cdev[cur_cluster])) { | ||
541 | dev_err(cpu_dev, | ||
542 | "running cpufreq without cooling device: %ld\n", | ||
543 | PTR_ERR(cdev[cur_cluster])); | ||
544 | cdev[cur_cluster] = NULL; | ||
545 | } | ||
546 | } | ||
547 | of_node_put(np); | ||
548 | } | ||
549 | |||
510 | static struct cpufreq_driver bL_cpufreq_driver = { | 550 | static struct cpufreq_driver bL_cpufreq_driver = { |
511 | .name = "arm-big-little", | 551 | .name = "arm-big-little", |
512 | .flags = CPUFREQ_STICKY | | 552 | .flags = CPUFREQ_STICKY | |
@@ -517,6 +557,7 @@ static struct cpufreq_driver bL_cpufreq_driver = { | |||
517 | .get = bL_cpufreq_get_rate, | 557 | .get = bL_cpufreq_get_rate, |
518 | .init = bL_cpufreq_init, | 558 | .init = bL_cpufreq_init, |
519 | .exit = bL_cpufreq_exit, | 559 | .exit = bL_cpufreq_exit, |
560 | .ready = bL_cpufreq_ready, | ||
520 | .attr = cpufreq_generic_attr, | 561 | .attr = cpufreq_generic_attr, |
521 | }; | 562 | }; |
522 | 563 | ||
diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index a9f8e5bd0716..12e97d8a9db0 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c | |||
@@ -112,7 +112,7 @@ static unsigned int bfin_getfreq_khz(unsigned int cpu) | |||
112 | } | 112 | } |
113 | 113 | ||
114 | #ifdef CONFIG_BF60x | 114 | #ifdef CONFIG_BF60x |
115 | unsigned long cpu_set_cclk(int cpu, unsigned long new) | 115 | static int cpu_set_cclk(int cpu, unsigned long new) |
116 | { | 116 | { |
117 | struct clk *clk; | 117 | struct clk *clk; |
118 | int ret; | 118 | int ret; |
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 90d64081ddb3..9bc37c437874 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c | |||
@@ -50,7 +50,8 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) | |||
50 | struct private_data *priv = policy->driver_data; | 50 | struct private_data *priv = policy->driver_data; |
51 | struct device *cpu_dev = priv->cpu_dev; | 51 | struct device *cpu_dev = priv->cpu_dev; |
52 | struct regulator *cpu_reg = priv->cpu_reg; | 52 | struct regulator *cpu_reg = priv->cpu_reg; |
53 | unsigned long volt = 0, volt_old = 0, tol = 0; | 53 | unsigned long volt = 0, tol = 0; |
54 | int volt_old = 0; | ||
54 | unsigned int old_freq, new_freq; | 55 | unsigned int old_freq, new_freq; |
55 | long freq_Hz, freq_exact; | 56 | long freq_Hz, freq_exact; |
56 | int ret; | 57 | int ret; |
@@ -83,7 +84,7 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) | |||
83 | opp_freq / 1000, volt); | 84 | opp_freq / 1000, volt); |
84 | } | 85 | } |
85 | 86 | ||
86 | dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", | 87 | dev_dbg(cpu_dev, "%u MHz, %d mV --> %u MHz, %ld mV\n", |
87 | old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1, | 88 | old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1, |
88 | new_freq / 1000, volt ? volt / 1000 : -1); | 89 | new_freq / 1000, volt ? volt / 1000 : -1); |
89 | 90 | ||
@@ -407,8 +408,13 @@ static void cpufreq_ready(struct cpufreq_policy *policy) | |||
407 | * thermal DT code takes care of matching them. | 408 | * thermal DT code takes care of matching them. |
408 | */ | 409 | */ |
409 | if (of_find_property(np, "#cooling-cells", NULL)) { | 410 | if (of_find_property(np, "#cooling-cells", NULL)) { |
410 | priv->cdev = of_cpufreq_cooling_register(np, | 411 | u32 power_coefficient = 0; |
411 | policy->related_cpus); | 412 | |
413 | of_property_read_u32(np, "dynamic-power-coefficient", | ||
414 | &power_coefficient); | ||
415 | |||
416 | priv->cdev = of_cpufreq_power_cooling_register(np, | ||
417 | policy->related_cpus, power_coefficient, NULL); | ||
412 | if (IS_ERR(priv->cdev)) { | 418 | if (IS_ERR(priv->cdev)) { |
413 | dev_err(priv->cpu_dev, | 419 | dev_err(priv->cpu_dev, |
414 | "running cpufreq without cooling device: %ld\n", | 420 | "running cpufreq without cooling device: %ld\n", |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 8412ce5f93a7..c35e7da1ed7a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -2330,29 +2330,15 @@ int cpufreq_boost_trigger_state(int state) | |||
2330 | return ret; | 2330 | return ret; |
2331 | } | 2331 | } |
2332 | 2332 | ||
2333 | int cpufreq_boost_supported(void) | 2333 | static bool cpufreq_boost_supported(void) |
2334 | { | 2334 | { |
2335 | if (likely(cpufreq_driver)) | 2335 | return likely(cpufreq_driver) && cpufreq_driver->set_boost; |
2336 | return cpufreq_driver->boost_supported; | ||
2337 | |||
2338 | return 0; | ||
2339 | } | 2336 | } |
2340 | EXPORT_SYMBOL_GPL(cpufreq_boost_supported); | ||
2341 | 2337 | ||
2342 | static int create_boost_sysfs_file(void) | 2338 | static int create_boost_sysfs_file(void) |
2343 | { | 2339 | { |
2344 | int ret; | 2340 | int ret; |
2345 | 2341 | ||
2346 | if (!cpufreq_boost_supported()) | ||
2347 | return 0; | ||
2348 | |||
2349 | /* | ||
2350 | * Check if driver provides function to enable boost - | ||
2351 | * if not, use cpufreq_boost_set_sw as default | ||
2352 | */ | ||
2353 | if (!cpufreq_driver->set_boost) | ||
2354 | cpufreq_driver->set_boost = cpufreq_boost_set_sw; | ||
2355 | |||
2356 | ret = sysfs_create_file(cpufreq_global_kobject, &boost.attr); | 2342 | ret = sysfs_create_file(cpufreq_global_kobject, &boost.attr); |
2357 | if (ret) | 2343 | if (ret) |
2358 | pr_err("%s: cannot register global BOOST sysfs file\n", | 2344 | pr_err("%s: cannot register global BOOST sysfs file\n", |
@@ -2375,7 +2361,7 @@ int cpufreq_enable_boost_support(void) | |||
2375 | if (cpufreq_boost_supported()) | 2361 | if (cpufreq_boost_supported()) |
2376 | return 0; | 2362 | return 0; |
2377 | 2363 | ||
2378 | cpufreq_driver->boost_supported = true; | 2364 | cpufreq_driver->set_boost = cpufreq_boost_set_sw; |
2379 | 2365 | ||
2380 | /* This will get removed on driver unregister */ | 2366 | /* This will get removed on driver unregister */ |
2381 | return create_boost_sysfs_file(); | 2367 | return create_boost_sysfs_file(); |
@@ -2435,9 +2421,11 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
2435 | if (driver_data->setpolicy) | 2421 | if (driver_data->setpolicy) |
2436 | driver_data->flags |= CPUFREQ_CONST_LOOPS; | 2422 | driver_data->flags |= CPUFREQ_CONST_LOOPS; |
2437 | 2423 | ||
2438 | ret = create_boost_sysfs_file(); | 2424 | if (cpufreq_boost_supported()) { |
2439 | if (ret) | 2425 | ret = create_boost_sysfs_file(); |
2440 | goto err_null_driver; | 2426 | if (ret) |
2427 | goto err_null_driver; | ||
2428 | } | ||
2441 | 2429 | ||
2442 | ret = subsys_interface_register(&cpufreq_interface); | 2430 | ret = subsys_interface_register(&cpufreq_interface); |
2443 | if (ret) | 2431 | if (ret) |
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 1fa1deb6e91f..606ad74abe6e 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c | |||
@@ -115,13 +115,13 @@ static void cs_check_cpu(int cpu, unsigned int load) | |||
115 | } | 115 | } |
116 | } | 116 | } |
117 | 117 | ||
118 | static unsigned int cs_dbs_timer(struct cpu_dbs_info *cdbs, | 118 | static unsigned int cs_dbs_timer(struct cpufreq_policy *policy, bool modify_all) |
119 | struct dbs_data *dbs_data, bool modify_all) | ||
120 | { | 119 | { |
120 | struct dbs_data *dbs_data = policy->governor_data; | ||
121 | struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; | 121 | struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; |
122 | 122 | ||
123 | if (modify_all) | 123 | if (modify_all) |
124 | dbs_check_cpu(dbs_data, cdbs->shared->policy->cpu); | 124 | dbs_check_cpu(dbs_data, policy->cpu); |
125 | 125 | ||
126 | return delay_for_sampling_rate(cs_tuners->sampling_rate); | 126 | return delay_for_sampling_rate(cs_tuners->sampling_rate); |
127 | } | 127 | } |
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index b260576ddb12..bab3a514ec12 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c | |||
@@ -84,6 +84,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) | |||
84 | (cur_wall_time - j_cdbs->prev_cpu_wall); | 84 | (cur_wall_time - j_cdbs->prev_cpu_wall); |
85 | j_cdbs->prev_cpu_wall = cur_wall_time; | 85 | j_cdbs->prev_cpu_wall = cur_wall_time; |
86 | 86 | ||
87 | if (cur_idle_time < j_cdbs->prev_cpu_idle) | ||
88 | cur_idle_time = j_cdbs->prev_cpu_idle; | ||
89 | |||
87 | idle_time = (unsigned int) | 90 | idle_time = (unsigned int) |
88 | (cur_idle_time - j_cdbs->prev_cpu_idle); | 91 | (cur_idle_time - j_cdbs->prev_cpu_idle); |
89 | j_cdbs->prev_cpu_idle = cur_idle_time; | 92 | j_cdbs->prev_cpu_idle = cur_idle_time; |
@@ -158,47 +161,55 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) | |||
158 | } | 161 | } |
159 | EXPORT_SYMBOL_GPL(dbs_check_cpu); | 162 | EXPORT_SYMBOL_GPL(dbs_check_cpu); |
160 | 163 | ||
161 | static inline void __gov_queue_work(int cpu, struct dbs_data *dbs_data, | 164 | void gov_add_timers(struct cpufreq_policy *policy, unsigned int delay) |
162 | unsigned int delay) | ||
163 | { | 165 | { |
164 | struct cpu_dbs_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu); | 166 | struct dbs_data *dbs_data = policy->governor_data; |
165 | 167 | struct cpu_dbs_info *cdbs; | |
166 | mod_delayed_work_on(cpu, system_wq, &cdbs->dwork, delay); | 168 | int cpu; |
167 | } | ||
168 | |||
169 | void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, | ||
170 | unsigned int delay, bool all_cpus) | ||
171 | { | ||
172 | int i; | ||
173 | 169 | ||
174 | if (!all_cpus) { | 170 | for_each_cpu(cpu, policy->cpus) { |
175 | /* | 171 | cdbs = dbs_data->cdata->get_cpu_cdbs(cpu); |
176 | * Use raw_smp_processor_id() to avoid preemptible warnings. | 172 | cdbs->timer.expires = jiffies + delay; |
177 | * We know that this is only called with all_cpus == false from | 173 | add_timer_on(&cdbs->timer, cpu); |
178 | * works that have been queued with *_work_on() functions and | ||
179 | * those works are canceled during CPU_DOWN_PREPARE so they | ||
180 | * can't possibly run on any other CPU. | ||
181 | */ | ||
182 | __gov_queue_work(raw_smp_processor_id(), dbs_data, delay); | ||
183 | } else { | ||
184 | for_each_cpu(i, policy->cpus) | ||
185 | __gov_queue_work(i, dbs_data, delay); | ||
186 | } | 174 | } |
187 | } | 175 | } |
188 | EXPORT_SYMBOL_GPL(gov_queue_work); | 176 | EXPORT_SYMBOL_GPL(gov_add_timers); |
189 | 177 | ||
190 | static inline void gov_cancel_work(struct dbs_data *dbs_data, | 178 | static inline void gov_cancel_timers(struct cpufreq_policy *policy) |
191 | struct cpufreq_policy *policy) | ||
192 | { | 179 | { |
180 | struct dbs_data *dbs_data = policy->governor_data; | ||
193 | struct cpu_dbs_info *cdbs; | 181 | struct cpu_dbs_info *cdbs; |
194 | int i; | 182 | int i; |
195 | 183 | ||
196 | for_each_cpu(i, policy->cpus) { | 184 | for_each_cpu(i, policy->cpus) { |
197 | cdbs = dbs_data->cdata->get_cpu_cdbs(i); | 185 | cdbs = dbs_data->cdata->get_cpu_cdbs(i); |
198 | cancel_delayed_work_sync(&cdbs->dwork); | 186 | del_timer_sync(&cdbs->timer); |
199 | } | 187 | } |
200 | } | 188 | } |
201 | 189 | ||
190 | void gov_cancel_work(struct cpu_common_dbs_info *shared) | ||
191 | { | ||
192 | /* Tell dbs_timer_handler() to skip queuing up work items. */ | ||
193 | atomic_inc(&shared->skip_work); | ||
194 | /* | ||
195 | * If dbs_timer_handler() is already running, it may not notice the | ||
196 | * incremented skip_work, so wait for it to complete to prevent its work | ||
197 | * item from being queued up after the cancel_work_sync() below. | ||
198 | */ | ||
199 | gov_cancel_timers(shared->policy); | ||
200 | /* | ||
201 | * In case dbs_timer_handler() managed to run and spawn a work item | ||
202 | * before the timers have been canceled, wait for that work item to | ||
203 | * complete and then cancel all of the timers set up by it. If | ||
204 | * dbs_timer_handler() runs again at that point, it will see the | ||
205 | * positive value of skip_work and won't spawn any more work items. | ||
206 | */ | ||
207 | cancel_work_sync(&shared->work); | ||
208 | gov_cancel_timers(shared->policy); | ||
209 | atomic_set(&shared->skip_work, 0); | ||
210 | } | ||
211 | EXPORT_SYMBOL_GPL(gov_cancel_work); | ||
212 | |||
202 | /* Will return if we need to evaluate cpu load again or not */ | 213 | /* Will return if we need to evaluate cpu load again or not */ |
203 | static bool need_load_eval(struct cpu_common_dbs_info *shared, | 214 | static bool need_load_eval(struct cpu_common_dbs_info *shared, |
204 | unsigned int sampling_rate) | 215 | unsigned int sampling_rate) |
@@ -217,29 +228,21 @@ static bool need_load_eval(struct cpu_common_dbs_info *shared, | |||
217 | return true; | 228 | return true; |
218 | } | 229 | } |
219 | 230 | ||
220 | static void dbs_timer(struct work_struct *work) | 231 | static void dbs_work_handler(struct work_struct *work) |
221 | { | 232 | { |
222 | struct cpu_dbs_info *cdbs = container_of(work, struct cpu_dbs_info, | 233 | struct cpu_common_dbs_info *shared = container_of(work, struct |
223 | dwork.work); | 234 | cpu_common_dbs_info, work); |
224 | struct cpu_common_dbs_info *shared = cdbs->shared; | ||
225 | struct cpufreq_policy *policy; | 235 | struct cpufreq_policy *policy; |
226 | struct dbs_data *dbs_data; | 236 | struct dbs_data *dbs_data; |
227 | unsigned int sampling_rate, delay; | 237 | unsigned int sampling_rate, delay; |
228 | bool modify_all = true; | 238 | bool eval_load; |
229 | |||
230 | mutex_lock(&shared->timer_mutex); | ||
231 | 239 | ||
232 | policy = shared->policy; | 240 | policy = shared->policy; |
233 | |||
234 | /* | ||
235 | * Governor might already be disabled and there is no point continuing | ||
236 | * with the work-handler. | ||
237 | */ | ||
238 | if (!policy) | ||
239 | goto unlock; | ||
240 | |||
241 | dbs_data = policy->governor_data; | 241 | dbs_data = policy->governor_data; |
242 | 242 | ||
243 | /* Kill all timers */ | ||
244 | gov_cancel_timers(policy); | ||
245 | |||
243 | if (dbs_data->cdata->governor == GOV_CONSERVATIVE) { | 246 | if (dbs_data->cdata->governor == GOV_CONSERVATIVE) { |
244 | struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; | 247 | struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; |
245 | 248 | ||
@@ -250,14 +253,37 @@ static void dbs_timer(struct work_struct *work) | |||
250 | sampling_rate = od_tuners->sampling_rate; | 253 | sampling_rate = od_tuners->sampling_rate; |
251 | } | 254 | } |
252 | 255 | ||
253 | if (!need_load_eval(cdbs->shared, sampling_rate)) | 256 | eval_load = need_load_eval(shared, sampling_rate); |
254 | modify_all = false; | ||
255 | |||
256 | delay = dbs_data->cdata->gov_dbs_timer(cdbs, dbs_data, modify_all); | ||
257 | gov_queue_work(dbs_data, policy, delay, modify_all); | ||
258 | 257 | ||
259 | unlock: | 258 | /* |
259 | * Make sure cpufreq_governor_limits() isn't evaluating load in | ||
260 | * parallel. | ||
261 | */ | ||
262 | mutex_lock(&shared->timer_mutex); | ||
263 | delay = dbs_data->cdata->gov_dbs_timer(policy, eval_load); | ||
260 | mutex_unlock(&shared->timer_mutex); | 264 | mutex_unlock(&shared->timer_mutex); |
265 | |||
266 | atomic_dec(&shared->skip_work); | ||
267 | |||
268 | gov_add_timers(policy, delay); | ||
269 | } | ||
270 | |||
271 | static void dbs_timer_handler(unsigned long data) | ||
272 | { | ||
273 | struct cpu_dbs_info *cdbs = (struct cpu_dbs_info *)data; | ||
274 | struct cpu_common_dbs_info *shared = cdbs->shared; | ||
275 | |||
276 | /* | ||
277 | * Timer handler may not be allowed to queue the work at the moment, | ||
278 | * because: | ||
279 | * - Another timer handler has done that | ||
280 | * - We are stopping the governor | ||
281 | * - Or we are updating the sampling rate of the ondemand governor | ||
282 | */ | ||
283 | if (atomic_inc_return(&shared->skip_work) > 1) | ||
284 | atomic_dec(&shared->skip_work); | ||
285 | else | ||
286 | queue_work(system_wq, &shared->work); | ||
261 | } | 287 | } |
262 | 288 | ||
263 | static void set_sampling_rate(struct dbs_data *dbs_data, | 289 | static void set_sampling_rate(struct dbs_data *dbs_data, |
@@ -287,6 +313,9 @@ static int alloc_common_dbs_info(struct cpufreq_policy *policy, | |||
287 | for_each_cpu(j, policy->related_cpus) | 313 | for_each_cpu(j, policy->related_cpus) |
288 | cdata->get_cpu_cdbs(j)->shared = shared; | 314 | cdata->get_cpu_cdbs(j)->shared = shared; |
289 | 315 | ||
316 | mutex_init(&shared->timer_mutex); | ||
317 | atomic_set(&shared->skip_work, 0); | ||
318 | INIT_WORK(&shared->work, dbs_work_handler); | ||
290 | return 0; | 319 | return 0; |
291 | } | 320 | } |
292 | 321 | ||
@@ -297,6 +326,8 @@ static void free_common_dbs_info(struct cpufreq_policy *policy, | |||
297 | struct cpu_common_dbs_info *shared = cdbs->shared; | 326 | struct cpu_common_dbs_info *shared = cdbs->shared; |
298 | int j; | 327 | int j; |
299 | 328 | ||
329 | mutex_destroy(&shared->timer_mutex); | ||
330 | |||
300 | for_each_cpu(j, policy->cpus) | 331 | for_each_cpu(j, policy->cpus) |
301 | cdata->get_cpu_cdbs(j)->shared = NULL; | 332 | cdata->get_cpu_cdbs(j)->shared = NULL; |
302 | 333 | ||
@@ -433,7 +464,6 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy, | |||
433 | 464 | ||
434 | shared->policy = policy; | 465 | shared->policy = policy; |
435 | shared->time_stamp = ktime_get(); | 466 | shared->time_stamp = ktime_get(); |
436 | mutex_init(&shared->timer_mutex); | ||
437 | 467 | ||
438 | for_each_cpu(j, policy->cpus) { | 468 | for_each_cpu(j, policy->cpus) { |
439 | struct cpu_dbs_info *j_cdbs = cdata->get_cpu_cdbs(j); | 469 | struct cpu_dbs_info *j_cdbs = cdata->get_cpu_cdbs(j); |
@@ -450,7 +480,9 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy, | |||
450 | if (ignore_nice) | 480 | if (ignore_nice) |
451 | j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; | 481 | j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; |
452 | 482 | ||
453 | INIT_DEFERRABLE_WORK(&j_cdbs->dwork, dbs_timer); | 483 | __setup_timer(&j_cdbs->timer, dbs_timer_handler, |
484 | (unsigned long)j_cdbs, | ||
485 | TIMER_DEFERRABLE | TIMER_IRQSAFE); | ||
454 | } | 486 | } |
455 | 487 | ||
456 | if (cdata->governor == GOV_CONSERVATIVE) { | 488 | if (cdata->governor == GOV_CONSERVATIVE) { |
@@ -468,8 +500,7 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy, | |||
468 | od_ops->powersave_bias_init_cpu(cpu); | 500 | od_ops->powersave_bias_init_cpu(cpu); |
469 | } | 501 | } |
470 | 502 | ||
471 | gov_queue_work(dbs_data, policy, delay_for_sampling_rate(sampling_rate), | 503 | gov_add_timers(policy, delay_for_sampling_rate(sampling_rate)); |
472 | true); | ||
473 | return 0; | 504 | return 0; |
474 | } | 505 | } |
475 | 506 | ||
@@ -483,18 +514,9 @@ static int cpufreq_governor_stop(struct cpufreq_policy *policy, | |||
483 | if (!shared || !shared->policy) | 514 | if (!shared || !shared->policy) |
484 | return -EBUSY; | 515 | return -EBUSY; |
485 | 516 | ||
486 | /* | 517 | gov_cancel_work(shared); |
487 | * Work-handler must see this updated, as it should not proceed any | ||
488 | * further after governor is disabled. And so timer_mutex is taken while | ||
489 | * updating this value. | ||
490 | */ | ||
491 | mutex_lock(&shared->timer_mutex); | ||
492 | shared->policy = NULL; | 518 | shared->policy = NULL; |
493 | mutex_unlock(&shared->timer_mutex); | ||
494 | |||
495 | gov_cancel_work(dbs_data, policy); | ||
496 | 519 | ||
497 | mutex_destroy(&shared->timer_mutex); | ||
498 | return 0; | 520 | return 0; |
499 | } | 521 | } |
500 | 522 | ||
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 5621bb03e874..91e767a058a7 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #ifndef _CPUFREQ_GOVERNOR_H | 17 | #ifndef _CPUFREQ_GOVERNOR_H |
18 | #define _CPUFREQ_GOVERNOR_H | 18 | #define _CPUFREQ_GOVERNOR_H |
19 | 19 | ||
20 | #include <linux/atomic.h> | ||
20 | #include <linux/cpufreq.h> | 21 | #include <linux/cpufreq.h> |
21 | #include <linux/kernel_stat.h> | 22 | #include <linux/kernel_stat.h> |
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -132,12 +133,14 @@ static void *get_cpu_dbs_info_s(int cpu) \ | |||
132 | struct cpu_common_dbs_info { | 133 | struct cpu_common_dbs_info { |
133 | struct cpufreq_policy *policy; | 134 | struct cpufreq_policy *policy; |
134 | /* | 135 | /* |
135 | * percpu mutex that serializes governor limit change with dbs_timer | 136 | * Per policy mutex that serializes load evaluation from limit-change |
136 | * invocation. We do not want dbs_timer to run when user is changing | 137 | * and work-handler. |
137 | * the governor or limits. | ||
138 | */ | 138 | */ |
139 | struct mutex timer_mutex; | 139 | struct mutex timer_mutex; |
140 | |||
140 | ktime_t time_stamp; | 141 | ktime_t time_stamp; |
142 | atomic_t skip_work; | ||
143 | struct work_struct work; | ||
141 | }; | 144 | }; |
142 | 145 | ||
143 | /* Per cpu structures */ | 146 | /* Per cpu structures */ |
@@ -152,7 +155,7 @@ struct cpu_dbs_info { | |||
152 | * wake-up from idle. | 155 | * wake-up from idle. |
153 | */ | 156 | */ |
154 | unsigned int prev_load; | 157 | unsigned int prev_load; |
155 | struct delayed_work dwork; | 158 | struct timer_list timer; |
156 | struct cpu_common_dbs_info *shared; | 159 | struct cpu_common_dbs_info *shared; |
157 | }; | 160 | }; |
158 | 161 | ||
@@ -209,8 +212,7 @@ struct common_dbs_data { | |||
209 | 212 | ||
210 | struct cpu_dbs_info *(*get_cpu_cdbs)(int cpu); | 213 | struct cpu_dbs_info *(*get_cpu_cdbs)(int cpu); |
211 | void *(*get_cpu_dbs_info_s)(int cpu); | 214 | void *(*get_cpu_dbs_info_s)(int cpu); |
212 | unsigned int (*gov_dbs_timer)(struct cpu_dbs_info *cdbs, | 215 | unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy, |
213 | struct dbs_data *dbs_data, | ||
214 | bool modify_all); | 216 | bool modify_all); |
215 | void (*gov_check_cpu)(int cpu, unsigned int load); | 217 | void (*gov_check_cpu)(int cpu, unsigned int load); |
216 | int (*init)(struct dbs_data *dbs_data, bool notify); | 218 | int (*init)(struct dbs_data *dbs_data, bool notify); |
@@ -269,11 +271,11 @@ static ssize_t show_sampling_rate_min_gov_pol \ | |||
269 | 271 | ||
270 | extern struct mutex cpufreq_governor_lock; | 272 | extern struct mutex cpufreq_governor_lock; |
271 | 273 | ||
274 | void gov_add_timers(struct cpufreq_policy *policy, unsigned int delay); | ||
275 | void gov_cancel_work(struct cpu_common_dbs_info *shared); | ||
272 | void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); | 276 | void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); |
273 | int cpufreq_governor_dbs(struct cpufreq_policy *policy, | 277 | int cpufreq_governor_dbs(struct cpufreq_policy *policy, |
274 | struct common_dbs_data *cdata, unsigned int event); | 278 | struct common_dbs_data *cdata, unsigned int event); |
275 | void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, | ||
276 | unsigned int delay, bool all_cpus); | ||
277 | void od_register_powersave_bias_handler(unsigned int (*f) | 279 | void od_register_powersave_bias_handler(unsigned int (*f) |
278 | (struct cpufreq_policy *, unsigned int, unsigned int), | 280 | (struct cpufreq_policy *, unsigned int, unsigned int), |
279 | unsigned int powersave_bias); | 281 | unsigned int powersave_bias); |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 03ac6ce54042..eae51070c034 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
@@ -191,10 +191,9 @@ static void od_check_cpu(int cpu, unsigned int load) | |||
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
194 | static unsigned int od_dbs_timer(struct cpu_dbs_info *cdbs, | 194 | static unsigned int od_dbs_timer(struct cpufreq_policy *policy, bool modify_all) |
195 | struct dbs_data *dbs_data, bool modify_all) | ||
196 | { | 195 | { |
197 | struct cpufreq_policy *policy = cdbs->shared->policy; | 196 | struct dbs_data *dbs_data = policy->governor_data; |
198 | unsigned int cpu = policy->cpu; | 197 | unsigned int cpu = policy->cpu; |
199 | struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, | 198 | struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, |
200 | cpu); | 199 | cpu); |
@@ -247,40 +246,66 @@ static void update_sampling_rate(struct dbs_data *dbs_data, | |||
247 | unsigned int new_rate) | 246 | unsigned int new_rate) |
248 | { | 247 | { |
249 | struct od_dbs_tuners *od_tuners = dbs_data->tuners; | 248 | struct od_dbs_tuners *od_tuners = dbs_data->tuners; |
249 | struct cpumask cpumask; | ||
250 | int cpu; | 250 | int cpu; |
251 | 251 | ||
252 | od_tuners->sampling_rate = new_rate = max(new_rate, | 252 | od_tuners->sampling_rate = new_rate = max(new_rate, |
253 | dbs_data->min_sampling_rate); | 253 | dbs_data->min_sampling_rate); |
254 | 254 | ||
255 | for_each_online_cpu(cpu) { | 255 | /* |
256 | * Lock governor so that governor start/stop can't execute in parallel. | ||
257 | */ | ||
258 | mutex_lock(&od_dbs_cdata.mutex); | ||
259 | |||
260 | cpumask_copy(&cpumask, cpu_online_mask); | ||
261 | |||
262 | for_each_cpu(cpu, &cpumask) { | ||
256 | struct cpufreq_policy *policy; | 263 | struct cpufreq_policy *policy; |
257 | struct od_cpu_dbs_info_s *dbs_info; | 264 | struct od_cpu_dbs_info_s *dbs_info; |
265 | struct cpu_dbs_info *cdbs; | ||
266 | struct cpu_common_dbs_info *shared; | ||
258 | unsigned long next_sampling, appointed_at; | 267 | unsigned long next_sampling, appointed_at; |
259 | 268 | ||
260 | policy = cpufreq_cpu_get(cpu); | ||
261 | if (!policy) | ||
262 | continue; | ||
263 | if (policy->governor != &cpufreq_gov_ondemand) { | ||
264 | cpufreq_cpu_put(policy); | ||
265 | continue; | ||
266 | } | ||
267 | dbs_info = &per_cpu(od_cpu_dbs_info, cpu); | 269 | dbs_info = &per_cpu(od_cpu_dbs_info, cpu); |
268 | cpufreq_cpu_put(policy); | 270 | cdbs = &dbs_info->cdbs; |
271 | shared = cdbs->shared; | ||
269 | 272 | ||
270 | if (!delayed_work_pending(&dbs_info->cdbs.dwork)) | 273 | /* |
274 | * A valid shared and shared->policy means governor hasn't | ||
275 | * stopped or exited yet. | ||
276 | */ | ||
277 | if (!shared || !shared->policy) | ||
278 | continue; | ||
279 | |||
280 | policy = shared->policy; | ||
281 | |||
282 | /* clear all CPUs of this policy */ | ||
283 | cpumask_andnot(&cpumask, &cpumask, policy->cpus); | ||
284 | |||
285 | /* | ||
286 | * Update sampling rate for CPUs whose policy is governed by | ||
287 | * dbs_data. In case of governor_per_policy, only a single | ||
288 | * policy will be governed by dbs_data, otherwise there can be | ||
289 | * multiple policies that are governed by the same dbs_data. | ||
290 | */ | ||
291 | if (dbs_data != policy->governor_data) | ||
271 | continue; | 292 | continue; |
272 | 293 | ||
294 | /* | ||
295 | * Checking this for any CPU should be fine, timers for all of | ||
296 | * them are scheduled together. | ||
297 | */ | ||
273 | next_sampling = jiffies + usecs_to_jiffies(new_rate); | 298 | next_sampling = jiffies + usecs_to_jiffies(new_rate); |
274 | appointed_at = dbs_info->cdbs.dwork.timer.expires; | 299 | appointed_at = dbs_info->cdbs.timer.expires; |
275 | 300 | ||
276 | if (time_before(next_sampling, appointed_at)) { | 301 | if (time_before(next_sampling, appointed_at)) { |
277 | cancel_delayed_work_sync(&dbs_info->cdbs.dwork); | 302 | gov_cancel_work(shared); |
278 | 303 | gov_add_timers(policy, usecs_to_jiffies(new_rate)); | |
279 | gov_queue_work(dbs_data, policy, | ||
280 | usecs_to_jiffies(new_rate), true); | ||
281 | 304 | ||
282 | } | 305 | } |
283 | } | 306 | } |
307 | |||
308 | mutex_unlock(&od_dbs_cdata.mutex); | ||
284 | } | 309 | } |
285 | 310 | ||
286 | static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, | 311 | static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf, |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 98fb8821382d..cd83d477e32d 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -66,6 +66,7 @@ static inline int ceiling_fp(int32_t x) | |||
66 | 66 | ||
67 | struct sample { | 67 | struct sample { |
68 | int32_t core_pct_busy; | 68 | int32_t core_pct_busy; |
69 | int32_t busy_scaled; | ||
69 | u64 aperf; | 70 | u64 aperf; |
70 | u64 mperf; | 71 | u64 mperf; |
71 | u64 tsc; | 72 | u64 tsc; |
@@ -112,6 +113,7 @@ struct cpudata { | |||
112 | u64 prev_aperf; | 113 | u64 prev_aperf; |
113 | u64 prev_mperf; | 114 | u64 prev_mperf; |
114 | u64 prev_tsc; | 115 | u64 prev_tsc; |
116 | u64 prev_cummulative_iowait; | ||
115 | struct sample sample; | 117 | struct sample sample; |
116 | }; | 118 | }; |
117 | 119 | ||
@@ -133,6 +135,7 @@ struct pstate_funcs { | |||
133 | int (*get_scaling)(void); | 135 | int (*get_scaling)(void); |
134 | void (*set)(struct cpudata*, int pstate); | 136 | void (*set)(struct cpudata*, int pstate); |
135 | void (*get_vid)(struct cpudata *); | 137 | void (*get_vid)(struct cpudata *); |
138 | int32_t (*get_target_pstate)(struct cpudata *); | ||
136 | }; | 139 | }; |
137 | 140 | ||
138 | struct cpu_defaults { | 141 | struct cpu_defaults { |
@@ -140,6 +143,9 @@ struct cpu_defaults { | |||
140 | struct pstate_funcs funcs; | 143 | struct pstate_funcs funcs; |
141 | }; | 144 | }; |
142 | 145 | ||
146 | static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu); | ||
147 | static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu); | ||
148 | |||
143 | static struct pstate_adjust_policy pid_params; | 149 | static struct pstate_adjust_policy pid_params; |
144 | static struct pstate_funcs pstate_funcs; | 150 | static struct pstate_funcs pstate_funcs; |
145 | static int hwp_active; | 151 | static int hwp_active; |
@@ -738,6 +744,7 @@ static struct cpu_defaults core_params = { | |||
738 | .get_turbo = core_get_turbo_pstate, | 744 | .get_turbo = core_get_turbo_pstate, |
739 | .get_scaling = core_get_scaling, | 745 | .get_scaling = core_get_scaling, |
740 | .set = core_set_pstate, | 746 | .set = core_set_pstate, |
747 | .get_target_pstate = get_target_pstate_use_performance, | ||
741 | }, | 748 | }, |
742 | }; | 749 | }; |
743 | 750 | ||
@@ -758,6 +765,7 @@ static struct cpu_defaults silvermont_params = { | |||
758 | .set = atom_set_pstate, | 765 | .set = atom_set_pstate, |
759 | .get_scaling = silvermont_get_scaling, | 766 | .get_scaling = silvermont_get_scaling, |
760 | .get_vid = atom_get_vid, | 767 | .get_vid = atom_get_vid, |
768 | .get_target_pstate = get_target_pstate_use_cpu_load, | ||
761 | }, | 769 | }, |
762 | }; | 770 | }; |
763 | 771 | ||
@@ -778,6 +786,7 @@ static struct cpu_defaults airmont_params = { | |||
778 | .set = atom_set_pstate, | 786 | .set = atom_set_pstate, |
779 | .get_scaling = airmont_get_scaling, | 787 | .get_scaling = airmont_get_scaling, |
780 | .get_vid = atom_get_vid, | 788 | .get_vid = atom_get_vid, |
789 | .get_target_pstate = get_target_pstate_use_cpu_load, | ||
781 | }, | 790 | }, |
782 | }; | 791 | }; |
783 | 792 | ||
@@ -797,6 +806,7 @@ static struct cpu_defaults knl_params = { | |||
797 | .get_turbo = knl_get_turbo_pstate, | 806 | .get_turbo = knl_get_turbo_pstate, |
798 | .get_scaling = core_get_scaling, | 807 | .get_scaling = core_get_scaling, |
799 | .set = core_set_pstate, | 808 | .set = core_set_pstate, |
809 | .get_target_pstate = get_target_pstate_use_performance, | ||
800 | }, | 810 | }, |
801 | }; | 811 | }; |
802 | 812 | ||
@@ -882,12 +892,11 @@ static inline void intel_pstate_sample(struct cpudata *cpu) | |||
882 | local_irq_save(flags); | 892 | local_irq_save(flags); |
883 | rdmsrl(MSR_IA32_APERF, aperf); | 893 | rdmsrl(MSR_IA32_APERF, aperf); |
884 | rdmsrl(MSR_IA32_MPERF, mperf); | 894 | rdmsrl(MSR_IA32_MPERF, mperf); |
885 | if (cpu->prev_mperf == mperf) { | 895 | tsc = rdtsc(); |
896 | if ((cpu->prev_mperf == mperf) || (cpu->prev_tsc == tsc)) { | ||
886 | local_irq_restore(flags); | 897 | local_irq_restore(flags); |
887 | return; | 898 | return; |
888 | } | 899 | } |
889 | |||
890 | tsc = rdtsc(); | ||
891 | local_irq_restore(flags); | 900 | local_irq_restore(flags); |
892 | 901 | ||
893 | cpu->last_sample_time = cpu->sample.time; | 902 | cpu->last_sample_time = cpu->sample.time; |
@@ -922,7 +931,43 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu) | |||
922 | mod_timer_pinned(&cpu->timer, jiffies + delay); | 931 | mod_timer_pinned(&cpu->timer, jiffies + delay); |
923 | } | 932 | } |
924 | 933 | ||
925 | static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) | 934 | static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu) |
935 | { | ||
936 | struct sample *sample = &cpu->sample; | ||
937 | u64 cummulative_iowait, delta_iowait_us; | ||
938 | u64 delta_iowait_mperf; | ||
939 | u64 mperf, now; | ||
940 | int32_t cpu_load; | ||
941 | |||
942 | cummulative_iowait = get_cpu_iowait_time_us(cpu->cpu, &now); | ||
943 | |||
944 | /* | ||
945 | * Convert iowait time into number of IO cycles spent at max_freq. | ||
946 | * IO is considered as busy only for the cpu_load algorithm. For | ||
947 | * performance this is not needed since we always try to reach the | ||
948 | * maximum P-State, so we are already boosting the IOs. | ||
949 | */ | ||
950 | delta_iowait_us = cummulative_iowait - cpu->prev_cummulative_iowait; | ||
951 | delta_iowait_mperf = div64_u64(delta_iowait_us * cpu->pstate.scaling * | ||
952 | cpu->pstate.max_pstate, MSEC_PER_SEC); | ||
953 | |||
954 | mperf = cpu->sample.mperf + delta_iowait_mperf; | ||
955 | cpu->prev_cummulative_iowait = cummulative_iowait; | ||
956 | |||
957 | |||
958 | /* | ||
959 | * The load can be estimated as the ratio of the mperf counter | ||
960 | * running at a constant frequency during active periods | ||
961 | * (C0) and the time stamp counter running at the same frequency | ||
962 | * also during C-states. | ||
963 | */ | ||
964 | cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc); | ||
965 | cpu->sample.busy_scaled = cpu_load; | ||
966 | |||
967 | return cpu->pstate.current_pstate - pid_calc(&cpu->pid, cpu_load); | ||
968 | } | ||
969 | |||
970 | static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) | ||
926 | { | 971 | { |
927 | int32_t core_busy, max_pstate, current_pstate, sample_ratio; | 972 | int32_t core_busy, max_pstate, current_pstate, sample_ratio; |
928 | s64 duration_us; | 973 | s64 duration_us; |
@@ -960,30 +1005,24 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) | |||
960 | core_busy = mul_fp(core_busy, sample_ratio); | 1005 | core_busy = mul_fp(core_busy, sample_ratio); |
961 | } | 1006 | } |
962 | 1007 | ||
963 | return core_busy; | 1008 | cpu->sample.busy_scaled = core_busy; |
1009 | return cpu->pstate.current_pstate - pid_calc(&cpu->pid, core_busy); | ||
964 | } | 1010 | } |
965 | 1011 | ||
966 | static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) | 1012 | static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) |
967 | { | 1013 | { |
968 | int32_t busy_scaled; | 1014 | int from, target_pstate; |
969 | struct _pid *pid; | ||
970 | signed int ctl; | ||
971 | int from; | ||
972 | struct sample *sample; | 1015 | struct sample *sample; |
973 | 1016 | ||
974 | from = cpu->pstate.current_pstate; | 1017 | from = cpu->pstate.current_pstate; |
975 | 1018 | ||
976 | pid = &cpu->pid; | 1019 | target_pstate = pstate_funcs.get_target_pstate(cpu); |
977 | busy_scaled = intel_pstate_get_scaled_busy(cpu); | ||
978 | 1020 | ||
979 | ctl = pid_calc(pid, busy_scaled); | 1021 | intel_pstate_set_pstate(cpu, target_pstate, true); |
980 | |||
981 | /* Negative values of ctl increase the pstate and vice versa */ | ||
982 | intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl, true); | ||
983 | 1022 | ||
984 | sample = &cpu->sample; | 1023 | sample = &cpu->sample; |
985 | trace_pstate_sample(fp_toint(sample->core_pct_busy), | 1024 | trace_pstate_sample(fp_toint(sample->core_pct_busy), |
986 | fp_toint(busy_scaled), | 1025 | fp_toint(sample->busy_scaled), |
987 | from, | 1026 | from, |
988 | cpu->pstate.current_pstate, | 1027 | cpu->pstate.current_pstate, |
989 | sample->mperf, | 1028 | sample->mperf, |
@@ -1237,6 +1276,8 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) | |||
1237 | pstate_funcs.get_scaling = funcs->get_scaling; | 1276 | pstate_funcs.get_scaling = funcs->get_scaling; |
1238 | pstate_funcs.set = funcs->set; | 1277 | pstate_funcs.set = funcs->set; |
1239 | pstate_funcs.get_vid = funcs->get_vid; | 1278 | pstate_funcs.get_vid = funcs->get_vid; |
1279 | pstate_funcs.get_target_pstate = funcs->get_target_pstate; | ||
1280 | |||
1240 | } | 1281 | } |
1241 | 1282 | ||
1242 | #if IS_ENABLED(CONFIG_ACPI) | 1283 | #if IS_ENABLED(CONFIG_ACPI) |
diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c index 83001dc5b646..1efba340456d 100644 --- a/drivers/cpufreq/mt8173-cpufreq.c +++ b/drivers/cpufreq/mt8173-cpufreq.c | |||
@@ -41,16 +41,35 @@ | |||
41 | * the original PLL becomes stable at target frequency. | 41 | * the original PLL becomes stable at target frequency. |
42 | */ | 42 | */ |
43 | struct mtk_cpu_dvfs_info { | 43 | struct mtk_cpu_dvfs_info { |
44 | struct cpumask cpus; | ||
44 | struct device *cpu_dev; | 45 | struct device *cpu_dev; |
45 | struct regulator *proc_reg; | 46 | struct regulator *proc_reg; |
46 | struct regulator *sram_reg; | 47 | struct regulator *sram_reg; |
47 | struct clk *cpu_clk; | 48 | struct clk *cpu_clk; |
48 | struct clk *inter_clk; | 49 | struct clk *inter_clk; |
49 | struct thermal_cooling_device *cdev; | 50 | struct thermal_cooling_device *cdev; |
51 | struct list_head list_head; | ||
50 | int intermediate_voltage; | 52 | int intermediate_voltage; |
51 | bool need_voltage_tracking; | 53 | bool need_voltage_tracking; |
52 | }; | 54 | }; |
53 | 55 | ||
56 | static LIST_HEAD(dvfs_info_list); | ||
57 | |||
58 | static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu) | ||
59 | { | ||
60 | struct mtk_cpu_dvfs_info *info; | ||
61 | struct list_head *list; | ||
62 | |||
63 | list_for_each(list, &dvfs_info_list) { | ||
64 | info = list_entry(list, struct mtk_cpu_dvfs_info, list_head); | ||
65 | |||
66 | if (cpumask_test_cpu(cpu, &info->cpus)) | ||
67 | return info; | ||
68 | } | ||
69 | |||
70 | return NULL; | ||
71 | } | ||
72 | |||
54 | static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, | 73 | static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, |
55 | int new_vproc) | 74 | int new_vproc) |
56 | { | 75 | { |
@@ -59,7 +78,10 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, | |||
59 | int old_vproc, old_vsram, new_vsram, vsram, vproc, ret; | 78 | int old_vproc, old_vsram, new_vsram, vsram, vproc, ret; |
60 | 79 | ||
61 | old_vproc = regulator_get_voltage(proc_reg); | 80 | old_vproc = regulator_get_voltage(proc_reg); |
62 | old_vsram = regulator_get_voltage(sram_reg); | 81 | if (old_vproc < 0) { |
82 | pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); | ||
83 | return old_vproc; | ||
84 | } | ||
63 | /* Vsram should not exceed the maximum allowed voltage of SoC. */ | 85 | /* Vsram should not exceed the maximum allowed voltage of SoC. */ |
64 | new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT); | 86 | new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT); |
65 | 87 | ||
@@ -72,7 +94,17 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, | |||
72 | */ | 94 | */ |
73 | do { | 95 | do { |
74 | old_vsram = regulator_get_voltage(sram_reg); | 96 | old_vsram = regulator_get_voltage(sram_reg); |
97 | if (old_vsram < 0) { | ||
98 | pr_err("%s: invalid Vsram value: %d\n", | ||
99 | __func__, old_vsram); | ||
100 | return old_vsram; | ||
101 | } | ||
75 | old_vproc = regulator_get_voltage(proc_reg); | 102 | old_vproc = regulator_get_voltage(proc_reg); |
103 | if (old_vproc < 0) { | ||
104 | pr_err("%s: invalid Vproc value: %d\n", | ||
105 | __func__, old_vproc); | ||
106 | return old_vproc; | ||
107 | } | ||
76 | 108 | ||
77 | vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT); | 109 | vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT); |
78 | 110 | ||
@@ -117,7 +149,17 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, | |||
117 | */ | 149 | */ |
118 | do { | 150 | do { |
119 | old_vproc = regulator_get_voltage(proc_reg); | 151 | old_vproc = regulator_get_voltage(proc_reg); |
152 | if (old_vproc < 0) { | ||
153 | pr_err("%s: invalid Vproc value: %d\n", | ||
154 | __func__, old_vproc); | ||
155 | return old_vproc; | ||
156 | } | ||
120 | old_vsram = regulator_get_voltage(sram_reg); | 157 | old_vsram = regulator_get_voltage(sram_reg); |
158 | if (old_vsram < 0) { | ||
159 | pr_err("%s: invalid Vsram value: %d\n", | ||
160 | __func__, old_vsram); | ||
161 | return old_vsram; | ||
162 | } | ||
121 | 163 | ||
122 | vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT); | 164 | vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT); |
123 | ret = regulator_set_voltage(proc_reg, vproc, | 165 | ret = regulator_set_voltage(proc_reg, vproc, |
@@ -185,6 +227,10 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, | |||
185 | 227 | ||
186 | old_freq_hz = clk_get_rate(cpu_clk); | 228 | old_freq_hz = clk_get_rate(cpu_clk); |
187 | old_vproc = regulator_get_voltage(info->proc_reg); | 229 | old_vproc = regulator_get_voltage(info->proc_reg); |
230 | if (old_vproc < 0) { | ||
231 | pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); | ||
232 | return old_vproc; | ||
233 | } | ||
188 | 234 | ||
189 | freq_hz = freq_table[index].frequency * 1000; | 235 | freq_hz = freq_table[index].frequency * 1000; |
190 | 236 | ||
@@ -344,7 +390,15 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) | |||
344 | /* Both presence and absence of sram regulator are valid cases. */ | 390 | /* Both presence and absence of sram regulator are valid cases. */ |
345 | sram_reg = regulator_get_exclusive(cpu_dev, "sram"); | 391 | sram_reg = regulator_get_exclusive(cpu_dev, "sram"); |
346 | 392 | ||
347 | ret = dev_pm_opp_of_add_table(cpu_dev); | 393 | /* Get OPP-sharing information from "operating-points-v2" bindings */ |
394 | ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus); | ||
395 | if (ret) { | ||
396 | pr_err("failed to get OPP-sharing information for cpu%d\n", | ||
397 | cpu); | ||
398 | goto out_free_resources; | ||
399 | } | ||
400 | |||
401 | ret = dev_pm_opp_of_cpumask_add_table(&info->cpus); | ||
348 | if (ret) { | 402 | if (ret) { |
349 | pr_warn("no OPP table for cpu%d\n", cpu); | 403 | pr_warn("no OPP table for cpu%d\n", cpu); |
350 | goto out_free_resources; | 404 | goto out_free_resources; |
@@ -378,7 +432,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) | |||
378 | return 0; | 432 | return 0; |
379 | 433 | ||
380 | out_free_opp_table: | 434 | out_free_opp_table: |
381 | dev_pm_opp_of_remove_table(cpu_dev); | 435 | dev_pm_opp_of_cpumask_remove_table(&info->cpus); |
382 | 436 | ||
383 | out_free_resources: | 437 | out_free_resources: |
384 | if (!IS_ERR(proc_reg)) | 438 | if (!IS_ERR(proc_reg)) |
@@ -404,7 +458,7 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) | |||
404 | if (!IS_ERR(info->inter_clk)) | 458 | if (!IS_ERR(info->inter_clk)) |
405 | clk_put(info->inter_clk); | 459 | clk_put(info->inter_clk); |
406 | 460 | ||
407 | dev_pm_opp_of_remove_table(info->cpu_dev); | 461 | dev_pm_opp_of_cpumask_remove_table(&info->cpus); |
408 | } | 462 | } |
409 | 463 | ||
410 | static int mtk_cpufreq_init(struct cpufreq_policy *policy) | 464 | static int mtk_cpufreq_init(struct cpufreq_policy *policy) |
@@ -413,22 +467,18 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy) | |||
413 | struct cpufreq_frequency_table *freq_table; | 467 | struct cpufreq_frequency_table *freq_table; |
414 | int ret; | 468 | int ret; |
415 | 469 | ||
416 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 470 | info = mtk_cpu_dvfs_info_lookup(policy->cpu); |
417 | if (!info) | 471 | if (!info) { |
418 | return -ENOMEM; | 472 | pr_err("dvfs info for cpu%d is not initialized.\n", |
419 | 473 | policy->cpu); | |
420 | ret = mtk_cpu_dvfs_info_init(info, policy->cpu); | 474 | return -EINVAL; |
421 | if (ret) { | ||
422 | pr_err("%s failed to initialize dvfs info for cpu%d\n", | ||
423 | __func__, policy->cpu); | ||
424 | goto out_free_dvfs_info; | ||
425 | } | 475 | } |
426 | 476 | ||
427 | ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table); | 477 | ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table); |
428 | if (ret) { | 478 | if (ret) { |
429 | pr_err("failed to init cpufreq table for cpu%d: %d\n", | 479 | pr_err("failed to init cpufreq table for cpu%d: %d\n", |
430 | policy->cpu, ret); | 480 | policy->cpu, ret); |
431 | goto out_release_dvfs_info; | 481 | return ret; |
432 | } | 482 | } |
433 | 483 | ||
434 | ret = cpufreq_table_validate_and_show(policy, freq_table); | 484 | ret = cpufreq_table_validate_and_show(policy, freq_table); |
@@ -437,8 +487,7 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy) | |||
437 | goto out_free_cpufreq_table; | 487 | goto out_free_cpufreq_table; |
438 | } | 488 | } |
439 | 489 | ||
440 | /* CPUs in the same cluster share a clock and power domain. */ | 490 | cpumask_copy(policy->cpus, &info->cpus); |
441 | cpumask_copy(policy->cpus, &cpu_topology[policy->cpu].core_sibling); | ||
442 | policy->driver_data = info; | 491 | policy->driver_data = info; |
443 | policy->clk = info->cpu_clk; | 492 | policy->clk = info->cpu_clk; |
444 | 493 | ||
@@ -446,13 +495,6 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy) | |||
446 | 495 | ||
447 | out_free_cpufreq_table: | 496 | out_free_cpufreq_table: |
448 | dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table); | 497 | dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table); |
449 | |||
450 | out_release_dvfs_info: | ||
451 | mtk_cpu_dvfs_info_release(info); | ||
452 | |||
453 | out_free_dvfs_info: | ||
454 | kfree(info); | ||
455 | |||
456 | return ret; | 498 | return ret; |
457 | } | 499 | } |
458 | 500 | ||
@@ -462,14 +504,13 @@ static int mtk_cpufreq_exit(struct cpufreq_policy *policy) | |||
462 | 504 | ||
463 | cpufreq_cooling_unregister(info->cdev); | 505 | cpufreq_cooling_unregister(info->cdev); |
464 | dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table); | 506 | dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table); |
465 | mtk_cpu_dvfs_info_release(info); | ||
466 | kfree(info); | ||
467 | 507 | ||
468 | return 0; | 508 | return 0; |
469 | } | 509 | } |
470 | 510 | ||
471 | static struct cpufreq_driver mt8173_cpufreq_driver = { | 511 | static struct cpufreq_driver mt8173_cpufreq_driver = { |
472 | .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | 512 | .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK | |
513 | CPUFREQ_HAVE_GOVERNOR_PER_POLICY, | ||
473 | .verify = cpufreq_generic_frequency_table_verify, | 514 | .verify = cpufreq_generic_frequency_table_verify, |
474 | .target_index = mtk_cpufreq_set_target, | 515 | .target_index = mtk_cpufreq_set_target, |
475 | .get = cpufreq_generic_get, | 516 | .get = cpufreq_generic_get, |
@@ -482,11 +523,47 @@ static struct cpufreq_driver mt8173_cpufreq_driver = { | |||
482 | 523 | ||
483 | static int mt8173_cpufreq_probe(struct platform_device *pdev) | 524 | static int mt8173_cpufreq_probe(struct platform_device *pdev) |
484 | { | 525 | { |
485 | int ret; | 526 | struct mtk_cpu_dvfs_info *info; |
527 | struct list_head *list, *tmp; | ||
528 | int cpu, ret; | ||
529 | |||
530 | for_each_possible_cpu(cpu) { | ||
531 | info = mtk_cpu_dvfs_info_lookup(cpu); | ||
532 | if (info) | ||
533 | continue; | ||
534 | |||
535 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | ||
536 | if (!info) { | ||
537 | ret = -ENOMEM; | ||
538 | goto release_dvfs_info_list; | ||
539 | } | ||
540 | |||
541 | ret = mtk_cpu_dvfs_info_init(info, cpu); | ||
542 | if (ret) { | ||
543 | dev_err(&pdev->dev, | ||
544 | "failed to initialize dvfs info for cpu%d\n", | ||
545 | cpu); | ||
546 | goto release_dvfs_info_list; | ||
547 | } | ||
548 | |||
549 | list_add(&info->list_head, &dvfs_info_list); | ||
550 | } | ||
486 | 551 | ||
487 | ret = cpufreq_register_driver(&mt8173_cpufreq_driver); | 552 | ret = cpufreq_register_driver(&mt8173_cpufreq_driver); |
488 | if (ret) | 553 | if (ret) { |
489 | pr_err("failed to register mtk cpufreq driver\n"); | 554 | dev_err(&pdev->dev, "failed to register mtk cpufreq driver\n"); |
555 | goto release_dvfs_info_list; | ||
556 | } | ||
557 | |||
558 | return 0; | ||
559 | |||
560 | release_dvfs_info_list: | ||
561 | list_for_each_safe(list, tmp, &dvfs_info_list) { | ||
562 | info = list_entry(list, struct mtk_cpu_dvfs_info, list_head); | ||
563 | |||
564 | mtk_cpu_dvfs_info_release(info); | ||
565 | list_del(list); | ||
566 | } | ||
490 | 567 | ||
491 | return ret; | 568 | return ret; |
492 | } | 569 | } |
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 2a0d58959acf..808a320e9d5d 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c | |||
@@ -555,6 +555,8 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
555 | policy->min = policy->cpuinfo.min_freq = | 555 | policy->min = policy->cpuinfo.min_freq = |
556 | ioread32(&pcch_hdr->minimum_frequency) * 1000; | 556 | ioread32(&pcch_hdr->minimum_frequency) * 1000; |
557 | 557 | ||
558 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | ||
559 | |||
558 | pr_debug("init: policy->max is %d, policy->min is %d\n", | 560 | pr_debug("init: policy->max is %d, policy->min is %d\n", |
559 | policy->max, policy->min); | 561 | policy->max, policy->min); |
560 | out: | 562 | out: |
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 358f0752c31e..b23e525a7af3 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
14 | #include <linux/cpufreq.h> | 14 | #include <linux/cpufreq.h> |
15 | #include <linux/cpu_cooling.h> | ||
15 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
@@ -33,6 +34,7 @@ | |||
33 | struct cpu_data { | 34 | struct cpu_data { |
34 | struct clk **pclk; | 35 | struct clk **pclk; |
35 | struct cpufreq_frequency_table *table; | 36 | struct cpufreq_frequency_table *table; |
37 | struct thermal_cooling_device *cdev; | ||
36 | }; | 38 | }; |
37 | 39 | ||
38 | /** | 40 | /** |
@@ -321,6 +323,27 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy, | |||
321 | return clk_set_parent(policy->clk, parent); | 323 | return clk_set_parent(policy->clk, parent); |
322 | } | 324 | } |
323 | 325 | ||
326 | |||
327 | static void qoriq_cpufreq_ready(struct cpufreq_policy *policy) | ||
328 | { | ||
329 | struct cpu_data *cpud = policy->driver_data; | ||
330 | struct device_node *np = of_get_cpu_node(policy->cpu, NULL); | ||
331 | |||
332 | if (of_find_property(np, "#cooling-cells", NULL)) { | ||
333 | cpud->cdev = of_cpufreq_cooling_register(np, | ||
334 | policy->related_cpus); | ||
335 | |||
336 | if (IS_ERR(cpud->cdev)) { | ||
337 | pr_err("Failed to register cooling device cpu%d: %ld\n", | ||
338 | policy->cpu, PTR_ERR(cpud->cdev)); | ||
339 | |||
340 | cpud->cdev = NULL; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | of_node_put(np); | ||
345 | } | ||
346 | |||
324 | static struct cpufreq_driver qoriq_cpufreq_driver = { | 347 | static struct cpufreq_driver qoriq_cpufreq_driver = { |
325 | .name = "qoriq_cpufreq", | 348 | .name = "qoriq_cpufreq", |
326 | .flags = CPUFREQ_CONST_LOOPS, | 349 | .flags = CPUFREQ_CONST_LOOPS, |
@@ -329,6 +352,7 @@ static struct cpufreq_driver qoriq_cpufreq_driver = { | |||
329 | .verify = cpufreq_generic_frequency_table_verify, | 352 | .verify = cpufreq_generic_frequency_table_verify, |
330 | .target_index = qoriq_cpufreq_target, | 353 | .target_index = qoriq_cpufreq_target, |
331 | .get = cpufreq_generic_get, | 354 | .get = cpufreq_generic_get, |
355 | .ready = qoriq_cpufreq_ready, | ||
332 | .attr = cpufreq_generic_attr, | 356 | .attr = cpufreq_generic_attr, |
333 | }; | 357 | }; |
334 | 358 | ||
diff --git a/drivers/cpufreq/sti-cpufreq.c b/drivers/cpufreq/sti-cpufreq.c new file mode 100644 index 000000000000..a9c659f58974 --- /dev/null +++ b/drivers/cpufreq/sti-cpufreq.c | |||
@@ -0,0 +1,294 @@ | |||
1 | /* | ||
2 | * Match running platform with pre-defined OPP values for CPUFreq | ||
3 | * | ||
4 | * Author: Ajit Pal Singh <ajitpal.singh@st.com> | ||
5 | * Lee Jones <lee.jones@linaro.org> | ||
6 | * | ||
7 | * Copyright (C) 2015 STMicroelectronics (R&D) Limited | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation | ||
12 | */ | ||
13 | |||
14 | #include <linux/cpu.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/mfd/syscon.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/pm_opp.h> | ||
21 | #include <linux/regmap.h> | ||
22 | |||
23 | #define VERSION_ELEMENTS 3 | ||
24 | #define MAX_PCODE_NAME_LEN 7 | ||
25 | |||
26 | #define VERSION_SHIFT 28 | ||
27 | #define HW_INFO_INDEX 1 | ||
28 | #define MAJOR_ID_INDEX 1 | ||
29 | #define MINOR_ID_INDEX 2 | ||
30 | |||
31 | /* | ||
32 | * Only match on "suitable for ALL versions" entries | ||
33 | * | ||
34 | * This will be used with the BIT() macro. It sets the | ||
35 | * top bit of a 32bit value and is equal to 0x80000000. | ||
36 | */ | ||
37 | #define DEFAULT_VERSION 31 | ||
38 | |||
39 | enum { | ||
40 | PCODE = 0, | ||
41 | SUBSTRATE, | ||
42 | DVFS_MAX_REGFIELDS, | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * ST CPUFreq Driver Data | ||
47 | * | ||
48 | * @cpu_node CPU's OF node | ||
49 | * @syscfg_eng Engineering Syscon register map | ||
50 | * @regmap Syscon register map | ||
51 | */ | ||
52 | static struct sti_cpufreq_ddata { | ||
53 | struct device *cpu; | ||
54 | struct regmap *syscfg_eng; | ||
55 | struct regmap *syscfg; | ||
56 | } ddata; | ||
57 | |||
58 | static int sti_cpufreq_fetch_major(void) { | ||
59 | struct device_node *np = ddata.cpu->of_node; | ||
60 | struct device *dev = ddata.cpu; | ||
61 | unsigned int major_offset; | ||
62 | unsigned int socid; | ||
63 | int ret; | ||
64 | |||
65 | ret = of_property_read_u32_index(np, "st,syscfg", | ||
66 | MAJOR_ID_INDEX, &major_offset); | ||
67 | if (ret) { | ||
68 | dev_err(dev, "No major number offset provided in %s [%d]\n", | ||
69 | np->full_name, ret); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | ret = regmap_read(ddata.syscfg, major_offset, &socid); | ||
74 | if (ret) { | ||
75 | dev_err(dev, "Failed to read major number from syscon [%d]\n", | ||
76 | ret); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | return ((socid >> VERSION_SHIFT) & 0xf) + 1; | ||
81 | } | ||
82 | |||
83 | static int sti_cpufreq_fetch_minor(void) | ||
84 | { | ||
85 | struct device *dev = ddata.cpu; | ||
86 | struct device_node *np = dev->of_node; | ||
87 | unsigned int minor_offset; | ||
88 | unsigned int minid; | ||
89 | int ret; | ||
90 | |||
91 | ret = of_property_read_u32_index(np, "st,syscfg-eng", | ||
92 | MINOR_ID_INDEX, &minor_offset); | ||
93 | if (ret) { | ||
94 | dev_err(dev, | ||
95 | "No minor number offset provided %s [%d]\n", | ||
96 | np->full_name, ret); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | ret = regmap_read(ddata.syscfg_eng, minor_offset, &minid); | ||
101 | if (ret) { | ||
102 | dev_err(dev, | ||
103 | "Failed to read the minor number from syscon [%d]\n", | ||
104 | ret); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | return minid & 0xf; | ||
109 | } | ||
110 | |||
111 | static int sti_cpufreq_fetch_regmap_field(const struct reg_field *reg_fields, | ||
112 | int hw_info_offset, int field) | ||
113 | { | ||
114 | struct regmap_field *regmap_field; | ||
115 | struct reg_field reg_field = reg_fields[field]; | ||
116 | struct device *dev = ddata.cpu; | ||
117 | unsigned int value; | ||
118 | int ret; | ||
119 | |||
120 | reg_field.reg = hw_info_offset; | ||
121 | regmap_field = devm_regmap_field_alloc(dev, | ||
122 | ddata.syscfg_eng, | ||
123 | reg_field); | ||
124 | if (IS_ERR(regmap_field)) { | ||
125 | dev_err(dev, "Failed to allocate reg field\n"); | ||
126 | return PTR_ERR(regmap_field); | ||
127 | } | ||
128 | |||
129 | ret = regmap_field_read(regmap_field, &value); | ||
130 | if (ret) { | ||
131 | dev_err(dev, "Failed to read %s code\n", | ||
132 | field ? "SUBSTRATE" : "PCODE"); | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | return value; | ||
137 | } | ||
138 | |||
139 | static const struct reg_field sti_stih407_dvfs_regfields[DVFS_MAX_REGFIELDS] = { | ||
140 | [PCODE] = REG_FIELD(0, 16, 19), | ||
141 | [SUBSTRATE] = REG_FIELD(0, 0, 2), | ||
142 | }; | ||
143 | |||
144 | static const struct reg_field *sti_cpufreq_match(void) | ||
145 | { | ||
146 | if (of_machine_is_compatible("st,stih407") || | ||
147 | of_machine_is_compatible("st,stih410")) | ||
148 | return sti_stih407_dvfs_regfields; | ||
149 | |||
150 | return NULL; | ||
151 | } | ||
152 | |||
153 | static int sti_cpufreq_set_opp_info(void) | ||
154 | { | ||
155 | struct device *dev = ddata.cpu; | ||
156 | struct device_node *np = dev->of_node; | ||
157 | const struct reg_field *reg_fields; | ||
158 | unsigned int hw_info_offset; | ||
159 | unsigned int version[VERSION_ELEMENTS]; | ||
160 | int pcode, substrate, major, minor; | ||
161 | int ret; | ||
162 | char name[MAX_PCODE_NAME_LEN]; | ||
163 | |||
164 | reg_fields = sti_cpufreq_match(); | ||
165 | if (!reg_fields) { | ||
166 | dev_err(dev, "This SoC doesn't support voltage scaling"); | ||
167 | return -ENODEV; | ||
168 | } | ||
169 | |||
170 | ret = of_property_read_u32_index(np, "st,syscfg-eng", | ||
171 | HW_INFO_INDEX, &hw_info_offset); | ||
172 | if (ret) { | ||
173 | dev_warn(dev, "Failed to read HW info offset from DT\n"); | ||
174 | substrate = DEFAULT_VERSION; | ||
175 | pcode = 0; | ||
176 | goto use_defaults; | ||
177 | } | ||
178 | |||
179 | pcode = sti_cpufreq_fetch_regmap_field(reg_fields, | ||
180 | hw_info_offset, | ||
181 | PCODE); | ||
182 | if (pcode < 0) { | ||
183 | dev_warn(dev, "Failed to obtain process code\n"); | ||
184 | /* Use default pcode */ | ||
185 | pcode = 0; | ||
186 | } | ||
187 | |||
188 | substrate = sti_cpufreq_fetch_regmap_field(reg_fields, | ||
189 | hw_info_offset, | ||
190 | SUBSTRATE); | ||
191 | if (substrate) { | ||
192 | dev_warn(dev, "Failed to obtain substrate code\n"); | ||
193 | /* Use default substrate */ | ||
194 | substrate = DEFAULT_VERSION; | ||
195 | } | ||
196 | |||
197 | use_defaults: | ||
198 | major = sti_cpufreq_fetch_major(); | ||
199 | if (major < 0) { | ||
200 | dev_err(dev, "Failed to obtain major version\n"); | ||
201 | /* Use default major number */ | ||
202 | major = DEFAULT_VERSION; | ||
203 | } | ||
204 | |||
205 | minor = sti_cpufreq_fetch_minor(); | ||
206 | if (minor < 0) { | ||
207 | dev_err(dev, "Failed to obtain minor version\n"); | ||
208 | /* Use default minor number */ | ||
209 | minor = DEFAULT_VERSION; | ||
210 | } | ||
211 | |||
212 | snprintf(name, MAX_PCODE_NAME_LEN, "pcode%d", pcode); | ||
213 | |||
214 | ret = dev_pm_opp_set_prop_name(dev, name); | ||
215 | if (ret) { | ||
216 | dev_err(dev, "Failed to set prop name\n"); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | version[0] = BIT(major); | ||
221 | version[1] = BIT(minor); | ||
222 | version[2] = BIT(substrate); | ||
223 | |||
224 | ret = dev_pm_opp_set_supported_hw(dev, version, VERSION_ELEMENTS); | ||
225 | if (ret) { | ||
226 | dev_err(dev, "Failed to set supported hardware\n"); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | dev_dbg(dev, "pcode: %d major: %d minor: %d substrate: %d\n", | ||
231 | pcode, major, minor, substrate); | ||
232 | dev_dbg(dev, "version[0]: %x version[1]: %x version[2]: %x\n", | ||
233 | version[0], version[1], version[2]); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int sti_cpufreq_fetch_syscon_regsiters(void) | ||
239 | { | ||
240 | struct device *dev = ddata.cpu; | ||
241 | struct device_node *np = dev->of_node; | ||
242 | |||
243 | ddata.syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | ||
244 | if (IS_ERR(ddata.syscfg)) { | ||
245 | dev_err(dev, "\"st,syscfg\" not supplied\n"); | ||
246 | return PTR_ERR(ddata.syscfg); | ||
247 | } | ||
248 | |||
249 | ddata.syscfg_eng = syscon_regmap_lookup_by_phandle(np, "st,syscfg-eng"); | ||
250 | if (IS_ERR(ddata.syscfg_eng)) { | ||
251 | dev_err(dev, "\"st,syscfg-eng\" not supplied\n"); | ||
252 | return PTR_ERR(ddata.syscfg_eng); | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int sti_cpufreq_init(void) | ||
259 | { | ||
260 | int ret; | ||
261 | |||
262 | ddata.cpu = get_cpu_device(0); | ||
263 | if (!ddata.cpu) { | ||
264 | dev_err(ddata.cpu, "Failed to get device for CPU0\n"); | ||
265 | goto skip_voltage_scaling; | ||
266 | } | ||
267 | |||
268 | if (!of_get_property(ddata.cpu->of_node, "operating-points-v2", NULL)) { | ||
269 | dev_err(ddata.cpu, "OPP-v2 not supported\n"); | ||
270 | goto skip_voltage_scaling; | ||
271 | } | ||
272 | |||
273 | ret = sti_cpufreq_fetch_syscon_regsiters(); | ||
274 | if (ret) | ||
275 | goto skip_voltage_scaling; | ||
276 | |||
277 | ret = sti_cpufreq_set_opp_info(); | ||
278 | if (!ret) | ||
279 | goto register_cpufreq_dt; | ||
280 | |||
281 | skip_voltage_scaling: | ||
282 | dev_err(ddata.cpu, "Not doing voltage scaling\n"); | ||
283 | |||
284 | register_cpufreq_dt: | ||
285 | platform_device_register_simple("cpufreq-dt", -1, NULL, 0); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | module_init(sti_cpufreq_init); | ||
290 | |||
291 | MODULE_DESCRIPTION("STMicroelectronics CPUFreq/OPP driver"); | ||
292 | MODULE_AUTHOR("Ajitpal Singh <ajitpal.singh@st.com>"); | ||
293 | MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); | ||
294 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 177c7680c1a8..88a4215125bc 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -278,7 +278,6 @@ struct cpufreq_driver { | |||
278 | struct freq_attr **attr; | 278 | struct freq_attr **attr; |
279 | 279 | ||
280 | /* platform specific boost support code */ | 280 | /* platform specific boost support code */ |
281 | bool boost_supported; | ||
282 | bool boost_enabled; | 281 | bool boost_enabled; |
283 | int (*set_boost)(int state); | 282 | int (*set_boost)(int state); |
284 | }; | 283 | }; |
@@ -574,7 +573,6 @@ ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); | |||
574 | 573 | ||
575 | #ifdef CONFIG_CPU_FREQ | 574 | #ifdef CONFIG_CPU_FREQ |
576 | int cpufreq_boost_trigger_state(int state); | 575 | int cpufreq_boost_trigger_state(int state); |
577 | int cpufreq_boost_supported(void); | ||
578 | int cpufreq_boost_enabled(void); | 576 | int cpufreq_boost_enabled(void); |
579 | int cpufreq_enable_boost_support(void); | 577 | int cpufreq_enable_boost_support(void); |
580 | bool policy_has_boost_freq(struct cpufreq_policy *policy); | 578 | bool policy_has_boost_freq(struct cpufreq_policy *policy); |
@@ -583,10 +581,6 @@ static inline int cpufreq_boost_trigger_state(int state) | |||
583 | { | 581 | { |
584 | return 0; | 582 | return 0; |
585 | } | 583 | } |
586 | static inline int cpufreq_boost_supported(void) | ||
587 | { | ||
588 | return 0; | ||
589 | } | ||
590 | static inline int cpufreq_boost_enabled(void) | 584 | static inline int cpufreq_boost_enabled(void) |
591 | { | 585 | { |
592 | return 0; | 586 | return 0; |