/* *NotethattheRTCmoduleclockmustbere-enabledonlyforrtc+ddrsuspend. *AndlookslikethemodulecanstayinSYSC_IDLE_SMART_WKUPmodeconfigured *bytheinterconnectcodejustfineforbothrtc+ddrsuspendandretention *suspend.
*/ staticint am33xx_pm_suspend(suspend_state_t suspend_state)
{ int i, ret = 0;
if (suspend_state == PM_SUSPEND_MEM &&
pm_ops->check_off_mode_enable()) {
ret = clk_prepare_enable(rtc_fck); if (ret) {
dev_err(pm33xx_dev, "Failed to enable clock: %i\n", ret); return ret;
}
pm_ops->save_context();
suspend_wfi_flags |= WFI_FLAG_RTC_ONLY;
clk_save_context();
ret = pm_ops->soc_suspend(suspend_state, am33xx_rtc_only_idle,
suspend_wfi_flags);
suspend_wfi_flags &= ~WFI_FLAG_RTC_ONLY;
dev_info(pm33xx_dev, "Entering RTC Only mode with DDR in self-refresh\n");
if (!ret) {
clk_restore_context();
pm_ops->restore_context();
m3_ipc->ops->set_rtc_only(m3_ipc);
am33xx_push_sram_idle();
}
} else {
ret = pm_ops->soc_suspend(suspend_state, am33xx_do_wfi_sram,
suspend_wfi_flags);
}
if (ret) {
dev_err(pm33xx_dev, "PM: Kernel suspend failure\n");
} else {
i = m3_ipc->ops->request_pm_status(m3_ipc);
switch (i) { case0:
dev_info(pm33xx_dev, "PM: Successfully put all powerdomains to target state\n"); break; case1:
dev_err(pm33xx_dev, "PM: Could not transition all powerdomains to target state\n");
ret = -1; break; default:
dev_err(pm33xx_dev, "PM: CM3 returned unknown result = %d\n", i);
ret = -1;
}
switch (state) { case PM_SUSPEND_MEM:
ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_DEEPSLEEP); break; case PM_SUSPEND_STANDBY:
ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_STANDBY); break;
}
return ret;
}
staticvoid am33xx_pm_end(void)
{
u32 val = 0; struct nvmem_device *nvmem;
nvmem = devm_nvmem_device_get(&omap_rtc->dev, "omap_rtc_scratch0"); if (IS_ERR(nvmem)) return;
if (!np) {
np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu"); if (!np) return dev_err_probe(pm33xx_dev, -ENODEV, "PM: %s: Unable to find device node for mpu\n",
__func__);
}
sram_pool = of_gen_pool_get(np, "pm-sram", 0); if (!sram_pool) return dev_err_probe(pm33xx_dev, -ENODEV, "PM: %s: Unable to get sram pool for ocmcram\n",
__func__);
sram_pool_data = of_gen_pool_get(np, "pm-sram", 1); if (!sram_pool_data) return dev_err_probe(pm33xx_dev, -ENODEV, "PM: %s: Unable to get sram data pool for ocmcram\n",
__func__);
ocmcram_location = gen_pool_alloc(sram_pool, *pm_sram->do_wfi_sz); if (!ocmcram_location) return dev_err_probe(pm33xx_dev, -ENOMEM, "PM: %s: Unable to allocate memory from ocmcram\n",
__func__);
ocmcram_location_data = gen_pool_alloc(sram_pool_data, sizeof(struct emif_regs_amx3)); if (!ocmcram_location_data) {
gen_pool_free(sram_pool, ocmcram_location, *pm_sram->do_wfi_sz); return dev_err_probe(pm33xx_dev, -ENOMEM, "PM: Unable to allocate memory from ocmcram\n");
}
return0;
}
staticint am33xx_pm_rtc_setup(void)
{ struct device_node *np; unsignedlong val = 0; struct nvmem_device *nvmem; int error;
np = of_find_node_by_name(NULL, "rtc");
if (of_device_is_available(np)) { /* RTC interconnect target module clock */
rtc_fck = of_clk_get_by_name(np->parent, "fck"); if (IS_ERR(rtc_fck)) return PTR_ERR(rtc_fck);
rtc_base_virt = of_iomap(np, 0); if (!rtc_base_virt) {
pr_warn("PM: could not iomap rtc\n");
error = -ENODEV; goto err_clk_put;
}
omap_rtc = rtc_class_open("rtc0"); if (!omap_rtc) {
pr_warn("PM: rtc0 not available\n");
error = -EPROBE_DEFER; goto err_iounmap;
}
nvmem = devm_nvmem_device_get(&omap_rtc->dev, "omap_rtc_scratch0"); if (!IS_ERR(nvmem)) {
nvmem_device_read(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4, (void *)&rtc_magic_val); if ((rtc_magic_val & 0xffff) != RTC_REG_BOOT_MAGIC)
pr_warn("PM: bootloader does not support rtc-only!\n");
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.