clockdomain.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382
  1. /*
  2. * OMAP2/3/4 clockdomain framework functions
  3. *
  4. * Copyright (C) 2008-2011 Texas Instruments, Inc.
  5. * Copyright (C) 2008-2011 Nokia Corporation
  6. *
  7. * Written by Paul Walmsley and Jouni Högander
  8. * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #undef DEBUG
  15. #include <linux/kernel.h>
  16. #include <linux/device.h>
  17. #include <linux/list.h>
  18. #include <linux/errno.h>
  19. #include <linux/string.h>
  20. #include <linux/delay.h>
  21. #include <linux/clk.h>
  22. #include <linux/limits.h>
  23. #include <linux/err.h>
  24. #include <linux/clk-provider.h>
  25. #include <linux/cpu_pm.h>
  26. #include <linux/io.h>
  27. #include <linux/bitops.h>
  28. #include "soc.h"
  29. #include "clock.h"
  30. #include "clockdomain.h"
  31. #include "pm.h"
  32. /* clkdm_list contains all registered struct clockdomains */
  33. static LIST_HEAD(clkdm_list);
  34. /* array of clockdomain deps to be added/removed when clkdm in hwsup mode */
  35. static struct clkdm_autodep *autodeps;
  36. static struct clkdm_ops *arch_clkdm;
  37. void clkdm_save_context(void);
  38. void clkdm_restore_context(void);
  39. /* Private functions */
  40. static struct clockdomain *_clkdm_lookup(const char *name)
  41. {
  42. struct clockdomain *clkdm, *temp_clkdm;
  43. if (!name)
  44. return NULL;
  45. clkdm = NULL;
  46. list_for_each_entry(temp_clkdm, &clkdm_list, node) {
  47. if (!strcmp(name, temp_clkdm->name)) {
  48. clkdm = temp_clkdm;
  49. break;
  50. }
  51. }
  52. return clkdm;
  53. }
  54. /**
  55. * _clkdm_register - register a clockdomain
  56. * @clkdm: struct clockdomain * to register
  57. *
  58. * Adds a clockdomain to the internal clockdomain list.
  59. * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is
  60. * already registered by the provided name, or 0 upon success.
  61. */
  62. static int _clkdm_register(struct clockdomain *clkdm)
  63. {
  64. struct powerdomain *pwrdm;
  65. if (!clkdm || !clkdm->name)
  66. return -EINVAL;
  67. pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
  68. if (!pwrdm) {
  69. pr_err("clockdomain: %s: powerdomain %s does not exist\n",
  70. clkdm->name, clkdm->pwrdm.name);
  71. return -EINVAL;
  72. }
  73. clkdm->pwrdm.ptr = pwrdm;
  74. /* Verify that the clockdomain is not already registered */
  75. if (_clkdm_lookup(clkdm->name))
  76. return -EEXIST;
  77. list_add(&clkdm->node, &clkdm_list);
  78. pwrdm_add_clkdm(pwrdm, clkdm);
  79. pr_debug("clockdomain: registered %s\n", clkdm->name);
  80. return 0;
  81. }
  82. /* _clkdm_deps_lookup - look up the specified clockdomain in a clkdm list */
  83. static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
  84. struct clkdm_dep *deps)
  85. {
  86. struct clkdm_dep *cd;
  87. if (!clkdm || !deps)
  88. return ERR_PTR(-EINVAL);
  89. for (cd = deps; cd->clkdm_name; cd++) {
  90. if (!cd->clkdm && cd->clkdm_name)
  91. cd->clkdm = _clkdm_lookup(cd->clkdm_name);
  92. if (cd->clkdm == clkdm)
  93. break;
  94. }
  95. if (!cd->clkdm_name)
  96. return ERR_PTR(-ENOENT);
  97. return cd;
  98. }
  99. /**
  100. * _autodep_lookup - resolve autodep clkdm names to clkdm pointers; store
  101. * @autodep: struct clkdm_autodep * to resolve
  102. *
  103. * Resolve autodep clockdomain names to clockdomain pointers via
  104. * clkdm_lookup() and store the pointers in the autodep structure. An
  105. * "autodep" is a clockdomain sleep/wakeup dependency that is
  106. * automatically added and removed whenever clocks in the associated
  107. * clockdomain are enabled or disabled (respectively) when the
  108. * clockdomain is in hardware-supervised mode. Meant to be called
  109. * once at clockdomain layer initialization, since these should remain
  110. * fixed for a particular architecture. No return value.
  111. *
  112. * XXX autodeps are deprecated and should be removed at the earliest
  113. * opportunity
  114. */
  115. static void _autodep_lookup(struct clkdm_autodep *autodep)
  116. {
  117. struct clockdomain *clkdm;
  118. if (!autodep)
  119. return;
  120. clkdm = clkdm_lookup(autodep->clkdm.name);
  121. if (!clkdm) {
  122. pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
  123. autodep->clkdm.name);
  124. clkdm = ERR_PTR(-ENOENT);
  125. }
  126. autodep->clkdm.ptr = clkdm;
  127. }
  128. /**
  129. * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
  130. * @clkdm: clockdomain that we are resolving dependencies for
  131. * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
  132. *
  133. * Iterates through @clkdm_deps, looking up the struct clockdomain named by
  134. * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
  135. * No return value.
  136. */
  137. static void _resolve_clkdm_deps(struct clockdomain *clkdm,
  138. struct clkdm_dep *clkdm_deps)
  139. {
  140. struct clkdm_dep *cd;
  141. for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
  142. if (cd->clkdm)
  143. continue;
  144. cd->clkdm = _clkdm_lookup(cd->clkdm_name);
  145. WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
  146. clkdm->name, cd->clkdm_name);
  147. }
  148. }
  149. /**
  150. * _clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1 (lockless)
  151. * @clkdm1: wake this struct clockdomain * up (dependent)
  152. * @clkdm2: when this struct clockdomain * wakes up (source)
  153. *
  154. * When the clockdomain represented by @clkdm2 wakes up, wake up
  155. * @clkdm1. Implemented in hardware on the OMAP, this feature is
  156. * designed to reduce wakeup latency of the dependent clockdomain @clkdm1.
  157. * Returns -EINVAL if presented with invalid clockdomain pointers,
  158. * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon
  159. * success.
  160. */
  161. static int _clkdm_add_wkdep(struct clockdomain *clkdm1,
  162. struct clockdomain *clkdm2)
  163. {
  164. struct clkdm_dep *cd;
  165. int ret = 0;
  166. if (!clkdm1 || !clkdm2)
  167. return -EINVAL;
  168. cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
  169. if (IS_ERR(cd))
  170. ret = PTR_ERR(cd);
  171. if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
  172. ret = -EINVAL;
  173. if (ret) {
  174. pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
  175. clkdm1->name, clkdm2->name);
  176. return ret;
  177. }
  178. cd->wkdep_usecount++;
  179. if (cd->wkdep_usecount == 1) {
  180. pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
  181. clkdm1->name, clkdm2->name);
  182. ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
  183. }
  184. return ret;
  185. }
  186. /**
  187. * _clkdm_del_wkdep - remove a wakeup dep from clkdm2 to clkdm1 (lockless)
  188. * @clkdm1: wake this struct clockdomain * up (dependent)
  189. * @clkdm2: when this struct clockdomain * wakes up (source)
  190. *
  191. * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2
  192. * wakes up. Returns -EINVAL if presented with invalid clockdomain
  193. * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or
  194. * 0 upon success.
  195. */
  196. static int _clkdm_del_wkdep(struct clockdomain *clkdm1,
  197. struct clockdomain *clkdm2)
  198. {
  199. struct clkdm_dep *cd;
  200. int ret = 0;
  201. if (!clkdm1 || !clkdm2)
  202. return -EINVAL;
  203. cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
  204. if (IS_ERR(cd))
  205. ret = PTR_ERR(cd);
  206. if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
  207. ret = -EINVAL;
  208. if (ret) {
  209. pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
  210. clkdm1->name, clkdm2->name);
  211. return ret;
  212. }
  213. cd->wkdep_usecount--;
  214. if (cd->wkdep_usecount == 0) {
  215. pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
  216. clkdm1->name, clkdm2->name);
  217. ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
  218. }
  219. return ret;
  220. }
  221. /**
  222. * _clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 (lockless)
  223. * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
  224. * @clkdm2: when this struct clockdomain * is active (source)
  225. *
  226. * Prevent @clkdm1 from automatically going inactive (and then to
  227. * retention or off) if @clkdm2 is active. Returns -EINVAL if
  228. * presented with invalid clockdomain pointers or called on a machine
  229. * that does not support software-configurable hardware sleep
  230. * dependencies, -ENOENT if the specified dependency cannot be set in
  231. * hardware, or 0 upon success.
  232. */
  233. static int _clkdm_add_sleepdep(struct clockdomain *clkdm1,
  234. struct clockdomain *clkdm2)
  235. {
  236. struct clkdm_dep *cd;
  237. int ret = 0;
  238. if (!clkdm1 || !clkdm2)
  239. return -EINVAL;
  240. cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
  241. if (IS_ERR(cd))
  242. ret = PTR_ERR(cd);
  243. if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
  244. ret = -EINVAL;
  245. if (ret) {
  246. pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
  247. clkdm1->name, clkdm2->name);
  248. return ret;
  249. }
  250. cd->sleepdep_usecount++;
  251. if (cd->sleepdep_usecount == 1) {
  252. pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
  253. clkdm1->name, clkdm2->name);
  254. ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
  255. }
  256. return ret;
  257. }
  258. /**
  259. * _clkdm_del_sleepdep - remove a sleep dep from clkdm2 to clkdm1 (lockless)
  260. * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
  261. * @clkdm2: when this struct clockdomain * is active (source)
  262. *
  263. * Allow @clkdm1 to automatically go inactive (and then to retention or
  264. * off), independent of the activity state of @clkdm2. Returns -EINVAL
  265. * if presented with invalid clockdomain pointers or called on a machine
  266. * that does not support software-configurable hardware sleep dependencies,
  267. * -ENOENT if the specified dependency cannot be cleared in hardware, or
  268. * 0 upon success.
  269. */
  270. static int _clkdm_del_sleepdep(struct clockdomain *clkdm1,
  271. struct clockdomain *clkdm2)
  272. {
  273. struct clkdm_dep *cd;
  274. int ret = 0;
  275. if (!clkdm1 || !clkdm2)
  276. return -EINVAL;
  277. cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
  278. if (IS_ERR(cd))
  279. ret = PTR_ERR(cd);
  280. if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
  281. ret = -EINVAL;
  282. if (ret) {
  283. pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
  284. clkdm1->name, clkdm2->name);
  285. return ret;
  286. }
  287. cd->sleepdep_usecount--;
  288. if (cd->sleepdep_usecount == 0) {
  289. pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
  290. clkdm1->name, clkdm2->name);
  291. ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
  292. }
  293. return ret;
  294. }
  295. /* Public functions */
  296. /**
  297. * clkdm_register_platform_funcs - register clockdomain implementation fns
  298. * @co: func pointers for arch specific implementations
  299. *
  300. * Register the list of function pointers used to implement the
  301. * clockdomain functions on different OMAP SoCs. Should be called
  302. * before any other clkdm_register*() function. Returns -EINVAL if
  303. * @co is null, -EEXIST if platform functions have already been
  304. * registered, or 0 upon success.
  305. */
  306. int clkdm_register_platform_funcs(struct clkdm_ops *co)
  307. {
  308. if (!co)
  309. return -EINVAL;
  310. if (arch_clkdm)
  311. return -EEXIST;
  312. arch_clkdm = co;
  313. return 0;
  314. };
  315. /**
  316. * clkdm_register_clkdms - register SoC clockdomains
  317. * @cs: pointer to an array of struct clockdomain to register
  318. *
  319. * Register the clockdomains available on a particular OMAP SoC. Must
  320. * be called after clkdm_register_platform_funcs(). May be called
  321. * multiple times. Returns -EACCES if called before
  322. * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is
  323. * null; or 0 upon success.
  324. */
  325. int clkdm_register_clkdms(struct clockdomain **cs)
  326. {
  327. struct clockdomain **c = NULL;
  328. if (!arch_clkdm)
  329. return -EACCES;
  330. if (!cs)
  331. return -EINVAL;
  332. for (c = cs; *c; c++)
  333. _clkdm_register(*c);
  334. return 0;
  335. }
  336. /**
  337. * clkdm_register_autodeps - register autodeps (if required)
  338. * @ia: pointer to a static array of struct clkdm_autodep to register
  339. *
  340. * Register clockdomain "automatic dependencies." These are
  341. * clockdomain wakeup and sleep dependencies that are automatically
  342. * added whenever the first clock inside a clockdomain is enabled, and
  343. * removed whenever the last clock inside a clockdomain is disabled.
  344. * These are currently only used on OMAP3 devices, and are deprecated,
  345. * since they waste energy. However, until the OMAP2/3 IP block
  346. * enable/disable sequence can be converted to match the OMAP4
  347. * sequence, they are needed.
  348. *
  349. * Must be called only after all of the SoC clockdomains are
  350. * registered, since the function will resolve autodep clockdomain
  351. * names into clockdomain pointers.
  352. *
  353. * The struct clkdm_autodep @ia array must be static, as this function
  354. * does not copy the array elements.
  355. *
  356. * Returns -EACCES if called before any clockdomains have been
  357. * registered, -EINVAL if called with a null @ia argument, -EEXIST if
  358. * autodeps have already been registered, or 0 upon success.
  359. */
  360. int clkdm_register_autodeps(struct clkdm_autodep *ia)
  361. {
  362. struct clkdm_autodep *a = NULL;
  363. if (list_empty(&clkdm_list))
  364. return -EACCES;
  365. if (!ia)
  366. return -EINVAL;
  367. if (autodeps)
  368. return -EEXIST;
  369. autodeps = ia;
  370. for (a = autodeps; a->clkdm.ptr; a++)
  371. _autodep_lookup(a);
  372. return 0;
  373. }
  374. static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
  375. {
  376. switch (cmd) {
  377. case CPU_CLUSTER_PM_ENTER:
  378. if (enable_off_mode)
  379. clkdm_save_context();
  380. break;
  381. case CPU_CLUSTER_PM_EXIT:
  382. if (enable_off_mode)
  383. clkdm_restore_context();
  384. break;
  385. }
  386. return NOTIFY_OK;
  387. }
  388. /**
  389. * clkdm_complete_init - set up the clockdomain layer
  390. *
  391. * Put all clockdomains into software-supervised mode; PM code should
  392. * later enable hardware-supervised mode as appropriate. Must be
  393. * called after clkdm_register_clkdms(). Returns -EACCES if called
  394. * before clkdm_register_clkdms(), or 0 upon success.
  395. */
  396. int clkdm_complete_init(void)
  397. {
  398. struct clockdomain *clkdm;
  399. static struct notifier_block nb;
  400. if (list_empty(&clkdm_list))
  401. return -EACCES;
  402. list_for_each_entry(clkdm, &clkdm_list, node) {
  403. clkdm_deny_idle(clkdm);
  404. _resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs);
  405. clkdm_clear_all_wkdeps(clkdm);
  406. _resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
  407. clkdm_clear_all_sleepdeps(clkdm);
  408. }
  409. /* Only AM43XX can lose clkdm context during rtc-ddr suspend */
  410. if (soc_is_am43xx()) {
  411. nb.notifier_call = cpu_notifier;
  412. cpu_pm_register_notifier(&nb);
  413. }
  414. return 0;
  415. }
  416. /**
  417. * clkdm_lookup - look up a clockdomain by name, return a pointer
  418. * @name: name of clockdomain
  419. *
  420. * Find a registered clockdomain by its name @name. Returns a pointer
  421. * to the struct clockdomain if found, or NULL otherwise.
  422. */
  423. struct clockdomain *clkdm_lookup(const char *name)
  424. {
  425. struct clockdomain *clkdm, *temp_clkdm;
  426. if (!name)
  427. return NULL;
  428. clkdm = NULL;
  429. list_for_each_entry(temp_clkdm, &clkdm_list, node) {
  430. if (!strcmp(name, temp_clkdm->name)) {
  431. clkdm = temp_clkdm;
  432. break;
  433. }
  434. }
  435. return clkdm;
  436. }
  437. /**
  438. * clkdm_for_each - call function on each registered clockdomain
  439. * @fn: callback function *
  440. *
  441. * Call the supplied function @fn for each registered clockdomain.
  442. * The callback function @fn can return anything but 0 to bail
  443. * out early from the iterator. The callback function is called with
  444. * the clkdm_mutex held, so no clockdomain structure manipulation
  445. * functions should be called from the callback, although hardware
  446. * clockdomain control functions are fine. Returns the last return
  447. * value of the callback function, which should be 0 for success or
  448. * anything else to indicate failure; or -EINVAL if the function pointer
  449. * is null.
  450. */
  451. int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
  452. void *user)
  453. {
  454. struct clockdomain *clkdm;
  455. int ret = 0;
  456. if (!fn)
  457. return -EINVAL;
  458. list_for_each_entry(clkdm, &clkdm_list, node) {
  459. ret = (*fn)(clkdm, user);
  460. if (ret)
  461. break;
  462. }
  463. return ret;
  464. }
  465. /**
  466. * clkdm_get_pwrdm - return a ptr to the pwrdm that this clkdm resides in
  467. * @clkdm: struct clockdomain *
  468. *
  469. * Return a pointer to the struct powerdomain that the specified clockdomain
  470. * @clkdm exists in, or returns NULL if @clkdm is NULL.
  471. */
  472. struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
  473. {
  474. if (!clkdm)
  475. return NULL;
  476. return clkdm->pwrdm.ptr;
  477. }
  478. /* Hardware clockdomain control */
  479. /**
  480. * clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1
  481. * @clkdm1: wake this struct clockdomain * up (dependent)
  482. * @clkdm2: when this struct clockdomain * wakes up (source)
  483. *
  484. * When the clockdomain represented by @clkdm2 wakes up, wake up
  485. * @clkdm1. Implemented in hardware on the OMAP, this feature is
  486. * designed to reduce wakeup latency of the dependent clockdomain @clkdm1.
  487. * Returns -EINVAL if presented with invalid clockdomain pointers,
  488. * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon
  489. * success.
  490. */
  491. int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  492. {
  493. struct clkdm_dep *cd;
  494. int ret;
  495. if (!clkdm1 || !clkdm2)
  496. return -EINVAL;
  497. cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
  498. if (IS_ERR(cd))
  499. return PTR_ERR(cd);
  500. pwrdm_lock(cd->clkdm->pwrdm.ptr);
  501. ret = _clkdm_add_wkdep(clkdm1, clkdm2);
  502. pwrdm_unlock(cd->clkdm->pwrdm.ptr);
  503. return ret;
  504. }
  505. /**
  506. * clkdm_del_wkdep - remove a wakeup dependency from clkdm2 to clkdm1
  507. * @clkdm1: wake this struct clockdomain * up (dependent)
  508. * @clkdm2: when this struct clockdomain * wakes up (source)
  509. *
  510. * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2
  511. * wakes up. Returns -EINVAL if presented with invalid clockdomain
  512. * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or
  513. * 0 upon success.
  514. */
  515. int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  516. {
  517. struct clkdm_dep *cd;
  518. int ret;
  519. if (!clkdm1 || !clkdm2)
  520. return -EINVAL;
  521. cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
  522. if (IS_ERR(cd))
  523. return PTR_ERR(cd);
  524. pwrdm_lock(cd->clkdm->pwrdm.ptr);
  525. ret = _clkdm_del_wkdep(clkdm1, clkdm2);
  526. pwrdm_unlock(cd->clkdm->pwrdm.ptr);
  527. return ret;
  528. }
  529. /**
  530. * clkdm_read_wkdep - read wakeup dependency state from clkdm2 to clkdm1
  531. * @clkdm1: wake this struct clockdomain * up (dependent)
  532. * @clkdm2: when this struct clockdomain * wakes up (source)
  533. *
  534. * Return 1 if a hardware wakeup dependency exists wherein @clkdm1 will be
  535. * awoken when @clkdm2 wakes up; 0 if dependency is not set; -EINVAL
  536. * if either clockdomain pointer is invalid; or -ENOENT if the hardware
  537. * is incapable.
  538. *
  539. * REVISIT: Currently this function only represents software-controllable
  540. * wakeup dependencies. Wakeup dependencies fixed in hardware are not
  541. * yet handled here.
  542. */
  543. int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  544. {
  545. struct clkdm_dep *cd;
  546. int ret = 0;
  547. if (!clkdm1 || !clkdm2)
  548. return -EINVAL;
  549. cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
  550. if (IS_ERR(cd))
  551. ret = PTR_ERR(cd);
  552. if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep)
  553. ret = -EINVAL;
  554. if (ret) {
  555. pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
  556. clkdm1->name, clkdm2->name);
  557. return ret;
  558. }
  559. /* XXX It's faster to return the wkdep_usecount */
  560. return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
  561. }
  562. /**
  563. * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm
  564. * @clkdm: struct clockdomain * to remove all wakeup dependencies from
  565. *
  566. * Remove all inter-clockdomain wakeup dependencies that could cause
  567. * @clkdm to wake. Intended to be used during boot to initialize the
  568. * PRCM to a known state, after all clockdomains are put into swsup idle
  569. * and woken up. Returns -EINVAL if @clkdm pointer is invalid, or
  570. * 0 upon success.
  571. */
  572. int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
  573. {
  574. if (!clkdm)
  575. return -EINVAL;
  576. if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps)
  577. return -EINVAL;
  578. return arch_clkdm->clkdm_clear_all_wkdeps(clkdm);
  579. }
  580. /**
  581. * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1
  582. * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
  583. * @clkdm2: when this struct clockdomain * is active (source)
  584. *
  585. * Prevent @clkdm1 from automatically going inactive (and then to
  586. * retention or off) if @clkdm2 is active. Returns -EINVAL if
  587. * presented with invalid clockdomain pointers or called on a machine
  588. * that does not support software-configurable hardware sleep
  589. * dependencies, -ENOENT if the specified dependency cannot be set in
  590. * hardware, or 0 upon success.
  591. */
  592. int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  593. {
  594. struct clkdm_dep *cd;
  595. int ret;
  596. if (!clkdm1 || !clkdm2)
  597. return -EINVAL;
  598. cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
  599. if (IS_ERR(cd))
  600. return PTR_ERR(cd);
  601. pwrdm_lock(cd->clkdm->pwrdm.ptr);
  602. ret = _clkdm_add_sleepdep(clkdm1, clkdm2);
  603. pwrdm_unlock(cd->clkdm->pwrdm.ptr);
  604. return ret;
  605. }
  606. /**
  607. * clkdm_del_sleepdep - remove a sleep dependency from clkdm2 to clkdm1
  608. * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
  609. * @clkdm2: when this struct clockdomain * is active (source)
  610. *
  611. * Allow @clkdm1 to automatically go inactive (and then to retention or
  612. * off), independent of the activity state of @clkdm2. Returns -EINVAL
  613. * if presented with invalid clockdomain pointers or called on a machine
  614. * that does not support software-configurable hardware sleep dependencies,
  615. * -ENOENT if the specified dependency cannot be cleared in hardware, or
  616. * 0 upon success.
  617. */
  618. int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  619. {
  620. struct clkdm_dep *cd;
  621. int ret;
  622. if (!clkdm1 || !clkdm2)
  623. return -EINVAL;
  624. cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
  625. if (IS_ERR(cd))
  626. return PTR_ERR(cd);
  627. pwrdm_lock(cd->clkdm->pwrdm.ptr);
  628. ret = _clkdm_del_sleepdep(clkdm1, clkdm2);
  629. pwrdm_unlock(cd->clkdm->pwrdm.ptr);
  630. return ret;
  631. }
  632. /**
  633. * clkdm_read_sleepdep - read sleep dependency state from clkdm2 to clkdm1
  634. * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
  635. * @clkdm2: when this struct clockdomain * is active (source)
  636. *
  637. * Return 1 if a hardware sleep dependency exists wherein @clkdm1 will
  638. * not be allowed to automatically go inactive if @clkdm2 is active;
  639. * 0 if @clkdm1's automatic power state inactivity transition is independent
  640. * of @clkdm2's; -EINVAL if either clockdomain pointer is invalid or called
  641. * on a machine that does not support software-configurable hardware sleep
  642. * dependencies; or -ENOENT if the hardware is incapable.
  643. *
  644. * REVISIT: Currently this function only represents software-controllable
  645. * sleep dependencies. Sleep dependencies fixed in hardware are not
  646. * yet handled here.
  647. */
  648. int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  649. {
  650. struct clkdm_dep *cd;
  651. int ret = 0;
  652. if (!clkdm1 || !clkdm2)
  653. return -EINVAL;
  654. cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
  655. if (IS_ERR(cd))
  656. ret = PTR_ERR(cd);
  657. if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep)
  658. ret = -EINVAL;
  659. if (ret) {
  660. pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
  661. clkdm1->name, clkdm2->name);
  662. return ret;
  663. }
  664. /* XXX It's faster to return the sleepdep_usecount */
  665. return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
  666. }
  667. /**
  668. * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm
  669. * @clkdm: struct clockdomain * to remove all sleep dependencies from
  670. *
  671. * Remove all inter-clockdomain sleep dependencies that could prevent
  672. * @clkdm from idling. Intended to be used during boot to initialize the
  673. * PRCM to a known state, after all clockdomains are put into swsup idle
  674. * and woken up. Returns -EINVAL if @clkdm pointer is invalid, or
  675. * 0 upon success.
  676. */
  677. int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
  678. {
  679. if (!clkdm)
  680. return -EINVAL;
  681. if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps)
  682. return -EINVAL;
  683. return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm);
  684. }
  685. /**
  686. * clkdm_sleep_nolock - force clockdomain sleep transition (lockless)
  687. * @clkdm: struct clockdomain *
  688. *
  689. * Instruct the CM to force a sleep transition on the specified
  690. * clockdomain @clkdm. Only for use by the powerdomain code. Returns
  691. * -EINVAL if @clkdm is NULL or if clockdomain does not support
  692. * software-initiated sleep; 0 upon success.
  693. */
  694. int clkdm_sleep_nolock(struct clockdomain *clkdm)
  695. {
  696. int ret;
  697. if (!clkdm)
  698. return -EINVAL;
  699. if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
  700. pr_debug("clockdomain: %s does not support forcing sleep via software\n",
  701. clkdm->name);
  702. return -EINVAL;
  703. }
  704. if (!arch_clkdm || !arch_clkdm->clkdm_sleep)
  705. return -EINVAL;
  706. pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
  707. clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
  708. ret = arch_clkdm->clkdm_sleep(clkdm);
  709. ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
  710. return ret;
  711. }
  712. /**
  713. * clkdm_sleep - force clockdomain sleep transition
  714. * @clkdm: struct clockdomain *
  715. *
  716. * Instruct the CM to force a sleep transition on the specified
  717. * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if
  718. * clockdomain does not support software-initiated sleep; 0 upon
  719. * success.
  720. */
  721. int clkdm_sleep(struct clockdomain *clkdm)
  722. {
  723. int ret;
  724. pwrdm_lock(clkdm->pwrdm.ptr);
  725. ret = clkdm_sleep_nolock(clkdm);
  726. pwrdm_unlock(clkdm->pwrdm.ptr);
  727. return ret;
  728. }
  729. /**
  730. * clkdm_wakeup_nolock - force clockdomain wakeup transition (lockless)
  731. * @clkdm: struct clockdomain *
  732. *
  733. * Instruct the CM to force a wakeup transition on the specified
  734. * clockdomain @clkdm. Only for use by the powerdomain code. Returns
  735. * -EINVAL if @clkdm is NULL or if the clockdomain does not support
  736. * software-controlled wakeup; 0 upon success.
  737. */
  738. int clkdm_wakeup_nolock(struct clockdomain *clkdm)
  739. {
  740. int ret;
  741. if (!clkdm)
  742. return -EINVAL;
  743. if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
  744. pr_debug("clockdomain: %s does not support forcing wakeup via software\n",
  745. clkdm->name);
  746. return -EINVAL;
  747. }
  748. if (!arch_clkdm || !arch_clkdm->clkdm_wakeup)
  749. return -EINVAL;
  750. pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
  751. clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
  752. ret = arch_clkdm->clkdm_wakeup(clkdm);
  753. ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
  754. return ret;
  755. }
  756. /**
  757. * clkdm_wakeup - force clockdomain wakeup transition
  758. * @clkdm: struct clockdomain *
  759. *
  760. * Instruct the CM to force a wakeup transition on the specified
  761. * clockdomain @clkdm. Returns -EINVAL if @clkdm is NULL or if the
  762. * clockdomain does not support software-controlled wakeup; 0 upon
  763. * success.
  764. */
  765. int clkdm_wakeup(struct clockdomain *clkdm)
  766. {
  767. int ret;
  768. pwrdm_lock(clkdm->pwrdm.ptr);
  769. ret = clkdm_wakeup_nolock(clkdm);
  770. pwrdm_unlock(clkdm->pwrdm.ptr);
  771. return ret;
  772. }
  773. /**
  774. * clkdm_allow_idle_nolock - enable hwsup idle transitions for clkdm
  775. * @clkdm: struct clockdomain *
  776. *
  777. * Allow the hardware to automatically switch the clockdomain @clkdm
  778. * into active or idle states, as needed by downstream clocks. If the
  779. * clockdomain has any downstream clocks enabled in the clock
  780. * framework, wkdep/sleepdep autodependencies are added; this is so
  781. * device drivers can read and write to the device. Only for use by
  782. * the powerdomain code. No return value.
  783. */
  784. void clkdm_allow_idle_nolock(struct clockdomain *clkdm)
  785. {
  786. if (!clkdm)
  787. return;
  788. if (!WARN_ON(!clkdm->forcewake_count))
  789. clkdm->forcewake_count--;
  790. if (clkdm->forcewake_count)
  791. return;
  792. if (!clkdm->usecount && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
  793. clkdm_sleep_nolock(clkdm);
  794. if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO))
  795. return;
  796. if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING)
  797. return;
  798. if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle)
  799. return;
  800. pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
  801. clkdm->name);
  802. clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
  803. arch_clkdm->clkdm_allow_idle(clkdm);
  804. pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
  805. }
  806. /**
  807. * clkdm_allow_idle - enable hwsup idle transitions for clkdm
  808. * @clkdm: struct clockdomain *
  809. *
  810. * Allow the hardware to automatically switch the clockdomain @clkdm into
  811. * active or idle states, as needed by downstream clocks. If the
  812. * clockdomain has any downstream clocks enabled in the clock
  813. * framework, wkdep/sleepdep autodependencies are added; this is so
  814. * device drivers can read and write to the device. No return value.
  815. */
  816. void clkdm_allow_idle(struct clockdomain *clkdm)
  817. {
  818. pwrdm_lock(clkdm->pwrdm.ptr);
  819. clkdm_allow_idle_nolock(clkdm);
  820. pwrdm_unlock(clkdm->pwrdm.ptr);
  821. }
  822. /**
  823. * clkdm_deny_idle - disable hwsup idle transitions for clkdm
  824. * @clkdm: struct clockdomain *
  825. *
  826. * Prevent the hardware from automatically switching the clockdomain
  827. * @clkdm into inactive or idle states. If the clockdomain has
  828. * downstream clocks enabled in the clock framework, wkdep/sleepdep
  829. * autodependencies are removed. Only for use by the powerdomain
  830. * code. No return value.
  831. */
  832. void clkdm_deny_idle_nolock(struct clockdomain *clkdm)
  833. {
  834. if (!clkdm)
  835. return;
  836. if (clkdm->forcewake_count++)
  837. return;
  838. if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
  839. clkdm_wakeup_nolock(clkdm);
  840. if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO))
  841. return;
  842. if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING)
  843. return;
  844. if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle)
  845. return;
  846. pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
  847. clkdm->name);
  848. clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
  849. arch_clkdm->clkdm_deny_idle(clkdm);
  850. pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
  851. }
  852. /**
  853. * clkdm_deny_idle - disable hwsup idle transitions for clkdm
  854. * @clkdm: struct clockdomain *
  855. *
  856. * Prevent the hardware from automatically switching the clockdomain
  857. * @clkdm into inactive or idle states. If the clockdomain has
  858. * downstream clocks enabled in the clock framework, wkdep/sleepdep
  859. * autodependencies are removed. No return value.
  860. */
  861. void clkdm_deny_idle(struct clockdomain *clkdm)
  862. {
  863. pwrdm_lock(clkdm->pwrdm.ptr);
  864. clkdm_deny_idle_nolock(clkdm);
  865. pwrdm_unlock(clkdm->pwrdm.ptr);
  866. }
  867. /**
  868. * clkdm_in_hwsup - is clockdomain @clkdm have hardware-supervised idle enabled?
  869. * @clkdm: struct clockdomain *
  870. *
  871. * Returns true if clockdomain @clkdm currently has
  872. * hardware-supervised idle enabled, or false if it does not or if
  873. * @clkdm is NULL. It is only valid to call this function after
  874. * clkdm_init() has been called. This function does not actually read
  875. * bits from the hardware; it instead tests an in-memory flag that is
  876. * changed whenever the clockdomain code changes the auto-idle mode.
  877. */
  878. bool clkdm_in_hwsup(struct clockdomain *clkdm)
  879. {
  880. bool ret;
  881. if (!clkdm)
  882. return false;
  883. ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false;
  884. return ret;
  885. }
  886. /**
  887. * clkdm_missing_idle_reporting - can @clkdm enter autoidle even if in use?
  888. * @clkdm: struct clockdomain *
  889. *
  890. * Returns true if clockdomain @clkdm has the
  891. * CLKDM_MISSING_IDLE_REPORTING flag set, or false if not or @clkdm is
  892. * null. More information is available in the documentation for the
  893. * CLKDM_MISSING_IDLE_REPORTING macro.
  894. */
  895. bool clkdm_missing_idle_reporting(struct clockdomain *clkdm)
  896. {
  897. if (!clkdm)
  898. return false;
  899. return (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) ? true : false;
  900. }
  901. /* Public autodep handling functions (deprecated) */
  902. /**
  903. * clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
  904. * @clkdm: struct clockdomain *
  905. *
  906. * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
  907. * in hardware-supervised mode. Meant to be called from clock framework
  908. * when a clock inside clockdomain 'clkdm' is enabled. No return value.
  909. *
  910. * XXX autodeps are deprecated and should be removed at the earliest
  911. * opportunity
  912. */
  913. void clkdm_add_autodeps(struct clockdomain *clkdm)
  914. {
  915. struct clkdm_autodep *autodep;
  916. if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
  917. return;
  918. for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
  919. if (IS_ERR(autodep->clkdm.ptr))
  920. continue;
  921. pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n",
  922. clkdm->name, autodep->clkdm.ptr->name);
  923. _clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
  924. _clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
  925. }
  926. }
  927. /**
  928. * clkdm_del_autodeps - remove auto sleepdeps/wkdeps from clkdm
  929. * @clkdm: struct clockdomain *
  930. *
  931. * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
  932. * in hardware-supervised mode. Meant to be called from clock framework
  933. * when a clock inside clockdomain 'clkdm' is disabled. No return value.
  934. *
  935. * XXX autodeps are deprecated and should be removed at the earliest
  936. * opportunity
  937. */
  938. void clkdm_del_autodeps(struct clockdomain *clkdm)
  939. {
  940. struct clkdm_autodep *autodep;
  941. if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
  942. return;
  943. for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
  944. if (IS_ERR(autodep->clkdm.ptr))
  945. continue;
  946. pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n",
  947. clkdm->name, autodep->clkdm.ptr->name);
  948. _clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
  949. _clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
  950. }
  951. }
  952. /* Clockdomain-to-clock/hwmod framework interface code */
  953. static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
  954. {
  955. if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
  956. return -EINVAL;
  957. pwrdm_lock(clkdm->pwrdm.ptr);
  958. /*
  959. * For arch's with no autodeps, clkcm_clk_enable
  960. * should be called for every clock instance or hwmod that is
  961. * enabled, so the clkdm can be force woken up.
  962. */
  963. clkdm->usecount++;
  964. if (clkdm->usecount > 1 && autodeps) {
  965. pwrdm_unlock(clkdm->pwrdm.ptr);
  966. return 0;
  967. }
  968. arch_clkdm->clkdm_clk_enable(clkdm);
  969. pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
  970. pwrdm_unlock(clkdm->pwrdm.ptr);
  971. pr_debug("clockdomain: %s: enabled\n", clkdm->name);
  972. return 0;
  973. }
  974. /**
  975. * clkdm_clk_enable - add an enabled downstream clock to this clkdm
  976. * @clkdm: struct clockdomain *
  977. * @clk: struct clk * of the enabled downstream clock
  978. *
  979. * Increment the usecount of the clockdomain @clkdm and ensure that it
  980. * is awake before @clk is enabled. Intended to be called by
  981. * clk_enable() code. If the clockdomain is in software-supervised
  982. * idle mode, force the clockdomain to wake. If the clockdomain is in
  983. * hardware-supervised idle mode, add clkdm-pwrdm autodependencies, to
  984. * ensure that devices in the clockdomain can be read from/written to
  985. * by on-chip processors. Returns -EINVAL if passed null pointers;
  986. * returns 0 upon success or if the clockdomain is in hwsup idle mode.
  987. */
  988. int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
  989. {
  990. /*
  991. * XXX Rewrite this code to maintain a list of enabled
  992. * downstream clocks for debugging purposes?
  993. */
  994. if (!clk)
  995. return -EINVAL;
  996. return _clkdm_clk_hwmod_enable(clkdm);
  997. }
  998. /**
  999. * clkdm_clk_disable - remove an enabled downstream clock from this clkdm
  1000. * @clkdm: struct clockdomain *
  1001. * @clk: struct clk * of the disabled downstream clock
  1002. *
  1003. * Decrement the usecount of this clockdomain @clkdm when @clk is
  1004. * disabled. Intended to be called by clk_disable() code. If the
  1005. * clockdomain usecount goes to 0, put the clockdomain to sleep
  1006. * (software-supervised mode) or remove the clkdm autodependencies
  1007. * (hardware-supervised mode). Returns -EINVAL if passed null
  1008. * pointers; -ERANGE if the @clkdm usecount underflows; or returns 0
  1009. * upon success or if the clockdomain is in hwsup idle mode.
  1010. */
  1011. int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
  1012. {
  1013. if (!clkdm || !clk || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
  1014. return -EINVAL;
  1015. pwrdm_lock(clkdm->pwrdm.ptr);
  1016. /* corner case: disabling unused clocks */
  1017. if ((__clk_get_enable_count(clk) == 0) && clkdm->usecount == 0)
  1018. goto ccd_exit;
  1019. if (clkdm->usecount == 0) {
  1020. pwrdm_unlock(clkdm->pwrdm.ptr);
  1021. WARN_ON(1); /* underflow */
  1022. return -ERANGE;
  1023. }
  1024. clkdm->usecount--;
  1025. if (clkdm->usecount > 0) {
  1026. pwrdm_unlock(clkdm->pwrdm.ptr);
  1027. return 0;
  1028. }
  1029. arch_clkdm->clkdm_clk_disable(clkdm);
  1030. pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
  1031. pr_debug("clockdomain: %s: disabled\n", clkdm->name);
  1032. ccd_exit:
  1033. pwrdm_unlock(clkdm->pwrdm.ptr);
  1034. return 0;
  1035. }
  1036. /**
  1037. * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
  1038. * @clkdm: struct clockdomain *
  1039. * @oh: struct omap_hwmod * of the enabled downstream hwmod
  1040. *
  1041. * Increment the usecount of the clockdomain @clkdm and ensure that it
  1042. * is awake before @oh is enabled. Intended to be called by
  1043. * module_enable() code.
  1044. * If the clockdomain is in software-supervised idle mode, force the
  1045. * clockdomain to wake. If the clockdomain is in hardware-supervised idle
  1046. * mode, add clkdm-pwrdm autodependencies, to ensure that devices in the
  1047. * clockdomain can be read from/written to by on-chip processors.
  1048. * Returns -EINVAL if passed null pointers;
  1049. * returns 0 upon success or if the clockdomain is in hwsup idle mode.
  1050. */
  1051. int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
  1052. {
  1053. /* The clkdm attribute does not exist yet prior OMAP4 */
  1054. if (cpu_is_omap24xx() || cpu_is_omap34xx())
  1055. return 0;
  1056. /*
  1057. * XXX Rewrite this code to maintain a list of enabled
  1058. * downstream hwmods for debugging purposes?
  1059. */
  1060. if (!oh)
  1061. return -EINVAL;
  1062. return _clkdm_clk_hwmod_enable(clkdm);
  1063. }
  1064. /**
  1065. * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm
  1066. * @clkdm: struct clockdomain *
  1067. * @oh: struct omap_hwmod * of the disabled downstream hwmod
  1068. *
  1069. * Decrement the usecount of this clockdomain @clkdm when @oh is
  1070. * disabled. Intended to be called by module_disable() code.
  1071. * If the clockdomain usecount goes to 0, put the clockdomain to sleep
  1072. * (software-supervised mode) or remove the clkdm autodependencies
  1073. * (hardware-supervised mode).
  1074. * Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount
  1075. * underflows; or returns 0 upon success or if the clockdomain is in hwsup
  1076. * idle mode.
  1077. */
  1078. int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
  1079. {
  1080. /* The clkdm attribute does not exist yet prior OMAP4 */
  1081. if (cpu_is_omap24xx() || cpu_is_omap34xx())
  1082. return 0;
  1083. /*
  1084. * XXX Rewrite this code to maintain a list of enabled
  1085. * downstream hwmods for debugging purposes?
  1086. */
  1087. if (!clkdm || !oh || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
  1088. return -EINVAL;
  1089. pwrdm_lock(clkdm->pwrdm.ptr);
  1090. if (clkdm->usecount == 0) {
  1091. pwrdm_unlock(clkdm->pwrdm.ptr);
  1092. WARN_ON(1); /* underflow */
  1093. return -ERANGE;
  1094. }
  1095. clkdm->usecount--;
  1096. if (clkdm->usecount > 0) {
  1097. pwrdm_unlock(clkdm->pwrdm.ptr);
  1098. return 0;
  1099. }
  1100. arch_clkdm->clkdm_clk_disable(clkdm);
  1101. pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
  1102. pwrdm_unlock(clkdm->pwrdm.ptr);
  1103. pr_debug("clockdomain: %s: disabled\n", clkdm->name);
  1104. return 0;
  1105. }
  1106. /**
  1107. * _clkdm_save_context - save the context for the control of this clkdm
  1108. *
  1109. * Due to a suspend or hibernation operation, the state of the registers
  1110. * controlling this clkdm will be lost, save their context.
  1111. */
  1112. static int _clkdm_save_context(struct clockdomain *clkdm, void *ununsed)
  1113. {
  1114. if (!arch_clkdm || !arch_clkdm->clkdm_save_context)
  1115. return -EINVAL;
  1116. return arch_clkdm->clkdm_save_context(clkdm);
  1117. }
  1118. /**
  1119. * _clkdm_restore_context - restore context for control of this clkdm
  1120. *
  1121. * Restore the register values for this clockdomain.
  1122. */
  1123. static int _clkdm_restore_context(struct clockdomain *clkdm, void *ununsed)
  1124. {
  1125. if (!arch_clkdm || !arch_clkdm->clkdm_restore_context)
  1126. return -EINVAL;
  1127. return arch_clkdm->clkdm_restore_context(clkdm);
  1128. }
  1129. /**
  1130. * clkdm_save_context - Saves the context for each registered clkdm
  1131. *
  1132. * Save the context for each registered clockdomain.
  1133. */
  1134. void clkdm_save_context(void)
  1135. {
  1136. clkdm_for_each(_clkdm_save_context, NULL);
  1137. }
  1138. /**
  1139. * clkdm_restore_context - Restores the context for each registered clkdm
  1140. *
  1141. * Restore the context for each registered clockdomain.
  1142. */
  1143. void clkdm_restore_context(void)
  1144. {
  1145. clkdm_for_each(_clkdm_restore_context, NULL);
  1146. }