if (fwspec->param_count != 3) return -EINVAL; /* Not GIC compliant */ if (fwspec->param[0] != 0) return -EINVAL; /* No PPI should point to this domain */
hwirq = fwspec->param[1];
for (i = 0; i < nr_irqs; i++)
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
&exynos_pmu_chip, NULL);
/* * Clear the OF_POPULATED flag set in of_irq_init so that * later the Exynos PMU platform device won't be skipped.
*/
of_node_clear_flag(node, OF_POPULATED);
staticint exynos5420_cpu_suspend(unsignedlong arg)
{ /* MCPM works with HW CPU identifiers */ unsignedint mpidr = read_cpuid_mpidr(); unsignedint cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); unsignedint cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
if (IS_ENABLED(CONFIG_EXYNOS_MCPM)) {
mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume);
mcpm_cpu_suspend();
}
pr_info("Failed to suspend the system\n");
/* return value != 0 means failure */ return 1;
}
staticvoid exynos_pm_set_wakeup_mask(void)
{ /* * Set wake-up mask registers * EXYNOS_EINT_WAKEUP_MASK is set by pinctrl driver in late suspend.
*/
pmu_raw_writel(exynos_irqwake_intmask & ~BIT(31), S5P_WAKEUP_MASK);
}
staticvoid exynos_pm_enter_sleep_mode(void)
{ /* Set value of power down register for sleep mode */
exynos_sys_powerdown_conf(SYS_SLEEP);
pmu_raw_writel(EXYNOS_SLEEP_MAGIC, S5P_INFORM1);
}
/* Set wake-up mask registers */
exynos_pm_set_wakeup_mask();
pm_state.pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3); /* * The cpu state needs to be saved and restored so that the * secondary CPUs will enter low power start. Though the U-Boot * is setting the cpu state with low power flag, the kernel * needs to restore it back in case, the primary cpu fails to * suspend for any reason.
*/
pm_state.cpu_state = readl_relaxed(pm_state.sysram_base +
EXYNOS5420_CPU_STATE);
writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE); if (pm_state.secure_firmware)
exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(pm_state.sysram_phys +
EXYNOS5420_CPU_STATE),
0, 0);
exynos_pm_enter_sleep_mode();
/* ensure at least INFORM0 has the resume address */ if (IS_ENABLED(CONFIG_EXYNOS_MCPM))
pmu_raw_writel(__pa_symbol(mcpm_entry_point), S5P_INFORM0);
if (IS_ENABLED(CONFIG_EXYNOS_MCPM))
WARN_ON(mcpm_cpu_powered_up());
if (IS_ENABLED(CONFIG_HW_PERF_EVENTS) && cluster != 0) { /* * When system is resumed on the LITTLE/KFC core (cluster 1), * the DSCR is not properly updated until the power is turned * on also for the cluster 0. Enable it for a while to * propagate the SPNIDEN and SPIDEN signals from Secure JTAG * block and avoid undefined instruction issue on CP14 reset.
*/
pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
EXYNOS_COMMON_CONFIGURATION(0));
pmu_raw_writel(0,
EXYNOS_COMMON_CONFIGURATION(0));
}
}
/* Restore the CPU0 low power state register */
tmp = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
pmu_raw_writel(tmp | S5P_CORE_LOCAL_PWR_EN,
EXYNOS5_ARM_CORE0_SYS_PWR_REG);
/* Restore the sysram cpu state register */
writel_relaxed(pm_state.cpu_state,
pm_state.sysram_base + EXYNOS5420_CPU_STATE); if (pm_state.secure_firmware)
exynos_smc(SMC_CMD_REG,
SMC_REG_ID_SFR_W(pm_state.sysram_phys +
EXYNOS5420_CPU_STATE),
EXYNOS_AFTR_MAGIC, 0);
pr_debug("%s: resuming the system...\n", __func__);
return 0;
}
staticint exynos_suspend_prepare(void)
{ int ret;
/* * REVISIT: It would be better if struct platform_suspend_ops * .prepare handler get the suspend_state_t as a parameter to * avoid hard-coding the suspend to mem state. It's safe to do * it now only because the suspend_valid_only_mem function is * used as the .valid callback used to check if a given state * is supported by the platform anyways.
*/
ret = regulator_suspend_prepare(PM_SUSPEND_MEM); if (ret) {
pr_err("Failed to prepare regulators for suspend (%d)\n", ret); return ret;
}
return 0;
}
staticvoid exynos_suspend_finish(void)
{ int ret;
ret = regulator_suspend_finish(); if (ret)
pr_warn("Failed to resume regulators from suspend (%d)\n", ret);
}
np = of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match); if (!np) {
pr_err("Failed to find PMU node\n"); return;
}
if (WARN_ON(!of_property_read_bool(np, "interrupt-controller"))) {
pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
of_node_put(np); return;
}
of_node_put(np);
/* * Applicable as of now only to Exynos542x. If booted under secure * firmware, the non-secure region of sysram should be used.
*/ if (exynos_secure_firmware_available()) {
pm_state.sysram_phys = sysram_base_phys;
pm_state.sysram_base = sysram_ns_base_addr;
pm_state.secure_firmware = true;
} else {
pm_state.sysram_base = sysram_base_addr;
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
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.