static void am33xx_pre_suspend(unsigned int state) { if (state == PM_SUSPEND_STANDBY) { clkdm_wakeup(l3s_clkdm); clkdm_wakeup(l4fw_clkdm); clkdm_wakeup(clk_24mhz_clkdm); } }
static int am33xx_pm_suspend(void) { int state, ret = 0; struct omap_hwmod *cpgmac_oh, *gpmc_oh, *usb_oh; cpgmac_oh = omap_hwmod_lookup("cpgmac0"); usb_oh = omap_hwmod_lookup("usb_otg_hs"); gpmc_oh = omap_hwmod_lookup("gpmc"); omap_hwmod_enable(cpgmac_oh); omap_hwmod_enable(usb_oh); omap_hwmod_enable(gpmc_oh); omap_hwmod_idle(cpgmac_oh); omap_hwmod_idle(usb_oh); omap_hwmod_idle(gpmc_oh); if (gfx_l3_clkdm && gfx_l4ls_clkdm) { clkdm_sleep(gfx_l3_clkdm); clkdm_sleep(gfx_l4ls_clkdm); } /* Try to put GFX to sleep */ if (gfx_pwrdm) pwrdm_set_next_pwrst(gfx_pwrdm, PWRDM_POWER_OFF); else pr_err("Could not program GFX to low power state\n"); writel(0x0, AM33XX_CM_MPU_MPU_CLKCTRL); ret = cpu_suspend(0, am33xx_do_sram_idle); writel(0x2, AM33XX_CM_MPU_MPU_CLKCTRL); if (gfx_pwrdm) { state = pwrdm_read_pwrst(gfx_pwrdm); if (state != PWRDM_POWER_OFF) pr_err("GFX domain did not transition to low power state\n"); else pr_info("GFX domain entered low power state\n"); } /* XXX: Why do we need to wakeup the clockdomains? */ if(gfx_l3_clkdm && gfx_l4ls_clkdm) { clkdm_wakeup(gfx_l3_clkdm); clkdm_wakeup(gfx_l4ls_clkdm); } core_suspend_stat = ret; return ret; }
static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) { /* For every clock enable, force wakeup the clkdm */ clkdm_wakeup(clkdm); return 0; }
void tf_clock_timer_start(void) { unsigned long flags; dprintk(KERN_INFO "%s\n", __func__); spin_lock_irqsave(&clk_timer_lock, flags); tf_crypto_clock_enabled++; wake_lock(&g_tf_wake_lock); clkdm_wakeup(smc_l4_sec_clkdm); /* Stop the timer if already running */ if (timer_pending(&tf_crypto_clock_timer)) del_timer(&tf_crypto_clock_timer); /* Configure the timer */ tf_crypto_clock_timer.expires = jiffies + msecs_to_jiffies(INACTIVITY_TIMER_TIMEOUT); tf_crypto_clock_timer.function = tf_clock_timer_cb; add_timer(&tf_crypto_clock_timer); spin_unlock_irqrestore(&clk_timer_lock, flags); }
/** * omap_sec_dispatcher: Routine to dispatch low power secure * service routines * @idx: The HAL API index * @flag: The flag indicating criticality of operation * @nargs: Number of valid arguments out of four. * @arg1, arg2, arg3 args4: Parameters passed to secure API * * Return the non-zero error value on failure. */ u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2, u32 arg3, u32 arg4) { u32 ret; u32 param[5]; param[0] = nargs; param[1] = arg1; param[2] = arg2; param[3] = arg3; param[4] = arg4; if (!l4_secure_clkdm) l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm"); clkdm_wakeup(l4_secure_clkdm); /* * Secure API needs physical address * pointer for the parameters */ flush_cache_all(); outer_clean_range(__pa(param), __pa(param + 5)); ret = omap_smc2(idx, flag, __pa(param)); clkdm_allow_idle(l4_secure_clkdm); return ret; }
int omap_rproc_activate(struct omap_device *od) { int i, ret = 0; struct rproc *rproc = platform_get_drvdata(&od->pdev); struct device *dev = rproc->dev; struct omap_rproc_pdata *pdata = dev->platform_data; struct omap_rproc_timers_info *timers = pdata->timers; struct omap_rproc_priv *rpp = rproc->priv; #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND struct iommu *iommu; if (!rpp->iommu) { iommu = iommu_get(pdata->iommu_name); if (IS_ERR(iommu)) { dev_err(dev, "iommu_get error: %ld\n", PTR_ERR(iommu)); return PTR_ERR(iommu); } rpp->iommu = iommu; } if (!rpp->mbox) rpp->mbox = omap_mbox_get(pdata->sus_mbox_name, NULL); #endif /** * explicitly configure a boot address from which remoteproc * starts executing code when taken out of reset. */ _load_boot_addr(rproc, rpp->bootaddr); /** * Domain is in HW SUP thus in hw_auto but * since remoteproc will be enabled clkdm * needs to be in sw_sup (Do not let it idle). */ if (pdata->clkdm) clkdm_wakeup(pdata->clkdm); for (i = 0; i < pdata->timers_cnt; i++) omap_dm_timer_start(timers[i].odt); for (i = 0; i < od->hwmods_cnt; i++) { ret = omap_hwmod_enable(od->hwmods[i]); if (ret) { for (i = 0; i < pdata->timers_cnt; i++) omap_dm_timer_stop(timers[i].odt); break; } } /** * Domain is in force_wkup but since remoteproc * was enabled it is safe now to switch clkdm * to hw_auto (let it idle). */ if (pdata->clkdm) clkdm_allow_idle(pdata->clkdm); return ret; }
static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) { static struct clockdomain *cpu1_clkdm; static bool booted; void __iomem *base = omap_get_wakeupgen_base(); /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * Update the AuxCoreBoot0 with boot state for secondary core. * omap_secondary_startup() routine will hold the secondary core till * the AuxCoreBoot1 register is updated with cpu state * A barrier is added to ensure that write buffer is drained */ if (omap_secure_apis_support()) omap_modify_auxcoreboot0(0x200, 0xfffffdff); else __raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0); flush_cache_all(); smp_wmb(); if (!cpu1_clkdm) cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); /* * The SGI(Software Generated Interrupts) are not wakeup capable * from low power states. This is known limitation on OMAP4 and * needs to be worked around by using software forced clockdomain * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to * software force wakeup. The clockdomain is then put back to * hardware supervised mode. * More details can be found in OMAP4430 TRM - Version J * Section : * 4.3.4.2 Power States of CPU0 and CPU1 */ if (booted) { clkdm_wakeup(cpu1_clkdm); clkdm_allow_idle(cpu1_clkdm); } else { dsb_sev(); booted = true; } gic_raise_softirq(cpumask_of(cpu), 0); /* * Now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ spin_unlock(&boot_lock); return 0; }
/** * omap4_prcm_freq_update - set freq_update bit * * Programs the CM shadow registers to update EMIF * parametrs. Few usecase only few registers needs to * be updated using prcm freq update sequence. * EMIF read-idle control and zq-config needs to be * updated for temprature alerts and voltage change * Returns -1 on error and 0 on success. */ int omap4_prcm_freq_update(void) { u32 shadow_freq_cfg1; int i = 0; unsigned long flags; if (!l3_emif_clkdm) { pr_err("%s: clockdomain lookup failed\n", __func__); return -EINVAL; } spin_lock_irqsave(&l3_emif_lock, flags); /* Configures MEMIF domain in SW_WKUP */ clkdm_wakeup(l3_emif_clkdm); /* Disable DDR self refresh (Errata ID: i728) */ omap_emif_frequency_pre_notify(); /* * FREQ_UPDATE sequence: * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden * after CORE DPLL lock) * - FREQ_UPDATE=1 (to start HW sequence) */ shadow_freq_cfg1 = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1); shadow_freq_cfg1 |= (1 << OMAP4430_DLL_RESET_SHIFT) | (1 << OMAP4430_FREQ_UPDATE_SHIFT); shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK; __raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1); /* wait for the configuration to be applied */ omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1) & OMAP4430_FREQ_UPDATE_MASK) == 0), MAX_FREQ_UPDATE_TIMEOUT, i); /* Re-enable DDR self refresh */ omap_emif_frequency_post_notify(); /* Configures MEMIF domain back to HW_WKUP */ clkdm_allow_idle(l3_emif_clkdm); spin_unlock_irqrestore(&l3_emif_lock, flags); if (i == MAX_FREQ_UPDATE_TIMEOUT) { pr_err("%s: Frequency update failed (call from %pF)\n", __func__, (void *)_RET_IP_); pr_err("CLKCTRL: EMIF_1=0x%x EMIF_2=0x%x DMM=0x%x\n", __raw_readl(OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL), __raw_readl(OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL), __raw_readl(OMAP4430_CM_MEMIF_DMM_CLKCTRL)); emif_dump(0); emif_dump(1); return -1; } return 0; }
/* * This sets pwrdm state (other than mpu & core. Currently only ON & * RET are supported. */ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) { u32 cur_state; int sleep_switch = 0; int ret = 0; if (pwrdm == NULL || IS_ERR(pwrdm)) return -EINVAL; while (!(pwrdm->pwrsts & (1 << state))) { if (state == PWRDM_POWER_OFF) return ret; state--; } cur_state = pwrdm_read_next_pwrst(pwrdm); if (cur_state == state) return ret; if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) { if ((pwrdm_read_pwrst(pwrdm) > state) && (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { sleep_switch = LOWPOWERSTATE_SWITCH; } else { clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); pwrdm_wait_transition(pwrdm); sleep_switch = FORCEWAKEUP_SWITCH; } } ret = pwrdm_set_next_pwrst(pwrdm, state); if (ret) { printk(KERN_ERR "Unable to set state of powerdomain: %s\n", pwrdm->name); goto err; } switch (sleep_switch) { case FORCEWAKEUP_SWITCH: if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO) clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); else clkdm_sleep(pwrdm->pwrdm_clkdms[0]); break; case LOWPOWERSTATE_SWITCH: pwrdm_set_lowpwrstchange(pwrdm); break; default: return ret; } pwrdm_wait_transition(pwrdm); pwrdm_state_switch(pwrdm); err: return ret; }
/* * This sets pwrdm state (other than mpu & core. Currently only ON & * RET are supported. */ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) { u32 cur_state; int sleep_switch = -1; int ret = 0; int hwsup = 0; if (pwrdm == NULL || IS_ERR(pwrdm)) return -EINVAL; while (!(pwrdm->pwrsts & (1 << state))) { if (state == PWRDM_POWER_OFF) return ret; state--; } cur_state = pwrdm_read_next_pwrst(pwrdm); if (cur_state == state) return ret; if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) { if ((pwrdm_read_pwrst(pwrdm) > state) && (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { sleep_switch = LOWPOWERSTATE_SWITCH; } else { hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); sleep_switch = FORCEWAKEUP_SWITCH; } } ret = pwrdm_set_next_pwrst(pwrdm, state); if (ret) { pr_err("%s: unable to set state of powerdomain: %s\n", __func__, pwrdm->name); goto err; } switch (sleep_switch) { case FORCEWAKEUP_SWITCH: if (hwsup) clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); else clkdm_sleep(pwrdm->pwrdm_clkdms[0]); break; case LOWPOWERSTATE_SWITCH: pwrdm_set_lowpwrstchange(pwrdm); break; default: return ret; } pwrdm_state_switch(pwrdm); err: return ret; }
static int omap_rproc_iommu_init(struct rproc *rproc, int (*callback)(struct rproc *rproc, u64 fa, u32 flags)) { struct device *dev = rproc->dev; struct omap_rproc_pdata *pdata = dev->platform_data; int ret, i; struct iommu *iommu; struct omap_rproc_priv *rpp; rpp = kzalloc(sizeof(*rpp), GFP_KERNEL); if (!rpp) return -ENOMEM; if (pdata->clkdm) clkdm_wakeup(pdata->clkdm); iommu_set_isr(pdata->iommu_name, omap_rproc_iommu_isr, rproc); iommu_set_secure(pdata->iommu_name, rproc->secure_mode, rproc->secure_ttb); iommu = iommu_get(pdata->iommu_name); if (IS_ERR(iommu)) { ret = PTR_ERR(iommu); dev_err(dev, "iommu_get error: %d\n", ret); goto err_mmu; } rpp->iommu = iommu; rpp->iommu_cb = callback; rproc->priv = rpp; if (!rproc->secure_mode) { for (i = 0; rproc->memory_maps[i].size; i++) { const struct rproc_mem_entry *me = &rproc->memory_maps[i]; ret = omap_rproc_map(dev, iommu, me->da, me->pa, me->size); if (ret) goto err_map; } } if (pdata->clkdm) clkdm_allow_idle(pdata->clkdm); return 0; err_map: iommu_put(iommu); err_mmu: iommu_set_secure(pdata->iommu_name, false, NULL); if (pdata->clkdm) clkdm_allow_idle(pdata->clkdm); kfree(rpp); return ret; }
void tf_l4sec_clkdm_wakeup(bool wakelock) { spin_lock(&tf_get_device()->sm.lock); #ifdef CONFIG_HAS_WAKELOCK if (wakelock) { atomic_inc(&tf_wake_lock_count); wake_lock(&g_tf_wake_lock); } #endif atomic_inc(&smc_l4_sec_clkdm_use_count); clkdm_wakeup(smc_l4_sec_clkdm); spin_unlock(&tf_get_device()->sm.lock); }
/* * This sets pwrdm state (other than mpu & core. Currently only ON & * RET are supported. */ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst) { u8 curr_pwrst, next_pwrst; int sleep_switch = -1, ret = 0, hwsup = 0; if (!pwrdm || IS_ERR(pwrdm)) return -EINVAL; while (!(pwrdm->pwrsts & (1 << pwrst))) { if (pwrst == PWRDM_POWER_OFF) return ret; pwrst--; } next_pwrst = pwrdm_read_next_pwrst(pwrdm); if (next_pwrst == pwrst) return ret; curr_pwrst = pwrdm_read_pwrst(pwrdm); if (curr_pwrst < PWRDM_POWER_ON) { if ((curr_pwrst > pwrst) && (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { sleep_switch = LOWPOWERSTATE_SWITCH; } else { hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); sleep_switch = FORCEWAKEUP_SWITCH; } } ret = pwrdm_set_next_pwrst(pwrdm, pwrst); if (ret) pr_err("%s: unable to set power state of powerdomain: %s\n", __func__, pwrdm->name); switch (sleep_switch) { case FORCEWAKEUP_SWITCH: if (hwsup) clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); else clkdm_sleep(pwrdm->pwrdm_clkdms[0]); break; case LOWPOWERSTATE_SWITCH: pwrdm_set_lowpwrstchange(pwrdm); pwrdm_wait_transition(pwrdm); pwrdm_state_switch(pwrdm); break; } return ret; }
static int usbhs_wakeup_handler(struct omap_hwmod_mux_info *unused) { int queued; queued = queue_delayed_work(pm_wq, &usbhs_wakeup, msecs_to_jiffies(20)); if (queued) { clkdm_wakeup(l3init_clkdm); pm_runtime_get(&pdev_usbhs->dev); } return 0; }
/** * omap_sec_dispatcher: Routine to dispatch low power secure * service routines * @idx: The HAL API index * @flag: The flag indicating criticality of operation * @nargs: Number of valid arguments out of four. * @arg1, arg2, arg3 args4: Parameters passed to secure API * * Return the non-zero error value on failure. */ u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2, u32 arg3, u32 arg4) { u32 ret = 0; u32 param[5]; unsigned long flags; /* If we have an alternate dispatcher api, use it, else use default */ spin_lock_irqsave(&_secure_dispatcher_lock, flags); if (_alternate_secure_dispatcher) { ret = _alternate_secure_dispatcher(idx, flag, nargs, arg1, arg2, arg3, arg4); spin_unlock_irqrestore(&_secure_dispatcher_lock, flags); return ret; } spin_unlock_irqrestore(&_secure_dispatcher_lock, flags); param[0] = nargs; param[1] = arg1; param[2] = arg2; param[3] = arg3; param[4] = arg4; if (!l4_secure_clkdm) { if (cpu_is_omap54xx()) l4_secure_clkdm = clkdm_lookup("l4sec_clkdm"); else l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm"); } if (!l4_secure_clkdm) { pr_err("%s: failed to get l4_secure_clkdm\n", __func__); return -EINVAL; } clkdm_wakeup(l4_secure_clkdm); /* * Secure API needs physical address * pointer for the parameters */ flush_cache_all(); outer_clean_range(__pa(param), __pa(param + 5)); ret = omap_smc2(idx, flag, __pa(param)); clkdm_allow_idle(l4_secure_clkdm); return ret; }
/* * Function responsible for formatting parameters to pass from NS world to * S world */ u32 omap4_secure_dispatcher(u32 app_id, u32 flags, u32 nargs, u32 arg1, u32 arg2, u32 arg3, u32 arg4) { u32 ret; unsigned long iflags; u32 pub2sec_args[5] = {0, 0, 0, 0, 0}; /*dpr_info("%s: app_id=0x%08x, flags=0x%08x, nargs=%u\n", __func__, app_id, flags, nargs);*/ /*if (nargs != 0) dpr_info("%s: args=%08x, %08x, %08x, %08x\n", __func__, arg1, arg2, arg3, arg4);*/ pub2sec_args[0] = nargs; pub2sec_args[1] = arg1; pub2sec_args[2] = arg2; pub2sec_args[3] = arg3; pub2sec_args[4] = arg4; /* Make sure parameters are visible to the secure world */ dmac_flush_range((void *)pub2sec_args, (void *)(((u32)(pub2sec_args)) + 5*sizeof(u32))); outer_clean_range(__pa(pub2sec_args), __pa(pub2sec_args) + 5*sizeof(u32)); wmb(); /* * Put L4 Secure clock domain to SW_WKUP so that modules are accessible */ clkdm_wakeup(smc_l4_sec_clkdm); local_irq_save(iflags); /* proc_id is always 0 */ ret = schedule_secure_world(app_id, 0, flags, __pa(pub2sec_args)); local_irq_restore(iflags); /* Restore the HW_SUP on L4 Sec clock domain so hardware can idle */ if ((app_id != API_HAL_HWATURNOFF_INDEX) && (!timer_pending(&tf_crypto_clock_timer))) { (void) tf_crypto_turn_off_clocks(); clkdm_allow_idle(smc_l4_sec_clkdm); } /*dpr_info("%s()\n", __func__);*/ return ret; }
static int omap_rproc_iommu_exit(struct rproc *rproc) { struct omap_rproc_priv *rpp = rproc->priv; struct omap_rproc_pdata *pdata = rproc->dev->platform_data; if (pdata->clkdm) clkdm_wakeup(pdata->clkdm); if (rpp->iommu) iommu_put(rpp->iommu); kfree(rpp); if (pdata->clkdm) clkdm_allow_idle(pdata->clkdm); return 0; }
/* * omap4_sar_save - * Save the context to SAR_RAM1 and SAR_RAM2 as per * omap4xxx_sar_ram1_layout and omap4xxx_sar_ram2_layout for the device OFF * mode */ int omap4_sar_save(void) { /* * Not supported on ES1.0 silicon */ if (omap_rev() == OMAP4430_REV_ES1_0) { WARN_ONCE(1, "omap4: SAR backup not supported on ES1.0 ..\n"); return -ENODEV; } if (omap4_sar_not_accessible()) { pr_debug("%s: USB SAR CNTX registers are not accessible!\n", __func__); return -EBUSY; } /* * SAR bits and clocks needs to be enabled */ clkdm_wakeup(l3init_clkdm); pwrdm_enable_hdwr_sar(l3init_pwrdm); clk_enable(usb_host_ck); clk_enable(usb_tll_ck); /* Save SAR BANK1 */ if (cpu_is_omap446x()) sar_save(ARRAY_SIZE(omap446x_sar_ram1_layout), SAR_BANK1_OFFSET, omap446x_sar_ram1_layout); else sar_save(ARRAY_SIZE(omap443x_sar_ram1_layout), SAR_BANK1_OFFSET, omap443x_sar_ram1_layout); clk_disable(usb_host_ck); clk_disable(usb_tll_ck); pwrdm_disable_hdwr_sar(l3init_pwrdm); clkdm_allow_idle(l3init_clkdm); /* Save SAR BANK2 */ if (cpu_is_omap446x()) sar_save(ARRAY_SIZE(omap446x_sar_ram2_layout), SAR_BANK2_OFFSET, omap446x_sar_ram2_layout); else sar_save(ARRAY_SIZE(omap443x_sar_ram2_layout), SAR_BANK2_OFFSET, omap443x_sar_ram2_layout); return 0; }
static void am33xx_post_suspend(unsigned int state) { int status = 0; status = pwrdm_read_pwrst(gfx_pwrdm); if (status != PWRDM_POWER_OFF) pr_err("GFX domain did not transition\n"); /* * BUG: GFX_L4LS clock domain needs to be woken up to * ensure thet L4LS clock domain does not get stuck in * transition. If that happens L3 module does not get * disabled, thereby leading to PER power domain * transition failing */ clkdm_wakeup(gfx_l4ls_clkdm); clkdm_sleep(gfx_l4ls_clkdm); }
void omap4_usb_sar_restore(void) { u32 i; pr_err("USB SAR- SW Restore\n"); clkdm_wakeup(l3init_clkdm); pwrdm_enable_hdwr_sar(l3init_pwrdm); clk_enable(usb_host_ck); clk_enable(usb_tll_ck); for (i = 0; i < (USB_SAR_AREA_END-USB_SAR_AREA_START)/4; i++) __raw_writel(usb_sar_data[i].val, usb_sar_data[i].reg_addr); clk_disable(usb_host_ck); clk_disable(usb_tll_ck); pwrdm_disable_hdwr_sar(l3init_pwrdm); clkdm_allow_idle(l3init_clkdm); }
static int omap2_clkdm_clk_enable(struct clockdomain *clkdm) { bool hwsup = false; if (!clkdm->clktrctrl_mask) return 0; hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, clkdm->clktrctrl_mask); if (hwsup) { /* Disable HW transitions when we are changing deps */ _disable_hwsup(clkdm); _clkdm_add_autodeps(clkdm); _enable_hwsup(clkdm); } else { clkdm_wakeup(clkdm); } return 0; }
int omap_rproc_deactivate(struct omap_device *od) { int i, ret = 0; struct rproc *rproc = platform_get_drvdata(&od->pdev); struct device *dev = rproc->dev; struct omap_rproc_pdata *pdata = dev->platform_data; struct omap_rproc_timers_info *timers = pdata->timers; #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND struct omap_rproc_priv *rpp = rproc->priv; #endif if (pdata->clkdm) clkdm_wakeup(pdata->clkdm); for (i = 0; i < od->hwmods_cnt; i++) { ret = omap_hwmod_shutdown(od->hwmods[i]); if (ret) goto err; } for (i = 0; i < pdata->timers_cnt; i++) omap_dm_timer_stop(timers[i].odt); #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND if (rpp->iommu) { iommu_put(rpp->iommu); rpp->iommu = NULL; } if (rpp->mbox) { omap_mbox_put(rpp->mbox, NULL); rpp->mbox = NULL; } #endif err: if (pdata->clkdm) clkdm_allow_idle(pdata->clkdm); return ret; }
/* * omap4_sec_dispatcher: Routine to dispatch low power secure * service routines * * @idx: The HAL API index * @flag: The flag indicating criticality of operation * @nargs: Number of valid arguments out of four. * @arg1, arg2, arg3 args4: Parameters passed to secure API * * Return the error value on success/failure */ u32 omap4_secure_dispatcher(u32 idx, u32 flag, u32 nargs, u32 arg1, u32 arg2, u32 arg3, u32 arg4) { u32 ret; u32 param[5]; param[0] = nargs; param[1] = arg1; param[2] = arg2; param[3] = arg3; param[4] = arg4; /* Look-up Only once */ if (!l4_secure_clkdm) l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm"); /* * Put l4 secure to software wakeup so that secure * modules are accessible */ clkdm_wakeup(l4_secure_clkdm); /* * Secure API needs physical address * pointer for the parameters */ flush_cache_all(); outer_clean_range(__pa(param), __pa(param + 5)); ret = omap_smc2(idx, flag, __pa(param)); /* * Restore l4 secure to hardware superwised to allow * secure modules idle */ clkdm_allow_idle(l4_secure_clkdm); return ret; }
static void save_sar_bank3(void) { struct clockdomain *l4_secure_clkdm; /* * Not supported on ES1.0 silicon */ if (omap_rev() == OMAP4430_REV_ES1_0) { WARN_ONCE(1, "omap4: SAR backup not supported on ES1.0 ..\n"); return; } l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm"); clkdm_wakeup(l4_secure_clkdm); if (cpu_is_omap446x()) sar_save(ARRAY_SIZE(omap446x_sar_ram3_layout), SAR_BANK3_OFFSET, omap446x_sar_ram3_layout); else sar_save(ARRAY_SIZE(omap443x_sar_ram3_layout), SAR_BANK3_OFFSET, omap443x_sar_ram3_layout); clkdm_allow_idle(l4_secure_clkdm); }
/** * omap4_core_dpll_m2_set_rate - set CORE DPLL M2 divider * @clk: struct clk * of DPLL to set * @rate: rounded target rate * * Programs the CM shadow registers to update CORE DPLL M2 * divider. M2 divider is used to clock external DDR and its * reconfiguration on frequency change is managed through a * hardware sequencer. This is managed by the PRCM with EMIF * uding shadow registers. * Returns -EINVAL/-1 on error and 0 on success. */ int omap4_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) { int i = 0; u32 validrate = 0, shadow_freq_cfg1 = 0, new_div = 0; unsigned long flags; if (!clk || !rate) return -EINVAL; validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); if (validrate != rate) return -EINVAL; /* Just to avoid look-up on every call to speed up */ if (!l3_emif_clkdm) { l3_emif_clkdm = clkdm_lookup("l3_emif_clkdm"); if (!l3_emif_clkdm) { pr_err("%s: clockdomain lookup failed\n", __func__); return -EINVAL; } } spin_lock_irqsave(&l3_emif_lock, flags); /* * Errata ID: i728 * * DESCRIPTION: * * If during a small window the following three events occur: * * 1) The EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM SR_TIMING counter expires * 2) Frequency change update is requested CM_SHADOW_FREQ_CONFIG1 * FREQ_UPDATE set to 1 * 3) OCP access is requested * * There will be instable clock on the DDR interface. * * WORKAROUND: * * Prevent event 1) while event 2) is happening. * * Disable the self-refresh when requesting a frequency change. * Before requesting a frequency change, program * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0 * (omap_emif_frequency_pre_notify) * * When the frequency change is completed, reprogram * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2. * (omap_emif_frequency_post_notify) */ omap_emif_frequency_pre_notify(); /* Configures MEMIF domain in SW_WKUP */ clkdm_wakeup(l3_emif_clkdm); /* * Program EMIF timing parameters in EMIF shadow registers * for targetted DRR clock. * DDR Clock = core_dpll_m2 / 2 */ omap_emif_setup_registers(validrate >> 1, LPDDR2_VOLTAGE_STABLE); /* * FREQ_UPDATE sequence: * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden * after CORE DPLL lock) * - DLL_RESET=1 (DLL must be reset upon frequency change) * - DPLL_CORE_M2_DIV with same value as the one already * in direct register * - DPLL_CORE_DPLL_EN=0x7 (to make CORE DPLL lock) * - FREQ_UPDATE=1 (to start HW sequence) */ shadow_freq_cfg1 = (1 << OMAP4430_DLL_RESET_SHIFT) | (new_div << OMAP4430_DPLL_CORE_M2_DIV_SHIFT) | (DPLL_LOCKED << OMAP4430_DPLL_CORE_DPLL_EN_SHIFT) | (1 << OMAP4430_FREQ_UPDATE_SHIFT); shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK; __raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1); /* wait for the configuration to be applied */ omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1) & OMAP4430_FREQ_UPDATE_MASK) == 0), MAX_FREQ_UPDATE_TIMEOUT, i); /* Configures MEMIF domain back to HW_WKUP */ clkdm_allow_idle(l3_emif_clkdm); /* Re-enable DDR self refresh */ omap_emif_frequency_post_notify(); spin_unlock_irqrestore(&l3_emif_lock, flags); if (i == MAX_FREQ_UPDATE_TIMEOUT) { pr_err("%s: Frequency update for CORE DPLL M2 change failed\n", __func__); return -1; } /* Update the clock change */ clk->rate = validrate; return 0; }
/** * omap4_prcm_freq_update - set freq_update bit * * Programs the CM shadow registers to update EMIF * parametrs. Few usecase only few registers needs to * be updated using prcm freq update sequence. * EMIF read-idle control and zq-config needs to be * updated for temprature alerts and voltage change * Returns -1 on error and 0 on success. */ int omap4_prcm_freq_update(void) { u32 shadow_freq_cfg1; int i = 0; unsigned long flags; if (!l3_emif_clkdm) { pr_err("%s: clockdomain lookup failed\n", __func__); return -EINVAL; } spin_lock_irqsave(&l3_emif_lock, flags); /* * Errata ID: i728 * * DESCRIPTION: * * If during a small window the following three events occur: * * 1) The EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM SR_TIMING counter expires * 2) Frequency change update is requested CM_SHADOW_FREQ_CONFIG1 * FREQ_UPDATE set to 1 * 3) OCP access is requested * * There will be instable clock on the DDR interface. * * WORKAROUND: * * Prevent event 1) while event 2) is happening. * * Disable the self-refresh when requesting a frequency change. * Before requesting a frequency change, program * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0 * (omap_emif_frequency_pre_notify) * * When the frequency change is completed, reprogram * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2. * (omap_emif_frequency_post_notify) */ omap_emif_frequency_pre_notify(); /* Configures MEMIF domain in SW_WKUP */ clkdm_wakeup(l3_emif_clkdm); /* * FREQ_UPDATE sequence: * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden * after CORE DPLL lock) * - FREQ_UPDATE=1 (to start HW sequence) */ shadow_freq_cfg1 = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1); shadow_freq_cfg1 |= (1 << OMAP4430_DLL_RESET_SHIFT) | (1 << OMAP4430_FREQ_UPDATE_SHIFT); shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK; __raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1); /* wait for the configuration to be applied */ omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1) & OMAP4430_FREQ_UPDATE_MASK) == 0), MAX_FREQ_UPDATE_TIMEOUT, i); /* Configures MEMIF domain back to HW_WKUP */ clkdm_allow_idle(l3_emif_clkdm); /* Re-enable DDR self refresh */ omap_emif_frequency_post_notify(); spin_unlock_irqrestore(&l3_emif_lock, flags); if (i == MAX_FREQ_UPDATE_TIMEOUT) { pr_err("%s: Frequency update failed (call from %pF)\n", __func__, (void *)_RET_IP_); pr_err("CLKCTRL: EMIF_1=0x%x EMIF_2=0x%x DMM=0x%x\n", __raw_readl(OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL), __raw_readl(OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL), __raw_readl(OMAP4430_CM_MEMIF_DMM_CLKCTRL)); emif_dump(0); emif_dump(1); return -1; } return 0; }
static int am33xx_pm_suspend(void) { int state, ret = 0; struct omap_hwmod *gpmc_oh, *usb_oh, *gpio1_oh; usb_oh = omap_hwmod_lookup("usb_otg_hs"); gpmc_oh = omap_hwmod_lookup("gpmc"); gpio1_oh = omap_hwmod_lookup("gpio1"); /* WKUP domain GPIO */ omap_hwmod_enable(usb_oh); omap_hwmod_enable(gpmc_oh); /* * Keep USB module enabled during standby * to enable USB remote wakeup * Note: This will result in hard-coding USB state * during standby */ if (suspend_state != PM_SUSPEND_STANDBY) omap_hwmod_idle(usb_oh); omap_hwmod_idle(gpmc_oh); /* * Disable the GPIO module. This ensure that * only sWAKEUP interrupts to Cortex-M3 get generated * * XXX: EVM_SK uses a GPIO0 pin for VTP control * in suspend and hence we can't do this for EVM_SK * alone. The side-effect of this is that GPIO wakeup * might have issues. Refer to commit 672639b for the * details */ /* * Keep GPIO0 module enabled during standby to * support wakeup via GPIO0 keys. */ if ((suspend_cfg_param_list[EVM_ID] != EVM_SK) && (suspend_state != PM_SUSPEND_STANDBY)) omap_hwmod_idle(gpio1_oh); /* * Update Suspend_State value to be used in sleep33xx.S to keep * GPIO0 module enabled during standby for EVM-SK */ if (suspend_state == PM_SUSPEND_STANDBY) suspend_cfg_param_list[SUSPEND_STATE] = PM_STANDBY; else suspend_cfg_param_list[SUSPEND_STATE] = PM_DS0; /* * Keep Touchscreen module enabled during standby * to enable wakeup from standby. */ if (suspend_state == PM_SUSPEND_STANDBY) writel(0x2, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL); if (gfx_l3_clkdm && gfx_l4ls_clkdm) { clkdm_sleep(gfx_l3_clkdm); clkdm_sleep(gfx_l4ls_clkdm); } /* Try to put GFX to sleep */ if (gfx_pwrdm) pwrdm_set_next_pwrst(gfx_pwrdm, PWRDM_POWER_OFF); else pr_err("Could not program GFX to low power state\n"); omap3_intc_suspend(); writel(0x0, AM33XX_CM_MPU_MPU_CLKCTRL); ret = cpu_suspend(0, am33xx_do_sram_idle); writel(0x2, AM33XX_CM_MPU_MPU_CLKCTRL); if (gfx_pwrdm) { state = pwrdm_read_pwrst(gfx_pwrdm); if (state != PWRDM_POWER_OFF) pr_err("GFX domain did not transition to low power state\n"); else pr_info("GFX domain entered low power state\n"); } /* XXX: Why do we need to wakeup the clockdomains? */ if(gfx_l3_clkdm && gfx_l4ls_clkdm) { clkdm_wakeup(gfx_l3_clkdm); clkdm_wakeup(gfx_l4ls_clkdm); } /* * Touchscreen module was enabled during standby * Disable it here. */ if (suspend_state == PM_SUSPEND_STANDBY) writel(0x0, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL); /* * Put USB module to idle on resume from standby */ if (suspend_state == PM_SUSPEND_STANDBY) omap_hwmod_idle(usb_oh); ret = am33xx_verify_lp_state(ret); /* * Enable the GPIO module. Once the driver is * fully adapted to runtime PM this will go away */ /* * During standby, GPIO was not disabled. Hence no * need to enable it here. */ if ((suspend_cfg_param_list[EVM_ID] != EVM_SK) && (suspend_state != PM_SUSPEND_STANDBY)) omap_hwmod_enable(gpio1_oh); return ret; }
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { static struct clockdomain *cpu1_clkdm; static bool booted; /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * Update the AuxCoreBoot0 with boot state for secondary core. * omap_secondary_startup() routine will hold the secondary core till * the AuxCoreBoot1 register is updated with cpu state * A barrier is added to ensure that write buffer is drained */ omap_modify_auxcoreboot0(0x200, 0xfffffdff); flush_cache_all(); smp_wmb(); if (!cpu1_clkdm) cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); /* * The SGI(Software Generated Interrupts) are not wakeup capable * from low power states. This is known limitation on OMAP4 and * needs to be worked around by using software forced clockdomain * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to * software force wakeup. After the wakeup, CPU1 restores its * clockdomain hardware supervised mode. * More details can be found in OMAP4430 TRM - Version J * Section : * 4.3.4.2 Power States of CPU0 and CPU1 */ if (booted) { /* * GIC distributor control register has changed between * CortexA9 r1pX and r2pX. The Control Register secure * banked version is now composed of 2 bits: * bit 0 == Secure Enable * bit 1 == Non-Secure Enable * The Non-Secure banked register has not changed * Because the ROM Code is based on the r1pX GIC, the CPU1 * GIC restoration will cause a problem to CPU0 Non-Secure SW. * The workaround must be: * 1) Before doing the CPU1 wakeup, CPU0 must disable * the GIC distributor * 2) CPU1 must re-enable the GIC distributor on * it's wakeup path. */ if (!cpu_is_omap443x()) { local_irq_disable(); gic_dist_disable(); } clkdm_wakeup(cpu1_clkdm); if (!cpu_is_omap443x()) { while (gic_dist_disabled()) { udelay(1); cpu_relax(); } gic_timer_retrigger(); local_irq_enable(); } } else { clkdm_init_mpu1(cpu1_clkdm); dsb_sev(); booted = true; } /* * Now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ spin_unlock(&boot_lock); return 0; }
/** * omap4_core_dpll_m2_set_rate - set CORE DPLL M2 divider * @clk: struct clk * of DPLL to set * @rate: rounded target rate * * Programs the CM shadow registers to update CORE DPLL M2 * divider. M2 divider is used to clock external DDR and its * reconfiguration on frequency change is managed through a * hardware sequencer. This is managed by the PRCM with EMIF * uding shadow registers. * Returns -EINVAL/-1 on error and 0 on success. */ int omap4_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) { int i = 0; u32 validrate = 0, shadow_freq_cfg1 = 0, new_div = 0; unsigned long flags; if (!clk || !rate) return -EINVAL; validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); if (validrate != rate) return -EINVAL; /* Just to avoid look-up on every call to speed up */ if (!l3_emif_clkdm) { l3_emif_clkdm = clkdm_lookup("l3_emif_clkdm"); if (!l3_emif_clkdm) { pr_err("%s: clockdomain lookup failed\n", __func__); return -EINVAL; } } spin_lock_irqsave(&l3_emif_lock, flags); /* Configures MEMIF domain in SW_WKUP */ clkdm_wakeup(l3_emif_clkdm); /* * Program EMIF timing parameters in EMIF shadow registers * for targetted DRR clock. * DDR Clock = core_dpll_m2 / 2 */ omap_emif_setup_registers(validrate >> 1, LPDDR2_VOLTAGE_STABLE); /* * FREQ_UPDATE sequence: * - DLL_OVERRIDE=0 (DLL lock & code must not be overridden * after CORE DPLL lock) * - DLL_RESET=1 (DLL must be reset upon frequency change) * - DPLL_CORE_M2_DIV with same value as the one already * in direct register * - DPLL_CORE_DPLL_EN=0x7 (to make CORE DPLL lock) * - FREQ_UPDATE=1 (to start HW sequence) */ shadow_freq_cfg1 = (1 << OMAP4430_DLL_RESET_SHIFT) | (new_div << OMAP4430_DPLL_CORE_M2_DIV_SHIFT) | (DPLL_LOCKED << OMAP4430_DPLL_CORE_DPLL_EN_SHIFT) | (1 << OMAP4430_FREQ_UPDATE_SHIFT); shadow_freq_cfg1 &= ~OMAP4430_DLL_OVERRIDE_MASK; __raw_writel(shadow_freq_cfg1, OMAP4430_CM_SHADOW_FREQ_CONFIG1); /* wait for the configuration to be applied */ omap_test_timeout(((__raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1) & OMAP4430_FREQ_UPDATE_MASK) == 0), MAX_FREQ_UPDATE_TIMEOUT, i); /* Configures MEMIF domain back to HW_WKUP */ clkdm_allow_idle(l3_emif_clkdm); spin_unlock_irqrestore(&l3_emif_lock, flags); if (i == MAX_FREQ_UPDATE_TIMEOUT) { pr_err("%s: Frequency update for CORE DPLL M2 change failed\n", __func__); return -1; } /* Update the clock change */ clk->rate = validrate; return 0; }
static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) { static struct clockdomain *cpu1_clkdm; static bool booted; static struct powerdomain *cpu1_pwrdm; void __iomem *base = omap_get_wakeupgen_base(); /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * Update the AuxCoreBoot0 with boot state for secondary core. * omap4_secondary_startup() routine will hold the secondary core till * the AuxCoreBoot1 register is updated with cpu state * A barrier is added to ensure that write buffer is drained */ if (omap_secure_apis_support()) omap_modify_auxcoreboot0(0x200, 0xfffffdff); else __raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0); if (!cpu1_clkdm && !cpu1_pwrdm) { cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); cpu1_pwrdm = pwrdm_lookup("cpu1_pwrdm"); } /* * The SGI(Software Generated Interrupts) are not wakeup capable * from low power states. This is known limitation on OMAP4 and * needs to be worked around by using software forced clockdomain * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to * software force wakeup. The clockdomain is then put back to * hardware supervised mode. * More details can be found in OMAP4430 TRM - Version J * Section : * 4.3.4.2 Power States of CPU0 and CPU1 */ if (booted && cpu1_pwrdm && cpu1_clkdm) { /* * GIC distributor control register has changed between * CortexA9 r1pX and r2pX. The Control Register secure * banked version is now composed of 2 bits: * bit 0 == Secure Enable * bit 1 == Non-Secure Enable * The Non-Secure banked register has not changed * Because the ROM Code is based on the r1pX GIC, the CPU1 * GIC restoration will cause a problem to CPU0 Non-Secure SW. * The workaround must be: * 1) Before doing the CPU1 wakeup, CPU0 must disable * the GIC distributor * 2) CPU1 must re-enable the GIC distributor on * it's wakeup path. */ if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) { local_irq_disable(); gic_dist_disable(); } /* * Ensure that CPU power state is set to ON to avoid CPU * powerdomain transition on wfi */ clkdm_wakeup(cpu1_clkdm); omap_set_pwrdm_state(cpu1_pwrdm, PWRDM_POWER_ON); clkdm_allow_idle(cpu1_clkdm); if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) { while (gic_dist_disabled()) { udelay(1); cpu_relax(); } gic_timer_retrigger(); local_irq_enable(); } } else { dsb_sev(); booted = true; } arch_send_wakeup_ipi_mask(cpumask_of(cpu)); /* * Now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ spin_unlock(&boot_lock); return 0; }