xref: /openbmc/linux/arch/powerpc/kernel/idle_64e.S (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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