/* * omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST * hardware register (which are specific to OMAP44xx SoCs) to reset * source ID bit shifts (which is an OMAP SoC-independent * enumeration)
*/ staticstruct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
{ OMAP4430_GLOBAL_WARM_SW_RST_SHIFT,
OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
{ OMAP4430_GLOBAL_COLD_RST_SHIFT,
OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
{ OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
{ OMAP4430_MPU_WDT_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
{ OMAP4430_SECURE_WDT_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
{ OMAP4430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
{ OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT,
OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
{ OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT,
OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT },
{ OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT,
OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
{ OMAP4430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
{ OMAP4430_C2C_RST_SHIFT, OMAP_C2C_RST_SRC_ID_SHIFT },
{ -1, -1 },
};
/* PRM low-level functions */
/* Read a register in a CM/PRM instance in the PRM module */ static u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
{ return readl_relaxed(prm_base.va + inst + reg);
}
/* Write into a register in a CM/PRM instance in the PRM module */ staticvoid omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
{
writel_relaxed(val, prm_base.va + inst + reg);
}
/* Read-modify-write a register in a PRM module. Caller must lock */ static u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
{
u32 v;
v = omap4_prm_read_inst_reg(inst, reg);
v &= ~mask;
v |= bits;
omap4_prm_write_inst_reg(v, inst, reg);
/* XXX read mask from RAM? */
mask = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
irqen_offs);
st = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, irqst_offs);
return mask & st;
}
/** * omap44xx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events * @events: ptr to two consecutive u32s, preallocated by caller * * Read PRM_IRQSTATUS_MPU* bits, AND'ed with the currently-enabled PRM * MPU IRQs, and store the result into the two u32s pointed to by @events. * No return value.
*/ staticvoid omap44xx_prm_read_pending_irqs(unsignedlong *events)
{ int i;
for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++)
events[i] = _read_pending_irq_reg(omap4_prcm_irq_setup.mask +
i * 4, omap4_prcm_irq_setup.ack + i * 4);
}
/** * omap44xx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete * * Force any buffered writes to the PRM IP block to complete. Needed * by the PRM IRQ handler, which reads and writes directly to the IP * block, to avoid race conditions after acknowledging or clearing IRQ * bits. No return value.
*/ staticvoid omap44xx_prm_ocp_barrier(void)
{
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_REVISION_PRM_OFFSET);
}
/** * omap44xx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU* regs * @saved_mask: ptr to a u32 array to save IRQENABLE bits * * Save the PRM_IRQENABLE_MPU and PRM_IRQENABLE_MPU_2 registers to * @saved_mask. @saved_mask must be allocated by the caller. * Intended to be used in the PRM interrupt handler suspend callback. * The OCP barrier is needed to ensure the write to disable PRM * interrupts reaches the PRM before returning; otherwise, spurious * interrupts might occur. No return value.
*/ staticvoid omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
{ int i;
u16 reg;
for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++) {
reg = omap4_prcm_irq_setup.mask + i * 4;
/** * omap44xx_prm_restore_irqen - set PRM_IRQENABLE_MPU* registers from args * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously * * Restore the PRM_IRQENABLE_MPU and PRM_IRQENABLE_MPU_2 registers from * @saved_mask. Intended to be used in the PRM interrupt handler resume * callback to restore values saved by omap44xx_prm_save_and_clear_irqen(). * No OCP barrier should be needed here; any pending PRM interrupts will fire * once the writes reach the PRM. No return value.
*/ staticvoid omap44xx_prm_restore_irqen(u32 *saved_mask)
{ int i;
for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++)
omap4_prm_write_inst_reg(saved_mask[i],
OMAP4430_PRM_OCP_SOCKET_INST,
omap4_prcm_irq_setup.mask + i * 4);
}
/** * omap44xx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain * * Clear any previously-latched I/O wakeup events and ensure that the * I/O wakeup gates are aligned with the current mux settings. Works * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then * deasserting WUCLKIN and waiting for WUCLKOUT to be deasserted. * No return value. XXX Are the final two steps necessary?
*/ staticvoid omap44xx_prm_reconfigure_io_chain(void)
{ int i = 0;
s32 inst = omap4_prmst_get_prm_dev_inst();
/** * omap44xx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches * * Activates the I/O wakeup event latches and allows events logged by * those latches to signal a wakeup event to the PRCM. For I/O wakeups * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and * omap44xx_prm_reconfigure_io_chain() must be called. No return value.
*/ staticvoid omap44xx_prm_enable_io_wakeup(void)
{
s32 inst = omap4_prmst_get_prm_dev_inst();
/** * omap44xx_prm_read_reset_sources - return the last SoC reset source * * Return a u32 representing the last reset sources of the SoC. The * returned reset source bits are standardized across OMAP SoCs.
*/ static u32 omap44xx_prm_read_reset_sources(void)
{ struct prm_reset_src_map *p;
u32 r = 0;
u32 v;
s32 inst = omap4_prmst_get_prm_dev_inst();
if (inst == PRM_INSTANCE_UNKNOWN) return 0;
v = omap4_prm_read_inst_reg(inst,
OMAP4_RM_RSTST);
p = omap44xx_prm_reset_src_map; while (p->reg_shift >= 0 && p->std_shift >= 0) { if (v & (1 << p->reg_shift))
r |= 1 << p->std_shift;
p++;
}
return r;
}
/** * omap44xx_prm_was_any_context_lost_old - was module hardware context lost? * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION) * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST) * @idx: CONTEXT register offset * * Return 1 if any bits were set in the *_CONTEXT_* register * identified by (@part, @inst, @idx), which means that some context * was lost for that module; otherwise, return 0.
*/ staticbool omap44xx_prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx)
{ return (omap4_prminst_read_inst_reg(part, inst, idx)) ? 1 : 0;
}
/** * omap44xx_prm_clear_context_loss_flags_old - clear context loss flags * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION) * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST) * @idx: CONTEXT register offset * * Clear hardware context loss bits for the module identified by * (@part, @inst, @idx). No return value. XXX Writes to reserved bits; * is there a way to avoid this?
*/ staticvoid omap44xx_prm_clear_context_loss_flags_old(u8 part, s16 inst,
u16 idx)
{
omap4_prminst_write_inst_reg(0xffffffff, part, inst, idx);
}
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
OMAP4_PM_PWSTST);
v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
OMAP4_PM_PWSTST);
v &= OMAP4430_LOGICSTATEST_MASK;
v >>= OMAP4430_LOGICSTATEST_SHIFT;
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
OMAP4_PM_PWSTCTRL);
v &= OMAP4430_LOGICRETSTATE_MASK;
v >>= OMAP4430_LOGICRETSTATE_SHIFT;
return v;
}
/** * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate * @pwrdm: struct powerdomain * to read the state for * * Reads the previous logic powerstate for a powerdomain. This * function must determine the previous logic powerstate by first * checking the previous powerstate for the domain. If that was OFF, * then logic has been lost. If previous state was RETENTION, the * function reads the setting for the next retention logic state to * see the actual value. In every other case, the logic is * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET * depending whether the logic was retained or not.
*/ staticint omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
{ int state;
state = omap4_pwrdm_read_prev_pwrst(pwrdm);
if (state == PWRDM_POWER_OFF) return PWRDM_POWER_OFF;
if (state != PWRDM_POWER_RET) return PWRDM_POWER_RET;
return omap4_pwrdm_read_logic_retst(pwrdm);
}
staticint omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
{
u32 m, v;
m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
OMAP4_PM_PWSTST);
v &= m;
v >>= __ffs(m);
return v;
}
staticint omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
{
u32 m, v;
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
OMAP4_PM_PWSTCTRL);
v &= m;
v >>= __ffs(m);
return v;
}
/** * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate * @pwrdm: struct powerdomain * to read mem powerstate for * @bank: memory bank index * * Reads the previous memory powerstate for a powerdomain. This * function must determine the previous memory powerstate by first * checking the previous powerstate for the domain. If that was OFF, * then logic has been lost. If previous state was RETENTION, the * function reads the setting for the next memory retention state to * see the actual value. In every other case, the logic is * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET * depending whether logic was retained or not.
*/ staticint omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
{ int state;
state = omap4_pwrdm_read_prev_pwrst(pwrdm);
if (state == PWRDM_POWER_OFF) return PWRDM_POWER_OFF;
if (state != PWRDM_POWER_RET) return PWRDM_POWER_RET;
return omap4_pwrdm_read_mem_retst(pwrdm, bank);
}
staticint omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
{
u32 c = 0;
/* * REVISIT: pwrdm_wait_transition() may be better implemented * via a callback and a periodic timer check -- how long do we expect * powerdomain transitions to take?
*/
/* XXX Is this udelay() value meaningful? */ while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
pwrdm->prcm_offs,
OMAP4_PM_PWSTST) &
OMAP_INTRANSITION_MASK) &&
(c++ < PWRDM_TRANSITION_BAILOUT))
udelay(1);
if (c > PWRDM_TRANSITION_BAILOUT) {
pr_err("powerdomain: %s: waited too long to complete transition\n",
pwrdm->name); return -EAGAIN;
}
pr_debug("powerdomain: completed transition in %d loops\n", c);
return 0;
}
staticint omap4_check_vcvp(void)
{ if (prm_features & PRM_HAS_VOLTAGE) return 1;
return 0;
}
/** * omap4_pwrdm_save_context - Saves the powerdomain state * @pwrdm: pointer to individual powerdomain * * The function saves the powerdomain state control information. * This is needed in rtc+ddr modes where we lose powerdomain context.
*/ staticvoid omap4_pwrdm_save_context(struct powerdomain *pwrdm)
{
pwrdm->context = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
pwrdm->prcm_offs,
pwrdm->pwrstctrl_offs);
/* * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request, * reading back a 1 indicates a request in progress.
*/
pwrdm->context &= ~OMAP4430_LOWPOWERSTATECHANGE_MASK;
}
/** * omap4_pwrdm_restore_context - Restores the powerdomain state * @pwrdm: pointer to individual powerdomain * * The function restores the powerdomain state control information. * This is needed in rtc+ddr modes where we lose powerdomain context.
*/ staticvoid omap4_pwrdm_restore_context(struct powerdomain *pwrdm)
{ int st, ctrl;
st = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
pwrdm->prcm_offs,
pwrdm->pwrstctrl_offs);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.