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 11a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown#define pr_fmt(fmt) "cpufreq: " fmt 12a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown 13b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/kernel.h> 14b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/types.h> 15b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/init.h> 16b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/cpufreq.h> 17b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/clk.h> 18b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/err.h> 19b3748ddd80569ec753f62e709629b8c639143222Mark Brown#include <linux/regulator/consumer.h> 20a6ee87790b708dc4cdd3643104417793f0d985ecMark Brown#include <linux/module.h> 21b3748ddd80569ec753f62e709629b8c639143222Mark Brown 22b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct clk *armclk; 23b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct regulator *vddarm; 2443f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brownstatic unsigned long regulator_latency; 25b3748ddd80569ec753f62e709629b8c639143222Mark Brown 26b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_CPU_S3C6410 27b3748ddd80569ec753f62e709629b8c639143222Mark Brownstruct s3c64xx_dvfs { 28b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int vddarm_min; 29b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int vddarm_max; 30b3748ddd80569ec753f62e709629b8c639143222Mark Brown}; 31b3748ddd80569ec753f62e709629b8c639143222Mark Brown 32b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct s3c64xx_dvfs s3c64xx_dvfs_table[] = { 33e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown [0] = { 1000000, 1150000 }, 34e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown [1] = { 1050000, 1150000 }, 35e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown [2] = { 1100000, 1150000 }, 36e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown [3] = { 1200000, 1350000 }, 37c6e2d68558b612fdfdb0d7ddcb51ad4578b81ebaMark Brown [4] = { 1300000, 1350000 }, 38b3748ddd80569ec753f62e709629b8c639143222Mark Brown}; 39b3748ddd80569ec753f62e709629b8c639143222Mark Brown 40b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct cpufreq_frequency_table s3c64xx_freq_table[] = { 41b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 0, 66000 }, 42ef993ef8dcd4f3e4d058400c5bd2f7c547344e74Mark Brown { 0, 100000 }, 43b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 0, 133000 }, 44ef993ef8dcd4f3e4d058400c5bd2f7c547344e74Mark Brown { 1, 200000 }, 45b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 1, 222000 }, 46b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 1, 266000 }, 47b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 2, 333000 }, 48b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 2, 400000 }, 49e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown { 2, 532000 }, 50e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown { 2, 533000 }, 51e9c08f0d5737a988e735f7371bc0bffb343c485cMark Brown { 3, 667000 }, 52c6e2d68558b612fdfdb0d7ddcb51ad4578b81ebaMark Brown { 4, 800000 }, 53b3748ddd80569ec753f62e709629b8c639143222Mark Brown { 0, CPUFREQ_TABLE_END }, 54b3748ddd80569ec753f62e709629b8c639143222Mark Brown}; 55b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 56b3748ddd80569ec753f62e709629b8c639143222Mark Brown 57b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy) 58b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 59b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (policy->cpu != 0) 60b3748ddd80569ec753f62e709629b8c639143222Mark Brown return -EINVAL; 61b3748ddd80569ec753f62e709629b8c639143222Mark Brown 62b3748ddd80569ec753f62e709629b8c639143222Mark Brown return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table); 63b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 64b3748ddd80569ec753f62e709629b8c639143222Mark Brown 65b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu) 66b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 67b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (cpu != 0) 68b3748ddd80569ec753f62e709629b8c639143222Mark Brown return 0; 69b3748ddd80569ec753f62e709629b8c639143222Mark Brown 70b3748ddd80569ec753f62e709629b8c639143222Mark Brown return clk_get_rate(armclk) / 1000; 71b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 72b3748ddd80569ec753f62e709629b8c639143222Mark Brown 73b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy, 74b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int target_freq, 75b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int relation) 76b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 77b3748ddd80569ec753f62e709629b8c639143222Mark Brown int ret; 78b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned int i; 79b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct cpufreq_freqs freqs; 80b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct s3c64xx_dvfs *dvfs; 81b3748ddd80569ec753f62e709629b8c639143222Mark Brown 82b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table, 83b3748ddd80569ec753f62e709629b8c639143222Mark Brown target_freq, relation, &i); 84b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret != 0) 85b3748ddd80569ec753f62e709629b8c639143222Mark Brown return ret; 86b3748ddd80569ec753f62e709629b8c639143222Mark Brown 87b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.cpu = 0; 88b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.old = clk_get_rate(armclk) / 1000; 89b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.new = s3c64xx_freq_table[i].frequency; 90b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.flags = 0; 91b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index]; 92b3748ddd80569ec753f62e709629b8c639143222Mark Brown 93b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (freqs.old == freqs.new) 94b3748ddd80569ec753f62e709629b8c639143222Mark Brown return 0; 95b3748ddd80569ec753f62e709629b8c639143222Mark Brown 96a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_debug("Transition %d-%dkHz\n", freqs.old, freqs.new); 97b3748ddd80569ec753f62e709629b8c639143222Mark Brown 98b3748ddd80569ec753f62e709629b8c639143222Mark Brown cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 99b3748ddd80569ec753f62e709629b8c639143222Mark Brown 100b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_REGULATOR 101b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (vddarm && freqs.new > freqs.old) { 102b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = regulator_set_voltage(vddarm, 103b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs->vddarm_min, 104b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs->vddarm_max); 105b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret != 0) { 106a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("Failed to set VDDARM for %dkHz: %d\n", 107b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.new, ret); 108b3748ddd80569ec753f62e709629b8c639143222Mark Brown goto err; 109b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 110b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 111b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 112b3748ddd80569ec753f62e709629b8c639143222Mark Brown 113b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = clk_set_rate(armclk, freqs.new * 1000); 114b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret < 0) { 115a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("Failed to set rate %dkHz: %d\n", 116b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.new, ret); 117b3748ddd80569ec753f62e709629b8c639143222Mark Brown goto err; 118b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 119b3748ddd80569ec753f62e709629b8c639143222Mark Brown 120fb3b1fefaaccdbdc716db0963ba41fb6b4221e60Mark Brown cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 121fb3b1fefaaccdbdc716db0963ba41fb6b4221e60Mark Brown 122b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_REGULATOR 123b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (vddarm && freqs.new < freqs.old) { 124b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = regulator_set_voltage(vddarm, 125b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs->vddarm_min, 126b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs->vddarm_max); 127b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret != 0) { 128a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("Failed to set VDDARM for %dkHz: %d\n", 129b3748ddd80569ec753f62e709629b8c639143222Mark Brown freqs.new, ret); 130b3748ddd80569ec753f62e709629b8c639143222Mark Brown goto err_clk; 131b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 132b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 133b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 134b3748ddd80569ec753f62e709629b8c639143222Mark Brown 135a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_debug("Set actual frequency %lukHz\n", 136b3748ddd80569ec753f62e709629b8c639143222Mark Brown clk_get_rate(armclk) / 1000); 137b3748ddd80569ec753f62e709629b8c639143222Mark Brown 138b3748ddd80569ec753f62e709629b8c639143222Mark Brown return 0; 139b3748ddd80569ec753f62e709629b8c639143222Mark Brown 140b3748ddd80569ec753f62e709629b8c639143222Mark Brownerr_clk: 141b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (clk_set_rate(armclk, freqs.old * 1000) < 0) 142b3748ddd80569ec753f62e709629b8c639143222Mark Brown pr_err("Failed to restore original clock rate\n"); 143b3748ddd80569ec753f62e709629b8c639143222Mark Brownerr: 144b3748ddd80569ec753f62e709629b8c639143222Mark Brown cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 145b3748ddd80569ec753f62e709629b8c639143222Mark Brown 146b3748ddd80569ec753f62e709629b8c639143222Mark Brown return ret; 147b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 148b3748ddd80569ec753f62e709629b8c639143222Mark Brown 149b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_REGULATOR 15043f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brownstatic void __init s3c64xx_cpufreq_config_regulator(void) 151b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 152b3748ddd80569ec753f62e709629b8c639143222Mark Brown int count, v, i, found; 153b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct cpufreq_frequency_table *freq; 154b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct s3c64xx_dvfs *dvfs; 155b3748ddd80569ec753f62e709629b8c639143222Mark Brown 156b3748ddd80569ec753f62e709629b8c639143222Mark Brown count = regulator_count_voltages(vddarm); 157b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (count < 0) { 158a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("Unable to check supported voltages\n"); 159b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 160b3748ddd80569ec753f62e709629b8c639143222Mark Brown 161b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq = s3c64xx_freq_table; 16243f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) { 163b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (freq->frequency == CPUFREQ_ENTRY_INVALID) 164b3748ddd80569ec753f62e709629b8c639143222Mark Brown continue; 165b3748ddd80569ec753f62e709629b8c639143222Mark Brown 166b3748ddd80569ec753f62e709629b8c639143222Mark Brown dvfs = &s3c64xx_dvfs_table[freq->index]; 167b3748ddd80569ec753f62e709629b8c639143222Mark Brown found = 0; 168b3748ddd80569ec753f62e709629b8c639143222Mark Brown 169b3748ddd80569ec753f62e709629b8c639143222Mark Brown for (i = 0; i < count; i++) { 170b3748ddd80569ec753f62e709629b8c639143222Mark Brown v = regulator_list_voltage(vddarm, i); 171b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (v >= dvfs->vddarm_min && v <= dvfs->vddarm_max) 172b3748ddd80569ec753f62e709629b8c639143222Mark Brown found = 1; 173b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 174b3748ddd80569ec753f62e709629b8c639143222Mark Brown 175b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (!found) { 176a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_debug("%dkHz unsupported by regulator\n", 177b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq->frequency); 178b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq->frequency = CPUFREQ_ENTRY_INVALID; 179b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 180b3748ddd80569ec753f62e709629b8c639143222Mark Brown 181b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq++; 182b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 18343f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown 18443f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown /* Guess based on having to do an I2C/SPI write; in future we 18543f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown * will be able to query the regulator performance here. */ 18643f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown regulator_latency = 1 * 1000 * 1000; 187b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 188b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 189b3748ddd80569ec753f62e709629b8c639143222Mark Brown 1906d0de1577eda1fad4be14f70021135ff7df95dcfMark Brownstatic int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) 191b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 192b3748ddd80569ec753f62e709629b8c639143222Mark Brown int ret; 193b3748ddd80569ec753f62e709629b8c639143222Mark Brown struct cpufreq_frequency_table *freq; 194b3748ddd80569ec753f62e709629b8c639143222Mark Brown 195b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (policy->cpu != 0) 196b3748ddd80569ec753f62e709629b8c639143222Mark Brown return -EINVAL; 197b3748ddd80569ec753f62e709629b8c639143222Mark Brown 198b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (s3c64xx_freq_table == NULL) { 199a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("No frequency information for this CPU\n"); 200b3748ddd80569ec753f62e709629b8c639143222Mark Brown return -ENODEV; 201b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 202b3748ddd80569ec753f62e709629b8c639143222Mark Brown 203b3748ddd80569ec753f62e709629b8c639143222Mark Brown armclk = clk_get(NULL, "armclk"); 204b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (IS_ERR(armclk)) { 205a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("Unable to obtain ARMCLK: %ld\n", 206b3748ddd80569ec753f62e709629b8c639143222Mark Brown PTR_ERR(armclk)); 207b3748ddd80569ec753f62e709629b8c639143222Mark Brown return PTR_ERR(armclk); 208b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 209b3748ddd80569ec753f62e709629b8c639143222Mark Brown 210b3748ddd80569ec753f62e709629b8c639143222Mark Brown#ifdef CONFIG_REGULATOR 211b3748ddd80569ec753f62e709629b8c639143222Mark Brown vddarm = regulator_get(NULL, "vddarm"); 212b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (IS_ERR(vddarm)) { 213b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = PTR_ERR(vddarm); 214a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("Failed to obtain VDDARM: %d\n", ret); 215a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("Only frequency scaling available\n"); 216b3748ddd80569ec753f62e709629b8c639143222Mark Brown vddarm = NULL; 217b3748ddd80569ec753f62e709629b8c639143222Mark Brown } else { 21843f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown s3c64xx_cpufreq_config_regulator(); 219b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 220b3748ddd80569ec753f62e709629b8c639143222Mark Brown#endif 221b3748ddd80569ec753f62e709629b8c639143222Mark Brown 222b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq = s3c64xx_freq_table; 223b3748ddd80569ec753f62e709629b8c639143222Mark Brown while (freq->frequency != CPUFREQ_TABLE_END) { 224b3748ddd80569ec753f62e709629b8c639143222Mark Brown unsigned long r; 225b3748ddd80569ec753f62e709629b8c639143222Mark Brown 226b3748ddd80569ec753f62e709629b8c639143222Mark Brown /* Check for frequencies we can generate */ 227b3748ddd80569ec753f62e709629b8c639143222Mark Brown r = clk_round_rate(armclk, freq->frequency * 1000); 228b3748ddd80569ec753f62e709629b8c639143222Mark Brown r /= 1000; 229383af9c2586e0c51e27ed4f186a2f23f8e889054Mark Brown if (r != freq->frequency) { 230a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_debug("%dkHz unsupported by clock\n", 231383af9c2586e0c51e27ed4f186a2f23f8e889054Mark Brown freq->frequency); 232b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq->frequency = CPUFREQ_ENTRY_INVALID; 233383af9c2586e0c51e27ed4f186a2f23f8e889054Mark Brown } 234b3748ddd80569ec753f62e709629b8c639143222Mark Brown 235b3748ddd80569ec753f62e709629b8c639143222Mark Brown /* If we have no regulator then assume startup 236b3748ddd80569ec753f62e709629b8c639143222Mark Brown * frequency is the maximum we can support. */ 237b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (!vddarm && freq->frequency > s3c64xx_cpufreq_get_speed(0)) 238b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq->frequency = CPUFREQ_ENTRY_INVALID; 239b3748ddd80569ec753f62e709629b8c639143222Mark Brown 240b3748ddd80569ec753f62e709629b8c639143222Mark Brown freq++; 241b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 242b3748ddd80569ec753f62e709629b8c639143222Mark Brown 243b3748ddd80569ec753f62e709629b8c639143222Mark Brown policy->cur = clk_get_rate(armclk) / 1000; 244b3748ddd80569ec753f62e709629b8c639143222Mark Brown 24543f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown /* Datasheet says PLL stabalisation time (if we were to use 24643f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown * the PLLs, which we don't currently) is ~300us worst case, 24743f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown * but add some fudge. 24843f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown */ 24943f1069ef9af9a0b1fa1a1d6b49b2b05e1efc998Mark Brown policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency; 250b3748ddd80569ec753f62e709629b8c639143222Mark Brown 251b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table); 252b3748ddd80569ec753f62e709629b8c639143222Mark Brown if (ret != 0) { 253a6a434124457fe64bb3980ceb2170505207db6e5Mark Brown pr_err("Failed to configure frequency table: %d\n", 254b3748ddd80569ec753f62e709629b8c639143222Mark Brown ret); 255b3748ddd80569ec753f62e709629b8c639143222Mark Brown regulator_put(vddarm); 256b3748ddd80569ec753f62e709629b8c639143222Mark Brown clk_put(armclk); 257b3748ddd80569ec753f62e709629b8c639143222Mark Brown } 258b3748ddd80569ec753f62e709629b8c639143222Mark Brown 259b3748ddd80569ec753f62e709629b8c639143222Mark Brown return ret; 260b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 261b3748ddd80569ec753f62e709629b8c639143222Mark Brown 262b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic struct cpufreq_driver s3c64xx_cpufreq_driver = { 263b3748ddd80569ec753f62e709629b8c639143222Mark Brown .owner = THIS_MODULE, 264b3748ddd80569ec753f62e709629b8c639143222Mark Brown .flags = 0, 265b3748ddd80569ec753f62e709629b8c639143222Mark Brown .verify = s3c64xx_cpufreq_verify_speed, 266b3748ddd80569ec753f62e709629b8c639143222Mark Brown .target = s3c64xx_cpufreq_set_target, 267b3748ddd80569ec753f62e709629b8c639143222Mark Brown .get = s3c64xx_cpufreq_get_speed, 268b3748ddd80569ec753f62e709629b8c639143222Mark Brown .init = s3c64xx_cpufreq_driver_init, 269b3748ddd80569ec753f62e709629b8c639143222Mark Brown .name = "s3c", 270b3748ddd80569ec753f62e709629b8c639143222Mark Brown}; 271b3748ddd80569ec753f62e709629b8c639143222Mark Brown 272b3748ddd80569ec753f62e709629b8c639143222Mark Brownstatic int __init s3c64xx_cpufreq_init(void) 273b3748ddd80569ec753f62e709629b8c639143222Mark Brown{ 274b3748ddd80569ec753f62e709629b8c639143222Mark Brown return cpufreq_register_driver(&s3c64xx_cpufreq_driver); 275b3748ddd80569ec753f62e709629b8c639143222Mark Brown} 276b3748ddd80569ec753f62e709629b8c639143222Mark Brownmodule_init(s3c64xx_cpufreq_init); 277