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	stb	r0,PACA_NAPSTATELOST(r13)
58
59	/* Continue saving state */
60	SAVE_GPR(2, r1)
61	SAVE_NVGPRS(r1)
62	mfcr	r3
63	std	r3,_CCR(r1)
64	std	r9,_MSR(r1)
65	std	r1,PACAR1(r13)
66
67	/* Magic NAP mode enter sequence */
68	std	r0,0(r1)
69	ptesync
70	ld	r0,0(r1)
711:	cmp	cr0,r0,r0
72	bne	1b
73	PPC_NAP
74	b	.
75
76_GLOBAL(power7_wakeup_loss)
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	lbz	r0,PACA_NAPSTATELOST(r13)
91	cmpwi	r0,0
92	bne	.power7_wakeup_loss
93	ld	r1,PACAR1(r13)
94	ld	r4,_MSR(r1)
95	ld	r5,_NIP(r1)
96	addi	r1,r1,INT_FRAME_SIZE
97	mtspr	SPRN_SRR1,r4
98	mtspr	SPRN_SRR0,r5
99	rfid
100