powerdomain.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292
  1. /*
  2. * OMAP powerdomain control
  3. *
  4. * Copyright (C) 2007-2008 Texas Instruments, Inc.
  5. * Copyright (C) 2007-2008 Nokia Corporation
  6. *
  7. * Written by Paul Walmsley
  8. *
  9. * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.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 "pm.h"
  36. enum {
  37. PWRDM_STATE_NOW = 0,
  38. PWRDM_STATE_PREV,
  39. };
  40. /* Variable holding value of the CPU dependent PWRSTCTRL Register Offset */
  41. static u16 pwrstctrl_reg_offs;
  42. /* Variable holding value of the CPU dependent PWRSTST Register Offset */
  43. static u16 pwrstst_reg_offs;
  44. /* OMAP3 and OMAP4 specific register bit initialisations
  45. * Notice that the names here are not according to each power
  46. * domain but the bit mapping used applies to all of them
  47. */
  48. /* OMAP3 and OMAP4 Memory Onstate Masks (common across all power domains) */
  49. #define OMAP_MEM0_ONSTATE_MASK OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK
  50. #define OMAP_MEM1_ONSTATE_MASK OMAP3430_L1FLATMEMONSTATE_MASK
  51. #define OMAP_MEM2_ONSTATE_MASK OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK
  52. #define OMAP_MEM3_ONSTATE_MASK OMAP3430_L2FLATMEMONSTATE_MASK
  53. #define OMAP_MEM4_ONSTATE_MASK OMAP4430_OCP_NRET_BANK_ONSTATE_MASK
  54. /* OMAP3 and OMAP4 Memory Retstate Masks (common across all power domains) */
  55. #define OMAP_MEM0_RETSTATE_MASK OMAP3430_SHAREDL1CACHEFLATRETSTATE
  56. #define OMAP_MEM1_RETSTATE_MASK OMAP3430_L1FLATMEMRETSTATE
  57. #define OMAP_MEM2_RETSTATE_MASK OMAP3430_SHAREDL2CACHEFLATRETSTATE
  58. #define OMAP_MEM3_RETSTATE_MASK OMAP3430_L2FLATMEMRETSTATE
  59. #define OMAP_MEM4_RETSTATE_MASK OMAP4430_OCP_NRET_BANK_RETSTATE_MASK
  60. /* OMAP3 and OMAP4 Memory Status bits */
  61. #define OMAP_MEM0_STATEST_MASK OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK
  62. #define OMAP_MEM1_STATEST_MASK OMAP3430_L1FLATMEMSTATEST_MASK
  63. #define OMAP_MEM2_STATEST_MASK OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK
  64. #define OMAP_MEM3_STATEST_MASK OMAP3430_L2FLATMEMSTATEST_MASK
  65. #define OMAP_MEM4_STATEST_MASK OMAP4430_OCP_NRET_BANK_STATEST_MASK
  66. /* pwrdm_list contains all registered struct powerdomains */
  67. static LIST_HEAD(pwrdm_list);
  68. /*
  69. * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to
  70. * protect pwrdm_clkdms[] during clkdm add/del ops
  71. */
  72. static DEFINE_RWLOCK(pwrdm_rwlock);
  73. /* Private functions */
  74. static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
  75. {
  76. u32 v;
  77. v = prm_read_mod_reg(domain, idx);
  78. v &= mask;
  79. v >>= __ffs(mask);
  80. return v;
  81. }
  82. static struct powerdomain *_pwrdm_lookup(const char *name)
  83. {
  84. struct powerdomain *pwrdm, *temp_pwrdm;
  85. pwrdm = NULL;
  86. list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
  87. if (!strcmp(name, temp_pwrdm->name)) {
  88. pwrdm = temp_pwrdm;
  89. break;
  90. }
  91. }
  92. return pwrdm;
  93. }
  94. /* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */
  95. static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
  96. struct pwrdm_dep *deps)
  97. {
  98. struct pwrdm_dep *pd;
  99. if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
  100. return ERR_PTR(-EINVAL);
  101. for (pd = deps; pd->pwrdm_name; pd++) {
  102. if (!omap_chip_is(pd->omap_chip))
  103. continue;
  104. if (!pd->pwrdm && pd->pwrdm_name)
  105. pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
  106. if (pd->pwrdm == pwrdm)
  107. break;
  108. }
  109. if (!pd->pwrdm_name)
  110. return ERR_PTR(-ENOENT);
  111. return pd->pwrdm;
  112. }
  113. static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
  114. {
  115. int prev;
  116. int state;
  117. if (pwrdm == NULL)
  118. return -EINVAL;
  119. state = pwrdm_read_pwrst(pwrdm);
  120. switch (flag) {
  121. case PWRDM_STATE_NOW:
  122. prev = pwrdm->state;
  123. break;
  124. case PWRDM_STATE_PREV:
  125. prev = pwrdm_read_prev_pwrst(pwrdm);
  126. if (pwrdm->state != prev)
  127. pwrdm->state_counter[prev]++;
  128. break;
  129. default:
  130. return -EINVAL;
  131. }
  132. if (state != prev)
  133. pwrdm->state_counter[state]++;
  134. pm_dbg_update_time(pwrdm, prev);
  135. pwrdm->state = state;
  136. return 0;
  137. }
  138. static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
  139. {
  140. pwrdm_clear_all_prev_pwrst(pwrdm);
  141. _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
  142. return 0;
  143. }
  144. static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
  145. {
  146. _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV);
  147. return 0;
  148. }
  149. static __init void _pwrdm_setup(struct powerdomain *pwrdm)
  150. {
  151. int i;
  152. for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
  153. pwrdm->state_counter[i] = 0;
  154. pwrdm_wait_transition(pwrdm);
  155. pwrdm->state = pwrdm_read_pwrst(pwrdm);
  156. pwrdm->state_counter[pwrdm->state] = 1;
  157. }
  158. /* Public functions */
  159. /**
  160. * pwrdm_init - set up the powerdomain layer
  161. *
  162. * Loop through the list of powerdomains, registering all that are
  163. * available on the current CPU. If pwrdm_list is supplied and not
  164. * null, all of the referenced powerdomains will be registered. No
  165. * return value.
  166. */
  167. void pwrdm_init(struct powerdomain **pwrdm_list)
  168. {
  169. struct powerdomain **p = NULL;
  170. if (cpu_is_omap24xx() | cpu_is_omap34xx()) {
  171. pwrstctrl_reg_offs = OMAP2_PM_PWSTCTRL;
  172. pwrstst_reg_offs = OMAP2_PM_PWSTST;
  173. } else if (cpu_is_omap44xx()) {
  174. pwrstctrl_reg_offs = OMAP4_PM_PWSTCTRL;
  175. pwrstst_reg_offs = OMAP4_PM_PWSTST;
  176. } else {
  177. printk(KERN_ERR "Power Domain struct not supported for " \
  178. "this CPU\n");
  179. return;
  180. }
  181. if (pwrdm_list) {
  182. for (p = pwrdm_list; *p; p++) {
  183. pwrdm_register(*p);
  184. _pwrdm_setup(*p);
  185. }
  186. }
  187. }
  188. /**
  189. * pwrdm_register - register a powerdomain
  190. * @pwrdm: struct powerdomain * to register
  191. *
  192. * Adds a powerdomain to the internal powerdomain list. Returns
  193. * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
  194. * already registered by the provided name, or 0 upon success.
  195. */
  196. int pwrdm_register(struct powerdomain *pwrdm)
  197. {
  198. unsigned long flags;
  199. int ret = -EINVAL;
  200. if (!pwrdm)
  201. return -EINVAL;
  202. if (!omap_chip_is(pwrdm->omap_chip))
  203. return -EINVAL;
  204. write_lock_irqsave(&pwrdm_rwlock, flags);
  205. if (_pwrdm_lookup(pwrdm->name)) {
  206. ret = -EEXIST;
  207. goto pr_unlock;
  208. }
  209. list_add(&pwrdm->node, &pwrdm_list);
  210. pr_debug("powerdomain: registered %s\n", pwrdm->name);
  211. ret = 0;
  212. pr_unlock:
  213. write_unlock_irqrestore(&pwrdm_rwlock, flags);
  214. return ret;
  215. }
  216. /**
  217. * pwrdm_unregister - unregister a powerdomain
  218. * @pwrdm: struct powerdomain * to unregister
  219. *
  220. * Removes a powerdomain from the internal powerdomain list. Returns
  221. * -EINVAL if pwrdm argument is NULL.
  222. */
  223. int pwrdm_unregister(struct powerdomain *pwrdm)
  224. {
  225. unsigned long flags;
  226. if (!pwrdm)
  227. return -EINVAL;
  228. write_lock_irqsave(&pwrdm_rwlock, flags);
  229. list_del(&pwrdm->node);
  230. write_unlock_irqrestore(&pwrdm_rwlock, flags);
  231. pr_debug("powerdomain: unregistered %s\n", pwrdm->name);
  232. return 0;
  233. }
  234. /**
  235. * pwrdm_lookup - look up a powerdomain by name, return a pointer
  236. * @name: name of powerdomain
  237. *
  238. * Find a registered powerdomain by its name. Returns a pointer to the
  239. * struct powerdomain if found, or NULL otherwise.
  240. */
  241. struct powerdomain *pwrdm_lookup(const char *name)
  242. {
  243. struct powerdomain *pwrdm;
  244. unsigned long flags;
  245. if (!name)
  246. return NULL;
  247. read_lock_irqsave(&pwrdm_rwlock, flags);
  248. pwrdm = _pwrdm_lookup(name);
  249. read_unlock_irqrestore(&pwrdm_rwlock, flags);
  250. return pwrdm;
  251. }
  252. /**
  253. * pwrdm_for_each_nolock - call function on each registered clockdomain
  254. * @fn: callback function *
  255. *
  256. * Call the supplied function for each registered powerdomain. The
  257. * callback function can return anything but 0 to bail out early from
  258. * the iterator. Returns the last return value of the callback function, which
  259. * should be 0 for success or anything else to indicate failure; or -EINVAL if
  260. * the function pointer is null.
  261. */
  262. int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
  263. void *user)
  264. {
  265. struct powerdomain *temp_pwrdm;
  266. int ret = 0;
  267. if (!fn)
  268. return -EINVAL;
  269. list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
  270. ret = (*fn)(temp_pwrdm, user);
  271. if (ret)
  272. break;
  273. }
  274. return ret;
  275. }
  276. /**
  277. * pwrdm_for_each - call function on each registered clockdomain
  278. * @fn: callback function *
  279. *
  280. * This function is the same as 'pwrdm_for_each_nolock()', but keeps the
  281. * &pwrdm_rwlock locked for reading, so no powerdomain structure manipulation
  282. * functions should be called from the callback, although hardware powerdomain
  283. * control functions are fine.
  284. */
  285. int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
  286. void *user)
  287. {
  288. unsigned long flags;
  289. int ret;
  290. read_lock_irqsave(&pwrdm_rwlock, flags);
  291. ret = pwrdm_for_each_nolock(fn, user);
  292. read_unlock_irqrestore(&pwrdm_rwlock, flags);
  293. return ret;
  294. }
  295. /**
  296. * pwrdm_add_clkdm - add a clockdomain to a powerdomain
  297. * @pwrdm: struct powerdomain * to add the clockdomain to
  298. * @clkdm: struct clockdomain * to associate with a powerdomain
  299. *
  300. * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'. This
  301. * enables the use of pwrdm_for_each_clkdm(). Returns -EINVAL if
  302. * presented with invalid pointers; -ENOMEM if memory could not be allocated;
  303. * or 0 upon success.
  304. */
  305. int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
  306. {
  307. unsigned long flags;
  308. int i;
  309. int ret = -EINVAL;
  310. if (!pwrdm || !clkdm)
  311. return -EINVAL;
  312. pr_debug("powerdomain: associating clockdomain %s with powerdomain "
  313. "%s\n", clkdm->name, pwrdm->name);
  314. write_lock_irqsave(&pwrdm_rwlock, flags);
  315. for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
  316. if (!pwrdm->pwrdm_clkdms[i])
  317. break;
  318. #ifdef DEBUG
  319. if (pwrdm->pwrdm_clkdms[i] == clkdm) {
  320. ret = -EINVAL;
  321. goto pac_exit;
  322. }
  323. #endif
  324. }
  325. if (i == PWRDM_MAX_CLKDMS) {
  326. pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
  327. "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
  328. WARN_ON(1);
  329. ret = -ENOMEM;
  330. goto pac_exit;
  331. }
  332. pwrdm->pwrdm_clkdms[i] = clkdm;
  333. ret = 0;
  334. pac_exit:
  335. write_unlock_irqrestore(&pwrdm_rwlock, flags);
  336. return ret;
  337. }
  338. /**
  339. * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
  340. * @pwrdm: struct powerdomain * to add the clockdomain to
  341. * @clkdm: struct clockdomain * to associate with a powerdomain
  342. *
  343. * Dissociate the clockdomain 'clkdm' from the powerdomain
  344. * 'pwrdm'. Returns -EINVAL if presented with invalid pointers;
  345. * -ENOENT if the clkdm was not associated with the powerdomain, or 0
  346. * upon success.
  347. */
  348. int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
  349. {
  350. unsigned long flags;
  351. int ret = -EINVAL;
  352. int i;
  353. if (!pwrdm || !clkdm)
  354. return -EINVAL;
  355. pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
  356. "%s\n", clkdm->name, pwrdm->name);
  357. write_lock_irqsave(&pwrdm_rwlock, flags);
  358. for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
  359. if (pwrdm->pwrdm_clkdms[i] == clkdm)
  360. break;
  361. if (i == PWRDM_MAX_CLKDMS) {
  362. pr_debug("powerdomain: clkdm %s not associated with pwrdm "
  363. "%s ?!\n", clkdm->name, pwrdm->name);
  364. ret = -ENOENT;
  365. goto pdc_exit;
  366. }
  367. pwrdm->pwrdm_clkdms[i] = NULL;
  368. ret = 0;
  369. pdc_exit:
  370. write_unlock_irqrestore(&pwrdm_rwlock, flags);
  371. return ret;
  372. }
  373. /**
  374. * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
  375. * @pwrdm: struct powerdomain * to iterate over
  376. * @fn: callback function *
  377. *
  378. * Call the supplied function for each clockdomain in the powerdomain
  379. * 'pwrdm'. The callback function can return anything but 0 to bail
  380. * out early from the iterator. The callback function is called with
  381. * the pwrdm_rwlock held for reading, so no powerdomain structure
  382. * manipulation functions should be called from the callback, although
  383. * hardware powerdomain control functions are fine. Returns -EINVAL
  384. * if presented with invalid pointers; or passes along the last return
  385. * value of the callback function, which should be 0 for success or
  386. * anything else to indicate failure.
  387. */
  388. int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
  389. int (*fn)(struct powerdomain *pwrdm,
  390. struct clockdomain *clkdm))
  391. {
  392. unsigned long flags;
  393. int ret = 0;
  394. int i;
  395. if (!fn)
  396. return -EINVAL;
  397. read_lock_irqsave(&pwrdm_rwlock, flags);
  398. for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
  399. ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
  400. read_unlock_irqrestore(&pwrdm_rwlock, flags);
  401. return ret;
  402. }
  403. /**
  404. * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
  405. * @pwrdm1: wake this struct powerdomain * up (dependent)
  406. * @pwrdm2: when this struct powerdomain * wakes up (source)
  407. *
  408. * When the powerdomain represented by pwrdm2 wakes up (due to an
  409. * interrupt), wake up pwrdm1. Implemented in hardware on the OMAP,
  410. * this feature is designed to reduce wakeup latency of the dependent
  411. * powerdomain. Returns -EINVAL if presented with invalid powerdomain
  412. * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
  413. * 0 upon success.
  414. */
  415. int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
  416. {
  417. struct powerdomain *p;
  418. if (!pwrdm1)
  419. return -EINVAL;
  420. p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
  421. if (IS_ERR(p)) {
  422. pr_debug("powerdomain: hardware cannot set/clear wake up of "
  423. "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
  424. return PTR_ERR(p);
  425. }
  426. pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
  427. pwrdm1->name, pwrdm2->name);
  428. prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
  429. pwrdm1->prcm_offs, PM_WKDEP);
  430. return 0;
  431. }
  432. /**
  433. * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1
  434. * @pwrdm1: wake this struct powerdomain * up (dependent)
  435. * @pwrdm2: when this struct powerdomain * wakes up (source)
  436. *
  437. * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2
  438. * wakes up. Returns -EINVAL if presented with invalid powerdomain
  439. * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
  440. * 0 upon success.
  441. */
  442. int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
  443. {
  444. struct powerdomain *p;
  445. if (!pwrdm1)
  446. return -EINVAL;
  447. p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
  448. if (IS_ERR(p)) {
  449. pr_debug("powerdomain: hardware cannot set/clear wake up of "
  450. "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
  451. return PTR_ERR(p);
  452. }
  453. pr_debug("powerdomain: hardware will no longer wake up %s after %s "
  454. "wakes up\n", pwrdm1->name, pwrdm2->name);
  455. prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
  456. pwrdm1->prcm_offs, PM_WKDEP);
  457. return 0;
  458. }
  459. /**
  460. * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1
  461. * @pwrdm1: wake this struct powerdomain * up (dependent)
  462. * @pwrdm2: when this struct powerdomain * wakes up (source)
  463. *
  464. * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be
  465. * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL
  466. * if either powerdomain pointer is invalid; or -ENOENT if the hardware
  467. * is incapable.
  468. *
  469. * REVISIT: Currently this function only represents software-controllable
  470. * wakeup dependencies. Wakeup dependencies fixed in hardware are not
  471. * yet handled here.
  472. */
  473. int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
  474. {
  475. struct powerdomain *p;
  476. if (!pwrdm1)
  477. return -EINVAL;
  478. p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
  479. if (IS_ERR(p)) {
  480. pr_debug("powerdomain: hardware cannot set/clear wake up of "
  481. "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
  482. return PTR_ERR(p);
  483. }
  484. return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
  485. (1 << pwrdm2->dep_bit));
  486. }
  487. /**
  488. * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1
  489. * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
  490. * @pwrdm2: when this struct powerdomain * is active (source)
  491. *
  492. * Prevent pwrdm1 from automatically going inactive (and then to
  493. * retention or off) if pwrdm2 is still active. Returns -EINVAL if
  494. * presented with invalid powerdomain pointers or called on a machine
  495. * that does not support software-configurable hardware sleep dependencies,
  496. * -ENOENT if the specified dependency cannot be set in hardware, or
  497. * 0 upon success.
  498. */
  499. int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
  500. {
  501. struct powerdomain *p;
  502. if (!cpu_is_omap34xx())
  503. return -EINVAL;
  504. if (!pwrdm1)
  505. return -EINVAL;
  506. p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
  507. if (IS_ERR(p)) {
  508. pr_debug("powerdomain: hardware cannot set/clear sleep "
  509. "dependency affecting %s from %s\n", pwrdm1->name,
  510. pwrdm2->name);
  511. return PTR_ERR(p);
  512. }
  513. pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
  514. pwrdm1->name, pwrdm2->name);
  515. cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
  516. pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
  517. return 0;
  518. }
  519. /**
  520. * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1
  521. * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
  522. * @pwrdm2: when this struct powerdomain * is active (source)
  523. *
  524. * Allow pwrdm1 to automatically go inactive (and then to retention or
  525. * off), independent of the activity state of pwrdm2. Returns -EINVAL
  526. * if presented with invalid powerdomain pointers or called on a machine
  527. * that does not support software-configurable hardware sleep dependencies,
  528. * -ENOENT if the specified dependency cannot be cleared in hardware, or
  529. * 0 upon success.
  530. */
  531. int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
  532. {
  533. struct powerdomain *p;
  534. if (!cpu_is_omap34xx())
  535. return -EINVAL;
  536. if (!pwrdm1)
  537. return -EINVAL;
  538. p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
  539. if (IS_ERR(p)) {
  540. pr_debug("powerdomain: hardware cannot set/clear sleep "
  541. "dependency affecting %s from %s\n", pwrdm1->name,
  542. pwrdm2->name);
  543. return PTR_ERR(p);
  544. }
  545. pr_debug("powerdomain: will no longer prevent %s from sleeping if "
  546. "%s is active\n", pwrdm1->name, pwrdm2->name);
  547. cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
  548. pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
  549. return 0;
  550. }
  551. /**
  552. * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1
  553. * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
  554. * @pwrdm2: when this struct powerdomain * is active (source)
  555. *
  556. * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will
  557. * not be allowed to automatically go inactive if pwrdm2 is active;
  558. * 0 if pwrdm1's automatic power state inactivity transition is independent
  559. * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called
  560. * on a machine that does not support software-configurable hardware sleep
  561. * dependencies; or -ENOENT if the hardware is incapable.
  562. *
  563. * REVISIT: Currently this function only represents software-controllable
  564. * sleep dependencies. Sleep dependencies fixed in hardware are not
  565. * yet handled here.
  566. */
  567. int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
  568. {
  569. struct powerdomain *p;
  570. if (!cpu_is_omap34xx())
  571. return -EINVAL;
  572. if (!pwrdm1)
  573. return -EINVAL;
  574. p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
  575. if (IS_ERR(p)) {
  576. pr_debug("powerdomain: hardware cannot set/clear sleep "
  577. "dependency affecting %s from %s\n", pwrdm1->name,
  578. pwrdm2->name);
  579. return PTR_ERR(p);
  580. }
  581. return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
  582. (1 << pwrdm2->dep_bit));
  583. }
  584. /**
  585. * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
  586. * @pwrdm: struct powerdomain *
  587. *
  588. * Return the number of controllable memory banks in powerdomain pwrdm,
  589. * starting with 1. Returns -EINVAL if the powerdomain pointer is null.
  590. */
  591. int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  592. {
  593. if (!pwrdm)
  594. return -EINVAL;
  595. return pwrdm->banks;
  596. }
  597. /**
  598. * pwrdm_set_next_pwrst - set next powerdomain power state
  599. * @pwrdm: struct powerdomain * to set
  600. * @pwrst: one of the PWRDM_POWER_* macros
  601. *
  602. * Set the powerdomain pwrdm's next power state to pwrst. The powerdomain
  603. * may not enter this state immediately if the preconditions for this state
  604. * have not been satisfied. Returns -EINVAL if the powerdomain pointer is
  605. * null or if the power state is invalid for the powerdomin, or returns 0
  606. * upon success.
  607. */
  608. int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
  609. {
  610. if (!pwrdm)
  611. return -EINVAL;
  612. if (!(pwrdm->pwrsts & (1 << pwrst)))
  613. return -EINVAL;
  614. pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
  615. pwrdm->name, pwrst);
  616. prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
  617. (pwrst << OMAP_POWERSTATE_SHIFT),
  618. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  619. return 0;
  620. }
  621. /**
  622. * pwrdm_read_next_pwrst - get next powerdomain power state
  623. * @pwrdm: struct powerdomain * to get power state
  624. *
  625. * Return the powerdomain pwrdm's next power state. Returns -EINVAL
  626. * if the powerdomain pointer is null or returns the next power state
  627. * upon success.
  628. */
  629. int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  630. {
  631. if (!pwrdm)
  632. return -EINVAL;
  633. return prm_read_mod_bits_shift(pwrdm->prcm_offs,
  634. pwrstctrl_reg_offs, OMAP_POWERSTATE_MASK);
  635. }
  636. /**
  637. * pwrdm_read_pwrst - get current powerdomain power state
  638. * @pwrdm: struct powerdomain * to get power state
  639. *
  640. * Return the powerdomain pwrdm's current power state. Returns -EINVAL
  641. * if the powerdomain pointer is null or returns the current power state
  642. * upon success.
  643. */
  644. int pwrdm_read_pwrst(struct powerdomain *pwrdm)
  645. {
  646. if (!pwrdm)
  647. return -EINVAL;
  648. return prm_read_mod_bits_shift(pwrdm->prcm_offs,
  649. pwrstst_reg_offs, OMAP_POWERSTATEST_MASK);
  650. }
  651. /**
  652. * pwrdm_read_prev_pwrst - get previous powerdomain power state
  653. * @pwrdm: struct powerdomain * to get previous power state
  654. *
  655. * Return the powerdomain pwrdm's previous power state. Returns -EINVAL
  656. * if the powerdomain pointer is null or returns the previous power state
  657. * upon success.
  658. */
  659. int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
  660. {
  661. if (!pwrdm)
  662. return -EINVAL;
  663. return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
  664. OMAP3430_LASTPOWERSTATEENTERED_MASK);
  665. }
  666. /**
  667. * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
  668. * @pwrdm: struct powerdomain * to set
  669. * @pwrst: one of the PWRDM_POWER_* macros
  670. *
  671. * Set the next power state that the logic portion of the powerdomain
  672. * pwrdm will enter when the powerdomain enters retention. This will
  673. * be either RETENTION or OFF, if supported. Returns -EINVAL if the
  674. * powerdomain pointer is null or the target power state is not not
  675. * supported, or returns 0 upon success.
  676. */
  677. int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
  678. {
  679. if (!pwrdm)
  680. return -EINVAL;
  681. if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
  682. return -EINVAL;
  683. pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
  684. pwrdm->name, pwrst);
  685. /*
  686. * The register bit names below may not correspond to the
  687. * actual names of the bits in each powerdomain's register,
  688. * but the type of value returned is the same for each
  689. * powerdomain.
  690. */
  691. prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
  692. (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
  693. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  694. return 0;
  695. }
  696. /**
  697. * pwrdm_set_mem_onst - set memory power state while powerdomain ON
  698. * @pwrdm: struct powerdomain * to set
  699. * @bank: memory bank number to set (0-3)
  700. * @pwrst: one of the PWRDM_POWER_* macros
  701. *
  702. * Set the next power state that memory bank x of the powerdomain
  703. * pwrdm will enter when the powerdomain enters the ON state. Bank
  704. * will be a number from 0 to 3, and represents different types of
  705. * memory, depending on the powerdomain. Returns -EINVAL if the
  706. * powerdomain pointer is null or the target power state is not not
  707. * supported for this memory bank, -EEXIST if the target memory bank
  708. * does not exist or is not controllable, or returns 0 upon success.
  709. */
  710. int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
  711. {
  712. u32 m;
  713. if (!pwrdm)
  714. return -EINVAL;
  715. if (pwrdm->banks < (bank + 1))
  716. return -EEXIST;
  717. if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
  718. return -EINVAL;
  719. pr_debug("powerdomain: setting next memory powerstate for domain %s "
  720. "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
  721. /*
  722. * The register bit names below may not correspond to the
  723. * actual names of the bits in each powerdomain's register,
  724. * but the type of value returned is the same for each
  725. * powerdomain.
  726. */
  727. switch (bank) {
  728. case 0:
  729. m = OMAP_MEM0_ONSTATE_MASK;
  730. break;
  731. case 1:
  732. m = OMAP_MEM1_ONSTATE_MASK;
  733. break;
  734. case 2:
  735. m = OMAP_MEM2_ONSTATE_MASK;
  736. break;
  737. case 3:
  738. m = OMAP_MEM3_ONSTATE_MASK;
  739. break;
  740. case 4:
  741. m = OMAP_MEM4_ONSTATE_MASK;
  742. break;
  743. default:
  744. WARN_ON(1); /* should never happen */
  745. return -EEXIST;
  746. }
  747. prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
  748. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  749. return 0;
  750. }
  751. /**
  752. * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
  753. * @pwrdm: struct powerdomain * to set
  754. * @bank: memory bank number to set (0-3)
  755. * @pwrst: one of the PWRDM_POWER_* macros
  756. *
  757. * Set the next power state that memory bank x of the powerdomain
  758. * pwrdm will enter when the powerdomain enters the RETENTION state.
  759. * Bank will be a number from 0 to 3, and represents different types
  760. * of memory, depending on the powerdomain. pwrst will be either
  761. * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain
  762. * pointer is null or the target power state is not not supported for
  763. * this memory bank, -EEXIST if the target memory bank does not exist
  764. * or is not controllable, or returns 0 upon success.
  765. */
  766. int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
  767. {
  768. u32 m;
  769. if (!pwrdm)
  770. return -EINVAL;
  771. if (pwrdm->banks < (bank + 1))
  772. return -EEXIST;
  773. if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
  774. return -EINVAL;
  775. pr_debug("powerdomain: setting next memory powerstate for domain %s "
  776. "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
  777. /*
  778. * The register bit names below may not correspond to the
  779. * actual names of the bits in each powerdomain's register,
  780. * but the type of value returned is the same for each
  781. * powerdomain.
  782. */
  783. switch (bank) {
  784. case 0:
  785. m = OMAP_MEM0_RETSTATE_MASK;
  786. break;
  787. case 1:
  788. m = OMAP_MEM1_RETSTATE_MASK;
  789. break;
  790. case 2:
  791. m = OMAP_MEM2_RETSTATE_MASK;
  792. break;
  793. case 3:
  794. m = OMAP_MEM3_RETSTATE_MASK;
  795. break;
  796. case 4:
  797. m = OMAP_MEM4_RETSTATE_MASK;
  798. break;
  799. default:
  800. WARN_ON(1); /* should never happen */
  801. return -EEXIST;
  802. }
  803. prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
  804. pwrstctrl_reg_offs);
  805. return 0;
  806. }
  807. /**
  808. * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
  809. * @pwrdm: struct powerdomain * to get current logic retention power state
  810. *
  811. * Return the current power state that the logic portion of
  812. * powerdomain pwrdm will enter
  813. * Returns -EINVAL if the powerdomain pointer is null or returns the
  814. * current logic retention power state upon success.
  815. */
  816. int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
  817. {
  818. if (!pwrdm)
  819. return -EINVAL;
  820. return prm_read_mod_bits_shift(pwrdm->prcm_offs,
  821. pwrstst_reg_offs, OMAP3430_LOGICSTATEST);
  822. }
  823. /**
  824. * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
  825. * @pwrdm: struct powerdomain * to get previous logic power state
  826. *
  827. * Return the powerdomain pwrdm's logic power state. Returns -EINVAL
  828. * if the powerdomain pointer is null or returns the previous logic
  829. * power state upon success.
  830. */
  831. int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
  832. {
  833. if (!pwrdm)
  834. return -EINVAL;
  835. /*
  836. * The register bit names below may not correspond to the
  837. * actual names of the bits in each powerdomain's register,
  838. * but the type of value returned is the same for each
  839. * powerdomain.
  840. */
  841. return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
  842. OMAP3430_LASTLOGICSTATEENTERED);
  843. }
  844. /**
  845. * pwrdm_read_mem_pwrst - get current memory bank power state
  846. * @pwrdm: struct powerdomain * to get current memory bank power state
  847. * @bank: memory bank number (0-3)
  848. *
  849. * Return the powerdomain pwrdm's current memory power state for bank
  850. * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
  851. * the target memory bank does not exist or is not controllable, or
  852. * returns the current memory power state upon success.
  853. */
  854. int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  855. {
  856. u32 m;
  857. if (!pwrdm)
  858. return -EINVAL;
  859. if (pwrdm->banks < (bank + 1))
  860. return -EEXIST;
  861. if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
  862. bank = 1;
  863. /*
  864. * The register bit names below may not correspond to the
  865. * actual names of the bits in each powerdomain's register,
  866. * but the type of value returned is the same for each
  867. * powerdomain.
  868. */
  869. switch (bank) {
  870. case 0:
  871. m = OMAP_MEM0_STATEST_MASK;
  872. break;
  873. case 1:
  874. m = OMAP_MEM1_STATEST_MASK;
  875. break;
  876. case 2:
  877. m = OMAP_MEM2_STATEST_MASK;
  878. break;
  879. case 3:
  880. m = OMAP_MEM3_STATEST_MASK;
  881. break;
  882. case 4:
  883. m = OMAP_MEM4_STATEST_MASK;
  884. break;
  885. default:
  886. WARN_ON(1); /* should never happen */
  887. return -EEXIST;
  888. }
  889. return prm_read_mod_bits_shift(pwrdm->prcm_offs,
  890. pwrstst_reg_offs, m);
  891. }
  892. /**
  893. * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
  894. * @pwrdm: struct powerdomain * to get previous memory bank power state
  895. * @bank: memory bank number (0-3)
  896. *
  897. * Return the powerdomain pwrdm's previous memory power state for bank
  898. * x. Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
  899. * the target memory bank does not exist or is not controllable, or
  900. * returns the previous memory power state upon success.
  901. */
  902. int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  903. {
  904. u32 m;
  905. if (!pwrdm)
  906. return -EINVAL;
  907. if (pwrdm->banks < (bank + 1))
  908. return -EEXIST;
  909. if (pwrdm->flags & PWRDM_HAS_MPU_QUIRK)
  910. bank = 1;
  911. /*
  912. * The register bit names below may not correspond to the
  913. * actual names of the bits in each powerdomain's register,
  914. * but the type of value returned is the same for each
  915. * powerdomain.
  916. */
  917. switch (bank) {
  918. case 0:
  919. m = OMAP3430_LASTMEM1STATEENTERED_MASK;
  920. break;
  921. case 1:
  922. m = OMAP3430_LASTMEM2STATEENTERED_MASK;
  923. break;
  924. case 2:
  925. m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
  926. break;
  927. case 3:
  928. m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
  929. break;
  930. default:
  931. WARN_ON(1); /* should never happen */
  932. return -EEXIST;
  933. }
  934. return prm_read_mod_bits_shift(pwrdm->prcm_offs,
  935. OMAP3430_PM_PREPWSTST, m);
  936. }
  937. /**
  938. * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
  939. * @pwrdm: struct powerdomain * to clear
  940. *
  941. * Clear the powerdomain's previous power state register. Clears the
  942. * entire register, including logic and memory bank previous power states.
  943. * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon
  944. * success.
  945. */
  946. int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
  947. {
  948. if (!pwrdm)
  949. return -EINVAL;
  950. /*
  951. * XXX should get the powerdomain's current state here;
  952. * warn & fail if it is not ON.
  953. */
  954. pr_debug("powerdomain: clearing previous power state reg for %s\n",
  955. pwrdm->name);
  956. prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
  957. return 0;
  958. }
  959. /**
  960. * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
  961. * @pwrdm: struct powerdomain *
  962. *
  963. * Enable automatic context save-and-restore upon power state change
  964. * for some devices in a powerdomain. Warning: this only affects a
  965. * subset of devices in a powerdomain; check the TRM closely. Returns
  966. * -EINVAL if the powerdomain pointer is null or if the powerdomain
  967. * does not support automatic save-and-restore, or returns 0 upon
  968. * success.
  969. */
  970. int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
  971. {
  972. if (!pwrdm)
  973. return -EINVAL;
  974. if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
  975. return -EINVAL;
  976. pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
  977. pwrdm->name);
  978. prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
  979. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  980. return 0;
  981. }
  982. /**
  983. * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
  984. * @pwrdm: struct powerdomain *
  985. *
  986. * Disable automatic context save-and-restore upon power state change
  987. * for some devices in a powerdomain. Warning: this only affects a
  988. * subset of devices in a powerdomain; check the TRM closely. Returns
  989. * -EINVAL if the powerdomain pointer is null or if the powerdomain
  990. * does not support automatic save-and-restore, or returns 0 upon
  991. * success.
  992. */
  993. int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
  994. {
  995. if (!pwrdm)
  996. return -EINVAL;
  997. if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
  998. return -EINVAL;
  999. pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
  1000. pwrdm->name);
  1001. prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
  1002. pwrdm->prcm_offs, pwrstctrl_reg_offs);
  1003. return 0;
  1004. }
  1005. /**
  1006. * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
  1007. * @pwrdm: struct powerdomain *
  1008. *
  1009. * Returns 1 if powerdomain 'pwrdm' supports hardware save-and-restore
  1010. * for some devices, or 0 if it does not.
  1011. */
  1012. bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
  1013. {
  1014. return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
  1015. }
  1016. /**
  1017. * pwrdm_wait_transition - wait for powerdomain power transition to finish
  1018. * @pwrdm: struct powerdomain * to wait for
  1019. *
  1020. * If the powerdomain pwrdm is in the process of a state transition,
  1021. * spin until it completes the power transition, or until an iteration
  1022. * bailout value is reached. Returns -EINVAL if the powerdomain
  1023. * pointer is null, -EAGAIN if the bailout value was reached, or
  1024. * returns 0 upon success.
  1025. */
  1026. int pwrdm_wait_transition(struct powerdomain *pwrdm)
  1027. {
  1028. u32 c = 0;
  1029. if (!pwrdm)
  1030. return -EINVAL;
  1031. /*
  1032. * REVISIT: pwrdm_wait_transition() may be better implemented
  1033. * via a callback and a periodic timer check -- how long do we expect
  1034. * powerdomain transitions to take?
  1035. */
  1036. /* XXX Is this udelay() value meaningful? */
  1037. while ((prm_read_mod_reg(pwrdm->prcm_offs, pwrstst_reg_offs) &
  1038. OMAP_INTRANSITION) &&
  1039. (c++ < PWRDM_TRANSITION_BAILOUT))
  1040. udelay(1);
  1041. if (c > PWRDM_TRANSITION_BAILOUT) {
  1042. printk(KERN_ERR "powerdomain: waited too long for "
  1043. "powerdomain %s to complete transition\n", pwrdm->name);
  1044. return -EAGAIN;
  1045. }
  1046. pr_debug("powerdomain: completed transition in %d loops\n", c);
  1047. return 0;
  1048. }
  1049. int pwrdm_state_switch(struct powerdomain *pwrdm)
  1050. {
  1051. return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
  1052. }
  1053. int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
  1054. {
  1055. if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) {
  1056. pwrdm_wait_transition(clkdm->pwrdm.ptr);
  1057. return pwrdm_state_switch(clkdm->pwrdm.ptr);
  1058. }
  1059. return -EINVAL;
  1060. }
  1061. int pwrdm_clk_state_switch(struct clk *clk)
  1062. {
  1063. if (clk != NULL && clk->clkdm != NULL)
  1064. return pwrdm_clkdm_state_switch(clk->clkdm);
  1065. return -EINVAL;
  1066. }
  1067. int pwrdm_pre_transition(void)
  1068. {
  1069. pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
  1070. return 0;
  1071. }
  1072. int pwrdm_post_transition(void)
  1073. {
  1074. pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
  1075. return 0;
  1076. }