| Benjamin Herrenschmidt | 34d97e0 | 2010-07-14 14:12:16 +1000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2010 IBM Corp, Benjamin Herrenschmidt <benh@kernel.crashing.org> | 
 | 3 |  * | 
 | 4 |  * Generic idle routine for Book3E processors | 
 | 5 |  * | 
 | 6 |  * This program is free software; you can redistribute it and/or | 
 | 7 |  * modify it under the terms of the GNU General Public License | 
 | 8 |  * as published by the Free Software Foundation; either version | 
 | 9 |  * 2 of the License, or (at your option) any later version. | 
 | 10 |  */ | 
 | 11 |  | 
 | 12 | #include <linux/threads.h> | 
 | 13 | #include <asm/reg.h> | 
 | 14 | #include <asm/ppc_asm.h> | 
 | 15 | #include <asm/asm-offsets.h> | 
 | 16 | #include <asm/ppc-opcode.h> | 
 | 17 | #include <asm/processor.h> | 
 | 18 | #include <asm/thread_info.h> | 
 | 19 |  | 
 | 20 | /* 64-bit version only for now */ | 
 | 21 | #ifdef CONFIG_PPC64 | 
 | 22 |  | 
 | 23 | _GLOBAL(book3e_idle) | 
 | 24 | 	/* Save LR for later */ | 
 | 25 | 	mflr	r0 | 
 | 26 | 	std	r0,16(r1) | 
 | 27 |  | 
 | 28 | 	/* Hard disable interrupts */ | 
 | 29 | 	wrteei	0 | 
 | 30 |  | 
 | 31 | 	/* Now check if an interrupt came in while we were soft disabled | 
 | 32 | 	 * since we may otherwise lose it (doorbells etc...). We know | 
 | 33 | 	 * that since PACAHARDIRQEN will have been cleared in that case. | 
 | 34 | 	 */ | 
 | 35 | 	lbz	r3,PACAHARDIRQEN(r13) | 
 | 36 | 	cmpwi	cr0,r3,0 | 
 | 37 | 	beqlr | 
 | 38 |  | 
 | 39 | 	/* Now we are going to mark ourselves as soft and hard enables in | 
 | 40 | 	 * order to be able to take interrupts while asleep. We inform lockdep | 
 | 41 | 	 * of that. We don't actually turn interrupts on just yet tho. | 
 | 42 | 	 */ | 
 | 43 | #ifdef CONFIG_TRACE_IRQFLAGS | 
 | 44 | 	stdu    r1,-128(r1) | 
 | 45 | 	bl	.trace_hardirqs_on | 
 | 46 | #endif | 
 | 47 | 	li	r0,1 | 
 | 48 | 	stb	r0,PACASOFTIRQEN(r13) | 
 | 49 | 	stb	r0,PACAHARDIRQEN(r13) | 
 | 50 | 	 | 
 | 51 | 	/* Interrupts will make use return to LR, so get something we want | 
 | 52 | 	 * in there | 
 | 53 | 	 */ | 
 | 54 | 	bl	1f | 
 | 55 |  | 
 | 56 | 	/* Hard disable interrupts again */ | 
 | 57 | 	wrteei	0 | 
 | 58 |  | 
 | 59 | 	/* Mark them off again in the PACA as well */ | 
 | 60 | 	li	r0,0 | 
 | 61 | 	stb	r0,PACASOFTIRQEN(r13) | 
 | 62 | 	stb	r0,PACAHARDIRQEN(r13) | 
 | 63 |  | 
 | 64 | 	/* Tell lockdep about it */ | 
 | 65 | #ifdef CONFIG_TRACE_IRQFLAGS | 
 | 66 | 	bl	.trace_hardirqs_off | 
 | 67 | 	addi    r1,r1,128 | 
 | 68 | #endif | 
 | 69 | 	ld	r0,16(r1) | 
 | 70 | 	mtlr	r0 | 
 | 71 | 	blr | 
 | 72 |  | 
 | 73 | 1:	/* Let's set the _TLF_NAPPING flag so interrupts make us return | 
 | 74 | 	 * to the right spot | 
 | 75 | 	*/ | 
 | 76 | 	clrrdi	r11,r1,THREAD_SHIFT | 
 | 77 | 	ld	r10,TI_LOCAL_FLAGS(r11) | 
 | 78 | 	ori	r10,r10,_TLF_NAPPING | 
 | 79 | 	std	r10,TI_LOCAL_FLAGS(r11) | 
 | 80 |  | 
 | 81 | 	/* We can now re-enable hard interrupts and go to sleep */ | 
 | 82 | 	wrteei	1 | 
 | 83 | 1:	PPC_WAIT(0) | 
 | 84 | 	b	1b | 
 | 85 |  | 
 | 86 | #endif /* CONFIG_PPC64 */ |