powerdomain.c 32 KB

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