|  | 
|  | 1 | +/* | 
|  | 2 | + *  This file contains the power_save function for 970-family CPUs. | 
|  | 3 | + * | 
|  | 4 | + *  This program is free software; you can redistribute it and/or | 
|  | 5 | + *  modify it under the terms of the GNU General Public License | 
|  | 6 | + *  as published by the Free Software Foundation; either version | 
|  | 7 | + *  2 of the License, or (at your option) any later version. | 
|  | 8 | + */ | 
|  | 9 | + | 
|  | 10 | +#include <linux/threads.h> | 
|  | 11 | +#include <asm/processor.h> | 
|  | 12 | +#include <asm/page.h> | 
|  | 13 | +#include <asm/cputable.h> | 
|  | 14 | +#include <asm/thread_info.h> | 
|  | 15 | +#include <asm/ppc_asm.h> | 
|  | 16 | +#include <asm/asm-offsets.h> | 
|  | 17 | +#include <asm/ppc-opcode.h> | 
|  | 18 | + | 
|  | 19 | +#undef DEBUG | 
|  | 20 | + | 
|  | 21 | +	.text | 
|  | 22 | + | 
|  | 23 | +_GLOBAL(power7_idle) | 
|  | 24 | +	/* Now check if user or arch enabled NAP mode */ | 
|  | 25 | +	LOAD_REG_ADDRBASE(r3,powersave_nap) | 
|  | 26 | +	lwz	r4,ADDROFF(powersave_nap)(r3) | 
|  | 27 | +	cmpwi	0,r4,0 | 
|  | 28 | +	beqlr | 
|  | 29 | + | 
|  | 30 | +	/* NAP is a state loss, we create a regs frame on the | 
|  | 31 | +	 * stack, fill it up with the state we care about and | 
|  | 32 | +	 * stick a pointer to it in PACAR1. We really only | 
|  | 33 | +	 * need to save PC, some CR bits and the NV GPRs, | 
|  | 34 | +	 * but for now an interrupt frame will do. | 
|  | 35 | +	 */ | 
|  | 36 | +	mflr	r0 | 
|  | 37 | +	std	r0,16(r1) | 
|  | 38 | +	stdu	r1,-INT_FRAME_SIZE(r1) | 
|  | 39 | +	std	r0,_LINK(r1) | 
|  | 40 | +	std	r0,_NIP(r1) | 
|  | 41 | + | 
|  | 42 | +#ifndef CONFIG_SMP | 
|  | 43 | +	/* Make sure FPU, VSX etc... are flushed as we may lose | 
|  | 44 | +	 * state when going to nap mode | 
|  | 45 | +	 */ | 
|  | 46 | +	bl	.discard_lazy_cpu_state | 
|  | 47 | +#endif /* CONFIG_SMP */ | 
|  | 48 | + | 
|  | 49 | +	/* Hard disable interrupts */ | 
|  | 50 | +	mfmsr	r9 | 
|  | 51 | +	rldicl	r9,r9,48,1 | 
|  | 52 | +	rotldi	r9,r9,16 | 
|  | 53 | +	mtmsrd	r9,1			/* hard-disable interrupts */ | 
|  | 54 | +	li	r0,0 | 
|  | 55 | +	stb	r0,PACASOFTIRQEN(r13)	/* we'll hard-enable shortly */ | 
|  | 56 | +	stb	r0,PACAHARDIRQEN(r13) | 
|  | 57 | + | 
|  | 58 | +	/* Continue saving state */ | 
|  | 59 | +	SAVE_GPR(2, r1) | 
|  | 60 | +	SAVE_NVGPRS(r1) | 
|  | 61 | +	mfcr	r3 | 
|  | 62 | +	std	r3,_CCR(r1) | 
|  | 63 | +	std	r9,_MSR(r1) | 
|  | 64 | +	std	r1,PACAR1(r13) | 
|  | 65 | + | 
|  | 66 | +	/* Magic NAP mode enter sequence */ | 
|  | 67 | +	std	r0,0(r1) | 
|  | 68 | +	ptesync | 
|  | 69 | +	ld	r0,0(r1) | 
|  | 70 | +1:	cmp	cr0,r0,r0 | 
|  | 71 | +	bne	1b | 
|  | 72 | +	PPC_NAP | 
|  | 73 | +	b	. | 
|  | 74 | + | 
|  | 75 | +_GLOBAL(power7_wakeup_loss) | 
|  | 76 | +	GET_PACA(r13) | 
|  | 77 | +	ld	r1,PACAR1(r13) | 
|  | 78 | +	REST_NVGPRS(r1) | 
|  | 79 | +	REST_GPR(2, r1) | 
|  | 80 | +	ld	r3,_CCR(r1) | 
|  | 81 | +	ld	r4,_MSR(r1) | 
|  | 82 | +	ld	r5,_NIP(r1) | 
|  | 83 | +	addi	r1,r1,INT_FRAME_SIZE | 
|  | 84 | +	mtcr	r3 | 
|  | 85 | +	mtspr	SPRN_SRR1,r4 | 
|  | 86 | +	mtspr	SPRN_SRR0,r5 | 
|  | 87 | +	rfid | 
|  | 88 | + | 
|  | 89 | +_GLOBAL(power7_wakeup_noloss) | 
|  | 90 | +	GET_PACA(r13) | 
|  | 91 | +	ld	r1,PACAR1(r13) | 
|  | 92 | +	ld	r4,_MSR(r1) | 
|  | 93 | +	ld	r5,_NIP(r1) | 
|  | 94 | +	addi	r1,r1,INT_FRAME_SIZE | 
|  | 95 | +	mtspr	SPRN_SRR1,r4 | 
|  | 96 | +	mtspr	SPRN_SRR0,r5 | 
|  | 97 | +	rfid | 
0 commit comments