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

cpufreq: update DB8500 cpufreq driver

This updates the ux500 cpufreq driver to the new interface from the
updated DB8500 PRCMU

Cc: Arnd Bergmann <arnd@arndb.de>
Acked-by: Dave Jones <davej@redhat.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

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