18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2010 IBM Corp, Benjamin Herrenschmidt <benh@kernel.crashing.org> 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Generic idle routine for Book3E processors 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/threads.h> 98c2ecf20Sopenharmony_ci#include <asm/reg.h> 108c2ecf20Sopenharmony_ci#include <asm/ppc_asm.h> 118c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 128c2ecf20Sopenharmony_ci#include <asm/ppc-opcode.h> 138c2ecf20Sopenharmony_ci#include <asm/processor.h> 148c2ecf20Sopenharmony_ci#include <asm/thread_info.h> 158c2ecf20Sopenharmony_ci#include <asm/epapr_hcalls.h> 168c2ecf20Sopenharmony_ci#include <asm/hw_irq.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 64-bit version only for now */ 198c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci.macro BOOK3E_IDLE name loop 228c2ecf20Sopenharmony_ci_GLOBAL(\name) 238c2ecf20Sopenharmony_ci /* Save LR for later */ 248c2ecf20Sopenharmony_ci mflr r0 258c2ecf20Sopenharmony_ci std r0,16(r1) 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci /* Hard disable interrupts */ 288c2ecf20Sopenharmony_ci wrteei 0 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci /* Now check if an interrupt came in while we were soft disabled 318c2ecf20Sopenharmony_ci * since we may otherwise lose it (doorbells etc...). 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci lbz r3,PACAIRQHAPPENED(r13) 348c2ecf20Sopenharmony_ci cmpwi cr0,r3,0 358c2ecf20Sopenharmony_ci bne 2f 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci /* Now we are going to mark ourselves as soft and hard enabled in 388c2ecf20Sopenharmony_ci * order to be able to take interrupts while asleep. We inform lockdep 398c2ecf20Sopenharmony_ci * of that. We don't actually turn interrupts on just yet tho. 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci#ifdef CONFIG_TRACE_IRQFLAGS 428c2ecf20Sopenharmony_ci stdu r1,-128(r1) 438c2ecf20Sopenharmony_ci bl trace_hardirqs_on 448c2ecf20Sopenharmony_ci addi r1,r1,128 458c2ecf20Sopenharmony_ci#endif 468c2ecf20Sopenharmony_ci li r0,IRQS_ENABLED 478c2ecf20Sopenharmony_ci stb r0,PACAIRQSOFTMASK(r13) 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* Interrupts will make use return to LR, so get something we want 508c2ecf20Sopenharmony_ci * in there 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci bl 1f 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* And return (interrupts are on) */ 558c2ecf20Sopenharmony_ci ld r0,16(r1) 568c2ecf20Sopenharmony_ci mtlr r0 578c2ecf20Sopenharmony_ci blr 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci1: /* Let's set the _TLF_NAPPING flag so interrupts make us return 608c2ecf20Sopenharmony_ci * to the right spot 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci ld r11, PACACURRENT(r13) 638c2ecf20Sopenharmony_ci ld r10,TI_LOCAL_FLAGS(r11) 648c2ecf20Sopenharmony_ci ori r10,r10,_TLF_NAPPING 658c2ecf20Sopenharmony_ci std r10,TI_LOCAL_FLAGS(r11) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* We can now re-enable hard interrupts and go to sleep */ 688c2ecf20Sopenharmony_ci wrteei 1 698c2ecf20Sopenharmony_ci \loop 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci2: 728c2ecf20Sopenharmony_ci lbz r10,PACAIRQHAPPENED(r13) 738c2ecf20Sopenharmony_ci ori r10,r10,PACA_IRQ_HARD_DIS 748c2ecf20Sopenharmony_ci stb r10,PACAIRQHAPPENED(r13) 758c2ecf20Sopenharmony_ci blr 768c2ecf20Sopenharmony_ci.endm 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci.macro BOOK3E_IDLE_LOOP 798c2ecf20Sopenharmony_ci1: 808c2ecf20Sopenharmony_ci PPC_WAIT(0) 818c2ecf20Sopenharmony_ci b 1b 828c2ecf20Sopenharmony_ci.endm 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* epapr_ev_idle_start below is patched with the proper hcall 858c2ecf20Sopenharmony_ci opcodes during kernel initialization */ 868c2ecf20Sopenharmony_ci.macro EPAPR_EV_IDLE_LOOP 878c2ecf20Sopenharmony_ciidle_loop: 888c2ecf20Sopenharmony_ci LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE)) 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci.global epapr_ev_idle_start 918c2ecf20Sopenharmony_ciepapr_ev_idle_start: 928c2ecf20Sopenharmony_ci li r3, -1 938c2ecf20Sopenharmony_ci nop 948c2ecf20Sopenharmony_ci nop 958c2ecf20Sopenharmony_ci nop 968c2ecf20Sopenharmony_ci b idle_loop 978c2ecf20Sopenharmony_ci.endm 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ciBOOK3E_IDLE epapr_ev_idle EPAPR_EV_IDLE_LOOP 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ciBOOK3E_IDLE book3e_idle BOOK3E_IDLE_LOOP 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 104