aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/devfreq/devfreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r--drivers/devfreq/devfreq.c78
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 */
91static 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
924static 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
930static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, 970static 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}
956static DEVICE_ATTR_RW(min_freq);
957 996
958static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr, 997#define show_one(name) \
959 char *buf) 998static 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}
1003show_one(min_freq);
1004show_one(max_freq);
1005
1006static DEVICE_ATTR_RW(min_freq);
963static DEVICE_ATTR_RW(max_freq); 1007static DEVICE_ATTR_RW(max_freq);
964 1008
965static ssize_t available_frequencies_show(struct device *d, 1009static 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]));