diff options
author | Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> | 2014-03-21 13:31:44 -0400 |
---|---|---|
committer | MyungJoo Ham <myungjoo.ham@samsung.com> | 2014-05-24 04:56:40 -0400 |
commit | f4145270894ba3e4edc120d8940f515a2cd75b4c (patch) | |
tree | aa74694e8351d40162cd34a8a8e6c659b1b31097 | |
parent | ba778b374d55945a190f01f7a741c9657ae5f519 (diff) |
PM / devfreq: exynos4: 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/exynos4_bus.c | 74 |
1 files changed, 46 insertions, 28 deletions
diff --git a/drivers/devfreq/exynos/exynos4_bus.c b/drivers/devfreq/exynos/exynos4_bus.c index 228c658c0e8c..d99ef9e80517 100644 --- a/drivers/devfreq/exynos/exynos4_bus.c +++ b/drivers/devfreq/exynos/exynos4_bus.c | |||
@@ -75,6 +75,11 @@ struct busfreq_opp_info { | |||
75 | unsigned long volt; | 75 | unsigned long volt; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | struct busfreq_ppmu_data { | ||
79 | struct exynos_ppmu *ppmu; | ||
80 | int ppmu_end; | ||
81 | }; | ||
82 | |||
78 | struct busfreq_data { | 83 | struct busfreq_data { |
79 | enum exynos4_busf_type type; | 84 | enum exynos4_busf_type type; |
80 | struct device *dev; | 85 | struct device *dev; |
@@ -83,7 +88,7 @@ struct busfreq_data { | |||
83 | struct regulator *vdd_int; | 88 | struct regulator *vdd_int; |
84 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ | 89 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ |
85 | struct busfreq_opp_info curr_oppinfo; | 90 | struct busfreq_opp_info curr_oppinfo; |
86 | struct exynos_ppmu ppmu[PPMU_END]; | 91 | struct busfreq_ppmu_data ppmu_data; |
87 | 92 | ||
88 | struct notifier_block pm_notifier; | 93 | struct notifier_block pm_notifier; |
89 | struct mutex lock; | 94 | struct mutex lock; |
@@ -510,47 +515,47 @@ static int exynos4x12_set_busclk(struct busfreq_data *data, | |||
510 | return 0; | 515 | return 0; |
511 | } | 516 | } |
512 | 517 | ||
513 | static void busfreq_mon_reset(struct busfreq_data *data) | 518 | static void busfreq_mon_reset(struct busfreq_ppmu_data *ppmu_data) |
514 | { | 519 | { |
515 | unsigned int i; | 520 | unsigned int i; |
516 | 521 | ||
517 | for (i = 0; i < PPMU_END; i++) { | 522 | for (i = 0; i < ppmu_data->ppmu_end; i++) { |
518 | void __iomem *ppmu_base = data->ppmu[i].hw_base; | 523 | void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base; |
519 | 524 | ||
520 | /* Reset the performance and cycle counters */ | 525 | /* Reset the performance and cycle counters */ |
521 | exynos_ppmu_reset(ppmu_base); | 526 | exynos_ppmu_reset(ppmu_base); |
522 | 527 | ||
523 | /* Setup count registers to monitor read/write transactions */ | 528 | /* Setup count registers to monitor read/write transactions */ |
524 | data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT; | 529 | ppmu_data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT; |
525 | exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3, | 530 | exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3, |
526 | data->ppmu[i].event[PPMU_PMNCNT3]); | 531 | ppmu_data->ppmu[i].event[PPMU_PMNCNT3]); |
527 | 532 | ||
528 | exynos_ppmu_start(ppmu_base); | 533 | exynos_ppmu_start(ppmu_base); |
529 | } | 534 | } |
530 | } | 535 | } |
531 | 536 | ||
532 | static void exynos4_read_ppmu(struct busfreq_data *data) | 537 | static void exynos4_read_ppmu(struct busfreq_ppmu_data *ppmu_data) |
533 | { | 538 | { |
534 | int i, j; | 539 | int i, j; |
535 | 540 | ||
536 | for (i = 0; i < PPMU_END; i++) { | 541 | for (i = 0; i < ppmu_data->ppmu_end; i++) { |
537 | void __iomem *ppmu_base = data->ppmu[i].hw_base; | 542 | void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base; |
538 | 543 | ||
539 | exynos_ppmu_stop(ppmu_base); | 544 | exynos_ppmu_stop(ppmu_base); |
540 | 545 | ||
541 | /* Update local data from PPMU */ | 546 | /* Update local data from PPMU */ |
542 | data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT); | 547 | ppmu_data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT); |
543 | 548 | ||
544 | for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { | 549 | for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { |
545 | if (data->ppmu[i].event[j] == 0) | 550 | if (ppmu_data->ppmu[i].event[j] == 0) |
546 | data->ppmu[i].count[j] = 0; | 551 | ppmu_data->ppmu[i].count[j] = 0; |
547 | else | 552 | else |
548 | data->ppmu[i].count[j] = | 553 | ppmu_data->ppmu[i].count[j] = |
549 | exynos_ppmu_read(ppmu_base, j); | 554 | exynos_ppmu_read(ppmu_base, j); |
550 | } | 555 | } |
551 | } | 556 | } |
552 | 557 | ||
553 | busfreq_mon_reset(data); | 558 | busfreq_mon_reset(ppmu_data); |
554 | } | 559 | } |
555 | 560 | ||
556 | static int exynos4x12_get_intspec(unsigned long mifclk) | 561 | static int exynos4x12_get_intspec(unsigned long mifclk) |
@@ -676,16 +681,16 @@ out: | |||
676 | return err; | 681 | return err; |
677 | } | 682 | } |
678 | 683 | ||
679 | static int exynos4_get_busier_ppmu(struct busfreq_data *data) | 684 | static int exynos4_get_busier_ppmu(struct busfreq_ppmu_data *ppmu_data) |
680 | { | 685 | { |
681 | int i, j; | 686 | int i, j; |
682 | int busy = 0; | 687 | int busy = 0; |
683 | unsigned int temp = 0; | 688 | unsigned int temp = 0; |
684 | 689 | ||
685 | for (i = 0; i < PPMU_END; i++) { | 690 | for (i = 0; i < ppmu_data->ppmu_end; i++) { |
686 | for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { | 691 | for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) { |
687 | if (data->ppmu[i].count[j] > temp) { | 692 | if (ppmu_data->ppmu[i].count[j] > temp) { |
688 | temp = data->ppmu[i].count[j]; | 693 | temp = ppmu_data->ppmu[i].count[j]; |
689 | busy = i; | 694 | busy = i; |
690 | } | 695 | } |
691 | } | 696 | } |
@@ -698,20 +703,21 @@ static int exynos4_bus_get_dev_status(struct device *dev, | |||
698 | struct devfreq_dev_status *stat) | 703 | struct devfreq_dev_status *stat) |
699 | { | 704 | { |
700 | struct busfreq_data *data = dev_get_drvdata(dev); | 705 | struct busfreq_data *data = dev_get_drvdata(dev); |
706 | struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data; | ||
701 | int busier; | 707 | int busier; |
702 | 708 | ||
703 | exynos4_read_ppmu(data); | 709 | exynos4_read_ppmu(ppmu_data); |
704 | busier = exynos4_get_busier_ppmu(data); | 710 | busier = exynos4_get_busier_ppmu(ppmu_data); |
705 | stat->current_frequency = data->curr_oppinfo.rate; | 711 | stat->current_frequency = data->curr_oppinfo.rate; |
706 | 712 | ||
707 | /* Number of cycles spent on memory access */ | 713 | /* Number of cycles spent on memory access */ |
708 | stat->busy_time = data->ppmu[busier].count[PPMU_PMNCNT3]; | 714 | stat->busy_time = ppmu_data->ppmu[busier].count[PPMU_PMNCNT3]; |
709 | stat->busy_time *= 100 / BUS_SATURATION_RATIO; | 715 | stat->busy_time *= 100 / BUS_SATURATION_RATIO; |
710 | stat->total_time = data->ppmu[busier].ccnt; | 716 | stat->total_time = ppmu_data->ppmu[busier].ccnt; |
711 | 717 | ||
712 | /* If the counters have overflown, retry */ | 718 | /* If the counters have overflown, retry */ |
713 | if (data->ppmu[busier].ccnt_overflow || | 719 | if (ppmu_data->ppmu[busier].ccnt_overflow || |
714 | data->ppmu[busier].count_overflow[0]) | 720 | ppmu_data->ppmu[busier].count_overflow[0]) |
715 | return -EAGAIN; | 721 | return -EAGAIN; |
716 | 722 | ||
717 | return 0; | 723 | return 0; |
@@ -966,6 +972,7 @@ unlock: | |||
966 | static int exynos4_busfreq_probe(struct platform_device *pdev) | 972 | static int exynos4_busfreq_probe(struct platform_device *pdev) |
967 | { | 973 | { |
968 | struct busfreq_data *data; | 974 | struct busfreq_data *data; |
975 | struct busfreq_ppmu_data *ppmu_data; | ||
969 | struct dev_pm_opp *opp; | 976 | struct dev_pm_opp *opp; |
970 | struct device *dev = &pdev->dev; | 977 | struct device *dev = &pdev->dev; |
971 | int err = 0; | 978 | int err = 0; |
@@ -976,9 +983,19 @@ static int exynos4_busfreq_probe(struct platform_device *pdev) | |||
976 | return -ENOMEM; | 983 | return -ENOMEM; |
977 | } | 984 | } |
978 | 985 | ||
986 | ppmu_data = &data->ppmu_data; | ||
987 | ppmu_data->ppmu_end = PPMU_END; | ||
988 | ppmu_data->ppmu = devm_kzalloc(dev, | ||
989 | sizeof(struct exynos_ppmu) * PPMU_END, | ||
990 | GFP_KERNEL); | ||
991 | if (!ppmu_data->ppmu) { | ||
992 | dev_err(dev, "Failed to allocate memory for exynos_ppmu\n"); | ||
993 | return -ENOMEM; | ||
994 | } | ||
995 | |||
979 | data->type = pdev->id_entry->driver_data; | 996 | data->type = pdev->id_entry->driver_data; |
980 | data->ppmu[PPMU_DMC0].hw_base = S5P_VA_DMC0; | 997 | ppmu_data->ppmu[PPMU_DMC0].hw_base = S5P_VA_DMC0; |
981 | data->ppmu[PPMU_DMC1].hw_base = S5P_VA_DMC1; | 998 | ppmu_data->ppmu[PPMU_DMC1].hw_base = S5P_VA_DMC1; |
982 | data->pm_notifier.notifier_call = exynos4_busfreq_pm_notifier_event; | 999 | data->pm_notifier.notifier_call = exynos4_busfreq_pm_notifier_event; |
983 | data->dev = dev; | 1000 | data->dev = dev; |
984 | mutex_init(&data->lock); | 1001 | mutex_init(&data->lock); |
@@ -1037,7 +1054,7 @@ static int exynos4_busfreq_probe(struct platform_device *pdev) | |||
1037 | * Start PPMU (Performance Profiling Monitoring Unit) to check | 1054 | * Start PPMU (Performance Profiling Monitoring Unit) to check |
1038 | * utilization of each IP in the Exynos4 SoC. | 1055 | * utilization of each IP in the Exynos4 SoC. |
1039 | */ | 1056 | */ |
1040 | busfreq_mon_reset(data); | 1057 | busfreq_mon_reset(ppmu_data); |
1041 | 1058 | ||
1042 | /* Register opp_notifier for Exynos4 busfreq */ | 1059 | /* Register opp_notifier for Exynos4 busfreq */ |
1043 | err = devfreq_register_opp_notifier(dev, data->devfreq); | 1060 | err = devfreq_register_opp_notifier(dev, data->devfreq); |
@@ -1081,8 +1098,9 @@ static int exynos4_busfreq_remove(struct platform_device *pdev) | |||
1081 | static int exynos4_busfreq_resume(struct device *dev) | 1098 | static int exynos4_busfreq_resume(struct device *dev) |
1082 | { | 1099 | { |
1083 | struct busfreq_data *data = dev_get_drvdata(dev); | 1100 | struct busfreq_data *data = dev_get_drvdata(dev); |
1101 | struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data; | ||
1084 | 1102 | ||
1085 | busfreq_mon_reset(data); | 1103 | busfreq_mon_reset(ppmu_data); |
1086 | return 0; | 1104 | return 0; |
1087 | } | 1105 | } |
1088 | #endif | 1106 | #endif |