diff options
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r-- | drivers/devfreq/devfreq.c | 78 |
1 files changed, 62 insertions, 16 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index ca848cc6a8fd..984c5e9e7bdd 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
@@ -85,6 +85,46 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | /** | 87 | /** |
88 | * devfreq_set_freq_table() - Initialize freq_table for the frequency | ||
89 | * @devfreq: the devfreq instance | ||
90 | */ | ||
91 | static void devfreq_set_freq_table(struct devfreq *devfreq) | ||
92 | { | ||
93 | struct devfreq_dev_profile *profile = devfreq->profile; | ||
94 | struct dev_pm_opp *opp; | ||
95 | unsigned long freq; | ||
96 | int i, count; | ||
97 | |||
98 | /* Initialize the freq_table from OPP table */ | ||
99 | count = dev_pm_opp_get_opp_count(devfreq->dev.parent); | ||
100 | if (count <= 0) | ||
101 | return; | ||
102 | |||
103 | profile->max_state = count; | ||
104 | profile->freq_table = devm_kcalloc(devfreq->dev.parent, | ||
105 | profile->max_state, | ||
106 | sizeof(*profile->freq_table), | ||
107 | GFP_KERNEL); | ||
108 | if (!profile->freq_table) { | ||
109 | profile->max_state = 0; | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | rcu_read_lock(); | ||
114 | for (i = 0, freq = 0; i < profile->max_state; i++, freq++) { | ||
115 | opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq); | ||
116 | if (IS_ERR(opp)) { | ||
117 | devm_kfree(devfreq->dev.parent, profile->freq_table); | ||
118 | profile->max_state = 0; | ||
119 | rcu_read_unlock(); | ||
120 | return; | ||
121 | } | ||
122 | profile->freq_table[i] = freq; | ||
123 | } | ||
124 | rcu_read_unlock(); | ||
125 | } | ||
126 | |||
127 | /** | ||
88 | * devfreq_update_status() - Update statistics of devfreq behavior | 128 | * devfreq_update_status() - Update statistics of devfreq behavior |
89 | * @devfreq: the devfreq instance | 129 | * @devfreq: the devfreq instance |
90 | * @freq: the update target frequency | 130 | * @freq: the update target frequency |
@@ -478,6 +518,12 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
478 | devfreq->data = data; | 518 | devfreq->data = data; |
479 | devfreq->nb.notifier_call = devfreq_notifier_call; | 519 | devfreq->nb.notifier_call = devfreq_notifier_call; |
480 | 520 | ||
521 | if (!devfreq->profile->max_state && !devfreq->profile->freq_table) { | ||
522 | mutex_unlock(&devfreq->lock); | ||
523 | devfreq_set_freq_table(devfreq); | ||
524 | mutex_lock(&devfreq->lock); | ||
525 | } | ||
526 | |||
481 | devfreq->trans_table = devm_kzalloc(dev, sizeof(unsigned int) * | 527 | devfreq->trans_table = devm_kzalloc(dev, sizeof(unsigned int) * |
482 | devfreq->profile->max_state * | 528 | devfreq->profile->max_state * |
483 | devfreq->profile->max_state, | 529 | devfreq->profile->max_state, |
@@ -921,12 +967,6 @@ unlock: | |||
921 | return ret; | 967 | return ret; |
922 | } | 968 | } |
923 | 969 | ||
924 | static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr, | ||
925 | char *buf) | ||
926 | { | ||
927 | return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq); | ||
928 | } | ||
929 | |||
930 | static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, | 970 | static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, |
931 | const char *buf, size_t count) | 971 | const char *buf, size_t count) |
932 | { | 972 | { |
@@ -953,13 +993,17 @@ unlock: | |||
953 | mutex_unlock(&df->lock); | 993 | mutex_unlock(&df->lock); |
954 | return ret; | 994 | return ret; |
955 | } | 995 | } |
956 | static DEVICE_ATTR_RW(min_freq); | ||
957 | 996 | ||
958 | static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr, | 997 | #define show_one(name) \ |
959 | char *buf) | 998 | static ssize_t name##_show \ |
960 | { | 999 | (struct device *dev, struct device_attribute *attr, char *buf) \ |
961 | return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq); | 1000 | { \ |
1001 | return sprintf(buf, "%lu\n", to_devfreq(dev)->name); \ | ||
962 | } | 1002 | } |
1003 | show_one(min_freq); | ||
1004 | show_one(max_freq); | ||
1005 | |||
1006 | static DEVICE_ATTR_RW(min_freq); | ||
963 | static DEVICE_ATTR_RW(max_freq); | 1007 | static DEVICE_ATTR_RW(max_freq); |
964 | 1008 | ||
965 | static ssize_t available_frequencies_show(struct device *d, | 1009 | static ssize_t available_frequencies_show(struct device *d, |
@@ -1005,11 +1049,13 @@ static ssize_t trans_stat_show(struct device *dev, | |||
1005 | if (!devfreq->stop_polling && | 1049 | if (!devfreq->stop_polling && |
1006 | devfreq_update_status(devfreq, devfreq->previous_freq)) | 1050 | devfreq_update_status(devfreq, devfreq->previous_freq)) |
1007 | return 0; | 1051 | return 0; |
1052 | if (max_state == 0) | ||
1053 | return sprintf(buf, "Not Supported.\n"); | ||
1008 | 1054 | ||
1009 | len = sprintf(buf, " From : To\n"); | 1055 | len = sprintf(buf, " From : To\n"); |
1010 | len += sprintf(buf + len, " :"); | 1056 | len += sprintf(buf + len, " :"); |
1011 | for (i = 0; i < max_state; i++) | 1057 | for (i = 0; i < max_state; i++) |
1012 | len += sprintf(buf + len, "%8u", | 1058 | len += sprintf(buf + len, "%10lu", |
1013 | devfreq->profile->freq_table[i]); | 1059 | devfreq->profile->freq_table[i]); |
1014 | 1060 | ||
1015 | len += sprintf(buf + len, " time(ms)\n"); | 1061 | len += sprintf(buf + len, " time(ms)\n"); |
@@ -1021,10 +1067,10 @@ static ssize_t trans_stat_show(struct device *dev, | |||
1021 | } else { | 1067 | } else { |
1022 | len += sprintf(buf + len, " "); | 1068 | len += sprintf(buf + len, " "); |
1023 | } | 1069 | } |
1024 | len += sprintf(buf + len, "%8u:", | 1070 | len += sprintf(buf + len, "%10lu:", |
1025 | devfreq->profile->freq_table[i]); | 1071 | devfreq->profile->freq_table[i]); |
1026 | for (j = 0; j < max_state; j++) | 1072 | for (j = 0; j < max_state; j++) |
1027 | len += sprintf(buf + len, "%8u", | 1073 | len += sprintf(buf + len, "%10u", |
1028 | devfreq->trans_table[(i * max_state) + j]); | 1074 | devfreq->trans_table[(i * max_state) + j]); |
1029 | len += sprintf(buf + len, "%10u\n", | 1075 | len += sprintf(buf + len, "%10u\n", |
1030 | jiffies_to_msecs(devfreq->time_in_state[i])); | 1076 | jiffies_to_msecs(devfreq->time_in_state[i])); |