Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.0-rc6 169 lines 4.1 kB view raw
1/* 2 * Copyright (C) STMicroelectronics 2009 3 * Copyright (C) ST-Ericsson SA 2010 4 * 5 * License Terms: GNU General Public License v2 6 * Author: Sundar Iyer <sundar.iyer@stericsson.com> 7 * Author: Martin Persson <martin.persson@stericsson.com> 8 * Author: Jonas Aaberg <jonas.aberg@stericsson.com> 9 * 10 */ 11#include <linux/kernel.h> 12#include <linux/cpufreq.h> 13#include <linux/delay.h> 14#include <linux/slab.h> 15#include <linux/mfd/db8500-prcmu.h> 16#include <mach/id.h> 17 18static struct cpufreq_frequency_table freq_table[] = { 19 [0] = { 20 .index = 0, 21 .frequency = 300000, 22 }, 23 [1] = { 24 .index = 1, 25 .frequency = 600000, 26 }, 27 [2] = { 28 /* Used for MAX_OPP, if available */ 29 .index = 2, 30 .frequency = CPUFREQ_TABLE_END, 31 }, 32 [3] = { 33 .index = 3, 34 .frequency = CPUFREQ_TABLE_END, 35 }, 36}; 37 38static enum arm_opp idx2opp[] = { 39 ARM_50_OPP, 40 ARM_100_OPP, 41 ARM_MAX_OPP 42}; 43 44static struct freq_attr *db8500_cpufreq_attr[] = { 45 &cpufreq_freq_attr_scaling_available_freqs, 46 NULL, 47}; 48 49static int db8500_cpufreq_verify_speed(struct cpufreq_policy *policy) 50{ 51 return cpufreq_frequency_table_verify(policy, freq_table); 52} 53 54static int db8500_cpufreq_target(struct cpufreq_policy *policy, 55 unsigned int target_freq, 56 unsigned int relation) 57{ 58 struct cpufreq_freqs freqs; 59 unsigned int idx; 60 61 /* scale the target frequency to one of the extremes supported */ 62 if (target_freq < policy->cpuinfo.min_freq) 63 target_freq = policy->cpuinfo.min_freq; 64 if (target_freq > policy->cpuinfo.max_freq) 65 target_freq = policy->cpuinfo.max_freq; 66 67 /* Lookup the next frequency */ 68 if (cpufreq_frequency_table_target 69 (policy, freq_table, target_freq, relation, &idx)) { 70 return -EINVAL; 71 } 72 73 freqs.old = policy->cur; 74 freqs.new = freq_table[idx].frequency; 75 freqs.cpu = policy->cpu; 76 77 if (freqs.old == freqs.new) 78 return 0; 79 80 /* pre-change notification */ 81 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 82 83 /* request the PRCM unit for opp change */ 84 if (prcmu_set_arm_opp(idx2opp[idx])) { 85 pr_err("db8500-cpufreq: Failed to set OPP level\n"); 86 return -EINVAL; 87 } 88 89 /* post change notification */ 90 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 91 92 return 0; 93} 94 95static unsigned int db8500_cpufreq_getspeed(unsigned int cpu) 96{ 97 int i; 98 /* request the prcm to get the current ARM opp */ 99 for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++) 100 ; 101 return freq_table[i].frequency; 102} 103 104static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) 105{ 106 int res; 107 int i; 108 109 BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); 110 111 if (cpu_is_u8500v2() && !prcmu_is_u8400()) { 112 freq_table[0].frequency = 400000; 113 freq_table[1].frequency = 800000; 114 if (prcmu_has_arm_maxopp()) 115 freq_table[2].frequency = 1000000; 116 } 117 118 /* get policy fields based on the table */ 119 res = cpufreq_frequency_table_cpuinfo(policy, freq_table); 120 if (!res) 121 cpufreq_frequency_table_get_attr(freq_table, policy->cpu); 122 else { 123 pr_err("db8500-cpufreq : Failed to read policy table\n"); 124 return res; 125 } 126 127 policy->min = policy->cpuinfo.min_freq; 128 policy->max = policy->cpuinfo.max_freq; 129 policy->cur = db8500_cpufreq_getspeed(policy->cpu); 130 131 for (i = 0; freq_table[i].frequency != policy->cur; i++) 132 ; 133 134 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 135 136 /* 137 * FIXME : Need to take time measurement across the target() 138 * function with no/some/all drivers in the notification 139 * list. 140 */ 141 policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */ 142 143 /* policy sharing between dual CPUs */ 144 cpumask_copy(policy->cpus, &cpu_present_map); 145 146 policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; 147 148 return 0; 149} 150 151static struct cpufreq_driver db8500_cpufreq_driver = { 152 .flags = CPUFREQ_STICKY, 153 .verify = db8500_cpufreq_verify_speed, 154 .target = db8500_cpufreq_target, 155 .get = db8500_cpufreq_getspeed, 156 .init = db8500_cpufreq_init, 157 .name = "DB8500", 158 .attr = db8500_cpufreq_attr, 159}; 160 161static int __init db8500_cpufreq_register(void) 162{ 163 if (!cpu_is_u8500v20_or_later()) 164 return -ENODEV; 165 166 pr_info("cpufreq for DB8500 started\n"); 167 return cpufreq_register_driver(&db8500_cpufreq_driver); 168} 169device_initcall(db8500_cpufreq_register);