// SPDX-License-Identifier: GPL-2.0-only /* * Low-level idle sequences */ #include #include #include #include #include #include enum { ARM64_IDLE_WFI, ARM64_IDLE_YIELD, ARM64_IDLE_NOP, } idle = ARM64_IDLE_WFI; static int __init setup_idle(char *arg) { if (!arg) return -1; else if (!strcmp(arg, "wfi")) idle = ARM64_IDLE_WFI; else if (!strcmp(arg, "yield")) idle = ARM64_IDLE_YIELD; else if (!strcmp(arg, "nop")) idle = ARM64_IDLE_NOP; else return -1; return 0; } early_param("idle", setup_idle); /* * cpu_do_idle() * * Idle the processor (wait for interrupt). * * If the CPU supports priority masking we must do additional work to * ensure that interrupts are not masked at the PMR (because the core will * not wake up if we block the wake up signal in the interrupt controller). */ void __cpuidle cpu_do_idle(void) { struct arm_cpuidle_irq_context context; arm_cpuidle_save_irq_context(&context); if (likely(idle == ARM64_IDLE_WFI)) { dsb(sy); wfi(); } else if (idle == ARM64_IDLE_YIELD) { dsb(sy); asm volatile("yield" ::: "memory"); } arm_cpuidle_restore_irq_context(&context); } /* * This is our default idle handler. */ void __cpuidle arch_cpu_idle(void) { /* * This should do all the clock switching and wait for interrupt * tricks */ cpu_do_idle(); }