prm44xx.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /*
  2. * OMAP4 PRM module functions
  3. *
  4. * Copyright (C) 2011-2012 Texas Instruments, Inc.
  5. * Copyright (C) 2010 Nokia Corporation
  6. * Benoît Cousson
  7. * Paul Walmsley
  8. * Rajendra Nayak <rnayak@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. #include <linux/kernel.h>
  15. #include <linux/delay.h>
  16. #include <linux/errno.h>
  17. #include <linux/err.h>
  18. #include <linux/io.h>
  19. #include "soc.h"
  20. #include "iomap.h"
  21. #include "common.h"
  22. #include "vp.h"
  23. #include "prm44xx.h"
  24. #include "prm-regbits-44xx.h"
  25. #include "prcm44xx.h"
  26. #include "prminst44xx.h"
  27. #include "powerdomain.h"
  28. /* Static data */
  29. static const struct omap_prcm_irq omap4_prcm_irqs[] = {
  30. OMAP_PRCM_IRQ("wkup", 0, 0),
  31. OMAP_PRCM_IRQ("io", 9, 1),
  32. };
  33. static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
  34. .ack = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
  35. .mask = OMAP4_PRM_IRQENABLE_MPU_OFFSET,
  36. .nr_regs = 2,
  37. .irqs = omap4_prcm_irqs,
  38. .nr_irqs = ARRAY_SIZE(omap4_prcm_irqs),
  39. .irq = 11 + OMAP44XX_IRQ_GIC_START,
  40. .read_pending_irqs = &omap44xx_prm_read_pending_irqs,
  41. .ocp_barrier = &omap44xx_prm_ocp_barrier,
  42. .save_and_clear_irqen = &omap44xx_prm_save_and_clear_irqen,
  43. .restore_irqen = &omap44xx_prm_restore_irqen,
  44. };
  45. /*
  46. * omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST
  47. * hardware register (which are specific to OMAP44xx SoCs) to reset
  48. * source ID bit shifts (which is an OMAP SoC-independent
  49. * enumeration)
  50. */
  51. static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
  52. { OMAP4430_GLOBAL_WARM_SW_RST_SHIFT,
  53. OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
  54. { OMAP4430_GLOBAL_COLD_RST_SHIFT,
  55. OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
  56. { OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
  57. OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
  58. { OMAP4430_MPU_WDT_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
  59. { OMAP4430_SECURE_WDT_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
  60. { OMAP4430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
  61. { OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT,
  62. OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
  63. { OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT,
  64. OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT },
  65. { OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT,
  66. OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
  67. { OMAP4430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
  68. { OMAP4430_C2C_RST_SHIFT, OMAP_C2C_RST_SRC_ID_SHIFT },
  69. { -1, -1 },
  70. };
  71. /* PRM low-level functions */
  72. /* Read a register in a CM/PRM instance in the PRM module */
  73. u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
  74. {
  75. return __raw_readl(OMAP44XX_PRM_REGADDR(inst, reg));
  76. }
  77. /* Write into a register in a CM/PRM instance in the PRM module */
  78. void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
  79. {
  80. __raw_writel(val, OMAP44XX_PRM_REGADDR(inst, reg));
  81. }
  82. /* Read-modify-write a register in a PRM module. Caller must lock */
  83. u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
  84. {
  85. u32 v;
  86. v = omap4_prm_read_inst_reg(inst, reg);
  87. v &= ~mask;
  88. v |= bits;
  89. omap4_prm_write_inst_reg(v, inst, reg);
  90. return v;
  91. }
  92. /* PRM VP */
  93. /*
  94. * struct omap4_vp - OMAP4 VP register access description.
  95. * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
  96. * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
  97. */
  98. struct omap4_vp {
  99. u32 irqstatus_mpu;
  100. u32 tranxdone_status;
  101. };
  102. static struct omap4_vp omap4_vp[] = {
  103. [OMAP4_VP_VDD_MPU_ID] = {
  104. .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
  105. .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
  106. },
  107. [OMAP4_VP_VDD_IVA_ID] = {
  108. .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
  109. .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
  110. },
  111. [OMAP4_VP_VDD_CORE_ID] = {
  112. .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
  113. .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
  114. },
  115. };
  116. u32 omap4_prm_vp_check_txdone(u8 vp_id)
  117. {
  118. struct omap4_vp *vp = &omap4_vp[vp_id];
  119. u32 irqstatus;
  120. irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
  121. OMAP4430_PRM_OCP_SOCKET_INST,
  122. vp->irqstatus_mpu);
  123. return irqstatus & vp->tranxdone_status;
  124. }
  125. void omap4_prm_vp_clear_txdone(u8 vp_id)
  126. {
  127. struct omap4_vp *vp = &omap4_vp[vp_id];
  128. omap4_prminst_write_inst_reg(vp->tranxdone_status,
  129. OMAP4430_PRM_PARTITION,
  130. OMAP4430_PRM_OCP_SOCKET_INST,
  131. vp->irqstatus_mpu);
  132. };
  133. u32 omap4_prm_vcvp_read(u8 offset)
  134. {
  135. return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
  136. OMAP4430_PRM_DEVICE_INST, offset);
  137. }
  138. void omap4_prm_vcvp_write(u32 val, u8 offset)
  139. {
  140. omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
  141. OMAP4430_PRM_DEVICE_INST, offset);
  142. }
  143. u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
  144. {
  145. return omap4_prminst_rmw_inst_reg_bits(mask, bits,
  146. OMAP4430_PRM_PARTITION,
  147. OMAP4430_PRM_DEVICE_INST,
  148. offset);
  149. }
  150. static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs)
  151. {
  152. u32 mask, st;
  153. /* XXX read mask from RAM? */
  154. mask = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
  155. irqen_offs);
  156. st = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, irqst_offs);
  157. return mask & st;
  158. }
  159. /**
  160. * omap44xx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
  161. * @events: ptr to two consecutive u32s, preallocated by caller
  162. *
  163. * Read PRM_IRQSTATUS_MPU* bits, AND'ed with the currently-enabled PRM
  164. * MPU IRQs, and store the result into the two u32s pointed to by @events.
  165. * No return value.
  166. */
  167. void omap44xx_prm_read_pending_irqs(unsigned long *events)
  168. {
  169. events[0] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_OFFSET,
  170. OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
  171. events[1] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_2_OFFSET,
  172. OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET);
  173. }
  174. /**
  175. * omap44xx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
  176. *
  177. * Force any buffered writes to the PRM IP block to complete. Needed
  178. * by the PRM IRQ handler, which reads and writes directly to the IP
  179. * block, to avoid race conditions after acknowledging or clearing IRQ
  180. * bits. No return value.
  181. */
  182. void omap44xx_prm_ocp_barrier(void)
  183. {
  184. omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
  185. OMAP4_REVISION_PRM_OFFSET);
  186. }
  187. /**
  188. * omap44xx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU* regs
  189. * @saved_mask: ptr to a u32 array to save IRQENABLE bits
  190. *
  191. * Save the PRM_IRQENABLE_MPU and PRM_IRQENABLE_MPU_2 registers to
  192. * @saved_mask. @saved_mask must be allocated by the caller.
  193. * Intended to be used in the PRM interrupt handler suspend callback.
  194. * The OCP barrier is needed to ensure the write to disable PRM
  195. * interrupts reaches the PRM before returning; otherwise, spurious
  196. * interrupts might occur. No return value.
  197. */
  198. void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
  199. {
  200. saved_mask[0] =
  201. omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
  202. OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
  203. saved_mask[1] =
  204. omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
  205. OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET);
  206. omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
  207. OMAP4_PRM_IRQENABLE_MPU_OFFSET);
  208. omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
  209. OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
  210. /* OCP barrier */
  211. omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
  212. OMAP4_REVISION_PRM_OFFSET);
  213. }
  214. /**
  215. * omap44xx_prm_restore_irqen - set PRM_IRQENABLE_MPU* registers from args
  216. * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously
  217. *
  218. * Restore the PRM_IRQENABLE_MPU and PRM_IRQENABLE_MPU_2 registers from
  219. * @saved_mask. Intended to be used in the PRM interrupt handler resume
  220. * callback to restore values saved by omap44xx_prm_save_and_clear_irqen().
  221. * No OCP barrier should be needed here; any pending PRM interrupts will fire
  222. * once the writes reach the PRM. No return value.
  223. */
  224. void omap44xx_prm_restore_irqen(u32 *saved_mask)
  225. {
  226. omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_OCP_SOCKET_INST,
  227. OMAP4_PRM_IRQENABLE_MPU_OFFSET);
  228. omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_OCP_SOCKET_INST,
  229. OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
  230. }
  231. /**
  232. * omap44xx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
  233. *
  234. * Clear any previously-latched I/O wakeup events and ensure that the
  235. * I/O wakeup gates are aligned with the current mux settings. Works
  236. * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
  237. * deasserting WUCLKIN and waiting for WUCLKOUT to be deasserted.
  238. * No return value. XXX Are the final two steps necessary?
  239. */
  240. void omap44xx_prm_reconfigure_io_chain(void)
  241. {
  242. int i = 0;
  243. /* Trigger WUCLKIN enable */
  244. omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
  245. OMAP4430_WUCLK_CTRL_MASK,
  246. OMAP4430_PRM_DEVICE_INST,
  247. OMAP4_PRM_IO_PMCTRL_OFFSET);
  248. omap_test_timeout(
  249. (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
  250. OMAP4_PRM_IO_PMCTRL_OFFSET) &
  251. OMAP4430_WUCLK_STATUS_MASK) >>
  252. OMAP4430_WUCLK_STATUS_SHIFT) == 1),
  253. MAX_IOPAD_LATCH_TIME, i);
  254. if (i == MAX_IOPAD_LATCH_TIME)
  255. pr_warn("PRM: I/O chain clock line assertion timed out\n");
  256. /* Trigger WUCLKIN disable */
  257. omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
  258. OMAP4430_PRM_DEVICE_INST,
  259. OMAP4_PRM_IO_PMCTRL_OFFSET);
  260. omap_test_timeout(
  261. (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
  262. OMAP4_PRM_IO_PMCTRL_OFFSET) &
  263. OMAP4430_WUCLK_STATUS_MASK) >>
  264. OMAP4430_WUCLK_STATUS_SHIFT) == 0),
  265. MAX_IOPAD_LATCH_TIME, i);
  266. if (i == MAX_IOPAD_LATCH_TIME)
  267. pr_warn("PRM: I/O chain clock line deassertion timed out\n");
  268. return;
  269. }
  270. /**
  271. * omap44xx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
  272. *
  273. * Activates the I/O wakeup event latches and allows events logged by
  274. * those latches to signal a wakeup event to the PRCM. For I/O wakeups
  275. * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
  276. * omap44xx_prm_reconfigure_io_chain() must be called. No return value.
  277. */
  278. static void __init omap44xx_prm_enable_io_wakeup(void)
  279. {
  280. omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
  281. OMAP4430_GLOBAL_WUEN_MASK,
  282. OMAP4430_PRM_DEVICE_INST,
  283. OMAP4_PRM_IO_PMCTRL_OFFSET);
  284. }
  285. /**
  286. * omap44xx_prm_read_reset_sources - return the last SoC reset source
  287. *
  288. * Return a u32 representing the last reset sources of the SoC. The
  289. * returned reset source bits are standardized across OMAP SoCs.
  290. */
  291. static u32 omap44xx_prm_read_reset_sources(void)
  292. {
  293. struct prm_reset_src_map *p;
  294. u32 r = 0;
  295. u32 v;
  296. v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
  297. OMAP4_RM_RSTST);
  298. p = omap44xx_prm_reset_src_map;
  299. while (p->reg_shift >= 0 && p->std_shift >= 0) {
  300. if (v & (1 << p->reg_shift))
  301. r |= 1 << p->std_shift;
  302. p++;
  303. }
  304. return r;
  305. }
  306. /**
  307. * omap44xx_prm_was_any_context_lost_old - was module hardware context lost?
  308. * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
  309. * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
  310. * @idx: CONTEXT register offset
  311. *
  312. * Return 1 if any bits were set in the *_CONTEXT_* register
  313. * identified by (@part, @inst, @idx), which means that some context
  314. * was lost for that module; otherwise, return 0.
  315. */
  316. static bool omap44xx_prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx)
  317. {
  318. return (omap4_prminst_read_inst_reg(part, inst, idx)) ? 1 : 0;
  319. }
  320. /**
  321. * omap44xx_prm_clear_context_lost_flags_old - clear context loss flags
  322. * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
  323. * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
  324. * @idx: CONTEXT register offset
  325. *
  326. * Clear hardware context loss bits for the module identified by
  327. * (@part, @inst, @idx). No return value. XXX Writes to reserved bits;
  328. * is there a way to avoid this?
  329. */
  330. static void omap44xx_prm_clear_context_loss_flags_old(u8 part, s16 inst,
  331. u16 idx)
  332. {
  333. omap4_prminst_write_inst_reg(0xffffffff, part, inst, idx);
  334. }
  335. /* Powerdomain low-level functions */
  336. static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
  337. {
  338. omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
  339. (pwrst << OMAP_POWERSTATE_SHIFT),
  340. pwrdm->prcm_partition,
  341. pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
  342. return 0;
  343. }
  344. static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  345. {
  346. u32 v;
  347. v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
  348. OMAP4_PM_PWSTCTRL);
  349. v &= OMAP_POWERSTATE_MASK;
  350. v >>= OMAP_POWERSTATE_SHIFT;
  351. return v;
  352. }
  353. static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
  354. {
  355. u32 v;
  356. v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
  357. OMAP4_PM_PWSTST);
  358. v &= OMAP_POWERSTATEST_MASK;
  359. v >>= OMAP_POWERSTATEST_SHIFT;
  360. return v;
  361. }
  362. static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
  363. {
  364. u32 v;
  365. v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
  366. OMAP4_PM_PWSTST);
  367. v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
  368. v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
  369. return v;
  370. }
  371. static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
  372. {
  373. omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
  374. (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
  375. pwrdm->prcm_partition,
  376. pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
  377. return 0;
  378. }
  379. static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
  380. {
  381. omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
  382. OMAP4430_LASTPOWERSTATEENTERED_MASK,
  383. pwrdm->prcm_partition,
  384. pwrdm->prcm_offs, OMAP4_PM_PWSTST);
  385. return 0;
  386. }
  387. static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
  388. {
  389. u32 v;
  390. v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
  391. omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
  392. pwrdm->prcm_partition, pwrdm->prcm_offs,
  393. OMAP4_PM_PWSTCTRL);
  394. return 0;
  395. }
  396. static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
  397. u8 pwrst)
  398. {
  399. u32 m;
  400. m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
  401. omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
  402. pwrdm->prcm_partition, pwrdm->prcm_offs,
  403. OMAP4_PM_PWSTCTRL);
  404. return 0;
  405. }
  406. static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
  407. u8 pwrst)
  408. {
  409. u32 m;
  410. m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
  411. omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
  412. pwrdm->prcm_partition, pwrdm->prcm_offs,
  413. OMAP4_PM_PWSTCTRL);
  414. return 0;
  415. }
  416. static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
  417. {
  418. u32 v;
  419. v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
  420. OMAP4_PM_PWSTST);
  421. v &= OMAP4430_LOGICSTATEST_MASK;
  422. v >>= OMAP4430_LOGICSTATEST_SHIFT;
  423. return v;
  424. }
  425. static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
  426. {
  427. u32 v;
  428. v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
  429. OMAP4_PM_PWSTCTRL);
  430. v &= OMAP4430_LOGICRETSTATE_MASK;
  431. v >>= OMAP4430_LOGICRETSTATE_SHIFT;
  432. return v;
  433. }
  434. /**
  435. * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
  436. * @pwrdm: struct powerdomain * to read the state for
  437. *
  438. * Reads the previous logic powerstate for a powerdomain. This
  439. * function must determine the previous logic powerstate by first
  440. * checking the previous powerstate for the domain. If that was OFF,
  441. * then logic has been lost. If previous state was RETENTION, the
  442. * function reads the setting for the next retention logic state to
  443. * see the actual value. In every other case, the logic is
  444. * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
  445. * depending whether the logic was retained or not.
  446. */
  447. static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
  448. {
  449. int state;
  450. state = omap4_pwrdm_read_prev_pwrst(pwrdm);
  451. if (state == PWRDM_POWER_OFF)
  452. return PWRDM_POWER_OFF;
  453. if (state != PWRDM_POWER_RET)
  454. return PWRDM_POWER_RET;
  455. return omap4_pwrdm_read_logic_retst(pwrdm);
  456. }
  457. static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  458. {
  459. u32 m, v;
  460. m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
  461. v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
  462. OMAP4_PM_PWSTST);
  463. v &= m;
  464. v >>= __ffs(m);
  465. return v;
  466. }
  467. static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
  468. {
  469. u32 m, v;
  470. m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
  471. v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
  472. OMAP4_PM_PWSTCTRL);
  473. v &= m;
  474. v >>= __ffs(m);
  475. return v;
  476. }
  477. /**
  478. * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
  479. * @pwrdm: struct powerdomain * to read mem powerstate for
  480. * @bank: memory bank index
  481. *
  482. * Reads the previous memory powerstate for a powerdomain. This
  483. * function must determine the previous memory powerstate by first
  484. * checking the previous powerstate for the domain. If that was OFF,
  485. * then logic has been lost. If previous state was RETENTION, the
  486. * function reads the setting for the next memory retention state to
  487. * see the actual value. In every other case, the logic is
  488. * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
  489. * depending whether logic was retained or not.
  490. */
  491. static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  492. {
  493. int state;
  494. state = omap4_pwrdm_read_prev_pwrst(pwrdm);
  495. if (state == PWRDM_POWER_OFF)
  496. return PWRDM_POWER_OFF;
  497. if (state != PWRDM_POWER_RET)
  498. return PWRDM_POWER_RET;
  499. return omap4_pwrdm_read_mem_retst(pwrdm, bank);
  500. }
  501. static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
  502. {
  503. u32 c = 0;
  504. /*
  505. * REVISIT: pwrdm_wait_transition() may be better implemented
  506. * via a callback and a periodic timer check -- how long do we expect
  507. * powerdomain transitions to take?
  508. */
  509. /* XXX Is this udelay() value meaningful? */
  510. while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
  511. pwrdm->prcm_offs,
  512. OMAP4_PM_PWSTST) &
  513. OMAP_INTRANSITION_MASK) &&
  514. (c++ < PWRDM_TRANSITION_BAILOUT))
  515. udelay(1);
  516. if (c > PWRDM_TRANSITION_BAILOUT) {
  517. pr_err("powerdomain: %s: waited too long to complete transition\n",
  518. pwrdm->name);
  519. return -EAGAIN;
  520. }
  521. pr_debug("powerdomain: completed transition in %d loops\n", c);
  522. return 0;
  523. }
  524. struct pwrdm_ops omap4_pwrdm_operations = {
  525. .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
  526. .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
  527. .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst,
  528. .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst,
  529. .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange,
  530. .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst,
  531. .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst,
  532. .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
  533. .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst,
  534. .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
  535. .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst,
  536. .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst,
  537. .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst,
  538. .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
  539. .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
  540. .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
  541. };
  542. /*
  543. * XXX document
  544. */
  545. static struct prm_ll_data omap44xx_prm_ll_data = {
  546. .read_reset_sources = &omap44xx_prm_read_reset_sources,
  547. .was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old,
  548. .clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old,
  549. };
  550. int __init omap44xx_prm_init(void)
  551. {
  552. if (!cpu_is_omap44xx())
  553. return 0;
  554. return prm_register(&omap44xx_prm_ll_data);
  555. }
  556. static int __init omap44xx_prm_late_init(void)
  557. {
  558. if (!cpu_is_omap44xx())
  559. return 0;
  560. omap44xx_prm_enable_io_wakeup();
  561. return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
  562. }
  563. omap_subsys_initcall(omap44xx_prm_late_init);
  564. static void __exit omap44xx_prm_exit(void)
  565. {
  566. if (!cpu_is_omap44xx())
  567. return;
  568. /* Should never happen */
  569. WARN(prm_unregister(&omap44xx_prm_ll_data),
  570. "%s: prm_ll_data function pointer mismatch\n", __func__);
  571. }
  572. __exitcall(omap44xx_prm_exit);