PageRenderTime 170ms CodeModel.GetById 32ms RepoModel.GetById 6ms app.codeStats 0ms

/arch/arm/plat-mxs/cpufreq.c

https://bitbucket.org/sola/android_board_imx53qsb_kernel
C | 527 lines | 412 code | 78 blank | 37 comment | 92 complexity | 796ff1d9a9bcc54f0f793c7ca165fd63 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /*
  2. * Copyright (C) 2008-2010 Freescale Semiconductor, Inc.
  3. * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. */
  19. #include <linux/types.h>
  20. #include <linux/kernel.h>
  21. #include <linux/sched.h>
  22. #include <linux/cpufreq.h>
  23. #include <linux/delay.h>
  24. #include <linux/init.h>
  25. #include <linux/err.h>
  26. #include <linux/clk.h>
  27. #include <linux/spinlock.h>
  28. #include <linux/platform_device.h>
  29. #include <linux/regulator/consumer.h>
  30. #include <linux/notifier.h>
  31. #include <mach/hardware.h>
  32. #include <linux/io.h>
  33. #include <asm/system.h>
  34. #include <mach/regulator.h>
  35. #include <mach/power.h>
  36. #include <mach/clock.h>
  37. #include <mach/bus_freq.h>
  38. static struct regulator *cpu_regulator;
  39. static struct clk *cpu_clk;
  40. static struct clk *ahb_clk;
  41. static struct clk *x_clk;
  42. static struct clk *emi_clk;
  43. static struct regulator *vddd;
  44. static struct regulator *vdddbo;
  45. static struct regulator *vddio;
  46. static struct regulator *vdda;
  47. static struct cpufreq_frequency_table imx_freq_table[7];
  48. int cpu_freq_khz_min;
  49. int cpu_freq_khz_max;
  50. int cpufreq_trig_needed;
  51. int cur_freq_table_size;
  52. int lcd_on_freq_table_size;
  53. int lcd_off_freq_table_size;
  54. int high_freq_needed;
  55. extern char *ahb_clk_id;
  56. extern struct profile profiles[OPERATION_WP_SUPPORTED];
  57. extern int low_freq_used(void);
  58. static int set_freq_table(struct cpufreq_policy *policy, int end_index)
  59. {
  60. int ret = 0;
  61. int i;
  62. int zero_no = 0;
  63. for (i = 0; i < end_index; i++) {
  64. if (profiles[i].cpu == 0)
  65. zero_no++;
  66. }
  67. end_index -= zero_no;
  68. cpu_freq_khz_min = profiles[0].cpu;
  69. cpu_freq_khz_max = profiles[0].cpu;
  70. for (i = 0; i < end_index; i++) {
  71. imx_freq_table[end_index - 1 - i].index = end_index - i;
  72. imx_freq_table[end_index - 1 - i].frequency =
  73. profiles[i].cpu;
  74. if ((profiles[i].cpu) < cpu_freq_khz_min)
  75. cpu_freq_khz_min = profiles[i].cpu;
  76. if ((profiles[i].cpu) > cpu_freq_khz_max)
  77. cpu_freq_khz_max = profiles[i].cpu;
  78. }
  79. imx_freq_table[i].index = 0;
  80. imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
  81. policy->cur = clk_get_rate(cpu_clk) / 1000;
  82. policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
  83. policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
  84. policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
  85. /* Manual states, that PLL stabilizes in two CLK32 periods */
  86. policy->cpuinfo.transition_latency = 1000;
  87. ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
  88. if (ret < 0) {
  89. printk(KERN_ERR "%s: failed to register i.MXC CPUfreq\n",
  90. __func__);
  91. return ret;
  92. }
  93. cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu);
  94. return ret;
  95. }
  96. static int set_op(struct cpufreq_policy *policy, unsigned int target_freq)
  97. {
  98. struct cpufreq_freqs freqs;
  99. int ret = 0, i;
  100. freqs.old = clk_get_rate(cpu_clk) / 1000;
  101. freqs.cpu = 0;
  102. /* work around usb problem when in updater firmare mode*/
  103. #ifdef CONFIG_MXS_UTP
  104. return 0;
  105. #endif
  106. for (i = cur_freq_table_size - 1; i > 0; i--) {
  107. if (profiles[i].cpu <= target_freq &&
  108. target_freq < profiles[i - 1].cpu) {
  109. freqs.new = profiles[i].cpu;
  110. break;
  111. }
  112. if (!vddd && profiles[i].cpu > freqs.old) {
  113. /* can't safely set more than now */
  114. freqs.new = profiles[i + 1].cpu;
  115. break;
  116. }
  117. }
  118. if (i == 0)
  119. freqs.new = profiles[i].cpu;
  120. if ((freqs.old / 1000) == (freqs.new / 1000)) {
  121. if (regulator_get_voltage(vddd) == profiles[i].vddd)
  122. return 0;
  123. }
  124. if (cpu_regulator && (freqs.old < freqs.new)) {
  125. ret = regulator_set_current_limit(cpu_regulator,
  126. profiles[i].cur, profiles[i].cur);
  127. if (ret)
  128. return ret;
  129. }
  130. cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
  131. if (freqs.old > freqs.new) {
  132. int ss = profiles[i].ss;
  133. /* change emi while cpu is fastest to minimize
  134. * time spent changing emiclk
  135. */
  136. clk_set_rate(emi_clk, (profiles[i].emi) * 1000);
  137. clk_set_rate(cpu_clk, (profiles[i].cpu) * 1000);
  138. clk_set_rate(ahb_clk, (profiles[i].ahb) * 1000);
  139. /* x_clk order doesn't really matter */
  140. clk_set_rate(x_clk, (profiles[i].xbus) * 1000);
  141. timing_ctrl_rams(ss);
  142. if (vddd && vdddbo && vddio && vdda) {
  143. ret = regulator_set_voltage(vddd,
  144. profiles[i].vddd,
  145. profiles[i].vddd);
  146. if (ret)
  147. ret = regulator_set_voltage(vddd,
  148. profiles[i].vddd,
  149. profiles[i].vddd);
  150. regulator_set_voltage(vdddbo,
  151. profiles[i].vddd_bo,
  152. profiles[i].vddd_bo);
  153. ret = regulator_set_voltage(vddio,
  154. profiles[i].vddio,
  155. profiles[i].vddio);
  156. if (ret)
  157. ret = regulator_set_voltage(vddio,
  158. profiles[i].vddio,
  159. profiles[i].vddio);
  160. ret = regulator_set_voltage(vdda,
  161. profiles[i].vdda,
  162. profiles[i].vdda);
  163. if (ret)
  164. ret = regulator_set_voltage(vdda,
  165. profiles[i].vdda,
  166. profiles[i].vdda);
  167. }
  168. } else {
  169. int ss = profiles[i].ss;
  170. if (vddd && vdddbo && vddio && vdda) {
  171. ret = regulator_set_voltage(vddd,
  172. profiles[i].vddd,
  173. profiles[i].vddd);
  174. if (ret)
  175. ret = regulator_set_voltage(vddd,
  176. profiles[i].vddd,
  177. profiles[i].vddd);
  178. regulator_set_voltage(vdddbo,
  179. profiles[i].vddd_bo,
  180. profiles[i].vddd_bo);
  181. ret = regulator_set_voltage(vddio,
  182. profiles[i].vddio,
  183. profiles[i].vddio);
  184. if (ret)
  185. ret = regulator_set_voltage(vddio,
  186. profiles[i].vddio,
  187. profiles[i].vddio);
  188. ret = regulator_set_voltage(vdda,
  189. profiles[i].vdda,
  190. profiles[i].vdda);
  191. if (ret)
  192. ret = regulator_set_voltage(vdda,
  193. profiles[i].vdda,
  194. profiles[i].vdda);
  195. }
  196. /* x_clk order doesn't really matter */
  197. clk_set_rate(x_clk, (profiles[i].xbus) * 1000);
  198. timing_ctrl_rams(ss);
  199. clk_set_rate(cpu_clk, (profiles[i].cpu) * 1000);
  200. clk_set_rate(ahb_clk, (profiles[i].ahb) * 1000);
  201. clk_set_rate(emi_clk, (profiles[i].emi) * 1000);
  202. }
  203. if (is_hclk_autoslow_ok())
  204. clk_set_h_autoslow_flags(profiles[i].h_autoslow_flags);
  205. else
  206. clk_enable_h_autoslow(false);
  207. if (high_freq_needed == 0)
  208. cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  209. if (cpu_regulator && (freqs.old > freqs.new)) /* will not fail */
  210. regulator_set_current_limit(cpu_regulator,
  211. profiles[i].cur,
  212. profiles[i].cur);
  213. if (high_freq_needed == 1) {
  214. high_freq_needed = 0;
  215. cur_freq_table_size = lcd_on_freq_table_size;
  216. set_freq_table(policy, cur_freq_table_size);
  217. cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  218. }
  219. return ret;
  220. }
  221. static int calc_frequency_khz(int target, unsigned int relation)
  222. {
  223. int i;
  224. if (target * 1000 == clk_get_rate(cpu_clk))
  225. return target;
  226. if (relation == CPUFREQ_RELATION_H) {
  227. for (i = cur_freq_table_size - 1; i >= 0; i--) {
  228. if (imx_freq_table[i].frequency <= target)
  229. return imx_freq_table[i].frequency;
  230. }
  231. } else if (relation == CPUFREQ_RELATION_L) {
  232. for (i = 0; i < cur_freq_table_size; i++) {
  233. if (imx_freq_table[i].frequency >= target)
  234. return imx_freq_table[i].frequency;
  235. }
  236. }
  237. printk(KERN_ERR "Error: No valid cpufreq relation\n");
  238. return cpu_freq_khz_max;
  239. }
  240. static int mxs_target(struct cpufreq_policy *policy,
  241. unsigned int target_freq,
  242. unsigned int relation)
  243. {
  244. int freq_KHz;
  245. struct cpufreq_freqs freqs;
  246. int low_freq_bus_ready = 0;
  247. if (cpufreq_trig_needed == 1) {
  248. /* Set the current working point. */
  249. cpufreq_trig_needed = 0;
  250. target_freq = clk_get_rate(cpu_clk) / 1000;
  251. low_freq_bus_ready = low_freq_used();
  252. if ((target_freq < LCD_ON_CPU_FREQ_KHZ) &&
  253. (low_freq_bus_ready == 0)) {
  254. high_freq_needed = 1;
  255. target_freq = LCD_ON_CPU_FREQ_KHZ;
  256. goto change_freq;
  257. }
  258. target_freq = clk_get_rate(cpu_clk) / 1000;
  259. freq_KHz = calc_frequency_khz(target_freq, relation);
  260. freqs.old = target_freq;
  261. freqs.new = freq_KHz;
  262. freqs.cpu = 0;
  263. freqs.flags = 0;
  264. cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
  265. low_freq_bus_ready = low_freq_used();
  266. if (low_freq_bus_ready) {
  267. int i;
  268. cur_freq_table_size = lcd_off_freq_table_size;
  269. /* find current table index to get
  270. * hbus autoslow flags and enable hbus autoslow.
  271. */
  272. for (i = cur_freq_table_size - 1; i > 0; i--) {
  273. if (profiles[i].cpu <= target_freq &&
  274. target_freq < profiles[i - 1].cpu) {
  275. clk_set_h_autoslow_flags(
  276. profiles[i].h_autoslow_flags);
  277. break;
  278. }
  279. }
  280. } else {
  281. cur_freq_table_size = lcd_on_freq_table_size;
  282. clk_enable_h_autoslow(false);
  283. }
  284. set_freq_table(policy, cur_freq_table_size);
  285. cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  286. return 0;
  287. }
  288. /*
  289. * Some governors do not respects CPU and policy lower limits
  290. * which leads to bad things (division by zero etc), ensure
  291. * that such things do not happen.
  292. */
  293. change_freq: if (target_freq < policy->cpuinfo.min_freq)
  294. target_freq = policy->cpuinfo.min_freq;
  295. if (target_freq < policy->min)
  296. target_freq = policy->min;
  297. freq_KHz = calc_frequency_khz(target_freq, relation);
  298. return set_op(policy, freq_KHz);
  299. }
  300. static unsigned int mxs_getspeed(unsigned int cpu)
  301. {
  302. if (cpu)
  303. return 0;
  304. return clk_get_rate(cpu_clk) / 1000;
  305. }
  306. static int mxs_verify_speed(struct cpufreq_policy *policy)
  307. {
  308. if (policy->cpu != 0)
  309. return -EINVAL;
  310. return cpufreq_frequency_table_verify(policy, imx_freq_table);
  311. }
  312. static int __init mxs_cpu_init(struct cpufreq_policy *policy)
  313. {
  314. int ret = 0;
  315. int i;
  316. cpu_clk = clk_get(NULL, "cpu");
  317. if (IS_ERR(cpu_clk)) {
  318. ret = PTR_ERR(cpu_clk);
  319. goto out_cpu;
  320. }
  321. ahb_clk = clk_get(NULL, "h");
  322. if (IS_ERR(ahb_clk)) {
  323. ret = PTR_ERR(ahb_clk);
  324. goto out_ahb;
  325. }
  326. x_clk = clk_get(NULL, "x");
  327. if (IS_ERR(ahb_clk)) {
  328. ret = PTR_ERR(x_clk);
  329. goto out_x;
  330. }
  331. emi_clk = clk_get(NULL, "emi");
  332. if (IS_ERR(emi_clk)) {
  333. ret = PTR_ERR(emi_clk);
  334. goto out_emi;
  335. }
  336. if (policy->cpu != 0)
  337. return -EINVAL;
  338. cpu_regulator = regulator_get(NULL, "cpufreq-1");
  339. if (IS_ERR(cpu_regulator)) {
  340. printk(KERN_ERR "%s: failed to get CPU regulator\n", __func__);
  341. cpu_regulator = NULL;
  342. ret = PTR_ERR(cpu_regulator);
  343. goto out_cur;
  344. }
  345. vddd = regulator_get(NULL, "vddd");
  346. if (IS_ERR(vddd)) {
  347. printk(KERN_ERR "%s: failed to get vddd regulator\n", __func__);
  348. vddd = NULL;
  349. ret = PTR_ERR(vddd);
  350. goto out_cur;
  351. }
  352. vdddbo = regulator_get(NULL, "vddd_bo");
  353. if (IS_ERR(vdddbo)) {
  354. vdddbo = NULL;
  355. pr_warning("unable to get vdddbo");
  356. ret = PTR_ERR(vdddbo);
  357. goto out_cur;
  358. }
  359. vddio = regulator_get(NULL, "vddio");
  360. if (IS_ERR(vddio)) {
  361. vddio = NULL;
  362. pr_warning("unable to get vddio");
  363. ret = PTR_ERR(vddio);
  364. goto out_cur;
  365. }
  366. vdda = regulator_get(NULL, "vdda");
  367. if (IS_ERR(vdda)) {
  368. vdda = NULL;
  369. pr_warning("unable to get vdda");
  370. ret = PTR_ERR(vdda);
  371. goto out_cur;
  372. }
  373. for (i = 0; i < ARRAY_SIZE(profiles); i++) {
  374. if ((profiles[i].cpu) == LCD_ON_CPU_FREQ_KHZ) {
  375. lcd_on_freq_table_size = i + 1;
  376. break;
  377. }
  378. }
  379. if (i == ARRAY_SIZE(profiles)) {
  380. pr_warning("unable to find frequency for LCD on");
  381. printk(KERN_ERR "lcd_on_freq_table_size=%d\n",
  382. lcd_on_freq_table_size);
  383. goto out_cur;
  384. }
  385. for (i = 0; i < ARRAY_SIZE(profiles); i++) {
  386. if ((profiles[i].cpu) == 0) {
  387. lcd_off_freq_table_size = i;
  388. break;
  389. }
  390. }
  391. if (i == ARRAY_SIZE(profiles))
  392. lcd_off_freq_table_size = i;
  393. /* Set the current working point. */
  394. set_freq_table(policy, lcd_on_freq_table_size);
  395. cpufreq_trig_needed = 0;
  396. high_freq_needed = 0;
  397. cur_freq_table_size = lcd_on_freq_table_size;
  398. printk(KERN_INFO "%s: cpufreq init finished\n", __func__);
  399. return 0;
  400. out_cur:
  401. if (cpu_regulator)
  402. regulator_put(cpu_regulator);
  403. if (vddd)
  404. regulator_put(vddd);
  405. if (vddio)
  406. regulator_put(vddio);
  407. if (vdda)
  408. regulator_put(vdda);
  409. clk_put(emi_clk);
  410. out_emi:
  411. clk_put(x_clk);
  412. out_x:
  413. clk_put(ahb_clk);
  414. out_ahb:
  415. clk_put(cpu_clk);
  416. out_cpu:
  417. return ret;
  418. }
  419. static int mxs_cpu_exit(struct cpufreq_policy *policy)
  420. {
  421. cpufreq_frequency_table_put_attr(policy->cpu);
  422. /* Reset CPU to 392MHz */
  423. set_op(policy, profiles[1].cpu);
  424. clk_put(cpu_clk);
  425. regulator_put(cpu_regulator);
  426. return 0;
  427. }
  428. static struct cpufreq_driver mxs_driver = {
  429. .flags = CPUFREQ_STICKY,
  430. .verify = mxs_verify_speed,
  431. .target = mxs_target,
  432. .get = mxs_getspeed,
  433. .init = mxs_cpu_init,
  434. .exit = mxs_cpu_exit,
  435. .name = "mxs",
  436. };
  437. static int __devinit mxs_cpufreq_init(void)
  438. {
  439. return cpufreq_register_driver(&mxs_driver);
  440. }
  441. static void mxs_cpufreq_exit(void)
  442. {
  443. cpufreq_unregister_driver(&mxs_driver);
  444. }
  445. module_init(mxs_cpufreq_init);
  446. module_exit(mxs_cpufreq_exit);
  447. MODULE_AUTHOR("Freescale Semiconductor, Inc.");
  448. MODULE_DESCRIPTION("CPUfreq driver for i.MX");
  449. MODULE_LICENSE("GPL");