diff options
author | Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> | 2014-03-21 13:31:45 -0400 |
---|---|---|
committer | MyungJoo Ham <myungjoo.ham@samsung.com> | 2014-05-24 04:56:41 -0400 |
commit | a94f6b4a6f60b4e80102dc431c11026df1307cbb (patch) | |
tree | a2dec6c61e58a43e7349a8f30de69ce238ddbff9 | |
parent | f4145270894ba3e4edc120d8940f515a2cd75b4c (diff) |
PM / devfreq: exynos5: introduce struct busfreq_ppmu_data
This is a preparation for making more PPMU code common for
EXYNOS devfreq drivers.
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
-rw-r--r-- | drivers/devfreq/exynos/exynos5_bus.c | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c index af6213fa39ba..b8ab32addef6 100644 --- a/drivers/devfreq/exynos/exynos5_bus.c +++ b/drivers/devfreq/exynos/exynos5_bus.c | |||
@@ -46,11 +46,16 @@ enum exynos_ppmu_list { | |||
46 | PPMU_END, | 46 | PPMU_END, |
47 | }; | 47 | }; |
48 | 48 | ||
49 | struct busfreq_ppmu_data { | ||
50 | struct exynos_ppmu *ppmu; | ||
51 | int ppmu_end; | ||
52 | }; | ||
53 | |||
49 | struct busfreq_data_int { | 54 | struct busfreq_data_int { |
50 | struct device *dev; | 55 | struct device *dev; |
51 | struct devfreq *devfreq; | 56 | struct devfreq *devfreq; |
52 | struct regulator *vdd_int; | 57 | struct regulator *vdd_int; |
53 | struct exynos_ppmu ppmu[PPMU_END]; | 58 | struct busfreq_ppmu_data ppmu_data; |
54 | unsigned long curr_freq; | 59 | unsigned long curr_freq; |
55 | bool disabled; | 60 | bool disabled; |
56 | 61 | ||
@@ -75,47 +80,47 @@ static struct int_bus_opp_table exynos5_int_opp_table[] = { | |||
75 | {0, 0, 0}, | 80 | {0, 0, 0}, |
76 | }; | 81 | }; |
77 | 82 | ||
78 | static void busfreq_mon_reset(struct busfreq_data_int *data) | 83 | static void busfreq_mon_reset(struct busfreq_ppmu_data *ppmu_data) |
79 | { | 84 | { |
80 | unsigned int i; | 85 | unsigned int i; |
81 | 86 | ||
82 | for (i = PPMU_RIGHT; i < PPMU_END; i++) { | 87 | for (i = 0; i < ppmu_data->ppmu_end; i++) { |
83 | void __iomem *ppmu_base = data->ppmu[i].hw_base; | 88 | void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base; |
84 | 89 | ||
85 | /* Reset the performance and cycle counters */ | 90 | /* Reset the performance and cycle counters */ |
86 | exynos_ppmu_reset(ppmu_base); | 91 | exynos_ppmu_reset(ppmu_base); |
87 | 92 | ||
88 | /* Setup count registers to monitor read/write transactions */ | 93 | /* Setup count registers to monitor read/write transactions */ |
89 | data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT; | 94 | ppmu_data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT; |
90 | exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3, | 95 | exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3, |
91 | data->ppmu[i].event[PPMU_PMNCNT3]); | 96 | ppmu_data->ppmu[i].event[PPMU_PMNCNT3]); |
92 | 97 | ||
93 | exynos_ppmu_start(ppmu_base); | 98 | exynos_ppmu_start(ppmu_base); |
94 | } | 99 | } |
95 | } | 100 | } |
96 | 101 | ||
97 | static void exynos5_read_ppmu(struct busfreq_data_int *data) | 102 | static void exynos5_read_ppmu(struct busfreq_ppmu_data *ppmu_data) |
98 | { | 103 | { |
99 | int i, j; | 104 | int i, j; |
100 | 105 | ||
101 | for (i = PPMU_RIGHT; i < PPMU_END; i++) { | 106 | for (i = 0; i < ppmu_data->ppmu_end; i++) { |
102 | void __iomem *ppmu_base = data->ppmu[i].hw_base; | 107 | void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base; |
103 | 108 | ||
104 | exynos_ppmu_stop(ppmu_base); | 109 | exynos_ppmu_stop(ppmu_base); |
105 | 110 | ||
106 | /* Update local data from PPMU */ | 111 | /* Update local data from PPMU */ |
107 | data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT); | 112 | ppmu_data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT); |
108 | 113 | ||
109 | for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { | 114 | for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { |
110 | if (data->ppmu[i].event[j] == 0) | 115 | if (ppmu_data->ppmu[i].event[j] == 0) |
111 | data->ppmu[i].count[j] = 0; | 116 | ppmu_data->ppmu[i].count[j] = 0; |
112 | else | 117 | else |
113 | data->ppmu[i].count[j] = | 118 | ppmu_data->ppmu[i].count[j] = |
114 | exynos_ppmu_read(ppmu_base, j); | 119 | exynos_ppmu_read(ppmu_base, j); |
115 | } | 120 | } |
116 | } | 121 | } |
117 | 122 | ||
118 | busfreq_mon_reset(data); | 123 | busfreq_mon_reset(ppmu_data); |
119 | } | 124 | } |
120 | 125 | ||
121 | static int exynos5_int_setvolt(struct busfreq_data_int *data, | 126 | static int exynos5_int_setvolt(struct busfreq_data_int *data, |
@@ -185,16 +190,16 @@ out: | |||
185 | return err; | 190 | return err; |
186 | } | 191 | } |
187 | 192 | ||
188 | static int exynos5_get_busier_dmc(struct busfreq_data_int *data) | 193 | static int exynos5_get_busier_dmc(struct busfreq_ppmu_data *ppmu_data) |
189 | { | 194 | { |
190 | int i, j; | 195 | int i, j; |
191 | int busy = 0; | 196 | int busy = 0; |
192 | unsigned int temp = 0; | 197 | unsigned int temp = 0; |
193 | 198 | ||
194 | for (i = PPMU_RIGHT; i < PPMU_END; i++) { | 199 | for (i = 0; i < ppmu_data->ppmu_end; i++) { |
195 | for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { | 200 | for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { |
196 | if (data->ppmu[i].count[j] > temp) { | 201 | if (ppmu_data->ppmu[i].count[j] > temp) { |
197 | temp = data->ppmu[i].count[j]; | 202 | temp = ppmu_data->ppmu[i].count[j]; |
198 | busy = i; | 203 | busy = i; |
199 | } | 204 | } |
200 | } | 205 | } |
@@ -209,17 +214,18 @@ static int exynos5_int_get_dev_status(struct device *dev, | |||
209 | struct platform_device *pdev = container_of(dev, struct platform_device, | 214 | struct platform_device *pdev = container_of(dev, struct platform_device, |
210 | dev); | 215 | dev); |
211 | struct busfreq_data_int *data = platform_get_drvdata(pdev); | 216 | struct busfreq_data_int *data = platform_get_drvdata(pdev); |
217 | struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data; | ||
212 | int busier_dmc; | 218 | int busier_dmc; |
213 | 219 | ||
214 | exynos5_read_ppmu(data); | 220 | exynos5_read_ppmu(ppmu_data); |
215 | busier_dmc = exynos5_get_busier_dmc(data); | 221 | busier_dmc = exynos5_get_busier_dmc(ppmu_data); |
216 | 222 | ||
217 | stat->current_frequency = data->curr_freq; | 223 | stat->current_frequency = data->curr_freq; |
218 | 224 | ||
219 | /* Number of cycles spent on memory access */ | 225 | /* Number of cycles spent on memory access */ |
220 | stat->busy_time = data->ppmu[busier_dmc].count[PPMU_PMNCNT3]; | 226 | stat->busy_time = ppmu_data->ppmu[busier_dmc].count[PPMU_PMNCNT3]; |
221 | stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO; | 227 | stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO; |
222 | stat->total_time = data->ppmu[busier_dmc].ccnt; | 228 | stat->total_time = ppmu_data->ppmu[busier_dmc].ccnt; |
223 | 229 | ||
224 | return 0; | 230 | return 0; |
225 | } | 231 | } |
@@ -315,6 +321,7 @@ unlock: | |||
315 | static int exynos5_busfreq_int_probe(struct platform_device *pdev) | 321 | static int exynos5_busfreq_int_probe(struct platform_device *pdev) |
316 | { | 322 | { |
317 | struct busfreq_data_int *data; | 323 | struct busfreq_data_int *data; |
324 | struct busfreq_ppmu_data *ppmu_data; | ||
318 | struct dev_pm_opp *opp; | 325 | struct dev_pm_opp *opp; |
319 | struct device *dev = &pdev->dev; | 326 | struct device *dev = &pdev->dev; |
320 | struct device_node *np; | 327 | struct device_node *np; |
@@ -330,16 +337,26 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) | |||
330 | return -ENOMEM; | 337 | return -ENOMEM; |
331 | } | 338 | } |
332 | 339 | ||
340 | ppmu_data = &data->ppmu_data; | ||
341 | ppmu_data->ppmu_end = PPMU_END; | ||
342 | ppmu_data->ppmu = devm_kzalloc(dev, | ||
343 | sizeof(struct exynos_ppmu) * PPMU_END, | ||
344 | GFP_KERNEL); | ||
345 | if (!ppmu_data->ppmu) { | ||
346 | dev_err(dev, "Failed to allocate memory for exynos_ppmu\n"); | ||
347 | return -ENOMEM; | ||
348 | } | ||
349 | |||
333 | np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu"); | 350 | np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu"); |
334 | if (np == NULL) { | 351 | if (np == NULL) { |
335 | pr_err("Unable to find PPMU node\n"); | 352 | pr_err("Unable to find PPMU node\n"); |
336 | return -ENOENT; | 353 | return -ENOENT; |
337 | } | 354 | } |
338 | 355 | ||
339 | for (i = PPMU_RIGHT; i < PPMU_END; i++) { | 356 | for (i = 0; i < ppmu_data->ppmu_end; i++) { |
340 | /* map PPMU memory region */ | 357 | /* map PPMU memory region */ |
341 | data->ppmu[i].hw_base = of_iomap(np, i); | 358 | ppmu_data->ppmu[i].hw_base = of_iomap(np, i); |
342 | if (data->ppmu[i].hw_base == NULL) { | 359 | if (ppmu_data->ppmu[i].hw_base == NULL) { |
343 | dev_err(&pdev->dev, "failed to map memory region\n"); | 360 | dev_err(&pdev->dev, "failed to map memory region\n"); |
344 | return -ENOMEM; | 361 | return -ENOMEM; |
345 | } | 362 | } |
@@ -390,7 +407,7 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev) | |||
390 | 407 | ||
391 | platform_set_drvdata(pdev, data); | 408 | platform_set_drvdata(pdev, data); |
392 | 409 | ||
393 | busfreq_mon_reset(data); | 410 | busfreq_mon_reset(ppmu_data); |
394 | 411 | ||
395 | data->devfreq = devfreq_add_device(dev, &exynos5_devfreq_int_profile, | 412 | data->devfreq = devfreq_add_device(dev, &exynos5_devfreq_int_profile, |
396 | "simple_ondemand", NULL); | 413 | "simple_ondemand", NULL); |
@@ -435,8 +452,9 @@ static int exynos5_busfreq_int_resume(struct device *dev) | |||
435 | struct platform_device *pdev = container_of(dev, struct platform_device, | 452 | struct platform_device *pdev = container_of(dev, struct platform_device, |
436 | dev); | 453 | dev); |
437 | struct busfreq_data_int *data = platform_get_drvdata(pdev); | 454 | struct busfreq_data_int *data = platform_get_drvdata(pdev); |
455 | struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data; | ||
438 | 456 | ||
439 | busfreq_mon_reset(data); | 457 | busfreq_mon_reset(ppmu_data); |
440 | return 0; | 458 | return 0; |
441 | } | 459 | } |
442 | static const struct dev_pm_ops exynos5_busfreq_int_pm = { | 460 | static const struct dev_pm_ops exynos5_busfreq_int_pm = { |