1 // Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL " http://www.eclipse.org/legal/epl-v10.html ". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // os\kernelhwsrv\kernel\eka\include\drivers\smppower\idlehelper.h |
|
15 // Helper classes required to implement CPU idle |
|
16 // functionality in a SMP BSP. |
|
17 |
|
18 |
|
19 /** |
|
20 @file |
|
21 @prototype |
|
22 */ |
|
23 |
|
24 #ifndef __SMP_IDLE_HELPER_H__ |
|
25 #define __SMP_IDLE_HELPER_H__ |
|
26 |
|
27 #define __PM_IDLE_ASSERT_ALWAYS(aCond) \ |
|
28 __ASSERT_ALWAYS( (aCond), \ |
|
29 ( \ |
|
30 Kern::Printf("Assertion '" #aCond "' failed;\nFile: '" __FILE__ "' Line: %d\n", __LINE__), \ |
|
31 Kern::Fault("TIdleSupport", 1) \ |
|
32 ) ) |
|
33 |
|
34 #define __PM_IDLE_ASSERT_DEBUG(aCond) \ |
|
35 __ASSERT_DEBUG( (aCond), \ |
|
36 ( \ |
|
37 Kern::Printf("Assertion '" #aCond "' failed;\nFile: '" __FILE__ "' Line: %d\n", __LINE__), \ |
|
38 Kern::Fault("TIdleSupport", 1) \ |
|
39 ) ) |
|
40 |
|
41 |
|
42 |
|
43 #ifdef __SMP__ |
|
44 |
|
45 #include <kernel/kpower.h> |
|
46 #include <e32btrace.h> |
|
47 #include <arm_gic.h> |
|
48 #include <kernel.h> |
|
49 #include <nk_priv.h> |
|
50 #include <nk_plat.h> |
|
51 |
|
52 |
|
53 const TUint32 KNoInterruptsPending = 1023; |
|
54 |
|
55 |
|
56 // Temp place holder for TRACE Categories |
|
57 const TInt KIsrPendingCat = 128; |
|
58 const TInt KPrintReg = 129; |
|
59 const TInt KIdleEntry = 130; |
|
60 const TUint8 KIdleEntryNormalCpu = 0x10; |
|
61 const TUint8 KIdleEntryLastCpu = 0; |
|
62 const TInt KIdleeXit = 131; |
|
63 const TUint8 KIdleeXitLastCpu0 = 0x1; |
|
64 const TUint8 KIdleeXitLastCpu1 = 0x1; |
|
65 const TUint8 KIdleeXitNormalCpu0 = 0x10; |
|
66 const TUint8 KIdleeXitNormalCpu1 = 0x11; |
|
67 const TInt KSyncPoint = 132; |
|
68 const TUint8 KSignalAndWaitFnEntry = 0x10; |
|
69 const TUint8 KSignalAndWaitFneXit = 0x11; |
|
70 const TUint8 KSignalAndWaitEntry = 0x0; |
|
71 const TUint8 KSignalAndWaiteXit = 0x1; |
|
72 const TInt KClearIPI = 133; |
|
73 const TInt KSendIPI = 134; |
|
74 const TInt KMisc=135; |
|
75 const TInt KIdleTickSupression=136; |
|
76 const TUint8 KCyclesInTickCyclesFullTick = 0x0; |
|
77 const TUint8 KNextInterrupt = 0x1; |
|
78 const TUint8 KTimeSleptTimeNextInt = 0x2; |
|
79 const TUint8 KTIcksSlept = 0x3; |
|
80 const TInt KRetireCore=137; |
|
81 const TUint8 KRetireCoreEntry = 0x1; |
|
82 const TUint8 KRetireCoreeXit = 0x2; |
|
83 const TUint8 KRetireMarkCoreRetired = 0x3; |
|
84 const TInt KEngageCore=138; |
|
85 const TUint8 KEngageMarkCoreEngaged = 0x3; |
|
86 const TInt KNTICK = 139; |
|
87 |
|
88 // End of Trace categories |
|
89 |
|
90 //#define DISABLE_TRACE |
|
91 #if defined(_DEBUG) && !defined(DISABLE_TRACE) |
|
92 |
|
93 #define PMBTRACE0(c,s) BTrace0((c),(s)) |
|
94 #define PMBTRACE4(c,s,a1) BTrace4((c),(s),(a1)) |
|
95 #define PMBTRACE8(c,s,a1,a2) BTrace8((c),(s),(a1),(a2)) |
|
96 |
|
97 #else |
|
98 |
|
99 #define PMBTRACE0(c,s) |
|
100 #define PMBTRACE4(c,s,a1) |
|
101 #define PMBTRACE8(c,s,a1,a2) |
|
102 |
|
103 #endif |
|
104 |
|
105 //This will be defined in kernel header file nk_plat.h in the future |
|
106 #ifndef IDLE_WAKEUP_IPI_VECTOR |
|
107 #define IDLE_WAKEUP_IPI_VECTOR 0x07 |
|
108 #endif |
|
109 |
|
110 |
|
111 #ifdef _DEBUG |
|
112 |
|
113 #define SYNCPOINT(obj,stage) (obj).SignalAndWait(stage) |
|
114 |
|
115 #else |
|
116 |
|
117 #define SYNCPOINT(obj,stage) (obj).SignalAndWait() |
|
118 |
|
119 #endif//_DEBUG |
|
120 |
|
121 #define PROPER_WFI //if defined uses ARM_WFI state otherwise a wait in loop |
|
122 #define SYNCPOINT_WFE //Sync Points use WFE and SEV |
|
123 |
|
124 //Base class for all sync points |
|
125 class TSyncPointBase |
|
126 { |
|
127 public: |
|
128 TSyncPointBase(); |
|
129 #ifdef _DEBUG |
|
130 void SignalAndWait(TUint32 aStage); |
|
131 #else |
|
132 void SignalAndWait(); |
|
133 #endif |
|
134 void Reset(); |
|
135 protected: |
|
136 virtual void DoSW(TUint32 aCpuMask) = 0; |
|
137 public: |
|
138 volatile TUint32 iStageAndCPUWaitingMask; // upper 16 are the stage and lower 16 are cpus waiting mask |
|
139 volatile TUint32* iAllEnagedCpusMask; |
|
140 }; |
|
141 |
|
142 |
|
143 // Auto reseting sync point. Can not be broken. |
|
144 class TSyncPoint : public TSyncPointBase |
|
145 { |
|
146 private: |
|
147 void DoSW(TUint32 aCpuMask); |
|
148 }; |
|
149 |
|
150 // Very similar to normal breakpoint except that: |
|
151 // 1. It does not autoreset between calls, therefore a call to Reset is required between |
|
152 // syncs. |
|
153 // 2. It can be broken. That is a call to Break will result in any cpu currently waiting on the point |
|
154 // to be freed inmediatelly, and attempt to start to wait on the point to return inmediatelly. This |
|
155 // condition remains until reset is called once more |
|
156 class TBreakableSyncPoint : public TSyncPointBase |
|
157 { |
|
158 public: |
|
159 void Break(); |
|
160 private: |
|
161 void DoSW(TUint32 aCpuMask); |
|
162 }; |
|
163 |
|
164 //Helper class for idle handler support to be used in smp bsp |
|
165 class TIdleSupport |
|
166 { |
|
167 public: |
|
168 static void SetupIdleSupport(TUint32 aGlobalIntDistAddress, TUint32 aBaseIntIfAddress, TUint32* aTimerCount=0);//setup GIC gid and cif base addresses |
|
169 static void SetIdleIPIToHighestPriority();//sets idle IPI priority to be the highest |
|
170 static void DoIdleIPI(TUint32); |
|
171 static void ClearIdleIPI(); |
|
172 static void DoWFI();//puts current CPU in wait for interrupt state |
|
173 static TBool IsIntPending(); |
|
174 static TInt IntPending(); |
|
175 static TUint32 GetTimerCount();//HW timer can be used for tracing |
|
176 //Atomic checks used to synchronise cores going idle |
|
177 static TBool ClearLocalAndCheckGlobalIdle(TUint32); |
|
178 static TBool SetLocalAndCheckSetGlobalIdle(TUint32); |
|
179 static TBool FirstCoreAwake(TUint32); |
|
180 // Retiring Cores |
|
181 static void MarkCoreRetired(TUint32); |
|
182 static void MarkCoreEngaged(TUint32); |
|
183 //Exit methods for sync points |
|
184 static void SetExitRequired(TBreakableSyncPoint* aBreakSyncPoint=0); |
|
185 static TBool GetExitRequired(); |
|
186 static void ResetLogic();//Reset helper class flags |
|
187 static TUint32 GetCpusIdleMask();//gets bit mask containing idling CPU's |
|
188 static volatile TUint32* EngagedCpusMaskAddr(); |
|
189 static TUint32 AllCpusMask(); |
|
190 private: |
|
191 static TInt DoClearIdleIPI(); |
|
192 private: |
|
193 static const TUint32 KGlobalIdleFlag = 0x8000000; |
|
194 static volatile TUint32 iAllEngagedCpusMask; |
|
195 static volatile TUint32 iIdlingCpus;//contains CPU's idle handler waiting to go idle |
|
196 static volatile TUint32 iRousingCpus;////contains CPU's waking up |
|
197 static volatile TUint32 iExitRequired; |
|
198 static TUint iGlobalIntDistAddress;//base address of gloabl interrupt dispatcher |
|
199 static TUint iBaseIntIfAddress;//base address of CPu interrupt interface |
|
200 static volatile TUint32* iTimerCount;//timer count register provided by bsp for tracing |
|
201 }; |
|
202 |
|
203 |
|
204 #endif //__SMP__ |
|
205 |
|
206 #endif //__SMP_IDLE_HELPER_H__ |
|
207 |
|