|
1 /* |
|
2 * Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * ne1_tb\inc\ne1_tb_power.h |
|
16 * NE1_TBVariant Power Management Header |
|
17 * (see also assp.cpp for a discussion on Sleep modes and xyin.cpp for example |
|
18 * of usage of Resource Manager and Peripheral self power down and interaction |
|
19 * with Power Controller for Wakeup Events) |
|
20 * |
|
21 */ |
|
22 |
|
23 |
|
24 |
|
25 #ifndef __PM_STD_H__ |
|
26 #define __PM_STD_H__ |
|
27 #include <kernel/kpower.h> |
|
28 #include "variant.h" |
|
29 #include <e32btrace.h> |
|
30 #ifdef __SMP__ |
|
31 #include <arm_gic.h> |
|
32 #endif |
|
33 #include <upd35001_timer.h> |
|
34 #if defined (__SMP__) && !defined(__NO_IDLE_HANDLER_PIL__) |
|
35 #include <smppower/idlehelper.h> |
|
36 #include "smpidlehandler.h" |
|
37 #endif |
|
38 |
|
39 #define __PM_ASSERT_ALWAYS(aCond) \ |
|
40 __ASSERT_ALWAYS( (aCond), \ |
|
41 ( \ |
|
42 Kern::Printf("Assertion '" #aCond "' failed;\nFile: '" __FILE__ "' Line: %d\n", __LINE__), \ |
|
43 Kern::Fault("Power Management", 1) \ |
|
44 ) ) |
|
45 |
|
46 #define __PM_ASSERT_DEBUG(aCond) \ |
|
47 __ASSERT_DEBUG( (aCond), \ |
|
48 ( \ |
|
49 Kern::Printf("Assertion '" #aCond "' failed;\nFile: '" __FILE__ "' Line: %d\n", __LINE__), \ |
|
50 Kern::Fault("Power Management", 1) \ |
|
51 ) ) |
|
52 |
|
53 class TNE1_TBPowerController; |
|
54 class DNE1_TBPowerController; |
|
55 |
|
56 struct TRetireEngageCb |
|
57 { |
|
58 TRetireEngageCb(TDfcFn aFunction, TAny* aPtr, TInt aPriority) |
|
59 :iDfc(aFunction,aPtr,aPriority) |
|
60 {}; |
|
61 TRetireEngageCb(TDfcFn aFunction, TAny* aPtr, TDfcQue* aDfcQ, TInt aPriority) |
|
62 :iDfc(aFunction,aPtr,aDfcQ,aPriority) |
|
63 {}; |
|
64 TDfc iDfc; |
|
65 TInt iResult; |
|
66 TAny* iParam; |
|
67 }; |
|
68 |
|
69 |
|
70 |
|
71 struct SRetireCall |
|
72 { |
|
73 SRetireCall(TInt aCpu,TRetireEngageCb& aCb); |
|
74 #if defined(__SMP__) && !defined(__NO_IDLE_HANDLER_PIL__) && defined(SIMULATE_RETIREMENT) |
|
75 static void RetireCoreDfcFn(TAny*); |
|
76 void Call() { iTimer.OneShot(0);} // use a timer instead of Dfc as call can race with timer ISR |
|
77 NTimer iTimer; // by using a timer we are kinda sure we will run between ticks |
|
78 TInt iCpu; |
|
79 TRetireEngageCb& iCb; |
|
80 const TUint32 iAllCpusMask; |
|
81 #endif |
|
82 }; |
|
83 |
|
84 |
|
85 struct SEngageCall |
|
86 { |
|
87 SEngageCall(TInt aCpu,TRetireEngageCb& aCb); |
|
88 #if defined(__SMP__) && !defined(__NO_IDLE_HANDLER_PIL__) && defined(SIMULATE_RETIREMENT) |
|
89 static void EngageCoreDfcFn(TAny*); |
|
90 void Call() { iDfc.Enque();} |
|
91 TDfc iDfc; |
|
92 TInt iCpu; |
|
93 TRetireEngageCb& iCb; |
|
94 #endif |
|
95 }; |
|
96 |
|
97 #if defined(__SMP__) && !defined(__NO_IDLE_HANDLER_PIL__) |
|
98 |
|
99 class DNE1_TBPowerController; |
|
100 |
|
101 NONSHARABLE_CLASS(DNE1_SMPIdleHandler) : public DSMPIdleHandler |
|
102 { |
|
103 friend class SRetireCall; |
|
104 friend class SEngageCall; |
|
105 |
|
106 public: |
|
107 DNE1_SMPIdleHandler(DNE1_TBPowerController* aController); |
|
108 TInt Initialise(); |
|
109 TBool DoEnterIdle(TInt aCpuMask, TInt aStage, volatile TAny* aU); |
|
110 TBool GetLowPowerMode(TInt aIdleTime, TInt &aLowPowerMode); |
|
111 TBool EnterLowPowerMode(TInt aMode, TInt aCpuMask, TBool aLastCpu); |
|
112 private: |
|
113 void DoRetireCore(TInt aCpu, TLinAddr aReturnPoint); |
|
114 #ifdef SIMULATE_RETIREMENT |
|
115 static void IdleSteal(TAny*); |
|
116 #endif |
|
117 |
|
118 private: |
|
119 #ifdef SIMULATE_RETIREMENT |
|
120 static volatile TUint32 iRetiredCores; |
|
121 // static volatile TUint32 iEngagingCores; |
|
122 TDfcQue** iIdleStealers; |
|
123 TDfc** iIdleStealDfcs; |
|
124 TDfcQue* iRetireEngageQue; |
|
125 #endif |
|
126 DNE1_TBPowerController* iController; |
|
127 }; |
|
128 |
|
129 #endif |
|
130 |
|
131 // |
|
132 // TO DO: (mandatory) |
|
133 // |
|
134 // Definition of the DPowerController derived class |
|
135 // |
|
136 NONSHARABLE_CLASS(DNE1_TBPowerController) : public DPowerController |
|
137 { |
|
138 friend class TNE1_TBPowerController; |
|
139 |
|
140 public: // from DPowerController |
|
141 void CpuIdle(); |
|
142 void EnableWakeupEvents(); |
|
143 void AbsoluteTimerExpired(); |
|
144 void DisableWakeupEvents(); |
|
145 void PowerDown(TTimeK aWakeupTime); |
|
146 void IdleTickSuppresionEntry(TUint32 aWakeDelay, TInt aNextTimer); |
|
147 void IdleTickSuppresionRestore(); |
|
148 public: |
|
149 DNE1_TBPowerController(); |
|
150 private: |
|
151 static TInt ClearTimerInterrupt(); // return pending interrupt or 1023 if non pending |
|
152 void DoStandby(TBool aTimed, TUint32 aWakeupRTC); |
|
153 public: |
|
154 static const TUint32 KCyclesPerTick; // clock cycles per ms tick |
|
155 static const TInt KMaxSleepTicks; // max number of ticks that can be slept |
|
156 static const TUint32 KWakeUpBeforeTick; // The time (in cycles) that we required to before next tick is due to expire (i.e. after idle tick suppression) |
|
157 static const TUint32 KTooCloseToTick; // In cycles abort idle tick suppresion if we very close current tick edge |
|
158 static const TUint32 KMinTimeToTick; // In cyles, if time to next interrupt is less than this value in wakeup |
|
159 // ... we need to update tick in idle tick restore |
|
160 static const TInt KMinIdleTicks; // Minimum amount of ticks we wish to enter power saving mode |
|
161 |
|
162 private: |
|
163 #if defined(__SMP__) && !defined(__NO_IDLE_HANDLER_PIL__) |
|
164 DNE1_SMPIdleHandler iIdleHandler; |
|
165 #endif |
|
166 // const TUint32 iNumCpus; |
|
167 // Idle tick supression related variables |
|
168 TBool iWakeupEventsOn; |
|
169 TUint32 iNextInterrupt; |
|
170 TUint32 iOriginalTimerExpire; |
|
171 TUint iIdleCount; // in SMP increased every time we do ITS |
|
172 // in unicore, updated on every entry to CpuIdle |
|
173 }; |
|
174 |
|
175 |
|
176 // |
|
177 // If you need to access to the Power Controller from Drivers/Extensions/Variant |
|
178 // or access to Resource Manager then define an accessor class as below |
|
179 // |
|
180 class TNE1_TBPowerController |
|
181 { |
|
182 friend class SRetireCall; |
|
183 friend class SEngageCall; |
|
184 public: |
|
185 // to allow Variant/Drivers/Extensions access to Resource Manager |
|
186 // used by drivers/extensions to signal a wakeup event to Power Controller |
|
187 IMPORT_C static void WakeupEvent(); |
|
188 IMPORT_C static void RetireCore(TInt aCpu, TRetireEngageCb& aCb); |
|
189 IMPORT_C static void EngageCore(TInt aCpu, TRetireEngageCb& aCb); |
|
190 IMPORT_C static TUint IdleCount(); |
|
191 |
|
192 inline static void RegisterPowerController(DNE1_TBPowerController* aPowerController); |
|
193 private: |
|
194 static DNE1_TBPowerController* iPowerController; |
|
195 #if defined(__SMP__) && !defined(__NO_IDLE_HANDLER_PIL__) |
|
196 static DNE1_SMPIdleHandler* iIdleHandler; |
|
197 #endif |
|
198 }; |
|
199 |
|
200 |
|
201 |
|
202 #include "ne1_tb_power.inl" |
|
203 |
|
204 #endif |
|
205 |