linux/drivers/devfreq/governor_simpleondemand.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/devfreq/governor_simpleondemand.c
   3 *
   4 *  Copyright (C) 2011 Samsung Electronics
   5 *      MyungJoo Ham <myungjoo.ham@samsung.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/errno.h>
  13#include <linux/devfreq.h>
  14#include <linux/math64.h>
  15
  16/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
  17#define DFSO_UPTHRESHOLD        (90)
  18#define DFSO_DOWNDIFFERENCTIAL  (5)
  19static int devfreq_simple_ondemand_func(struct devfreq *df,
  20                                        unsigned long *freq)
  21{
  22        struct devfreq_dev_status stat;
  23        int err = df->profile->get_dev_status(df->dev.parent, &stat);
  24        unsigned long long a, b;
  25        unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
  26        unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
  27        struct devfreq_simple_ondemand_data *data = df->data;
  28        unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX;
  29
  30        if (err)
  31                return err;
  32
  33        if (data) {
  34                if (data->upthreshold)
  35                        dfso_upthreshold = data->upthreshold;
  36                if (data->downdifferential)
  37                        dfso_downdifferential = data->downdifferential;
  38        }
  39        if (dfso_upthreshold > 100 ||
  40            dfso_upthreshold < dfso_downdifferential)
  41                return -EINVAL;
  42
  43        /* Assume MAX if it is going to be divided by zero */
  44        if (stat.total_time == 0) {
  45                *freq = max;
  46                return 0;
  47        }
  48
  49        /* Prevent overflow */
  50        if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) {
  51                stat.busy_time >>= 7;
  52                stat.total_time >>= 7;
  53        }
  54
  55        /* Set MAX if it's busy enough */
  56        if (stat.busy_time * 100 >
  57            stat.total_time * dfso_upthreshold) {
  58                *freq = max;
  59                return 0;
  60        }
  61
  62        /* Set MAX if we do not know the initial frequency */
  63        if (stat.current_frequency == 0) {
  64                *freq = max;
  65                return 0;
  66        }
  67
  68        /* Keep the current frequency */
  69        if (stat.busy_time * 100 >
  70            stat.total_time * (dfso_upthreshold - dfso_downdifferential)) {
  71                *freq = stat.current_frequency;
  72                return 0;
  73        }
  74
  75        /* Set the desired frequency based on the load */
  76        a = stat.busy_time;
  77        a *= stat.current_frequency;
  78        b = div_u64(a, stat.total_time);
  79        b *= 100;
  80        b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
  81        *freq = (unsigned long) b;
  82
  83        if (df->min_freq && *freq < df->min_freq)
  84                *freq = df->min_freq;
  85        if (df->max_freq && *freq > df->max_freq)
  86                *freq = df->max_freq;
  87
  88        return 0;
  89}
  90
  91const struct devfreq_governor devfreq_simple_ondemand = {
  92        .name = "simple_ondemand",
  93        .get_target_freq = devfreq_simple_ondemand_func,
  94};
  95
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.