aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/devfreq
diff options
context:
space:
mode:
authorChanwoo Choi <cw00.choi@samsung.com>2015-11-23 09:58:17 -0500
committerMyungJoo Ham <myungjoo.ham@samsung.com>2016-05-02 22:20:09 -0400
commitbfcd6204871cf63e6833b87cdcfe47d7d2da8a29 (patch)
tree1949b9180d4884ce28c4f73f71fa56fa7b15eafd /drivers/devfreq
parent38279cac36397477d14edf84eff77c8454bc259a (diff)
PM / devfreq: exynos: Remove unused exynos4/5 busfreq driver
This patch removes the unused exynos4/5 busfreq driver. Instead, generic exynos-bus frequency driver support the all Exynos SoCs. Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> Acked-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Diffstat (limited to 'drivers/devfreq')
-rw-r--r--drivers/devfreq/Kconfig22
-rw-r--r--drivers/devfreq/Makefile2
-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
8 files changed, 0 insertions, 1828 deletions
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 30e1daf1c827..78dac0e9da11 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -90,28 +90,6 @@ config ARM_EXYNOS_BUS_DEVFREQ
90 and adjusts the operating frequencies and voltages with OPP support. 90 and adjusts the operating frequencies and voltages with OPP support.
91 This does not yet operate with optimal voltages. 91 This does not yet operate with optimal voltages.
92 92
93config ARM_EXYNOS4_BUS_DEVFREQ
94 bool "ARM Exynos4210/4212/4412 Memory Bus DEVFREQ Driver"
95 depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM
96 select DEVFREQ_GOV_SIMPLE_ONDEMAND
97 select PM_OPP
98 help
99 This adds the DEVFREQ driver for Exynos4210 memory bus (vdd_int)
100 and Exynos4212/4412 memory interface and bus (vdd_mif + vdd_int).
101 It reads PPMU counters of memory controllers and adjusts
102 the operating frequencies and voltages with OPP support.
103 This does not yet operate with optimal voltages.
104
105config ARM_EXYNOS5_BUS_DEVFREQ
106 tristate "ARM Exynos5250 Bus DEVFREQ Driver"
107 depends on SOC_EXYNOS5250
108 select DEVFREQ_GOV_SIMPLE_ONDEMAND
109 select PM_OPP
110 help
111 This adds the DEVFREQ driver for Exynos5250 bus interface (vdd_int).
112 It reads PPMU counters of memory controllers and adjusts the
113 operating frequencies and voltages with OPP support.
114
115config ARM_TEGRA_DEVFREQ 93config ARM_TEGRA_DEVFREQ
116 tristate "Tegra DEVFREQ Driver" 94 tristate "Tegra DEVFREQ Driver"
117 depends on ARCH_TEGRA_124_SOC 95 depends on ARCH_TEGRA_124_SOC
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 2633087d5c63..09f11d9d40d5 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -8,8 +8,6 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o
8 8
9# DEVFREQ Drivers 9# DEVFREQ Drivers
10obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o 10obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o
11obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ) += exynos/
12obj-$(CONFIG_ARM_EXYNOS5_BUS_DEVFREQ) += exynos/
13obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o 11obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o
14 12
15# DEVFREQ Event Drivers 13# DEVFREQ Event Drivers
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 */