s3c64xx-cpufreq.c revision c6e2d68558b612fdfdb0d7ddcb51ad4578b81eba
1be2de99beaca6506a1f97a636750c108a41b5c00Mark Brown/* 2b3748ddd80569ec753f62e709629b8c639143222Mark Brown * Copyright 2009 Wolfson Microelectronics plc 3b3748ddd80569ec753f62e709629b8c639143222Mark Brown * 4b3748ddd80569ec753f62e709629b8c639143222Mark Brown * S3C64xx CPUfreq Support 5b3748ddd80569ec753f62e709629b8c639143222Mark Brown * 6b3748ddd80569ec753f62e709629b8c639143222Mark Brown * This program is free software; you can redistribute it and/or modify 7b3748ddd80569ec753f62e709629b8c639143222Mark Brown * it under the terms of the GNU General Public License version 2 as 8b3748ddd80569ec753f62e709629b8c639143222Mark Brown * published by the Free Software Foundation. 9b3748ddd80569ec753f62e709629b8c639143222Mark Brown */ 10b3748ddd80569ec753f62e709629b8c639143222Mark Brown 11b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/kernel.h> 12b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/types.h> 13b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/init.h> 14b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/cpufreq.h> 15b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/clk.h> 16b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/err.h> 17b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/regulator/consumer.h> 18b3748ddd80569ec753f62e709629b8c639143222Mark Brown 19b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct clk *armclk; 20b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct regulator *vddarm; 2143f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brownstatic unsigned long regulator_latency; 22b3748ddd80569ec753f62e709629b8c639143222Mark Brown 23b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_CPU_S3C6410 24b3748ddd80569ec753f62e709629b8c639143222Mark Brownstruct s3c64xx_dvfs { 25b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int vddarm_min; 26b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int vddarm_max; 27b3748ddd80569ec753f62e709629b8c639143222Mark Brown}; 28b3748ddd80569ec753f62e709629b8c639143222Mark Brown 29b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct s3c64xx_dvfs s3c64xx_dvfs_table[] = { 30e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown [0] = { 1000000, 1150000 }, 31e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown [1] = { 1050000, 1150000 }, 32e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown [2] = { 1100000, 1150000 }, 33e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown [3] = { 1200000, 1350000 }, 34c6e2d68558b612fdfdb0d7ddcb51ad4578b81ebaMark Brown [4] = { 1300000, 1350000 }, 35b3748ddd80569ec753f62e709629b8c639143222Mark Brown}; 36b3748ddd80569ec753f62e709629b8c639143222Mark Brown 37b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct cpufreq_frequency_table s3c64xx_freq_table[] = { 38b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 0, 66000 }, 39b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 0, 133000 }, 40b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 1, 222000 }, 41b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 1, 266000 }, 42b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 2, 333000 }, 43b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 2, 400000 }, 44e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown { 2, 532000 }, 45e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown { 2, 533000 }, 46e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown { 3, 667000 }, 47c6e2d68558b612fdfdb0d7ddcb51ad4578b81ebaMark Brown { 4, 800000 }, 48b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 0, CPUFREQ_TABLE_END }, 49b3748ddd80569ec753f62e709629b8c639143222Mark Brown}; 50b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 51b3748ddd80569ec753f62e709629b8c639143222Mark Brown 52b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy) 53b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 54b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (policy->cpu != 0) 55b3748ddd80569ec753f62e709629b8c639143222Mark Brown return -EINVAL; 56b3748ddd80569ec753f62e709629b8c639143222Mark Brown 57b3748ddd80569ec753f62e709629b8c639143222Mark Brown return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table); 58b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 59b3748ddd80569ec753f62e709629b8c639143222Mark Brown 60b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu) 61b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 62b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (cpu != 0) 63b3748ddd80569ec753f62e709629b8c639143222Mark Brown return 0; 64b3748ddd80569ec753f62e709629b8c639143222Mark Brown 65b3748ddd80569ec753f62e709629b8c639143222Mark Brown return clk_get_rate(armclk) / 1000; 66b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 67b3748ddd80569ec753f62e709629b8c639143222Mark Brown 68b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy, 69b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int target_freq, 70b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int relation) 71b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 72b3748ddd80569ec753f62e709629b8c639143222Mark Brown int ret; 73b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int i; 74b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct cpufreq_freqs freqs; 75b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct s3c64xx_dvfs *dvfs; 76b3748ddd80569ec753f62e709629b8c639143222Mark Brown 77b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table, 78b3748ddd80569ec753f62e709629b8c639143222Mark Brown target_freq, relation, &i); 79b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret != 0) 80b3748ddd80569ec753f62e709629b8c639143222Mark Brown return ret; 81b3748ddd80569ec753f62e709629b8c639143222Mark Brown 82b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.cpu = 0; 83b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.old = clk_get_rate(armclk) / 1000; 84b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.new = s3c64xx_freq_table[i].frequency; 85b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.flags = 0; 86b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index]; 87b3748ddd80569ec753f62e709629b8c639143222Mark Brown 88b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (freqs.old == freqs.new) 89b3748ddd80569ec753f62e709629b8c639143222Mark Brown return 0; 90b3748ddd80569ec753f62e709629b8c639143222Mark Brown 91b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new); 92b3748ddd80569ec753f62e709629b8c639143222Mark Brown 93b3748ddd80569ec753f62e709629b8c639143222Mark Brown cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 94b3748ddd80569ec753f62e709629b8c639143222Mark Brown 95b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_REGULATOR 96b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (vddarm && freqs.new > freqs.old) { 97b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = regulator_set_voltage(vddarm, 98b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs->vddarm_min, 99b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs->vddarm_max); 100b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret != 0) { 101b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n", 102b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.new, ret); 103b3748ddd80569ec753f62e709629b8c639143222Mark Brown goto err; 104b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 105b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 106b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 107b3748ddd80569ec753f62e709629b8c639143222Mark Brown 108b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = clk_set_rate(armclk, freqs.new * 1000); 109b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret < 0) { 110b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: Failed to set rate %dkHz: %d\n", 111b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.new, ret); 112b3748ddd80569ec753f62e709629b8c639143222Mark Brown goto err; 113b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 114b3748ddd80569ec753f62e709629b8c639143222Mark Brown 115b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_REGULATOR 116b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (vddarm && freqs.new < freqs.old) { 117b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = regulator_set_voltage(vddarm, 118b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs->vddarm_min, 119b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs->vddarm_max); 120b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret != 0) { 121b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n", 122b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.new, ret); 123b3748ddd80569ec753f62e709629b8c639143222Mark Brown goto err_clk; 124b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 125b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 126b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 127b3748ddd80569ec753f62e709629b8c639143222Mark Brown 128b3748ddd80569ec753f62e709629b8c639143222Mark Brown cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 129b3748ddd80569ec753f62e709629b8c639143222Mark Brown 130b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_debug("cpufreq: Set actual frequency %lukHz\n", 131b3748ddd80569ec753f62e709629b8c639143222Mark Brown clk_get_rate(armclk) / 1000); 132b3748ddd80569ec753f62e709629b8c639143222Mark Brown 133b3748ddd80569ec753f62e709629b8c639143222Mark Brown return 0; 134b3748ddd80569ec753f62e709629b8c639143222Mark Brown 135b3748ddd80569ec753f62e709629b8c639143222Mark Brownerr_clk: 136b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (clk_set_rate(armclk, freqs.old * 1000) < 0) 137b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("Failed to restore original clock rate\n"); 138b3748ddd80569ec753f62e709629b8c639143222Mark Brownerr: 139b3748ddd80569ec753f62e709629b8c639143222Mark Brown cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 140b3748ddd80569ec753f62e709629b8c639143222Mark Brown 141b3748ddd80569ec753f62e709629b8c639143222Mark Brown return ret; 142b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 143b3748ddd80569ec753f62e709629b8c639143222Mark Brown 144b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_REGULATOR 14543f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brownstatic void __init s3c64xx_cpufreq_config_regulator(void) 146b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 147b3748ddd80569ec753f62e709629b8c639143222Mark Brown int count, v, i, found; 148b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct cpufreq_frequency_table *freq; 149b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct s3c64xx_dvfs *dvfs; 150b3748ddd80569ec753f62e709629b8c639143222Mark Brown 151b3748ddd80569ec753f62e709629b8c639143222Mark Brown count = regulator_count_voltages(vddarm); 152b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (count < 0) { 153b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: Unable to check supported voltages\n"); 154b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 155b3748ddd80569ec753f62e709629b8c639143222Mark Brown 156b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq = s3c64xx_freq_table; 15743f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) { 158b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (freq->frequency == CPUFREQ_ENTRY_INVALID) 159b3748ddd80569ec753f62e709629b8c639143222Mark Brown continue; 160b3748ddd80569ec753f62e709629b8c639143222Mark Brown 161b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs = &s3c64xx_dvfs_table[freq->index]; 162b3748ddd80569ec753f62e709629b8c639143222Mark Brown found = 0; 163b3748ddd80569ec753f62e709629b8c639143222Mark Brown 164b3748ddd80569ec753f62e709629b8c639143222Mark Brown for (i = 0; i < count; i++) { 165b3748ddd80569ec753f62e709629b8c639143222Mark Brown v = regulator_list_voltage(vddarm, i); 166b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (v >= dvfs->vddarm_min && v <= dvfs->vddarm_max) 167b3748ddd80569ec753f62e709629b8c639143222Mark Brown found = 1; 168b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 169b3748ddd80569ec753f62e709629b8c639143222Mark Brown 170b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (!found) { 171b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_debug("cpufreq: %dkHz unsupported by regulator\n", 172b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq->frequency); 173b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq->frequency = CPUFREQ_ENTRY_INVALID; 174b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 175b3748ddd80569ec753f62e709629b8c639143222Mark Brown 176b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq++; 177b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 17843f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown 17943f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown /* Guess based on having to do an I2C/SPI write; in future we 18043f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown * will be able to query the regulator performance here. */ 18143f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown regulator_latency = 1 * 1000 * 1000; 182b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 183b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 184b3748ddd80569ec753f62e709629b8c639143222Mark Brown 1856d0de1577eda1fad4be14f70021135ff7df95dcfMark Brownstatic int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) 186b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 187b3748ddd80569ec753f62e709629b8c639143222Mark Brown int ret; 188b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct cpufreq_frequency_table *freq; 189b3748ddd80569ec753f62e709629b8c639143222Mark Brown 190b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (policy->cpu != 0) 191b3748ddd80569ec753f62e709629b8c639143222Mark Brown return -EINVAL; 192b3748ddd80569ec753f62e709629b8c639143222Mark Brown 193b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (s3c64xx_freq_table == NULL) { 194b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: No frequency information for this CPU\n"); 195b3748ddd80569ec753f62e709629b8c639143222Mark Brown return -ENODEV; 196b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 197b3748ddd80569ec753f62e709629b8c639143222Mark Brown 198b3748ddd80569ec753f62e709629b8c639143222Mark Brown armclk = clk_get(NULL, "armclk"); 199b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (IS_ERR(armclk)) { 200b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n", 201b3748ddd80569ec753f62e709629b8c639143222Mark Brown PTR_ERR(armclk)); 202b3748ddd80569ec753f62e709629b8c639143222Mark Brown return PTR_ERR(armclk); 203b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 204b3748ddd80569ec753f62e709629b8c639143222Mark Brown 205b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_REGULATOR 206b3748ddd80569ec753f62e709629b8c639143222Mark Brown vddarm = regulator_get(NULL, "vddarm"); 207b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (IS_ERR(vddarm)) { 208b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = PTR_ERR(vddarm); 209b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret); 210b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: Only frequency scaling available\n"); 211b3748ddd80569ec753f62e709629b8c639143222Mark Brown vddarm = NULL; 212b3748ddd80569ec753f62e709629b8c639143222Mark Brown } else { 21343f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown s3c64xx_cpufreq_config_regulator(); 214b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 215b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 216b3748ddd80569ec753f62e709629b8c639143222Mark Brown 217b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq = s3c64xx_freq_table; 218b3748ddd80569ec753f62e709629b8c639143222Mark Brown while (freq->frequency != CPUFREQ_TABLE_END) { 219b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned long r; 220b3748ddd80569ec753f62e709629b8c639143222Mark Brown 221b3748ddd80569ec753f62e709629b8c639143222Mark Brown /* Check for frequencies we can generate */ 222b3748ddd80569ec753f62e709629b8c639143222Mark Brown r = clk_round_rate(armclk, freq->frequency * 1000); 223b3748ddd80569ec753f62e709629b8c639143222Mark Brown r /= 1000; 224383af9c2586e0c51e27ed4f186a2f23f8e889054Mark Brown if (r != freq->frequency) { 225383af9c2586e0c51e27ed4f186a2f23f8e889054Mark Brown pr_debug("cpufreq: %dkHz unsupported by clock\n", 226383af9c2586e0c51e27ed4f186a2f23f8e889054Mark Brown freq->frequency); 227b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq->frequency = CPUFREQ_ENTRY_INVALID; 228383af9c2586e0c51e27ed4f186a2f23f8e889054Mark Brown } 229b3748ddd80569ec753f62e709629b8c639143222Mark Brown 230b3748ddd80569ec753f62e709629b8c639143222Mark Brown /* If we have no regulator then assume startup 231b3748ddd80569ec753f62e709629b8c639143222Mark Brown * frequency is the maximum we can support. */ 232b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (!vddarm && freq->frequency > s3c64xx_cpufreq_get_speed(0)) 233b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq->frequency = CPUFREQ_ENTRY_INVALID; 234b3748ddd80569ec753f62e709629b8c639143222Mark Brown 235b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq++; 236b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 237b3748ddd80569ec753f62e709629b8c639143222Mark Brown 238b3748ddd80569ec753f62e709629b8c639143222Mark Brown policy->cur = clk_get_rate(armclk) / 1000; 239b3748ddd80569ec753f62e709629b8c639143222Mark Brown 24043f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown /* Datasheet says PLL stabalisation time (if we were to use 24143f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown * the PLLs, which we don't currently) is ~300us worst case, 24243f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown * but add some fudge. 24343f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown */ 24443f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency; 245b3748ddd80569ec753f62e709629b8c639143222Mark Brown 246b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table); 247b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret != 0) { 248b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("cpufreq: Failed to configure frequency table: %d\n", 249b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret); 250b3748ddd80569ec753f62e709629b8c639143222Mark Brown regulator_put(vddarm); 251b3748ddd80569ec753f62e709629b8c639143222Mark Brown clk_put(armclk); 252b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 253b3748ddd80569ec753f62e709629b8c639143222Mark Brown 254b3748ddd80569ec753f62e709629b8c639143222Mark Brown return ret; 255b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 256b3748ddd80569ec753f62e709629b8c639143222Mark Brown 257b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct cpufreq_driver s3c64xx_cpufreq_driver = { 258b3748ddd80569ec753f62e709629b8c639143222Mark Brown .owner = THIS_MODULE, 259b3748ddd80569ec753f62e709629b8c639143222Mark Brown .flags = 0, 260b3748ddd80569ec753f62e709629b8c639143222Mark Brown .verify = s3c64xx_cpufreq_verify_speed, 261b3748ddd80569ec753f62e709629b8c639143222Mark Brown .target = s3c64xx_cpufreq_set_target, 262b3748ddd80569ec753f62e709629b8c639143222Mark Brown .get = s3c64xx_cpufreq_get_speed, 263b3748ddd80569ec753f62e709629b8c639143222Mark Brown .init = s3c64xx_cpufreq_driver_init, 264b3748ddd80569ec753f62e709629b8c639143222Mark Brown .name = "s3c", 265b3748ddd80569ec753f62e709629b8c639143222Mark Brown}; 266b3748ddd80569ec753f62e709629b8c639143222Mark Brown 267b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic int __init s3c64xx_cpufreq_init(void) 268b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 269b3748ddd80569ec753f62e709629b8c639143222Mark Brown return cpufreq_register_driver(&s3c64xx_cpufreq_driver); 270b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 271b3748ddd80569ec753f62e709629b8c639143222Mark Brownmodule_init(s3c64xx_cpufreq_init); 272