aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-29 21:54:27 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-29 21:54:27 -0400
commit6392bfd57654338f0df8346dd058e91b8215ab11 (patch)
tree5757dff822c031f591db86a8fafbed3c96fa19b1
parentc7208164e66f63e3ec1759b98087849286410741 (diff)
parentcb7063f453e543b97285a10343cfc02983d792ad (diff)
Merge tag 'for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq into pm-devfreq
Pull devfreq updates for v3.16 from MyungJoo Ham. - Clean up with modern macro in the core and drivers. - Fix incorrect error returns - Remove dead CONFIG check. - Fix resource leak in a driver. * tag 'for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq: PM / devfreq: remove checks for CONFIG_EXYNOS_ASV PM / devfreq: exynos5: Use devm_devfreq_* function using device resource management PM / devfreq: exynos4: Use devm_devfreq_* function using device resource management PM / devfreq: Add devm_devfreq_{register,unregister}_opp_notfier function PM / devfreq: Add resource-managed function for devfreq device PM / devfreq: Fix devfreq_remove_device() to improve the sequence of resource free PM / devfreq: exynos: make more PPMU code common PM / devfreq: exynos5: introduce struct busfreq_ppmu_data PM / devfreq: exynos4: introduce struct busfreq_ppmu_data PM / devfreq: exynos4: use common PPMU code PM / devfreq: exynos5: Add CONFIG_PM_OPP dependency to fix probe fail PM / devfreq: exynos5: Use SIMPLE_DEV_PM_OPS macro PM / devfreq: exynos4: Add CONFIG_PM_OPP dependency to fix probe fail PM / devfreq: exynos4: Use SIMPLE_DEV_PM_OPS macro PM / devfreq: exynos4: Fix bug of resource leak and code clean on probe()
-rw-r--r--drivers/devfreq/Kconfig5
-rw-r--r--drivers/devfreq/devfreq.c125
-rw-r--r--drivers/devfreq/exynos/Makefile2
-rw-r--r--drivers/devfreq/exynos/exynos4_bus.c219
-rw-r--r--drivers/devfreq/exynos/exynos5_bus.c130
-rw-r--r--drivers/devfreq/exynos/exynos_ppmu.c60
-rw-r--r--drivers/devfreq/exynos/exynos_ppmu.h8
-rw-r--r--include/linux/devfreq.h35
8 files changed, 317 insertions, 267 deletions
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 7d2f43550700..49e74c1fc639 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -70,19 +70,20 @@ config ARM_EXYNOS4_BUS_DEVFREQ
70 depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM 70 depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM
71 select ARCH_HAS_OPP 71 select ARCH_HAS_OPP
72 select DEVFREQ_GOV_SIMPLE_ONDEMAND 72 select DEVFREQ_GOV_SIMPLE_ONDEMAND
73 select PM_OPP
73 help 74 help
74 This adds the DEVFREQ driver for Exynos4210 memory bus (vdd_int) 75 This adds the DEVFREQ driver for Exynos4210 memory bus (vdd_int)
75 and Exynos4212/4412 memory interface and bus (vdd_mif + vdd_int). 76 and Exynos4212/4412 memory interface and bus (vdd_mif + vdd_int).
76 It reads PPMU counters of memory controllers and adjusts 77 It reads PPMU counters of memory controllers and adjusts
77 the operating frequencies and voltages with OPP support. 78 the operating frequencies and voltages with OPP support.
78 To operate with optimal voltages, ASV support is required 79 This does not yet operate with optimal voltages.
79 (CONFIG_EXYNOS_ASV).
80 80
81config ARM_EXYNOS5_BUS_DEVFREQ 81config ARM_EXYNOS5_BUS_DEVFREQ
82 bool "ARM Exynos5250 Bus DEVFREQ Driver" 82 bool "ARM Exynos5250 Bus DEVFREQ Driver"
83 depends on SOC_EXYNOS5250 83 depends on SOC_EXYNOS5250
84 select ARCH_HAS_OPP 84 select ARCH_HAS_OPP
85 select DEVFREQ_GOV_SIMPLE_ONDEMAND 85 select DEVFREQ_GOV_SIMPLE_ONDEMAND
86 select PM_OPP
86 help 87 help
87 This adds the DEVFREQ driver for Exynos5250 bus interface (vdd_int). 88 This adds the DEVFREQ driver for Exynos5250 bus interface (vdd_int).
88 It reads PPMU counters of memory controllers and adjusts the 89 It reads PPMU counters of memory controllers and adjusts the
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 2042ec3656ba..9f90369dd6bd 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -394,7 +394,7 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
394 * @devfreq: the devfreq struct 394 * @devfreq: the devfreq struct
395 * @skip: skip calling device_unregister(). 395 * @skip: skip calling device_unregister().
396 */ 396 */
397static void _remove_devfreq(struct devfreq *devfreq, bool skip) 397static void _remove_devfreq(struct devfreq *devfreq)
398{ 398{
399 mutex_lock(&devfreq_list_lock); 399 mutex_lock(&devfreq_list_lock);
400 if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) { 400 if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
@@ -412,11 +412,6 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
412 if (devfreq->profile->exit) 412 if (devfreq->profile->exit)
413 devfreq->profile->exit(devfreq->dev.parent); 413 devfreq->profile->exit(devfreq->dev.parent);
414 414
415 if (!skip && get_device(&devfreq->dev)) {
416 device_unregister(&devfreq->dev);
417 put_device(&devfreq->dev);
418 }
419
420 mutex_destroy(&devfreq->lock); 415 mutex_destroy(&devfreq->lock);
421 kfree(devfreq); 416 kfree(devfreq);
422} 417}
@@ -426,14 +421,12 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
426 * @dev: the devfreq device 421 * @dev: the devfreq device
427 * 422 *
428 * This calls _remove_devfreq() if _remove_devfreq() is not called. 423 * This calls _remove_devfreq() if _remove_devfreq() is not called.
429 * Note that devfreq_dev_release() could be called by _remove_devfreq() as
430 * well as by others unregistering the device.
431 */ 424 */
432static void devfreq_dev_release(struct device *dev) 425static void devfreq_dev_release(struct device *dev)
433{ 426{
434 struct devfreq *devfreq = to_devfreq(dev); 427 struct devfreq *devfreq = to_devfreq(dev);
435 428
436 _remove_devfreq(devfreq, true); 429 _remove_devfreq(devfreq);
437} 430}
438 431
439/** 432/**
@@ -544,12 +537,76 @@ int devfreq_remove_device(struct devfreq *devfreq)
544 if (!devfreq) 537 if (!devfreq)
545 return -EINVAL; 538 return -EINVAL;
546 539
547 _remove_devfreq(devfreq, false); 540 device_unregister(&devfreq->dev);
541 put_device(&devfreq->dev);
548 542
549 return 0; 543 return 0;
550} 544}
551EXPORT_SYMBOL(devfreq_remove_device); 545EXPORT_SYMBOL(devfreq_remove_device);
552 546
547static int devm_devfreq_dev_match(struct device *dev, void *res, void *data)
548{
549 struct devfreq **r = res;
550
551 if (WARN_ON(!r || !*r))
552 return 0;
553
554 return *r == data;
555}
556
557static void devm_devfreq_dev_release(struct device *dev, void *res)
558{
559 devfreq_remove_device(*(struct devfreq **)res);
560}
561
562/**
563 * devm_devfreq_add_device() - Resource-managed devfreq_add_device()
564 * @dev: the device to add devfreq feature.
565 * @profile: device-specific profile to run devfreq.
566 * @governor_name: name of the policy to choose frequency.
567 * @data: private data for the governor. The devfreq framework does not
568 * touch this value.
569 *
570 * This function manages automatically the memory of devfreq device using device
571 * resource management and simplify the free operation for memory of devfreq
572 * device.
573 */
574struct devfreq *devm_devfreq_add_device(struct device *dev,
575 struct devfreq_dev_profile *profile,
576 const char *governor_name,
577 void *data)
578{
579 struct devfreq **ptr, *devfreq;
580
581 ptr = devres_alloc(devm_devfreq_dev_release, sizeof(*ptr), GFP_KERNEL);
582 if (!ptr)
583 return ERR_PTR(-ENOMEM);
584
585 devfreq = devfreq_add_device(dev, profile, governor_name, data);
586 if (IS_ERR(devfreq)) {
587 devres_free(ptr);
588 return ERR_PTR(-ENOMEM);
589 }
590
591 *ptr = devfreq;
592 devres_add(dev, ptr);
593
594 return devfreq;
595}
596EXPORT_SYMBOL(devm_devfreq_add_device);
597
598/**
599 * devm_devfreq_remove_device() - Resource-managed devfreq_remove_device()
600 * @dev: the device to add devfreq feature.
601 * @devfreq: the devfreq instance to be removed
602 */
603void devm_devfreq_remove_device(struct device *dev, struct devfreq *devfreq)
604{
605 WARN_ON(devres_release(dev, devm_devfreq_dev_release,
606 devm_devfreq_dev_match, devfreq));
607}
608EXPORT_SYMBOL(devm_devfreq_remove_device);
609
553/** 610/**
554 * devfreq_suspend_device() - Suspend devfreq of a device. 611 * devfreq_suspend_device() - Suspend devfreq of a device.
555 * @devfreq: the devfreq instance to be suspended 612 * @devfreq: the devfreq instance to be suspended
@@ -1112,6 +1169,54 @@ int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
1112 return ret; 1169 return ret;
1113} 1170}
1114 1171
1172static void devm_devfreq_opp_release(struct device *dev, void *res)
1173{
1174 devfreq_unregister_opp_notifier(dev, *(struct devfreq **)res);
1175}
1176
1177/**
1178 * devm_ devfreq_register_opp_notifier()
1179 * - Resource-managed devfreq_register_opp_notifier()
1180 * @dev: The devfreq user device. (parent of devfreq)
1181 * @devfreq: The devfreq object.
1182 */
1183int devm_devfreq_register_opp_notifier(struct device *dev,
1184 struct devfreq *devfreq)
1185{
1186 struct devfreq **ptr;
1187 int ret;
1188
1189 ptr = devres_alloc(devm_devfreq_opp_release, sizeof(*ptr), GFP_KERNEL);
1190 if (!ptr)
1191 return -ENOMEM;
1192
1193 ret = devfreq_register_opp_notifier(dev, devfreq);
1194 if (ret) {
1195 devres_free(ptr);
1196 return ret;
1197 }
1198
1199 *ptr = devfreq;
1200 devres_add(dev, ptr);
1201
1202 return 0;
1203}
1204EXPORT_SYMBOL(devm_devfreq_register_opp_notifier);
1205
1206/**
1207 * devm_devfreq_unregister_opp_notifier()
1208 * - Resource-managed devfreq_unregister_opp_notifier()
1209 * @dev: The devfreq user device. (parent of devfreq)
1210 * @devfreq: The devfreq object.
1211 */
1212void devm_devfreq_unregister_opp_notifier(struct device *dev,
1213 struct devfreq *devfreq)
1214{
1215 WARN_ON(devres_release(dev, devm_devfreq_opp_release,
1216 devm_devfreq_dev_match, devfreq));
1217}
1218EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier);
1219
1115MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); 1220MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
1116MODULE_DESCRIPTION("devfreq class support"); 1221MODULE_DESCRIPTION("devfreq class support");
1117MODULE_LICENSE("GPL"); 1222MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/exynos/Makefile b/drivers/devfreq/exynos/Makefile
index bfaaf5b0d61d..49bc9175f923 100644
--- a/drivers/devfreq/exynos/Makefile
+++ b/drivers/devfreq/exynos/Makefile
@@ -1,3 +1,3 @@
1# Exynos DEVFREQ Drivers 1# Exynos DEVFREQ Drivers
2obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ) += exynos4_bus.o 2obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ) += exynos_ppmu.o exynos4_bus.o
3obj-$(CONFIG_ARM_EXYNOS5_BUS_DEVFREQ) += exynos_ppmu.o exynos5_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
index e07b0c68c715..d9b08d3b6830 100644
--- a/drivers/devfreq/exynos/exynos4_bus.c
+++ b/drivers/devfreq/exynos/exynos4_bus.c
@@ -25,13 +25,9 @@
25#include <linux/regulator/consumer.h> 25#include <linux/regulator/consumer.h>
26#include <linux/module.h> 26#include <linux/module.h>
27 27
28/* Exynos4 ASV has been in the mailing list, but not upstreamed, yet. */
29#ifdef CONFIG_EXYNOS_ASV
30extern unsigned int exynos_result_of_asv;
31#endif
32
33#include <mach/map.h> 28#include <mach/map.h>
34 29
30#include "exynos_ppmu.h"
35#include "exynos4_bus.h" 31#include "exynos4_bus.h"
36 32
37#define MAX_SAFEVOLT 1200000 /* 1.2V */ 33#define MAX_SAFEVOLT 1200000 /* 1.2V */
@@ -44,22 +40,6 @@ enum exynos4_busf_type {
44/* Assume that the bus is saturated if the utilization is 40% */ 40/* Assume that the bus is saturated if the utilization is 40% */
45#define BUS_SATURATION_RATIO 40 41#define BUS_SATURATION_RATIO 40
46 42
47enum ppmu_counter {
48 PPMU_PMNCNT0 = 0,
49 PPMU_PMCCNT1,
50 PPMU_PMNCNT2,
51 PPMU_PMNCNT3,
52 PPMU_PMNCNT_MAX,
53};
54struct exynos4_ppmu {
55 void __iomem *hw_base;
56 unsigned int ccnt;
57 unsigned int event;
58 unsigned int count[PPMU_PMNCNT_MAX];
59 bool ccnt_overflow;
60 bool count_overflow[PPMU_PMNCNT_MAX];
61};
62
63enum busclk_level_idx { 43enum busclk_level_idx {
64 LV_0 = 0, 44 LV_0 = 0,
65 LV_1, 45 LV_1,
@@ -68,6 +48,13 @@ enum busclk_level_idx {
68 LV_4, 48 LV_4,
69 _LV_END 49 _LV_END
70}; 50};
51
52enum exynos_ppmu_idx {
53 PPMU_DMC0,
54 PPMU_DMC1,
55 PPMU_END,
56};
57
71#define EX4210_LV_MAX LV_2 58#define EX4210_LV_MAX LV_2
72#define EX4x12_LV_MAX LV_4 59#define EX4x12_LV_MAX LV_4
73#define EX4210_LV_NUM (LV_2 + 1) 60#define EX4210_LV_NUM (LV_2 + 1)
@@ -91,7 +78,7 @@ struct busfreq_data {
91 struct regulator *vdd_int; 78 struct regulator *vdd_int;
92 struct regulator *vdd_mif; /* Exynos4412/4212 only */ 79 struct regulator *vdd_mif; /* Exynos4412/4212 only */
93 struct busfreq_opp_info curr_oppinfo; 80 struct busfreq_opp_info curr_oppinfo;
94 struct exynos4_ppmu dmc[2]; 81 struct busfreq_ppmu_data ppmu_data;
95 82
96 struct notifier_block pm_notifier; 83 struct notifier_block pm_notifier;
97 struct mutex lock; 84 struct mutex lock;
@@ -101,12 +88,6 @@ struct busfreq_data {
101 unsigned int top_divtable[_LV_END]; 88 unsigned int top_divtable[_LV_END];
102}; 89};
103 90
104struct bus_opp_table {
105 unsigned int idx;
106 unsigned long clk;
107 unsigned long volt;
108};
109
110/* 4210 controls clock of mif and voltage of int */ 91/* 4210 controls clock of mif and voltage of int */
111static struct bus_opp_table exynos4210_busclk_table[] = { 92static struct bus_opp_table exynos4210_busclk_table[] = {
112 {LV_0, 400000, 1150000}, 93 {LV_0, 400000, 1150000},
@@ -524,57 +505,6 @@ static int exynos4x12_set_busclk(struct busfreq_data *data,
524 return 0; 505 return 0;
525} 506}
526 507
527
528static void busfreq_mon_reset(struct busfreq_data *data)
529{
530 unsigned int i;
531
532 for (i = 0; i < 2; i++) {
533 void __iomem *ppmu_base = data->dmc[i].hw_base;
534
535 /* Reset PPMU */
536 __raw_writel(0x8000000f, ppmu_base + 0xf010);
537 __raw_writel(0x8000000f, ppmu_base + 0xf050);
538 __raw_writel(0x6, ppmu_base + 0xf000);
539 __raw_writel(0x0, ppmu_base + 0xf100);
540
541 /* Set PPMU Event */
542 data->dmc[i].event = 0x6;
543 __raw_writel(((data->dmc[i].event << 12) | 0x1),
544 ppmu_base + 0xfc);
545
546 /* Start PPMU */
547 __raw_writel(0x1, ppmu_base + 0xf000);
548 }
549}
550
551static void exynos4_read_ppmu(struct busfreq_data *data)
552{
553 int i, j;
554
555 for (i = 0; i < 2; i++) {
556 void __iomem *ppmu_base = data->dmc[i].hw_base;
557 u32 overflow;
558
559 /* Stop PPMU */
560 __raw_writel(0x0, ppmu_base + 0xf000);
561
562 /* Update local data from PPMU */
563 overflow = __raw_readl(ppmu_base + 0xf050);
564
565 data->dmc[i].ccnt = __raw_readl(ppmu_base + 0xf100);
566 data->dmc[i].ccnt_overflow = overflow & (1 << 31);
567
568 for (j = 0; j < PPMU_PMNCNT_MAX; j++) {
569 data->dmc[i].count[j] = __raw_readl(
570 ppmu_base + (0xf110 + (0x10 * j)));
571 data->dmc[i].count_overflow[j] = overflow & (1 << j);
572 }
573 }
574
575 busfreq_mon_reset(data);
576}
577
578static int exynos4x12_get_intspec(unsigned long mifclk) 508static int exynos4x12_get_intspec(unsigned long mifclk)
579{ 509{
580 int i = 0; 510 int i = 0;
@@ -698,84 +628,35 @@ out:
698 return err; 628 return err;
699} 629}
700 630
701static int exynos4_get_busier_dmc(struct busfreq_data *data)
702{
703 u64 p0 = data->dmc[0].count[0];
704 u64 p1 = data->dmc[1].count[0];
705
706 p0 *= data->dmc[1].ccnt;
707 p1 *= data->dmc[0].ccnt;
708
709 if (data->dmc[1].ccnt == 0)
710 return 0;
711
712 if (p0 > p1)
713 return 0;
714 return 1;
715}
716
717static int exynos4_bus_get_dev_status(struct device *dev, 631static int exynos4_bus_get_dev_status(struct device *dev,
718 struct devfreq_dev_status *stat) 632 struct devfreq_dev_status *stat)
719{ 633{
720 struct busfreq_data *data = dev_get_drvdata(dev); 634 struct busfreq_data *data = dev_get_drvdata(dev);
721 int busier_dmc; 635 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
722 int cycles_x2 = 2; /* 2 x cycles */ 636 int busier;
723 void __iomem *addr;
724 u32 timing;
725 u32 memctrl;
726
727 exynos4_read_ppmu(data);
728 busier_dmc = exynos4_get_busier_dmc(data);
729 stat->current_frequency = data->curr_oppinfo.rate;
730 637
731 if (busier_dmc) 638 exynos_read_ppmu(ppmu_data);
732 addr = S5P_VA_DMC1; 639 busier = exynos_get_busier_ppmu(ppmu_data);
733 else 640 stat->current_frequency = data->curr_oppinfo.rate;
734 addr = S5P_VA_DMC0;
735
736 memctrl = __raw_readl(addr + 0x04); /* one of DDR2/3/LPDDR2 */
737 timing = __raw_readl(addr + 0x38); /* CL or WL/RL values */
738
739 switch ((memctrl >> 8) & 0xf) {
740 case 0x4: /* DDR2 */
741 cycles_x2 = ((timing >> 16) & 0xf) * 2;
742 break;
743 case 0x5: /* LPDDR2 */
744 case 0x6: /* DDR3 */
745 cycles_x2 = ((timing >> 8) & 0xf) + ((timing >> 0) & 0xf);
746 break;
747 default:
748 pr_err("%s: Unknown Memory Type(%d).\n", __func__,
749 (memctrl >> 8) & 0xf);
750 return -EINVAL;
751 }
752 641
753 /* Number of cycles spent on memory access */ 642 /* Number of cycles spent on memory access */
754 stat->busy_time = data->dmc[busier_dmc].count[0] / 2 * (cycles_x2 + 2); 643 stat->busy_time = ppmu_data->ppmu[busier].count[PPMU_PMNCNT3];
755 stat->busy_time *= 100 / BUS_SATURATION_RATIO; 644 stat->busy_time *= 100 / BUS_SATURATION_RATIO;
756 stat->total_time = data->dmc[busier_dmc].ccnt; 645 stat->total_time = ppmu_data->ppmu[busier].ccnt;
757 646
758 /* If the counters have overflown, retry */ 647 /* If the counters have overflown, retry */
759 if (data->dmc[busier_dmc].ccnt_overflow || 648 if (ppmu_data->ppmu[busier].ccnt_overflow ||
760 data->dmc[busier_dmc].count_overflow[0]) 649 ppmu_data->ppmu[busier].count_overflow[0])
761 return -EAGAIN; 650 return -EAGAIN;
762 651
763 return 0; 652 return 0;
764} 653}
765 654
766static void exynos4_bus_exit(struct device *dev)
767{
768 struct busfreq_data *data = dev_get_drvdata(dev);
769
770 devfreq_unregister_opp_notifier(dev, data->devfreq);
771}
772
773static struct devfreq_dev_profile exynos4_devfreq_profile = { 655static struct devfreq_dev_profile exynos4_devfreq_profile = {
774 .initial_freq = 400000, 656 .initial_freq = 400000,
775 .polling_ms = 50, 657 .polling_ms = 50,
776 .target = exynos4_bus_target, 658 .target = exynos4_bus_target,
777 .get_dev_status = exynos4_bus_get_dev_status, 659 .get_dev_status = exynos4_bus_get_dev_status,
778 .exit = exynos4_bus_exit,
779}; 660};
780 661
781static int exynos4210_init_tables(struct busfreq_data *data) 662static int exynos4210_init_tables(struct busfreq_data *data)
@@ -837,11 +718,11 @@ static int exynos4210_init_tables(struct busfreq_data *data)
837 data->top_divtable[i] = tmp; 718 data->top_divtable[i] = tmp;
838 } 719 }
839 720
840#ifdef CONFIG_EXYNOS_ASV 721 /*
841 tmp = exynos4_result_of_asv; 722 * TODO: init tmp based on busfreq_data
842#else 723 * (device-tree or platform-data)
724 */
843 tmp = 0; /* Max voltages for the reliability of the unknown */ 725 tmp = 0; /* Max voltages for the reliability of the unknown */
844#endif
845 726
846 pr_debug("ASV Group of Exynos4 is %d\n", tmp); 727 pr_debug("ASV Group of Exynos4 is %d\n", tmp);
847 /* Use merged grouping for voltage */ 728 /* Use merged grouping for voltage */
@@ -922,11 +803,7 @@ static int exynos4x12_init_tables(struct busfreq_data *data)
922 data->dmc_divtable[i] = tmp; 803 data->dmc_divtable[i] = tmp;
923 } 804 }
924 805
925#ifdef CONFIG_EXYNOS_ASV
926 tmp = exynos4_result_of_asv;
927#else
928 tmp = 0; /* Max voltages for the reliability of the unknown */ 806 tmp = 0; /* Max voltages for the reliability of the unknown */
929#endif
930 807
931 if (tmp > 8) 808 if (tmp > 8)
932 tmp = 0; 809 tmp = 0;
@@ -1020,6 +897,7 @@ unlock:
1020static int exynos4_busfreq_probe(struct platform_device *pdev) 897static int exynos4_busfreq_probe(struct platform_device *pdev)
1021{ 898{
1022 struct busfreq_data *data; 899 struct busfreq_data *data;
900 struct busfreq_ppmu_data *ppmu_data;
1023 struct dev_pm_opp *opp; 901 struct dev_pm_opp *opp;
1024 struct device *dev = &pdev->dev; 902 struct device *dev = &pdev->dev;
1025 int err = 0; 903 int err = 0;
@@ -1030,9 +908,19 @@ static int exynos4_busfreq_probe(struct platform_device *pdev)
1030 return -ENOMEM; 908 return -ENOMEM;
1031 } 909 }
1032 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
1033 data->type = pdev->id_entry->driver_data; 921 data->type = pdev->id_entry->driver_data;
1034 data->dmc[0].hw_base = S5P_VA_DMC0; 922 ppmu_data->ppmu[PPMU_DMC0].hw_base = S5P_VA_DMC0;
1035 data->dmc[1].hw_base = S5P_VA_DMC1; 923 ppmu_data->ppmu[PPMU_DMC1].hw_base = S5P_VA_DMC1;
1036 data->pm_notifier.notifier_call = exynos4_busfreq_pm_notifier_event; 924 data->pm_notifier.notifier_call = exynos4_busfreq_pm_notifier_event;
1037 data->dev = dev; 925 data->dev = dev;
1038 mutex_init(&data->lock); 926 mutex_init(&data->lock);
@@ -1048,8 +936,11 @@ static int exynos4_busfreq_probe(struct platform_device *pdev)
1048 dev_err(dev, "Cannot determine the device id %d\n", data->type); 936 dev_err(dev, "Cannot determine the device id %d\n", data->type);
1049 err = -EINVAL; 937 err = -EINVAL;
1050 } 938 }
1051 if (err) 939 if (err) {
940 dev_err(dev, "Cannot initialize busfreq table %d\n",
941 data->type);
1052 return err; 942 return err;
943 }
1053 944
1054 data->vdd_int = devm_regulator_get(dev, "vdd_int"); 945 data->vdd_int = devm_regulator_get(dev, "vdd_int");
1055 if (IS_ERR(data->vdd_int)) { 946 if (IS_ERR(data->vdd_int)) {
@@ -1079,19 +970,28 @@ static int exynos4_busfreq_probe(struct platform_device *pdev)
1079 970
1080 platform_set_drvdata(pdev, data); 971 platform_set_drvdata(pdev, data);
1081 972
1082 busfreq_mon_reset(data); 973 data->devfreq = devm_devfreq_add_device(dev, &exynos4_devfreq_profile,
1083
1084 data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile,
1085 "simple_ondemand", NULL); 974 "simple_ondemand", NULL);
1086 if (IS_ERR(data->devfreq)) 975 if (IS_ERR(data->devfreq))
1087 return PTR_ERR(data->devfreq); 976 return PTR_ERR(data->devfreq);
1088 977
1089 devfreq_register_opp_notifier(dev, data->devfreq); 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);
1090 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 */
1091 err = register_pm_notifier(&data->pm_notifier); 992 err = register_pm_notifier(&data->pm_notifier);
1092 if (err) { 993 if (err) {
1093 dev_err(dev, "Failed to setup pm notifier\n"); 994 dev_err(dev, "Failed to setup pm notifier\n");
1094 devfreq_remove_device(data->devfreq);
1095 return err; 995 return err;
1096 } 996 }
1097 997
@@ -1102,23 +1002,24 @@ static int exynos4_busfreq_remove(struct platform_device *pdev)
1102{ 1002{
1103 struct busfreq_data *data = platform_get_drvdata(pdev); 1003 struct busfreq_data *data = platform_get_drvdata(pdev);
1104 1004
1005 /* Unregister all of notifier chain */
1105 unregister_pm_notifier(&data->pm_notifier); 1006 unregister_pm_notifier(&data->pm_notifier);
1106 devfreq_remove_device(data->devfreq);
1107 1007
1108 return 0; 1008 return 0;
1109} 1009}
1110 1010
1011#ifdef CONFIG_PM_SLEEP
1111static int exynos4_busfreq_resume(struct device *dev) 1012static int exynos4_busfreq_resume(struct device *dev)
1112{ 1013{
1113 struct busfreq_data *data = dev_get_drvdata(dev); 1014 struct busfreq_data *data = dev_get_drvdata(dev);
1015 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
1114 1016
1115 busfreq_mon_reset(data); 1017 busfreq_mon_reset(ppmu_data);
1116 return 0; 1018 return 0;
1117} 1019}
1020#endif
1118 1021
1119static const struct dev_pm_ops exynos4_busfreq_pm = { 1022static SIMPLE_DEV_PM_OPS(exynos4_busfreq_pm_ops, NULL, exynos4_busfreq_resume);
1120 .resume = exynos4_busfreq_resume,
1121};
1122 1023
1123static const struct platform_device_id exynos4_busfreq_id[] = { 1024static const struct platform_device_id exynos4_busfreq_id[] = {
1124 { "exynos4210-busfreq", TYPE_BUSF_EXYNOS4210 }, 1025 { "exynos4210-busfreq", TYPE_BUSF_EXYNOS4210 },
@@ -1134,7 +1035,7 @@ static struct platform_driver exynos4_busfreq_driver = {
1134 .driver = { 1035 .driver = {
1135 .name = "exynos4-busfreq", 1036 .name = "exynos4-busfreq",
1136 .owner = THIS_MODULE, 1037 .owner = THIS_MODULE,
1137 .pm = &exynos4_busfreq_pm, 1038 .pm = &exynos4_busfreq_pm_ops,
1138 }, 1039 },
1139}; 1040};
1140 1041
diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c
index 6eef1f7397c6..6cd0392e2798 100644
--- a/drivers/devfreq/exynos/exynos5_bus.c
+++ b/drivers/devfreq/exynos/exynos5_bus.c
@@ -50,7 +50,7 @@ struct busfreq_data_int {
50 struct device *dev; 50 struct device *dev;
51 struct devfreq *devfreq; 51 struct devfreq *devfreq;
52 struct regulator *vdd_int; 52 struct regulator *vdd_int;
53 struct exynos_ppmu ppmu[PPMU_END]; 53 struct busfreq_ppmu_data ppmu_data;
54 unsigned long curr_freq; 54 unsigned long curr_freq;
55 bool disabled; 55 bool disabled;
56 56
@@ -75,49 +75,6 @@ static struct int_bus_opp_table exynos5_int_opp_table[] = {
75 {0, 0, 0}, 75 {0, 0, 0},
76}; 76};
77 77
78static void busfreq_mon_reset(struct busfreq_data_int *data)
79{
80 unsigned int i;
81
82 for (i = PPMU_RIGHT; i < PPMU_END; i++) {
83 void __iomem *ppmu_base = data->ppmu[i].hw_base;
84
85 /* Reset the performance and cycle counters */
86 exynos_ppmu_reset(ppmu_base);
87
88 /* Setup count registers to monitor read/write transactions */
89 data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT;
90 exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3,
91 data->ppmu[i].event[PPMU_PMNCNT3]);
92
93 exynos_ppmu_start(ppmu_base);
94 }
95}
96
97static void exynos5_read_ppmu(struct busfreq_data_int *data)
98{
99 int i, j;
100
101 for (i = PPMU_RIGHT; i < PPMU_END; i++) {
102 void __iomem *ppmu_base = data->ppmu[i].hw_base;
103
104 exynos_ppmu_stop(ppmu_base);
105
106 /* Update local data from PPMU */
107 data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT);
108
109 for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
110 if (data->ppmu[i].event[j] == 0)
111 data->ppmu[i].count[j] = 0;
112 else
113 data->ppmu[i].count[j] =
114 exynos_ppmu_read(ppmu_base, j);
115 }
116 }
117
118 busfreq_mon_reset(data);
119}
120
121static int exynos5_int_setvolt(struct busfreq_data_int *data, 78static int exynos5_int_setvolt(struct busfreq_data_int *data,
122 unsigned long volt) 79 unsigned long volt)
123{ 80{
@@ -185,59 +142,33 @@ out:
185 return err; 142 return err;
186} 143}
187 144
188static int exynos5_get_busier_dmc(struct busfreq_data_int *data)
189{
190 int i, j;
191 int busy = 0;
192 unsigned int temp = 0;
193
194 for (i = PPMU_RIGHT; i < PPMU_END; i++) {
195 for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
196 if (data->ppmu[i].count[j] > temp) {
197 temp = data->ppmu[i].count[j];
198 busy = i;
199 }
200 }
201 }
202
203 return busy;
204}
205
206static int exynos5_int_get_dev_status(struct device *dev, 145static int exynos5_int_get_dev_status(struct device *dev,
207 struct devfreq_dev_status *stat) 146 struct devfreq_dev_status *stat)
208{ 147{
209 struct platform_device *pdev = container_of(dev, struct platform_device, 148 struct platform_device *pdev = container_of(dev, struct platform_device,
210 dev); 149 dev);
211 struct busfreq_data_int *data = platform_get_drvdata(pdev); 150 struct busfreq_data_int *data = platform_get_drvdata(pdev);
151 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
212 int busier_dmc; 152 int busier_dmc;
213 153
214 exynos5_read_ppmu(data); 154 exynos_read_ppmu(ppmu_data);
215 busier_dmc = exynos5_get_busier_dmc(data); 155 busier_dmc = exynos_get_busier_ppmu(ppmu_data);
216 156
217 stat->current_frequency = data->curr_freq; 157 stat->current_frequency = data->curr_freq;
218 158
219 /* Number of cycles spent on memory access */ 159 /* Number of cycles spent on memory access */
220 stat->busy_time = data->ppmu[busier_dmc].count[PPMU_PMNCNT3]; 160 stat->busy_time = ppmu_data->ppmu[busier_dmc].count[PPMU_PMNCNT3];
221 stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO; 161 stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO;
222 stat->total_time = data->ppmu[busier_dmc].ccnt; 162 stat->total_time = ppmu_data->ppmu[busier_dmc].ccnt;
223 163
224 return 0; 164 return 0;
225} 165}
226static void exynos5_int_exit(struct device *dev)
227{
228 struct platform_device *pdev = container_of(dev, struct platform_device,
229 dev);
230 struct busfreq_data_int *data = platform_get_drvdata(pdev);
231
232 devfreq_unregister_opp_notifier(dev, data->devfreq);
233}
234 166
235static struct devfreq_dev_profile exynos5_devfreq_int_profile = { 167static struct devfreq_dev_profile exynos5_devfreq_int_profile = {
236 .initial_freq = 160000, 168 .initial_freq = 160000,
237 .polling_ms = 100, 169 .polling_ms = 100,
238 .target = exynos5_busfreq_int_target, 170 .target = exynos5_busfreq_int_target,
239 .get_dev_status = exynos5_int_get_dev_status, 171 .get_dev_status = exynos5_int_get_dev_status,
240 .exit = exynos5_int_exit,
241}; 172};
242 173
243static int exynos5250_init_int_tables(struct busfreq_data_int *data) 174static int exynos5250_init_int_tables(struct busfreq_data_int *data)
@@ -315,6 +246,7 @@ unlock:
315static int exynos5_busfreq_int_probe(struct platform_device *pdev) 246static int exynos5_busfreq_int_probe(struct platform_device *pdev)
316{ 247{
317 struct busfreq_data_int *data; 248 struct busfreq_data_int *data;
249 struct busfreq_ppmu_data *ppmu_data;
318 struct dev_pm_opp *opp; 250 struct dev_pm_opp *opp;
319 struct device *dev = &pdev->dev; 251 struct device *dev = &pdev->dev;
320 struct device_node *np; 252 struct device_node *np;
@@ -330,16 +262,26 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
330 return -ENOMEM; 262 return -ENOMEM;
331 } 263 }
332 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
333 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu"); 275 np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu");
334 if (np == NULL) { 276 if (np == NULL) {
335 pr_err("Unable to find PPMU node\n"); 277 pr_err("Unable to find PPMU node\n");
336 return -ENOENT; 278 return -ENOENT;
337 } 279 }
338 280
339 for (i = PPMU_RIGHT; i < PPMU_END; i++) { 281 for (i = 0; i < ppmu_data->ppmu_end; i++) {
340 /* map PPMU memory region */ 282 /* map PPMU memory region */
341 data->ppmu[i].hw_base = of_iomap(np, i); 283 ppmu_data->ppmu[i].hw_base = of_iomap(np, i);
342 if (data->ppmu[i].hw_base == NULL) { 284 if (ppmu_data->ppmu[i].hw_base == NULL) {
343 dev_err(&pdev->dev, "failed to map memory region\n"); 285 dev_err(&pdev->dev, "failed to map memory region\n");
344 return -ENOMEM; 286 return -ENOMEM;
345 } 287 }
@@ -390,32 +332,29 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
390 332
391 platform_set_drvdata(pdev, data); 333 platform_set_drvdata(pdev, data);
392 334
393 busfreq_mon_reset(data); 335 busfreq_mon_reset(ppmu_data);
394 336
395 data->devfreq = devfreq_add_device(dev, &exynos5_devfreq_int_profile, 337 data->devfreq = devm_devfreq_add_device(dev, &exynos5_devfreq_int_profile,
396 "simple_ondemand", NULL); 338 "simple_ondemand", NULL);
339 if (IS_ERR(data->devfreq))
340 return PTR_ERR(data->devfreq);
397 341
398 if (IS_ERR(data->devfreq)) { 342 err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
399 err = PTR_ERR(data->devfreq); 343 if (err < 0) {
400 goto err_devfreq_add; 344 dev_err(dev, "Failed to register opp notifier\n");
345 return err;
401 } 346 }
402 347
403 devfreq_register_opp_notifier(dev, data->devfreq);
404
405 err = register_pm_notifier(&data->pm_notifier); 348 err = register_pm_notifier(&data->pm_notifier);
406 if (err) { 349 if (err) {
407 dev_err(dev, "Failed to setup pm notifier\n"); 350 dev_err(dev, "Failed to setup pm notifier\n");
408 goto err_devfreq_add; 351 return err;
409 } 352 }
410 353
411 /* TODO: Add a new QOS class for int/mif bus */ 354 /* TODO: Add a new QOS class for int/mif bus */
412 pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1); 355 pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1);
413 356
414 return 0; 357 return 0;
415
416err_devfreq_add:
417 devfreq_remove_device(data->devfreq);
418 return err;
419} 358}
420 359
421static int exynos5_busfreq_int_remove(struct platform_device *pdev) 360static int exynos5_busfreq_int_remove(struct platform_device *pdev)
@@ -424,24 +363,27 @@ static int exynos5_busfreq_int_remove(struct platform_device *pdev)
424 363
425 pm_qos_remove_request(&data->int_req); 364 pm_qos_remove_request(&data->int_req);
426 unregister_pm_notifier(&data->pm_notifier); 365 unregister_pm_notifier(&data->pm_notifier);
427 devfreq_remove_device(data->devfreq);
428 366
429 return 0; 367 return 0;
430} 368}
431 369
370#ifdef CONFIG_PM_SLEEP
432static int exynos5_busfreq_int_resume(struct device *dev) 371static int exynos5_busfreq_int_resume(struct device *dev)
433{ 372{
434 struct platform_device *pdev = container_of(dev, struct platform_device, 373 struct platform_device *pdev = container_of(dev, struct platform_device,
435 dev); 374 dev);
436 struct busfreq_data_int *data = platform_get_drvdata(pdev); 375 struct busfreq_data_int *data = platform_get_drvdata(pdev);
376 struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
437 377
438 busfreq_mon_reset(data); 378 busfreq_mon_reset(ppmu_data);
439 return 0; 379 return 0;
440} 380}
441
442static const struct dev_pm_ops exynos5_busfreq_int_pm = { 381static const struct dev_pm_ops exynos5_busfreq_int_pm = {
443 .resume = exynos5_busfreq_int_resume, 382 .resume = exynos5_busfreq_int_resume,
444}; 383};
384#endif
385static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops, NULL,
386 exynos5_busfreq_int_resume);
445 387
446/* platform device pointer for exynos5 devfreq device. */ 388/* platform device pointer for exynos5 devfreq device. */
447static struct platform_device *exynos5_devfreq_pdev; 389static struct platform_device *exynos5_devfreq_pdev;
@@ -452,7 +394,7 @@ static struct platform_driver exynos5_busfreq_int_driver = {
452 .driver = { 394 .driver = {
453 .name = "exynos5-bus-int", 395 .name = "exynos5-bus-int",
454 .owner = THIS_MODULE, 396 .owner = THIS_MODULE,
455 .pm = &exynos5_busfreq_int_pm, 397 .pm = &exynos5_busfreq_int_pm_ops,
456 }, 398 },
457}; 399};
458 400
diff --git a/drivers/devfreq/exynos/exynos_ppmu.c b/drivers/devfreq/exynos/exynos_ppmu.c
index 85fc5ac1036a..75fcc5140ffb 100644
--- a/drivers/devfreq/exynos/exynos_ppmu.c
+++ b/drivers/devfreq/exynos/exynos_ppmu.c
@@ -54,3 +54,63 @@ unsigned int exynos_ppmu_read(void __iomem *ppmu_base, unsigned int ch)
54 54
55 return total; 55 return total;
56} 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}
76
77void exynos_read_ppmu(struct busfreq_ppmu_data *ppmu_data)
78{
79 int i, j;
80
81 for (i = 0; i < ppmu_data->ppmu_end; i++) {
82 void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base;
83
84 exynos_ppmu_stop(ppmu_base);
85
86 /* Update local data from PPMU */
87 ppmu_data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT);
88
89 for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
90 if (ppmu_data->ppmu[i].event[j] == 0)
91 ppmu_data->ppmu[i].count[j] = 0;
92 else
93 ppmu_data->ppmu[i].count[j] =
94 exynos_ppmu_read(ppmu_base, j);
95 }
96 }
97
98 busfreq_mon_reset(ppmu_data);
99}
100
101int exynos_get_busier_ppmu(struct busfreq_ppmu_data *ppmu_data)
102{
103 unsigned int count = 0;
104 int i, j, busy = 0;
105
106 for (i = 0; i < ppmu_data->ppmu_end; i++) {
107 for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
108 if (ppmu_data->ppmu[i].count[j] > count) {
109 count = ppmu_data->ppmu[i].count[j];
110 busy = i;
111 }
112 }
113 }
114
115 return busy;
116}
diff --git a/drivers/devfreq/exynos/exynos_ppmu.h b/drivers/devfreq/exynos/exynos_ppmu.h
index 7dfb221eaccd..71f17ba3563c 100644
--- a/drivers/devfreq/exynos/exynos_ppmu.h
+++ b/drivers/devfreq/exynos/exynos_ppmu.h
@@ -69,10 +69,18 @@ struct exynos_ppmu {
69 bool count_overflow[PPMU_PMNCNT_MAX]; 69 bool count_overflow[PPMU_PMNCNT_MAX];
70}; 70};
71 71
72struct busfreq_ppmu_data {
73 struct exynos_ppmu *ppmu;
74 int ppmu_end;
75};
76
72void exynos_ppmu_reset(void __iomem *ppmu_base); 77void exynos_ppmu_reset(void __iomem *ppmu_base);
73void exynos_ppmu_setevent(void __iomem *ppmu_base, unsigned int ch, 78void exynos_ppmu_setevent(void __iomem *ppmu_base, unsigned int ch,
74 unsigned int evt); 79 unsigned int evt);
75void exynos_ppmu_start(void __iomem *ppmu_base); 80void exynos_ppmu_start(void __iomem *ppmu_base);
76void exynos_ppmu_stop(void __iomem *ppmu_base); 81void exynos_ppmu_stop(void __iomem *ppmu_base);
77unsigned int exynos_ppmu_read(void __iomem *ppmu_base, unsigned int ch); 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);
78#endif /* __DEVFREQ_EXYNOS_PPMU_H */ 86#endif /* __DEVFREQ_EXYNOS_PPMU_H */
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index d48dc00232a4..f1863dcd83ea 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -181,6 +181,12 @@ extern struct devfreq *devfreq_add_device(struct device *dev,
181 const char *governor_name, 181 const char *governor_name,
182 void *data); 182 void *data);
183extern int devfreq_remove_device(struct devfreq *devfreq); 183extern int devfreq_remove_device(struct devfreq *devfreq);
184extern struct devfreq *devm_devfreq_add_device(struct device *dev,
185 struct devfreq_dev_profile *profile,
186 const char *governor_name,
187 void *data);
188extern void devm_devfreq_remove_device(struct device *dev,
189 struct devfreq *devfreq);
184 190
185/* Supposed to be called by PM_SLEEP/PM_RUNTIME callbacks */ 191/* Supposed to be called by PM_SLEEP/PM_RUNTIME callbacks */
186extern int devfreq_suspend_device(struct devfreq *devfreq); 192extern int devfreq_suspend_device(struct devfreq *devfreq);
@@ -193,6 +199,10 @@ extern int devfreq_register_opp_notifier(struct device *dev,
193 struct devfreq *devfreq); 199 struct devfreq *devfreq);
194extern int devfreq_unregister_opp_notifier(struct device *dev, 200extern int devfreq_unregister_opp_notifier(struct device *dev,
195 struct devfreq *devfreq); 201 struct devfreq *devfreq);
202extern int devm_devfreq_register_opp_notifier(struct device *dev,
203 struct devfreq *devfreq);
204extern void devm_devfreq_unregister_opp_notifier(struct device *dev,
205 struct devfreq *devfreq);
196 206
197#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) 207#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
198/** 208/**
@@ -220,7 +230,7 @@ static inline struct devfreq *devfreq_add_device(struct device *dev,
220 const char *governor_name, 230 const char *governor_name,
221 void *data) 231 void *data)
222{ 232{
223 return NULL; 233 return ERR_PTR(-ENOSYS);
224} 234}
225 235
226static inline int devfreq_remove_device(struct devfreq *devfreq) 236static inline int devfreq_remove_device(struct devfreq *devfreq)
@@ -228,6 +238,19 @@ static inline int devfreq_remove_device(struct devfreq *devfreq)
228 return 0; 238 return 0;
229} 239}
230 240
241static inline struct devfreq *devm_devfreq_add_device(struct device *dev,
242 struct devfreq_dev_profile *profile,
243 const char *governor_name,
244 void *data)
245{
246 return ERR_PTR(-ENOSYS);
247}
248
249static inline void devm_devfreq_remove_device(struct device *dev,
250 struct devfreq *devfreq)
251{
252}
253
231static inline int devfreq_suspend_device(struct devfreq *devfreq) 254static inline int devfreq_suspend_device(struct devfreq *devfreq)
232{ 255{
233 return 0; 256 return 0;
@@ -256,6 +279,16 @@ static inline int devfreq_unregister_opp_notifier(struct device *dev,
256 return -EINVAL; 279 return -EINVAL;
257} 280}
258 281
282static inline int devm_devfreq_register_opp_notifier(struct device *dev,
283 struct devfreq *devfreq)
284{
285 return -EINVAL;
286}
287
288static inline void devm_devfreq_unregister_opp_notifier(struct device *dev,
289 struct devfreq *devfreq)
290{
291}
259#endif /* CONFIG_PM_DEVFREQ */ 292#endif /* CONFIG_PM_DEVFREQ */
260 293
261#endif /* __LINUX_DEVFREQ_H__ */ 294#endif /* __LINUX_DEVFREQ_H__ */