linux/arch/arm/mach-ux500/cpufreq.c
<<
>>
Prefs
   1/*
   2 * CPU frequency scaling for u8500
   3 * Inspired by linux/arch/arm/mach-davinci/cpufreq.c
   4 *
   5 * Copyright (C) STMicroelectronics 2009
   6 * Copyright (C) ST-Ericsson SA 2010
   7 *
   8 * License Terms: GNU General Public License v2
   9 *
  10 * Author: Sundar Iyer <sundar.iyer@stericsson.com>
  11 * Author: Martin Persson <martin.persson@stericsson.com>
  12 * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
  13 *
  14 */
  15
  16#include <linux/platform_device.h>
  17#include <linux/kernel.h>
  18#include <linux/cpufreq.h>
  19#include <linux/delay.h>
  20
  21#include <mach/hardware.h>
  22#include <mach/prcmu.h>
  23#include <mach/prcmu-defs.h>
  24
  25#define DRIVER_NAME "cpufreq-u8500"
  26#define CPUFREQ_NAME "u8500"
  27
  28static struct device *dev;
  29
  30static struct cpufreq_frequency_table freq_table[] = {
  31        [0] = {
  32                .index = 0,
  33                .frequency = 200000,
  34        },
  35        [1] = {
  36                .index = 1,
  37                .frequency = 300000,
  38        },
  39        [2] = {
  40                .index = 2,
  41                .frequency = 600000,
  42        },
  43        [3] = {
  44                /* Used for CPU_OPP_MAX, if available */
  45                .index = 3,
  46                .frequency = CPUFREQ_TABLE_END,
  47        },
  48        [4] = {
  49                .index = 4,
  50                .frequency = CPUFREQ_TABLE_END,
  51        },
  52};
  53
  54static enum prcmu_cpu_opp index2opp[] = {
  55        CPU_OPP_EXT_CLK,
  56        CPU_OPP_50,
  57        CPU_OPP_100,
  58        CPU_OPP_MAX
  59};
  60
  61static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy)
  62{
  63        return cpufreq_frequency_table_verify(policy, freq_table);
  64}
  65
  66static int u8500_cpufreq_target(struct cpufreq_policy *policy,
  67                                unsigned int target_freq,
  68                                unsigned int relation)
  69{
  70        struct cpufreq_freqs freqs;
  71        unsigned int index;
  72        int ret = 0;
  73
  74        /*
  75         * Ensure desired rate is within allowed range.  Some govenors
  76         * (ondemand) will just pass target_freq=0 to get the minimum.
  77         */
  78        if (target_freq < policy->cpuinfo.min_freq)
  79                target_freq = policy->cpuinfo.min_freq;
  80        if (target_freq > policy->cpuinfo.max_freq)
  81                target_freq = policy->cpuinfo.max_freq;
  82
  83        ret = cpufreq_frequency_table_target(policy, freq_table,
  84                                             target_freq, relation, &index);
  85        if (ret < 0) {
  86                dev_err(dev, "Could not look up next frequency\n");
  87                return ret;
  88        }
  89
  90        freqs.old = policy->cur;
  91        freqs.new = freq_table[index].frequency;
  92        freqs.cpu = policy->cpu;
  93
  94        if (freqs.old == freqs.new) {
  95                dev_dbg(dev, "Current and target frequencies are equal\n");
  96                return 0;
  97        }
  98
  99        dev_dbg(dev, "transition: %u --> %u\n", freqs.old, freqs.new);
 100        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 101
 102        ret = prcmu_set_cpu_opp(index2opp[index]);
 103        if (ret < 0) {
 104                dev_err(dev, "Failed to set OPP level\n");
 105                return ret;
 106        }
 107
 108        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 109
 110        return ret;
 111}
 112
 113static unsigned int u8500_cpufreq_getspeed(unsigned int cpu)
 114{
 115        int i;
 116
 117        for (i = 0; prcmu_get_cpu_opp() != index2opp[i]; i++)
 118                ;
 119        return freq_table[i].frequency;
 120}
 121
 122static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy)
 123{
 124        int res;
 125
 126        BUILD_BUG_ON(ARRAY_SIZE(index2opp) + 1 != ARRAY_SIZE(freq_table));
 127
 128        if (cpu_is_u8500v2()) {
 129                freq_table[1].frequency = 400000;
 130                freq_table[2].frequency = 800000;
 131                if (prcmu_has_arm_maxopp())
 132                        freq_table[3].frequency = 1000000;
 133        }
 134
 135        /* get policy fields based on the table */
 136        res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
 137        if (!res)
 138                cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
 139        else {
 140                dev_err(dev, "u8500-cpufreq : Failed to read policy table\n");
 141                return res;
 142        }
 143
 144        policy->min = policy->cpuinfo.min_freq;
 145        policy->max = policy->cpuinfo.max_freq;
 146        policy->cur = u8500_cpufreq_getspeed(policy->cpu);
 147        policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 148
 149        /*
 150         * FIXME : Need to take time measurement across the target()
 151         *         function with no/some/all drivers in the notification
 152         *         list.
 153         */
 154        policy->cpuinfo.transition_latency = 200 * 1000; /* in ns */
 155
 156        /* policy sharing between dual CPUs */
 157        cpumask_copy(policy->cpus, &cpu_present_map);
 158
 159        policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
 160
 161        return res;
 162}
 163
 164static struct freq_attr *u8500_cpufreq_attr[] = {
 165        &cpufreq_freq_attr_scaling_available_freqs,
 166        NULL,
 167};
 168static int u8500_cpu_exit(struct cpufreq_policy *policy)
 169{
 170        cpufreq_frequency_table_put_attr(policy->cpu);
 171        return 0;
 172}
 173
 174static struct cpufreq_driver u8500_driver = {
 175        .owner = THIS_MODULE,
 176        .flags = CPUFREQ_STICKY,
 177        .verify = u8500_cpufreq_verify_speed,
 178        .target = u8500_cpufreq_target,
 179        .get = u8500_cpufreq_getspeed,
 180        .init = u8500_cpu_init,
 181        .exit = u8500_cpu_exit,
 182        .name = CPUFREQ_NAME,
 183        .attr = u8500_cpufreq_attr,
 184};
 185
 186static int __init u8500_cpufreq_probe(struct platform_device *pdev)
 187{
 188        dev = &pdev->dev;
 189        return cpufreq_register_driver(&u8500_driver);
 190}
 191
 192static int __exit u8500_cpufreq_remove(struct platform_device *pdev)
 193{
 194        return cpufreq_unregister_driver(&u8500_driver);
 195}
 196
 197static struct platform_driver u8500_cpufreq_driver = {
 198        .driver = {
 199                .name    = DRIVER_NAME,
 200                .owner   = THIS_MODULE,
 201        },
 202        .remove = __exit_p(u8500_cpufreq_remove),
 203};
 204
 205static int __init u8500_cpufreq_init(void)
 206{
 207        return platform_driver_probe(&u8500_cpufreq_driver,
 208                                     &u8500_cpufreq_probe);
 209}
 210
 211device_initcall(u8500_cpufreq_init);
 212