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