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