1 /* 2 * This file provides the ACPI based P-state support. This 3 * module works with generic cpufreq infrastructure. Most of 4 * the code is based on i386 version 5 * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c) 6 * 7 * Copyright (C) 2005 Intel Corp 8 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> 9 */ 10 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13 #include <linux/kernel.h> 14 #include <linux/slab.h> 15 #include <linux/module.h> 16 #include <linux/init.h> 17 #include <linux/cpufreq.h> 18 #include <linux/proc_fs.h> 19 #include <asm/io.h> 20 #include <linux/uaccess.h> 21 #include <asm/pal.h> 22 23 #include <linux/acpi.h> 24 #include <acpi/processor.h> 25 26 MODULE_AUTHOR("Venkatesh Pallipadi"); 27 MODULE_DESCRIPTION("ACPI Processor P-States Driver"); 28 MODULE_LICENSE("GPL"); 29 30 struct cpufreq_acpi_io { 31 struct acpi_processor_performance acpi_data; 32 unsigned int resume; 33 }; 34 35 struct cpufreq_acpi_req { 36 unsigned int cpu; 37 unsigned int state; 38 }; 39 40 static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS]; 41 42 static struct cpufreq_driver acpi_cpufreq_driver; 43 44 45 static int 46 processor_set_pstate ( 47 u32 value) 48 { 49 s64 retval; 50 51 pr_debug("processor_set_pstate\n"); 52 53 retval = ia64_pal_set_pstate((u64)value); 54 55 if (retval) { 56 pr_debug("Failed to set freq to 0x%x, with error 0x%lx\n", 57 value, retval); 58 return -ENODEV; 59 } 60 return (int)retval; 61 } 62 63 64 static int 65 processor_get_pstate ( 66 u32 *value) 67 { 68 u64 pstate_index = 0; 69 s64 retval; 70 71 pr_debug("processor_get_pstate\n"); 72 73 retval = ia64_pal_get_pstate(&pstate_index, 74 PAL_GET_PSTATE_TYPE_INSTANT); 75 *value = (u32) pstate_index; 76 77 if (retval) 78 pr_debug("Failed to get current freq with " 79 "error 0x%lx, idx 0x%x\n", retval, *value); 80 81 return (int)retval; 82 } 83 84 85 /* To be used only after data->acpi_data is initialized */ 86 static unsigned 87 extract_clock ( 88 struct cpufreq_acpi_io *data, 89 unsigned value) 90 { 91 unsigned long i; 92 93 pr_debug("extract_clock\n"); 94 95 for (i = 0; i < data->acpi_data.state_count; i++) { 96 if (value == data->acpi_data.states[i].status) 97 return data->acpi_data.states[i].core_frequency; 98 } 99 return data->acpi_data.states[i-1].core_frequency; 100 } 101 102 103 static long 104 processor_get_freq ( 105 void *arg) 106 { 107 struct cpufreq_acpi_req *req = arg; 108 unsigned int cpu = req->cpu; 109 struct cpufreq_acpi_io *data = acpi_io_data[cpu]; 110 u32 value; 111 int ret; 112 113 pr_debug("processor_get_freq\n"); 114 if (smp_processor_id() != cpu) 115 return -EAGAIN; 116 117 /* processor_get_pstate gets the instantaneous frequency */ 118 ret = processor_get_pstate(&value); 119 if (ret) { 120 pr_warn("get performance failed with error %d\n", ret); 121 return ret; 122 } 123 return 1000 * extract_clock(data, value); 124 } 125 126 127 static long 128 processor_set_freq ( 129 void *arg) 130 { 131 struct cpufreq_acpi_req *req = arg; 132 unsigned int cpu = req->cpu; 133 struct cpufreq_acpi_io *data = acpi_io_data[cpu]; 134 int ret, state = req->state; 135 u32 value; 136 137 pr_debug("processor_set_freq\n"); 138 if (smp_processor_id() != cpu) 139 return -EAGAIN; 140 141 if (state == data->acpi_data.state) { 142 if (unlikely(data->resume)) { 143 pr_debug("Called after resume, resetting to P%d\n", state); 144 data->resume = 0; 145 } else { 146 pr_debug("Already at target state (P%d)\n", state); 147 return 0; 148 } 149 } 150 151 pr_debug("Transitioning from P%d to P%d\n", 152 data->acpi_data.state, state); 153 154 /* 155 * First we write the target state's 'control' value to the 156 * control_register. 157 */ 158 value = (u32) data->acpi_data.states[state].control; 159 160 pr_debug("Transitioning to state: 0x%08x\n", value); 161 162 ret = processor_set_pstate(value); 163 if (ret) { 164 pr_warn("Transition failed with error %d\n", ret); 165 return -ENODEV; 166 } 167 168 data->acpi_data.state = state; 169 return 0; 170 } 171 172 173 static unsigned int 174 acpi_cpufreq_get ( 175 unsigned int cpu) 176 { 177 struct cpufreq_acpi_req req; 178 long ret; 179 180 req.cpu = cpu; 181 ret = work_on_cpu(cpu, processor_get_freq, &req); 182 183 return ret > 0 ? (unsigned int) ret : 0; 184 } 185 186 187 static int 188 acpi_cpufreq_target ( 189 struct cpufreq_policy *policy, 190 unsigned int index) 191 { 192 struct cpufreq_acpi_req req; 193 194 req.cpu = policy->cpu; 195 req.state = index; 196 197 return work_on_cpu(req.cpu, processor_set_freq, &req); 198 } 199 200 static int 201 acpi_cpufreq_cpu_init ( 202 struct cpufreq_policy *policy) 203 { 204 unsigned int i; 205 unsigned int cpu = policy->cpu; 206 struct cpufreq_acpi_io *data; 207 unsigned int result = 0; 208 struct cpufreq_frequency_table *freq_table; 209 210 pr_debug("acpi_cpufreq_cpu_init\n"); 211 212 data = kzalloc(sizeof(*data), GFP_KERNEL); 213 if (!data) 214 return (-ENOMEM); 215 216 acpi_io_data[cpu] = data; 217 218 result = acpi_processor_register_performance(&data->acpi_data, cpu); 219 220 if (result) 221 goto err_free; 222 223 /* capability check */ 224 if (data->acpi_data.state_count <= 1) { 225 pr_debug("No P-States\n"); 226 result = -ENODEV; 227 goto err_unreg; 228 } 229 230 if ((data->acpi_data.control_register.space_id != 231 ACPI_ADR_SPACE_FIXED_HARDWARE) || 232 (data->acpi_data.status_register.space_id != 233 ACPI_ADR_SPACE_FIXED_HARDWARE)) { 234 pr_debug("Unsupported address space [%d, %d]\n", 235 (u32) (data->acpi_data.control_register.space_id), 236 (u32) (data->acpi_data.status_register.space_id)); 237 result = -ENODEV; 238 goto err_unreg; 239 } 240 241 /* alloc freq_table */ 242 freq_table = kcalloc(data->acpi_data.state_count + 1, 243 sizeof(*freq_table), 244 GFP_KERNEL); 245 if (!freq_table) { 246 result = -ENOMEM; 247 goto err_unreg; 248 } 249 250 /* detect transition latency */ 251 policy->cpuinfo.transition_latency = 0; 252 for (i=0; i<data->acpi_data.state_count; i++) { 253 if ((data->acpi_data.states[i].transition_latency * 1000) > 254 policy->cpuinfo.transition_latency) { 255 policy->cpuinfo.transition_latency = 256 data->acpi_data.states[i].transition_latency * 1000; 257 } 258 } 259 260 /* table init */ 261 for (i = 0; i <= data->acpi_data.state_count; i++) 262 { 263 if (i < data->acpi_data.state_count) { 264 freq_table[i].frequency = 265 data->acpi_data.states[i].core_frequency * 1000; 266 } else { 267 freq_table[i].frequency = CPUFREQ_TABLE_END; 268 } 269 } 270 271 policy->freq_table = freq_table; 272 273 /* notify BIOS that we exist */ 274 acpi_processor_notify_smm(THIS_MODULE); 275 276 pr_info("CPU%u - ACPI performance management activated\n", cpu); 277 278 for (i = 0; i < data->acpi_data.state_count; i++) 279 pr_debug(" %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n", 280 (i == data->acpi_data.state?'*':' '), i, 281 (u32) data->acpi_data.states[i].core_frequency, 282 (u32) data->acpi_data.states[i].power, 283 (u32) data->acpi_data.states[i].transition_latency, 284 (u32) data->acpi_data.states[i].bus_master_latency, 285 (u32) data->acpi_data.states[i].status, 286 (u32) data->acpi_data.states[i].control); 287 288 /* the first call to ->target() should result in us actually 289 * writing something to the appropriate registers. */ 290 data->resume = 1; 291 292 return (result); 293 294 err_unreg: 295 acpi_processor_unregister_performance(cpu); 296 err_free: 297 kfree(data); 298 acpi_io_data[cpu] = NULL; 299 300 return (result); 301 } 302 303 304 static int 305 acpi_cpufreq_cpu_exit ( 306 struct cpufreq_policy *policy) 307 { 308 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; 309 310 pr_debug("acpi_cpufreq_cpu_exit\n"); 311 312 if (data) { 313 acpi_io_data[policy->cpu] = NULL; 314 acpi_processor_unregister_performance(policy->cpu); 315 kfree(policy->freq_table); 316 kfree(data); 317 } 318 319 return (0); 320 } 321 322 323 static struct cpufreq_driver acpi_cpufreq_driver = { 324 .verify = cpufreq_generic_frequency_table_verify, 325 .target_index = acpi_cpufreq_target, 326 .get = acpi_cpufreq_get, 327 .init = acpi_cpufreq_cpu_init, 328 .exit = acpi_cpufreq_cpu_exit, 329 .name = "acpi-cpufreq", 330 .attr = cpufreq_generic_attr, 331 }; 332 333 334 static int __init 335 acpi_cpufreq_init (void) 336 { 337 pr_debug("acpi_cpufreq_init\n"); 338 339 return cpufreq_register_driver(&acpi_cpufreq_driver); 340 } 341 342 343 static void __exit 344 acpi_cpufreq_exit (void) 345 { 346 pr_debug("acpi_cpufreq_exit\n"); 347 348 cpufreq_unregister_driver(&acpi_cpufreq_driver); 349 } 350 351 late_initcall(acpi_cpufreq_init); 352 module_exit(acpi_cpufreq_exit); 353