PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/recipes/linux/linux-omap3-psp/omap3evm/2.1.0.2/0058-OMAP3-PM-CPUidle-Basic-support-for-C1-C2.patch

https://bitbucket.org/flozzone/my-arago-da830
Patch | 349 lines | 340 code | 9 blank | 0 comment | 0 complexity | bf0c01beddfc27b63f50f07e2f140919 MD5 | raw file
  1. From 02afae2d8acd6f2462c2103ecf05671059025e92 Mon Sep 17 00:00:00 2001
  2. From: Rajendra Nayak <rnayak@ti.com>
  3. Date: Wed, 8 Oct 2008 17:30:58 +0530
  4. Subject: [PATCH 058/304] OMAP3: PM: CPUidle: Basic support for C1-C2
  5. Basic cpuidle driver for OMAP3 with deepest sleep state supported
  6. being MPU CSWR.
  7. Signed-off-by: Rajendra Nayak <rnayak@ti.com>
  8. Signed-off-by: Sanjeev Premi <premi@ti.com>
  9. ---
  10. arch/arm/mach-omap2/Makefile | 2 +-
  11. arch/arm/mach-omap2/cpuidle34xx.c | 274 ++++++++++++++++++++++++++++++++++
  12. arch/arm/mach-omap2/pm34xx.c | 4 +-
  13. arch/arm/plat-omap/include/mach/pm.h | 1 +
  14. 4 files changed, 279 insertions(+), 2 deletions(-)
  15. create mode 100644 arch/arm/mach-omap2/cpuidle34xx.c
  16. diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
  17. index efb49fb..3317ff4 100644
  18. --- a/arch/arm/mach-omap2/Makefile
  19. +++ b/arch/arm/mach-omap2/Makefile
  20. @@ -23,7 +23,7 @@ ifeq ($(CONFIG_PM),y)
  21. obj-y += pm.o
  22. obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
  23. obj-$(CONFIG_ARCH_OMAP24XX) += sleep24xx.o
  24. -obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o
  25. +obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o cpuidle34xx.o
  26. obj-$(CONFIG_PM_DEBUG) += pm-debug.o
  27. endif
  28. diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
  29. new file mode 100644
  30. index 0000000..f9ce420
  31. --- /dev/null
  32. +++ b/arch/arm/mach-omap2/cpuidle34xx.c
  33. @@ -0,0 +1,274 @@
  34. +/*
  35. + * linux/arch/arm/mach-omap2/cpuidle34xx.c
  36. + *
  37. + * OMAP3 CPU IDLE Routines
  38. + *
  39. + * Copyright (C) 2008 Texas Instruments, Inc.
  40. + * Rajendra Nayak <rnayak@ti.com>
  41. + *
  42. + * Copyright (C) 2007 Texas Instruments, Inc.
  43. + * Karthik Dasu <karthik-dp@ti.com>
  44. + *
  45. + * Copyright (C) 2006 Nokia Corporation
  46. + * Tony Lindgren <tony@atomide.com>
  47. + *
  48. + * Copyright (C) 2005 Texas Instruments, Inc.
  49. + * Richard Woodruff <r-woodruff2@ti.com>
  50. + *
  51. + * Based on pm.c for omap2
  52. + *
  53. + * This program is free software; you can redistribute it and/or modify
  54. + * it under the terms of the GNU General Public License version 2 as
  55. + * published by the Free Software Foundation.
  56. + */
  57. +
  58. +#include <linux/cpuidle.h>
  59. +#include <mach/pm.h>
  60. +#include <mach/prcm.h>
  61. +#include <mach/powerdomain.h>
  62. +
  63. +#ifdef CONFIG_CPU_IDLE
  64. +
  65. +#define OMAP3_MAX_STATES 7
  66. +#define OMAP3_STATE_C0 0 /* C0 - System executing code */
  67. +#define OMAP3_STATE_C1 1 /* C1 - MPU WFI + Core active */
  68. +#define OMAP3_STATE_C2 2 /* C2 - MPU CSWR + Core active */
  69. +#define OMAP3_STATE_C3 3 /* C3 - MPU OFF + Core active */
  70. +#define OMAP3_STATE_C4 4 /* C4 - MPU RET + Core RET */
  71. +#define OMAP3_STATE_C5 5 /* C5 - MPU OFF + Core RET */
  72. +#define OMAP3_STATE_C6 6 /* C6 - MPU OFF + Core OFF */
  73. +
  74. +struct omap3_processor_cx {
  75. + u8 valid;
  76. + u8 type;
  77. + u32 sleep_latency;
  78. + u32 wakeup_latency;
  79. + u32 mpu_state;
  80. + u32 core_state;
  81. + u32 threshold;
  82. + u32 flags;
  83. +};
  84. +
  85. +struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
  86. +struct omap3_processor_cx current_cx_state;
  87. +struct powerdomain *mpu_pd;
  88. +
  89. +static int omap3_idle_bm_check(void)
  90. +{
  91. + return 0;
  92. +}
  93. +
  94. +/**
  95. + * omap3_enter_idle - Programs OMAP3 to enter the specified state
  96. + * @dev: cpuidle device
  97. + * @state: The target state to be programmed
  98. + *
  99. + * Called from the CPUidle framework to program the device to the
  100. + * specified target state selected by the governor.
  101. + */
  102. +static int omap3_enter_idle(struct cpuidle_device *dev,
  103. + struct cpuidle_state *state)
  104. +{
  105. + struct omap3_processor_cx *cx = cpuidle_get_statedata(state);
  106. + struct timespec ts_preidle, ts_postidle, ts_idle;
  107. +
  108. + current_cx_state = *cx;
  109. +
  110. + /* Used to keep track of the total time in idle */
  111. + getnstimeofday(&ts_preidle);
  112. +
  113. + local_irq_disable();
  114. + local_fiq_disable();
  115. +
  116. + /* Program MPU to target state */
  117. + if (cx->mpu_state < PWRDM_POWER_ON)
  118. + pwrdm_set_next_pwrst(mpu_pd, cx->mpu_state);
  119. +
  120. + /* Execute ARM wfi */
  121. + omap_sram_idle();
  122. +
  123. + /* Program MPU to ON */
  124. + if (cx->mpu_state < PWRDM_POWER_ON)
  125. + pwrdm_set_next_pwrst(mpu_pd, PWRDM_POWER_ON);
  126. +
  127. + getnstimeofday(&ts_postidle);
  128. + ts_idle = timespec_sub(ts_postidle, ts_preidle);
  129. +
  130. + local_irq_enable();
  131. + local_fiq_enable();
  132. +
  133. + return timespec_to_ns(&ts_idle);
  134. +}
  135. +
  136. +/**
  137. + * omap3_enter_idle_bm - Checks for any bus activity
  138. + * @dev: cpuidle device
  139. + * @state: The target state to be programmed
  140. + *
  141. + * Called from the CPUidle framework for C states with CPUIDLE_FLAG_CHECK_BM
  142. + * flag set. This function checks for any pending bus activity and then
  143. + * programs the device to the specified or a lower possible state
  144. + */
  145. +static int omap3_enter_idle_bm(struct cpuidle_device *dev,
  146. + struct cpuidle_state *state)
  147. +{
  148. + struct cpuidle_state *new_state = NULL;
  149. + int i, j;
  150. +
  151. + if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) {
  152. +
  153. + /* Find current state in list */
  154. + for (i = 0; i < OMAP3_MAX_STATES; i++)
  155. + if (state == &dev->states[i])
  156. + break;
  157. + BUG_ON(i == OMAP3_MAX_STATES);
  158. +
  159. + /* Back up to non 'CHECK_BM' state */
  160. + for (j = i - 1; j > 0; j--) {
  161. + struct cpuidle_state *s = &dev->states[j];
  162. +
  163. + if (!(s->flags & CPUIDLE_FLAG_CHECK_BM)) {
  164. + new_state = s;
  165. + break;
  166. + }
  167. + }
  168. +
  169. + pr_debug("%s: Bus activity: Entering %s (instead of %s)\n",
  170. + __func__, new_state->name, state->name);
  171. + }
  172. +
  173. + return omap3_enter_idle(dev, new_state ? : state);
  174. +}
  175. +
  176. +DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
  177. +
  178. +/* omap3_init_power_states - Initialises the OMAP3 specific C states.
  179. + *
  180. + * Below is the desciption of each C state.
  181. + * C0 . System executing code (Not an idle state)
  182. + * C1 . MPU WFI + Core active
  183. + * C2 . MPU CSWR + Core active
  184. + * C3 . MPU OFF + Core active
  185. + * C4 . MPU CSWR + Core CSWR
  186. + * C5 . MPU OFF + Core CSWR
  187. + * C6 . MPU OFF + Core OFF
  188. + */
  189. +void omap_init_power_states(void)
  190. +{
  191. + /* C1 . MPU WFI + Core active */
  192. + omap3_power_states[OMAP3_STATE_C1].valid = 1;
  193. + omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1;
  194. + omap3_power_states[OMAP3_STATE_C1].sleep_latency = 10;
  195. + omap3_power_states[OMAP3_STATE_C1].wakeup_latency = 10;
  196. + omap3_power_states[OMAP3_STATE_C1].threshold = 30;
  197. + omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON;
  198. + omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON;
  199. + omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
  200. +
  201. + /* C2 . MPU CSWR + Core active */
  202. + omap3_power_states[OMAP3_STATE_C2].valid = 1;
  203. + omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2;
  204. + omap3_power_states[OMAP3_STATE_C2].sleep_latency = 50;
  205. + omap3_power_states[OMAP3_STATE_C2].wakeup_latency = 50;
  206. + omap3_power_states[OMAP3_STATE_C2].threshold = 300;
  207. + omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_RET;
  208. + omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
  209. + omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
  210. +
  211. + /* C3 . MPU OFF + Core active */
  212. + omap3_power_states[OMAP3_STATE_C3].valid = 0;
  213. + omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3;
  214. + omap3_power_states[OMAP3_STATE_C3].sleep_latency = 1500;
  215. + omap3_power_states[OMAP3_STATE_C3].wakeup_latency = 1800;
  216. + omap3_power_states[OMAP3_STATE_C3].threshold = 4000;
  217. + omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_OFF;
  218. + omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
  219. + omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID;
  220. +
  221. + /* C4 . MPU CSWR + Core CSWR*/
  222. + omap3_power_states[OMAP3_STATE_C4].valid = 0;
  223. + omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4;
  224. + omap3_power_states[OMAP3_STATE_C4].sleep_latency = 2500;
  225. + omap3_power_states[OMAP3_STATE_C4].wakeup_latency = 7500;
  226. + omap3_power_states[OMAP3_STATE_C4].threshold = 12000;
  227. + omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_RET;
  228. + omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_RET;
  229. + omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
  230. + CPUIDLE_FLAG_CHECK_BM;
  231. +
  232. + /* C5 . MPU OFF + Core CSWR */
  233. + omap3_power_states[OMAP3_STATE_C5].valid = 0;
  234. + omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5;
  235. + omap3_power_states[OMAP3_STATE_C5].sleep_latency = 3000;
  236. + omap3_power_states[OMAP3_STATE_C5].wakeup_latency = 8500;
  237. + omap3_power_states[OMAP3_STATE_C5].threshold = 15000;
  238. + omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_OFF;
  239. + omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET;
  240. + omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID |
  241. + CPUIDLE_FLAG_CHECK_BM;
  242. +
  243. + /* C6 . MPU OFF + Core OFF */
  244. + omap3_power_states[OMAP3_STATE_C6].valid = 0;
  245. + omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6;
  246. + omap3_power_states[OMAP3_STATE_C6].sleep_latency = 10000;
  247. + omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 30000;
  248. + omap3_power_states[OMAP3_STATE_C6].threshold = 300000;
  249. + omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF;
  250. + omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_OFF;
  251. + omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID |
  252. + CPUIDLE_FLAG_CHECK_BM;
  253. +}
  254. +
  255. +struct cpuidle_driver omap3_idle_driver = {
  256. + .name = "omap3_idle",
  257. + .owner = THIS_MODULE,
  258. +};
  259. +
  260. +/**
  261. + * omap3_idle_init - Init routine for OMAP3 idle
  262. + *
  263. + * Registers the OMAP3 specific cpuidle driver with the cpuidle
  264. + * framework with the valid set of states.
  265. + */
  266. +int omap3_idle_init(void)
  267. +{
  268. + int i, count = 0;
  269. + struct omap3_processor_cx *cx;
  270. + struct cpuidle_state *state;
  271. + struct cpuidle_device *dev;
  272. +
  273. + omap_init_power_states();
  274. + cpuidle_register_driver(&omap3_idle_driver);
  275. +
  276. + dev = &per_cpu(omap3_idle_dev, smp_processor_id());
  277. +
  278. + for (i = 1; i < OMAP3_MAX_STATES; i++) {
  279. + cx = &omap3_power_states[i];
  280. + state = &dev->states[count];
  281. +
  282. + if (!cx->valid)
  283. + continue;
  284. + cpuidle_set_statedata(state, cx);
  285. + state->exit_latency = cx->sleep_latency + cx->wakeup_latency;
  286. + state->target_residency = cx->threshold;
  287. + state->flags = cx->flags;
  288. + state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ?
  289. + omap3_enter_idle_bm : omap3_enter_idle;
  290. + sprintf(state->name, "C%d", count+1);
  291. + count++;
  292. + }
  293. +
  294. + if (!count)
  295. + return -EINVAL;
  296. + dev->state_count = count;
  297. +
  298. + if (cpuidle_register_device(dev)) {
  299. + printk(KERN_ERR "%s: CPUidle register device failed\n",
  300. + __func__);
  301. + return -EIO;
  302. + }
  303. + mpu_pd = pwrdm_lookup("mpu_pwrdm");
  304. + return 0;
  305. +}
  306. +device_initcall(omap3_idle_init);
  307. +#endif /* CONFIG_CPU_IDLE */
  308. diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
  309. index d878610..657f6be 100644
  310. --- a/arch/arm/mach-omap2/pm34xx.c
  311. +++ b/arch/arm/mach-omap2/pm34xx.c
  312. @@ -231,7 +231,7 @@ static void restore_table_entry(void)
  313. restore_control_register(control_reg_value);
  314. }
  315. -static void omap_sram_idle(void)
  316. +void omap_sram_idle(void)
  317. {
  318. /* Variable to tell what needs to be saved and restored
  319. * in omap_sram_idle*/
  320. @@ -844,7 +844,9 @@ int __init omap3_pm_init(void)
  321. omap_push_sram_idle();
  322. suspend_set_ops(&omap_pm_ops);
  323. +#ifndef CONFIG_CPU_IDLE
  324. pm_idle = omap3_pm_idle;
  325. +#endif
  326. pwrdm_add_wkdep(neon_pwrdm, mpu_pwrdm);
  327. /*
  328. diff --git a/arch/arm/plat-omap/include/mach/pm.h b/arch/arm/plat-omap/include/mach/pm.h
  329. index 15c19f0..4727dc0 100644
  330. --- a/arch/arm/plat-omap/include/mach/pm.h
  331. +++ b/arch/arm/plat-omap/include/mach/pm.h
  332. @@ -135,6 +135,7 @@ void clk_allow_idle(struct clk *clk);
  333. extern void omap_pm_idle(void);
  334. extern void omap_pm_suspend(void);
  335. +extern void omap_sram_idle(void);
  336. #ifdef CONFIG_PM
  337. extern void omap2_block_sleep(void);
  338. extern void omap2_allow_sleep(void);
  339. --
  340. 1.5.6