0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/errno.h>
0010 #include <linux/module.h>
0011 #include <linux/devfreq.h>
0012 #include <linux/math64.h>
0013 #include "governor.h"
0014
0015
0016 #define DFSO_UPTHRESHOLD (90)
0017 #define DFSO_DOWNDIFFERENCTIAL (5)
0018 static int devfreq_simple_ondemand_func(struct devfreq *df,
0019 unsigned long *freq)
0020 {
0021 int err;
0022 struct devfreq_dev_status *stat;
0023 unsigned long long a, b;
0024 unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
0025 unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
0026 struct devfreq_simple_ondemand_data *data = df->data;
0027
0028 err = devfreq_update_stats(df);
0029 if (err)
0030 return err;
0031
0032 stat = &df->last_status;
0033
0034 if (data) {
0035 if (data->upthreshold)
0036 dfso_upthreshold = data->upthreshold;
0037 if (data->downdifferential)
0038 dfso_downdifferential = data->downdifferential;
0039 }
0040 if (dfso_upthreshold > 100 ||
0041 dfso_upthreshold < dfso_downdifferential)
0042 return -EINVAL;
0043
0044
0045 if (stat->total_time == 0) {
0046 *freq = DEVFREQ_MAX_FREQ;
0047 return 0;
0048 }
0049
0050
0051 if (stat->busy_time >= (1 << 24) || stat->total_time >= (1 << 24)) {
0052 stat->busy_time >>= 7;
0053 stat->total_time >>= 7;
0054 }
0055
0056
0057 if (stat->busy_time * 100 >
0058 stat->total_time * dfso_upthreshold) {
0059 *freq = DEVFREQ_MAX_FREQ;
0060 return 0;
0061 }
0062
0063
0064 if (stat->current_frequency == 0) {
0065 *freq = DEVFREQ_MAX_FREQ;
0066 return 0;
0067 }
0068
0069
0070 if (stat->busy_time * 100 >
0071 stat->total_time * (dfso_upthreshold - dfso_downdifferential)) {
0072 *freq = stat->current_frequency;
0073 return 0;
0074 }
0075
0076
0077 a = stat->busy_time;
0078 a *= stat->current_frequency;
0079 b = div_u64(a, stat->total_time);
0080 b *= 100;
0081 b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
0082 *freq = (unsigned long) b;
0083
0084 return 0;
0085 }
0086
0087 static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
0088 unsigned int event, void *data)
0089 {
0090 switch (event) {
0091 case DEVFREQ_GOV_START:
0092 devfreq_monitor_start(devfreq);
0093 break;
0094
0095 case DEVFREQ_GOV_STOP:
0096 devfreq_monitor_stop(devfreq);
0097 break;
0098
0099 case DEVFREQ_GOV_UPDATE_INTERVAL:
0100 devfreq_update_interval(devfreq, (unsigned int *)data);
0101 break;
0102
0103 case DEVFREQ_GOV_SUSPEND:
0104 devfreq_monitor_suspend(devfreq);
0105 break;
0106
0107 case DEVFREQ_GOV_RESUME:
0108 devfreq_monitor_resume(devfreq);
0109 break;
0110
0111 default:
0112 break;
0113 }
0114
0115 return 0;
0116 }
0117
0118 static struct devfreq_governor devfreq_simple_ondemand = {
0119 .name = DEVFREQ_GOV_SIMPLE_ONDEMAND,
0120 .attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL
0121 | DEVFREQ_GOV_ATTR_TIMER,
0122 .get_target_freq = devfreq_simple_ondemand_func,
0123 .event_handler = devfreq_simple_ondemand_handler,
0124 };
0125
0126 static int __init devfreq_simple_ondemand_init(void)
0127 {
0128 return devfreq_add_governor(&devfreq_simple_ondemand);
0129 }
0130 subsys_initcall(devfreq_simple_ondemand_init);
0131
0132 static void __exit devfreq_simple_ondemand_exit(void)
0133 {
0134 int ret;
0135
0136 ret = devfreq_remove_governor(&devfreq_simple_ondemand);
0137 if (ret)
0138 pr_err("%s: failed remove governor %d\n", __func__, ret);
0139
0140 return;
0141 }
0142 module_exit(devfreq_simple_ondemand_exit);
0143 MODULE_LICENSE("GPL");