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 /drivers/devfreq | |
| 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>
Diffstat (limited to 'drivers/devfreq')
| -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 = { |
