static int am33xx_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 ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs) & 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; }
/** * am33xx_prm_is_hardreset_asserted - read the HW reset line state of * submodules contained in the hwmod module * @shift: register bit shift corresponding to the reset line to check * @inst: CM instance register offset (*_INST macro) * @rstctrl_offs: RM_RSTCTRL register address offset for this module * * Returns 1 if the (sub)module hardreset line is currently asserted, * 0 if the (sub)module hardreset line is not currently asserted, or * -EINVAL upon parameter error. */ int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, u16 rstctrl_offs) { u32 v; v = am33xx_prm_read_reg(inst, rstctrl_offs); v &= 1 << shift; v >>= shift; return v; }
static void am33xx_pwrdm_save_context(struct powerdomain *pwrdm) { pwrdm->context = am33xx_prm_read_reg(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 &= ~AM33XX_LOWPOWERSTATECHANGE_MASK; }
static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) { u32 v; v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); v &= AM33XX_LOGICSTATEST_MASK; v >>= AM33XX_LOGICSTATEST_SHIFT; return v; }
static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) { u32 v; v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); v &= AM33XX_LASTPOWERSTATEENTERED_MASK; v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT; return v; }
static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm) { u32 v; v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); v &= OMAP_POWERSTATEST_MASK; v >>= OMAP_POWERSTATEST_SHIFT; return v; }
/* Read-modify-write a register in PRM. Caller must lock */ u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx) { u32 v; v = am33xx_prm_read_reg(inst, idx); v &= ~mask; v |= bits; am33xx_prm_write_reg(v, inst, idx); return v; }
/** * am33xx_prm_global_warm_sw_reset - reboot the device via warm reset * * Immediately reboots the device through warm reset. */ static void am33xx_prm_global_warm_sw_reset(void) { am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK, AM33XX_RST_GLOBAL_WARM_SW_MASK, AM33XX_PRM_DEVICE_MOD, AM33XX_PRM_RSTCTRL_OFFSET); /* OCP barrier */ (void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD, AM33XX_PRM_RSTCTRL_OFFSET); }
/** * am3xx_restart - trigger a software restart of the SoC * @mode: the "reboot mode", see arch/arm/kernel/{setup,process}.c * @cmd: passed from the userspace program rebooting the system (if provided) * * Resets the SoC. For @cmd, see the 'reboot' syscall in * kernel/sys.c. No return value. */ void am33xx_restart(enum reboot_mode mode, const char *cmd) { /* TODO: Handle mode and cmd if necessary */ am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK, AM33XX_RST_GLOBAL_WARM_SW_MASK, AM33XX_PRM_DEVICE_MOD, AM33XX_PRM_RSTCTRL_OFFSET); /* OCP barrier */ (void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD, AM33XX_PRM_RSTCTRL_OFFSET); }
static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) { u32 m, v; m = pwrdm->mem_retst_mask[bank]; if (!m) return -EINVAL; v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); v &= m; v >>= __ffs(m); return v; }
static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm) { u32 v, m; m = pwrdm->logicretstate_mask; if (!m) return -EINVAL; v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); v &= m; v >>= __ffs(m); return v; }
static void am33xx_pwrdm_restore_context(struct powerdomain *pwrdm) { int st, ctrl; st = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); am33xx_prm_write_reg(pwrdm->context, pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); /* Make sure we only wait for a transition if there is one */ st &= OMAP_POWERSTATEST_MASK; ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context; if (st != ctrl) am33xx_pwrdm_wait_transition(pwrdm); }