16556fd1aSChristophe Leroy/* SPDX-License-Identifier: GPL-2.0-or-later */ 26556fd1aSChristophe Leroy/* 36556fd1aSChristophe Leroy * Copyright 2010 IBM Corp, Benjamin Herrenschmidt <benh@kernel.crashing.org> 46556fd1aSChristophe Leroy * 56556fd1aSChristophe Leroy * Generic idle routine for 64 bits e500 processors 66556fd1aSChristophe Leroy */ 76556fd1aSChristophe Leroy 86556fd1aSChristophe Leroy#include <linux/threads.h> 96556fd1aSChristophe Leroy#include <asm/reg.h> 106556fd1aSChristophe Leroy#include <asm/ppc_asm.h> 116556fd1aSChristophe Leroy#include <asm/asm-offsets.h> 126556fd1aSChristophe Leroy#include <asm/ppc-opcode.h> 136556fd1aSChristophe Leroy#include <asm/processor.h> 146556fd1aSChristophe Leroy#include <asm/thread_info.h> 156556fd1aSChristophe Leroy#include <asm/epapr_hcalls.h> 166556fd1aSChristophe Leroy#include <asm/hw_irq.h> 176556fd1aSChristophe Leroy 186556fd1aSChristophe Leroy/* 64-bit version only for now */ 196556fd1aSChristophe Leroy.macro BOOK3E_IDLE name loop 206556fd1aSChristophe Leroy_GLOBAL(\name) 216556fd1aSChristophe Leroy /* Save LR for later */ 226556fd1aSChristophe Leroy mflr r0 236556fd1aSChristophe Leroy std r0,16(r1) 246556fd1aSChristophe Leroy 256556fd1aSChristophe Leroy /* Hard disable interrupts */ 266556fd1aSChristophe Leroy wrteei 0 276556fd1aSChristophe Leroy 286556fd1aSChristophe Leroy /* Now check if an interrupt came in while we were soft disabled 296556fd1aSChristophe Leroy * since we may otherwise lose it (doorbells etc...). 306556fd1aSChristophe Leroy */ 316556fd1aSChristophe Leroy lbz r3,PACAIRQHAPPENED(r13) 326556fd1aSChristophe Leroy cmpwi cr0,r3,0 336556fd1aSChristophe Leroy bne 2f 346556fd1aSChristophe Leroy 356556fd1aSChristophe Leroy /* Now we are going to mark ourselves as soft and hard enabled in 366556fd1aSChristophe Leroy * order to be able to take interrupts while asleep. We inform lockdep 376556fd1aSChristophe Leroy * of that. We don't actually turn interrupts on just yet tho. 386556fd1aSChristophe Leroy */ 396556fd1aSChristophe Leroy#ifdef CONFIG_TRACE_IRQFLAGS 406556fd1aSChristophe Leroy stdu r1,-128(r1) 416556fd1aSChristophe Leroy bl trace_hardirqs_on 426556fd1aSChristophe Leroy addi r1,r1,128 436556fd1aSChristophe Leroy#endif 446556fd1aSChristophe Leroy li r0,IRQS_ENABLED 456556fd1aSChristophe Leroy stb r0,PACAIRQSOFTMASK(r13) 466556fd1aSChristophe Leroy 476556fd1aSChristophe Leroy /* Interrupts will make use return to LR, so get something we want 486556fd1aSChristophe Leroy * in there 496556fd1aSChristophe Leroy */ 506556fd1aSChristophe Leroy bl 1f 516556fd1aSChristophe Leroy 526556fd1aSChristophe Leroy /* And return (interrupts are on) */ 536556fd1aSChristophe Leroy ld r0,16(r1) 546556fd1aSChristophe Leroy mtlr r0 556556fd1aSChristophe Leroy blr 566556fd1aSChristophe Leroy 576556fd1aSChristophe Leroy1: /* Let's set the _TLF_NAPPING flag so interrupts make us return 586556fd1aSChristophe Leroy * to the right spot 596556fd1aSChristophe Leroy */ 606556fd1aSChristophe Leroy ld r11, PACACURRENT(r13) 616556fd1aSChristophe Leroy ld r10,TI_LOCAL_FLAGS(r11) 626556fd1aSChristophe Leroy ori r10,r10,_TLF_NAPPING 636556fd1aSChristophe Leroy std r10,TI_LOCAL_FLAGS(r11) 646556fd1aSChristophe Leroy 656556fd1aSChristophe Leroy /* We can now re-enable hard interrupts and go to sleep */ 666556fd1aSChristophe Leroy wrteei 1 676556fd1aSChristophe Leroy \loop 686556fd1aSChristophe Leroy 696556fd1aSChristophe Leroy2: 706556fd1aSChristophe Leroy lbz r10,PACAIRQHAPPENED(r13) 716556fd1aSChristophe Leroy ori r10,r10,PACA_IRQ_HARD_DIS 726556fd1aSChristophe Leroy stb r10,PACAIRQHAPPENED(r13) 736556fd1aSChristophe Leroy blr 746556fd1aSChristophe Leroy.endm 756556fd1aSChristophe Leroy 766556fd1aSChristophe Leroy.macro BOOK3E_IDLE_LOOP 776556fd1aSChristophe Leroy1: 78*dabeb572SNicholas Piggin PPC_WAIT_v203 796556fd1aSChristophe Leroy b 1b 806556fd1aSChristophe Leroy.endm 816556fd1aSChristophe Leroy 826556fd1aSChristophe Leroy/* epapr_ev_idle_start below is patched with the proper hcall 836556fd1aSChristophe Leroy opcodes during kernel initialization */ 846556fd1aSChristophe Leroy.macro EPAPR_EV_IDLE_LOOP 856556fd1aSChristophe Leroyidle_loop: 866556fd1aSChristophe Leroy LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE)) 876556fd1aSChristophe Leroy 886556fd1aSChristophe Leroy.global epapr_ev_idle_start 896556fd1aSChristophe Leroyepapr_ev_idle_start: 906556fd1aSChristophe Leroy li r3, -1 916556fd1aSChristophe Leroy nop 926556fd1aSChristophe Leroy nop 936556fd1aSChristophe Leroy nop 946556fd1aSChristophe Leroy b idle_loop 956556fd1aSChristophe Leroy.endm 966556fd1aSChristophe Leroy 976556fd1aSChristophe LeroyBOOK3E_IDLE epapr_ev_idle EPAPR_EV_IDLE_LOOP 986556fd1aSChristophe Leroy 996556fd1aSChristophe LeroyBOOK3E_IDLE e500_idle BOOK3E_IDLE_LOOP 100