powerdomain.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. /*
  2. * OMAP powerdomain control
  3. *
  4. * Copyright (C) 2007-2008 Texas Instruments, Inc.
  5. * Copyright (C) 2007-2009 Nokia Corporation
  6. *
  7. * Written by Paul Walmsley
  8. * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
  9. * State counting code by Tero Kristo <tero.kristo@nokia.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. */
  15. #undef DEBUG
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/types.h>
  19. #include <linux/delay.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/list.h>
  22. #include <linux/errno.h>
  23. #include <linux/err.h>
  24. #include <linux/io.h>
  25. #include <asm/atomic.h>
  26. #include "cm.h"
  27. #include "cm-regbits-34xx.h"
  28. #include "cm-regbits-44xx.h"
  29. #include "prm.h"
  30. #include "prm-regbits-34xx.h"
  31. #include "prm-regbits-44xx.h"
  32. #include <plat/cpu.h>
  33. #include <plat/powerdomain.h>
  34. #include <plat/clockdomain.h>
  35. #include <plat/prcm.h>
  36. #include "pm.h"
  37. enum {
  38. PWRDM_STATE_NOW = 0,
  39. PWRDM_STATE_PREV,
  40. };
  41. /* Variable holding value of the CPU dependent PWRSTCTRL Register Offset */
  42. static u16 pwrstctrl_reg_offs;
  43. /* Variable holding value of the CPU dependent PWRSTST Register Offset */
  44. static u16 pwrstst_reg_offs;
  45. /* OMAP3 and OMAP4 specific register bit initialisations
  46. * Notice that the names here are not according to each power
  47. * domain but the bit mapping used applies to all of them
  48. */
  49. /* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */
  50. #define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK
  51. #define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK
  52. #define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK
  53. #define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK
  54. #define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK
  55. /* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */
  56. #define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE_MASK
  57. #define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE_MASK
  58. #define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE_MASK
  59. #define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE_MASK
  60. #define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK
  61. /* OMAP3 and OMAP4 Memory Status bits */
  62. #define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK
  63. #define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK
  64. #define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK
  65. #define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK
  66. #define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK
  67. /* pwrdm_list contains all registered struct powerdomains */
  68. static LIST_HEAD(pwrdm_list);
  69. static struct pwrdm_ops *arch_pwrdm;
  70. /* Private functions */
  71. static struct powerdomain *_pwrdm_lookup(const char *name)
  72. {
  73. struct powerdomain *pwrdm, *temp_pwrdm;
  74. pwrdm = NULL;
  75. list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
  76. if (!strcmp(name, temp_pwrdm->name)) {
  77. pwrdm = temp_pwrdm;
  78. break;
  79. }
  80. }
  81. return pwrdm;
  82. }
  83. /**
  84. * _pwrdm_register - register a powerdomain
  85. * @pwrdm: struct powerdomain * to register
  86. *
  87. * Adds a powerdomain to the internal powerdomain list. Returns
  88. * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
  89. * already registered by the provided name, or 0 upon success.
  90. */
  91. static int _pwrdm_register(struct powerdomain *pwrdm)
  92. {
  93. int i;
  94. if (!pwrdm)
  95. return -EINVAL;
  96. if (!omap_chip_is(pwrdm->omap_chip))
  97. return -EINVAL;
  98. if (_pwrdm_lookup(pwrdm->name))
  99. return -EEXIST;
  100. list_add(&pwrdm->node, &pwrdm_list);
  101. /* Initialize the powerdomain's state counter */
  102. for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
  103. pwrdm->state_counter[i] = 0;
  104. pwrdm->ret_logic_off_counter = 0;
  105. for (i = 0; i < pwrdm->banks; i++)
  106. pwrdm->ret_mem_off_counter[i] = 0;
  107. pwrdm_wait_transition(pwrdm);
  108. pwrdm->state = pwrdm_read_pwrst(pwrdm);
  109. pwrdm->state_counter[pwrdm->state] = 1;
  110. pr_debug("powerdomain: registered %s\n", pwrdm->name);
  111. return 0;
  112. }
  113. static void _update_logic_membank_counters(struct powerdomain *pwrdm)
  114. {
  115. int i;
  116. u8 prev_logic_pwrst, prev_mem_pwrst;
  117. prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
  118. if ((pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) &&
  119. (prev_logic_pwrst == PWRDM_POWER_OFF))
  120. pwrdm->ret_logic_off_counter++;
  121. for (i = 0; i < pwrdm->banks; i++) {
  122. prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i);
  123. if ((pwrdm->pwrsts_mem_ret[i] == PWRSTS_OFF_RET) &&
  124. (prev_mem_pwrst == PWRDM_POWER_OFF))
  125. pwrdm->ret_mem_off_counter[i]++;
  126. }
  127. }
  128. static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
  129. {
  130. int prev;
  131. int state;
  132. if (pwrdm == NULL)
  133. return -EINVAL;
  134. state = pwrdm_read_pwrst(pwrdm);
  135. switch (flag) {
  136. case PWRDM_STATE_NOW:
  137. prev = pwrdm->state;
  138. break;
  139. case PWRDM_STATE_PREV:
  140. prev = pwrdm_read_prev_pwrst(pwrdm);
  141. if (pwrdm->state != prev)
  142. pwrdm->state_counter[prev]++;
  143. if (prev == PWRDM_POWER_RET)
  144. _update_logic_membank_counters(pwrdm);
  145. break;
  146. default:
  147. return -EINVAL;
  148. }
  149. if (state != prev)
  150. pwrdm->state_counter[state]++;
  151. pm_dbg_update_time(pwrdm, prev);
  152. pwrdm->state = state;
  153. return 0;
  154. }
  155. static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
  156. {
  157. pwrdm_clear_all_prev_pwrst(pwrdm);
  158. _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
  159. return 0;
  160. }
  161. static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
  162. {
  163. _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV);
  164. return 0;
  165. }
  166. /* Public functions */
  167. /**
  168. * pwrdm_init - set up the powerdomain layer
  169. * @pwrdm_list: array of struct powerdomain pointers to register
  170. * @custom_funcs: func pointers for arch specfic implementations
  171. *
  172. * Loop through the array of powerdomains @pwrdm_list, registering all
  173. * that are available on the current CPU. If pwrdm_list is supplied
  174. * and not null, all of the referenced powerdomains will be
  175. * registered. No return value. XXX pwrdm_list is not really a
  176. * "list"; it is an array. Rename appropriately.
  177. */
  178. void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs)
  179. {
  180. struct powerdomain **p = NULL;
  181. if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
  182. pwrstctrl_reg_offs = OMAP2_PM_PWSTCTRL;
  183. pwrstst_reg_offs = OMAP2_PM_PWSTST;
  184. } else if (cpu_is_omap44xx()) {
  185. pwrstctrl_reg_offs = OMAP4_PM_PWSTCTRL;
  186. pwrstst_reg_offs = OMAP4_PM_PWSTST;
  187. } else {
  188. printk(KERN_ERR "Power Domain struct not supported for " \
  189. "this CPU\n");
  190. return;
  191. }
  192. if (!custom_funcs)
  193. WARN(1, "powerdomain: No custom pwrdm functions registered\n");
  194. else
  195. arch_pwrdm = custom_funcs;
  196. if (pwrdm_list) {
  197. for (p = pwrdm_list; *p; p++)
  198. _pwrdm_register(*p);
  199. }
  200. }
  201. /**
  202. * pwrdm_lookup - look up a powerdomain by name, return a pointer
  203. * @name: name of powerdomain
  204. *
  205. * Find a registered powerdomain by its name @name. Returns a pointer
  206. * to the struct powerdomain if found, or NULL otherwise.
  207. */
  208. struct powerdomain *pwrdm_lookup(const char *name)
  209. {
  210. struct powerdomain *pwrdm;
  211. if (!name)
  212. return NULL;
  213. pwrdm = _pwrdm_lookup(name);
  214. return pwrdm;
  215. }
  216. /**
  217. * pwrdm_for_each - call function on each registered clockdomain
  218. * @fn: callback function *
  219. *
  220. * Call the supplied function @fn for each registered powerdomain.
  221. * The callback function @fn can return anything but 0 to bail out
  222. * early from the iterator. Returns the last return value of the
  223. * callback function, which should be 0 for success or anything else
  224. * to indicate failure; or -EINVAL if the function pointer is null.
  225. */
  226. int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
  227. void *user)
  228. {
  229. struct powerdomain *temp_pwrdm;
  230. int ret = 0;
  231. if (!fn)
  232. return -EINVAL;
  233. list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
  234. ret = (*fn)(temp_pwrdm, user);
  235. if (ret)
  236. break;
  237. }
  238. return ret;
  239. }
  240. /**
  241. * pwrdm_add_clkdm - add a clockdomain to a powerdomain
  242. * @pwrdm: struct powerdomain * to add the clockdomain to
  243. * @clkdm: struct clockdomain * to associate with a powerdomain
  244. *
  245. * Associate the clockdomain @clkdm with a powerdomain @pwrdm. This
  246. * enables the use of pwrdm_for_each_clkdm(). Returns -EINVAL if
  247. * presented with invalid pointers; -ENOMEM if memory could not be allocated;
  248. * or 0 upon success.
  249. */
  250. int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
  251. {
  252. int i;
  253. int ret = -EINVAL;
  254. if (!pwrdm || !clkdm)
  255. return -EINVAL;
  256. pr_debug("powerdomain: associating clockdomain %s with powerdomain "
  257. "%s\n", clkdm->name, pwrdm->name);
  258. for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
  259. if (!pwrdm->pwrdm_clkdms[i])
  260. break;
  261. #ifdef DEBUG
  262. if (pwrdm->pwrdm_clkdms[i] == clkdm) {
  263. ret = -EINVAL;
  264. goto pac_exit;
  265. }
  266. #endif
  267. }
  268. if (i == PWRDM_MAX_CLKDMS) {
  269. pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
  270. "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
  271. WARN_ON(1);
  272. ret = -ENOMEM;
  273. goto pac_exit;
  274. }
  275. pwrdm->pwrdm_clkdms[i] = clkdm;
  276. ret = 0;
  277. pac_exit:
  278. return ret;
  279. }
  280. /**
  281. * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
  282. * @pwrdm: struct powerdomain * to add the clockdomain to
  283. * @clkdm: struct clockdomain * to associate with a powerdomain
  284. *
  285. * Dissociate the clockdomain @clkdm from the powerdomain
  286. * @pwrdm. Returns -EINVAL if presented with invalid pointers; -ENOENT
  287. * if @clkdm was not associated with the powerdomain, or 0 upon
  288. * success.
  289. */
  290. int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
  291. {
  292. int ret = -EINVAL;
  293. int i;
  294. if (!pwrdm || !clkdm)
  295. return -EINVAL;
  296. pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
  297. "%s\n", clkdm->name, pwrdm->name);
  298. for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
  299. if (pwrdm->pwrdm_clkdms[i] == clkdm)
  300. break;
  301. if (i == PWRDM_MAX_CLKDMS) {
  302. pr_debug("powerdomain: clkdm %s not associated with pwrdm "
  303. "%s ?!\n", clkdm->name, pwrdm->name);
  304. ret = -ENOENT;
  305. goto pdc_exit;
  306. }
  307. pwrdm->pwrdm_clkdms[i] = NULL;
  308. ret = 0;
  309. pdc_exit:
  310. return ret;
  311. }
  312. /**
  313. * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
  314. * @pwrdm: struct powerdomain * to iterate over
  315. * @fn: callback function *
  316. *
  317. * Call the supplied function @fn for each clockdomain in the powerdomain
  318. * @pwrdm. The callback function can return anything but 0 to bail
  319. * out early from the iterator. Returns -EINVAL if presented with
  320. * invalid pointers; or passes along the last return value of the
  321. * callback function, which should be 0 for success or anything else
  322. * to indicate failure.
  323. */
  324. int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
  325. int (*fn)(struct powerdomain *pwrdm,
  326. struct clockdomain *clkdm))
  327. {
  328. int ret = 0;
  329. int i;
  330. if (!fn)
  331. return -EINVAL;
  332. for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
  333. ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
  334. return ret;
  335. }
  336. /**
  337. * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
  338. * @pwrdm: struct powerdomain *
  339. *
  340. * Return the number of controllable memory banks in powerdomain @pwrdm,
  341. * starting with 1. Returns -EINVAL if the powerdomain pointer is null.
  342. */
  343. int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  344. {
  345. if (!pwrdm)
  346. return -EINVAL;
  347. return pwrdm->banks;
  348. }
  349. /**
  350. * pwrdm_set_next_pwrst - set next powerdomain power state
  351. * @pwrdm: struct powerdomain * to set
  352. * @pwrst: one of the PWRDM_POWER_* macros
  353. *
  354. * Set the powerdomain @pwrdm's next power state to @pwrst. The powerdomain
  355. * may not enter this state immediately if the preconditions for this state
  356. * have not been satisfied. Returns -EINVAL if the powerdomain pointer is
  357. * null or if the power state is invalid for the powerdomin, or returns 0
  358. * upon success.
  359. */
  360. int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
  361. {
  362. int ret = -EINVAL;
  363. if (!pwrdm)
  364. return -EINVAL;
  365. if (!(pwrdm->pwrsts & (1 << pwrst)))
  366. return -EINVAL;
  367. pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
  368. pwrdm->name, pwrst);
  369. if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst)
  370. ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
  371. return ret;
  372. }
  373. /**
  374. * pwrdm_read_next_pwrst - get next powerdomain power state
  375. * @pwrdm: struct powerdomain * to get power state
  376. *
  377. * Return the powerdomain @pwrdm's next power state. Returns -EINVAL
  378. * if the powerdomain pointer is null or returns the next power state
  379. * upon success.
  380. */
  381. int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  382. {
  383. int ret = -EINVAL;
  384. if (!pwrdm)
  385. return -EINVAL;
  386. if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst)
  387. ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
  388. return ret;
  389. }
  390. /**
  391. * pwrdm_read_pwrst - get current powerdomain power state
  392. * @pwrdm: struct powerdomain * to get power state
  393. *
  394. * Return the powerdomain @pwrdm's current power state. Returns -EINVAL
  395. * if the powerdomain pointer is null or returns the current power state
  396. * upon success.
  397. */
  398. int pwrdm_read_pwrst(struct powerdomain *pwrdm)
  399. {
  400. int ret = -EINVAL;
  401. if (!pwrdm)
  402. return -EINVAL;
  403. if (arch_pwrdm && arch_pwrdm->pwrdm_read_pwrst)
  404. ret = arch_pwrdm->pwrdm_read_pwrst(pwrdm);
  405. return ret;
  406. }
  407. /**
  408. * pwrdm_read_prev_pwrst - get previous powerdomain power state
  409. * @pwrdm: struct powerdomain * to get previous power state
  410. *
  411. * Return the powerdomain @pwrdm's previous power state. Returns -EINVAL
  412. * if the powerdomain pointer is null or returns the previous power state
  413. * upon success.
  414. */
  415. int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
  416. {
  417. int ret = -EINVAL;
  418. if (!pwrdm)
  419. return -EINVAL;
  420. if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_pwrst)
  421. ret = arch_pwrdm->pwrdm_read_prev_pwrst(pwrdm);
  422. return ret;
  423. }
  424. /**
  425. * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
  426. * @pwrdm: struct powerdomain * to set
  427. * @pwrst: one of the PWRDM_POWER_* macros
  428. *
  429. * Set the next power state @pwrst that the logic portion of the
  430. * powerdomain @pwrdm will enter when the powerdomain enters retention.
  431. * This will be either RETENTION or OFF, if supported. Returns
  432. * -EINVAL if the powerdomain pointer is null or the target power
  433. * state is not not supported, or returns 0 upon success.
  434. */
  435. int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
  436. {
  437. int ret = -EINVAL;
  438. if (!pwrdm)
  439. return -EINVAL;
  440. if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
  441. return -EINVAL;
  442. pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
  443. pwrdm->name, pwrst);
  444. if (arch_pwrdm && arch_pwrdm->pwrdm_set_logic_retst)
  445. ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, pwrst);
  446. return ret;
  447. }
  448. /**
  449. * pwrdm_set_mem_onst - set memory power state while powerdomain ON
  450. * @pwrdm: struct powerdomain * to set
  451. * @bank: memory bank number to set (0-3)
  452. * @pwrst: one of the PWRDM_POWER_* macros
  453. *
  454. * Set the next power state @pwrst that memory bank @bank of the
  455. * powerdomain @pwrdm will enter when the powerdomain enters the ON
  456. * state. @bank will be a number from 0 to 3, and represents different
  457. * types of memory, depending on the powerdomain. Returns -EINVAL if
  458. * the powerdomain pointer is null or the target power state is not
  459. * not supported for this memory bank, -EEXIST if the target memory
  460. * bank does not exist or is not controllable, or returns 0 upon
  461. * success.
  462. */
  463. int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
  464. {
  465. u32 m;
  466. if (!pwrdm)
  467. return -EINVAL;
  468. if (pwrdm->banks < (bank + 1))
  469. return -EEXIST;
  470. if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
  471. return -EINVAL;
  472. pr_debug("powerdomain: setting next memory powerstate for domain %s "
  473. "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
  474. /*
  475. * The register bit names below may not correspond to the
  476. * actual names of the bits in each powerdomain's register,
  477. * but the type of value returned is the same for each
  478. * powerdomain.
  479. */
  480. switch (bank) {
  481. case 0:
  482. m = OMAP_MEM0_ONSTATE_MASK;
  483. break;
  484. case 1:
  485. m = OMAP_MEM1_ONSTATE_MASK;
  486. break;
  487. case 2:
  488. m = OMAP_MEM2_ONSTATE_MASK;
  489. break;
  490. case 3:
  491. m = OMAP_MEM3_ONSTATE_MASK;
  492. break;
  493. case 4:
  494. m = OMAP_MEM4_ONSTATE_MASK;
  495. break;
  496. default:
  497. WARN_ON(1); /* should never happen */
  498. return -EEXIST;
  499. }
  500. prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
  501. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  502. return 0;
  503. }
  504. /**
  505. * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
  506. * @pwrdm: struct powerdomain * to set
  507. * @bank: memory bank number to set (0-3)
  508. * @pwrst: one of the PWRDM_POWER_* macros
  509. *
  510. * Set the next power state @pwrst that memory bank @bank of the
  511. * powerdomain @pwrdm will enter when the powerdomain enters the
  512. * RETENTION state. Bank will be a number from 0 to 3, and represents
  513. * different types of memory, depending on the powerdomain. @pwrst
  514. * will be either RETENTION or OFF, if supported. Returns -EINVAL if
  515. * the powerdomain pointer is null or the target power state is not
  516. * not supported for this memory bank, -EEXIST if the target memory
  517. * bank does not exist or is not controllable, or returns 0 upon
  518. * success.
  519. */
  520. int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
  521. {
  522. u32 m;
  523. if (!pwrdm)
  524. return -EINVAL;
  525. if (pwrdm->banks < (bank + 1))
  526. return -EEXIST;
  527. if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
  528. return -EINVAL;
  529. pr_debug("powerdomain: setting next memory powerstate for domain %s "
  530. "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
  531. /*
  532. * The register bit names below may not correspond to the
  533. * actual names of the bits in each powerdomain's register,
  534. * but the type of value returned is the same for each
  535. * powerdomain.
  536. */
  537. switch (bank) {
  538. case 0:
  539. m = OMAP_MEM0_RETSTATE_MASK;
  540. break;
  541. case 1:
  542. m = OMAP_MEM1_RETSTATE_MASK;
  543. break;
  544. case 2:
  545. m = OMAP_MEM2_RETSTATE_MASK;
  546. break;
  547. case 3:
  548. m = OMAP_MEM3_RETSTATE_MASK;
  549. break;
  550. case 4:
  551. m = OMAP_MEM4_RETSTATE_MASK;
  552. break;
  553. default:
  554. WARN_ON(1); /* should never happen */
  555. return -EEXIST;
  556. }
  557. prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
  558. pwrstctrl_reg_offs);
  559. return 0;
  560. }
  561. /**
  562. * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
  563. * @pwrdm: struct powerdomain * to get current logic retention power state
  564. *
  565. * Return the power state that the logic portion of powerdomain @pwrdm
  566. * will enter when the powerdomain enters retention. Returns -EINVAL
  567. * if the powerdomain pointer is null or returns the logic retention
  568. * power state upon success.
  569. */
  570. int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
  571. {
  572. int ret = -EINVAL;
  573. if (!pwrdm)
  574. return -EINVAL;
  575. if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_pwrst)
  576. ret = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm);
  577. return ret;
  578. }
  579. /**
  580. * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
  581. * @pwrdm: struct powerdomain * to get previous logic power state
  582. *
  583. * Return the powerdomain @pwrdm's previous logic power state. Returns
  584. * -EINVAL if the powerdomain pointer is null or returns the previous
  585. * logic power state upon success.
  586. */
  587. int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
  588. {
  589. int ret = -EINVAL;
  590. if (!pwrdm)
  591. return -EINVAL;
  592. if (arch_pwrdm && arch_pwrdm->pwrdm_read_prev_logic_pwrst)
  593. ret = arch_pwrdm->pwrdm_read_prev_logic_pwrst(pwrdm);
  594. return ret;
  595. }
  596. /**
  597. * pwrdm_read_logic_retst - get next powerdomain logic power state
  598. * @pwrdm: struct powerdomain * to get next logic power state
  599. *
  600. * Return the powerdomain pwrdm's logic power state. Returns -EINVAL
  601. * if the powerdomain pointer is null or returns the next logic
  602. * power state upon success.
  603. */
  604. int pwrdm_read_logic_retst(struct powerdomain *pwrdm)
  605. {
  606. int ret = -EINVAL;
  607. if (!pwrdm)
  608. return -EINVAL;
  609. if (arch_pwrdm && arch_pwrdm->pwrdm_read_logic_retst)
  610. ret = arch_pwrdm->pwrdm_read_logic_retst(pwrdm);
  611. return ret;
  612. }
  613. /**
  614. * pwrdm_read_mem_pwrst - get current memory bank power state
  615. * @pwrdm: struct powerdomain * to get current memory bank power state
  616. * @bank: memory bank number (0-3)
  617. *
  618. * Return the powerdomain @pwrdm's current memory power state for bank
  619. * @bank. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
  620. * the target memory bank does not exist or is not controllable, or
  621. * returns the current memory power state upon success.
  622. */
  623. int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  624. {
  625. u32 m;
  626. if (!pwrdm)
  627. return -EINVAL;
  628. if (pwrdm->banks < (bank + 1))
  629. return -EEXIST;
  630. if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
  631. bank = 1;
  632. /*
  633. * The register bit names below may not correspond to the
  634. * actual names of the bits in each powerdomain's register,
  635. * but the type of value returned is the same for each
  636. * powerdomain.
  637. */
  638. switch (bank) {
  639. case 0:
  640. m = OMAP_MEM0_STATEST_MASK;
  641. break;
  642. case 1:
  643. m = OMAP_MEM1_STATEST_MASK;
  644. break;
  645. case 2:
  646. m = OMAP_MEM2_STATEST_MASK;
  647. break;
  648. case 3:
  649. m = OMAP_MEM3_STATEST_MASK;
  650. break;
  651. case 4:
  652. m = OMAP_MEM4_STATEST_MASK;
  653. break;
  654. default:
  655. WARN_ON(1); /* should never happen */
  656. return -EEXIST;
  657. }
  658. return prm_read_mod_bits_shift(pwrdm->prcm_offs,
  659. pwrstst_reg_offs, m);
  660. }
  661. /**
  662. * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
  663. * @pwrdm: struct powerdomain * to get previous memory bank power state
  664. * @bank: memory bank number (0-3)
  665. *
  666. * Return the powerdomain @pwrdm's previous memory power state for
  667. * bank @bank. Returns -EINVAL if the powerdomain pointer is null,
  668. * -EEXIST if the target memory bank does not exist or is not
  669. * controllable, or returns the previous memory power state upon
  670. * success.
  671. */
  672. int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  673. {
  674. u32 m;
  675. if (!pwrdm)
  676. return -EINVAL;
  677. if (pwrdm->banks < (bank + 1))
  678. return -EEXIST;
  679. if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
  680. bank = 1;
  681. /*
  682. * The register bit names below may not correspond to the
  683. * actual names of the bits in each powerdomain's register,
  684. * but the type of value returned is the same for each
  685. * powerdomain.
  686. */
  687. switch (bank) {
  688. case 0:
  689. m = OMAP3430_LASTMEM1STATEENTERED_MASK;
  690. break;
  691. case 1:
  692. m = OMAP3430_LASTMEM2STATEENTERED_MASK;
  693. break;
  694. case 2:
  695. m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
  696. break;
  697. case 3:
  698. m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
  699. break;
  700. default:
  701. WARN_ON(1); /* should never happen */
  702. return -EEXIST;
  703. }
  704. return prm_read_mod_bits_shift(pwrdm->prcm_offs,
  705. OMAP3430_PM_PREPWSTST, m);
  706. }
  707. /**
  708. * pwrdm_read_mem_retst - get next memory bank power state
  709. * @pwrdm: struct powerdomain * to get mext memory bank power state
  710. * @bank: memory bank number (0-3)
  711. *
  712. * Return the powerdomain pwrdm's next memory power state for bank
  713. * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
  714. * the target memory bank does not exist or is not controllable, or
  715. * returns the next memory power state upon success.
  716. */
  717. int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
  718. {
  719. u32 m;
  720. if (!pwrdm)
  721. return -EINVAL;
  722. if (pwrdm->banks < (bank + 1))
  723. return -EEXIST;
  724. /*
  725. * The register bit names below may not correspond to the
  726. * actual names of the bits in each powerdomain's register,
  727. * but the type of value returned is the same for each
  728. * powerdomain.
  729. */
  730. switch (bank) {
  731. case 0:
  732. m = OMAP_MEM0_RETSTATE_MASK;
  733. break;
  734. case 1:
  735. m = OMAP_MEM1_RETSTATE_MASK;
  736. break;
  737. case 2:
  738. m = OMAP_MEM2_RETSTATE_MASK;
  739. break;
  740. case 3:
  741. m = OMAP_MEM3_RETSTATE_MASK;
  742. break;
  743. case 4:
  744. m = OMAP_MEM4_RETSTATE_MASK;
  745. break;
  746. default:
  747. WARN_ON(1); /* should never happen */
  748. return -EEXIST;
  749. }
  750. return prm_read_mod_bits_shift(pwrdm->prcm_offs,
  751. pwrstctrl_reg_offs, m);
  752. }
  753. /**
  754. * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
  755. * @pwrdm: struct powerdomain * to clear
  756. *
  757. * Clear the powerdomain's previous power state register @pwrdm.
  758. * Clears the entire register, including logic and memory bank
  759. * previous power states. Returns -EINVAL if the powerdomain pointer
  760. * is null, or returns 0 upon success.
  761. */
  762. int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
  763. {
  764. if (!pwrdm)
  765. return -EINVAL;
  766. /*
  767. * XXX should get the powerdomain's current state here;
  768. * warn & fail if it is not ON.
  769. */
  770. pr_debug("powerdomain: clearing previous power state reg for %s\n",
  771. pwrdm->name);
  772. prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
  773. return 0;
  774. }
  775. /**
  776. * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
  777. * @pwrdm: struct powerdomain *
  778. *
  779. * Enable automatic context save-and-restore upon power state change
  780. * for some devices in the powerdomain @pwrdm. Warning: this only
  781. * affects a subset of devices in a powerdomain; check the TRM
  782. * closely. Returns -EINVAL if the powerdomain pointer is null or if
  783. * the powerdomain does not support automatic save-and-restore, or
  784. * returns 0 upon success.
  785. */
  786. int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
  787. {
  788. if (!pwrdm)
  789. return -EINVAL;
  790. if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
  791. return -EINVAL;
  792. pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
  793. pwrdm->name);
  794. prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
  795. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  796. return 0;
  797. }
  798. /**
  799. * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
  800. * @pwrdm: struct powerdomain *
  801. *
  802. * Disable automatic context save-and-restore upon power state change
  803. * for some devices in the powerdomain @pwrdm. Warning: this only
  804. * affects a subset of devices in a powerdomain; check the TRM
  805. * closely. Returns -EINVAL if the powerdomain pointer is null or if
  806. * the powerdomain does not support automatic save-and-restore, or
  807. * returns 0 upon success.
  808. */
  809. int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
  810. {
  811. if (!pwrdm)
  812. return -EINVAL;
  813. if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
  814. return -EINVAL;
  815. pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
  816. pwrdm->name);
  817. prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
  818. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  819. return 0;
  820. }
  821. /**
  822. * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
  823. * @pwrdm: struct powerdomain *
  824. *
  825. * Returns 1 if powerdomain @pwrdm supports hardware save-and-restore
  826. * for some devices, or 0 if it does not.
  827. */
  828. bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
  829. {
  830. return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
  831. }
  832. /**
  833. * pwrdm_set_lowpwrstchange - Request a low power state change
  834. * @pwrdm: struct powerdomain *
  835. *
  836. * Allows a powerdomain to transtion to a lower power sleep state
  837. * from an existing sleep state without waking up the powerdomain.
  838. * Returns -EINVAL if the powerdomain pointer is null or if the
  839. * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0
  840. * upon success.
  841. */
  842. int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
  843. {
  844. if (!pwrdm)
  845. return -EINVAL;
  846. if (!(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE))
  847. return -EINVAL;
  848. pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n",
  849. pwrdm->name);
  850. prm_rmw_mod_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
  851. (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
  852. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  853. return 0;
  854. }
  855. /**
  856. * pwrdm_wait_transition - wait for powerdomain power transition to finish
  857. * @pwrdm: struct powerdomain * to wait for
  858. *
  859. * If the powerdomain @pwrdm is in the process of a state transition,
  860. * spin until it completes the power transition, or until an iteration
  861. * bailout value is reached. Returns -EINVAL if the powerdomain
  862. * pointer is null, -EAGAIN if the bailout value was reached, or
  863. * returns 0 upon success.
  864. */
  865. int pwrdm_wait_transition(struct powerdomain *pwrdm)
  866. {
  867. u32 c = 0;
  868. if (!pwrdm)
  869. return -EINVAL;
  870. /*
  871. * REVISIT: pwrdm_wait_transition() may be better implemented
  872. * via a callback and a periodic timer check -- how long do we expect
  873. * powerdomain transitions to take?
  874. */
  875. /* XXX Is this udelay() value meaningful? */
  876. while ((prm_read_mod_reg(pwrdm->prcm_offs, pwrstst_reg_offs) &
  877. OMAP_INTRANSITION_MASK) &&
  878. (c++ < PWRDM_TRANSITION_BAILOUT))
  879. udelay(1);
  880. if (c > PWRDM_TRANSITION_BAILOUT) {
  881. printk(KERN_ERR "powerdomain: waited too long for "
  882. "powerdomain %s to complete transition\n", pwrdm->name);
  883. return -EAGAIN;
  884. }
  885. pr_debug("powerdomain: completed transition in %d loops\n", c);
  886. return 0;
  887. }
  888. int pwrdm_state_switch(struct powerdomain *pwrdm)
  889. {
  890. return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
  891. }
  892. int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
  893. {
  894. if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) {
  895. pwrdm_wait_transition(clkdm->pwrdm.ptr);
  896. return pwrdm_state_switch(clkdm->pwrdm.ptr);
  897. }
  898. return -EINVAL;
  899. }
  900. int pwrdm_pre_transition(void)
  901. {
  902. pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
  903. return 0;
  904. }
  905. int pwrdm_post_transition(void)
  906. {
  907. pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
  908. return 0;
  909. }