aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-05-04 16:50:47 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-05-04 16:50:47 -0400
commit512eae392abe7b5be3c1fe69b3d8cf54bb0ff3f2 (patch)
tree76210fbe08a14c31dc824cc224747b7b3b7e1339
parent04974df8049fc4240d22759a91e035082ccd18b4 (diff)
parent83cb0e4d837af4348cc218638e9d6daddd21d260 (diff)
Merge tag 'PR_4.7_20160503' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq into pm-devfreq
Pull devfreq material for v4.7 from MyungJoo Ham. "Updates: - Passive governor: for SoC subsystems that may either have an independent voltage rail or have a parent subsystem or collegue subsystem sharing a voltage rail, when there is a parent of a collegue that is going to be the owner of the voltage rail, the dependent subsystem may use the passive governor. - Consolidated exynos bus/mem-if driver: now we have a single driver that supports (almost) all Exynos SoC's bus/mem-if subsystems. - New devfreq drivers included: Exynos NoC probe" * tag 'PR_4.7_20160503' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq: PM / devfreq: style/typo fixes PM / devfreq: exynos: Add the detailed correlation for Exynos5422 bus PM / devfreq: event: Find the instance of devfreq-event device by using phandle PM / devfreq: event: Add new Exynos NoC probe driver MAINTAINERS: Add samsung bus frequency driver entry PM / devfreq: exynos: Remove unused exynos4/5 busfreq driver PM / devfreq: exynos: Add the detailed correlation between sub-blocks and power line PM / devfreq: exynos: Update documentation for bus devices using passive governor PM / devfreq: exynos: Add support of bus frequency of sub-blocks using passive governor PM / devfreq: Add new passive governor PM / devfreq: Add new DEVFREQ_TRANSITION_NOTIFIER notifier PM / devfreq: Add devfreq_get_devfreq_by_phandle() PM / devfreq: exynos: Add documentation for generic exynos bus frequency driver PM / devfreq: exynos: Add generic exynos bus frequency driver
-rw-r--r--Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt26
-rw-r--r--Documentation/devicetree/bindings/devfreq/exynos-bus.txt409
-rw-r--r--MAINTAINERS9
-rw-r--r--drivers/devfreq/Kconfig36
-rw-r--r--drivers/devfreq/Makefile4
-rw-r--r--drivers/devfreq/devfreq-event.c5
-rw-r--r--drivers/devfreq/devfreq.c207
-rw-r--r--drivers/devfreq/event/Kconfig8
-rw-r--r--drivers/devfreq/event/Makefile2
-rw-r--r--drivers/devfreq/event/exynos-nocp.c304
-rw-r--r--drivers/devfreq/event/exynos-nocp.h78
-rw-r--r--drivers/devfreq/exynos-bus.c570
-rw-r--r--drivers/devfreq/exynos/Makefile3
-rw-r--r--drivers/devfreq/exynos/exynos4_bus.c1055
-rw-r--r--drivers/devfreq/exynos/exynos4_bus.h110
-rw-r--r--drivers/devfreq/exynos/exynos5_bus.c431
-rw-r--r--drivers/devfreq/exynos/exynos_ppmu.c119
-rw-r--r--drivers/devfreq/exynos/exynos_ppmu.h86
-rw-r--r--drivers/devfreq/governor_passive.c205
-rw-r--r--include/linux/devfreq.h99
20 files changed, 1942 insertions, 1824 deletions
diff --git a/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt b/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt
new file mode 100644
index 000000000000..fd459f00aa5a
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt
@@ -0,0 +1,26 @@
1
2* Samsung Exynos NoC (Network on Chip) Probe device
3
4The Samsung Exynos542x SoC has NoC (Network on Chip) Probe for NoC bus.
5NoC provides the primitive values to get the performance data. The packets
6that the Network on Chip (NoC) probes detects are transported over
7the network infrastructure to observer units. You can configure probes to
8capture packets with header or data on the data request response network,
9or as traffic debug or statistic collectors. Exynos542x bus has multiple
10NoC probes to provide bandwidth information about behavior of the SoC
11that you can use while analyzing system performance.
12
13Required properties:
14- compatible: Should be "samsung,exynos5420-nocp"
15- reg: physical base address of each NoC Probe and length of memory mapped region.
16
17Optional properties:
18- clock-names : the name of clock used by the NoC Probe, "nocp"
19- clocks : phandles for clock specified in "clock-names" property
20
21Example : NoC Probe nodes in Device Tree are listed below.
22
23 nocp_mem0_0: nocp@10CA1000 {
24 compatible = "samsung,exynos5420-nocp";
25 reg = <0x10CA1000 0x200>;
26 };
diff --git a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
new file mode 100644
index 000000000000..d3ec8e676b6b
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
@@ -0,0 +1,409 @@
1* Generic Exynos Bus frequency device
2
3The Samsung Exynos SoC has many buses for data transfer between DRAM
4and sub-blocks in SoC. Most Exynos SoCs share the common architecture
5for buses. Generally, each bus of Exynos SoC includes a source clock
6and a power line, which are able to change the clock frequency
7of the bus in runtime. To monitor the usage of each bus in runtime,
8the driver uses the PPMU (Platform Performance Monitoring Unit), which
9is able to measure the current load of sub-blocks.
10
11The Exynos SoC includes the various sub-blocks which have the each AXI bus.
12The each AXI bus has the owned source clock but, has not the only owned
13power line. The power line might be shared among one more sub-blocks.
14So, we can divide into two type of device as the role of each sub-block.
15There are two type of bus devices as following:
16- parent bus device
17- passive bus device
18
19Basically, parent and passive bus device share the same power line.
20The parent bus device can only change the voltage of shared power line
21and the rest bus devices (passive bus device) depend on the decision of
22the parent bus device. If there are three blocks which share the VDD_xxx
23power line, Only one block should be parent device and then the rest blocks
24should depend on the parent device as passive device.
25
26 VDD_xxx |--- A block (parent)
27 |--- B block (passive)
28 |--- C block (passive)
29
30There are a little different composition among Exynos SoC because each Exynos
31SoC has different sub-blocks. Therefore, such difference should be specified
32in devicetree file instead of each device driver. In result, this driver
33is able to support the bus frequency for all Exynos SoCs.
34
35Required properties for all bus devices:
36- compatible: Should be "samsung,exynos-bus".
37- clock-names : the name of clock used by the bus, "bus".
38- clocks : phandles for clock specified in "clock-names" property.
39- operating-points-v2: the OPP table including frequency/voltage information
40 to support DVFS (Dynamic Voltage/Frequency Scaling) feature.
41
42Required properties only for parent bus device:
43- vdd-supply: the regulator to provide the buses with the voltage.
44- devfreq-events: the devfreq-event device to monitor the current utilization
45 of buses.
46
47Required properties only for passive bus device:
48- devfreq: the parent bus device.
49
50Optional properties only for parent bus device:
51- exynos,saturation-ratio: the percentage value which is used to calibrate
52 the performance count against total cycle count.
53- exynos,voltage-tolerance: the percentage value for bus voltage tolerance
54 which is used to calculate the max voltage.
55
56Detailed correlation between sub-blocks and power line according to Exynos SoC:
57- In case of Exynos3250, there are two power line as following:
58 VDD_MIF |--- DMC
59
60 VDD_INT |--- LEFTBUS (parent device)
61 |--- PERIL
62 |--- MFC
63 |--- G3D
64 |--- RIGHTBUS
65 |--- PERIR
66 |--- FSYS
67 |--- LCD0
68 |--- PERIR
69 |--- ISP
70 |--- CAM
71
72- In case of Exynos4210, there is one power line as following:
73 VDD_INT |--- DMC (parent device)
74 |--- LEFTBUS
75 |--- PERIL
76 |--- MFC(L)
77 |--- G3D
78 |--- TV
79 |--- LCD0
80 |--- RIGHTBUS
81 |--- PERIR
82 |--- MFC(R)
83 |--- CAM
84 |--- FSYS
85 |--- GPS
86 |--- LCD0
87 |--- LCD1
88
89- In case of Exynos4x12, there are two power line as following:
90 VDD_MIF |--- DMC
91
92 VDD_INT |--- LEFTBUS (parent device)
93 |--- PERIL
94 |--- MFC(L)
95 |--- G3D
96 |--- TV
97 |--- IMAGE
98 |--- RIGHTBUS
99 |--- PERIR
100 |--- MFC(R)
101 |--- CAM
102 |--- FSYS
103 |--- GPS
104 |--- LCD0
105 |--- ISP
106
107- In case of Exynos5422, there are two power line as following:
108 VDD_MIF |--- DREX 0 (parent device, DRAM EXpress controller)
109 |--- DREX 1
110
111 VDD_INT |--- NoC_Core (parent device)
112 |--- G2D
113 |--- G3D
114 |--- DISP1
115 |--- NoC_WCORE
116 |--- GSCL
117 |--- MSCL
118 |--- ISP
119 |--- MFC
120 |--- GEN
121 |--- PERIS
122 |--- PERIC
123 |--- FSYS
124 |--- FSYS2
125
126Example1:
127 Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to
128 power line (regulator). The MIF (Memory Interface) AXI bus is used to
129 transfer data between DRAM and CPU and uses the VDD_MIF regulator.
130
131 - MIF (Memory Interface) block
132 : VDD_MIF |--- DMC (Dynamic Memory Controller)
133
134 - INT (Internal) block
135 : VDD_INT |--- LEFTBUS (parent device)
136 |--- PERIL
137 |--- MFC
138 |--- G3D
139 |--- RIGHTBUS
140 |--- FSYS
141 |--- LCD0
142 |--- PERIR
143 |--- ISP
144 |--- CAM
145
146 - MIF bus's frequency/voltage table
147 -----------------------
148 |Lv| Freq | Voltage |
149 -----------------------
150 |L1| 50000 |800000 |
151 |L2| 100000 |800000 |
152 |L3| 134000 |800000 |
153 |L4| 200000 |825000 |
154 |L5| 400000 |875000 |
155 -----------------------
156
157 - INT bus's frequency/voltage table
158 ----------------------------------------------------------
159 |Block|LEFTBUS|RIGHTBUS|MCUISP |ISP |PERIL ||VDD_INT |
160 | name| |LCD0 | | | || |
161 | | |FSYS | | | || |
162 | | |MFC | | | || |
163 ----------------------------------------------------------
164 |Mode |*parent|passive |passive|passive|passive|| |
165 ----------------------------------------------------------
166 |Lv |Frequency ||Voltage |
167 ----------------------------------------------------------
168 |L1 |50000 |50000 |50000 |50000 |50000 ||900000 |
169 |L2 |80000 |80000 |80000 |80000 |80000 ||900000 |
170 |L3 |100000 |100000 |100000 |100000 |100000 ||1000000 |
171 |L4 |134000 |134000 |200000 |200000 | ||1000000 |
172 |L5 |200000 |200000 |400000 |300000 | ||1000000 |
173 ----------------------------------------------------------
174
175Example2 :
176 The bus of DMC (Dynamic Memory Controller) block in exynos3250.dtsi
177 is listed below:
178
179 bus_dmc: bus_dmc {
180 compatible = "samsung,exynos-bus";
181 clocks = <&cmu_dmc CLK_DIV_DMC>;
182 clock-names = "bus";
183 operating-points-v2 = <&bus_dmc_opp_table>;
184 status = "disabled";
185 };
186
187 bus_dmc_opp_table: opp_table1 {
188 compatible = "operating-points-v2";
189 opp-shared;
190
191 opp@50000000 {
192 opp-hz = /bits/ 64 <50000000>;
193 opp-microvolt = <800000>;
194 };
195 opp@100000000 {
196 opp-hz = /bits/ 64 <100000000>;
197 opp-microvolt = <800000>;
198 };
199 opp@134000000 {
200 opp-hz = /bits/ 64 <134000000>;
201 opp-microvolt = <800000>;
202 };
203 opp@200000000 {
204 opp-hz = /bits/ 64 <200000000>;
205 opp-microvolt = <825000>;
206 };
207 opp@400000000 {
208 opp-hz = /bits/ 64 <400000000>;
209 opp-microvolt = <875000>;
210 };
211 };
212
213 bus_leftbus: bus_leftbus {
214 compatible = "samsung,exynos-bus";
215 clocks = <&cmu CLK_DIV_GDL>;
216 clock-names = "bus";
217 operating-points-v2 = <&bus_leftbus_opp_table>;
218 status = "disabled";
219 };
220
221 bus_rightbus: bus_rightbus {
222 compatible = "samsung,exynos-bus";
223 clocks = <&cmu CLK_DIV_GDR>;
224 clock-names = "bus";
225 operating-points-v2 = <&bus_leftbus_opp_table>;
226 status = "disabled";
227 };
228
229 bus_lcd0: bus_lcd0 {
230 compatible = "samsung,exynos-bus";
231 clocks = <&cmu CLK_DIV_ACLK_160>;
232 clock-names = "bus";
233 operating-points-v2 = <&bus_leftbus_opp_table>;
234 status = "disabled";
235 };
236
237 bus_fsys: bus_fsys {
238 compatible = "samsung,exynos-bus";
239 clocks = <&cmu CLK_DIV_ACLK_200>;
240 clock-names = "bus";
241 operating-points-v2 = <&bus_leftbus_opp_table>;
242 status = "disabled";
243 };
244
245 bus_mcuisp: bus_mcuisp {
246 compatible = "samsung,exynos-bus";
247 clocks = <&cmu CLK_DIV_ACLK_400_MCUISP>;
248 clock-names = "bus";
249 operating-points-v2 = <&bus_mcuisp_opp_table>;
250 status = "disabled";
251 };
252
253 bus_isp: bus_isp {
254 compatible = "samsung,exynos-bus";
255 clocks = <&cmu CLK_DIV_ACLK_266>;
256 clock-names = "bus";
257 operating-points-v2 = <&bus_isp_opp_table>;
258 status = "disabled";
259 };
260
261 bus_peril: bus_peril {
262 compatible = "samsung,exynos-bus";
263 clocks = <&cmu CLK_DIV_ACLK_100>;
264 clock-names = "bus";
265 operating-points-v2 = <&bus_peril_opp_table>;
266 status = "disabled";
267 };
268
269 bus_mfc: bus_mfc {
270 compatible = "samsung,exynos-bus";
271 clocks = <&cmu CLK_SCLK_MFC>;
272 clock-names = "bus";
273 operating-points-v2 = <&bus_leftbus_opp_table>;
274 status = "disabled";
275 };
276
277 bus_leftbus_opp_table: opp_table1 {
278 compatible = "operating-points-v2";
279 opp-shared;
280
281 opp@50000000 {
282 opp-hz = /bits/ 64 <50000000>;
283 opp-microvolt = <900000>;
284 };
285 opp@80000000 {
286 opp-hz = /bits/ 64 <80000000>;
287 opp-microvolt = <900000>;
288 };
289 opp@100000000 {
290 opp-hz = /bits/ 64 <100000000>;
291 opp-microvolt = <1000000>;
292 };
293 opp@134000000 {
294 opp-hz = /bits/ 64 <134000000>;
295 opp-microvolt = <1000000>;
296 };
297 opp@200000000 {
298 opp-hz = /bits/ 64 <200000000>;
299 opp-microvolt = <1000000>;
300 };
301 };
302
303 bus_mcuisp_opp_table: opp_table2 {
304 compatible = "operating-points-v2";
305 opp-shared;
306
307 opp@50000000 {
308 opp-hz = /bits/ 64 <50000000>;
309 };
310 opp@80000000 {
311 opp-hz = /bits/ 64 <80000000>;
312 };
313 opp@100000000 {
314 opp-hz = /bits/ 64 <100000000>;
315 };
316 opp@200000000 {
317 opp-hz = /bits/ 64 <200000000>;
318 };
319 opp@400000000 {
320 opp-hz = /bits/ 64 <400000000>;
321 };
322 };
323
324 bus_isp_opp_table: opp_table3 {
325 compatible = "operating-points-v2";
326 opp-shared;
327
328 opp@50000000 {
329 opp-hz = /bits/ 64 <50000000>;
330 };
331 opp@80000000 {
332 opp-hz = /bits/ 64 <80000000>;
333 };
334 opp@100000000 {
335 opp-hz = /bits/ 64 <100000000>;
336 };
337 opp@200000000 {
338 opp-hz = /bits/ 64 <200000000>;
339 };
340 opp@300000000 {
341 opp-hz = /bits/ 64 <300000000>;
342 };
343 };
344
345 bus_peril_opp_table: opp_table4 {
346 compatible = "operating-points-v2";
347 opp-shared;
348
349 opp@50000000 {
350 opp-hz = /bits/ 64 <50000000>;
351 };
352 opp@80000000 {
353 opp-hz = /bits/ 64 <80000000>;
354 };
355 opp@100000000 {
356 opp-hz = /bits/ 64 <100000000>;
357 };
358 };
359
360
361 Usage case to handle the frequency and voltage of bus on runtime
362 in exynos3250-rinato.dts is listed below:
363
364 &bus_dmc {
365 devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
366 vdd-supply = <&buck1_reg>; /* VDD_MIF */
367 status = "okay";
368 };
369
370 &bus_leftbus {
371 devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
372 vdd-supply = <&buck3_reg>;
373 status = "okay";
374 };
375
376 &bus_rightbus {
377 devfreq = <&bus_leftbus>;
378 status = "okay";
379 };
380
381 &bus_lcd0 {
382 devfreq = <&bus_leftbus>;
383 status = "okay";
384 };
385
386 &bus_fsys {
387 devfreq = <&bus_leftbus>;
388 status = "okay";
389 };
390
391 &bus_mcuisp {
392 devfreq = <&bus_leftbus>;
393 status = "okay";
394 };
395
396 &bus_isp {
397 devfreq = <&bus_leftbus>;
398 status = "okay";
399 };
400
401 &bus_peril {
402 devfreq = <&bus_leftbus>;
403 status = "okay";
404 };
405
406 &bus_mfc {
407 devfreq = <&bus_leftbus>;
408 status = "okay";
409 };
diff --git a/MAINTAINERS b/MAINTAINERS
index 42e65d128d01..7e9da3aa9851 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3539,6 +3539,15 @@ F: drivers/devfreq/devfreq-event.c
3539F: include/linux/devfreq-event.h 3539F: include/linux/devfreq-event.h
3540F: Documentation/devicetree/bindings/devfreq/event/ 3540F: Documentation/devicetree/bindings/devfreq/event/
3541 3541
3542BUS FREQUENCY DRIVER FOR SAMSUNG EXYNOS
3543M: Chanwoo Choi <cw00.choi@samsung.com>
3544L: linux-pm@vger.kernel.org
3545L: linux-samsung-soc@vger.kernel.org
3546T: git git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git
3547S: Maintained
3548F: drivers/devfreq/exynos-bus.c
3549F: Documentation/devicetree/bindings/devfreq/exynos-bus.txt
3550
3542DEVICE NUMBER REGISTRY 3551DEVICE NUMBER REGISTRY
3543M: Torben Mathiasen <device@lanana.org> 3552M: Torben Mathiasen <device@lanana.org>
3544W: http://lanana.org/docs/device-list/index.html 3553W: http://lanana.org/docs/device-list/index.html
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 4de78c552251..78dac0e9da11 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -64,30 +64,32 @@ config DEVFREQ_GOV_USERSPACE
64 Otherwise, the governor does not change the frequency 64 Otherwise, the governor does not change the frequency
65 given at the initialization. 65 given at the initialization.
66 66
67config DEVFREQ_GOV_PASSIVE
68 tristate "Passive"
69 help
70 Sets the frequency based on the frequency of its parent devfreq
71 device. This governor does not change the frequency by itself
72 through sysfs entries. The passive governor recommends that
73 devfreq device uses the OPP table to get the frequency/voltage.
74
67comment "DEVFREQ Drivers" 75comment "DEVFREQ Drivers"
68 76
69config ARM_EXYNOS4_BUS_DEVFREQ 77config ARM_EXYNOS_BUS_DEVFREQ
70 bool "ARM Exynos4210/4212/4412 Memory Bus DEVFREQ Driver" 78 bool "ARM EXYNOS Generic Memory Bus DEVFREQ Driver"
71 depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM 79 depends on ARCH_EXYNOS
72 select DEVFREQ_GOV_SIMPLE_ONDEMAND 80 select DEVFREQ_GOV_SIMPLE_ONDEMAND
81 select DEVFREQ_GOV_PASSIVE
82 select DEVFREQ_EVENT_EXYNOS_PPMU
83 select PM_DEVFREQ_EVENT
73 select PM_OPP 84 select PM_OPP
74 help 85 help
75 This adds the DEVFREQ driver for Exynos4210 memory bus (vdd_int) 86 This adds the common DEVFREQ driver for Exynos Memory bus. Exynos
76 and Exynos4212/4412 memory interface and bus (vdd_mif + vdd_int). 87 Memory bus has one more group of memory bus (e.g, MIF and INT block).
77 It reads PPMU counters of memory controllers and adjusts 88 Each memory bus group could contain many memoby bus block. It reads
78 the operating frequencies and voltages with OPP support. 89 PPMU counters of memory controllers by using DEVFREQ-event device
90 and adjusts the operating frequencies and voltages with OPP support.
79 This does not yet operate with optimal voltages. 91 This does not yet operate with optimal voltages.
80 92
81config ARM_EXYNOS5_BUS_DEVFREQ
82 tristate "ARM Exynos5250 Bus DEVFREQ Driver"
83 depends on SOC_EXYNOS5250
84 select DEVFREQ_GOV_SIMPLE_ONDEMAND
85 select PM_OPP
86 help
87 This adds the DEVFREQ driver for Exynos5250 bus interface (vdd_int).
88 It reads PPMU counters of memory controllers and adjusts the
89 operating frequencies and voltages with OPP support.
90
91config ARM_TEGRA_DEVFREQ 93config ARM_TEGRA_DEVFREQ
92 tristate "Tegra DEVFREQ Driver" 94 tristate "Tegra DEVFREQ Driver"
93 depends on ARCH_TEGRA_124_SOC 95 depends on ARCH_TEGRA_124_SOC
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 5134f9ee983d..09f11d9d40d5 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -4,10 +4,10 @@ obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) += governor_simpleondemand.o
4obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE) += governor_performance.o 4obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE) += governor_performance.o
5obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o 5obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o
6obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o 6obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o
7obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o
7 8
8# DEVFREQ Drivers 9# DEVFREQ Drivers
9obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ) += exynos/ 10obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o
10obj-$(CONFIG_ARM_EXYNOS5_BUS_DEVFREQ) += exynos/
11obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o 11obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o
12 12
13# DEVFREQ Event Drivers 13# DEVFREQ Event Drivers
diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c
index 38bf144ca147..39b048eda2ce 100644
--- a/drivers/devfreq/devfreq-event.c
+++ b/drivers/devfreq/devfreq-event.c
@@ -235,6 +235,11 @@ struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(struct device *dev,
235 235
236 mutex_lock(&devfreq_event_list_lock); 236 mutex_lock(&devfreq_event_list_lock);
237 list_for_each_entry(edev, &devfreq_event_list, node) { 237 list_for_each_entry(edev, &devfreq_event_list, node) {
238 if (edev->dev.parent && edev->dev.parent->of_node == node)
239 goto out;
240 }
241
242 list_for_each_entry(edev, &devfreq_event_list, node) {
238 if (!strcmp(edev->desc->name, node->name)) 243 if (!strcmp(edev->desc->name, node->name))
239 goto out; 244 goto out;
240 } 245 }
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 984c5e9e7bdd..1d6c803804d5 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -25,6 +25,7 @@
25#include <linux/list.h> 25#include <linux/list.h>
26#include <linux/printk.h> 26#include <linux/printk.h>
27#include <linux/hrtimer.h> 27#include <linux/hrtimer.h>
28#include <linux/of.h>
28#include "governor.h" 29#include "governor.h"
29 30
30static struct class *devfreq_class; 31static struct class *devfreq_class;
@@ -188,6 +189,29 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
188 return ERR_PTR(-ENODEV); 189 return ERR_PTR(-ENODEV);
189} 190}
190 191
192static int devfreq_notify_transition(struct devfreq *devfreq,
193 struct devfreq_freqs *freqs, unsigned int state)
194{
195 if (!devfreq)
196 return -EINVAL;
197
198 switch (state) {
199 case DEVFREQ_PRECHANGE:
200 srcu_notifier_call_chain(&devfreq->transition_notifier_list,
201 DEVFREQ_PRECHANGE, freqs);
202 break;
203
204 case DEVFREQ_POSTCHANGE:
205 srcu_notifier_call_chain(&devfreq->transition_notifier_list,
206 DEVFREQ_POSTCHANGE, freqs);
207 break;
208 default:
209 return -EINVAL;
210 }
211
212 return 0;
213}
214
191/* Load monitoring helper functions for governors use */ 215/* Load monitoring helper functions for governors use */
192 216
193/** 217/**
@@ -199,7 +223,8 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
199 */ 223 */
200int update_devfreq(struct devfreq *devfreq) 224int update_devfreq(struct devfreq *devfreq)
201{ 225{
202 unsigned long freq; 226 struct devfreq_freqs freqs;
227 unsigned long freq, cur_freq;
203 int err = 0; 228 int err = 0;
204 u32 flags = 0; 229 u32 flags = 0;
205 230
@@ -233,10 +258,22 @@ int update_devfreq(struct devfreq *devfreq)
233 flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ 258 flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
234 } 259 }
235 260
261 if (devfreq->profile->get_cur_freq)
262 devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
263 else
264 cur_freq = devfreq->previous_freq;
265
266 freqs.old = cur_freq;
267 freqs.new = freq;
268 devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
269
236 err = devfreq->profile->target(devfreq->dev.parent, &freq, flags); 270 err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
237 if (err) 271 if (err)
238 return err; 272 return err;
239 273
274 freqs.new = freq;
275 devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
276
240 if (devfreq->profile->freq_table) 277 if (devfreq->profile->freq_table)
241 if (devfreq_update_status(devfreq, freq)) 278 if (devfreq_update_status(devfreq, freq))
242 dev_err(&devfreq->dev, 279 dev_err(&devfreq->dev,
@@ -541,6 +578,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
541 goto err_out; 578 goto err_out;
542 } 579 }
543 580
581 srcu_init_notifier_head(&devfreq->transition_notifier_list);
582
544 mutex_unlock(&devfreq->lock); 583 mutex_unlock(&devfreq->lock);
545 584
546 mutex_lock(&devfreq_list_lock); 585 mutex_lock(&devfreq_list_lock);
@@ -639,6 +678,49 @@ struct devfreq *devm_devfreq_add_device(struct device *dev,
639} 678}
640EXPORT_SYMBOL(devm_devfreq_add_device); 679EXPORT_SYMBOL(devm_devfreq_add_device);
641 680
681#ifdef CONFIG_OF
682/*
683 * devfreq_get_devfreq_by_phandle - Get the devfreq device from devicetree
684 * @dev - instance to the given device
685 * @index - index into list of devfreq
686 *
687 * return the instance of devfreq device
688 */
689struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
690{
691 struct device_node *node;
692 struct devfreq *devfreq;
693
694 if (!dev)
695 return ERR_PTR(-EINVAL);
696
697 if (!dev->of_node)
698 return ERR_PTR(-EINVAL);
699
700 node = of_parse_phandle(dev->of_node, "devfreq", index);
701 if (!node)
702 return ERR_PTR(-ENODEV);
703
704 mutex_lock(&devfreq_list_lock);
705 list_for_each_entry(devfreq, &devfreq_list, node) {
706 if (devfreq->dev.parent
707 && devfreq->dev.parent->of_node == node) {
708 mutex_unlock(&devfreq_list_lock);
709 return devfreq;
710 }
711 }
712 mutex_unlock(&devfreq_list_lock);
713
714 return ERR_PTR(-EPROBE_DEFER);
715}
716#else
717struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
718{
719 return ERR_PTR(-ENODEV);
720}
721#endif /* CONFIG_OF */
722EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_phandle);
723
642/** 724/**
643 * devm_devfreq_remove_device() - Resource-managed devfreq_remove_device() 725 * devm_devfreq_remove_device() - Resource-managed devfreq_remove_device()
644 * @dev: the device to add devfreq feature. 726 * @dev: the device to add devfreq feature.
@@ -1266,6 +1348,129 @@ void devm_devfreq_unregister_opp_notifier(struct device *dev,
1266} 1348}
1267EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier); 1349EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier);
1268 1350
1351/**
1352 * devfreq_register_notifier() - Register a driver with devfreq
1353 * @devfreq: The devfreq object.
1354 * @nb: The notifier block to register.
1355 * @list: DEVFREQ_TRANSITION_NOTIFIER.
1356 */
1357int devfreq_register_notifier(struct devfreq *devfreq,
1358 struct notifier_block *nb,
1359 unsigned int list)
1360{
1361 int ret = 0;
1362
1363 if (!devfreq)
1364 return -EINVAL;
1365
1366 switch (list) {
1367 case DEVFREQ_TRANSITION_NOTIFIER:
1368 ret = srcu_notifier_chain_register(
1369 &devfreq->transition_notifier_list, nb);
1370 break;
1371 default:
1372 ret = -EINVAL;
1373 }
1374
1375 return ret;
1376}
1377EXPORT_SYMBOL(devfreq_register_notifier);
1378
1379/*
1380 * devfreq_unregister_notifier() - Unregister a driver with devfreq
1381 * @devfreq: The devfreq object.
1382 * @nb: The notifier block to be unregistered.
1383 * @list: DEVFREQ_TRANSITION_NOTIFIER.
1384 */
1385int devfreq_unregister_notifier(struct devfreq *devfreq,
1386 struct notifier_block *nb,
1387 unsigned int list)
1388{
1389 int ret = 0;
1390
1391 if (!devfreq)
1392 return -EINVAL;
1393
1394 switch (list) {
1395 case DEVFREQ_TRANSITION_NOTIFIER:
1396 ret = srcu_notifier_chain_unregister(
1397 &devfreq->transition_notifier_list, nb);
1398 break;
1399 default:
1400 ret = -EINVAL;
1401 }
1402
1403 return ret;
1404}
1405EXPORT_SYMBOL(devfreq_unregister_notifier);
1406
1407struct devfreq_notifier_devres {
1408 struct devfreq *devfreq;
1409 struct notifier_block *nb;
1410 unsigned int list;
1411};
1412
1413static void devm_devfreq_notifier_release(struct device *dev, void *res)
1414{
1415 struct devfreq_notifier_devres *this = res;
1416
1417 devfreq_unregister_notifier(this->devfreq, this->nb, this->list);
1418}
1419
1420/**
1421 * devm_devfreq_register_notifier()
1422 - Resource-managed devfreq_register_notifier()
1423 * @dev: The devfreq user device. (parent of devfreq)
1424 * @devfreq: The devfreq object.
1425 * @nb: The notifier block to be unregistered.
1426 * @list: DEVFREQ_TRANSITION_NOTIFIER.
1427 */
1428int devm_devfreq_register_notifier(struct device *dev,
1429 struct devfreq *devfreq,
1430 struct notifier_block *nb,
1431 unsigned int list)
1432{
1433 struct devfreq_notifier_devres *ptr;
1434 int ret;
1435
1436 ptr = devres_alloc(devm_devfreq_notifier_release, sizeof(*ptr),
1437 GFP_KERNEL);
1438 if (!ptr)
1439 return -ENOMEM;
1440
1441 ret = devfreq_register_notifier(devfreq, nb, list);
1442 if (ret) {
1443 devres_free(ptr);
1444 return ret;
1445 }
1446
1447 ptr->devfreq = devfreq;
1448 ptr->nb = nb;
1449 ptr->list = list;
1450 devres_add(dev, ptr);
1451
1452 return 0;
1453}
1454EXPORT_SYMBOL(devm_devfreq_register_notifier);
1455
1456/**
1457 * devm_devfreq_unregister_notifier()
1458 - Resource-managed devfreq_unregister_notifier()
1459 * @dev: The devfreq user device. (parent of devfreq)
1460 * @devfreq: The devfreq object.
1461 * @nb: The notifier block to be unregistered.
1462 * @list: DEVFREQ_TRANSITION_NOTIFIER.
1463 */
1464void devm_devfreq_unregister_notifier(struct device *dev,
1465 struct devfreq *devfreq,
1466 struct notifier_block *nb,
1467 unsigned int list)
1468{
1469 WARN_ON(devres_release(dev, devm_devfreq_notifier_release,
1470 devm_devfreq_dev_match, devfreq));
1471}
1472EXPORT_SYMBOL(devm_devfreq_unregister_notifier);
1473
1269MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); 1474MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
1270MODULE_DESCRIPTION("devfreq class support"); 1475MODULE_DESCRIPTION("devfreq class support");
1271MODULE_LICENSE("GPL"); 1476MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index a11720affc31..1e8b4f469f38 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -13,6 +13,14 @@ menuconfig PM_DEVFREQ_EVENT
13 13
14if PM_DEVFREQ_EVENT 14if PM_DEVFREQ_EVENT
15 15
16config DEVFREQ_EVENT_EXYNOS_NOCP
17 bool "EXYNOS NoC (Network On Chip) Probe DEVFREQ event Driver"
18 depends on ARCH_EXYNOS
19 select PM_OPP
20 help
21 This add the devfreq-event driver for Exynos SoC. It provides NoC
22 (Network on Chip) Probe counters to measure the bandwidth of AXI bus.
23
16config DEVFREQ_EVENT_EXYNOS_PPMU 24config DEVFREQ_EVENT_EXYNOS_PPMU
17 bool "EXYNOS PPMU (Platform Performance Monitoring Unit) DEVFREQ event Driver" 25 bool "EXYNOS PPMU (Platform Performance Monitoring Unit) DEVFREQ event Driver"
18 depends on ARCH_EXYNOS 26 depends on ARCH_EXYNOS
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index be146ead79cf..3d6afd352253 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -1,2 +1,4 @@
1# Exynos DEVFREQ Event Drivers 1# Exynos DEVFREQ Event Drivers
2
3obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
2obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o 4obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
diff --git a/drivers/devfreq/event/exynos-nocp.c b/drivers/devfreq/event/exynos-nocp.c
new file mode 100644
index 000000000000..6b6a5f310486
--- /dev/null
+++ b/drivers/devfreq/event/exynos-nocp.c
@@ -0,0 +1,304 @@
1/*
2 * exynos-nocp.c - EXYNOS NoC (Network On Chip) Probe support
3 *
4 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5 * Author : Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/clk.h>
13#include <linux/module.h>
14#include <linux/devfreq-event.h>
15#include <linux/kernel.h>
16#include <linux/of_address.h>
17#include <linux/platform_device.h>
18#include <linux/regmap.h>
19
20#include "exynos-nocp.h"
21
22struct exynos_nocp {
23 struct devfreq_event_dev *edev;
24 struct devfreq_event_desc desc;
25
26 struct device *dev;
27
28 struct regmap *regmap;
29 struct clk *clk;
30};
31
32/*
33 * The devfreq-event ops structure for nocp probe.
34 */
35static int exynos_nocp_set_event(struct devfreq_event_dev *edev)
36{
37 struct exynos_nocp *nocp = devfreq_event_get_drvdata(edev);
38 int ret;
39
40 /* Disable NoC probe */
41 ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
42 NOCP_MAIN_CTL_STATEN_MASK, 0);
43 if (ret < 0) {
44 dev_err(nocp->dev, "failed to disable the NoC probe device\n");
45 return ret;
46 }
47
48 /* Set a statistics dump period to 0 */
49 ret = regmap_write(nocp->regmap, NOCP_STAT_PERIOD, 0x0);
50 if (ret < 0)
51 goto out;
52
53 /* Set the IntEvent fields of *_SRC */
54 ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_0_SRC,
55 NOCP_CNT_SRC_INTEVENT_MASK,
56 NOCP_CNT_SRC_INTEVENT_BYTE_MASK);
57 if (ret < 0)
58 goto out;
59
60 ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_1_SRC,
61 NOCP_CNT_SRC_INTEVENT_MASK,
62 NOCP_CNT_SRC_INTEVENT_CHAIN_MASK);
63 if (ret < 0)
64 goto out;
65
66 ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_2_SRC,
67 NOCP_CNT_SRC_INTEVENT_MASK,
68 NOCP_CNT_SRC_INTEVENT_CYCLE_MASK);
69 if (ret < 0)
70 goto out;
71
72 ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_3_SRC,
73 NOCP_CNT_SRC_INTEVENT_MASK,
74 NOCP_CNT_SRC_INTEVENT_CHAIN_MASK);
75 if (ret < 0)
76 goto out;
77
78
79 /* Set an alarm with a max/min value of 0 to generate StatALARM */
80 ret = regmap_write(nocp->regmap, NOCP_STAT_ALARM_MIN, 0x0);
81 if (ret < 0)
82 goto out;
83
84 ret = regmap_write(nocp->regmap, NOCP_STAT_ALARM_MAX, 0x0);
85 if (ret < 0)
86 goto out;
87
88 /* Set AlarmMode */
89 ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_0_ALARM_MODE,
90 NOCP_CNT_ALARM_MODE_MASK,
91 NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
92 if (ret < 0)
93 goto out;
94
95 ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_1_ALARM_MODE,
96 NOCP_CNT_ALARM_MODE_MASK,
97 NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
98 if (ret < 0)
99 goto out;
100
101 ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_2_ALARM_MODE,
102 NOCP_CNT_ALARM_MODE_MASK,
103 NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
104 if (ret < 0)
105 goto out;
106
107 ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_3_ALARM_MODE,
108 NOCP_CNT_ALARM_MODE_MASK,
109 NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
110 if (ret < 0)
111 goto out;
112
113 /* Enable the measurements by setting AlarmEn and StatEn */
114 ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
115 NOCP_MAIN_CTL_STATEN_MASK | NOCP_MAIN_CTL_ALARMEN_MASK,
116 NOCP_MAIN_CTL_STATEN_MASK | NOCP_MAIN_CTL_ALARMEN_MASK);
117 if (ret < 0)
118 goto out;
119
120 /* Set GlobalEN */
121 ret = regmap_update_bits(nocp->regmap, NOCP_CFG_CTL,
122 NOCP_CFG_CTL_GLOBALEN_MASK,
123 NOCP_CFG_CTL_GLOBALEN_MASK);
124 if (ret < 0)
125 goto out;
126
127 /* Enable NoC probe */
128 ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
129 NOCP_MAIN_CTL_STATEN_MASK,
130 NOCP_MAIN_CTL_STATEN_MASK);
131 if (ret < 0)
132 goto out;
133
134 return 0;
135
136out:
137 /* Reset NoC probe */
138 if (regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
139 NOCP_MAIN_CTL_STATEN_MASK, 0)) {
140 dev_err(nocp->dev, "Failed to reset NoC probe device\n");
141 }
142
143 return ret;
144}
145
146static int exynos_nocp_get_event(struct devfreq_event_dev *edev,
147 struct devfreq_event_data *edata)
148{
149 struct exynos_nocp *nocp = devfreq_event_get_drvdata(edev);
150 unsigned int counter[4];
151 int ret;
152
153 /* Read cycle count */
154 ret = regmap_read(nocp->regmap, NOCP_COUNTERS_0_VAL, &counter[0]);
155 if (ret < 0)
156 goto out;
157
158 ret = regmap_read(nocp->regmap, NOCP_COUNTERS_1_VAL, &counter[1]);
159 if (ret < 0)
160 goto out;
161
162 ret = regmap_read(nocp->regmap, NOCP_COUNTERS_2_VAL, &counter[2]);
163 if (ret < 0)
164 goto out;
165
166 ret = regmap_read(nocp->regmap, NOCP_COUNTERS_3_VAL, &counter[3]);
167 if (ret < 0)
168 goto out;
169
170 edata->load_count = ((counter[1] << 16) | counter[0]);
171 edata->total_count = ((counter[3] << 16) | counter[2]);
172
173 dev_dbg(&edev->dev, "%s (event: %ld/%ld)\n", edev->desc->name,
174 edata->load_count, edata->total_count);
175
176 return 0;
177
178out:
179 edata->load_count = 0;
180 edata->total_count = 0;
181
182 dev_err(nocp->dev, "Failed to read the counter of NoC probe device\n");
183
184 return ret;
185}
186
187static const struct devfreq_event_ops exynos_nocp_ops = {
188 .set_event = exynos_nocp_set_event,
189 .get_event = exynos_nocp_get_event,
190};
191
192static const struct of_device_id exynos_nocp_id_match[] = {
193 { .compatible = "samsung,exynos5420-nocp", },
194 { /* sentinel */ },
195};
196
197static struct regmap_config exynos_nocp_regmap_config = {
198 .reg_bits = 32,
199 .val_bits = 32,
200 .reg_stride = 4,
201 .max_register = NOCP_COUNTERS_3_VAL,
202};
203
204static int exynos_nocp_parse_dt(struct platform_device *pdev,
205 struct exynos_nocp *nocp)
206{
207 struct device *dev = nocp->dev;
208 struct device_node *np = dev->of_node;
209 struct resource *res;
210 void __iomem *base;
211
212 if (!np) {
213 dev_err(dev, "failed to find devicetree node\n");
214 return -EINVAL;
215 }
216
217 nocp->clk = devm_clk_get(dev, "nocp");
218 if (IS_ERR(nocp->clk))
219 nocp->clk = NULL;
220
221 /* Maps the memory mapped IO to control nocp register */
222 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
223 if (IS_ERR(res))
224 return PTR_ERR(res);
225
226 base = devm_ioremap_resource(dev, res);
227 if (IS_ERR(base))
228 return PTR_ERR(base);
229
230 exynos_nocp_regmap_config.max_register = resource_size(res) - 4;
231
232 nocp->regmap = devm_regmap_init_mmio(dev, base,
233 &exynos_nocp_regmap_config);
234 if (IS_ERR(nocp->regmap)) {
235 dev_err(dev, "failed to initialize regmap\n");
236 return PTR_ERR(nocp->regmap);
237 }
238
239 return 0;
240}
241
242static int exynos_nocp_probe(struct platform_device *pdev)
243{
244 struct device *dev = &pdev->dev;
245 struct device_node *np = dev->of_node;
246 struct exynos_nocp *nocp;
247 int ret;
248
249 nocp = devm_kzalloc(&pdev->dev, sizeof(*nocp), GFP_KERNEL);
250 if (!nocp)
251 return -ENOMEM;
252
253 nocp->dev = &pdev->dev;
254
255 /* Parse dt data to get resource */
256 ret = exynos_nocp_parse_dt(pdev, nocp);
257 if (ret < 0) {
258 dev_err(&pdev->dev,
259 "failed to parse devicetree for resource\n");
260 return ret;
261 }
262
263 /* Add devfreq-event device to measure the bandwidth of NoC */
264 nocp->desc.ops = &exynos_nocp_ops;
265 nocp->desc.driver_data = nocp;
266 nocp->desc.name = np->full_name;
267 nocp->edev = devm_devfreq_event_add_edev(&pdev->dev, &nocp->desc);
268 if (IS_ERR(nocp->edev)) {
269 dev_err(&pdev->dev,
270 "failed to add devfreq-event device\n");
271 return PTR_ERR(nocp->edev);
272 }
273 platform_set_drvdata(pdev, nocp);
274
275 clk_prepare_enable(nocp->clk);
276
277 pr_info("exynos-nocp: new NoC Probe device registered: %s\n",
278 dev_name(dev));
279
280 return 0;
281}
282
283static int exynos_nocp_remove(struct platform_device *pdev)
284{
285 struct exynos_nocp *nocp = platform_get_drvdata(pdev);
286
287 clk_disable_unprepare(nocp->clk);
288
289 return 0;
290}
291
292static struct platform_driver exynos_nocp_driver = {
293 .probe = exynos_nocp_probe,
294 .remove = exynos_nocp_remove,
295 .driver = {
296 .name = "exynos-nocp",
297 .of_match_table = exynos_nocp_id_match,
298 },
299};
300module_platform_driver(exynos_nocp_driver);
301
302MODULE_DESCRIPTION("Exynos NoC (Network on Chip) Probe driver");
303MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
304MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/event/exynos-nocp.h b/drivers/devfreq/event/exynos-nocp.h
new file mode 100644
index 000000000000..28564db0edb8
--- /dev/null
+++ b/drivers/devfreq/event/exynos-nocp.h
@@ -0,0 +1,78 @@
1/*
2 * exynos-nocp.h - EXYNOS NoC (Network on Chip) Probe header file
3 *
4 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5 * Author : Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __EXYNOS_NOCP_H__
13#define __EXYNOS_NOCP_H__
14
15enum nocp_reg {
16 NOCP_ID_REVISION_ID = 0x04,
17 NOCP_MAIN_CTL = 0x08,
18 NOCP_CFG_CTL = 0x0C,
19
20 NOCP_STAT_PERIOD = 0x24,
21 NOCP_STAT_GO = 0x28,
22 NOCP_STAT_ALARM_MIN = 0x2C,
23 NOCP_STAT_ALARM_MAX = 0x30,
24 NOCP_STAT_ALARM_STATUS = 0x34,
25 NOCP_STAT_ALARM_CLR = 0x38,
26
27 NOCP_COUNTERS_0_SRC = 0x138,
28 NOCP_COUNTERS_0_ALARM_MODE = 0x13C,
29 NOCP_COUNTERS_0_VAL = 0x140,
30
31 NOCP_COUNTERS_1_SRC = 0x14C,
32 NOCP_COUNTERS_1_ALARM_MODE = 0x150,
33 NOCP_COUNTERS_1_VAL = 0x154,
34
35 NOCP_COUNTERS_2_SRC = 0x160,
36 NOCP_COUNTERS_2_ALARM_MODE = 0x164,
37 NOCP_COUNTERS_2_VAL = 0x168,
38
39 NOCP_COUNTERS_3_SRC = 0x174,
40 NOCP_COUNTERS_3_ALARM_MODE = 0x178,
41 NOCP_COUNTERS_3_VAL = 0x17C,
42};
43
44/* NOCP_MAIN_CTL register */
45#define NOCP_MAIN_CTL_ERREN_MASK BIT(0)
46#define NOCP_MAIN_CTL_TRACEEN_MASK BIT(1)
47#define NOCP_MAIN_CTL_PAYLOADEN_MASK BIT(2)
48#define NOCP_MAIN_CTL_STATEN_MASK BIT(3)
49#define NOCP_MAIN_CTL_ALARMEN_MASK BIT(4)
50#define NOCP_MAIN_CTL_STATCONDDUMP_MASK BIT(5)
51#define NOCP_MAIN_CTL_INTRUSIVEMODE_MASK BIT(6)
52
53/* NOCP_CFG_CTL register */
54#define NOCP_CFG_CTL_GLOBALEN_MASK BIT(0)
55#define NOCP_CFG_CTL_ACTIVE_MASK BIT(1)
56
57/* NOCP_COUNTERS_x_SRC register */
58#define NOCP_CNT_SRC_INTEVENT_SHIFT 0
59#define NOCP_CNT_SRC_INTEVENT_MASK (0x1F << NOCP_CNT_SRC_INTEVENT_SHIFT)
60#define NOCP_CNT_SRC_INTEVENT_OFF_MASK (0x0 << NOCP_CNT_SRC_INTEVENT_SHIFT)
61#define NOCP_CNT_SRC_INTEVENT_CYCLE_MASK (0x1 << NOCP_CNT_SRC_INTEVENT_SHIFT)
62#define NOCP_CNT_SRC_INTEVENT_IDLE_MASK (0x2 << NOCP_CNT_SRC_INTEVENT_SHIFT)
63#define NOCP_CNT_SRC_INTEVENT_XFER_MASK (0x3 << NOCP_CNT_SRC_INTEVENT_SHIFT)
64#define NOCP_CNT_SRC_INTEVENT_BUSY_MASK (0x4 << NOCP_CNT_SRC_INTEVENT_SHIFT)
65#define NOCP_CNT_SRC_INTEVENT_WAIT_MASK (0x5 << NOCP_CNT_SRC_INTEVENT_SHIFT)
66#define NOCP_CNT_SRC_INTEVENT_PKT_MASK (0x6 << NOCP_CNT_SRC_INTEVENT_SHIFT)
67#define NOCP_CNT_SRC_INTEVENT_BYTE_MASK (0x8 << NOCP_CNT_SRC_INTEVENT_SHIFT)
68#define NOCP_CNT_SRC_INTEVENT_CHAIN_MASK (0x10 << NOCP_CNT_SRC_INTEVENT_SHIFT)
69
70/* NOCP_COUNTERS_x_ALARM_MODE register */
71#define NOCP_CNT_ALARM_MODE_SHIFT 0
72#define NOCP_CNT_ALARM_MODE_MASK (0x3 << NOCP_CNT_ALARM_MODE_SHIFT)
73#define NOCP_CNT_ALARM_MODE_OFF_MASK (0x0 << NOCP_CNT_ALARM_MODE_SHIFT)
74#define NOCP_CNT_ALARM_MODE_MIN_MASK (0x1 << NOCP_CNT_ALARM_MODE_SHIFT)
75#define NOCP_CNT_ALARM_MODE_MAX_MASK (0x2 << NOCP_CNT_ALARM_MODE_SHIFT)
76#define NOCP_CNT_ALARM_MODE_MIN_MAX_MASK (0x3 << NOCP_CNT_ALARM_MODE_SHIFT)
77
78#endif /* __EXYNOS_NOCP_H__ */
diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
new file mode 100644
index 000000000000..2363d0a189b7
--- /dev/null
+++ b/drivers/devfreq/exynos-bus.c
@@ -0,0 +1,570 @@
1/*
2 * Generic Exynos Bus frequency driver with DEVFREQ Framework
3 *
4 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5 * Author : Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This driver support Exynos Bus frequency feature by using
8 * DEVFREQ framework and is based on drivers/devfreq/exynos/exynos4_bus.c.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/clk.h>
16#include <linux/devfreq.h>
17#include <linux/devfreq-event.h>
18#include <linux/device.h>
19#include <linux/export.h>
20#include <linux/module.h>
21#include <linux/of_device.h>
22#include <linux/pm_opp.h>
23#include <linux/platform_device.h>
24#include <linux/regulator/consumer.h>
25#include <linux/slab.h>
26
27#define DEFAULT_SATURATION_RATIO 40
28#define DEFAULT_VOLTAGE_TOLERANCE 2
29
30struct exynos_bus {
31 struct device *dev;
32
33 struct devfreq *devfreq;
34 struct devfreq_event_dev **edev;
35 unsigned int edev_count;
36 struct mutex lock;
37
38 struct dev_pm_opp *curr_opp;
39
40 struct regulator *regulator;
41 struct clk *clk;
42 unsigned int voltage_tolerance;
43 unsigned int ratio;
44};
45
46/*
47 * Control the devfreq-event device to get the current state of bus
48 */
49#define exynos_bus_ops_edev(ops) \
50static int exynos_bus_##ops(struct exynos_bus *bus) \
51{ \
52 int i, ret; \
53 \
54 for (i = 0; i < bus->edev_count; i++) { \
55 if (!bus->edev[i]) \
56 continue; \
57 ret = devfreq_event_##ops(bus->edev[i]); \
58 if (ret < 0) \
59 return ret; \
60 } \
61 \
62 return 0; \
63}
64exynos_bus_ops_edev(enable_edev);
65exynos_bus_ops_edev(disable_edev);
66exynos_bus_ops_edev(set_event);
67
68static int exynos_bus_get_event(struct exynos_bus *bus,
69 struct devfreq_event_data *edata)
70{
71 struct devfreq_event_data event_data;
72 unsigned long load_count = 0, total_count = 0;
73 int i, ret = 0;
74
75 for (i = 0; i < bus->edev_count; i++) {
76 if (!bus->edev[i])
77 continue;
78
79 ret = devfreq_event_get_event(bus->edev[i], &event_data);
80 if (ret < 0)
81 return ret;
82
83 if (i == 0 || event_data.load_count > load_count) {
84 load_count = event_data.load_count;
85 total_count = event_data.total_count;
86 }
87 }
88
89 edata->load_count = load_count;
90 edata->total_count = total_count;
91
92 return ret;
93}
94
95/*
96 * Must necessary function for devfreq simple-ondemand governor
97 */
98static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
99{
100 struct exynos_bus *bus = dev_get_drvdata(dev);
101 struct dev_pm_opp *new_opp;
102 unsigned long old_freq, new_freq, old_volt, new_volt, tol;
103 int ret = 0;
104
105 /* Get new opp-bus instance according to new bus clock */
106 rcu_read_lock();
107 new_opp = devfreq_recommended_opp(dev, freq, flags);
108 if (IS_ERR(new_opp)) {
109 dev_err(dev, "failed to get recommended opp instance\n");
110 rcu_read_unlock();
111 return PTR_ERR(new_opp);
112 }
113
114 new_freq = dev_pm_opp_get_freq(new_opp);
115 new_volt = dev_pm_opp_get_voltage(new_opp);
116 old_freq = dev_pm_opp_get_freq(bus->curr_opp);
117 old_volt = dev_pm_opp_get_voltage(bus->curr_opp);
118 rcu_read_unlock();
119
120 if (old_freq == new_freq)
121 return 0;
122 tol = new_volt * bus->voltage_tolerance / 100;
123
124 /* Change voltage and frequency according to new OPP level */
125 mutex_lock(&bus->lock);
126
127 if (old_freq < new_freq) {
128 ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
129 if (ret < 0) {
130 dev_err(bus->dev, "failed to set voltage\n");
131 goto out;
132 }
133 }
134
135 ret = clk_set_rate(bus->clk, new_freq);
136 if (ret < 0) {
137 dev_err(dev, "failed to change clock of bus\n");
138 clk_set_rate(bus->clk, old_freq);
139 goto out;
140 }
141
142 if (old_freq > new_freq) {
143 ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
144 if (ret < 0) {
145 dev_err(bus->dev, "failed to set voltage\n");
146 goto out;
147 }
148 }
149 bus->curr_opp = new_opp;
150
151 dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n",
152 old_freq/1000, new_freq/1000);
153out:
154 mutex_unlock(&bus->lock);
155
156 return ret;
157}
158
159static int exynos_bus_get_dev_status(struct device *dev,
160 struct devfreq_dev_status *stat)
161{
162 struct exynos_bus *bus = dev_get_drvdata(dev);
163 struct devfreq_event_data edata;
164 int ret;
165
166 rcu_read_lock();
167 stat->current_frequency = dev_pm_opp_get_freq(bus->curr_opp);
168 rcu_read_unlock();
169
170 ret = exynos_bus_get_event(bus, &edata);
171 if (ret < 0) {
172 stat->total_time = stat->busy_time = 0;
173 goto err;
174 }
175
176 stat->busy_time = (edata.load_count * 100) / bus->ratio;
177 stat->total_time = edata.total_count;
178
179 dev_dbg(dev, "Usage of devfreq-event : %lu/%lu\n", stat->busy_time,
180 stat->total_time);
181
182err:
183 ret = exynos_bus_set_event(bus);
184 if (ret < 0) {
185 dev_err(dev, "failed to set event to devfreq-event devices\n");
186 return ret;
187 }
188
189 return ret;
190}
191
192static void exynos_bus_exit(struct device *dev)
193{
194 struct exynos_bus *bus = dev_get_drvdata(dev);
195 int ret;
196
197 ret = exynos_bus_disable_edev(bus);
198 if (ret < 0)
199 dev_warn(dev, "failed to disable the devfreq-event devices\n");
200
201 if (bus->regulator)
202 regulator_disable(bus->regulator);
203
204 dev_pm_opp_of_remove_table(dev);
205 clk_disable_unprepare(bus->clk);
206}
207
208/*
209 * Must necessary function for devfreq passive governor
210 */
211static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
212 u32 flags)
213{
214 struct exynos_bus *bus = dev_get_drvdata(dev);
215 struct dev_pm_opp *new_opp;
216 unsigned long old_freq, new_freq;
217 int ret = 0;
218
219 /* Get new opp-bus instance according to new bus clock */
220 rcu_read_lock();
221 new_opp = devfreq_recommended_opp(dev, freq, flags);
222 if (IS_ERR(new_opp)) {
223 dev_err(dev, "failed to get recommended opp instance\n");
224 rcu_read_unlock();
225 return PTR_ERR(new_opp);
226 }
227
228 new_freq = dev_pm_opp_get_freq(new_opp);
229 old_freq = dev_pm_opp_get_freq(bus->curr_opp);
230 rcu_read_unlock();
231
232 if (old_freq == new_freq)
233 return 0;
234
235 /* Change the frequency according to new OPP level */
236 mutex_lock(&bus->lock);
237
238 ret = clk_set_rate(bus->clk, new_freq);
239 if (ret < 0) {
240 dev_err(dev, "failed to set the clock of bus\n");
241 goto out;
242 }
243
244 *freq = new_freq;
245 bus->curr_opp = new_opp;
246
247 dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n",
248 old_freq/1000, new_freq/1000);
249out:
250 mutex_unlock(&bus->lock);
251
252 return ret;
253}
254
255static void exynos_bus_passive_exit(struct device *dev)
256{
257 struct exynos_bus *bus = dev_get_drvdata(dev);
258
259 dev_pm_opp_of_remove_table(dev);
260 clk_disable_unprepare(bus->clk);
261}
262
263static int exynos_bus_parent_parse_of(struct device_node *np,
264 struct exynos_bus *bus)
265{
266 struct device *dev = bus->dev;
267 int i, ret, count, size;
268
269 /* Get the regulator to provide each bus with the power */
270 bus->regulator = devm_regulator_get(dev, "vdd");
271 if (IS_ERR(bus->regulator)) {
272 dev_err(dev, "failed to get VDD regulator\n");
273 return PTR_ERR(bus->regulator);
274 }
275
276 ret = regulator_enable(bus->regulator);
277 if (ret < 0) {
278 dev_err(dev, "failed to enable VDD regulator\n");
279 return ret;
280 }
281
282 /*
283 * Get the devfreq-event devices to get the current utilization of
284 * buses. This raw data will be used in devfreq ondemand governor.
285 */
286 count = devfreq_event_get_edev_count(dev);
287 if (count < 0) {
288 dev_err(dev, "failed to get the count of devfreq-event dev\n");
289 ret = count;
290 goto err_regulator;
291 }
292 bus->edev_count = count;
293
294 size = sizeof(*bus->edev) * count;
295 bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
296 if (!bus->edev) {
297 ret = -ENOMEM;
298 goto err_regulator;
299 }
300
301 for (i = 0; i < count; i++) {
302 bus->edev[i] = devfreq_event_get_edev_by_phandle(dev, i);
303 if (IS_ERR(bus->edev[i])) {
304 ret = -EPROBE_DEFER;
305 goto err_regulator;
306 }
307 }
308
309 /*
310 * Optionally, Get the saturation ratio according to Exynos SoC
311 * When measuring the utilization of each AXI bus with devfreq-event
312 * devices, the measured real cycle might be much lower than the
313 * total cycle of bus during sampling rate. In result, the devfreq
314 * simple-ondemand governor might not decide to change the current
315 * frequency due to too utilization (= real cycle/total cycle).
316 * So, this property is used to adjust the utilization when calculating
317 * the busy_time in exynos_bus_get_dev_status().
318 */
319 if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio))
320 bus->ratio = DEFAULT_SATURATION_RATIO;
321
322 if (of_property_read_u32(np, "exynos,voltage-tolerance",
323 &bus->voltage_tolerance))
324 bus->voltage_tolerance = DEFAULT_VOLTAGE_TOLERANCE;
325
326 return 0;
327
328err_regulator:
329 regulator_disable(bus->regulator);
330
331 return ret;
332}
333
334static int exynos_bus_parse_of(struct device_node *np,
335 struct exynos_bus *bus)
336{
337 struct device *dev = bus->dev;
338 unsigned long rate;
339 int ret;
340
341 /* Get the clock to provide each bus with source clock */
342 bus->clk = devm_clk_get(dev, "bus");
343 if (IS_ERR(bus->clk)) {
344 dev_err(dev, "failed to get bus clock\n");
345 return PTR_ERR(bus->clk);
346 }
347
348 ret = clk_prepare_enable(bus->clk);
349 if (ret < 0) {
350 dev_err(dev, "failed to get enable clock\n");
351 return ret;
352 }
353
354 /* Get the freq and voltage from OPP table to scale the bus freq */
355 rcu_read_lock();
356 ret = dev_pm_opp_of_add_table(dev);
357 if (ret < 0) {
358 dev_err(dev, "failed to get OPP table\n");
359 rcu_read_unlock();
360 goto err_clk;
361 }
362
363 rate = clk_get_rate(bus->clk);
364 bus->curr_opp = devfreq_recommended_opp(dev, &rate, 0);
365 if (IS_ERR(bus->curr_opp)) {
366 dev_err(dev, "failed to find dev_pm_opp\n");
367 rcu_read_unlock();
368 ret = PTR_ERR(bus->curr_opp);
369 goto err_opp;
370 }
371 rcu_read_unlock();
372
373 return 0;
374
375err_opp:
376 dev_pm_opp_of_remove_table(dev);
377err_clk:
378 clk_disable_unprepare(bus->clk);
379
380 return ret;
381}
382
383static int exynos_bus_probe(struct platform_device *pdev)
384{
385 struct device *dev = &pdev->dev;
386 struct device_node *np = dev->of_node;
387 struct devfreq_dev_profile *profile;
388 struct devfreq_simple_ondemand_data *ondemand_data;
389 struct devfreq_passive_data *passive_data;
390 struct devfreq *parent_devfreq;
391 struct exynos_bus *bus;
392 int ret, max_state;
393 unsigned long min_freq, max_freq;
394
395 if (!np) {
396 dev_err(dev, "failed to find devicetree node\n");
397 return -EINVAL;
398 }
399
400 bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
401 if (!bus)
402 return -ENOMEM;
403 mutex_init(&bus->lock);
404 bus->dev = &pdev->dev;
405 platform_set_drvdata(pdev, bus);
406
407 /* Parse the device-tree to get the resource information */
408 ret = exynos_bus_parse_of(np, bus);
409 if (ret < 0)
410 goto err;
411
412 profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
413 if (!profile) {
414 ret = -ENOMEM;
415 goto err;
416 }
417
418 if (of_parse_phandle(dev->of_node, "devfreq", 0))
419 goto passive;
420 else
421 ret = exynos_bus_parent_parse_of(np, bus);
422
423 if (ret < 0)
424 goto err;
425
426 /* Initialize the struct profile and governor data for parent device */
427 profile->polling_ms = 50;
428 profile->target = exynos_bus_target;
429 profile->get_dev_status = exynos_bus_get_dev_status;
430 profile->exit = exynos_bus_exit;
431
432 ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
433 if (!ondemand_data) {
434 ret = -ENOMEM;
435 goto err;
436 }
437 ondemand_data->upthreshold = 40;
438 ondemand_data->downdifferential = 5;
439
440 /* Add devfreq device to monitor and handle the exynos bus */
441 bus->devfreq = devm_devfreq_add_device(dev, profile, "simple_ondemand",
442 ondemand_data);
443 if (IS_ERR(bus->devfreq)) {
444 dev_err(dev, "failed to add devfreq device\n");
445 ret = PTR_ERR(bus->devfreq);
446 goto err;
447 }
448
449 /* Register opp_notifier to catch the change of OPP */
450 ret = devm_devfreq_register_opp_notifier(dev, bus->devfreq);
451 if (ret < 0) {
452 dev_err(dev, "failed to register opp notifier\n");
453 goto err;
454 }
455
456 /*
457 * Enable devfreq-event to get raw data which is used to determine
458 * current bus load.
459 */
460 ret = exynos_bus_enable_edev(bus);
461 if (ret < 0) {
462 dev_err(dev, "failed to enable devfreq-event devices\n");
463 goto err;
464 }
465
466 ret = exynos_bus_set_event(bus);
467 if (ret < 0) {
468 dev_err(dev, "failed to set event to devfreq-event devices\n");
469 goto err;
470 }
471
472 goto out;
473passive:
474 /* Initialize the struct profile and governor data for passive device */
475 profile->target = exynos_bus_passive_target;
476 profile->exit = exynos_bus_passive_exit;
477
478 /* Get the instance of parent devfreq device */
479 parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
480 if (IS_ERR(parent_devfreq)) {
481 ret = -EPROBE_DEFER;
482 goto err;
483 }
484
485 passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
486 if (!passive_data) {
487 ret = -ENOMEM;
488 goto err;
489 }
490 passive_data->parent = parent_devfreq;
491
492 /* Add devfreq device for exynos bus with passive governor */
493 bus->devfreq = devm_devfreq_add_device(dev, profile, "passive",
494 passive_data);
495 if (IS_ERR(bus->devfreq)) {
496 dev_err(dev,
497 "failed to add devfreq dev with passive governor\n");
498 ret = -EPROBE_DEFER;
499 goto err;
500 }
501
502out:
503 max_state = bus->devfreq->profile->max_state;
504 min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
505 max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
506 pr_info("exynos-bus: new bus device registered: %s (%6ld KHz ~ %6ld KHz)\n",
507 dev_name(dev), min_freq, max_freq);
508
509 return 0;
510
511err:
512 dev_pm_opp_of_remove_table(dev);
513 clk_disable_unprepare(bus->clk);
514
515 return ret;
516}
517
518#ifdef CONFIG_PM_SLEEP
519static int exynos_bus_resume(struct device *dev)
520{
521 struct exynos_bus *bus = dev_get_drvdata(dev);
522 int ret;
523
524 ret = exynos_bus_enable_edev(bus);
525 if (ret < 0) {
526 dev_err(dev, "failed to enable the devfreq-event devices\n");
527 return ret;
528 }
529
530 return 0;
531}
532
533static int exynos_bus_suspend(struct device *dev)
534{
535 struct exynos_bus *bus = dev_get_drvdata(dev);
536 int ret;
537
538 ret = exynos_bus_disable_edev(bus);
539 if (ret < 0) {
540 dev_err(dev, "failed to disable the devfreq-event devices\n");
541 return ret;
542 }
543
544 return 0;
545}
546#endif
547
548static const struct dev_pm_ops exynos_bus_pm = {
549 SET_SYSTEM_SLEEP_PM_OPS(exynos_bus_suspend, exynos_bus_resume)
550};
551
552static const struct of_device_id exynos_bus_of_match[] = {
553 { .compatible = "samsung,exynos-bus", },
554 { /* sentinel */ },
555};
556MODULE_DEVICE_TABLE(of, exynos_bus_of_match);
557
558static struct platform_driver exynos_bus_platdrv = {
559 .probe = exynos_bus_probe,
560 .driver = {
561 .name = "exynos-bus",
562 .pm = &exynos_bus_pm,
563 .of_match_table = of_match_ptr(exynos_bus_of_match),
564 },
565};
566module_platform_driver(exynos_bus_platdrv);
567
568MODULE_DESCRIPTION("Generic Exynos Bus frequency driver");
569MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
570MODULE_LICENSE("GPL v2");
diff --git a/drivers/devfreq/exynos/Makefile b/drivers/devfreq/exynos/Makefile
deleted file mode 100644
index 49bc9175f923..000000000000
--- a/drivers/devfreq/exynos/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
1# Exynos DEVFREQ Drivers
2obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ) += exynos_ppmu.o exynos4_bus.o
3obj-$(CONFIG_ARM_EXYNOS5_BUS_DEVFREQ) += exynos_ppmu.o exynos5_bus.o
diff --git a/drivers/devfreq/exynos/exynos4_bus.c b/drivers/devfreq/exynos/exynos4_bus.c
deleted file mode 100644
index da9509205169..000000000000
--- a/drivers/devfreq/exynos/exynos4_bus.c
+++ /dev/null
@@ -1,1055 +0,0 @@
1/* drivers/devfreq/exynos4210_memorybus.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 * MyungJoo Ham <myungjoo.ham@samsung.com>
6 *
7 * EXYNOS4 - Memory/Bus clock frequency scaling support in DEVFREQ framework
8 * This version supports EXYNOS4210 only. This changes bus frequencies
9 * and vddint voltages. Exynos4412/4212 should be able to be supported
10 * with minor modifications.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/io.h>
19#include <linux/slab.h>
20#include <linux/mutex.h>
21#include <linux/suspend.h>
22#include <linux/pm_opp.h>
23#include <linux/devfreq.h>
24#include <linux/platform_device.h>
25#include <linux/regulator/consumer.h>
26#include <linux/module.h>
27
28#include <mach/map.h>
29
30#include "exynos_ppmu.h"
31#include "exynos4_bus.h"
32
33#define MAX_SAFEVOLT 1200000 /* 1.2V */
34
35enum exynos4_busf_type {
36 TYPE_BUSF_EXYNOS4210,
37 TYPE_BUSF_EXYNOS4x12,
38};
39
40/* Assume that the bus is saturated if the utilization is 40% */
41#define BUS_SATURATION_RATIO 40
42
43enum busclk_level_idx {
44 LV_0 = 0,
45 LV_1,
46 LV_2,
47 LV_3,
48 LV_4,
49 _LV_END
50};
51
52enum exynos_ppmu_idx {
53 PPMU_DMC0,
54 PPMU_DMC1,
55 PPMU_END,
56};
57
58#define EX4210_LV_MAX LV_2
59#define EX4x12_LV_MAX LV_4
60#define EX4210_LV_NUM (LV_2 + 1)
61#define EX4x12_LV_NUM (LV_4 + 1)
62
63/**
64 * struct busfreq_opp_info - opp information for bus
65 * @rate: Frequency in hertz
66 * @volt: Voltage in microvolts corresponding to this OPP
67 */
68struct busfreq_opp_info {
69 unsigned long rate;
70 unsigned long volt;
71};
72
73struct busfreq_data {
74 enum exynos4_busf_type type;
75 struct device *dev;
76 struct devfreq *devfreq;
77 bool disabled;
78 struct regulator *vdd_int;
79 struct regulator *vdd_mif; /* Exynos4412/4212 only */
80 struct busfreq_opp_info curr_oppinfo;
81 struct busfreq_ppmu_data ppmu_data;
82
83 struct notifier_block pm_notifier;
84 struct mutex lock;
85
86 /* Dividers calculated at boot/probe-time */
87 unsigned int dmc_divtable[_LV_END]; /* DMC0 */
88 unsigned int top_divtable[_LV_END];
89};
90
91/* 4210 controls clock of mif and voltage of int */
92static struct bus_opp_table exynos4210_busclk_table[] = {
93 {LV_0, 400000, 1150000},
94 {LV_1, 267000, 1050000},
95 {LV_2, 133000, 1025000},
96 {0, 0, 0},
97};
98
99/*
100 * MIF is the main control knob clock for Exynos4x12 MIF/INT
101 * clock and voltage of both mif/int are controlled.
102 */
103static struct bus_opp_table exynos4x12_mifclk_table[] = {
104 {LV_0, 400000, 1100000},
105 {LV_1, 267000, 1000000},
106 {LV_2, 160000, 950000},
107 {LV_3, 133000, 950000},
108 {LV_4, 100000, 950000},
109 {0, 0, 0},
110};
111
112/*
113 * INT is not the control knob of 4x12. LV_x is not meant to represent
114 * the current performance. (MIF does)
115 */
116static struct bus_opp_table exynos4x12_intclk_table[] = {
117 {LV_0, 200000, 1000000},
118 {LV_1, 160000, 950000},
119 {LV_2, 133000, 925000},
120 {LV_3, 100000, 900000},
121 {0, 0, 0},
122};
123
124/* TODO: asv volt definitions are "__initdata"? */
125/* Some chips have different operating voltages */
126static unsigned int exynos4210_asv_volt[][EX4210_LV_NUM] = {
127 {1150000, 1050000, 1050000},
128 {1125000, 1025000, 1025000},
129 {1100000, 1000000, 1000000},
130 {1075000, 975000, 975000},
131 {1050000, 950000, 950000},
132};
133
134static unsigned int exynos4x12_mif_step_50[][EX4x12_LV_NUM] = {
135 /* 400 267 160 133 100 */
136 {1050000, 950000, 900000, 900000, 900000}, /* ASV0 */
137 {1050000, 950000, 900000, 900000, 900000}, /* ASV1 */
138 {1050000, 950000, 900000, 900000, 900000}, /* ASV2 */
139 {1050000, 900000, 900000, 900000, 900000}, /* ASV3 */
140 {1050000, 900000, 900000, 900000, 850000}, /* ASV4 */
141 {1050000, 900000, 900000, 850000, 850000}, /* ASV5 */
142 {1050000, 900000, 850000, 850000, 850000}, /* ASV6 */
143 {1050000, 900000, 850000, 850000, 850000}, /* ASV7 */
144 {1050000, 900000, 850000, 850000, 850000}, /* ASV8 */
145};
146
147static unsigned int exynos4x12_int_volt[][EX4x12_LV_NUM] = {
148 /* 200 160 133 100 */
149 {1000000, 950000, 925000, 900000}, /* ASV0 */
150 {975000, 925000, 925000, 900000}, /* ASV1 */
151 {950000, 925000, 900000, 875000}, /* ASV2 */
152 {950000, 900000, 900000, 875000}, /* ASV3 */
153 {925000, 875000, 875000, 875000}, /* ASV4 */
154 {900000, 850000, 850000, 850000}, /* ASV5 */
155 {900000, 850000, 850000, 850000}, /* ASV6 */
156 {900000, 850000, 850000, 850000}, /* ASV7 */
157 {900000, 850000, 850000, 850000}, /* ASV8 */
158};
159
160/*** Clock Divider Data for Exynos4210 ***/
161static unsigned int exynos4210_clkdiv_dmc0[][8] = {
162 /*
163 * Clock divider value for following
164 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
165 * DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
166 */
167
168 /* DMC L0: 400MHz */
169 { 3, 1, 1, 1, 1, 1, 3, 1 },
170 /* DMC L1: 266.7MHz */
171 { 4, 1, 1, 2, 1, 1, 3, 1 },
172 /* DMC L2: 133MHz */
173 { 5, 1, 1, 5, 1, 1, 3, 1 },
174};
175static unsigned int exynos4210_clkdiv_top[][5] = {
176 /*
177 * Clock divider value for following
178 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
179 */
180 /* ACLK200 L0: 200MHz */
181 { 3, 7, 4, 5, 1 },
182 /* ACLK200 L1: 160MHz */
183 { 4, 7, 5, 6, 1 },
184 /* ACLK200 L2: 133MHz */
185 { 5, 7, 7, 7, 1 },
186};
187static unsigned int exynos4210_clkdiv_lr_bus[][2] = {
188 /*
189 * Clock divider value for following
190 * { DIVGDL/R, DIVGPL/R }
191 */
192 /* ACLK_GDL/R L1: 200MHz */
193 { 3, 1 },
194 /* ACLK_GDL/R L2: 160MHz */
195 { 4, 1 },
196 /* ACLK_GDL/R L3: 133MHz */
197 { 5, 1 },
198};
199
200/*** Clock Divider Data for Exynos4212/4412 ***/
201static unsigned int exynos4x12_clkdiv_dmc0[][6] = {
202 /*
203 * Clock divider value for following
204 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
205 * DIVDMCP}
206 */
207
208 /* DMC L0: 400MHz */
209 {3, 1, 1, 1, 1, 1},
210 /* DMC L1: 266.7MHz */
211 {4, 1, 1, 2, 1, 1},
212 /* DMC L2: 160MHz */
213 {5, 1, 1, 4, 1, 1},
214 /* DMC L3: 133MHz */
215 {5, 1, 1, 5, 1, 1},
216 /* DMC L4: 100MHz */
217 {7, 1, 1, 7, 1, 1},
218};
219static unsigned int exynos4x12_clkdiv_dmc1[][6] = {
220 /*
221 * Clock divider value for following
222 * { G2DACP, DIVC2C, DIVC2C_ACLK }
223 */
224
225 /* DMC L0: 400MHz */
226 {3, 1, 1},
227 /* DMC L1: 266.7MHz */
228 {4, 2, 1},
229 /* DMC L2: 160MHz */
230 {5, 4, 1},
231 /* DMC L3: 133MHz */
232 {5, 5, 1},
233 /* DMC L4: 100MHz */
234 {7, 7, 1},
235};
236static unsigned int exynos4x12_clkdiv_top[][5] = {
237 /*
238 * Clock divider value for following
239 * { DIVACLK266_GPS, DIVACLK100, DIVACLK160,
240 DIVACLK133, DIVONENAND }
241 */
242
243 /* ACLK_GDL/R L0: 200MHz */
244 {2, 7, 4, 5, 1},
245 /* ACLK_GDL/R L1: 200MHz */
246 {2, 7, 4, 5, 1},
247 /* ACLK_GDL/R L2: 160MHz */
248 {4, 7, 5, 7, 1},
249 /* ACLK_GDL/R L3: 133MHz */
250 {4, 7, 5, 7, 1},
251 /* ACLK_GDL/R L4: 100MHz */
252 {7, 7, 7, 7, 1},
253};
254static unsigned int exynos4x12_clkdiv_lr_bus[][2] = {
255 /*
256 * Clock divider value for following
257 * { DIVGDL/R, DIVGPL/R }
258 */
259
260 /* ACLK_GDL/R L0: 200MHz */
261 {3, 1},
262 /* ACLK_GDL/R L1: 200MHz */
263 {3, 1},
264 /* ACLK_GDL/R L2: 160MHz */
265 {4, 1},
266 /* ACLK_GDL/R L3: 133MHz */
267 {5, 1},
268 /* ACLK_GDL/R L4: 100MHz */
269 {7, 1},
270};
271static unsigned int exynos4x12_clkdiv_sclkip[][3] = {
272 /*
273 * Clock divider value for following
274 * { DIVMFC, DIVJPEG, DIVFIMC0~3}
275 */
276
277 /* SCLK_MFC: 200MHz */
278 {3, 3, 4},
279 /* SCLK_MFC: 200MHz */
280 {3, 3, 4},
281 /* SCLK_MFC: 160MHz */
282 {4, 4, 5},
283 /* SCLK_MFC: 133MHz */
284 {5, 5, 5},
285 /* SCLK_MFC: 100MHz */
286 {7, 7, 7},
287};
288
289
290static int exynos4210_set_busclk(struct busfreq_data *data,
291 struct busfreq_opp_info *oppi)
292{
293 unsigned int index;
294 unsigned int tmp;
295
296 for (index = LV_0; index < EX4210_LV_NUM; index++)
297 if (oppi->rate == exynos4210_busclk_table[index].clk)
298 break;
299
300 if (index == EX4210_LV_NUM)
301 return -EINVAL;
302
303 /* Change Divider - DMC0 */
304 tmp = data->dmc_divtable[index];
305
306 __raw_writel(tmp, EXYNOS4_CLKDIV_DMC0);
307
308 do {
309 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_DMC0);
310 } while (tmp & 0x11111111);
311
312 /* Change Divider - TOP */
313 tmp = data->top_divtable[index];
314
315 __raw_writel(tmp, EXYNOS4_CLKDIV_TOP);
316
317 do {
318 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_TOP);
319 } while (tmp & 0x11111);
320
321 /* Change Divider - LEFTBUS */
322 tmp = __raw_readl(EXYNOS4_CLKDIV_LEFTBUS);
323
324 tmp &= ~(EXYNOS4_CLKDIV_BUS_GDLR_MASK | EXYNOS4_CLKDIV_BUS_GPLR_MASK);
325
326 tmp |= ((exynos4210_clkdiv_lr_bus[index][0] <<
327 EXYNOS4_CLKDIV_BUS_GDLR_SHIFT) |
328 (exynos4210_clkdiv_lr_bus[index][1] <<
329 EXYNOS4_CLKDIV_BUS_GPLR_SHIFT));
330
331 __raw_writel(tmp, EXYNOS4_CLKDIV_LEFTBUS);
332
333 do {
334 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_LEFTBUS);
335 } while (tmp & 0x11);
336
337 /* Change Divider - RIGHTBUS */
338 tmp = __raw_readl(EXYNOS4_CLKDIV_RIGHTBUS);
339
340 tmp &= ~(EXYNOS4_CLKDIV_BUS_GDLR_MASK | EXYNOS4_CLKDIV_BUS_GPLR_MASK);
341
342 tmp |= ((exynos4210_clkdiv_lr_bus[index][0] <<
343 EXYNOS4_CLKDIV_BUS_GDLR_SHIFT) |
344 (exynos4210_clkdiv_lr_bus[index][1] <<
345 EXYNOS4_CLKDIV_BUS_GPLR_SHIFT));
346
347 __raw_writel(tmp, EXYNOS4_CLKDIV_RIGHTBUS);
348
349 do {
350 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_RIGHTBUS);
351 } while (tmp & 0x11);
352
353 return 0;
354}
355
356static int exynos4x12_set_busclk(struct busfreq_data *data,
357 struct busfreq_opp_info *oppi)
358{
359 unsigned int index;
360 unsigned int tmp;
361
362 for (index = LV_0; index < EX4x12_LV_NUM; index++)
363 if (oppi->rate == exynos4x12_mifclk_table[index].clk)
364 break;
365
366 if (index == EX4x12_LV_NUM)
367 return -EINVAL;
368
369 /* Change Divider - DMC0 */
370 tmp = data->dmc_divtable[index];
371
372 __raw_writel(tmp, EXYNOS4_CLKDIV_DMC0);
373
374 do {
375 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_DMC0);
376 } while (tmp & 0x11111111);
377
378 /* Change Divider - DMC1 */
379 tmp = __raw_readl(EXYNOS4_CLKDIV_DMC1);
380
381 tmp &= ~(EXYNOS4_CLKDIV_DMC1_G2D_ACP_MASK |
382 EXYNOS4_CLKDIV_DMC1_C2C_MASK |
383 EXYNOS4_CLKDIV_DMC1_C2CACLK_MASK);
384
385 tmp |= ((exynos4x12_clkdiv_dmc1[index][0] <<
386 EXYNOS4_CLKDIV_DMC1_G2D_ACP_SHIFT) |
387 (exynos4x12_clkdiv_dmc1[index][1] <<
388 EXYNOS4_CLKDIV_DMC1_C2C_SHIFT) |
389 (exynos4x12_clkdiv_dmc1[index][2] <<
390 EXYNOS4_CLKDIV_DMC1_C2CACLK_SHIFT));
391
392 __raw_writel(tmp, EXYNOS4_CLKDIV_DMC1);
393
394 do {
395 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_DMC1);
396 } while (tmp & 0x111111);
397
398 /* Change Divider - TOP */
399 tmp = __raw_readl(EXYNOS4_CLKDIV_TOP);
400
401 tmp &= ~(EXYNOS4_CLKDIV_TOP_ACLK266_GPS_MASK |
402 EXYNOS4_CLKDIV_TOP_ACLK100_MASK |
403 EXYNOS4_CLKDIV_TOP_ACLK160_MASK |
404 EXYNOS4_CLKDIV_TOP_ACLK133_MASK |
405 EXYNOS4_CLKDIV_TOP_ONENAND_MASK);
406
407 tmp |= ((exynos4x12_clkdiv_top[index][0] <<
408 EXYNOS4_CLKDIV_TOP_ACLK266_GPS_SHIFT) |
409 (exynos4x12_clkdiv_top[index][1] <<
410 EXYNOS4_CLKDIV_TOP_ACLK100_SHIFT) |
411 (exynos4x12_clkdiv_top[index][2] <<
412 EXYNOS4_CLKDIV_TOP_ACLK160_SHIFT) |
413 (exynos4x12_clkdiv_top[index][3] <<
414 EXYNOS4_CLKDIV_TOP_ACLK133_SHIFT) |
415 (exynos4x12_clkdiv_top[index][4] <<
416 EXYNOS4_CLKDIV_TOP_ONENAND_SHIFT));
417
418 __raw_writel(tmp, EXYNOS4_CLKDIV_TOP);
419
420 do {
421 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_TOP);
422 } while (tmp & 0x11111);
423
424 /* Change Divider - LEFTBUS */
425 tmp = __raw_readl(EXYNOS4_CLKDIV_LEFTBUS);
426
427 tmp &= ~(EXYNOS4_CLKDIV_BUS_GDLR_MASK | EXYNOS4_CLKDIV_BUS_GPLR_MASK);
428
429 tmp |= ((exynos4x12_clkdiv_lr_bus[index][0] <<
430 EXYNOS4_CLKDIV_BUS_GDLR_SHIFT) |
431 (exynos4x12_clkdiv_lr_bus[index][1] <<
432 EXYNOS4_CLKDIV_BUS_GPLR_SHIFT));
433
434 __raw_writel(tmp, EXYNOS4_CLKDIV_LEFTBUS);
435
436 do {
437 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_LEFTBUS);
438 } while (tmp & 0x11);
439
440 /* Change Divider - RIGHTBUS */
441 tmp = __raw_readl(EXYNOS4_CLKDIV_RIGHTBUS);
442
443 tmp &= ~(EXYNOS4_CLKDIV_BUS_GDLR_MASK | EXYNOS4_CLKDIV_BUS_GPLR_MASK);
444
445 tmp |= ((exynos4x12_clkdiv_lr_bus[index][0] <<
446 EXYNOS4_CLKDIV_BUS_GDLR_SHIFT) |
447 (exynos4x12_clkdiv_lr_bus[index][1] <<
448 EXYNOS4_CLKDIV_BUS_GPLR_SHIFT));
449
450 __raw_writel(tmp, EXYNOS4_CLKDIV_RIGHTBUS);
451
452 do {
453 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_RIGHTBUS);
454 } while (tmp & 0x11);
455
456 /* Change Divider - MFC */
457 tmp = __raw_readl(EXYNOS4_CLKDIV_MFC);
458
459 tmp &= ~(EXYNOS4_CLKDIV_MFC_MASK);
460
461 tmp |= ((exynos4x12_clkdiv_sclkip[index][0] <<
462 EXYNOS4_CLKDIV_MFC_SHIFT));
463
464 __raw_writel(tmp, EXYNOS4_CLKDIV_MFC);
465
466 do {
467 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_MFC);
468 } while (tmp & 0x1);
469
470 /* Change Divider - JPEG */
471 tmp = __raw_readl(EXYNOS4_CLKDIV_CAM1);
472
473 tmp &= ~(EXYNOS4_CLKDIV_CAM1_JPEG_MASK);
474
475 tmp |= ((exynos4x12_clkdiv_sclkip[index][1] <<
476 EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT));
477
478 __raw_writel(tmp, EXYNOS4_CLKDIV_CAM1);
479
480 do {
481 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_CAM1);
482 } while (tmp & 0x1);
483
484 /* Change Divider - FIMC0~3 */
485 tmp = __raw_readl(EXYNOS4_CLKDIV_CAM);
486
487 tmp &= ~(EXYNOS4_CLKDIV_CAM_FIMC0_MASK | EXYNOS4_CLKDIV_CAM_FIMC1_MASK |
488 EXYNOS4_CLKDIV_CAM_FIMC2_MASK | EXYNOS4_CLKDIV_CAM_FIMC3_MASK);
489
490 tmp |= ((exynos4x12_clkdiv_sclkip[index][2] <<
491 EXYNOS4_CLKDIV_CAM_FIMC0_SHIFT) |
492 (exynos4x12_clkdiv_sclkip[index][2] <<
493 EXYNOS4_CLKDIV_CAM_FIMC1_SHIFT) |
494 (exynos4x12_clkdiv_sclkip[index][2] <<
495 EXYNOS4_CLKDIV_CAM_FIMC2_SHIFT) |
496 (exynos4x12_clkdiv_sclkip[index][2] <<
497 EXYNOS4_CLKDIV_CAM_FIMC3_SHIFT));
498
499 __raw_writel(tmp, EXYNOS4_CLKDIV_CAM);
500
501 do {
502 tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_CAM1);
503 } while (tmp & 0x1111);
504
505 return 0;
506}
507
508static int exynos4x12_get_intspec(unsigned long mifclk)
509{
510 int i = 0;
511
512 while (exynos4x12_intclk_table[i].clk) {
513 if (exynos4x12_intclk_table[i].clk <= mifclk)
514 return i;
515 i++;
516 }
517
518 return -EINVAL;
519}
520
521static int exynos4_bus_setvolt(struct busfreq_data *data,
522 struct busfreq_opp_info *oppi,
523 struct busfreq_opp_info *oldoppi)
524{
525 int err = 0, tmp;
526 unsigned long volt = oppi->volt;
527
528 switch (data->type) {
529 case TYPE_BUSF_EXYNOS4210:
530 /* OPP represents DMC clock + INT voltage */
531 err = regulator_set_voltage(data->vdd_int, volt,
532 MAX_SAFEVOLT);
533 break;
534 case TYPE_BUSF_EXYNOS4x12:
535 /* OPP represents MIF clock + MIF voltage */
536 err = regulator_set_voltage(data->vdd_mif, volt,
537 MAX_SAFEVOLT);
538 if (err)
539 break;
540
541 tmp = exynos4x12_get_intspec(oppi->rate);
542 if (tmp < 0) {
543 err = tmp;
544 regulator_set_voltage(data->vdd_mif,
545 oldoppi->volt,
546 MAX_SAFEVOLT);
547 break;
548 }
549 err = regulator_set_voltage(data->vdd_int,
550 exynos4x12_intclk_table[tmp].volt,
551 MAX_SAFEVOLT);
552 /* Try to recover */
553 if (err)
554 regulator_set_voltage(data->vdd_mif,
555 oldoppi->volt,
556 MAX_SAFEVOLT);
557 break;
558 default:
559 err = -EINVAL;
560 }
561
562 return err;
563}
564
565static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
566 u32 flags)
567{
568 int err = 0;
569 struct platform_device *pdev = container_of(dev, struct platform_device,
570 dev);
571 struct busfreq_data *data = platform_get_drvdata(pdev);
572 struct dev_pm_opp *opp;
573 unsigned long freq;
574 unsigned long old_freq = data->curr_oppinfo.rate;
575 struct busfreq_opp_info new_oppinfo;
576
577 rcu_read_lock();
578 opp = devfreq_recommended_opp(dev, _freq, flags);
579 if (IS_ERR(opp)) {
580 rcu_read_unlock();
581 return PTR_ERR(opp);
582 }
583 new_oppinfo.rate = dev_pm_opp_get_freq(opp);
584 new_oppinfo.volt = dev_pm_opp_get_voltage(opp);
585 rcu_read_unlock();
586 freq = new_oppinfo.rate;
587
588 if (old_freq == freq)
589 return 0;
590
591 dev_dbg(dev, "targeting %lukHz %luuV\n", freq, new_oppinfo.volt);
592
593 mutex_lock(&data->lock);
594
595 if (data->disabled)
596 goto out;
597
598 if (old_freq < freq)
599 err = exynos4_bus_setvolt(data, &new_oppinfo,
600 &data->curr_oppinfo);
601 if (err)
602 goto out;
603
604 if (old_freq != freq) {
605 switch (data->type) {
606 case TYPE_BUSF_EXYNOS4210:
607 err = exynos4210_set_busclk(data, &new_oppinfo);
608 break;
609 case TYPE_BUSF_EXYNOS4x12:
610 err = exynos4x12_set_busclk(data, &new_oppinfo);
611 break;
612 default:
613 err = -EINVAL;
614 }
615 }
616 if (err)
617 goto out;
618
619 if (old_freq > freq)
620 err = exynos4_bus_setvolt(data, &new_oppinfo,
621 &data->curr_oppinfo);
622 if (err)
623 goto out;
624
625 data->curr_oppinfo = new_oppinfo;
626out:
627 mutex_unlock(&data->lock);
628 return err;
629}
630
631static int exynos4_bus_get_dev_status(struct device *dev,
632 struct devfreq_dev_status *stat)
633{
634 struct busfreq_data *data = dev_get_drvdata(dev);
635 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
636 int busier;
637
638 exynos_read_ppmu(ppmu_data);
639 busier = exynos_get_busier_ppmu(ppmu_data);
640 stat->current_frequency = data->curr_oppinfo.rate;
641
642 /* Number of cycles spent on memory access */
643 stat->busy_time = ppmu_data->ppmu[busier].count[PPMU_PMNCNT3];
644 stat->busy_time *= 100 / BUS_SATURATION_RATIO;
645 stat->total_time = ppmu_data->ppmu[busier].ccnt;
646
647 /* If the counters have overflown, retry */
648 if (ppmu_data->ppmu[busier].ccnt_overflow ||
649 ppmu_data->ppmu[busier].count_overflow[0])
650 return -EAGAIN;
651
652 return 0;
653}
654
655static struct devfreq_dev_profile exynos4_devfreq_profile = {
656 .initial_freq = 400000,
657 .polling_ms = 50,
658 .target = exynos4_bus_target,
659 .get_dev_status = exynos4_bus_get_dev_status,
660};
661
662static int exynos4210_init_tables(struct busfreq_data *data)
663{
664 u32 tmp;
665 int mgrp;
666 int i, err = 0;
667
668 tmp = __raw_readl(EXYNOS4_CLKDIV_DMC0);
669 for (i = LV_0; i < EX4210_LV_NUM; i++) {
670 tmp &= ~(EXYNOS4_CLKDIV_DMC0_ACP_MASK |
671 EXYNOS4_CLKDIV_DMC0_ACPPCLK_MASK |
672 EXYNOS4_CLKDIV_DMC0_DPHY_MASK |
673 EXYNOS4_CLKDIV_DMC0_DMC_MASK |
674 EXYNOS4_CLKDIV_DMC0_DMCD_MASK |
675 EXYNOS4_CLKDIV_DMC0_DMCP_MASK |
676 EXYNOS4_CLKDIV_DMC0_COPY2_MASK |
677 EXYNOS4_CLKDIV_DMC0_CORETI_MASK);
678
679 tmp |= ((exynos4210_clkdiv_dmc0[i][0] <<
680 EXYNOS4_CLKDIV_DMC0_ACP_SHIFT) |
681 (exynos4210_clkdiv_dmc0[i][1] <<
682 EXYNOS4_CLKDIV_DMC0_ACPPCLK_SHIFT) |
683 (exynos4210_clkdiv_dmc0[i][2] <<
684 EXYNOS4_CLKDIV_DMC0_DPHY_SHIFT) |
685 (exynos4210_clkdiv_dmc0[i][3] <<
686 EXYNOS4_CLKDIV_DMC0_DMC_SHIFT) |
687 (exynos4210_clkdiv_dmc0[i][4] <<
688 EXYNOS4_CLKDIV_DMC0_DMCD_SHIFT) |
689 (exynos4210_clkdiv_dmc0[i][5] <<
690 EXYNOS4_CLKDIV_DMC0_DMCP_SHIFT) |
691 (exynos4210_clkdiv_dmc0[i][6] <<
692 EXYNOS4_CLKDIV_DMC0_COPY2_SHIFT) |
693 (exynos4210_clkdiv_dmc0[i][7] <<
694 EXYNOS4_CLKDIV_DMC0_CORETI_SHIFT));
695
696 data->dmc_divtable[i] = tmp;
697 }
698
699 tmp = __raw_readl(EXYNOS4_CLKDIV_TOP);
700 for (i = LV_0; i < EX4210_LV_NUM; i++) {
701 tmp &= ~(EXYNOS4_CLKDIV_TOP_ACLK200_MASK |
702 EXYNOS4_CLKDIV_TOP_ACLK100_MASK |
703 EXYNOS4_CLKDIV_TOP_ACLK160_MASK |
704 EXYNOS4_CLKDIV_TOP_ACLK133_MASK |
705 EXYNOS4_CLKDIV_TOP_ONENAND_MASK);
706
707 tmp |= ((exynos4210_clkdiv_top[i][0] <<
708 EXYNOS4_CLKDIV_TOP_ACLK200_SHIFT) |
709 (exynos4210_clkdiv_top[i][1] <<
710 EXYNOS4_CLKDIV_TOP_ACLK100_SHIFT) |
711 (exynos4210_clkdiv_top[i][2] <<
712 EXYNOS4_CLKDIV_TOP_ACLK160_SHIFT) |
713 (exynos4210_clkdiv_top[i][3] <<
714 EXYNOS4_CLKDIV_TOP_ACLK133_SHIFT) |
715 (exynos4210_clkdiv_top[i][4] <<
716 EXYNOS4_CLKDIV_TOP_ONENAND_SHIFT));
717
718 data->top_divtable[i] = tmp;
719 }
720
721 /*
722 * TODO: init tmp based on busfreq_data
723 * (device-tree or platform-data)
724 */
725 tmp = 0; /* Max voltages for the reliability of the unknown */
726
727 pr_debug("ASV Group of Exynos4 is %d\n", tmp);
728 /* Use merged grouping for voltage */
729 switch (tmp) {
730 case 0:
731 mgrp = 0;
732 break;
733 case 1:
734 case 2:
735 mgrp = 1;
736 break;
737 case 3:
738 case 4:
739 mgrp = 2;
740 break;
741 case 5:
742 case 6:
743 mgrp = 3;
744 break;
745 case 7:
746 mgrp = 4;
747 break;
748 default:
749 pr_warn("Unknown ASV Group. Use max voltage.\n");
750 mgrp = 0;
751 }
752
753 for (i = LV_0; i < EX4210_LV_NUM; i++)
754 exynos4210_busclk_table[i].volt = exynos4210_asv_volt[mgrp][i];
755
756 for (i = LV_0; i < EX4210_LV_NUM; i++) {
757 err = dev_pm_opp_add(data->dev, exynos4210_busclk_table[i].clk,
758 exynos4210_busclk_table[i].volt);
759 if (err) {
760 dev_err(data->dev, "Cannot add opp entries.\n");
761 return err;
762 }
763 }
764
765
766 return 0;
767}
768
769static int exynos4x12_init_tables(struct busfreq_data *data)
770{
771 unsigned int i;
772 unsigned int tmp;
773 int ret;
774
775 /* Enable pause function for DREX2 DVFS */
776 tmp = __raw_readl(EXYNOS4_DMC_PAUSE_CTRL);
777 tmp |= EXYNOS4_DMC_PAUSE_ENABLE;
778 __raw_writel(tmp, EXYNOS4_DMC_PAUSE_CTRL);
779
780 tmp = __raw_readl(EXYNOS4_CLKDIV_DMC0);
781
782 for (i = 0; i < EX4x12_LV_NUM; i++) {
783 tmp &= ~(EXYNOS4_CLKDIV_DMC0_ACP_MASK |
784 EXYNOS4_CLKDIV_DMC0_ACPPCLK_MASK |
785 EXYNOS4_CLKDIV_DMC0_DPHY_MASK |
786 EXYNOS4_CLKDIV_DMC0_DMC_MASK |
787 EXYNOS4_CLKDIV_DMC0_DMCD_MASK |
788 EXYNOS4_CLKDIV_DMC0_DMCP_MASK);
789
790 tmp |= ((exynos4x12_clkdiv_dmc0[i][0] <<
791 EXYNOS4_CLKDIV_DMC0_ACP_SHIFT) |
792 (exynos4x12_clkdiv_dmc0[i][1] <<
793 EXYNOS4_CLKDIV_DMC0_ACPPCLK_SHIFT) |
794 (exynos4x12_clkdiv_dmc0[i][2] <<
795 EXYNOS4_CLKDIV_DMC0_DPHY_SHIFT) |
796 (exynos4x12_clkdiv_dmc0[i][3] <<
797 EXYNOS4_CLKDIV_DMC0_DMC_SHIFT) |
798 (exynos4x12_clkdiv_dmc0[i][4] <<
799 EXYNOS4_CLKDIV_DMC0_DMCD_SHIFT) |
800 (exynos4x12_clkdiv_dmc0[i][5] <<
801 EXYNOS4_CLKDIV_DMC0_DMCP_SHIFT));
802
803 data->dmc_divtable[i] = tmp;
804 }
805
806 tmp = 0; /* Max voltages for the reliability of the unknown */
807
808 if (tmp > 8)
809 tmp = 0;
810 pr_debug("ASV Group of Exynos4x12 is %d\n", tmp);
811
812 for (i = 0; i < EX4x12_LV_NUM; i++) {
813 exynos4x12_mifclk_table[i].volt =
814 exynos4x12_mif_step_50[tmp][i];
815 exynos4x12_intclk_table[i].volt =
816 exynos4x12_int_volt[tmp][i];
817 }
818
819 for (i = 0; i < EX4x12_LV_NUM; i++) {
820 ret = dev_pm_opp_add(data->dev, exynos4x12_mifclk_table[i].clk,
821 exynos4x12_mifclk_table[i].volt);
822 if (ret) {
823 dev_err(data->dev, "Fail to add opp entries.\n");
824 return ret;
825 }
826 }
827
828 return 0;
829}
830
831static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
832 unsigned long event, void *ptr)
833{
834 struct busfreq_data *data = container_of(this, struct busfreq_data,
835 pm_notifier);
836 struct dev_pm_opp *opp;
837 struct busfreq_opp_info new_oppinfo;
838 unsigned long maxfreq = ULONG_MAX;
839 int err = 0;
840
841 switch (event) {
842 case PM_SUSPEND_PREPARE:
843 /* Set Fastest and Deactivate DVFS */
844 mutex_lock(&data->lock);
845
846 data->disabled = true;
847
848 rcu_read_lock();
849 opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
850 if (IS_ERR(opp)) {
851 rcu_read_unlock();
852 dev_err(data->dev, "%s: unable to find a min freq\n",
853 __func__);
854 mutex_unlock(&data->lock);
855 return PTR_ERR(opp);
856 }
857 new_oppinfo.rate = dev_pm_opp_get_freq(opp);
858 new_oppinfo.volt = dev_pm_opp_get_voltage(opp);
859 rcu_read_unlock();
860
861 err = exynos4_bus_setvolt(data, &new_oppinfo,
862 &data->curr_oppinfo);
863 if (err)
864 goto unlock;
865
866 switch (data->type) {
867 case TYPE_BUSF_EXYNOS4210:
868 err = exynos4210_set_busclk(data, &new_oppinfo);
869 break;
870 case TYPE_BUSF_EXYNOS4x12:
871 err = exynos4x12_set_busclk(data, &new_oppinfo);
872 break;
873 default:
874 err = -EINVAL;
875 }
876 if (err)
877 goto unlock;
878
879 data->curr_oppinfo = new_oppinfo;
880unlock:
881 mutex_unlock(&data->lock);
882 if (err)
883 return err;
884 return NOTIFY_OK;
885 case PM_POST_RESTORE:
886 case PM_POST_SUSPEND:
887 /* Reactivate */
888 mutex_lock(&data->lock);
889 data->disabled = false;
890 mutex_unlock(&data->lock);
891 return NOTIFY_OK;
892 }
893
894 return NOTIFY_DONE;
895}
896
897static int exynos4_busfreq_probe(struct platform_device *pdev)
898{
899 struct busfreq_data *data;
900 struct busfreq_ppmu_data *ppmu_data;
901 struct dev_pm_opp *opp;
902 struct device *dev = &pdev->dev;
903 int err = 0;
904
905 data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data), GFP_KERNEL);
906 if (data == NULL) {
907 dev_err(dev, "Cannot allocate memory.\n");
908 return -ENOMEM;
909 }
910
911 ppmu_data = &data->ppmu_data;
912 ppmu_data->ppmu_end = PPMU_END;
913 ppmu_data->ppmu = devm_kzalloc(dev,
914 sizeof(struct exynos_ppmu) * PPMU_END,
915 GFP_KERNEL);
916 if (!ppmu_data->ppmu) {
917 dev_err(dev, "Failed to allocate memory for exynos_ppmu\n");
918 return -ENOMEM;
919 }
920
921 data->type = pdev->id_entry->driver_data;
922 ppmu_data->ppmu[PPMU_DMC0].hw_base = S5P_VA_DMC0;
923 ppmu_data->ppmu[PPMU_DMC1].hw_base = S5P_VA_DMC1;
924 data->pm_notifier.notifier_call = exynos4_busfreq_pm_notifier_event;
925 data->dev = dev;
926 mutex_init(&data->lock);
927
928 switch (data->type) {
929 case TYPE_BUSF_EXYNOS4210:
930 err = exynos4210_init_tables(data);
931 break;
932 case TYPE_BUSF_EXYNOS4x12:
933 err = exynos4x12_init_tables(data);
934 break;
935 default:
936 dev_err(dev, "Cannot determine the device id %d\n", data->type);
937 err = -EINVAL;
938 }
939 if (err) {
940 dev_err(dev, "Cannot initialize busfreq table %d\n",
941 data->type);
942 return err;
943 }
944
945 data->vdd_int = devm_regulator_get(dev, "vdd_int");
946 if (IS_ERR(data->vdd_int)) {
947 dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
948 return PTR_ERR(data->vdd_int);
949 }
950 if (data->type == TYPE_BUSF_EXYNOS4x12) {
951 data->vdd_mif = devm_regulator_get(dev, "vdd_mif");
952 if (IS_ERR(data->vdd_mif)) {
953 dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n");
954 return PTR_ERR(data->vdd_mif);
955 }
956 }
957
958 rcu_read_lock();
959 opp = dev_pm_opp_find_freq_floor(dev,
960 &exynos4_devfreq_profile.initial_freq);
961 if (IS_ERR(opp)) {
962 rcu_read_unlock();
963 dev_err(dev, "Invalid initial frequency %lu kHz.\n",
964 exynos4_devfreq_profile.initial_freq);
965 return PTR_ERR(opp);
966 }
967 data->curr_oppinfo.rate = dev_pm_opp_get_freq(opp);
968 data->curr_oppinfo.volt = dev_pm_opp_get_voltage(opp);
969 rcu_read_unlock();
970
971 platform_set_drvdata(pdev, data);
972
973 data->devfreq = devm_devfreq_add_device(dev, &exynos4_devfreq_profile,
974 "simple_ondemand", NULL);
975 if (IS_ERR(data->devfreq))
976 return PTR_ERR(data->devfreq);
977
978 /*
979 * Start PPMU (Performance Profiling Monitoring Unit) to check
980 * utilization of each IP in the Exynos4 SoC.
981 */
982 busfreq_mon_reset(ppmu_data);
983
984 /* Register opp_notifier for Exynos4 busfreq */
985 err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
986 if (err < 0) {
987 dev_err(dev, "Failed to register opp notifier\n");
988 return err;
989 }
990
991 /* Register pm_notifier for Exynos4 busfreq */
992 err = register_pm_notifier(&data->pm_notifier);
993 if (err) {
994 dev_err(dev, "Failed to setup pm notifier\n");
995 return err;
996 }
997
998 return 0;
999}
1000
1001static int exynos4_busfreq_remove(struct platform_device *pdev)
1002{
1003 struct busfreq_data *data = platform_get_drvdata(pdev);
1004
1005 /* Unregister all of notifier chain */
1006 unregister_pm_notifier(&data->pm_notifier);
1007
1008 return 0;
1009}
1010
1011#ifdef CONFIG_PM_SLEEP
1012static int exynos4_busfreq_resume(struct device *dev)
1013{
1014 struct busfreq_data *data = dev_get_drvdata(dev);
1015 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
1016
1017 busfreq_mon_reset(ppmu_data);
1018 return 0;
1019}
1020#endif
1021
1022static SIMPLE_DEV_PM_OPS(exynos4_busfreq_pm_ops, NULL, exynos4_busfreq_resume);
1023
1024static const struct platform_device_id exynos4_busfreq_id[] = {
1025 { "exynos4210-busfreq", TYPE_BUSF_EXYNOS4210 },
1026 { "exynos4412-busfreq", TYPE_BUSF_EXYNOS4x12 },
1027 { "exynos4212-busfreq", TYPE_BUSF_EXYNOS4x12 },
1028 { },
1029};
1030
1031static struct platform_driver exynos4_busfreq_driver = {
1032 .probe = exynos4_busfreq_probe,
1033 .remove = exynos4_busfreq_remove,
1034 .id_table = exynos4_busfreq_id,
1035 .driver = {
1036 .name = "exynos4-busfreq",
1037 .pm = &exynos4_busfreq_pm_ops,
1038 },
1039};
1040
1041static int __init exynos4_busfreq_init(void)
1042{
1043 return platform_driver_register(&exynos4_busfreq_driver);
1044}
1045late_initcall(exynos4_busfreq_init);
1046
1047static void __exit exynos4_busfreq_exit(void)
1048{
1049 platform_driver_unregister(&exynos4_busfreq_driver);
1050}
1051module_exit(exynos4_busfreq_exit);
1052
1053MODULE_LICENSE("GPL");
1054MODULE_DESCRIPTION("EXYNOS4 busfreq driver with devfreq framework");
1055MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff --git a/drivers/devfreq/exynos/exynos4_bus.h b/drivers/devfreq/exynos/exynos4_bus.h
deleted file mode 100644
index 94c73c18d28c..000000000000
--- a/drivers/devfreq/exynos/exynos4_bus.h
+++ /dev/null
@@ -1,110 +0,0 @@
1/*
2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
4 *
5 * EXYNOS4 BUS header
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#ifndef __DEVFREQ_EXYNOS4_BUS_H
13#define __DEVFREQ_EXYNOS4_BUS_H __FILE__
14
15#include <mach/map.h>
16
17#define EXYNOS4_CLKDIV_LEFTBUS (S5P_VA_CMU + 0x04500)
18#define EXYNOS4_CLKDIV_STAT_LEFTBUS (S5P_VA_CMU + 0x04600)
19
20#define EXYNOS4_CLKDIV_RIGHTBUS (S5P_VA_CMU + 0x08500)
21#define EXYNOS4_CLKDIV_STAT_RIGHTBUS (S5P_VA_CMU + 0x08600)
22
23#define EXYNOS4_CLKDIV_TOP (S5P_VA_CMU + 0x0C510)
24#define EXYNOS4_CLKDIV_CAM (S5P_VA_CMU + 0x0C520)
25#define EXYNOS4_CLKDIV_MFC (S5P_VA_CMU + 0x0C528)
26
27#define EXYNOS4_CLKDIV_STAT_TOP (S5P_VA_CMU + 0x0C610)
28#define EXYNOS4_CLKDIV_STAT_MFC (S5P_VA_CMU + 0x0C628)
29
30#define EXYNOS4210_CLKGATE_IP_IMAGE (S5P_VA_CMU + 0x0C930)
31#define EXYNOS4212_CLKGATE_IP_IMAGE (S5P_VA_CMU + 0x04930)
32
33#define EXYNOS4_CLKDIV_DMC0 (S5P_VA_CMU + 0x10500)
34#define EXYNOS4_CLKDIV_DMC1 (S5P_VA_CMU + 0x10504)
35#define EXYNOS4_CLKDIV_STAT_DMC0 (S5P_VA_CMU + 0x10600)
36#define EXYNOS4_CLKDIV_STAT_DMC1 (S5P_VA_CMU + 0x10604)
37
38#define EXYNOS4_DMC_PAUSE_CTRL (S5P_VA_CMU + 0x11094)
39#define EXYNOS4_DMC_PAUSE_ENABLE (1 << 0)
40
41#define EXYNOS4_CLKDIV_DMC0_ACP_SHIFT (0)
42#define EXYNOS4_CLKDIV_DMC0_ACP_MASK (0x7 << EXYNOS4_CLKDIV_DMC0_ACP_SHIFT)
43#define EXYNOS4_CLKDIV_DMC0_ACPPCLK_SHIFT (4)
44#define EXYNOS4_CLKDIV_DMC0_ACPPCLK_MASK (0x7 << EXYNOS4_CLKDIV_DMC0_ACPPCLK_SHIFT)
45#define EXYNOS4_CLKDIV_DMC0_DPHY_SHIFT (8)
46#define EXYNOS4_CLKDIV_DMC0_DPHY_MASK (0x7 << EXYNOS4_CLKDIV_DMC0_DPHY_SHIFT)
47#define EXYNOS4_CLKDIV_DMC0_DMC_SHIFT (12)
48#define EXYNOS4_CLKDIV_DMC0_DMC_MASK (0x7 << EXYNOS4_CLKDIV_DMC0_DMC_SHIFT)
49#define EXYNOS4_CLKDIV_DMC0_DMCD_SHIFT (16)
50#define EXYNOS4_CLKDIV_DMC0_DMCD_MASK (0x7 << EXYNOS4_CLKDIV_DMC0_DMCD_SHIFT)
51#define EXYNOS4_CLKDIV_DMC0_DMCP_SHIFT (20)
52#define EXYNOS4_CLKDIV_DMC0_DMCP_MASK (0x7 << EXYNOS4_CLKDIV_DMC0_DMCP_SHIFT)
53#define EXYNOS4_CLKDIV_DMC0_COPY2_SHIFT (24)
54#define EXYNOS4_CLKDIV_DMC0_COPY2_MASK (0x7 << EXYNOS4_CLKDIV_DMC0_COPY2_SHIFT)
55#define EXYNOS4_CLKDIV_DMC0_CORETI_SHIFT (28)
56#define EXYNOS4_CLKDIV_DMC0_CORETI_MASK (0x7 << EXYNOS4_CLKDIV_DMC0_CORETI_SHIFT)
57
58#define EXYNOS4_CLKDIV_DMC1_G2D_ACP_SHIFT (0)
59#define EXYNOS4_CLKDIV_DMC1_G2D_ACP_MASK (0xf << EXYNOS4_CLKDIV_DMC1_G2D_ACP_SHIFT)
60#define EXYNOS4_CLKDIV_DMC1_C2C_SHIFT (4)
61#define EXYNOS4_CLKDIV_DMC1_C2C_MASK (0x7 << EXYNOS4_CLKDIV_DMC1_C2C_SHIFT)
62#define EXYNOS4_CLKDIV_DMC1_PWI_SHIFT (8)
63#define EXYNOS4_CLKDIV_DMC1_PWI_MASK (0xf << EXYNOS4_CLKDIV_DMC1_PWI_SHIFT)
64#define EXYNOS4_CLKDIV_DMC1_C2CACLK_SHIFT (12)
65#define EXYNOS4_CLKDIV_DMC1_C2CACLK_MASK (0x7 << EXYNOS4_CLKDIV_DMC1_C2CACLK_SHIFT)
66#define EXYNOS4_CLKDIV_DMC1_DVSEM_SHIFT (16)
67#define EXYNOS4_CLKDIV_DMC1_DVSEM_MASK (0x7f << EXYNOS4_CLKDIV_DMC1_DVSEM_SHIFT)
68#define EXYNOS4_CLKDIV_DMC1_DPM_SHIFT (24)
69#define EXYNOS4_CLKDIV_DMC1_DPM_MASK (0x7f << EXYNOS4_CLKDIV_DMC1_DPM_SHIFT)
70
71#define EXYNOS4_CLKDIV_MFC_SHIFT (0)
72#define EXYNOS4_CLKDIV_MFC_MASK (0x7 << EXYNOS4_CLKDIV_MFC_SHIFT)
73
74#define EXYNOS4_CLKDIV_TOP_ACLK200_SHIFT (0)
75#define EXYNOS4_CLKDIV_TOP_ACLK200_MASK (0x7 << EXYNOS4_CLKDIV_TOP_ACLK200_SHIFT)
76#define EXYNOS4_CLKDIV_TOP_ACLK100_SHIFT (4)
77#define EXYNOS4_CLKDIV_TOP_ACLK100_MASK (0xF << EXYNOS4_CLKDIV_TOP_ACLK100_SHIFT)
78#define EXYNOS4_CLKDIV_TOP_ACLK160_SHIFT (8)
79#define EXYNOS4_CLKDIV_TOP_ACLK160_MASK (0x7 << EXYNOS4_CLKDIV_TOP_ACLK160_SHIFT)
80#define EXYNOS4_CLKDIV_TOP_ACLK133_SHIFT (12)
81#define EXYNOS4_CLKDIV_TOP_ACLK133_MASK (0x7 << EXYNOS4_CLKDIV_TOP_ACLK133_SHIFT)
82#define EXYNOS4_CLKDIV_TOP_ONENAND_SHIFT (16)
83#define EXYNOS4_CLKDIV_TOP_ONENAND_MASK (0x7 << EXYNOS4_CLKDIV_TOP_ONENAND_SHIFT)
84#define EXYNOS4_CLKDIV_TOP_ACLK266_GPS_SHIFT (20)
85#define EXYNOS4_CLKDIV_TOP_ACLK266_GPS_MASK (0x7 << EXYNOS4_CLKDIV_TOP_ACLK266_GPS_SHIFT)
86#define EXYNOS4_CLKDIV_TOP_ACLK400_MCUISP_SHIFT (24)
87#define EXYNOS4_CLKDIV_TOP_ACLK400_MCUISP_MASK (0x7 << EXYNOS4_CLKDIV_TOP_ACLK400_MCUISP_SHIFT)
88
89#define EXYNOS4_CLKDIV_BUS_GDLR_SHIFT (0)
90#define EXYNOS4_CLKDIV_BUS_GDLR_MASK (0x7 << EXYNOS4_CLKDIV_BUS_GDLR_SHIFT)
91#define EXYNOS4_CLKDIV_BUS_GPLR_SHIFT (4)
92#define EXYNOS4_CLKDIV_BUS_GPLR_MASK (0x7 << EXYNOS4_CLKDIV_BUS_GPLR_SHIFT)
93
94#define EXYNOS4_CLKDIV_CAM_FIMC0_SHIFT (0)
95#define EXYNOS4_CLKDIV_CAM_FIMC0_MASK (0xf << EXYNOS4_CLKDIV_CAM_FIMC0_SHIFT)
96#define EXYNOS4_CLKDIV_CAM_FIMC1_SHIFT (4)
97#define EXYNOS4_CLKDIV_CAM_FIMC1_MASK (0xf << EXYNOS4_CLKDIV_CAM_FIMC1_SHIFT)
98#define EXYNOS4_CLKDIV_CAM_FIMC2_SHIFT (8)
99#define EXYNOS4_CLKDIV_CAM_FIMC2_MASK (0xf << EXYNOS4_CLKDIV_CAM_FIMC2_SHIFT)
100#define EXYNOS4_CLKDIV_CAM_FIMC3_SHIFT (12)
101#define EXYNOS4_CLKDIV_CAM_FIMC3_MASK (0xf << EXYNOS4_CLKDIV_CAM_FIMC3_SHIFT)
102
103#define EXYNOS4_CLKDIV_CAM1 (S5P_VA_CMU + 0x0C568)
104
105#define EXYNOS4_CLKDIV_STAT_CAM1 (S5P_VA_CMU + 0x0C668)
106
107#define EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT (0)
108#define EXYNOS4_CLKDIV_CAM1_JPEG_MASK (0xf << EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT)
109
110#endif /* __DEVFREQ_EXYNOS4_BUS_H */
diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c
deleted file mode 100644
index 297ea30d4159..000000000000
--- a/drivers/devfreq/exynos/exynos5_bus.c
+++ /dev/null
@@ -1,431 +0,0 @@
1/*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
4 *
5 * EXYNOS5 INT clock frequency scaling support using DEVFREQ framework
6 * Based on work done by Jonghwan Choi <jhbird.choi@samsung.com>
7 * Support for only EXYNOS5250 is present.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/devfreq.h>
17#include <linux/io.h>
18#include <linux/pm_opp.h>
19#include <linux/slab.h>
20#include <linux/suspend.h>
21#include <linux/clk.h>
22#include <linux/delay.h>
23#include <linux/platform_device.h>
24#include <linux/pm_qos.h>
25#include <linux/regulator/consumer.h>
26#include <linux/of_address.h>
27#include <linux/of_platform.h>
28
29#include "exynos_ppmu.h"
30
31#define MAX_SAFEVOLT 1100000 /* 1.10V */
32/* Assume that the bus is saturated if the utilization is 25% */
33#define INT_BUS_SATURATION_RATIO 25
34
35enum int_level_idx {
36 LV_0,
37 LV_1,
38 LV_2,
39 LV_3,
40 LV_4,
41 _LV_END
42};
43
44enum exynos_ppmu_list {
45 PPMU_RIGHT,
46 PPMU_END,
47};
48
49struct busfreq_data_int {
50 struct device *dev;
51 struct devfreq *devfreq;
52 struct regulator *vdd_int;
53 struct busfreq_ppmu_data ppmu_data;
54 unsigned long curr_freq;
55 bool disabled;
56
57 struct notifier_block pm_notifier;
58 struct mutex lock;
59 struct pm_qos_request int_req;
60 struct clk *int_clk;
61};
62
63struct int_bus_opp_table {
64 unsigned int idx;
65 unsigned long clk;
66 unsigned long volt;
67};
68
69static struct int_bus_opp_table exynos5_int_opp_table[] = {
70 {LV_0, 266000, 1025000},
71 {LV_1, 200000, 1025000},
72 {LV_2, 160000, 1025000},
73 {LV_3, 133000, 1025000},
74 {LV_4, 100000, 1025000},
75 {0, 0, 0},
76};
77
78static int exynos5_int_setvolt(struct busfreq_data_int *data,
79 unsigned long volt)
80{
81 return regulator_set_voltage(data->vdd_int, volt, MAX_SAFEVOLT);
82}
83
84static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
85 u32 flags)
86{
87 int err = 0;
88 struct platform_device *pdev = container_of(dev, struct platform_device,
89 dev);
90 struct busfreq_data_int *data = platform_get_drvdata(pdev);
91 struct dev_pm_opp *opp;
92 unsigned long old_freq, freq;
93 unsigned long volt;
94
95 rcu_read_lock();
96 opp = devfreq_recommended_opp(dev, _freq, flags);
97 if (IS_ERR(opp)) {
98 rcu_read_unlock();
99 dev_err(dev, "%s: Invalid OPP.\n", __func__);
100 return PTR_ERR(opp);
101 }
102
103 freq = dev_pm_opp_get_freq(opp);
104 volt = dev_pm_opp_get_voltage(opp);
105 rcu_read_unlock();
106
107 old_freq = data->curr_freq;
108
109 if (old_freq == freq)
110 return 0;
111
112 dev_dbg(dev, "targeting %lukHz %luuV\n", freq, volt);
113
114 mutex_lock(&data->lock);
115
116 if (data->disabled)
117 goto out;
118
119 if (freq > exynos5_int_opp_table[0].clk)
120 pm_qos_update_request(&data->int_req, freq * 16 / 1000);
121 else
122 pm_qos_update_request(&data->int_req, -1);
123
124 if (old_freq < freq)
125 err = exynos5_int_setvolt(data, volt);
126 if (err)
127 goto out;
128
129 err = clk_set_rate(data->int_clk, freq * 1000);
130
131 if (err)
132 goto out;
133
134 if (old_freq > freq)
135 err = exynos5_int_setvolt(data, volt);
136 if (err)
137 goto out;
138
139 data->curr_freq = freq;
140out:
141 mutex_unlock(&data->lock);
142 return err;
143}
144
145static int exynos5_int_get_dev_status(struct device *dev,
146 struct devfreq_dev_status *stat)
147{
148 struct platform_device *pdev = container_of(dev, struct platform_device,
149 dev);
150 struct busfreq_data_int *data = platform_get_drvdata(pdev);
151 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
152 int busier_dmc;
153
154 exynos_read_ppmu(ppmu_data);
155 busier_dmc = exynos_get_busier_ppmu(ppmu_data);
156
157 stat->current_frequency = data->curr_freq;
158
159 /* Number of cycles spent on memory access */
160 stat->busy_time = ppmu_data->ppmu[busier_dmc].count[PPMU_PMNCNT3];
161 stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO;
162 stat->total_time = ppmu_data->ppmu[busier_dmc].ccnt;
163
164 return 0;
165}
166
167static struct devfreq_dev_profile exynos5_devfreq_int_profile = {
168 .initial_freq = 160000,
169 .polling_ms = 100,
170 .target = exynos5_busfreq_int_target,
171 .get_dev_status = exynos5_int_get_dev_status,
172};
173
174static int exynos5250_init_int_tables(struct busfreq_data_int *data)
175{
176 int i, err = 0;
177
178 for (i = LV_0; i < _LV_END; i++) {
179 err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
180 exynos5_int_opp_table[i].volt);
181 if (err) {
182 dev_err(data->dev, "Cannot add opp entries.\n");
183 return err;
184 }
185 }
186
187 return 0;
188}
189
190static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
191 unsigned long event, void *ptr)
192{
193 struct busfreq_data_int *data = container_of(this,
194 struct busfreq_data_int, pm_notifier);
195 struct dev_pm_opp *opp;
196 unsigned long maxfreq = ULONG_MAX;
197 unsigned long freq;
198 unsigned long volt;
199 int err = 0;
200
201 switch (event) {
202 case PM_SUSPEND_PREPARE:
203 /* Set Fastest and Deactivate DVFS */
204 mutex_lock(&data->lock);
205
206 data->disabled = true;
207
208 rcu_read_lock();
209 opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
210 if (IS_ERR(opp)) {
211 rcu_read_unlock();
212 err = PTR_ERR(opp);
213 goto unlock;
214 }
215 freq = dev_pm_opp_get_freq(opp);
216 volt = dev_pm_opp_get_voltage(opp);
217 rcu_read_unlock();
218
219 err = exynos5_int_setvolt(data, volt);
220 if (err)
221 goto unlock;
222
223 err = clk_set_rate(data->int_clk, freq * 1000);
224
225 if (err)
226 goto unlock;
227
228 data->curr_freq = freq;
229unlock:
230 mutex_unlock(&data->lock);
231 if (err)
232 return NOTIFY_BAD;
233 return NOTIFY_OK;
234 case PM_POST_RESTORE:
235 case PM_POST_SUSPEND:
236 /* Reactivate */
237 mutex_lock(&data->lock);
238 data->disabled = false;
239 mutex_unlock(&data->lock);
240 return NOTIFY_OK;
241 }
242
243 return NOTIFY_DONE;
244}
245
246static int exynos5_busfreq_int_probe(struct platform_device *pdev)
247{
248 struct busfreq_data_int *data;
249 struct busfreq_ppmu_data *ppmu_data;
250 struct dev_pm_opp *opp;
251 struct device *dev = &pdev->dev;
252 struct device_node *np;
253 unsigned long initial_freq;
254 unsigned long initial_volt;
255 int err = 0;
256 int i;
257
258 data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data_int),
259 GFP_KERNEL);
260 if (data == NULL) {
261 dev_err(dev, "Cannot allocate memory.\n");
262 return -ENOMEM;
263 }
264
265 ppmu_data = &data->ppmu_data;
266 ppmu_data->ppmu_end = PPMU_END;
267 ppmu_data->ppmu = devm_kzalloc(dev,
268 sizeof(struct exynos_ppmu) * PPMU_END,
269 GFP_KERNEL);
270 if (!ppmu_data->ppmu) {
271 dev_err(dev, "Failed to allocate memory for exynos_ppmu\n");
272 return -ENOMEM;
273 }
274
275 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu");
276 if (np == NULL) {
277 pr_err("Unable to find PPMU node\n");
278 return -ENOENT;
279 }
280
281 for (i = 0; i < ppmu_data->ppmu_end; i++) {
282 /* map PPMU memory region */
283 ppmu_data->ppmu[i].hw_base = of_iomap(np, i);
284 if (ppmu_data->ppmu[i].hw_base == NULL) {
285 dev_err(&pdev->dev, "failed to map memory region\n");
286 return -ENOMEM;
287 }
288 }
289 data->pm_notifier.notifier_call = exynos5_busfreq_int_pm_notifier_event;
290 data->dev = dev;
291 mutex_init(&data->lock);
292
293 err = exynos5250_init_int_tables(data);
294 if (err)
295 return err;
296
297 data->vdd_int = devm_regulator_get(dev, "vdd_int");
298 if (IS_ERR(data->vdd_int)) {
299 dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
300 return PTR_ERR(data->vdd_int);
301 }
302
303 data->int_clk = devm_clk_get(dev, "int_clk");
304 if (IS_ERR(data->int_clk)) {
305 dev_err(dev, "Cannot get clock \"int_clk\"\n");
306 return PTR_ERR(data->int_clk);
307 }
308
309 rcu_read_lock();
310 opp = dev_pm_opp_find_freq_floor(dev,
311 &exynos5_devfreq_int_profile.initial_freq);
312 if (IS_ERR(opp)) {
313 rcu_read_unlock();
314 dev_err(dev, "Invalid initial frequency %lu kHz.\n",
315 exynos5_devfreq_int_profile.initial_freq);
316 return PTR_ERR(opp);
317 }
318 initial_freq = dev_pm_opp_get_freq(opp);
319 initial_volt = dev_pm_opp_get_voltage(opp);
320 rcu_read_unlock();
321 data->curr_freq = initial_freq;
322
323 err = clk_set_rate(data->int_clk, initial_freq * 1000);
324 if (err) {
325 dev_err(dev, "Failed to set initial frequency\n");
326 return err;
327 }
328
329 err = exynos5_int_setvolt(data, initial_volt);
330 if (err)
331 return err;
332
333 platform_set_drvdata(pdev, data);
334
335 busfreq_mon_reset(ppmu_data);
336
337 data->devfreq = devm_devfreq_add_device(dev, &exynos5_devfreq_int_profile,
338 "simple_ondemand", NULL);
339 if (IS_ERR(data->devfreq))
340 return PTR_ERR(data->devfreq);
341
342 err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
343 if (err < 0) {
344 dev_err(dev, "Failed to register opp notifier\n");
345 return err;
346 }
347
348 err = register_pm_notifier(&data->pm_notifier);
349 if (err) {
350 dev_err(dev, "Failed to setup pm notifier\n");
351 return err;
352 }
353
354 /* TODO: Add a new QOS class for int/mif bus */
355 pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1);
356
357 return 0;
358}
359
360static int exynos5_busfreq_int_remove(struct platform_device *pdev)
361{
362 struct busfreq_data_int *data = platform_get_drvdata(pdev);
363
364 pm_qos_remove_request(&data->int_req);
365 unregister_pm_notifier(&data->pm_notifier);
366
367 return 0;
368}
369
370#ifdef CONFIG_PM_SLEEP
371static int exynos5_busfreq_int_resume(struct device *dev)
372{
373 struct platform_device *pdev = container_of(dev, struct platform_device,
374 dev);
375 struct busfreq_data_int *data = platform_get_drvdata(pdev);
376 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
377
378 busfreq_mon_reset(ppmu_data);
379 return 0;
380}
381static const struct dev_pm_ops exynos5_busfreq_int_pm = {
382 .resume = exynos5_busfreq_int_resume,
383};
384#endif
385static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops, NULL,
386 exynos5_busfreq_int_resume);
387
388/* platform device pointer for exynos5 devfreq device. */
389static struct platform_device *exynos5_devfreq_pdev;
390
391static struct platform_driver exynos5_busfreq_int_driver = {
392 .probe = exynos5_busfreq_int_probe,
393 .remove = exynos5_busfreq_int_remove,
394 .driver = {
395 .name = "exynos5-bus-int",
396 .pm = &exynos5_busfreq_int_pm_ops,
397 },
398};
399
400static int __init exynos5_busfreq_int_init(void)
401{
402 int ret;
403
404 ret = platform_driver_register(&exynos5_busfreq_int_driver);
405 if (ret < 0)
406 goto out;
407
408 exynos5_devfreq_pdev =
409 platform_device_register_simple("exynos5-bus-int", -1, NULL, 0);
410 if (IS_ERR(exynos5_devfreq_pdev)) {
411 ret = PTR_ERR(exynos5_devfreq_pdev);
412 goto out1;
413 }
414
415 return 0;
416out1:
417 platform_driver_unregister(&exynos5_busfreq_int_driver);
418out:
419 return ret;
420}
421late_initcall(exynos5_busfreq_int_init);
422
423static void __exit exynos5_busfreq_int_exit(void)
424{
425 platform_device_unregister(exynos5_devfreq_pdev);
426 platform_driver_unregister(&exynos5_busfreq_int_driver);
427}
428module_exit(exynos5_busfreq_int_exit);
429
430MODULE_LICENSE("GPL");
431MODULE_DESCRIPTION("EXYNOS5 busfreq driver with devfreq framework");
diff --git a/drivers/devfreq/exynos/exynos_ppmu.c b/drivers/devfreq/exynos/exynos_ppmu.c
deleted file mode 100644
index 97b75e513d29..000000000000
--- a/drivers/devfreq/exynos/exynos_ppmu.c
+++ /dev/null
@@ -1,119 +0,0 @@
1/*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
4 *
5 * EXYNOS - PPMU support
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/io.h>
15
16#include "exynos_ppmu.h"
17
18void exynos_ppmu_reset(void __iomem *ppmu_base)
19{
20 __raw_writel(PPMU_CYCLE_RESET | PPMU_COUNTER_RESET, ppmu_base);
21 __raw_writel(PPMU_ENABLE_CYCLE |
22 PPMU_ENABLE_COUNT0 |
23 PPMU_ENABLE_COUNT1 |
24 PPMU_ENABLE_COUNT2 |
25 PPMU_ENABLE_COUNT3,
26 ppmu_base + PPMU_CNTENS);
27}
28
29void exynos_ppmu_setevent(void __iomem *ppmu_base, unsigned int ch,
30 unsigned int evt)
31{
32 __raw_writel(evt, ppmu_base + PPMU_BEVTSEL(ch));
33}
34
35void exynos_ppmu_start(void __iomem *ppmu_base)
36{
37 __raw_writel(PPMU_ENABLE, ppmu_base);
38}
39
40void exynos_ppmu_stop(void __iomem *ppmu_base)
41{
42 __raw_writel(PPMU_DISABLE, ppmu_base);
43}
44
45unsigned int exynos_ppmu_read(void __iomem *ppmu_base, unsigned int ch)
46{
47 unsigned int total;
48
49 if (ch == PPMU_PMNCNT3)
50 total = ((__raw_readl(ppmu_base + PMCNT_OFFSET(ch)) << 8) |
51 __raw_readl(ppmu_base + PMCNT_OFFSET(ch + 1)));
52 else
53 total = __raw_readl(ppmu_base + PMCNT_OFFSET(ch));
54
55 return total;
56}
57
58void busfreq_mon_reset(struct busfreq_ppmu_data *ppmu_data)
59{
60 unsigned int i;
61
62 for (i = 0; i < ppmu_data->ppmu_end; i++) {
63 void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base;
64
65 /* Reset the performance and cycle counters */
66 exynos_ppmu_reset(ppmu_base);
67
68 /* Setup count registers to monitor read/write transactions */
69 ppmu_data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT;
70 exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3,
71 ppmu_data->ppmu[i].event[PPMU_PMNCNT3]);
72
73 exynos_ppmu_start(ppmu_base);
74 }
75}
76EXPORT_SYMBOL(busfreq_mon_reset);
77
78void exynos_read_ppmu(struct busfreq_ppmu_data *ppmu_data)
79{
80 int i, j;
81
82 for (i = 0; i < ppmu_data->ppmu_end; i++) {
83 void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base;
84
85 exynos_ppmu_stop(ppmu_base);
86
87 /* Update local data from PPMU */
88 ppmu_data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT);
89
90 for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
91 if (ppmu_data->ppmu[i].event[j] == 0)
92 ppmu_data->ppmu[i].count[j] = 0;
93 else
94 ppmu_data->ppmu[i].count[j] =
95 exynos_ppmu_read(ppmu_base, j);
96 }
97 }
98
99 busfreq_mon_reset(ppmu_data);
100}
101EXPORT_SYMBOL(exynos_read_ppmu);
102
103int exynos_get_busier_ppmu(struct busfreq_ppmu_data *ppmu_data)
104{
105 unsigned int count = 0;
106 int i, j, busy = 0;
107
108 for (i = 0; i < ppmu_data->ppmu_end; i++) {
109 for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
110 if (ppmu_data->ppmu[i].count[j] > count) {
111 count = ppmu_data->ppmu[i].count[j];
112 busy = i;
113 }
114 }
115 }
116
117 return busy;
118}
119EXPORT_SYMBOL(exynos_get_busier_ppmu);
diff --git a/drivers/devfreq/exynos/exynos_ppmu.h b/drivers/devfreq/exynos/exynos_ppmu.h
deleted file mode 100644
index 71f17ba3563c..000000000000
--- a/drivers/devfreq/exynos/exynos_ppmu.h
+++ /dev/null
@@ -1,86 +0,0 @@
1/*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
4 *
5 * EXYNOS PPMU header
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10*/
11
12#ifndef __DEVFREQ_EXYNOS_PPMU_H
13#define __DEVFREQ_EXYNOS_PPMU_H __FILE__
14
15#include <linux/ktime.h>
16
17/* For PPMU Control */
18#define PPMU_ENABLE BIT(0)
19#define PPMU_DISABLE 0x0
20#define PPMU_CYCLE_RESET BIT(1)
21#define PPMU_COUNTER_RESET BIT(2)
22
23#define PPMU_ENABLE_COUNT0 BIT(0)
24#define PPMU_ENABLE_COUNT1 BIT(1)
25#define PPMU_ENABLE_COUNT2 BIT(2)
26#define PPMU_ENABLE_COUNT3 BIT(3)
27#define PPMU_ENABLE_CYCLE BIT(31)
28
29#define PPMU_CNTENS 0x10
30#define PPMU_FLAG 0x50
31#define PPMU_CCNT_OVERFLOW BIT(31)
32#define PPMU_CCNT 0x100
33
34#define PPMU_PMCNT0 0x110
35#define PPMU_PMCNT_OFFSET 0x10
36#define PMCNT_OFFSET(x) (PPMU_PMCNT0 + (PPMU_PMCNT_OFFSET * x))
37
38#define PPMU_BEVT0SEL 0x1000
39#define PPMU_BEVTSEL_OFFSET 0x100
40#define PPMU_BEVTSEL(x) (PPMU_BEVT0SEL + (ch * PPMU_BEVTSEL_OFFSET))
41
42/* For Event Selection */
43#define RD_DATA_COUNT 0x5
44#define WR_DATA_COUNT 0x6
45#define RDWR_DATA_COUNT 0x7
46
47enum ppmu_counter {
48 PPMU_PMNCNT0,
49 PPMU_PMCCNT1,
50 PPMU_PMNCNT2,
51 PPMU_PMNCNT3,
52 PPMU_PMNCNT_MAX,
53};
54
55struct bus_opp_table {
56 unsigned int idx;
57 unsigned long clk;
58 unsigned long volt;
59};
60
61struct exynos_ppmu {
62 void __iomem *hw_base;
63 unsigned int ccnt;
64 unsigned int event[PPMU_PMNCNT_MAX];
65 unsigned int count[PPMU_PMNCNT_MAX];
66 unsigned long long ns;
67 ktime_t reset_time;
68 bool ccnt_overflow;
69 bool count_overflow[PPMU_PMNCNT_MAX];
70};
71
72struct busfreq_ppmu_data {
73 struct exynos_ppmu *ppmu;
74 int ppmu_end;
75};
76
77void exynos_ppmu_reset(void __iomem *ppmu_base);
78void exynos_ppmu_setevent(void __iomem *ppmu_base, unsigned int ch,
79 unsigned int evt);
80void exynos_ppmu_start(void __iomem *ppmu_base);
81void exynos_ppmu_stop(void __iomem *ppmu_base);
82unsigned int exynos_ppmu_read(void __iomem *ppmu_base, unsigned int ch);
83void busfreq_mon_reset(struct busfreq_ppmu_data *ppmu_data);
84void exynos_read_ppmu(struct busfreq_ppmu_data *ppmu_data);
85int exynos_get_busier_ppmu(struct busfreq_ppmu_data *ppmu_data);
86#endif /* __DEVFREQ_EXYNOS_PPMU_H */
diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
new file mode 100644
index 000000000000..9ef46e2592c4
--- /dev/null
+++ b/drivers/devfreq/governor_passive.c
@@ -0,0 +1,205 @@
1/*
2 * linux/drivers/devfreq/governor_passive.c
3 *
4 * Copyright (C) 2016 Samsung Electronics
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/devfreq.h>
16#include "governor.h"
17
18static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
19 unsigned long *freq)
20{
21 struct devfreq_passive_data *p_data
22 = (struct devfreq_passive_data *)devfreq->data;
23 struct devfreq *parent_devfreq = (struct devfreq *)p_data->parent;
24 unsigned long child_freq = ULONG_MAX;
25 struct dev_pm_opp *opp;
26 int i, count, ret = 0;
27
28 /*
29 * If the devfreq device with passive governor has the specific method
30 * to determine the next frequency, should use the get_target_freq()
31 * of struct devfreq_passive_data.
32 */
33 if (p_data->get_target_freq) {
34 ret = p_data->get_target_freq(devfreq, freq);
35 goto out;
36 }
37
38 /*
39 * If the parent and passive devfreq device uses the OPP table,
40 * get the next frequency by using the OPP table.
41 */
42
43 /*
44 * - parent devfreq device uses the governors except for passive.
45 * - passive devfreq device uses the passive governor.
46 *
47 * Each devfreq has the OPP table. After deciding the new frequency
48 * from the governor of parent devfreq device, the passive governor
49 * need to get the index of new frequency on OPP table of parent
50 * device. And then the index is used for getting the suitable
51 * new frequency for passive devfreq device.
52 */
53 if (!devfreq->profile || !devfreq->profile->freq_table
54 || devfreq->profile->max_state <= 0)
55 return -EINVAL;
56
57 /*
58 * The passive governor have to get the correct frequency from OPP
59 * list of parent device. Because in this case, *freq is temporary
60 * value which is decided by ondemand governor.
61 */
62 rcu_read_lock();
63 opp = devfreq_recommended_opp(parent_devfreq->dev.parent, freq, 0);
64 rcu_read_unlock();
65 if (IS_ERR(opp)) {
66 ret = PTR_ERR(opp);
67 goto out;
68 }
69
70 /*
71 * Get the OPP table's index of decided freqeuncy by governor
72 * of parent device.
73 */
74 for (i = 0; i < parent_devfreq->profile->max_state; i++)
75 if (parent_devfreq->profile->freq_table[i] == *freq)
76 break;
77
78 if (i == parent_devfreq->profile->max_state) {
79 ret = -EINVAL;
80 goto out;
81 }
82
83 /* Get the suitable frequency by using index of parent device. */
84 if (i < devfreq->profile->max_state) {
85 child_freq = devfreq->profile->freq_table[i];
86 } else {
87 count = devfreq->profile->max_state;
88 child_freq = devfreq->profile->freq_table[count - 1];
89 }
90
91 /* Return the suitable frequency for passive device. */
92 *freq = child_freq;
93
94out:
95 return ret;
96}
97
98static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq)
99{
100 int ret;
101
102 if (!devfreq->governor)
103 return -EINVAL;
104
105 mutex_lock_nested(&devfreq->lock, SINGLE_DEPTH_NESTING);
106
107 ret = devfreq->governor->get_target_freq(devfreq, &freq);
108 if (ret < 0)
109 goto out;
110
111 ret = devfreq->profile->target(devfreq->dev.parent, &freq, 0);
112 if (ret < 0)
113 goto out;
114
115 devfreq->previous_freq = freq;
116
117out:
118 mutex_unlock(&devfreq->lock);
119
120 return 0;
121}
122
123static int devfreq_passive_notifier_call(struct notifier_block *nb,
124 unsigned long event, void *ptr)
125{
126 struct devfreq_passive_data *data
127 = container_of(nb, struct devfreq_passive_data, nb);
128 struct devfreq *devfreq = (struct devfreq *)data->this;
129 struct devfreq *parent = (struct devfreq *)data->parent;
130 struct devfreq_freqs *freqs = (struct devfreq_freqs *)ptr;
131 unsigned long freq = freqs->new;
132
133 switch (event) {
134 case DEVFREQ_PRECHANGE:
135 if (parent->previous_freq > freq)
136 update_devfreq_passive(devfreq, freq);
137 break;
138 case DEVFREQ_POSTCHANGE:
139 if (parent->previous_freq < freq)
140 update_devfreq_passive(devfreq, freq);
141 break;
142 }
143
144 return NOTIFY_DONE;
145}
146
147static int devfreq_passive_event_handler(struct devfreq *devfreq,
148 unsigned int event, void *data)
149{
150 struct device *dev = devfreq->dev.parent;
151 struct devfreq_passive_data *p_data
152 = (struct devfreq_passive_data *)devfreq->data;
153 struct devfreq *parent = (struct devfreq *)p_data->parent;
154 struct notifier_block *nb = &p_data->nb;
155 int ret = 0;
156
157 if (!parent)
158 return -EPROBE_DEFER;
159
160 switch (event) {
161 case DEVFREQ_GOV_START:
162 if (!p_data->this)
163 p_data->this = devfreq;
164
165 nb->notifier_call = devfreq_passive_notifier_call;
166 ret = devm_devfreq_register_notifier(dev, parent, nb,
167 DEVFREQ_TRANSITION_NOTIFIER);
168 break;
169 case DEVFREQ_GOV_STOP:
170 devm_devfreq_unregister_notifier(dev, parent, nb,
171 DEVFREQ_TRANSITION_NOTIFIER);
172 break;
173 default:
174 break;
175 }
176
177 return ret;
178}
179
180static struct devfreq_governor devfreq_passive = {
181 .name = "passive",
182 .get_target_freq = devfreq_passive_get_target_freq,
183 .event_handler = devfreq_passive_event_handler,
184};
185
186static int __init devfreq_passive_init(void)
187{
188 return devfreq_add_governor(&devfreq_passive);
189}
190subsys_initcall(devfreq_passive_init);
191
192static void __exit devfreq_passive_exit(void)
193{
194 int ret;
195
196 ret = devfreq_remove_governor(&devfreq_passive);
197 if (ret)
198 pr_err("%s: failed remove governor %d\n", __func__, ret);
199}
200module_exit(devfreq_passive_exit);
201
202MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
203MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
204MODULE_DESCRIPTION("DEVFREQ Passive governor");
205MODULE_LICENSE("GPL v2");
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 6fa02a20eb63..2de4e2eea180 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -19,6 +19,13 @@
19 19
20#define DEVFREQ_NAME_LEN 16 20#define DEVFREQ_NAME_LEN 16
21 21
22/* DEVFREQ notifier interface */
23#define DEVFREQ_TRANSITION_NOTIFIER (0)
24
25/* Transition notifiers of DEVFREQ_TRANSITION_NOTIFIER */
26#define DEVFREQ_PRECHANGE (0)
27#define DEVFREQ_POSTCHANGE (1)
28
22struct devfreq; 29struct devfreq;
23 30
24/** 31/**
@@ -143,6 +150,7 @@ struct devfreq_governor {
143 * @trans_table: Statistics of devfreq transitions 150 * @trans_table: Statistics of devfreq transitions
144 * @time_in_state: Statistics of devfreq states 151 * @time_in_state: Statistics of devfreq states
145 * @last_stat_updated: The last time stat updated 152 * @last_stat_updated: The last time stat updated
153 * @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier
146 * 154 *
147 * This structure stores the devfreq information for a give device. 155 * This structure stores the devfreq information for a give device.
148 * 156 *
@@ -177,6 +185,13 @@ struct devfreq {
177 unsigned int *trans_table; 185 unsigned int *trans_table;
178 unsigned long *time_in_state; 186 unsigned long *time_in_state;
179 unsigned long last_stat_updated; 187 unsigned long last_stat_updated;
188
189 struct srcu_notifier_head transition_notifier_list;
190};
191
192struct devfreq_freqs {
193 unsigned long old;
194 unsigned long new;
180}; 195};
181 196
182#if defined(CONFIG_PM_DEVFREQ) 197#if defined(CONFIG_PM_DEVFREQ)
@@ -207,6 +222,22 @@ extern int devm_devfreq_register_opp_notifier(struct device *dev,
207 struct devfreq *devfreq); 222 struct devfreq *devfreq);
208extern void devm_devfreq_unregister_opp_notifier(struct device *dev, 223extern void devm_devfreq_unregister_opp_notifier(struct device *dev,
209 struct devfreq *devfreq); 224 struct devfreq *devfreq);
225extern int devfreq_register_notifier(struct devfreq *devfreq,
226 struct notifier_block *nb,
227 unsigned int list);
228extern int devfreq_unregister_notifier(struct devfreq *devfreq,
229 struct notifier_block *nb,
230 unsigned int list);
231extern int devm_devfreq_register_notifier(struct device *dev,
232 struct devfreq *devfreq,
233 struct notifier_block *nb,
234 unsigned int list);
235extern void devm_devfreq_unregister_notifier(struct device *dev,
236 struct devfreq *devfreq,
237 struct notifier_block *nb,
238 unsigned int list);
239extern struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
240 int index);
210 241
211/** 242/**
212 * devfreq_update_stats() - update the last_status pointer in struct devfreq 243 * devfreq_update_stats() - update the last_status pointer in struct devfreq
@@ -241,6 +272,39 @@ struct devfreq_simple_ondemand_data {
241}; 272};
242#endif 273#endif
243 274
275#if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE)
276/**
277 * struct devfreq_passive_data - void *data fed to struct devfreq
278 * and devfreq_add_device
279 * @parent: the devfreq instance of parent device.
280 * @get_target_freq: Optional callback, Returns desired operating frequency
281 * for the device using passive governor. That is called
282 * when passive governor should decide the next frequency
283 * by using the new frequency of parent devfreq device
284 * using governors except for passive governor.
285 * If the devfreq device has the specific method to decide
286 * the next frequency, should use this callback.
287 * @this: the devfreq instance of own device.
288 * @nb: the notifier block for DEVFREQ_TRANSITION_NOTIFIER list
289 *
290 * The devfreq_passive_data have to set the devfreq instance of parent
291 * device with governors except for the passive governor. But, don't need to
292 * initialize the 'this' and 'nb' field because the devfreq core will handle
293 * them.
294 */
295struct devfreq_passive_data {
296 /* Should set the devfreq instance of parent device */
297 struct devfreq *parent;
298
299 /* Optional callback to decide the next frequency of passvice device */
300 int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
301
302 /* For passive governor's internal use. Don't need to set them */
303 struct devfreq *this;
304 struct notifier_block nb;
305};
306#endif
307
244#else /* !CONFIG_PM_DEVFREQ */ 308#else /* !CONFIG_PM_DEVFREQ */
245static inline struct devfreq *devfreq_add_device(struct device *dev, 309static inline struct devfreq *devfreq_add_device(struct device *dev,
246 struct devfreq_dev_profile *profile, 310 struct devfreq_dev_profile *profile,
@@ -307,6 +371,41 @@ static inline void devm_devfreq_unregister_opp_notifier(struct device *dev,
307{ 371{
308} 372}
309 373
374static inline int devfreq_register_notifier(struct devfreq *devfreq,
375 struct notifier_block *nb,
376 unsigned int list)
377{
378 return 0;
379}
380
381static inline int devfreq_unregister_notifier(struct devfreq *devfreq,
382 struct notifier_block *nb,
383 unsigned int list)
384{
385 return 0;
386}
387
388static inline int devm_devfreq_register_notifier(struct device *dev,
389 struct devfreq *devfreq,
390 struct notifier_block *nb,
391 unsigned int list)
392{
393 return 0;
394}
395
396static inline void devm_devfreq_unregister_notifier(struct device *dev,
397 struct devfreq *devfreq,
398 struct notifier_block *nb,
399 unsigned int list)
400{
401}
402
403static inline struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
404 int index)
405{
406 return ERR_PTR(-ENODEV);
407}
408
310static inline int devfreq_update_stats(struct devfreq *df) 409static inline int devfreq_update_stats(struct devfreq *df)
311{ 410{
312 return -EINVAL; 411 return -EINVAL;