xref: /OK3568_Linux_fs/kernel/arch/powerpc/include/asm/cpuidle.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef _ASM_POWERPC_CPUIDLE_H
3*4882a593Smuzhiyun #define _ASM_POWERPC_CPUIDLE_H
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #ifdef CONFIG_PPC_POWERNV
6*4882a593Smuzhiyun /* Thread state used in powernv idle state management */
7*4882a593Smuzhiyun #define PNV_THREAD_RUNNING              0
8*4882a593Smuzhiyun #define PNV_THREAD_NAP                  1
9*4882a593Smuzhiyun #define PNV_THREAD_SLEEP                2
10*4882a593Smuzhiyun #define PNV_THREAD_WINKLE               3
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun /*
13*4882a593Smuzhiyun  * Core state used in powernv idle for POWER8.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * The lock bit synchronizes updates to the state, as well as parts of the
16*4882a593Smuzhiyun  * sleep/wake code (see kernel/idle_book3s.S).
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * Bottom 8 bits track the idle state of each thread. Bit is cleared before
19*4882a593Smuzhiyun  * the thread executes an idle instruction (nap/sleep/winkle).
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * Then there is winkle tracking. A core does not lose complete state
22*4882a593Smuzhiyun  * until every thread is in winkle. So the winkle count field counts the
23*4882a593Smuzhiyun  * number of threads in winkle (small window of false positives is okay
24*4882a593Smuzhiyun  * around the sleep/wake, so long as there are no false negatives).
25*4882a593Smuzhiyun  *
26*4882a593Smuzhiyun  * When the winkle count reaches 8 (the COUNT_ALL_BIT becomes set), then
27*4882a593Smuzhiyun  * the THREAD_WINKLE_BITS are set, which indicate which threads have not
28*4882a593Smuzhiyun  * yet woken from the winkle state.
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun #define NR_PNV_CORE_IDLE_LOCK_BIT		28
31*4882a593Smuzhiyun #define PNV_CORE_IDLE_LOCK_BIT			(1ULL << NR_PNV_CORE_IDLE_LOCK_BIT)
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define PNV_CORE_IDLE_WINKLE_COUNT_SHIFT	16
34*4882a593Smuzhiyun #define PNV_CORE_IDLE_WINKLE_COUNT		0x00010000
35*4882a593Smuzhiyun #define PNV_CORE_IDLE_WINKLE_COUNT_BITS		0x000F0000
36*4882a593Smuzhiyun #define PNV_CORE_IDLE_THREAD_WINKLE_BITS_SHIFT	8
37*4882a593Smuzhiyun #define PNV_CORE_IDLE_THREAD_WINKLE_BITS	0x0000FF00
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define PNV_CORE_IDLE_THREAD_BITS       	0x000000FF
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /*
42*4882a593Smuzhiyun  * ============================ NOTE =================================
43*4882a593Smuzhiyun  * The older firmware populates only the RL field in the psscr_val and
44*4882a593Smuzhiyun  * sets the psscr_mask to 0xf. On such a firmware, the kernel sets the
45*4882a593Smuzhiyun  * remaining PSSCR fields to default values as follows:
46*4882a593Smuzhiyun  *
47*4882a593Smuzhiyun  * - ESL and EC bits are to 1. So wakeup from any stop state will be
48*4882a593Smuzhiyun  *   at vector 0x100.
49*4882a593Smuzhiyun  *
50*4882a593Smuzhiyun  * - MTL and PSLL are set to the maximum allowed value as per the ISA,
51*4882a593Smuzhiyun  *    i.e. 15.
52*4882a593Smuzhiyun  *
53*4882a593Smuzhiyun  * - The Transition Rate, TR is set to the Maximum value 3.
54*4882a593Smuzhiyun  */
55*4882a593Smuzhiyun #define PSSCR_HV_DEFAULT_VAL    (PSSCR_ESL | PSSCR_EC |		    \
56*4882a593Smuzhiyun 				PSSCR_PSLL_MASK | PSSCR_TR_MASK |   \
57*4882a593Smuzhiyun 				PSSCR_MTL_MASK)
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun #define PSSCR_HV_DEFAULT_MASK   (PSSCR_ESL | PSSCR_EC |		    \
60*4882a593Smuzhiyun 				PSSCR_PSLL_MASK | PSSCR_TR_MASK |   \
61*4882a593Smuzhiyun 				PSSCR_MTL_MASK | PSSCR_RL_MASK)
62*4882a593Smuzhiyun #define PSSCR_EC_SHIFT    20
63*4882a593Smuzhiyun #define PSSCR_ESL_SHIFT   21
64*4882a593Smuzhiyun #define GET_PSSCR_EC(x)   (((x) & PSSCR_EC) >> PSSCR_EC_SHIFT)
65*4882a593Smuzhiyun #define GET_PSSCR_ESL(x)  (((x) & PSSCR_ESL) >> PSSCR_ESL_SHIFT)
66*4882a593Smuzhiyun #define GET_PSSCR_RL(x)   ((x) & PSSCR_RL_MASK)
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun #define ERR_EC_ESL_MISMATCH		-1
69*4882a593Smuzhiyun #define ERR_DEEP_STATE_ESL_MISMATCH	-2
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #ifndef __ASSEMBLY__
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun #define PNV_IDLE_NAME_LEN    16
74*4882a593Smuzhiyun struct pnv_idle_states_t {
75*4882a593Smuzhiyun 	char name[PNV_IDLE_NAME_LEN];
76*4882a593Smuzhiyun 	u32 latency_ns;
77*4882a593Smuzhiyun 	u32 residency_ns;
78*4882a593Smuzhiyun 	u64 psscr_val;
79*4882a593Smuzhiyun 	u64 psscr_mask;
80*4882a593Smuzhiyun 	u32 flags;
81*4882a593Smuzhiyun 	bool valid;
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun extern struct pnv_idle_states_t *pnv_idle_states;
85*4882a593Smuzhiyun extern int nr_pnv_idle_states;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun unsigned long pnv_cpu_offline(unsigned int cpu);
88*4882a593Smuzhiyun int validate_psscr_val_mask(u64 *psscr_val, u64 *psscr_mask, u32 flags);
report_invalid_psscr_val(u64 psscr_val,int err)89*4882a593Smuzhiyun static inline void report_invalid_psscr_val(u64 psscr_val, int err)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	switch (err) {
92*4882a593Smuzhiyun 	case ERR_EC_ESL_MISMATCH:
93*4882a593Smuzhiyun 		pr_warn("Invalid psscr 0x%016llx : ESL,EC bits unequal",
94*4882a593Smuzhiyun 			psscr_val);
95*4882a593Smuzhiyun 		break;
96*4882a593Smuzhiyun 	case ERR_DEEP_STATE_ESL_MISMATCH:
97*4882a593Smuzhiyun 		pr_warn("Invalid psscr 0x%016llx : ESL cleared for deep stop-state",
98*4882a593Smuzhiyun 			psscr_val);
99*4882a593Smuzhiyun 	}
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun #endif
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun #endif
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun #endif
106