linux/arch/arm/mach-omap2/prm44xx.c
<<
>>
Prefs
   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
  34static const struct omap_prcm_irq omap4_prcm_irqs[] = {
  35        OMAP_PRCM_IRQ("wkup",   0,      0),
  36        OMAP_PRCM_IRQ("io",     9,      1),
  37};
  38
  39static 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 */
  58static 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 */
  82u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
  83{
  84        return __raw_readl(prm_base + inst + reg);
  85}
  86
  87/* Write into a register in a CM/PRM instance in the PRM module */
  88void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
  89{
  90        __raw_writel(val, prm_base + inst + reg);
  91}
  92
  93/* Read-modify-write a register in a PRM module. Caller must lock */
  94u32 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 */
 113struct omap4_vp {
 114        u32 irqstatus_mpu;
 115        u32 tranxdone_status;
 116};
 117
 118static 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
 133u32 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
 144void 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
 154u32 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
 160void 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
 166u32 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
 174static 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 */
 194void 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 */
 211void 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 */
 228void 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 */
 257void 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 */
 274void 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 */
 316static 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 */
 330static 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 */
 359static 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 */
 374static 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
 382static 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
 391static 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
 403static 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
 415static 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
 427static 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
 436static 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
 445static 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
 457static 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
 471static 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
 485static 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
 497static 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 */
 522static 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
 537static 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
 551static 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 */
 579static 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
 594static 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
 623struct 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 */
 645static 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
 651int __init omap44xx_prm_init(void)
 652{
 653        if (!cpu_is_omap44xx() && !soc_is_omap54xx())
 654                return 0;
 655
 656        return prm_register(&omap44xx_prm_ll_data);
 657}
 658
 659static 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}
 668omap_subsys_initcall(omap44xx_prm_late_init);
 669
 670static 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